Merge pull request #583 from neilsb/user-setting-screen

This commit is contained in:
Neil Burrows 2022-05-02 14:04:22 +01:00 committed by GitHub
commit bdb296a870
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 300 additions and 24 deletions

1
app.mk
View File

@ -108,6 +108,7 @@ prep_staging:
cp -r $(SOURCEREL)/source $(STAGINGREL)
cp -r $(SOURCEREL)/components $(STAGINGREL)
cp -r $(SOURCEREL)/images $(STAGINGREL)
cp -r $(SOURCEREL)/settings $(STAGINGREL)
# Copy only supported languages over to staging
mkdir $(STAGINGREL)/locale

View File

@ -5,7 +5,8 @@
"components/**/*.*",
"images/**/*.*",
"resources/**/*.*",
"locale/**/*.*"
"locale/**/*.*",
"settings/*.*"
],
"plugins": [ "@rokucommunity/bslint" ]
}

View File

@ -114,6 +114,12 @@ sub clearScenes()
m.groups = []
end sub
'
' Display user/device settings screen
sub settings()
settingsScreen = createObject("roSGNode", "Settings")
pushScene(settingsScreen)
end sub
'
' Register observers for overhang data

View File

@ -3,6 +3,7 @@
<interface>
<function name="pushScene" />
<function name="popScene" />
<function name="settings" />
<function name="getActiveScene" />
<function name="clearScenes" />
<function name="resetTime" />

View File

@ -0,0 +1,5 @@
<component name="Setting" extends="ContentNode">
<interface>
<field id="type" type="string" />
</interface>
</component>

View File

@ -0,0 +1,141 @@
sub init()
m.top.overhangTitle = tr("Settings")
m.top.optionsAvailable = false
m.userLocation = []
m.settingsMenu = m.top.findNode("settingsMenu")
m.settingDetail = m.top.findNode("settingDetail")
m.settingDesc = m.top.findNode("settingDesc")
m.settingTitle = m.top.findNode("settingTitle")
m.path = m.top.findNode("path")
m.boolSetting = m.top.findNode("boolSetting")
m.settingsMenu.setFocus(true)
m.settingsMenu.observeField("itemFocused", "settingFocused")
m.settingsMenu.observeField("itemSelected", "settingSelected")
m.boolSetting.observeField("checkedItem", "boolSettingChanged")
' Load Configuration Tree
m.configTree = GetConfigTree()
LoadMenu({ children: m.configTree })
end sub
sub LoadMenu(configSection)
if configSection.children = invalid
' Load parent menu
m.userLocation.pop()
configSection = m.userLocation.peek()
else
if m.userLocation.Count() > 0 then m.userLocation.peek().selectedIndex = m.settingsMenu.itemFocused
m.userLocation.push(configSection)
end if
result = CreateObject("roSGNode", "ContentNode")
for each item in configSection.children
listItem = result.CreateChild("ContentNode")
listItem.title = tr(item.title)
listItem.Description = tr(item.description)
listItem.id = item.id
end for
m.settingsMenu.content = result
if configSection.selectedIndex <> invalid and configSection.selectedIndex > -1
m.settingsMenu.jumpToItem = configSection.selectedIndex
end if
' Set Path display
m.path.text = ""
for each level in m.userLocation
if level.title <> invalid then m.path.text += " / " + tr(level.title)
end for
end sub
sub settingFocused()
selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]
m.settingDesc.text = tr(selectedSetting.Description)
m.settingTitle.text = tr(selectedSetting.Title)
' Hide Settings
m.boolSetting.visible = false
if selectedSetting.type = invalid
return
else if selectedSetting.type = "bool"
m.boolSetting.visible = true
if get_user_setting(selectedSetting.settingName) = "true"
m.boolSetting.checkedItem = 1
else
m.boolSetting.checkedItem = 0
end if
else
print "Unknown setting type " + selectedSetting.type
end if
end sub
sub settingSelected()
selectedItem = m.userLocation.peek().children[m.settingsMenu.itemFocused]
if selectedItem.type <> invalid ' Show setting
if selectedItem.type = "bool"
m.boolSetting.setFocus(true)
end if
else if selectedItem.children <> invalid and selectedItem.children.Count() > 0 ' Show sub menu
LoadMenu(selectedItem)
m.settingsMenu.setFocus(true)
else
return
end if
m.settingDesc.text = m.settingsMenu.content.GetChild(m.settingsMenu.itemFocused).Description
end sub
sub boolSettingChanged()
if m.boolSetting.focusedChild = invalid then return
selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]
if m.boolSetting.checkedItem
set_user_setting(selectedSetting.settingName, "true")
else
set_user_setting(selectedSetting.settingName, "false")
end if
end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if (key = "back" or key = "left") and m.settingsMenu.focusedChild <> invalid and m.userLocation.Count() > 1
LoadMenu({})
return true
else if (key = "back" or key = "left") and m.settingDetail.focusedChild <> invalid
m.settingsMenu.setFocus(true)
return true
end if
if key = "right"
settingSelected()
end if
return false
end function

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="Settings" extends="JFGroup">
<children>
<Label id="path" translation = "[95,175]" font="font:SmallestBoldSystemFont" />
<LabelList
translation = "[120,250]"
id = "settingsMenu"
itemSize = "[440,48]"
vertFocusAnimationStyle = "floatingFocus"
focusBitmapBlendColor = "#006fab"
focusedColor = "#ffffff"
itemSpacing = "[0,5]"
/>
<Poster
translation = "[710,250]"
id="testRectangle"
width="880"
height="700"
uri="pkg:/images/white.9.png"
blendColor = "#3f3f3f"
/>
<LayoutGroup
translation = "[1150,275]"
id="settingDetail"
vertAlignment="top"
horizAlignment="center"
itemSpacings="[50]"
>
<ScrollingLabel font="font:LargeSystemFont" id="settingTitle" maxWidth="750" />
<Label id="settingDesc" width="750" wrap = "true" />
<RadioButtonList id="boolSetting" vertFocusAnimationStyle="floatingFocus">
<ContentNode role="content">
<ContentNode title="Disabled" />
<ContentNode title="Enabled" />
</ContentNode>
</RadioButtonList>
</LayoutGroup>
</children>
<script type="text/brightscript" uri="settings.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
</component>

