mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-06-12 13:17:42 +02:00
feat: override video playback rate
This commit is contained in:
@ -7,6 +7,8 @@ import me.rhunk.snapenhance.core.util.hook.hook
|
||||
import me.rhunk.snapenhance.mapper.impl.OperaViewerParamsMapper
|
||||
|
||||
class OperaViewerParamsOverride : Feature("OperaViewerParamsOverride", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) {
|
||||
var currentPlaybackRate = 1.0F
|
||||
|
||||
data class OverrideKey(
|
||||
val name: String,
|
||||
val defaultValue: Any?
|
||||
@ -24,6 +26,12 @@ class OperaViewerParamsOverride : Feature("OperaViewerParamsOverride", loadParam
|
||||
overrideMap[key] = Override(filter, value)
|
||||
}
|
||||
|
||||
currentPlaybackRate = context.config.global.defaultVideoPlaybackRate.getNullable()?.takeIf { it > 0 } ?: 1.0F
|
||||
|
||||
if (context.config.global.videoPlaybackRateSlider.get() || currentPlaybackRate != 1.0F) {
|
||||
overrideParam("video_playback_rate", { currentPlaybackRate != 1.0F }, { _, _ -> currentPlaybackRate.toDouble() })
|
||||
}
|
||||
|
||||
if (context.config.messaging.loopMediaPlayback.get()) {
|
||||
//https://github.com/rodit/SnapMod/blob/master/app/src/main/java/xyz/rodit/snapmod/features/opera/SnapDurationModifier.kt
|
||||
overrideParam("auto_advance_mode", { true }, { key, _ -> key.defaultValue })
|
||||
@ -37,29 +45,36 @@ class OperaViewerParamsOverride : Feature("OperaViewerParamsOverride", loadParam
|
||||
}
|
||||
|
||||
context.mappings.useMapper(OperaViewerParamsMapper::class) {
|
||||
classReference.get()?.hook(putMethod.get()!!, HookStage.BEFORE) { param ->
|
||||
val key = param.argNullable<Any>(0)?.let { key ->
|
||||
val fields = key::class.java.fields
|
||||
OverrideKey(
|
||||
name = fields.firstOrNull {
|
||||
it.type == String::class.java
|
||||
}?.get(key)?.toString() ?: return@hook,
|
||||
defaultValue = fields.firstOrNull {
|
||||
it.type == Object::class.java
|
||||
}?.get(key)
|
||||
)
|
||||
} ?: return@hook
|
||||
val value = param.argNullable<Any>(1) ?: return@hook
|
||||
fun overrideParamResult(paramKey: Any, value: Any?): Any? {
|
||||
val fields = paramKey::class.java.fields
|
||||
val key = OverrideKey(
|
||||
name = fields.firstOrNull {
|
||||
it.type == String::class.java
|
||||
}?.get(paramKey)?.toString() ?: return value,
|
||||
defaultValue = fields.firstOrNull {
|
||||
it.type == Object::class.java
|
||||
}?.get(paramKey)
|
||||
)
|
||||
|
||||
overrideMap[key.name]?.let { override ->
|
||||
if (override.filter(value)) {
|
||||
runCatching {
|
||||
param.setArg(1, override.value(key, value))
|
||||
return override.value(key, value)
|
||||
}.onFailure {
|
||||
context.log.error("Failed to override param $key", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
classReference.get()?.hook(getMethod.get()!!, HookStage.AFTER) { param ->
|
||||
param.setResult(overrideParamResult(param.arg(0), param.getResult()))
|
||||
}
|
||||
|
||||
classReference.get()?.hook(getOrDefaultMethod.get()!!, HookStage.AFTER) { param ->
|
||||
param.setResult(overrideParamResult(param.arg(0), param.getResult()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,27 @@ import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import me.rhunk.snapenhance.common.ui.createComposeView
|
||||
import me.rhunk.snapenhance.core.features.impl.OperaViewerParamsOverride
|
||||
import me.rhunk.snapenhance.core.features.impl.downloader.MediaDownloader
|
||||
import me.rhunk.snapenhance.core.ui.applyTheme
|
||||
import me.rhunk.snapenhance.core.ui.menu.AbstractMenu
|
||||
import me.rhunk.snapenhance.core.ui.triggerCloseTouchEvent
|
||||
import me.rhunk.snapenhance.core.util.ktx.getId
|
||||
import me.rhunk.snapenhance.core.util.ktx.getIdentifier
|
||||
import me.rhunk.snapenhance.core.util.ktx.vibrateLongPress
|
||||
import me.rhunk.snapenhance.core.wrapper.impl.ScSize
|
||||
import java.text.DateFormat
|
||||
@ -129,6 +145,45 @@ class OperaContextActionMenu : AbstractMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
if (context.config.global.videoPlaybackRateSlider.get()) {
|
||||
val operaViewerParamsOverride = context.feature(OperaViewerParamsOverride::class)
|
||||
|
||||
linearLayout.addView(createComposeView(view.context) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(10.dp)
|
||||
) {
|
||||
var value by remember { mutableFloatStateOf(operaViewerParamsOverride.currentPlaybackRate) }
|
||||
Slider(
|
||||
value = value,
|
||||
onValueChange = {
|
||||
value = it
|
||||
operaViewerParamsOverride.currentPlaybackRate = it
|
||||
},
|
||||
valueRange = 0.1F..4.0F,
|
||||
steps = 0,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Text(
|
||||
text = "x" + value.toString().take(4),
|
||||
color = remember {
|
||||
view.context.theme.obtainStyledAttributes(
|
||||
intArrayOf(view.context.resources.getIdentifier("sigColorTextPrimary", "attr"))
|
||||
).getColor(0, 0).let { Color(it) }
|
||||
},
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}.apply {
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (context.config.downloader.downloadContextMenu.get()) {
|
||||
linearLayout.addView(Button(view.context).apply {
|
||||
text = translation["download"]
|
||||
|
Reference in New Issue
Block a user