feat(youtube/video-speed): change custom video speeds inside app settings (#2114)

This commit is contained in:
LisoUseInAIKyrios 2023-05-11 10:25:21 +04:00 committed by GitHub
parent 6a2b6b6e03
commit d97815af18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 112 deletions

View File

@ -1,6 +1,8 @@
package app.revanced.patches.shared.settings.preference.impl package app.revanced.patches.shared.settings.preference.impl
enum class InputType(val type: String) { enum class InputType(val type: String) {
STRING("text"), STRING("text"), // TODO: rename to "TEXT"
TEXT_CAP_CHARACTERS("textCapCharacters"),
TEXT_MULTI_LINE("textMultiLine"),
NUMBER("number"), NUMBER("number"),
} }

View File

@ -0,0 +1,24 @@
package app.revanced.patches.youtube.misc.video.speed
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.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.youtube.misc.video.speed.custom.patch.CustomVideoSpeedPatch
import app.revanced.patches.youtube.misc.video.speed.remember.patch.RememberPlaybackSpeedPatch
@Patch
@Name("video-speed")
@Description("Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout.")
@DependsOn([CustomVideoSpeedPatch::class, RememberPlaybackSpeedPatch::class])
@Version("0.0.1")
class VideoSpeeds : BytecodePatch() {
override fun execute(context: BytecodeContext): PatchResult {
return PatchResultSuccess() // All sub patches succeeded.
}
}

View File

@ -1,11 +0,0 @@
package app.revanced.patches.youtube.misc.video.speed.custom.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object VideoSpeedPatchFingerprint : MethodFingerprint(
opcodes = listOf(Opcode.FILL_ARRAY_DATA),
customFingerprint = { methodDef ->
methodDef.definingClass.endsWith("CustomVideoSpeedPatch;") && methodDef.name == "<clinit>"
}
)

View File

@ -8,37 +8,47 @@ import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.replaceInstruction import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.* import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.shared.settings.preference.impl.InputType
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.TextPreference
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch 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.speed.custom.annotations.CustomPlaybackSpeedCompatibility import app.revanced.patches.youtube.misc.video.speed.custom.annotations.CustomPlaybackSpeedCompatibility
import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedArrayGeneratorFingerprint import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedArrayGeneratorFingerprint
import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedLimiterFingerprint import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedLimiterFingerprint
import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.VideoSpeedPatchFingerprint
import org.jf.dexlib2.builder.instruction.BuilderArrayPayload
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
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.iface.reference.MethodReference
import java.util.stream.DoubleStream
import kotlin.math.roundToInt
@Patch
@Name("custom-video-speed") @Name("custom-video-speed")
@Description("Adds more video speed options.") @Description("Adds custom video speed options.")
@DependsOn([IntegrationsPatch::class]) @DependsOn([IntegrationsPatch::class])
@CustomPlaybackSpeedCompatibility @CustomPlaybackSpeedCompatibility
@Version("0.0.1") @Version("0.0.1")
class CustomVideoSpeedPatch : BytecodePatch( class CustomVideoSpeedPatch : BytecodePatch(
listOf( listOf(
SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint, VideoSpeedPatchFingerprint SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
val speedLimitMin = minVideoSpeed!!.toFloat() SettingsPatch.PreferenceScreen.MISC.addPreferences(
val speedLimitMax = maxVideoSpeed!!.toFloat().coerceAtLeast(speedLimitMin) TextPreference(
val speedsGranularity = videoSpeedsGranularity!!.toFloat() key = "revanced_custom_video_speeds",
title = StringResource(
"revanced_custom_video_speeds_title",
"Custom playback speeds"
),
inputType = InputType.TEXT_MULTI_LINE,
summary = StringResource(
"revanced_custom_video_speeds_summary",
"Add or change the video speeds available"
),
default = "0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0"
)
)
val arrayGenMethod = SpeedArrayGeneratorFingerprint.result?.mutableMethod!! val arrayGenMethod = SpeedArrayGeneratorFingerprint.result?.mutableMethod!!
val arrayGenMethodImpl = arrayGenMethod.implementation!! val arrayGenMethodImpl = arrayGenMethod.implementation!!
@ -61,7 +71,7 @@ class CustomVideoSpeedPatch : BytecodePatch(
val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA
val videoSpeedsArrayType = "Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->videoSpeeds:[F" val videoSpeedsArrayType = "Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->customVideoSpeeds:[F"
arrayGenMethod.addInstructions( arrayGenMethod.addInstructions(
arrayLengthConstIndex + 1, arrayLengthConstIndex + 1,
@ -96,100 +106,17 @@ class CustomVideoSpeedPatch : BytecodePatch(
val limiterMinConstDestination = (limiterMinConst as OneRegisterInstruction).registerA val limiterMinConstDestination = (limiterMinConst as OneRegisterInstruction).registerA
val limiterMaxConstDestination = (limiterMaxConst as OneRegisterInstruction).registerA val limiterMaxConstDestination = (limiterMaxConst as OneRegisterInstruction).registerA
fun hexFloat(float: Float): String = "0x%08x".format(float.toRawBits()) // edit: alternatively this might work by overriding with fixed values such as 0.1x and 10x
limiterMethod.replaceInstruction( limiterMethod.replaceInstruction(
limiterMinConstIndex, limiterMinConstIndex,
"const/high16 v$limiterMinConstDestination, ${hexFloat(speedLimitMin)}" "sget v$limiterMinConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->minVideoSpeed:F"
) )
limiterMethod.replaceInstruction( limiterMethod.replaceInstruction(
limiterMaxConstIndex, limiterMaxConstIndex,
"const/high16 v$limiterMaxConstDestination, ${hexFloat(speedLimitMax)}" "sget v$limiterMaxConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->maxVideoSpeed:F"
)
val constructorResult = VideoSpeedPatchFingerprint.result!!
val constructor = constructorResult.mutableMethod
val implementation = constructor.implementation!!
val stepsGranularity = 8F
val step = speedLimitMax
.minus(speedLimitMin) // calculate the range of the speeds
.div(speedsGranularity)
.times(stepsGranularity)
.roundToInt()
.div(stepsGranularity)// round to nearest multiple of stepsGranularity
.coerceAtLeast(1 / stepsGranularity) // ensure steps are at least 1/8th of the step granularity
val videoSpeedsArray = buildList<Number> {
DoubleStream
.iterate(speedLimitMin.toDouble()) { it + step } // create a stream of speeds
.let { speedStream ->
for (speed in speedStream) {
if (speed > speedLimitMax) break
add(speed.toFloat().toRawBits())
}
}
}
// adjust the new array of speeds size
constructor.replaceInstruction(
0,
"const/16 v0, ${videoSpeedsArray.size}"
)
// create the payload with the new speeds
val arrayPayloadIndex = implementation.instructions.size - 1
implementation.replaceInstruction(
arrayPayloadIndex,
BuilderArrayPayload(
4,
videoSpeedsArray
)
) )
return PatchResultSuccess() return PatchResultSuccess()
} }
companion object : OptionsContainer() {
private fun String?.validate(max: Int? = null) = this?.toFloatOrNull() != null &&
toFloat().let { float ->
float > 0 && max?.let { max -> float <= max } ?: true
}
val videoSpeedsGranularity by option(
PatchOption.StringOption(
"granularity",
"16",
"Video speed granularity",
"The granularity of the video speeds. The higher the value, the more speeds will be available.",
true
) {
it.validate()
}
)
val minVideoSpeed by option(
PatchOption.StringOption(
"min",
"0.25",
"Minimum video speed",
"The minimum video speed.",
true
) {
it.validate()
}
)
val maxVideoSpeed by option(
PatchOption.StringOption(
"max",
"5.0",
"Maximum video speed",
"The maximum video speed. Must be greater than the minimum video speed and smaller than 5.",
true
) {
it.validate(5)
}
)
}
} }

View File

@ -21,13 +21,13 @@ 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.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch 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.information.patch.VideoInformationPatch.Companion.reference
import app.revanced.patches.youtube.misc.video.speed.custom.patch.CustomVideoSpeedPatch
import app.revanced.patches.youtube.misc.video.speed.remember.annotation.RememberPlaybackSpeedCompatibility 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.InitializePlaybackSpeedValuesFingerprint
@Patch
@Name("remember-playback-speed") @Name("remember-playback-speed")
@Description("Adds the ability to remember the playback speed you chose in the video playback speed flyout.") @Description("Adds the ability to remember the playback speed you chose in the video playback speed flyout.")
@DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoInformationPatch::class]) @DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoInformationPatch::class, CustomVideoSpeedPatch::class])
@RememberPlaybackSpeedCompatibility @RememberPlaybackSpeedCompatibility
@Version("0.0.1") @Version("0.0.1")
class RememberPlaybackSpeedPatch : BytecodePatch( class RememberPlaybackSpeedPatch : BytecodePatch(