View File

@ -470,5 +470,28 @@
<source>Version</source>
<translation>Version</translation>
</message>
<message>
<source>Playback</source>
<translation>Playback</translation>
<extracomment>Title for Playback section in user setting screen.</extracomment>
</message>
<message>
<source>MPEG 2 Support</source>
<translation>MPEG 2 Support</translation>
<extracomment>Settings Menu - Title for option</extracomment>
</message>
<message>
<source>Support direct play of MPEG 2 content (e.g. Live TV). This will prevent transcoding of MPEG 2 content, but uses significantly more bandwidth</source>
<translation>Support direct play of MPEG 2 content (e.g. Live TV). This will prevent transcoding of MPEG 2 content, but uses significantly more bandwidth</translation>
<extracomment>Settings Menu - Description for option</extracomment>
</message>
<message>
<source>Enabled</source>
<translation>Enabled</translation>
</message>
<message>
<source>Disabled</source>
<translation>Disabled</translation>
</message>
</context>
</TS>

15
settings/settings.json Normal file
View File

@ -0,0 +1,15 @@
[
{
"title": "Playback",
"description": "Settings related to playback and supported codec and media types",
"children": [
{
"title": "MPEG 2 Support",
"description": "Support direct play of MPEG 2 content (e.g. Live TV). This will prevent transcoding of MPEG 2 content, but uses significantly more bandwidth",
"settingName": "playback.mpeg2",
"type": "bool",
"default": "false"
}
]
}
]

View File

