feat(YouTube): Add player button to change video quality (#5435)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
co-authored by
LisoUseInAIKyrios
parent
6e60ac6963
commit
7bdc32867a
-1
@@ -11,7 +11,6 @@ val recyclerViewTreeHookPatch = bytecodePatch {
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
execute {
|
||||
|
||||
recyclerViewTreeObserverFingerprint.method.apply {
|
||||
val insertIndex = recyclerViewTreeObserverFingerprint.patternMatch!!.startIndex + 1
|
||||
val recyclerViewParameter = 2
|
||||
|
||||
+1
-2
@@ -68,7 +68,6 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch {
|
||||
// region Patch for the old type of the video quality menu.
|
||||
// Used for regular videos when spoofing to old app version,
|
||||
// and for the Shorts quality flyout on newer app versions.
|
||||
|
||||
videoQualityMenuViewInflateFingerprint.let {
|
||||
it.method.apply {
|
||||
val checkCastIndex = it.patternMatch!!.endIndex
|
||||
@@ -77,7 +76,7 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch {
|
||||
addInstruction(
|
||||
checkCastIndex + 1,
|
||||
"invoke-static { v$listViewRegister }, $EXTENSION_CLASS_DESCRIPTOR->" +
|
||||
"showAdvancedVideoQualityMenu(Landroid/widget/ListView;)V",
|
||||
"addVideoQualityListMenuListener(Landroid/widget/ListView;)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ internal val videoQualityFingerprint = fingerprint {
|
||||
/**
|
||||
* Matches with the class found in [videoQualitySetterFingerprint].
|
||||
*/
|
||||
internal val setQualityByIndexMethodClassFieldReferenceFingerprint = fingerprint {
|
||||
internal val setVideoQualityFingerprint = fingerprint {
|
||||
returns("V")
|
||||
parameters("L")
|
||||
opcodes(
|
||||
|
||||
+13
-21
@@ -67,13 +67,6 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
SwitchPreference("revanced_remember_video_quality_last_selected_toast")
|
||||
))
|
||||
|
||||
/*
|
||||
* The following code works by hooking the method which is called when the user selects a video quality
|
||||
* to remember the last selected video quality.
|
||||
*
|
||||
* It also hooks the method which is called when the video quality to set is determined.
|
||||
* Conveniently, at this point the video quality is overridden to the remembered playback speed.
|
||||
*/
|
||||
onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted")
|
||||
|
||||
videoQualityFingerprint.let {
|
||||
@@ -82,7 +75,7 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
0,
|
||||
"""
|
||||
invoke-static { p2, p1 }, $EXTENSION_CLASS_DESCRIPTOR->fixVideoQualityResolution(Ljava/lang/String;I)I
|
||||
move-result p1
|
||||
move-result p1
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -142,10 +135,10 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
}
|
||||
|
||||
// Inject a call to set the remembered quality once a video loads.
|
||||
setQualityByIndexMethodClassFieldReferenceFingerprint.match(
|
||||
setVideoQualityFingerprint.match(
|
||||
videoQualitySetterFingerprint.originalClassDef
|
||||
).let { match ->
|
||||
// This instruction refers to the field with the type that contains the setQualityByIndex method.
|
||||
// This instruction refers to the field with the type that contains the setQuality method.
|
||||
val instructions = match.method.implementation!!.instructions
|
||||
val onItemClickListenerClassReference =
|
||||
(instructions.elementAt(0) as ReferenceInstruction).reference
|
||||
@@ -160,15 +153,10 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
// Add interface and helper methods to allow extension code to call obfuscated methods.
|
||||
interfaces.add(EXTENSION_VIDEO_QUALITY_MENU_INTERFACE)
|
||||
|
||||
// Get the name of the setQualityByIndex method.
|
||||
val setQualityMenuIndexMethod = methods.single {
|
||||
method -> method.parameterTypes.firstOrNull() == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
|
||||
}
|
||||
|
||||
methods.add(
|
||||
ImmutableMethod(
|
||||
type,
|
||||
"patch_setMenuIndexFromQuality",
|
||||
"patch_setQuality",
|
||||
listOf(
|
||||
ImmutableMethodParameter(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE, null, null)
|
||||
),
|
||||
@@ -178,6 +166,10 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
null,
|
||||
MutableMethodImplementation(2),
|
||||
).toMutable().apply {
|
||||
val setQualityMenuIndexMethod = methods.single { method ->
|
||||
method.parameterTypes.firstOrNull() == YOUTUBE_VIDEO_QUALITY_CLASS_TYPE
|
||||
}
|
||||
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
@@ -192,7 +184,7 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
videoQualitySetterFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
# Get the object instance to invoke the setQualityByIndex method on.
|
||||
# Get object instance to invoke setQuality method.
|
||||
iget-object v0, p0, $onItemClickListenerClassReference
|
||||
iget-object v0, v0, $setQualityFieldReference
|
||||
|
||||
@@ -202,15 +194,15 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
)
|
||||
}
|
||||
|
||||
// Inject a call to remember the selected quality.
|
||||
// Inject a call to remember the selected quality for Shorts.
|
||||
videoQualityItemOnClickFingerprint.match(
|
||||
videoQualityItemOnClickParentFingerprint.classDef
|
||||
).method.addInstruction(
|
||||
0,
|
||||
"invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V"
|
||||
"invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedShortsQuality(I)V"
|
||||
)
|
||||
|
||||
// Inject a call to remember the user selected quality.
|
||||
// Inject a call to remember the user selected quality for regular videos.
|
||||
videoQualityChangedFingerprint.let {
|
||||
it.method.apply {
|
||||
val index = it.patternMatch!!.startIndex
|
||||
@@ -218,7 +210,7 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||
|
||||
addInstruction(
|
||||
index + 1,
|
||||
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQualityInFlyout(I)V",
|
||||
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->userChangedQuality(I)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -5,6 +5,7 @@ import app.revanced.patches.shared.misc.settings.preference.BasePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceCategory
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.video.quality.button.videoQualityButtonPatch
|
||||
|
||||
/**
|
||||
* Video quality settings. Used to organize all speed related settings together.
|
||||
@@ -19,6 +20,7 @@ val videoQualityPatch = bytecodePatch(
|
||||
dependsOn(
|
||||
rememberVideoQualityPatch,
|
||||
advancedVideoQualityMenuPatch,
|
||||
videoQualityButtonPatch,
|
||||
)
|
||||
|
||||
compatibleWith(
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package app.revanced.patches.youtube.video.quality.button
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playercontrols.*
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.video.quality.rememberVideoQualityPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
|
||||
private val videoQualityButtonResourcePatch = resourcePatch {
|
||||
dependsOn(playerControlsResourcePatch)
|
||||
|
||||
execute {
|
||||
copyResources(
|
||||
"qualitybutton",
|
||||
ResourceGroup(
|
||||
"drawable",
|
||||
"revanced_video_quality_dialog_button_ld.xml",
|
||||
"revanced_video_quality_dialog_button_sd.xml",
|
||||
"revanced_video_quality_dialog_button_hd.xml",
|
||||
"revanced_video_quality_dialog_button_fhd.xml",
|
||||
"revanced_video_quality_dialog_button_fhd_plus.xml",
|
||||
"revanced_video_quality_dialog_button_qhd.xml",
|
||||
"revanced_video_quality_dialog_button_4k.xml",
|
||||
"revanced_video_quality_dialog_button_unknown.xml",
|
||||
),
|
||||
)
|
||||
|
||||
addBottomControl("qualitybutton")
|
||||
}
|
||||
}
|
||||
|
||||
private const val QUALITY_BUTTON_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/extension/youtube/videoplayer/VideoQualityDialogButton;"
|
||||
|
||||
val videoQualityButtonPatch = bytecodePatch(
|
||||
description = "Adds the option to display video quality dialog button in the video player.",
|
||||
) {
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
settingsPatch,
|
||||
addResourcesPatch,
|
||||
rememberVideoQualityPatch,
|
||||
videoQualityButtonResourcePatch,
|
||||
playerControlsPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
addResources("youtube", "video.quality.button.videoQualityButtonPatch")
|
||||
|
||||
PreferenceScreen.PLAYER.addPreferences(
|
||||
SwitchPreference("revanced_video_quality_dialog_button"),
|
||||
)
|
||||
|
||||
initializeBottomControl(QUALITY_BUTTON_CLASS_DESCRIPTOR)
|
||||
injectVisibilityCheckCall(QUALITY_BUTTON_CLASS_DESCRIPTOR)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user