Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Tiktok - Playback speed): Remember playback speed #2506

Merged
merged 8 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,49 +1,89 @@
package app.revanced.patches.tiktok.interaction.speed

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.tiktok.interaction.speed.fingerprints.ChangeSpeedFingerprint
import app.revanced.patches.tiktok.interaction.speed.fingerprints.GetSpeedFingerprint
import app.revanced.patches.tiktok.interaction.speed.fingerprints.OnRenderFirstFrameFingerprint
import app.revanced.patches.tiktok.interaction.speed.fingerprints.SpeedControlParentFingerprint
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction11x
import com.android.tools.smali.dexlib2.iface.reference.MethodReference

@Patch(
name = "Playback speed",
description = "Enables the playback speed option for all videos.",
description = "Enables the playback speed option for all videos and " +
"retains the speed configurations in between videos.",
compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
]
)
@Suppress("unused")
object PlaybackSpeedPatch : BytecodePatch(setOf(SpeedControlParentFingerprint)) {
object PlaybackSpeedPatch : BytecodePatch(
d4rkk3y marked this conversation as resolved.
Show resolved Hide resolved
setOf(
SpeedControlParentFingerprint,
GetSpeedFingerprint,
OnRenderFirstFrameFingerprint,
ChangeSpeedFingerprint
)
) {
override fun execute(context: BytecodeContext) {
d4rkk3y marked this conversation as resolved.
Show resolved Hide resolved
SpeedControlParentFingerprint.result?.mutableMethod?.apply {
val targetMethodCallIndex = indexOfFirstInstruction {
if (opcode == Opcode.INVOKE_STATIC) {
val paramsTypes = ((this as Instruction35c).reference as MethodReference).parameterTypes
paramsTypes.size == 1 && paramsTypes[0].contains("/Aweme;")
} else false
SpeedControlParentFingerprint.result?.mutableMethod?.let { it ->
val speedControlMethodCallIndex = it.indexOfFirstInstruction {
val paramsTypes = getReference<MethodReference>()?.parameterTypes
?: return@indexOfFirstInstruction false

paramsTypes.size == 1 && paramsTypes.first().contains("/Aweme;")
}

val isSpeedEnableMethod = context
.toMethodWalker(this)
.nextMethod(targetMethodCallIndex, true)
val enableSpeedControlMethod = context
.toMethodWalker(it)
.nextMethod(speedControlMethodCallIndex, true)
.getMethod() as MutableMethod

isSpeedEnableMethod.addInstructions(
enableSpeedControlMethod.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
"""
)
} ?: throw SpeedControlParentFingerprint.exception

GetSpeedFingerprint.result?.mutableMethod?.apply {
val injectIndex = indexOfFirstInstruction { getReference<MethodReference>()?.returnType == "F" } + 2
val register = getInstruction<Instruction11x>(injectIndex - 1).registerA

addInstruction(
injectIndex,
"invoke-static { v$register }," +
" Lapp/revanced/tiktok/speed/SpeedPatch;->saveDefaultSpeed(F)V"
d4rkk3y marked this conversation as resolved.
Show resolved Hide resolved
)
} ?: throw GetSpeedFingerprint.exception

val changeSpeedMethod = ChangeSpeedFingerprint.result?.mutableMethod
?: throw ChangeSpeedFingerprint.exception
OnRenderFirstFrameFingerprint.result?.mutableMethod?.addInstructions(
0,
"""
const/4 v0, 0x1
d4rkk3y marked this conversation as resolved.
Show resolved Hide resolved
oSumAtrIX marked this conversation as resolved.
Show resolved Hide resolved
invoke-virtual {p0, v0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getEnterFrom(Z)Ljava/lang/String;
move-result-object v0
invoke-virtual {p0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getCurrentAweme()Lcom/ss/android/ugc/aweme/feed/model/Aweme;
move-result-object v1
invoke-static {}, Lapp/revanced/tiktok/speed/SpeedPatch;->getDefaultSpeed()F
move-result-object v2
invoke-static { v0, v1, v2 }, $changeSpeedMethod
"""
) ?: throw OnRenderFirstFrameFingerprint.exception
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package app.revanced.patches.tiktok.interaction.speed.fingerprints

import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode

internal object ChangeSpeedFingerprint : MethodFingerprint(
d4rkk3y marked this conversation as resolved.
Show resolved Hide resolved
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf(
"Ljava/lang/String;",
"Lcom/ss/android/ugc/aweme/feed/model/Aweme;",
"F"
),
opcodes = listOf(
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.SGET,
Opcode.SPUT_OBJECT,
Opcode.SPUT,
Opcode.SPUT,
Opcode.SGET_OBJECT,
Opcode.IF_EQZ,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.SGET_OBJECT
),
strings = listOf("enterFrom")
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package app.revanced.patches.tiktok.interaction.speed.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object GetSpeedFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onFeedSpeedSelectedEvent"
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package app.revanced.patches.tiktok.interaction.speed.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object OnRenderFirstFrameFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onRenderFirstFrame"
}
)