diff --git a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/InputType.kt b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/InputType.kt index 09432143b..be2358235 100644 --- a/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/InputType.kt +++ b/src/main/kotlin/app/revanced/patches/shared/settings/preference/impl/InputType.kt @@ -1,6 +1,8 @@ package app.revanced.patches.shared.settings.preference.impl enum class InputType(val type: String) { - STRING("text"), + STRING("text"), // TODO: rename to "TEXT" + TEXT_CAP_CHARACTERS("textCapCharacters"), + TEXT_MULTI_LINE("textMultiLine"), NUMBER("number"), } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/VideoSpeeds.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/VideoSpeeds.kt new file mode 100644 index 000000000..2db31001b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/VideoSpeeds.kt @@ -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. + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt deleted file mode 100644 index 541601fd1..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt +++ /dev/null @@ -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 == "" - } -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt index c038ba497..72585066b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt @@ -8,37 +8,47 @@ import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.replaceInstruction import app.revanced.patcher.patch.* 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.settings.bytecode.patch.SettingsPatch 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.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.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.reference.FieldReference import org.jf.dexlib2.iface.reference.MethodReference -import java.util.stream.DoubleStream -import kotlin.math.roundToInt -@Patch @Name("custom-video-speed") -@Description("Adds more video speed options.") +@Description("Adds custom video speed options.") @DependsOn([IntegrationsPatch::class]) @CustomPlaybackSpeedCompatibility @Version("0.0.1") class CustomVideoSpeedPatch : BytecodePatch( listOf( - SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint, VideoSpeedPatchFingerprint + SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint ) ) { override fun execute(context: BytecodeContext): PatchResult { - val speedLimitMin = minVideoSpeed!!.toFloat() - val speedLimitMax = maxVideoSpeed!!.toFloat().coerceAtLeast(speedLimitMin) - val speedsGranularity = videoSpeedsGranularity!!.toFloat() + SettingsPatch.PreferenceScreen.MISC.addPreferences( + TextPreference( + 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 arrayGenMethodImpl = arrayGenMethod.implementation!! @@ -61,7 +71,7 @@ class CustomVideoSpeedPatch : BytecodePatch( 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( arrayLengthConstIndex + 1, @@ -96,100 +106,17 @@ class CustomVideoSpeedPatch : BytecodePatch( val limiterMinConstDestination = (limiterMinConst 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( limiterMinConstIndex, - "const/high16 v$limiterMinConstDestination, ${hexFloat(speedLimitMin)}" + "sget v$limiterMinConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->minVideoSpeed:F" ) limiterMethod.replaceInstruction( limiterMaxConstIndex, - "const/high16 v$limiterMaxConstDestination, ${hexFloat(speedLimitMax)}" - ) - - 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 { - 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 - ) + "sget v$limiterMaxConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->maxVideoSpeed:F" ) 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) - } - ) - } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt index 230c149be..b135b9f50 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt @@ -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.video.information.patch.VideoInformationPatch 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.fingerprint.InitializePlaybackSpeedValuesFingerprint -@Patch @Name("remember-playback-speed") @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 @Version("0.0.1") class RememberPlaybackSpeedPatch : BytecodePatch(