diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/SpoofClientPatch.java b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/SpoofClientPatch.java index 675068ffd..12fe6d571 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/SpoofClientPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/SpoofClientPatch.java @@ -116,4 +116,19 @@ public class SpoofClientPatch extends BlockRequestPatch { } return original; } + + /** + * Injection point. + *
+ * When spoofing the client to Android, the playback speed menu is missing from the player response. + * This fix is required because playback speed is not available in YouTube Music Podcasts. + *
+ * Return false to force create the playback speed menu.
+ */
+ public static boolean forceCreatePlaybackSpeedMenuInverse(boolean original) {
+ if (SPOOF_CLIENT) {
+ return false;
+ }
+ return original;
+ }
}
\ No newline at end of file
diff --git a/patches/src/main/kotlin/app/revanced/patches/music/utils/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/utils/Fingerprints.kt
index 2bbf58903..6a66410c5 100644
--- a/patches/src/main/kotlin/app/revanced/patches/music/utils/Fingerprints.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/music/utils/Fingerprints.kt
@@ -1,5 +1,6 @@
package app.revanced.patches.music.utils
+import app.revanced.patches.music.utils.resourceid.varispeedUnavailableTitle
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
@@ -22,6 +23,14 @@ internal val playbackSpeedBottomSheetFingerprint = legacyFingerprint(
strings = listOf("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT")
)
+internal val playbackRateBottomSheetClassFingerprint = legacyFingerprint(
+ name = "playbackRateBottomSheetClassFingerprint",
+ returnType = "V",
+ accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
+ parameters = emptyList(),
+ literals = listOf(varispeedUnavailableTitle)
+)
+
internal val playbackSpeedFingerprint = legacyFingerprint(
name = "playbackSpeedFingerprint",
returnType = "V",
diff --git a/patches/src/main/kotlin/app/revanced/patches/music/utils/fix/client/SpoofClientPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/utils/fix/client/SpoofClientPatch.kt
index f689c5dc5..712812ca1 100644
--- a/patches/src/main/kotlin/app/revanced/patches/music/utils/fix/client/SpoofClientPatch.kt
+++ b/patches/src/main/kotlin/app/revanced/patches/music/utils/fix/client/SpoofClientPatch.kt
@@ -9,8 +9,12 @@ import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
+import app.revanced.patches.music.utils.extension.Constants.VIDEO_PATH
import app.revanced.patches.music.utils.patch.PatchList.SPOOF_CLIENT
+import app.revanced.patches.music.utils.playbackRateBottomSheetClassFingerprint
import app.revanced.patches.music.utils.playbackSpeedBottomSheetFingerprint
+import app.revanced.patches.music.utils.resourceid.sharedResourceIdPatch
+import app.revanced.patches.music.utils.resourceid.varispeedUnavailableTitle
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
import app.revanced.patches.music.utils.settings.addPreferenceWithIntent
@@ -18,6 +22,7 @@ import app.revanced.patches.music.utils.settings.addSwitchPreference
import app.revanced.patches.music.utils.settings.settingsPatch
import app.revanced.patches.shared.spoof.blockrequest.blockRequestPatch
import app.revanced.patches.shared.createPlayerRequestBodyWithModelFingerprint
+import app.revanced.patches.shared.customspeed.customPlaybackSpeedPatch
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
import app.revanced.patches.shared.extension.Constants.SPOOF_PATH
import app.revanced.patches.shared.indexOfBrandInstruction
@@ -32,6 +37,7 @@ import app.revanced.util.getReference
import app.revanced.util.getWalkerMethod
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
+import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -61,7 +67,12 @@ val spoofClientPatch = bytecodePatch(
dependsOn(
settingsPatch,
+ sharedResourceIdPatch,
blockRequestPatch,
+ customPlaybackSpeedPatch(
+ "$VIDEO_PATH/CustomPlaybackSpeedPatch;",
+ 5.0f
+ ),
)
execute {
@@ -267,6 +278,7 @@ val spoofClientPatch = bytecodePatch(
// region fix for playback speed menu is not available in Podcasts
+ // for iOS Music
playbackSpeedBottomSheetFingerprint.mutableClassOrThrow().let {
val onItemClickMethod =
it.methods.find { method -> method.name == "onItemClick" }
@@ -302,6 +314,24 @@ val spoofClientPatch = bytecodePatch(
}
}
+ // for Android Music
+ playbackRateBottomSheetClassFingerprint.methodOrThrow().apply {
+ val literalIndex =
+ indexOfFirstLiteralInstructionOrThrow(varispeedUnavailableTitle)
+ val insertIndex =
+ indexOfFirstInstructionReversedOrThrow(literalIndex, Opcode.IF_EQZ)
+ val insertRegister =
+ getInstruction