feat(youtube): add save-video-speed settings

This commit is contained in:
inotia00 2023-01-08 00:51:37 +09:00
parent be62437ab3
commit a1a74e7c51
6 changed files with 124 additions and 95 deletions

View File

@ -0,0 +1,17 @@
package app.revanced.patches.youtube.video.speed.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object VideoSpeedChangedFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.IF_EQZ,
Opcode.IGET,
Opcode.CHECK_CAST,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL
),
customFingerprint = { it.name == "onItemClick" }
)

View File

@ -0,0 +1,8 @@
package app.revanced.patches.youtube.video.speed.bytecode.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object VideoSpeedParentFingerprint : MethodFingerprint(
returnType = "V",
strings = listOf("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT")
)

View File

@ -1,27 +0,0 @@
package app.revanced.patches.youtube.video.speed.bytecode.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object VideoUserSpeedChangeFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("L","L","I","J"),
listOf(
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.IF_EQZ,
Opcode.IGET,
Opcode.CHECK_CAST,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
)
)

View File

@ -7,22 +7,25 @@ import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.util.smali.toInstructions import app.revanced.patcher.util.smali.toInstructions
import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoSpeedSetterFingerprint
import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoUserSpeedChangeFingerprint
import app.revanced.patches.youtube.misc.videoid.legacy.patch.LegacyVideoIdPatch import app.revanced.patches.youtube.misc.videoid.legacy.patch.LegacyVideoIdPatch
import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoSpeedChangedFingerprint
import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoSpeedParentFingerprint
import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoSpeedSetterFingerprint
import app.revanced.shared.annotation.YouTubeCompatibility import app.revanced.shared.annotation.YouTubeCompatibility
import app.revanced.shared.extensions.toErrorResult
import app.revanced.shared.util.bytecode.BytecodeHelper import app.revanced.shared.util.bytecode.BytecodeHelper
import app.revanced.shared.util.integrations.Constants.VIDEO_PATH import app.revanced.shared.util.integrations.Constants.VIDEO_PATH
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.FieldReference import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.immutable.ImmutableMethod import org.jf.dexlib2.immutable.ImmutableMethod
import org.jf.dexlib2.immutable.ImmutableMethodImplementation import org.jf.dexlib2.immutable.ImmutableMethodImplementation
import org.jf.dexlib2.immutable.ImmutableMethodParameter import org.jf.dexlib2.immutable.ImmutableMethodParameter
@ -33,74 +36,83 @@ import org.jf.dexlib2.immutable.ImmutableMethodParameter
@Version("0.0.1") @Version("0.0.1")
class VideoSpeedBytecodePatch : BytecodePatch( class VideoSpeedBytecodePatch : BytecodePatch(
listOf( listOf(
VideoSpeedSetterFingerprint, VideoUserSpeedChangeFingerprint VideoSpeedChangedFingerprint,
VideoSpeedParentFingerprint,
VideoSpeedSetterFingerprint
) )
) { ) {
private companion object {
const val INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR =
"$VIDEO_PATH/VideoSpeedPatch;"
}
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
val userSpeedResult = VideoUserSpeedChangeFingerprint.result!! VideoSpeedParentFingerprint.result?.let { parentResult ->
val userSpeedMutableMethod = userSpeedResult.mutableMethod val parentClassDef = parentResult.classDef
val setterResult = VideoSpeedSetterFingerprint.result!! VideoSpeedChangedFingerprint.also { it.resolve(context, parentClassDef) }.result?.let { result ->
val setterMutableMethod = setterResult.mutableMethod startIndex = result.scanResult.patternScanResult!!.startIndex
endIndex = result.scanResult.patternScanResult!!.endIndex
with (result.method) {
val speedInstruction = implementation!!.instructions
VideoUserSpeedChangeFingerprint.resolve(context, setterResult.classDef) firstRef =
val FirstReference = (speedInstruction.elementAt(startIndex) as ReferenceInstruction).reference as FieldReference
VideoUserSpeedChangeFingerprint.result!!.method.let { method ->
(method.implementation!!.instructions.elementAt(5) as ReferenceInstruction).reference as FieldReference
}
val SecondReference =
VideoUserSpeedChangeFingerprint.result!!.method.let { method ->
(method.implementation!!.instructions.elementAt(10) as ReferenceInstruction).reference as FieldReference
}
val ThirdReference =
VideoUserSpeedChangeFingerprint.result!!.method.let { method ->
(method.implementation!!.instructions.elementAt(11) as ReferenceInstruction).reference as MethodReference
}
userSpeedMutableMethod.addInstruction( secondRef =
0, "invoke-static {}, $INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->userChangedSpeed()V" (speedInstruction.elementAt(endIndex - 1) as ReferenceInstruction).reference as FieldReference
)
setterMutableMethod.addInstructions( thirdRef =
0, (speedInstruction.elementAt(endIndex) as ReferenceInstruction).reference as DexBackedMethodReference
"""
invoke-static {p1, p2}, $INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->getSpeedValue([Ljava/lang/Object;I)F
move-result v0
invoke-direct {p0, v0}, ${setterResult.classDef.type}->overrideSpeed(F)V
""",
)
val classDef = userSpeedResult.mutableClass val register =
classDef.methods.add( (speedInstruction.elementAt(endIndex) as FiveRegisterInstruction).registerD
ImmutableMethod(
classDef.type, result.mutableMethod.addInstruction(
"overrideSpeed", endIndex,
listOf(ImmutableMethodParameter("F", null, null)), "invoke-static { v$register }, $INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR" +
"V", "->" +
AccessFlags.PRIVATE or AccessFlags.PRIVATE, "userChangedSpeed(F)V"
null, )
null, }
ImmutableMethodImplementation(
4, """ } ?: return VideoSpeedChangedFingerprint.toErrorResult()
const/4 v0, 0x0
cmpg-float v0, v3, v0 val parentMutableClass = parentResult.mutableClass
if-gez v0, :cond_0
return-void parentMutableClass.methods.add(
:cond_0 ImmutableMethod(
iget-object v0, v2, ${setterResult.classDef.type}->${FirstReference.name}:${FirstReference.type} parentMutableClass.type,
check-cast v0, ${SecondReference.definingClass} "overrideSpeed",
iget-object v1, v0, ${SecondReference.definingClass}->${SecondReference.name}:${SecondReference.type} listOf(ImmutableMethodParameter("F", null, null)),
invoke-virtual {v1, v3}, $ThirdReference "V",
return-void AccessFlags.PRIVATE or AccessFlags.PRIVATE,
""".toInstructions(), null, null null,
null,
ImmutableMethodImplementation(
4, """
const/4 v0, 0x0
cmpg-float v0, v3, v0
if-lez v0, :cond_0
iget-object v0, v2, ${parentClassDef.type}->${firstRef.name}:${firstRef.type}
check-cast v0, ${secondRef.definingClass}
iget-object v1, v0, ${secondRef.definingClass}->${secondRef.name}:${secondRef.type}
invoke-virtual {v1, v3}, $thirdRef
:cond_0
return-void
""".toInstructions(), null, null
)
).toMutable()
)
} ?: return VideoSpeedParentFingerprint.toErrorResult()
VideoSpeedSetterFingerprint.result?.let { result ->
result.mutableMethod.addInstructions(
0, """
invoke-static {}, $INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->getSpeedValue()F
move-result v0
invoke-direct {p0, v0}, ${result.classDef.type}->overrideSpeed(F)V
""",
) )
).toMutable() } ?: return VideoSpeedSetterFingerprint.toErrorResult()
)
LegacyVideoIdPatch.injectCall("$INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V") LegacyVideoIdPatch.injectCall("$INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
@ -108,4 +120,16 @@ class VideoSpeedBytecodePatch : BytecodePatch(
return PatchResultSuccess() return PatchResultSuccess()
} }
private companion object {
const val INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR =
"$VIDEO_PATH/VideoSpeedPatch;"
var startIndex: Int = 0
var endIndex: Int = 0
private lateinit var firstRef: FieldReference
private lateinit var secondRef: FieldReference
private lateinit var thirdRef: DexBackedMethodReference
}
} }

