Skip to content

Commit 3e57b87

Browse files
committed
Sync v5.34.0
1 parent 970be44 commit 3e57b87

File tree

3 files changed

+103
-101
lines changed

3 files changed

+103
-101
lines changed

app/src/main/java/io/github/chsbuffer/revancedxposed/youtube/video/RememberVideoQuality.kt

Lines changed: 0 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,9 @@ package io.github.chsbuffer.revancedxposed.youtube.video
22

33
import app.revanced.extension.shared.settings.preference.NoTitlePreferenceCategory
44
import app.revanced.extension.youtube.patches.playback.quality.RememberVideoQualityPatch
5-
import com.google.android.libraries.youtube.innertube.model.media.VideoQuality
65
import de.robv.android.xposed.XC_MethodHook
7-
import de.robv.android.xposed.XposedBridge
86
import io.github.chsbuffer.revancedxposed.AccessFlags
9-
import io.github.chsbuffer.revancedxposed.Opcode
107
import io.github.chsbuffer.revancedxposed.ScopedHook
11-
import io.github.chsbuffer.revancedxposed.findFirstFieldByExactType
128
import io.github.chsbuffer.revancedxposed.fingerprint
139
import io.github.chsbuffer.revancedxposed.getIntField
1410
import io.github.chsbuffer.revancedxposed.shared.misc.settings.preference.ListPreference
@@ -17,15 +13,8 @@ import io.github.chsbuffer.revancedxposed.shared.misc.settings.preference.Prefer
1713
import io.github.chsbuffer.revancedxposed.shared.misc.settings.preference.SwitchPreference
1814
import io.github.chsbuffer.revancedxposed.youtube.YoutubeHook
1915
import io.github.chsbuffer.revancedxposed.youtube.misc.PreferenceScreen
20-
import org.luckypray.dexkit.wrap.DexClass
2116
import java.lang.reflect.Modifier
2217

23-
private lateinit var getQualityName: (VideoQuality) -> String
24-
private lateinit var getResolution: (VideoQuality) -> Int
25-
26-
fun VideoQuality.getResolution() = getResolution(this)
27-
fun VideoQuality.getQualityName() = getQualityName(this)
28-
2918
fun YoutubeHook.RememberVideoQuality() {
3019
val settingsMenuVideoQualityGroup = setOf(
3120
ListPreference(
@@ -69,93 +58,6 @@ fun YoutubeHook.RememberVideoQuality() {
6958
RememberVideoQualityPatch.newVideoStarted(controller)
7059
}
7160

72-
val YOUTUBE_VIDEO_QUALITY_CLASS_TYPE =
73-
"Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"
74-
75-
val videoQualityClass = DexClass(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE).toClass()
76-
val qualityNameField = videoQualityClass.findFirstFieldByExactType(String::class.java)
77-
val resolutionField = videoQualityClass.findFirstFieldByExactType(Int::class.java)
78-
79-
getQualityName = { quality -> qualityNameField.get(quality) as String }
80-
getResolution = { quality -> resolutionField.get(quality) as Int }
81-
82-
// Fix bad data used by YouTube.
83-
XposedBridge.hookAllConstructors(
84-
videoQualityClass, object : XC_MethodHook() {
85-
override fun afterHookedMethod(param: MethodHookParam) {
86-
val quality = param.thisObject as VideoQuality
87-
val newResolution = RememberVideoQualityPatch.fixVideoQualityResolution(
88-
quality.getQualityName(), quality.getResolution()
89-
)
90-
resolutionField.set(quality, newResolution)
91-
}
92-
})
93-
94-
val videoQualitySetterFingerprint = getDexMethod("videoQualitySetterFingerprint") {
95-
fingerprint {
96-
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
97-
returns("V")
98-
parameters("[L", "I", "Z")
99-
opcodes(
100-
Opcode.IF_EQZ,
101-
Opcode.INVOKE_VIRTUAL,
102-
Opcode.MOVE_RESULT_OBJECT,
103-
Opcode.INVOKE_VIRTUAL,
104-
Opcode.IPUT_BOOLEAN,
105-
)
106-
strings("menu_item_video_quality")
107-
}
108-
}
109-
110-
getDexMethod("setVideoQualityFingerprint") {
111-
fingerprint {
112-
returns("V")
113-
parameters("L")
114-
opcodes(
115-
Opcode.IGET_OBJECT,
116-
Opcode.IPUT_OBJECT,
117-
Opcode.IGET_OBJECT,
118-
)
119-
classMatcher {
120-
className = videoQualitySetterFingerprint.className
121-
}
122-
}.also { method ->
123-
val usingFields = method.usingFields
124-
getDexField("onItemClickListenerClassReference") {
125-
usingFields[0].field
126-
}
127-
getDexField("setQualityFieldReference") {
128-
usingFields[1].field
129-
}
130-
getDexMethod("setQualityMenuIndexMethod") {
131-
usingFields[1].field.type.findMethod {
132-
matcher { addParamType { descriptor = YOUTUBE_VIDEO_QUALITY_CLASS_TYPE } }
133-
}.single()
134-
}
135-
}
136-
}
137-
138-
// Inject a call to set the remembered quality once a video loads.
139-
videoQualitySetterFingerprint.hookMethod(object : XC_MethodHook() {
140-
val onItemClickListenerClass = getDexField("onItemClickListenerClassReference").toField()
141-
val setQualityField = getDexField("setQualityFieldReference").toField()
142-
val setQualityMenuIndexMethod = getDexMethod("setQualityMenuIndexMethod").toMethod()
143-
144-
@Suppress("UNCHECKED_CAST")
145-
override fun beforeHookedMethod(param: MethodHookParam) {
146-
val qualities = param.args[0] as Array<out VideoQuality>
147-
val originalQualityIndex = param.args[1] as Int
148-
val menu = param.thisObject.let { onItemClickListenerClass.get(it) }
149-
.let { setQualityField.get(it) }
150-
151-
param.args[1] = RememberVideoQualityPatch.setVideoQuality(
152-
qualities,
153-
{ quality -> setQualityMenuIndexMethod(menu, quality) },
154-
originalQualityIndex
155-
)
156-
}
157-
})
158-
15961
// Inject a call to remember the selected quality for Shorts.
16062
getDexMethod("videoQualityItemOnClickParentFingerprint") {
16163
fingerprint {

app/src/main/java/io/github/chsbuffer/revancedxposed/youtube/video/VideoInformation.kt

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package io.github.chsbuffer.revancedxposed.youtube.video
22

33
import app.revanced.extension.youtube.patches.VideoInformation
4+
import com.google.android.libraries.youtube.innertube.model.media.VideoQuality
45
import de.robv.android.xposed.XC_MethodHook
6+
import de.robv.android.xposed.XposedBridge
7+
import io.github.chsbuffer.revancedxposed.AccessFlags
58
import io.github.chsbuffer.revancedxposed.Opcode
9+
import io.github.chsbuffer.revancedxposed.findFirstFieldByExactType
10+
import io.github.chsbuffer.revancedxposed.fingerprint
611
import io.github.chsbuffer.revancedxposed.getStaticObjectField
712
import io.github.chsbuffer.revancedxposed.opcodes
813
import io.github.chsbuffer.revancedxposed.strings
914
import io.github.chsbuffer.revancedxposed.youtube.YoutubeHook
1015
import org.luckypray.dexkit.query.enums.OpCodeMatchType
1116
import org.luckypray.dexkit.result.FieldUsingType
17+
import org.luckypray.dexkit.wrap.DexClass
1218
import java.lang.reflect.Method
1319
import java.lang.reflect.Modifier
1420

@@ -30,15 +36,21 @@ class PlaybackController(
3036
private val seekToRelative: Method,
3137
val seekSourceNone: Any
3238
) : VideoInformation.PlaybackController {
33-
override fun seekTo(videoTime: Long): Boolean {
39+
override fun patch_seekTo(videoTime: Long): Boolean {
3440
return seekTo.invoke(obj, videoTime, seekSourceNone) as Boolean
3541
}
3642

37-
override fun seekToRelative(videoTimeOffset: Long) {
43+
override fun patch_seekToRelative(videoTimeOffset: Long) {
3844
seekToRelative.invoke(obj)
3945
}
4046
}
4147

48+
private lateinit var getQualityName: (VideoQuality) -> String
49+
private lateinit var getResolution: (VideoQuality) -> Int
50+
51+
fun VideoQuality.getResolution() = getResolution(this)
52+
fun VideoQuality.getQualityName() = getQualityName(this)
53+
4254
fun YoutubeHook.VideoInformationHook() {
4355
dependsOn(
4456
::VideoIdPatch,
@@ -245,4 +257,92 @@ fun YoutubeHook.VideoInformationHook() {
245257
// TODO Hook the user playback speed selection.
246258

247259
// TODO Handle new playback speed menu.
260+
261+
// videoQuality
262+
val YOUTUBE_VIDEO_QUALITY_CLASS_TYPE =
263+
"Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;"
264+
265+
val videoQualityClass = DexClass(YOUTUBE_VIDEO_QUALITY_CLASS_TYPE).toClass()
266+
val qualityNameField = videoQualityClass.findFirstFieldByExactType(String::class.java)
267+
val resolutionField = videoQualityClass.findFirstFieldByExactType(Int::class.java)
268+
269+
getQualityName = { quality -> qualityNameField.get(quality) as String }
270+
getResolution = { quality -> resolutionField.get(quality) as Int }
271+
272+
// Fix bad data used by YouTube.
273+
XposedBridge.hookAllConstructors(
274+
videoQualityClass, object : XC_MethodHook() {
275+
override fun afterHookedMethod(param: MethodHookParam) {
276+
val quality = param.thisObject as VideoQuality
277+
val newResolution = VideoInformation.fixVideoQualityResolution(
278+
quality.getQualityName(), quality.getResolution()
279+
)
280+
resolutionField.set(quality, newResolution)
281+
}
282+
})
283+
284+
val videoQualitySetterFingerprint = getDexMethod("videoQualitySetterFingerprint") {
285+
fingerprint {
286+
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
287+
returns("V")
288+
parameters("[L", "I", "Z")
289+
opcodes(
290+
Opcode.IF_EQZ,
291+
Opcode.INVOKE_VIRTUAL,
292+
Opcode.MOVE_RESULT_OBJECT,
293+
Opcode.INVOKE_VIRTUAL,
294+
Opcode.IPUT_BOOLEAN,
295+
)
296+
strings("menu_item_video_quality")
297+
}
298+
}
299+
300+
getDexMethod("setVideoQualityFingerprint") {
301+
fingerprint {
302+
returns("V")
303+
parameters("L")
304+
opcodes(
305+
Opcode.IGET_OBJECT,
306+
Opcode.IPUT_OBJECT,
307+
Opcode.IGET_OBJECT,
308+
)
309+
classMatcher {
310+
className = videoQualitySetterFingerprint.className
311+
}
312+
}.also { method ->
313+
val usingFields = method.usingFields
314+
getDexField("onItemClickListenerClassReference") {
315+
usingFields[0].field
316+
}
317+
getDexField("setQualityFieldReference") {
318+
usingFields[1].field
319+
}
320+
getDexMethod("setQualityMenuIndexMethod") {
321+
usingFields[1].field.type.findMethod {
322+
matcher { addParamType { descriptor = YOUTUBE_VIDEO_QUALITY_CLASS_TYPE } }
323+
}.single()
324+
}
325+
}
326+
}
327+
328+
// Detect video quality changes and override the current quality.
329+
videoQualitySetterFingerprint.hookMethod(object : XC_MethodHook() {
330+
val onItemClickListenerClass = getDexField("onItemClickListenerClassReference").toField()
331+
val setQualityField = getDexField("setQualityFieldReference").toField()
332+
val setQualityMenuIndexMethod = getDexMethod("setQualityMenuIndexMethod").toMethod()
333+
334+
@Suppress("UNCHECKED_CAST")
335+
override fun beforeHookedMethod(param: MethodHookParam) {
336+
val qualities = param.args[0] as Array<out VideoQuality>
337+
val originalQualityIndex = param.args[1] as Int
338+
val menu = param.thisObject.let { onItemClickListenerClass.get(it) }
339+
.let { setQualityField.get(it) }
340+
341+
param.args[1] = VideoInformation.setVideoQuality(
342+
qualities,
343+
{ quality -> setQualityMenuIndexMethod(menu, quality) },
344+
originalQualityIndex
345+
)
346+
}
347+
})
248348
}

revanced-patches

Submodule revanced-patches updated 155 files

0 commit comments

Comments
 (0)