Skip to content

Commit

Permalink
fix(YouTube Music - Spoof client): When the default client is `Androi…
Browse files Browse the repository at this point in the history
…d Music`, playback speed menu does not open
  • Loading branch information
inotia00 authored and anddea committed Feb 11, 2025
1 parent 026800e commit bd4a2ec
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,19 @@ public static boolean forceCreatePlaybackSpeedMenu(boolean original) {
}
return original;
}

/**
* Injection point.
* <p>
* 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.
* <p>
* Return false to force create the playback speed menu.
*/
public static boolean forceCreatePlaybackSpeedMenuInverse(boolean original) {
if (SPOOF_CLIENT) {
return false;
}
return original;
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,20 @@ 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
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
Expand All @@ -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
Expand Down Expand Up @@ -61,7 +67,12 @@ val spoofClientPatch = bytecodePatch(

dependsOn(
settingsPatch,
sharedResourceIdPatch,
blockRequestPatch,
customPlaybackSpeedPatch(
"$VIDEO_PATH/CustomPlaybackSpeedPatch;",
5.0f
),
)

execute {
Expand Down Expand Up @@ -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" }
Expand Down Expand Up @@ -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<OneRegisterInstruction>(insertIndex).registerA

addInstructions(
insertIndex,
"""
invoke-static { v$insertRegister }, $EXTENSION_CLASS_DESCRIPTOR->forceCreatePlaybackSpeedMenuInverse(Z)Z
move-result v$insertRegister
""",
)
}

// endregion

findMethodOrThrow("$PATCHES_PATH/PatchStatus;") {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package app.revanced.patches.music.utils.flyoutmenu

import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.music.utils.extension.Constants.EXTENSION_PATH
import app.revanced.patches.music.utils.extension.sharedExtensionPatch
import app.revanced.patches.music.utils.playbackRateBottomSheetClassFingerprint
import app.revanced.patches.music.utils.resourceid.sharedResourceIdPatch
import app.revanced.util.addStaticFieldToExtension
import app.revanced.util.fingerprint.methodOrThrow
Expand All @@ -12,7 +14,10 @@ private const val EXTENSION_VIDEO_UTILS_CLASS_DESCRIPTOR =
val flyoutMenuHookPatch = bytecodePatch(
description = "flyoutMenuHookPatch",
) {
dependsOn(sharedResourceIdPatch)
dependsOn(
sharedExtensionPatch,
sharedResourceIdPatch,
)

execute {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference

private var patchIncluded = false

fun customPlaybackSpeedPatch(
descriptor: String,
maxSpeed: Float
) = bytecodePatch(
description = "customPlaybackSpeedPatch"
) {
execute {
if (patchIncluded) {
return@execute
}

arrayGeneratorFingerprint.matchOrThrow().let {
it.method.apply {
val targetIndex = it.patternMatch!!.startIndex
Expand Down Expand Up @@ -85,6 +91,8 @@ fun customPlaybackSpeedPatch(
}
}

patchIncluded = true

}
}

0 comments on commit bd4a2ec

Please sign in to comment.