@ -10,6 +10,13 @@ sub Main (args as dynamic) as void
' Set global constants
setConstants()
' Temporary code to migrate MPEG2 setting from device setting to user setting
' Added for 1.4.13 release and should probably be removed for 1.4.15
if get_setting("playback.mpeg2") <> invalid and registry_read("playback.mpeg2", get_setting("active_user")) = invalid
set_user_setting("playback.mpeg2", get_setting("playback.mpeg2"))
end if
' End Temporary code
m.port = CreateObject("roMessagePort")
m.screen.setMessagePort(m.port)
m.scene = m.screen.CreateScene("JFScene")
@ -274,16 +281,16 @@ sub Main (args as dynamic) as void
SignOut()
sceneManager.callFunc("clearScenes")
goto app_start
else if button.id = "play_mpeg2"
playMpeg2 = get_setting("playback.mpeg2")
if playMpeg2 = "true"
playMpeg2 = "false"
button.title = tr("MPEG2 Support: Off")
else if button.id = "settings"
' Exit out of the side panel
panel = group.findNode("options")
panel.visible = false
if group.lastFocus <> invalid
group.lastFocus.setFocus(true)
else
playMpeg2 = "true"
button.title = tr("MPEG2 Support: On")
group.setFocus(true)
end if
set_setting("playback.mpeg2", playMpeg2)
sceneManager.callFunc("settings")
end if
else if isNodeEvent(msg, "selectSubtitlePressed")
node = m.scene.focusedChild

View File

@ -258,19 +258,10 @@ function CreateHomeGroup()
new_options.push(o)
end for
' Add option for mpeg-2 playback
playMpeg2 = get_setting("playback.mpeg2")
if playMpeg2 = invalid
playMpeg2 = "true"
set_setting("playback.mpeg2", playMpeg2)
end if
' Add settings option to menu
o = CreateObject("roSGNode", "OptionsButton")
if playMpeg2 = "true"
o.title = tr("MPEG2 Support: On")
else
o.title = tr("MPEG2 Support: Off")
end if
o.id = "play_mpeg2"
o.title = "Settings"
o.id = "settings"
o.observeField("optionSelected", m.port)
new_options.push(o)

View File

@ -1,5 +1,10 @@
' "Registry" is where Roku stores config
' Read config tree from json config file and return
function GetConfigTree()
return ParseJSON(ReadAsciiFile("pkg:/settings/settings.json"))
end function
' Generic registry accessors
function registry_read(key, section = invalid)
@ -44,7 +49,19 @@ end sub
function get_user_setting(key, default = invalid)
if get_setting("active_user") = invalid then return default
value = registry_read(key, get_setting("active_user"))
if value = invalid then return default
if value = invalid
' Check for default in Config Tree
configTree = GetConfigTree()
configKey = findConfigTreeKey(key, configTree)
if configKey <> invalid and configKey.default <> invalid
set_user_setting(key, configKey.default) ' Set user setting to default
return configKey.default
end if
return default
end if
return value
end function
@ -57,3 +74,20 @@ sub unset_user_setting(key)
if get_setting("active_user") = invalid then return
registry_delete(key, get_setting("active_user"))
end sub
' Recursivly search the config tree for entry with settingname equal to key
function findConfigTreeKey(key as string, tree)
for each item in tree
if item.settingName <> invalid and item.settingName = key then return item
if item.children <> invalid and item.children.Count() > 0
result = findConfigTreeKey(key, item.children)
if result <> invalid then return result
end if
end for
return invalid
end function

View File

@ -17,7 +17,7 @@ end function
function getDeviceProfile() as object
playMpeg2 = get_setting("playback.mpeg2") = "true"
playMpeg2 = get_user_setting("playback.mpeg2") = "true"
'Check if 5.1 Audio Output connected
maxAudioChannels = 2
@ -165,7 +165,7 @@ function GetDirectPlayProfiles() as object
mkvAudio = "mp3,pcm,lpcm,wav"
audio = "mp3,pcm,lpcm,wav"
playMpeg2 = get_setting("playback.mpeg2") = "true"
playMpeg2 = get_user_setting("playback.mpeg2") = "true"
di = CreateObject("roDeviceInfo")