Skip to content

Commit 973427e

Browse files
committed
Update code docs
1 parent bac5099 commit 973427e

3 files changed

Lines changed: 81 additions & 6 deletions

File tree

docs/data/search.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/module-streamSelection.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/source_utils_streamSelection.bs.html

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66
' Comprehensive audio and video stream selection utilities
77
' Combines user preferences with hardware capabilities for optimal playback
88

9+
' JellyfinLanguage: ISO 639-2 three-letter language codes used by Jellyfin
10+
' Only includes languages supported by Roku OS locales
11+
enum JellyfinLanguage
12+
ENGLISH = "eng"
13+
SPANISH = "spa"
14+
PORTUGUESE = "por"
15+
FRENCH = "fra"
16+
GERMAN = "deu"
17+
ITALIAN = "ita"
18+
end enum
19+
920
' resolvePlayDefaultAudioTrack: Resolves the playDefaultAudioTrack setting value
1021
'
1122
' Checks JellyRock override setting first, then falls back to web client setting.
@@ -40,6 +51,54 @@
4051
return defaultValue
4152
end function
4253

54+
' mapRokuLocaleToJellyfinLanguage: Converts Roku locale codes to Jellyfin ISO 639-2 language codes
55+
'
56+
' Maps Roku device locale (e.g., "en_US", "fr_CA") to Jellyfin's 3-letter language codes.
57+
' Extracts base language from locale and maps to standard ISO 639-2 codes.
58+
'
59+
' Supported Roku locales:
60+
' - en_US, en_GB, en_CA, en_AU → eng (English)
61+
' - es_ES, es_MX → spa (Spanish)
62+
' - pt_BR → por (Portuguese)
63+
' - fr_CA → fra (French)
64+
' - de_DE → deu (German)
65+
' - it_IT → ita (Italian)
66+
'
67+
' @param {dynamic} rokuLocale - Roku locale string (e.g., "en_US", "fr_CA")
68+
' @returns {string} - Jellyfin ISO 639-2 language code (e.g., "eng", "fra"), or empty string if not recognized
69+
function mapRokuLocaleToJellyfinLanguage(rokuLocale as dynamic) as string
70+
if not isValid(rokuLocale) or rokuLocale = "" then return ""
71+
72+
' Extract base language (first 2 characters before underscore)
73+
' "en_US" → "en", "fr_CA" → "fr"
74+
baseLanguage = ""
75+
underscorePos = rokuLocale.Instr("_")
76+
if underscorePos > -1
77+
baseLanguage = LCase(Left(rokuLocale, underscorePos))
78+
else
79+
' No underscore found - use entire string (shouldn't happen with valid Roku locales)
80+
baseLanguage = LCase(rokuLocale)
81+
end if
82+
83+
' Map base language to Jellyfin ISO 639-2 code
84+
if baseLanguage = "en"
85+
return JellyfinLanguage.ENGLISH
86+
else if baseLanguage = "es"
87+
return JellyfinLanguage.SPANISH
88+
else if baseLanguage = "pt"
89+
return JellyfinLanguage.PORTUGUESE
90+
else if baseLanguage = "fr"
91+
return JellyfinLanguage.FRENCH
92+
else if baseLanguage = "de"
93+
return JellyfinLanguage.GERMAN
94+
else if baseLanguage = "it"
95+
return JellyfinLanguage.ITALIAN
96+
end if
97+
98+
' Unknown language - return empty string
99+
return ""
100+
end function
101+
43102
' findBestAudioStreamIndex: Primary function for selecting the best audio stream
44103
'
45104
' Selection priority when playDefault = true (Jellyfin: "Play default audio track regardless of language"):
@@ -53,6 +112,11 @@
53112
' 2. If multiple language matches, apply hardware optimization
54113
' 3. If no language matches, apply hardware optimization to all streams
55114
'
115+
' Roku OS Language Fallback:
116+
' When preferredLanguage is blank/empty, automatically uses the Roku device's
117+
' OS language (from m.global.device.locale) as fallback for better
118+
' out-of-box experience (see issue #179)
119+
'
56120
' Hardware optimization:
57121
' - Prefer streams matching device's max channel capability
58122
' - Among matches, prefer direct-playable codecs
@@ -71,6 +135,17 @@
71135
deviceCapabilities = getDeviceAudioCapabilities()
72136
end if
73137

138+
' Apply Roku OS language fallback when web client language preference is blank
139+
' This provides better out-of-box experience for new users (issue #179)
140+
effectiveLanguage = preferredLanguage
141+
if not isValid(preferredLanguage) or preferredLanguage = ""
142+
' Get Roku OS locale from global device node
143+
rokuLocale = m.global.device.locale
144+
if isValid(rokuLocale) and rokuLocale <> ""
145+
effectiveLanguage = mapRokuLocaleToJellyfinLanguage(rokuLocale)
146+
end if
147+
end if
148+
74149
' Collect all audio streams with valid index fields
75150
' Streams without index cannot be selected, so filter them out early
76151
audioStreams = []
@@ -111,10 +186,10 @@
111186
end if
112187
else
113188
' Multiple IsDefault streams - try language preference as tiebreaker
114-
if isValid(preferredLanguage) and preferredLanguage <> ""
189+
if isValid(effectiveLanguage) and effectiveLanguage <> ""
115190
languageMatchedDefaults = []
116191
for i = 0 to defaultStreams.Count() - 1
117-
if isValid(defaultStreams[i].Language) and LCase(defaultStreams[i].Language) = LCase(preferredLanguage)
192+
if isValid(defaultStreams[i].Language) and LCase(defaultStreams[i].Language) = LCase(effectiveLanguage)
118193
languageMatchedDefaults.push(defaultStreams[i])
119194
end if
120195
end for
@@ -141,10 +216,10 @@
141216

142217
' BRANCH 2: Either playDefault = false OR playDefault = true but no IsDefault streams found
143218
' Use language preference as primary filter (completely ignore IsDefault flag)
144-
if isValid(preferredLanguage) and preferredLanguage <> ""
219+
if isValid(effectiveLanguage) and effectiveLanguage <> ""
145220
languageMatchedStreams = []
146221
for i = 0 to audioStreams.Count() - 1
147-
if isValid(audioStreams[i].Language) and LCase(audioStreams[i].Language) = LCase(preferredLanguage)
222+
if isValid(audioStreams[i].Language) and LCase(audioStreams[i].Language) = LCase(effectiveLanguage)
148223
languageMatchedStreams.push(audioStreams[i])
149224
end if
150225
end for

0 commit comments

Comments
 (0)