View File

@ -239,6 +239,9 @@ Is it ready to submit?"</string>
<string name="revanced_enable_save_video_quality_summary_off">Does not save video quality values even when changing video quality</string> <string name="revanced_enable_save_video_quality_summary_off">Does not save video quality values even when changing video quality</string>
<string name="revanced_enable_save_video_quality_summary_on">Save the video quality value whenever you change the video quality</string> <string name="revanced_enable_save_video_quality_summary_on">Save the video quality value whenever you change the video quality</string>
<string name="revanced_enable_save_video_quality_title">Enable save video quality</string> <string name="revanced_enable_save_video_quality_title">Enable save video quality</string>
<string name="revanced_enable_save_video_speed_summary_off">Does not save video speed values even when changing video speed</string>
<string name="revanced_enable_save_video_speed_summary_on">Save the video speed value whenever you change the video speed</string>
<string name="revanced_enable_save_video_speed_title">Enable save video speed</string>
<string name="revanced_enable_seekbar_tapping_summary_on">Seekbar tapping is enabled</string> <string name="revanced_enable_seekbar_tapping_summary_on">Seekbar tapping is enabled</string>
<string name="revanced_enable_seekbar_tapping_title">Enable seekbar tapping</string> <string name="revanced_enable_seekbar_tapping_title">Enable seekbar tapping</string>
<string name="revanced_enable_swipe_auto_brightness_summary_off">Even if the brightness is set to 0 by swiping, auto brightness is not activated</string> <string name="revanced_enable_swipe_auto_brightness_summary_off">Even if the brightness is set to 0 by swiping, auto brightness is not activated</string>
@ -507,6 +510,13 @@ Would you like to continue?"</string>
<string name="revanced_ryd_dislike_separator_summary_on">Dislikes shown with separator</string> <string name="revanced_ryd_dislike_separator_summary_on">Dislikes shown with separator</string>
<string name="revanced_ryd_dislike_separator_title">Dislikes with separator</string> <string name="revanced_ryd_dislike_separator_title">Dislikes with separator</string>
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Hidden</string> <string name="revanced_ryd_video_likes_hidden_by_video_owner">Hidden</string>
<string name="revanced_save_video_quality_common_error">Failed to set quality</string>
<string name="revanced_save_video_quality_internet_error">No internet connection</string>
<string name="revanced_save_video_quality_mobile">Changing default mobile data quality to:</string>
<string name="revanced_save_video_quality_mobile_error">Failed to change default mobile data quality</string>
<string name="revanced_save_video_quality_wifi">Changing default Wi-Fi quality to:</string>
<string name="revanced_save_video_quality_wifi_error">Failed to change default WI-FI quality</string>
<string name="revanced_save_video_speed">Changing default speed to:</string>
<string name="revanced_settings">ReVanced settings</string> <string name="revanced_settings">ReVanced settings</string>
<string name="revanced_swipe_controls_summary">Swipe controls related settings</string> <string name="revanced_swipe_controls_summary">Swipe controls related settings</string>
<string name="revanced_swipe_controls_title">Swipe controls settings</string> <string name="revanced_swipe_controls_title">Swipe controls settings</string>
@ -522,12 +532,6 @@ Would you like to continue?"</string>
<string name="revanced_video_ads_removal_summary_off">Video ads are shown</string> <string name="revanced_video_ads_removal_summary_off">Video ads are shown</string>
<string name="revanced_video_ads_removal_summary_on">Video ads are hidden</string> <string name="revanced_video_ads_removal_summary_on">Video ads are hidden</string>
<string name="revanced_video_ads_removal_title">Hide video ads</string> <string name="revanced_video_ads_removal_title">Hide video ads</string>
<string name="revanced_video_quality_common_error">Failed to set quality</string>
<string name="revanced_video_quality_internet_error">No internet connection</string>
<string name="revanced_video_quality_mobile">Changing default mobile data quality to:</string>
<string name="revanced_video_quality_mobile_error">Failed to change default mobile data quality</string>
<string name="revanced_video_quality_wifi">Changing default Wi-Fi quality to:</string>
<string name="revanced_video_quality_wifi_error">Failed to change default WI-FI quality</string>
<string name="revanced_video_settings_summary">Video related settings</string> <string name="revanced_video_settings_summary">Video related settings</string>
<string name="revanced_video_settings_title">Video settings</string> <string name="revanced_video_settings_title">Video settings</string>
<string name="revanced_whitelisting_add_failed" formatted="false">Failed to add channel %s to the %s whitelist</string> <string name="revanced_whitelisting_add_failed" formatted="false">Failed to add channel %s to the %s whitelist</string>

