feat(YouTube - Playback speed): Add "Restore old playback speed menu" option (#5552)
This commit is contained in:
parent
0579a9f760
commit
e9e4cf39b6
11 changed files with 216 additions and 45 deletions
|
|
@ -99,7 +99,7 @@ val hideInfoCardsPatch = bytecodePatch(
|
|||
)
|
||||
|
||||
// Info cards can also appear as Litho components.
|
||||
val filterClassDescriptor = "Lapp/revanced/extension/youtube/patches/components/HideInfoCardsFilterPatch;"
|
||||
val filterClassDescriptor = "Lapp/revanced/extension/youtube/patches/components/HideInfoCardsFilter;"
|
||||
addLithoFilter(filterClassDescriptor)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
|||
"Lapp/revanced/extension/youtube/patches/ReturnYouTubeDislikePatch;"
|
||||
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch;"
|
||||
"Lapp/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilter;"
|
||||
|
||||
val returnYouTubeDislikePatch = bytecodePatch(
|
||||
name = "Return YouTube Dislike",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,19 @@
|
|||
package app.revanced.patches.youtube.video.speed.custom
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.mapping.get
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappings
|
||||
import app.revanced.patches.shared.misc.settings.preference.InputType
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
|
|
@ -18,18 +26,34 @@ import app.revanced.patches.youtube.misc.recyclerviewtree.hook.addRecyclerViewTr
|
|||
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.recyclerViewTreeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.video.speed.settingsMenuVideoSpeedGroup
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstLiteralInstruction
|
||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
||||
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilterPatch;"
|
||||
"Lapp/revanced/extension/youtube/patches/components/PlaybackSpeedMenuFilter;"
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch;"
|
||||
|
||||
internal var speedUnavailableId = -1L
|
||||
private set
|
||||
|
||||
private val customPlaybackSpeedResourcePatch = resourcePatch {
|
||||
dependsOn(resourceMappingPatch)
|
||||
|
||||
execute {
|
||||
speedUnavailableId = resourceMappings["string", "varispeed_unavailable_message"]
|
||||
}
|
||||
}
|
||||
|
||||
internal val customPlaybackSpeedPatch = bytecodePatch(
|
||||
description = "Adds custom playback speed options.",
|
||||
) {
|
||||
|
|
@ -39,7 +63,8 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
|||
addResourcesPatch,
|
||||
lithoFilterPatch,
|
||||
versionCheckPatch,
|
||||
recyclerViewTreeHookPatch
|
||||
recyclerViewTreeHookPatch,
|
||||
customPlaybackSpeedResourcePatch
|
||||
)
|
||||
|
||||
execute {
|
||||
|
|
@ -48,6 +73,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
|||
settingsMenuVideoSpeedGroup.addAll(
|
||||
listOf(
|
||||
SwitchPreference("revanced_custom_speed_menu"),
|
||||
SwitchPreference("revanced_restore_old_speed_menu"),
|
||||
TextPreference(
|
||||
"revanced_custom_playback_speeds",
|
||||
inputType = InputType.TEXT_MULTI_LINE
|
||||
|
|
@ -77,15 +103,88 @@ internal val customPlaybackSpeedPatch = bytecodePatch(
|
|||
replaceInstruction(limitMaxIndex, "const/high16 v$limitMaxRegister, 8.0f")
|
||||
}
|
||||
|
||||
|
||||
// Replace the speeds float array with custom speeds.
|
||||
// These speeds are used if the speed menu is immediately opened after a video is opened.
|
||||
speedArrayGeneratorFingerprint.method.apply {
|
||||
val sizeCallIndex = indexOfFirstInstructionOrThrow { getReference<MethodReference>()?.name == "size" }
|
||||
val sizeCallResultRegister = getInstruction<OneRegisterInstruction>(sizeCallIndex + 1).registerA
|
||||
|
||||
replaceInstruction(sizeCallIndex + 1, "const/4 v$sizeCallResultRegister, 0x0")
|
||||
|
||||
val arrayLengthConstIndex = indexOfFirstLiteralInstructionOrThrow(7)
|
||||
val arrayLengthConstDestination = getInstruction<OneRegisterInstruction>(arrayLengthConstIndex).registerA
|
||||
val playbackSpeedsArrayType = "$EXTENSION_CLASS_DESCRIPTOR->customPlaybackSpeeds:[F"
|
||||
|
||||
addInstructions(
|
||||
arrayLengthConstIndex + 1,
|
||||
"""
|
||||
sget-object v$arrayLengthConstDestination, $playbackSpeedsArrayType
|
||||
array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination
|
||||
""",
|
||||
)
|
||||
|
||||
val originalArrayFetchIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<FieldReference>()
|
||||
reference?.type == "[F" && reference.definingClass.endsWith("/PlayerConfigModel;")
|
||||
}
|
||||
val originalArrayFetchDestination =
|
||||
getInstruction<OneRegisterInstruction>(originalArrayFetchIndex).registerA
|
||||
|
||||
replaceInstruction(
|
||||
originalArrayFetchIndex,
|
||||
"sget-object v$originalArrayFetchDestination, $playbackSpeedsArrayType",
|
||||
)
|
||||
}
|
||||
|
||||
// region Force old video quality menu.
|
||||
|
||||
// Add a static INSTANCE field to the class.
|
||||
// This is later used to call "showOldPlaybackSpeedMenu" on the instance.
|
||||
|
||||
val instanceField = ImmutableField(
|
||||
getOldPlaybackSpeedsFingerprint.originalClassDef.type,
|
||||
"INSTANCE",
|
||||
getOldPlaybackSpeedsFingerprint.originalClassDef.type,
|
||||
AccessFlags.PUBLIC.value or AccessFlags.STATIC.value,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
).toMutable()
|
||||
|
||||
getOldPlaybackSpeedsFingerprint.classDef.staticFields.add(instanceField)
|
||||
// Set the INSTANCE field to the instance of the class.
|
||||
// In order to prevent a conflict with another patch, add the instruction at index 1.
|
||||
getOldPlaybackSpeedsFingerprint.method.addInstruction(1, "sput-object p0, $instanceField")
|
||||
|
||||
// Get the "showOldPlaybackSpeedMenu" method.
|
||||
// This is later called on the field INSTANCE.
|
||||
val showOldPlaybackSpeedMenuMethod = showOldPlaybackSpeedMenuFingerprint.match(
|
||||
getOldPlaybackSpeedsFingerprint.classDef,
|
||||
).method
|
||||
|
||||
// Insert the call to the "showOldPlaybackSpeedMenu" method on the field INSTANCE.
|
||||
showOldPlaybackSpeedMenuExtensionFingerprint.method.apply {
|
||||
addInstructionsWithLabels(
|
||||
instructions.lastIndex,
|
||||
"""
|
||||
sget-object v0, $instanceField
|
||||
if-nez v0, :not_null
|
||||
return-void
|
||||
:not_null
|
||||
invoke-virtual { v0 }, $showOldPlaybackSpeedMenuMethod
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// Close the unpatched playback dialog and show the modern custom dialog.
|
||||
addRecyclerViewTreeHook(EXTENSION_CLASS_DESCRIPTOR)
|
||||
|
||||
// Required to check if the playback speed menu is currently shown.
|
||||
addLithoFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
// endregion
|
||||
|
||||
|
||||
// region Custom tap and hold 2x speed.
|
||||
|
||||
if (is_19_25_or_greater) {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,33 @@ package app.revanced.patches.youtube.video.speed.custom
|
|||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.literal
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
|
||||
internal val getOldPlaybackSpeedsFingerprint = fingerprint {
|
||||
parameters("[L", "I")
|
||||
strings("menu_item_playback_speed")
|
||||
}
|
||||
|
||||
internal val showOldPlaybackSpeedMenuFingerprint = fingerprint {
|
||||
literal { speedUnavailableId }
|
||||
}
|
||||
|
||||
internal val showOldPlaybackSpeedMenuExtensionFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
method.name == "showOldPlaybackSpeedMenu" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
internal val speedArrayGeneratorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("[L")
|
||||
parameters("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;")
|
||||
strings("0.0#")
|
||||
}
|
||||
|
||||
internal val speedLimiterFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
|
|
|
|||
|
|
@ -1547,6 +1547,9 @@ Enabling this can unlock higher video qualities"</string>
|
|||
<string name="revanced_custom_speed_menu_title">Custom playback speed menu</string>
|
||||
<string name="revanced_custom_speed_menu_summary_on">Custom speed menu is shown</string>
|
||||
<string name="revanced_custom_speed_menu_summary_off">Custom speed menu is not shown</string>
|
||||
<string name="revanced_restore_old_speed_menu_title">Restore old playback speed menu</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_on">Old speed menu is shown</string>
|
||||
<string name="revanced_restore_old_speed_menu_summary_off">Modern speed menu is shown</string>
|
||||
<string name="revanced_custom_playback_speeds_title">Custom playback speeds</string>
|
||||
<string name="revanced_custom_playback_speeds_summary">Add or change the custom playback speeds</string>
|
||||
<string name="revanced_custom_playback_speeds_invalid">Custom speeds must be less than %s</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue