Skip to content

Commit ede666b

Browse files
feat(YouTube - Spoof video streams): Allow picking a default audio language track (ReVanced#4050)
1 parent fd7db2f commit ede666b

File tree

7 files changed

+328
-14
lines changed

7 files changed

+328
-14
lines changed

extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package app.revanced.extension.shared.settings;
22

3-
import app.revanced.extension.shared.spoof.ClientType;
4-
import app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch;
5-
63
import static java.lang.Boolean.FALSE;
74
import static java.lang.Boolean.TRUE;
85
import static app.revanced.extension.shared.settings.Setting.parent;
6+
import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.ForceiOSAVCAvailability;
7+
8+
import app.revanced.extension.shared.spoof.AudioStreamLanguage;
9+
import app.revanced.extension.shared.spoof.ClientType;
910

1011
/**
1112
* Settings shared across multiple apps.
@@ -21,8 +22,9 @@ public class BaseSettings {
2122
public static final IntegerSetting CHECK_ENVIRONMENT_WARNINGS_ISSUED = new IntegerSetting("revanced_check_environment_warnings_issued", 0, true, false);
2223

2324
public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message");
25+
public static final EnumSetting<AudioStreamLanguage> SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AudioStreamLanguage.DEFAULT);
2426
public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true,
25-
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofVideoStreamsPatch.ForceiOSAVCAvailability());
27+
"revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new ForceiOSAVCAvailability());
2628
public static final EnumSetting<ClientType> SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client", ClientType.ANDROID_VR, true, parent(SPOOF_VIDEO_STREAMS));
2729

2830
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package app.revanced.extension.shared.spoof;
2+
3+
import java.util.Locale;
4+
5+
public enum AudioStreamLanguage {
6+
DEFAULT,
7+
8+
// Language codes found in locale_config.xml
9+
// Region specific variants of Chinese/English/Spanish/French have been removed.
10+
AF,
11+
AM,
12+
AR,
13+
AS,
14+
AZ,
15+
BE,
16+
BG,
17+
BN,
18+
BS,
19+
CA,
20+
CS,
21+
DA,
22+
DE,
23+
EL,
24+
EN,
25+
ES,
26+
ET,
27+
EU,
28+
FA,
29+
FI,
30+
FR,
31+
GL,
32+
GU,
33+
HI,
34+
HE, // App uses obsolete 'IW' and 'HE' is modern ISO code.
35+
HR,
36+
HU,
37+
HY,
38+
ID,
39+
IS,
40+
IT,
41+
JA,
42+
KA,
43+
KK,
44+
KM,
45+
KN,
46+
KO,
47+
KY,
48+
LO,
49+
LT,
50+
LV,
51+
MK,
52+
ML,
53+
MN,
54+
MR,
55+
MS,
56+
MY,
57+
NE,
58+
NL,
59+
NB,
60+
OR,
61+
PA,
62+
PL,
63+
PT_BR,
64+
PT_PT,
65+
RO,
66+
RU,
67+
SI,
68+
SK,
69+
SL,
70+
SQ,
71+
SR,
72+
SV,
73+
SW,
74+
TA,
75+
TE,
76+
TH,
77+
TL,
78+
TR,
79+
UK,
80+
UR,
81+
UZ,
82+
VI,
83+
ZH,
84+
ZU;
85+
86+
private final String iso639_1;
87+
88+
AudioStreamLanguage() {
89+
iso639_1 = name().replace('_', '-');
90+
}
91+
92+
public String getIso639_1() {
93+
// Changing the app language does not force the app to completely restart,
94+
// so the default needs to be the current language and not a static field.
95+
if (this == DEFAULT) {
96+
// Android VR requires uppercase language code.
97+
return Locale.getDefault().toLanguageTag().toUpperCase(Locale.US);
98+
}
99+
100+
return iso639_1;
101+
}
102+
}

extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/SpoofVideoStreamsPatch.java

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import app.revanced.extension.shared.settings.BaseSettings;
1414
import app.revanced.extension.shared.settings.Setting;
1515
import app.revanced.extension.shared.spoof.requests.StreamingDataRequest;
16-
import app.revanced.extension.shared.settings.BaseSettings;
1716

1817
@SuppressWarnings("unused")
1918
public class SpoofVideoStreamsPatch {

extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/requests/PlayerRoutes.java

+2-6
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
import java.net.HttpURLConnection;
88

99
import app.revanced.extension.shared.Logger;
10-
import app.revanced.extension.shared.Utils;
1110
import app.revanced.extension.shared.requests.Requester;
1211
import app.revanced.extension.shared.requests.Route;
12+
import app.revanced.extension.shared.settings.BaseSettings;
1313
import app.revanced.extension.shared.spoof.ClientType;
1414

1515
final class PlayerRoutes {
@@ -25,9 +25,6 @@ final class PlayerRoutes {
2525
*/
2626
private static final int CONNECTION_TIMEOUT_MILLISECONDS = 10 * 1000; // 10 Seconds.
2727

28-
private static final String LOCALE_LANGUAGE = Utils.getContext().getResources()
29-
.getConfiguration().locale.getLanguage();
30-
3128
private PlayerRoutes() {
3229
}
3330

@@ -38,8 +35,7 @@ static String createInnertubeBody(ClientType clientType) {
3835
JSONObject context = new JSONObject();
3936

4037
JSONObject client = new JSONObject();
41-
// Required to use correct default audio channel with iOS.
42-
client.put("hl", LOCALE_LANGUAGE);
38+
client.put("hl", BaseSettings.SPOOF_VIDEO_STREAMS_LANGUAGE.get().getIso639_1());
4339
client.put("clientName", clientType.name());
4440
client.put("clientVersion", clientType.clientVersion);
4541
client.put("deviceModel", clientType.deviceModel);

extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReVancedPreferenceFragment.java

+53-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.preference.ListPreference;
1111
import android.preference.Preference;
1212
import android.preference.PreferenceScreen;
13+
import android.util.Pair;
1314
import android.util.TypedValue;
1415
import android.view.ViewGroup;
1516
import android.view.WindowInsets;
@@ -18,6 +19,10 @@
1819

1920
import androidx.annotation.RequiresApi;
2021

22+
import java.util.ArrayList;
23+
import java.util.Collections;
24+
import java.util.List;
25+
2126
import app.revanced.extension.shared.Logger;
2227
import app.revanced.extension.shared.Utils;
2328
import app.revanced.extension.shared.settings.preference.AbstractPreferenceFragment;
@@ -41,6 +46,46 @@ public static Drawable getBackButtonDrawable() {
4146
return Utils.getContext().getResources().getDrawable(backButtonResource);
4247
}
4348

49+
/**
50+
* Sorts a preference list by menu entries, but preserves the first value as the first entry.
51+
*/
52+
private static void sortListPreferenceByValues(ListPreference listPreference) {
53+
CharSequence[] entries = listPreference.getEntries();
54+
CharSequence[] entryValues = listPreference.getEntryValues();
55+
final int entrySize = entries.length;
56+
57+
if (entrySize != entryValues.length) {
58+
throw new IllegalStateException();
59+
}
60+
61+
// Ensure the first entry remains the first after sorting.
62+
CharSequence firstEntry = entries[0];
63+
CharSequence firstEntryValue = entryValues[0];
64+
65+
List<Pair<String, String>> entryPairs = new ArrayList<>(entrySize);
66+
for (int i = 1; i < entrySize; i++) {
67+
entryPairs.add(new Pair<>(entries[i].toString(), entryValues[i].toString()));
68+
}
69+
70+
Collections.sort(entryPairs, (pair1, pair2) -> pair1.first.compareToIgnoreCase(pair2.first));
71+
72+
CharSequence[] sortedEntries = new CharSequence[entrySize];
73+
CharSequence[] sortedEntryValues = new CharSequence[entrySize];
74+
75+
sortedEntries[0] = firstEntry;
76+
sortedEntryValues[0] = firstEntryValue;
77+
78+
int i = 1;
79+
for (Pair<String, String> pair : entryPairs) {
80+
sortedEntries[i] = pair.first;
81+
sortedEntryValues[i] = pair.second;
82+
i++;
83+
}
84+
85+
listPreference.setEntries(sortedEntries);
86+
listPreference.setEntryValues(sortedEntryValues);
87+
}
88+
4489
@RequiresApi(api = Build.VERSION_CODES.O)
4590
@Override
4691
protected void initialize() {
@@ -50,9 +95,14 @@ protected void initialize() {
5095
setPreferenceScreenToolbar(getPreferenceScreen());
5196

5297
// If the preference was included, then initialize it based on the available playback speed.
53-
Preference defaultSpeedPreference = findPreference(Settings.PLAYBACK_SPEED_DEFAULT.key);
54-
if (defaultSpeedPreference instanceof ListPreference) {
55-
CustomPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference);
98+
Preference preference = findPreference(Settings.PLAYBACK_SPEED_DEFAULT.key);
99+
if (preference instanceof ListPreference playbackPreference) {
100+
CustomPlaybackSpeedPatch.initializeListPreference(playbackPreference);
101+
}
102+
103+
preference = findPreference(Settings.SPOOF_VIDEO_STREAMS_LANGUAGE.key);
104+
if (preference instanceof ListPreference languagePreference) {
105+
sortListPreferenceByValues(languagePreference);
56106
}
57107
} catch (Exception ex) {
58108
Logger.printException(() -> "initialize failure", ex);

patches/src/main/resources/addresources/values/arrays.xml

+110
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,116 @@
1111
<item>ANDROID_VR</item>
1212
<item>IOS</item>
1313
</string-array>
14+
<string-array name="revanced_spoof_video_streams_language_entries">
15+
<item>@string/revanced_spoof_video_streams_language_DEFAULT</item>
16+
<item>@string/revanced_spoof_video_streams_language_AR</item>
17+
<item>@string/revanced_spoof_video_streams_language_AZ</item>
18+
<item>@string/revanced_spoof_video_streams_language_BG</item>
19+
<item>@string/revanced_spoof_video_streams_language_BN</item>
20+
<item>@string/revanced_spoof_video_streams_language_CA</item>
21+
<item>@string/revanced_spoof_video_streams_language_CS</item>
22+
<item>@string/revanced_spoof_video_streams_language_DA</item>
23+
<item>@string/revanced_spoof_video_streams_language_DE</item>
24+
<item>@string/revanced_spoof_video_streams_language_EL</item>
25+
<item>@string/revanced_spoof_video_streams_language_EN</item>
26+
<item>@string/revanced_spoof_video_streams_language_ES</item>
27+
<item>@string/revanced_spoof_video_streams_language_ET</item>
28+
<item>@string/revanced_spoof_video_streams_language_FA</item>
29+
<item>@string/revanced_spoof_video_streams_language_FI</item>
30+
<item>@string/revanced_spoof_video_streams_language_FR</item>
31+
<item>@string/revanced_spoof_video_streams_language_GU</item>
32+
<item>@string/revanced_spoof_video_streams_language_HI</item>
33+
<item>@string/revanced_spoof_video_streams_language_HR</item>
34+
<item>@string/revanced_spoof_video_streams_language_HU</item>
35+
<item>@string/revanced_spoof_video_streams_language_ID</item>
36+
<item>@string/revanced_spoof_video_streams_language_IT</item>
37+
<item>@string/revanced_spoof_video_streams_language_JA</item>
38+
<item>@string/revanced_spoof_video_streams_language_KK</item>
39+
<item>@string/revanced_spoof_video_streams_language_KO</item>
40+
<item>@string/revanced_spoof_video_streams_language_LT</item>
41+
<item>@string/revanced_spoof_video_streams_language_LV</item>
42+
<item>@string/revanced_spoof_video_streams_language_MK</item>
43+
<item>@string/revanced_spoof_video_streams_language_MN</item>
44+
<item>@string/revanced_spoof_video_streams_language_MR</item>
45+
<item>@string/revanced_spoof_video_streams_language_MS</item>
46+
<item>@string/revanced_spoof_video_streams_language_MY</item>
47+
<item>@string/revanced_spoof_video_streams_language_NL</item>
48+
<item>@string/revanced_spoof_video_streams_language_OR</item>
49+
<item>@string/revanced_spoof_video_streams_language_PA</item>
50+
<item>@string/revanced_spoof_video_streams_language_PL</item>
51+
<item>@string/revanced_spoof_video_streams_language_PT_BR</item>
52+
<item>@string/revanced_spoof_video_streams_language_PT_PT</item>
53+
<item>@string/revanced_spoof_video_streams_language_RO</item>
54+
<item>@string/revanced_spoof_video_streams_language_RU</item>
55+
<item>@string/revanced_spoof_video_streams_language_SK</item>
56+
<item>@string/revanced_spoof_video_streams_language_SL</item>
57+
<item>@string/revanced_spoof_video_streams_language_SR</item>
58+
<item>@string/revanced_spoof_video_streams_language_SV</item>
59+
<item>@string/revanced_spoof_video_streams_language_SW</item>
60+
<item>@string/revanced_spoof_video_streams_language_TA</item>
61+
<item>@string/revanced_spoof_video_streams_language_TE</item>
62+
<item>@string/revanced_spoof_video_streams_language_TH</item>
63+
<item>@string/revanced_spoof_video_streams_language_TR</item>
64+
<item>@string/revanced_spoof_video_streams_language_UK</item>
65+
<item>@string/revanced_spoof_video_streams_language_UR</item>
66+
<item>@string/revanced_spoof_video_streams_language_VI</item>
67+
<item>@string/revanced_spoof_video_streams_language_ZH</item>
68+
</string-array>
69+
<string-array name="revanced_spoof_video_streams_language_entry_values">
70+
<item>DEFAULT</item>
71+
<item>AR</item>
72+
<item>AZ</item>
73+
<item>BG</item>
74+
<item>BN</item>
75+
<item>CA</item>
76+
<item>CS</item>
77+
<item>DA</item>
78+
<item>DE</item>
79+
<item>EL</item>
80+
<item>EN</item>
81+
<item>ES</item>
82+
<item>ET</item>
83+
<item>FA</item>
84+
<item>FI</item>
85+
<item>FR</item>
86+
<item>GU</item>
87+
<item>HI</item>
88+
<item>HR</item>
89+
<item>HU</item>
90+
<item>ID</item>
91+
<item>IT</item>
92+
<item>JA</item>
93+
<item>KK</item>
94+
<item>KO</item>
95+
<item>LT</item>
96+
<item>LV</item>
97+
<item>MK</item>
98+
<item>MN</item>
99+
<item>MR</item>
100+
<item>MS</item>
101+
<item>MY</item>
102+
<item>NL</item>
103+
<item>OR</item>
104+
<item>PA</item>
105+
<item>PL</item>
106+
<item>PT_BR</item>
107+
<item>PT_PT</item>
108+
<item>RO</item>
109+
<item>RU</item>
110+
<item>SK</item>
111+
<item>SL</item>
112+
<item>SR</item>
113+
<item>SV</item>
114+
<item>SW</item>
115+
<item>TA</item>
116+
<item>TE</item>
117+
<item>TH</item>
118+
<item>TR</item>
119+
<item>UK</item>
120+
<item>UR</item>
121+
<item>VI</item>
122+
<item>ZH</item>
123+
</string-array>
14124
</patch>
15125
<patch id="layout.spoofappversion.spoofAppVersionPatch">
16126
<string-array name="revanced_spoof_app_version_target_entries">

0 commit comments

Comments
 (0)