View File

@ -295,6 +295,9 @@
<!-- SETTINGS: DEFAULT_VIDEO_QUALITY <!-- SETTINGS: DEFAULT_VIDEO_QUALITY
<SwitchPreference android:title="@string/revanced_enable_save_video_quality_title" android:key="revanced_enable_save_video_quality" android:defaultValue="false" android:summaryOn="@string/revanced_enable_save_video_quality_summary_on" android:summaryOff="@string/revanced_enable_save_video_quality_summary_off" />SETTINGS: DEFAULT_VIDEO_QUALITY --> <SwitchPreference android:title="@string/revanced_enable_save_video_quality_title" android:key="revanced_enable_save_video_quality" android:defaultValue="false" android:summaryOn="@string/revanced_enable_save_video_quality_summary_on" android:summaryOff="@string/revanced_enable_save_video_quality_summary_off" />SETTINGS: DEFAULT_VIDEO_QUALITY -->
<!-- SETTINGS: DEFAULT_VIDEO_SPEED
<SwitchPreference android:title="@string/revanced_enable_save_video_speed_title" android:key="revanced_enable_save_video_speed" android:defaultValue="false" android:summaryOn="@string/revanced_enable_save_video_speed_summary_on" android:summaryOff="@string/revanced_enable_save_video_speed_summary_off" />SETTINGS: DEFAULT_VIDEO_SPEED -->
<!-- SETTINGS: CUSTOM_VIDEO_SPEED <!-- SETTINGS: CUSTOM_VIDEO_SPEED
<SwitchPreference android:title="@string/revanced_enable_custom_video_speed_title" android:key="revanced_enable_custom_video_speed" android:defaultValue="false" android:summaryOn="@string/revanced_enable_custom_video_speed_summary_on" android:summaryOff="@string/revanced_enable_custom_video_speed_summary_off" />SETTINGS: CUSTOM_VIDEO_SPEED --> <SwitchPreference android:title="@string/revanced_enable_custom_video_speed_title" android:key="revanced_enable_custom_video_speed" android:defaultValue="false" android:summaryOn="@string/revanced_enable_custom_video_speed_summary_on" android:summaryOff="@string/revanced_enable_custom_video_speed_summary_off" />SETTINGS: CUSTOM_VIDEO_SPEED -->