Merge pull request #459 from neilsb/add-brightscript-linter

Add brightscript linter to CI pipeline
This commit is contained in:
Anthony Lavado 2021-06-28 20:18:08 -04:00 committed by GitHub
commit 09a1d87283
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 1160 additions and 890 deletions

View File

@ -6,5 +6,6 @@
"images/**/*.*",
"resources/**/*.*",
"locale/**/*.*"
]
],
"plugins": [ "@rokucommunity/bslint" ]
}

View File

@ -34,7 +34,7 @@ end sub
'
' When options are fully displayed, set focus and selected option
sub renderChanged()
if m.top.renderTracking = "full" then
if m.top.renderTracking = "full"
highlightSelected(m.selectedFocusedIndex, false)
m.top.setfocus(true)
end if
@ -77,7 +77,7 @@ sub highlightSelected(index as integer, animate = true)
val = m.buttonGroup.getChild(index)
rect = val.ancestorBoundingRect(m.top)
if animate = true then
if animate = true
m.focusAnimTranslation.keyValue = [m.focusRing.translation, [rect.x - 25, rect.y - 30]]
m.focusAnimWidth.keyValue = [m.focusRing.width, val.width + 50]
m.focusAnimHeight.keyValue = [m.focusRing.height, val.height + 60]
@ -92,7 +92,7 @@ end sub
' Change opacity of the highlighted menu item based on focus
sub focusChanged()
if m.top.isInFocusChain() then
if m.top.isInFocusChain()
m.focusRing.opacity = 1
else
m.focusRing.opacity = 0.6
@ -105,12 +105,12 @@ function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if key = "left"
if(m.selectedFocusedIndex > 0) m.selectedFocusedIndex = m.selectedFocusedIndex - 1
if m.selectedFocusedIndex > 0 then m.selectedFocusedIndex = m.selectedFocusedIndex - 1
highlightSelected(m.selectedFocusedIndex)
m.top.focusedIndex = m.selectedFocusedIndex
return true
else if key = "right"
if(m.selectedFocusedIndex < m.buttonCount - 1) m.selectedFocusedIndex = m.selectedFocusedIndex + 1
if m.selectedFocusedIndex < m.buttonCount - 1 then m.selectedFocusedIndex = m.selectedFocusedIndex + 1
highlightSelected(m.selectedFocusedIndex)
m.top.focusedIndex = m.selectedFocusedIndex
return true

View File

@ -29,23 +29,23 @@ sub itemContentChanged()
if itemData = invalid then return
if itemData.type = "Movie" then
if itemData.type = "Movie"
m.itemPoster.uri = itemData.PosterUrl
m.itemText.text = itemData.Title
else if itemData.type = "Series" then
else if itemData.type = "Series"
m.itemPoster.uri = itemData.PosterUrl
m.itemText.text = itemData.Title
else if itemData.type = "Boxset" then
else if itemData.type = "Boxset"
m.itemPoster.uri = itemData.PosterUrl
m.itemText.text = itemData.Title
else if itemData.type = "TvChannel" then
else if itemData.type = "TvChannel"
m.itemPoster.uri = itemData.PosterUrl
m.itemText.text = itemData.Title
else if itemData.type = "Folder" then
else if itemData.type = "Folder"
m.itemPoster.uri = itemData.PosterUrl
m.itemIcon.uri = itemData.iconUrl
m.itemText.text = itemData.Title
else if itemData.type = "Video" then
else if itemData.type = "Video"
m.itemPoster.uri = itemData.PosterUrl
m.itemText.text = itemData.Title
else
@ -53,7 +53,7 @@ sub itemContentChanged()
end if
'If Poster not loaded, ensure "blue box" is shown until loaded
if m.itemPoster.loadStatus <> "ready" then
if m.itemPoster.loadStatus <> "ready"
m.backdrop.visible = true
m.posterText.visible = true
end if
@ -73,7 +73,7 @@ end sub
'Display or hide title Visibility on focus change
sub focusChanged()
if m.top.itemHasFocus = true then
if m.top.itemHasFocus = true
m.itemText.visible = true
m.itemText.repeatCount = -1
else
@ -85,7 +85,7 @@ end sub
'Hide backdrop and text when poster loaded
sub onPosterLoadStatusChanged()
if m.itemPoster.loadStatus = "ready" then
if m.itemPoster.loadStatus = "ready"
m.backdrop.visible = false
m.posterText.visible = false
end if

View File

@ -40,7 +40,7 @@ end sub
'Load initial set of Data
sub loadInitialItems()
if m.top.parentItem.backdropUrl <> invalid then
if m.top.parentItem.backdropUrl <> invalid
SetBackground(m.top.parentItem.backdropUrl)
end if
@ -50,24 +50,24 @@ sub loadInitialItems()
m.loadItemsTask.filter = m.filter
m.loadItemsTask.startIndex = 0
if m.top.parentItem.collectionType = "movies" then
if m.top.parentItem.collectionType = "movies"
m.loadItemsTask.itemType = "Movie"
else if m.top.parentItem.collectionType = "tvshows" then
else if m.top.parentItem.collectionType = "tvshows"
m.loadItemsTask.itemType = "Series"
else if m.top.parentItem.collectionType = "livetv" then
else if m.top.parentItem.collectionType = "livetv"
m.loadItemsTask.itemType = "LiveTV"
'For LiveTV, we want to "Fit" the item images, not zoom
m.top.imageDisplayMode = "scaleToFit"
if get_user_setting("display.livetv.landing") = "guide" then
if get_user_setting("display.livetv.landing") = "guide"
showTvGuid()
end if
else if m.top.parentItem.collectionType = "CollectionFolder" OR m.top.parentItem.collectionType = "boxsets" or m.top.parentItem.Type = "Folder" or m.top.parentItem.Type = "Channel" then
else if m.top.parentItem.collectionType = "CollectionFolder" OR m.top.parentItem.collectionType = "boxsets" or m.top.parentItem.Type = "Folder" or m.top.parentItem.Type = "Channel"
' Non-recursive, to not show subfolder contents
m.loadItemsTask.recursive = false
else if m.top.parentItem.collectionType = "Channel" then
else if m.top.parentItem.collectionType = "Channel"
m.top.imageDisplayMode = "scaleToFit"
else
print "[ItemGrid] Unknown Type: " m.top.parentItem
@ -87,7 +87,7 @@ sub SetUpOptions()
options.filter = []
'Movies
if m.top.parentItem.collectionType = "movies" then
if m.top.parentItem.collectionType = "movies"
options.views = [
{ "Title": tr("Movies"), "Name": "movies" },
]
@ -107,7 +107,7 @@ sub SetUpOptions()
{ "Title": tr("Favorites"), "Name": "Favorites" }
]
'Boxsets
else if m.top.parentItem.collectionType = "boxsets" then
else if m.top.parentItem.collectionType = "boxsets"
options.views = [{ "Title": tr("Shows"), "Name": "shows" }]
options.sort = [
{ "Title": tr("TITLE"), "Name": "SortName" },
@ -120,7 +120,7 @@ sub SetUpOptions()
{ "Title": tr("Favorites"), "Name": "Favorites" }
]
'TV Shows
else if m.top.parentItem.collectionType = "tvshows" then
else if m.top.parentItem.collectionType = "tvshows"
options.views = [{ "Title": tr("Shows"), "Name": "shows" }]
options.sort = [
{ "Title": tr("TITLE"), "Name": "SortName" },
@ -132,7 +132,7 @@ sub SetUpOptions()
]
options.filter = []
'Live TV
else if m.top.parentItem.collectionType = "livetv" then
else if m.top.parentItem.collectionType = "livetv"
options.views = [
{"Title": tr("Channels"), "Name": "livetv" },
{"Title": tr("TV Guide"), "Name": "tvGuide", "Selected": get_user_setting("display.livetv.landing") = "guide" }
@ -152,14 +152,14 @@ sub SetUpOptions()
end if
for each o in options.sort
if o.Name = m.sortField then
if o.Name = m.sortField
o.Selected = true
o.Ascending = m.sortAscending
end if
end for
for each o in options.filter
if o.Name = m.filter then
if o.Name = m.filter
o.Selected = true
end if
end for
@ -174,11 +174,10 @@ end sub
sub ItemDataLoaded(msg)
itemData = msg.GetData()
data = msg.getField()
m.loadItemsTask.unobserveField("content")
m.loadItemsTask.content = []
if itemData = invalid then
if itemData = invalid
m.Loading = false
return
end if
@ -193,7 +192,7 @@ sub ItemDataLoaded(msg)
m.Loading = false
'If there are no items to display, show message
if m.loadedItems = 0 then
if m.loadedItems = 0
m.emptyText.text = tr("NO_ITEMS").Replace("%1", m.top.parentItem.Type)
m.emptyText.visible = true
end if
@ -207,7 +206,7 @@ end sub
sub SetBackground(backgroundUri as string)
'If a new image is being loaded, or transitioned to, store URL to load next
if m.swapAnimation.state <> "stopped" or m.newBackdrop.loadStatus = "loading" then
if m.swapAnimation.state <> "stopped" or m.newBackdrop.loadStatus = "loading"
m.queuedBGUri = backgroundUri
return
end if
@ -224,7 +223,7 @@ sub onItemFocused()
itemInt = m.itemGrid.itemFocused
' If no selected item, set background to parent backdrop
if itemInt = -1 then
if itemInt = -1
return
end if
@ -232,7 +231,7 @@ sub onItemFocused()
SetBackground(m.itemGrid.content.getChild(m.itemGrid.itemFocused).backdropUrl)
' Load more data if focus is within last 3 rows, and there are more items to load
if focusedRow >= m.loadedRows - 3 and m.loadeditems < m.loadItemsTask.totalRecordCount then
if focusedRow >= m.loadedRows - 3 and m.loadeditems < m.loadItemsTask.totalRecordCount
loadMoreData()
end if
end sub
@ -250,7 +249,7 @@ end sub
'Swap Complete
sub swapDone()
if m.swapAnimation.state = "stopped" then
if m.swapAnimation.state = "stopped"
'Set main BG node image and hide transitioning node
m.backdrop.uri = m.newBackdrop.uri
@ -258,7 +257,7 @@ sub swapDone()
m.newBackdrop.opacity = 0
'If there is another one to load
if m.newBackdrop.uri <> m.queuedBGUri and m.queuedBGUri <> "" then
if m.newBackdrop.uri <> m.queuedBGUri and m.queuedBGUri <> ""
SetBackground(m.queuedBGUri)
m.queuedBGUri = ""
end if
@ -288,21 +287,21 @@ end sub
'Check if options updated and any reloading required
sub optionsClosed()
if (m.options.view = "tvGuide") then
if m.options.view = "tvGuide"
showTVGuid()
return
else if m.tvGuide <> invalid then
else if m.tvGuide <> invalid
' Try to hide the TV Guide
m.top.removeChild(m.tvGuide)
end if
reload = false
if m.options.sortField <> m.sortField or m.options.sortAscending <> m.sortAscending then
if m.options.sortField <> m.sortField or m.options.sortAscending <> m.sortAscending
m.sortField = m.options.sortField
m.sortAscending = m.options.sortAscending
reload = true
end if
if m.options.filter <> m.filter then
if m.options.filter <> m.filter
m.filter = m.options.filter
reload = true
end if
@ -318,7 +317,7 @@ end sub
sub showTVGuid()
m.top.signalBeacon("EPGLaunchInitiate") ' Required Roku Performance monitoring
if m.tvGuide = invalid then
if m.tvGuide = invalid
m.tvGuide = createObject("roSGNode", "Schedule")
endif
m.tvGuide.observeField("watchChannel", "onChannelSelected")
@ -329,7 +328,7 @@ end sub
sub onChannelSelected(msg)
node = msg.getRoSGNode()
m.top.lastFocus = lastFocusedChild(node)
if node.watchChannel <> invalid then
if node.watchChannel <> invalid
' Clone the node when it's reused/update in the TimeGrid it doesn't automatically start playing
m.top.selectedItem = node.watchChannel.clone(false)
end if
@ -340,7 +339,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if key = "options"
if m.options.visible = true then
if m.options.visible = true
m.options.visible = false
m.top.removeChild(m.options)
optionsClosed()
@ -350,16 +349,16 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.options.setFocus(true)
end if
return true
else if key = "back" then
if m.options.visible = true then
else if key = "back"
if m.options.visible = true
m.options.visible = false
optionsClosed()
return true
end if
else if key = "play" then
else if key = "play"
markupGrid = m.top.getChild(2)
itemToPlay = markupGrid.content.getChild(markupGrid.itemFocused)
if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode") then
if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
m.top.quickPlayNode = itemToPlay
end if
return true

View File

@ -30,7 +30,7 @@ end sub
sub optionsSet()
' Views Tab
if m.top.options.views <> invalid then
if m.top.options.views <> invalid
viewContent = CreateObject("roSGNode", "ContentNode")
index = 0
selectedViewIndex = 0
@ -39,7 +39,7 @@ sub optionsSet()
entry = viewContent.CreateChild("ContentNode")
entry.title = view.Title
m.viewNames.push(view.Name)
if (view.selected <> invalid and view.selected = true) or viewContent.Name = m.top.view then
if (view.selected <> invalid and view.selected = true) or viewContent.Name = m.top.view
selectedViewIndex = index
end if
index = index + 1
@ -49,7 +49,7 @@ sub optionsSet()
end if
' Sort Tab
if m.top.options.sort <> invalid then
if m.top.options.sort <> invalid
sortContent = CreateObject("roSGNode", "ContentNode")
index = 0
m.selectedSortIndex = 0
@ -58,9 +58,9 @@ sub optionsSet()
entry = sortContent.CreateChild("ContentNode")
entry.title = sortItem.Title
m.sortNames.push(sortItem.Name)
if sortItem.Selected <> invalid and sortItem.Selected = true then
if sortItem.Selected <> invalid and sortItem.Selected = true
m.selectedSortIndex = index
if sortItem.Ascending <> invalid and sortItem.Ascending = false then
if sortItem.Ascending <> invalid and sortItem.Ascending = false
m.top.sortAscending = 0
else
m.top.sortAscending = 1
@ -71,7 +71,7 @@ sub optionsSet()
m.menus[1].content = sortContent
m.menus[1].checkedItem = m.selectedSortIndex
if m.top.sortAscending = 1 then
if m.top.sortAscending = 1
m.menus[1].focusedCheckedIconUri = m.global.constants.icons.ascending_black
m.menus[1].checkedIconUri = m.global.constants.icons.ascending_white
else
@ -81,7 +81,7 @@ sub optionsSet()
end if
' Filter Tab
if m.top.options.filter <> invalid then
if m.top.options.filter <> invalid
filterContent = CreateObject("roSGNode", "ContentNode")
index = 0
m.selectedFilterIndex = 0
@ -90,7 +90,7 @@ sub optionsSet()
entry = filterContent.CreateChild("ContentNode")
entry.title = filterItem.Title
m.filterNames.push(filterItem.Name)
if filterItem.selected <> invalid and filterItem.selected = true then
if filterItem.selected <> invalid and filterItem.selected = true
m.selectedFilterIndex = index
end if
index = index + 1
@ -121,13 +121,13 @@ end sub
function onKeyEvent(key as string, press as boolean) as boolean
if key = "down" or (key = "OK" and m.top.findNode("buttons").hasFocus()) then
if key = "down" or (key = "OK" and m.top.findNode("buttons").hasFocus())
m.top.findNode("buttons").setFocus(false)
m.menus[m.selectedItem].setFocus(true)
m.menus[m.selectedItem].drawFocusFeedback = true
'If user presses down from button menu, focus first item. If OK, focus checked item
if key = "down" then
if key = "down"
m.menus[m.selectedItem].jumpToItem = 0
else
m.menus[m.selectedItem].jumpToItem = m.menus[m.selectedItem].itemSelected
@ -135,16 +135,16 @@ function onKeyEvent(key as string, press as boolean) as boolean
return true
else if key = "OK"
if(m.menus[m.selectedItem].isInFocusChain()) then
if m.menus[m.selectedItem].isInFocusChain()
' Handle View Screen
if(m.selectedItem = 0) then
if m.selectedItem = 0
m.selectedViewIndex = m.menus[0].itemSelected
m.top.view = m.viewNames[m.selectedViewIndex]
end if
' Handle Sort screen
if(m.selectedItem = 1) then
if m.menus[1].itemSelected <> m.selectedSortIndex then
if m.selectedItem = 1
if m.menus[1].itemSelected <> m.selectedSortIndex
m.menus[1].focusedCheckedIconUri = m.global.constants.icons.ascending_black
m.menus[1].checkedIconUri = m.global.constants.icons.ascending_white
@ -153,7 +153,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.top.sortField = m.sortNames[m.selectedSortIndex]
else
if m.top.sortAscending = true then
if m.top.sortAscending = true
m.top.sortAscending = false
m.menus[1].focusedCheckedIconUri = m.global.constants.icons.descending_black
m.menus[1].checkedIconUri = m.global.constants.icons.descending_white
@ -165,14 +165,14 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
end if
' Handle Filter screen
if(m.selectedItem = 2) then
if m.selectedItem = 2
m.selectedFilterIndex = m.menus[2].itemSelected
m.top.filter = m.filterNames[m.selectedFilterIndex]
end if
end if
return true
else if key = "back" or key = "up"
if m.menus[m.selectedItem].isInFocusChain() then
if m.menus[m.selectedItem].isInFocusChain()
m.buttons.setFocus(true)
m.menus[m.selectedItem].drawFocusFeedback = false
return true

View File

@ -8,7 +8,7 @@ sub loadItems()
sort_field = m.top.sortField
if m.top.sortAscending = true then
if m.top.sortAscending = true
sort_order = "Ascending"
else
sort_order = "Descending"
@ -26,17 +26,17 @@ sub loadItems()
}
filter = m.top.filter
if filter = "All" or filter = "all" then
if filter = "All" or filter = "all"
' do nothing
else if filter = "Favorites" then
else if filter = "Favorites"
params.append({ Filters: "IsFavorite"})
end if
if m.top.ItemType <> "" then
if m.top.ItemType <> ""
params.append({ IncludeItemTypes: m.top.ItemType})
end if
if m.top.ItemType = "LiveTV" then
if m.top.ItemType = "LiveTV"
url = "LiveTv/Channels"
else
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
@ -44,30 +44,30 @@ sub loadItems()
resp = APIRequest(url, params)
data = getJson(resp)
if data.TotalRecordCount <> invalid then
if data.TotalRecordCount <> invalid
m.top.totalRecordCount = data.TotalRecordCount
end if
for each item in data.Items
tmp = invalid
if item.Type = "Movie" then
if item.Type = "Movie"
tmp = CreateObject("roSGNode", "MovieData")
else if item.Type = "Series" then
else if item.Type = "Series"
tmp = CreateObject("roSGNode", "SeriesData")
else if item.Type = "BoxSet" then
else if item.Type = "BoxSet"
tmp = CreateObject("roSGNode", "CollectionData")
else if item.Type = "TvChannel" then
else if item.Type = "TvChannel"
tmp = CreateObject("roSGNode", "ChannelData")
else if item.Type = "Folder" or item.Type = "ChannelFolderItem" or item.Type = "CollectionFolder" then
else if item.Type = "Folder" or item.Type = "ChannelFolderItem" or item.Type = "CollectionFolder"
tmp = CreateObject("roSGNode", "FolderData")
else if item.Type = "Video" then
else if item.Type = "Video"
tmp = CreateObject("roSGNode", "VideoData")
else
print "[LoadItems] Unknown Type: " item.Type
end if
if tmp <> invalid then
if tmp <> invalid
tmp.json = item
results.push(tmp)

View File

@ -42,7 +42,7 @@ sub redraw()
fontHeight = m.top.fontHeight
fontWidth = m.top.fontWidth
if text.text.len() > 0 then
if text.text.len() > 0
textWidth = boxWidth - ( border * 2 )
text.width = textWidth
text.numLines = int(fontWidth / textWidth) + 1
@ -58,7 +58,7 @@ sub redraw()
options.itemSpacing = "[0,20]"
options.numRows = m.top.options.count()
if options.numRows > maxRows then
if options.numRows > maxRows
options.numRows = maxRows
options.wrapDividerHeight = 0
options.vertFocusAnimationStyle= "fixedFocusWrap"

View File

@ -29,9 +29,9 @@ sub init()
end sub
function updateTitle()
sub updateTitle()
leftSeperator = m.top.findNode("overlayLeftSeperator")
if m.top.title <> "" then
if m.top.title <> ""
leftSeperator.visible = "true"
else
leftSeperator.visible = "false"
@ -39,21 +39,21 @@ function updateTitle()
title = m.top.findNode("overlayTitle")
title.text = m.top.title
resetTime()
end function
end sub
function updateUser()
sub updateUser()
rightSeperator = m.top.findNode("overlayRightSeperator")
if m.top.currentUser <> "" then
if m.top.currentUser <> ""
rightSeperator.visible = "true"
else
rightSeperator.visible = "false"
end if
user = m.top.findNode("overlayCurrentUser")
user.text = m.top.currentUser
end function
end sub
function updateTime()
if (m.currentMinutes + 1) > 59 then
sub updateTime()
if (m.currentMinutes + 1) > 59
m.currentHours = m.currentHours + 1
m.currentMinutes = 0
else
@ -61,9 +61,9 @@ function updateTime()
end if
updateTimeDisplay()
end function
end sub
function resetTime()
sub resetTime()
m.currentTimeTimer.control = "stop"
currentTime = CreateObject("roDateTime")
@ -75,31 +75,31 @@ function resetTime()
m.currentMinutes = currentTime.GetMinutes()
updateTimeDisplay()
end function
end sub
function updateTimeDisplay()
sub updateTimeDisplay()
overlayHours = m.top.findNode("overlayHours")
overlayMinutes = m.top.findNode("overlayMinutes")
overlayMeridian = m.top.findNode("overlayMeridian")
if m.clockFormat = "24h" then
if m.clockFormat = "24h"
overlayMeridian.text = ""
if m.currentHours < 10 then
if m.currentHours < 10
overlayHours.text = "0" + StrI(m.currentHours).trim()
else
overlayHours.text = m.currentHours
end if
else
if m.currentHours < 12 then
if m.currentHours < 12
overlayMeridian.text = "AM"
if m.currentHours = 0 then
if m.currentHours = 0
overlayHours.text = "12"
else
overlayHours.text = m.currentHours
end if
else
overlayMeridian.text = "PM"
if m.currentHours = 12 then
if m.currentHours = 12
overlayHours.text = "12"
else
overlayHours.text = m.currentHours - 12
@ -107,21 +107,21 @@ function updateTimeDisplay()
end if
end if
if m.currentMinutes < 10 then
if m.currentMinutes < 10
overlayMinutes.text = "0" + StrI(m.currentMinutes).trim()
else
overlayMinutes.text = m.currentMinutes
end if
end function
end sub
function updateOptions()
sub updateOptions()
optionText = m.top.findNode("overlayOptionsText")
optionStar = m.top.findNode("overlayOptionsStar")
if m.top.showOptions = true then
if m.top.showOptions = true
optionText.visible = true
optionStar.visible = true
else
optionText.visible = false
optionStar.visible = false
end if
end function
end sub

View File

@ -11,13 +11,13 @@ end sub
sub onState(msg)
' When buffering, start timer to monitor buffering process
if m.top.state = "buffering" and m.bufferCheckTimer <> invalid then
if m.top.state = "buffering" and m.bufferCheckTimer <> invalid
' start timer
m.bufferCheckTimer = m.top.findNode("bufferCheckTimer")
m.bufferCheckTimer.control = "start"
m.bufferCheckTimer.ObserveField("fire", "bufferCheck")
else if m.top.state = "error" then
else if m.top.state = "error"
' If an error was encountered, Display dialog
dialog = createObject("roSGNode", "Dialog")
@ -45,10 +45,10 @@ sub bufferCheck(msg)
return
end if
if m.top.bufferingStatus <> invalid then
if m.top.bufferingStatus <> invalid
' Check that the buffering percentage is increasing
if m.top.bufferingStatus["percentage"] > m.bufferPercentage then
if m.top.bufferingStatus["percentage"] > m.bufferPercentage
m.bufferPercentage = m.top.bufferingStatus["percentage"]
else
' If buffering has stopped Display dialog
@ -80,7 +80,7 @@ end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if m.top.Subtitles.count() and key = "down" then
if m.top.Subtitles.count() and key = "down"
m.top.selectSubtitlePressed = true
return true
end if

View File

@ -59,25 +59,25 @@ sub updateSize()
end sub
function itemContentChanged() as void
m.poster = m.top.findNode("poster")
itemData = m.top.itemContent
m.title.text = itemData.title
if itemData.json.lookup("Type") = "Episode" and itemData.json.IndexNumber <> invalid
m.title.text = StrI(itemData.json.IndexNumber) + ". " + m.title.text
end if
m.staticTitle.text = m.title.text
sub itemContentChanged() as void
m.poster = m.top.findNode("poster")
itemData = m.top.itemContent
m.title.text = itemData.title
if itemData.json.lookup("Type") = "Episode" and itemData.json.IndexNumber <> invalid
m.title.text = StrI(itemData.json.IndexNumber) + ". " + m.title.text
end if
m.staticTitle.text = m.title.text
m.poster.uri = itemData.posterUrl
m.poster.uri = itemData.posterUrl
updateSize()
end function
updateSize()
end sub
'
' Enable title scrolling based on item Focus
sub focusChanged()
if m.top.itemHasFocus = true then
if m.top.itemHasFocus = true
m.title.repeatCount = -1
m.staticTitle.visible = false
m.title.visible = true

View File

@ -13,22 +13,20 @@ sub init()
end sub
function setData()
sub setData()
items = m.top.configItems
data = CreateObject("roSGNode", "ContentNode")
data.appendChildren(items)
m.top.content = data
end function
end sub
function onItemSelected()
print "HI"
sub onItemSelected()
i = m.top.itemSelected
itemField = m.top.content.getchild(i)
show_dialog(itemField)
end function
end sub
function onDialogButton()
d = m.dialog
@ -42,6 +40,7 @@ function onDialogButton()
dismiss_dialog()
return true
end if
return false
end function

View File

@ -9,7 +9,7 @@ function onKeyEvent(key as String, press as Boolean) as Boolean
list = m.top.findNode("configOptions")
button = m.top.findNode("submit")
if key = "back" then
if key = "back"
m.top.backPressed = true
else if key = "down" and button.focusedChild = invalid
limit = list.content.getChildren(-1, 0).count() - 1

View File

@ -11,7 +11,7 @@ end sub
sub setPoster()
if m.top.image <> invalid
m.top.posterURL = m.top.image.url
else if m.top.json.ImageTags <> invalid and m.top.json.ImageTags.Primary <> invalid then
else if m.top.json.ImageTags <> invalid and m.top.json.ImageTags.Primary <> invalid
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
end if

View File

@ -17,16 +17,16 @@ sub setPoster()
m.top.posterURL = m.top.image.url
else
if m.top.json.ImageTags.Primary <> invalid then
if m.top.json.ImageTags.Primary <> invalid
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag" : m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
else if m.top.json.BackdropImageTags <> invalid then
else if m.top.json.BackdropImageTags <> invalid
imgParams = { "maxHeight": 440, "Tag" : m.top.json.BackdropImageTags[0] }
m.top.posterURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
' Add Backdrop Image
if m.top.json.BackdropImageTags <> invalid then
if m.top.json.BackdropImageTags <> invalid
imgParams = { "maxHeight": 720, "maxWidth": 1280, "Tag" : m.top.json.BackdropImageTags[0] }
m.top.backdropURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if

View File

@ -17,7 +17,7 @@ end sub
sub setPoster()
if m.top.image <> invalid
m.top.posterURL = m.top.image.url
else if m.top.json.ImageTags.Primary <> invalid then
else if m.top.json.ImageTags.Primary <> invalid
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
end if

View File

@ -7,7 +7,7 @@ sub setData()
m.top.name = datum.name
m.top.type = datum.type
if datum.CollectionType = invalid then
if datum.CollectionType = invalid
m.top.CollectionType = datum.type
else
m.top.CollectionType = datum.CollectionType
@ -15,29 +15,29 @@ sub setData()
' Set appropriate Images for Wide and Tall based on type
if datum.type = "CollectionFolder" OR datum.type = "UserView" then
if datum.type = "CollectionFolder" OR datum.type = "UserView"
params = { "Tag" : datum.ImageTags.Primary, "maxHeight" : 261, "maxWidth" : 464 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
' Add Icon URLs for display if there is no Poster
if datum.CollectionType = "livetv" then
if datum.CollectionType = "livetv"
m.top.iconUrl = "pkg:/images/media_type_icons/live_tv_white.png"
else if datum.CollectionType = "folders" then
else if datum.CollectionType = "folders"
m.top.iconUrl = "pkg:/images/media_type_icons/folder_white.png"
end if
else if datum.type = "Episode" then
else if datum.type = "Episode"
imgParams = { "AddPlayedIndicator": datum.UserData.Played }
if datum.UserData.PlayedPercentage <> invalid then
if datum.UserData.PlayedPercentage <> invalid
imgParams.Append({ "PercentPlayed": datum.UserData.PlayedPercentage })
end if
imgParams.Append({ "maxHeight": 261 })
imgParams.Append({ "maxWidth": 464 })
if datum.ImageTags.Primary <> invalid then
if datum.ImageTags.Primary <> invalid
param = { "Tag" : datum.ImageTags.Primary }
imgParams.Append(param)
end if
@ -45,51 +45,51 @@ sub setData()
m.top.thumbnailURL = ImageURL(datum.id, "Primary", imgParams)
' Add Wide Poster (Series Backdrop)
if datum.ParentThumbImageTag <> invalid then
if datum.ParentThumbImageTag <> invalid
imgParams["Tag"] = datum.ParentThumbImageTag
m.top.widePosterUrl = ImageURL(datum.ParentThumbItemId, "Thumb", imgParams)
else if datum.ParentBackdropImageTags <> invalid then
else if datum.ParentBackdropImageTags <> invalid
imgParams["Tag"] = datum.ParentBackdropImageTags[0]
m.top.widePosterUrl = ImageURL(datum.ParentBackdropItemId, "Backdrop", imgParams)
else if datum.ImageTags.Primary <> invalid then
else if datum.ImageTags.Primary <> invalid
imgParams["Tag"] = datum.SeriesPrimaryImageTag
m.top.widePosterUrl = ImageURL(datum.id, "Primary", imgParams)
end if
else if datum.type = "Series" then
else if datum.type = "Series"
imgParams = { "maxHeight": 261 }
imgParams.Append({ "maxWidth": 464 })
if datum.UserData.UnplayedItemCount > 0 then
if datum.UserData.UnplayedItemCount > 0
imgParams["UnplayedCount"] = datum.UserData.UnplayedItemCount
end if
if datum.ImageTags.Primary <> invalid then
if datum.ImageTags.Primary <> invalid
imgParams["Tag"] = datum.ImageTags.Primary
end if
m.top.posterURL = ImageURL(datum.id, "Primary", imgParams)
' Add Wide Poster (Series Backdrop)
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid then
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid
imgParams["Tag"] = datum.imageTags.Thumb
m.top.widePosterUrl = ImageURL(datum.Id, "Thumb", imgParams)
else if datum.BackdropImageTags <> invalid then
else if datum.BackdropImageTags <> invalid
imgParams["Tag"] = datum.BackdropImageTags[0]
m.top.widePosterUrl = ImageURL(datum.Id, "Backdrop", imgParams)
end if
else if datum.type = "Movie" then
else if datum.type = "Movie"
imgParams = { AddPlayedIndicator: datum.UserData.Played }
if datum.UserData.PlayedPercentage <> invalid then
if datum.UserData.PlayedPercentage <> invalid
imgParams.Append({ "PercentPlayed": datum.UserData.PlayedPercentage })
end if
imgParams.Append({ "maxHeight": 261 })
imgParams.Append({ "maxWidth": 175 })
if datum.ImageTags.Primary <> invalid then
if datum.ImageTags.Primary <> invalid
param = { "Tag" : datum.ImageTags.Primary }
imgParams.Append(param)
end if
@ -99,25 +99,25 @@ sub setData()
' For wide image, use backdrop
imgParams["maxWidth"] = 464
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid then
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid
imgParams["Tag"] = datum.imageTags.Thumb
m.top.thumbnailUrl = ImageURL(datum.Id, "Thumb", imgParams)
else if datum.BackdropImageTags[0] <> invalid then
else if datum.BackdropImageTags[0] <> invalid
imgParams["Tag"] = datum.BackdropImageTags[0]
m.top.thumbnailUrl = ImageURL(datum.id, "Backdrop", imgParams)
end if
else if datum.type = "Video" then
else if datum.type = "Video"
imgParams = { AddPlayedIndicator: datum.UserData.Played }
if datum.UserData.PlayedPercentage <> invalid then
if datum.UserData.PlayedPercentage <> invalid
imgParams.Append({ "PercentPlayed": datum.UserData.PlayedPercentage })
end if
imgParams.Append({ "maxHeight": 261 })
imgParams.Append({ "maxWidth": 175 })
if datum.ImageTags.Primary <> invalid then
if datum.ImageTags.Primary <> invalid
param = { "Tag" : datum.ImageTags.Primary }
imgParams.Append(param)
end if
@ -127,20 +127,20 @@ sub setData()
' For wide image, use backdrop
imgParams["maxWidth"] = 464
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid then
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid
imgParams["Tag"] = datum.imageTags.Thumb
m.top.thumbnailUrl = ImageURL(datum.Id, "Thumb", imgParams)
else if datum.BackdropImageTags[0] <> invalid then
else if datum.BackdropImageTags[0] <> invalid
imgParams["Tag"] = datum.BackdropImageTags[0]
m.top.thumbnailUrl = ImageURL(datum.id, "Backdrop", imgParams)
end if
else if datum.type = "MusicAlbum" then
else if datum.type = "MusicAlbum"
params = { "Tag" : datum.ImageTags.Primary, "maxHeight" : 261, "maxWidth" : 261 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
m.top.posterUrl = m.top.thumbnailURL
else if datum.type = "TvChannel" OR datum.type = "Channel" then
else if datum.type = "TvChannel" OR datum.type = "Channel"
params = { "Tag" : datum.ImageTags.Primary, "maxHeight" : 261, "maxWidth" : 464 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL

View File

@ -8,13 +8,13 @@ sub setFields()
m.top.watched = json.UserData.played
m.top.Type = "Movie"
if json.ProductionYear <> invalid then
if json.ProductionYear <> invalid
m.top.SubTitle = json.ProductionYear
end if
if json.OfficialRating <> invalid and json.OfficialRating <> "" then
if json.OfficialRating <> invalid and json.OfficialRating <> ""
m.top.Rating = json.OfficialRating
if m.top.SubTitle <> "" then
if m.top.SubTitle <> ""
m.top.SubTitle = m.top.SubTitle + " - " + m.top.Rating
else
m.top.SubTitle = m.top.Rating
@ -30,19 +30,19 @@ sub setPoster()
m.top.posterURL = m.top.image.url
else
if m.top.json.ImageTags.Primary <> invalid then
if m.top.json.ImageTags.Primary <> invalid
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag" : m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
else if m.top.json.BackdropImageTags[0] <> invalid then
else if m.top.json.BackdropImageTags[0] <> invalid
imgParams = { "maxHeight": 440, "Tag" : m.top.json.BackdropImageTags[0] }
m.top.posterURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
else if m.top.json.ParentThumbImageTag <> invalid and m.top.json.ParentThumbItemId <> invalid then
else if m.top.json.ParentThumbImageTag <> invalid and m.top.json.ParentThumbItemId <> invalid
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag" : m.top.json.ParentThumbImageTag }
m.top.posterURL = ImageURL(m.top.json.ParentThumbItemId, "Thumb", imgParams)
end if
' Add Backdrop Image
if m.top.json.BackdropImageTags[0] <> invalid then
if m.top.json.BackdropImageTags[0] <> invalid
imgParams = { "maxHeight": 720, "maxWidth": 1280, "Tag" : m.top.json.BackdropImageTags[0] }
m.top.backdropURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if

View File

@ -18,7 +18,7 @@ sub setFields()
m.top.endDate = json.endDate
m.top.channelId = json.channelId
if json.IsSeries <> invalid and json.IsSeries = true then
if json.IsSeries <> invalid and json.IsSeries = true
if json.IndexNumber <> invalid
m.top.episodeNumber = json.IndexNumber
end if
@ -35,7 +35,7 @@ sub setFields()
if m.top.image <> invalid
m.top.posterURL = m.top.image.url
else
if m.top.json.ImageTags <> invalid and m.top.json.ImageTags.Thumb <> invalid then
if m.top.json.ImageTags <> invalid and m.top.json.ImageTags.Thumb <> invalid
imgParams = { "maxHeight": 500, "maxWidth": 500, "Tag" : m.top.json.ImageTags.Thumb }
m.top.posterURL = ImageURL(m.top.json.id, "Thumb", imgParams)
end if

View File

@ -9,13 +9,13 @@ sub setFields()
m.top.Type = "Series"
m.top.overview = json.overview
if json.ProductionYear <> invalid then
if json.ProductionYear <> invalid
m.top.SubTitle = json.ProductionYear
end if
if json.OfficialRating <> invalid and json.OfficialRating <> "" then
if json.OfficialRating <> invalid and json.OfficialRating <> ""
m.top.Rating = json.OfficialRating
if m.top.SubTitle <> "" then
if m.top.SubTitle <> ""
m.top.SubTitle = m.top.SubTitle + " - " + m.top.Rating
else
m.top.SubTitle = m.top.Rating
@ -30,17 +30,17 @@ sub setPoster()
m.top.posterURL = m.top.image.url
else
if m.top.json.ImageTags.Primary <> invalid then
if m.top.json.ImageTags.Primary <> invalid
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag" : m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
else if m.top.json.BackdropImageTags <> invalid then
else if m.top.json.BackdropImageTags <> invalid
imgParams = { "maxHeight": 440, "Tag" : m.top.json.BackdropImageTags[0] }
m.top.posterURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
' Add Backdrop Image
if m.top.json.BackdropImageTags <> invalid then
if m.top.json.BackdropImageTags <> invalid
imgParams = { "maxHeight": 720, "maxWidth": 1280, "Tag" : m.top.json.BackdropImageTags[0] }
m.top.backdropURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if

View File

@ -3,21 +3,21 @@ sub setDataFromJSON()
loadFromJSON(json)
end sub
function loadFromJSON(json)
sub loadFromJSON(json)
m.top.id = json.User.id
m.top.username = json.User.name
m.top.token = json.AccessToken
end function
end sub
function loadFromRegistry(id as string)
sub loadFromRegistry(id as string)
m.top.id = id
m.top.username = get_user_setting("username")
m.top.token = get_user_setting("token")
end function
end sub
function saveToRegistry()
sub saveToRegistry()
set_user_setting("username", m.top.username)
set_user_setting("token", m.top.token)
@ -34,9 +34,9 @@ function saveToRegistry()
})
set_setting("available_users", formatJson(users))
end if
end function
end sub
function removeFromRegistry()
sub removeFromRegistry()
new_users = []
users = parseJson(get_setting("available_users", "[]"))
for each user in users
@ -44,7 +44,7 @@ function removeFromRegistry()
end for
set_setting("available_users", formatJson(new_users))
end function
end sub
function getPreference(key as string, default as string)
return get_user_setting("pref-" + key, default)
@ -54,10 +54,10 @@ function setPreference(key as string, value as string)
return set_user_setting("pref-" + key, value)
end function
function setActive()
sub setActive()
set_setting("active_user", m.top.id)
end function
end sub
function setServer(hostname as string)
sub setServer(hostname as string)
m.top.server = hostname
end function
end sub

View File

@ -14,7 +14,7 @@ end sub
sub setPoster()
if m.top.image <> invalid
m.top.posterURL = m.top.image.url
else if m.top.json.ImageTags.Primary <> invalid then
else if m.top.json.ImageTags.Primary <> invalid
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
end if

View File

@ -3,10 +3,10 @@ sub init()
m.top.optionsAvailable = true
end sub
function refresh()
sub refresh()
m.top.findNode("homeRows").callFunc("updateHomeRows")
end function
end sub
function loadLibraries()
sub loadLibraries()
m.top.findNode("homeRows").callFunc("loadLibraries")
end function
end sub

View File

@ -33,13 +33,13 @@ sub itemContentChanged()
end if
' Format the Data based on the type of Home Data
if itemData.type = "CollectionFolder" OR itemData.type = "UserView" OR itemData.type = "Channel" then
if itemData.type = "CollectionFolder" OR itemData.type = "UserView" OR itemData.type = "Channel"
m.itemText.text = itemData.name
m.itemPoster.uri = itemData.widePosterURL
return
end if
if itemData.type = "UserView" then
if itemData.type = "UserView"
m.itemPoster.width = "96"
m.itemPoster.height = "96"
m.itemPoster.translation = "[192, 88]"
@ -57,10 +57,10 @@ sub itemContentChanged()
m.itemTextExtra.font.size = 22
if itemData.type = "Episode" then
if itemData.type = "Episode"
m.itemText.text = itemData.json.SeriesName
if itemData.usePoster = true then
if itemData.usePoster = true
m.itemPoster.uri = itemData.widePosterURL
else
m.itemPoster.uri = itemData.thumbnailURL
@ -68,13 +68,13 @@ sub itemContentChanged()
' Set Series and Episode Number for Extra Text
extraPrefix = ""
if itemData.json.ParentIndexNumber <> invalid then
if itemData.json.ParentIndexNumber <> invalid
extraPrefix = "S" + StrI(itemData.json.ParentIndexNumber).trim()
end if
if itemData.json.IndexNumber <> invalid then
if itemData.json.IndexNumber <> invalid
extraPrefix = extraPrefix + "E" + StrI(itemData.json.IndexNumber).trim()
end if
if extraPrefix.len() > 0 then
if extraPrefix.len() > 0
extraPrefix = extraPrefix + " - "
end if
@ -82,7 +82,7 @@ sub itemContentChanged()
return
end if
if itemData.type = "Movie" then
if itemData.type = "Movie"
m.itemText.text = itemData.name
' Use best image, but fallback to secondary if it's empty
@ -94,11 +94,11 @@ sub itemContentChanged()
' Set Release Year and Age Rating for Extra Text
textExtra = ""
if itemData.json.ProductionYear <> invalid then
if itemData.json.ProductionYear <> invalid
textExtra = StrI(itemData.json.ProductionYear).trim()
end if
if itemData.json.OfficialRating <> invalid then
if textExtra <> "" then
if itemData.json.OfficialRating <> invalid
if textExtra <> ""
textExtra = textExtra + " - " + itemData.json.OfficialRating
else
textExtra = itemData.json.OfficialRating
@ -109,7 +109,7 @@ sub itemContentChanged()
return
end if
if itemData.type = "Video" then
if itemData.type = "Video"
m.itemText.text = itemData.name
if itemData.imageWidth = 180
@ -119,12 +119,12 @@ sub itemContentChanged()
end if
return
end if
if itemData.type = "Series" then
if itemData.type = "Series"
m.itemText.text = itemData.name
if itemData.usePoster = true then
if itemData.imageWidth = 180 then
if itemData.usePoster = true
if itemData.imageWidth = 180
m.itemPoster.uri = itemData.posterURL
else
m.itemPoster.uri = itemData.widePosterURL
@ -134,12 +134,12 @@ sub itemContentChanged()
end if
textExtra = ""
if itemData.json.ProductionYear <> invalid then
if itemData.json.ProductionYear <> invalid
textExtra = StrI(itemData.json.ProductionYear).trim()
end if
' Set Years Run for Extra Text
if itemData.json.Status = "Continuing" then
if itemData.json.Status = "Continuing"
textExtra = textExtra + " - Present"
else if itemData.json.Status = "Ended" and itemData.json.EndDate <> invalid
textExtra = textExtra + " - " + LEFT(itemData.json.EndDate, 4)
@ -149,7 +149,7 @@ sub itemContentChanged()
return
end if
if itemData.type = "MusicAlbum" then
if itemData.type = "MusicAlbum"
m.itemText.text = itemData.name
m.itemTextExtra.text = itemData.json.AlbumArtist
m.itemPoster.uri = itemData.posterURL
@ -164,7 +164,7 @@ end sub
' Enable title scrolling based on item Focus
sub focusChanged()
if m.top.itemHasFocus = true then
if m.top.itemHasFocus = true
m.itemText.repeatCount = -1
else
m.itemText.repeatCount = 0
@ -174,7 +174,7 @@ end sub
'Hide backdrop and icon when poster loaded
sub onPosterLoadStatusChanged()
if m.itemPoster.loadStatus = "ready" and m.itemPoster.uri <> "" then
if m.itemPoster.loadStatus = "ready" and m.itemPoster.uri <> ""
m.backdrop.visible = false
m.itemIcon.visible = false
else

View File

@ -26,15 +26,12 @@ sub init()
m.LoadNextUpTask.itemsToLoad = "nextUp"
end sub
function loadLibraries()
sub loadLibraries()
m.LoadLibrariesTask.control = "RUN"
end function
end sub
sub updateSize()
sideborder = 100
m.top.translation = [111, 180]
itemWidth = 480
itemHeight = 330
'Set width of Rows to cut off at edge of Safe Zone
@ -68,7 +65,7 @@ sub onLibrariesLoaded()
[464, 331] ' Next Up
]
' validate library data
if (m.libraryData <> invalid and m.libraryData.count() > 0) then
if m.libraryData <> invalid and m.libraryData.count() > 0
userConfig = m.top.userConfig
' populate My Media row
filteredMedia = filterNodeArray(m.libraryData, "id", userConfig.MyMediaExcludes)
@ -78,7 +75,7 @@ sub onLibrariesLoaded()
' create a "Latest In" row for each library
filteredLatest = filterNodeArray(m.libraryData, "id", userConfig.LatestItemsExcludes)
for each lib in filteredLatest
if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv" then
if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv"
latestInRow = content.CreateChild("HomeRow")
latestInRow.title = tr("Latest in") + " " + lib.name + " >"
sizeArray.Push([464, 331])
@ -94,23 +91,23 @@ sub onLibrariesLoaded()
m.LoadContinueTask.control = "RUN"
end sub
function updateHomeRows()
sub updateHomeRows()
m.LoadContinueTask.observeField("content", "updateContinueItems")
m.LoadContinueTask.control = "RUN"
end function
end sub
function updateContinueItems()
sub updateContinueItems()
itemData = m.LoadContinueTask.content
m.LoadContinueTask.unobserveField("content")
m.LoadContinueTask.content = []
if itemData = invalid then return false
if itemData = invalid then return
homeRows = m.top.content
continueRowIndex = getRowIndex("Continue Watching")
if itemData.count() < 1 then
if continueRowIndex <> invalid then
if itemData.count() < 1
if continueRowIndex <> invalid
' remove the row
deleteFromSizeArray(continueRowIndex)
homeRows.removeChildIndex(continueRowIndex)
@ -126,7 +123,7 @@ function updateContinueItems()
row.appendChild(item)
end for
if continueRowIndex = invalid then
if continueRowIndex = invalid
' insert new row under "My Media"
updateSizeArray(itemSize, 1)
homeRows.insertChild(row, 1)
@ -138,20 +135,20 @@ function updateContinueItems()
m.LoadNextUpTask.observeField("content", "updateNextUpItems")
m.LoadNextUpTask.control = "RUN"
end function
end sub
function updateNextUpItems()
sub updateNextUpItems()
itemData = m.LoadNextUpTask.content
m.LoadNextUpTask.unobserveField("content")
m.LoadNextUpTask.content = []
if itemData = invalid then return false
if itemData = invalid then return
homeRows = m.top.content
nextUpRowIndex = getRowIndex("Next Up >")
if itemData.count() < 1 then
if nextUpRowIndex <> invalid then
if itemData.count() < 1
if nextUpRowIndex <> invalid
' remove the row
deleteFromSizeArray(nextUpRowIndex)
homeRows.removeChildIndex(nextUpRowIndex)
@ -167,10 +164,10 @@ function updateNextUpItems()
row.appendChild(item)
end for
if nextUpRowIndex = invalid then
if nextUpRowIndex = invalid
' insert new row under "Continue Watching"
continueRowIndex = getRowIndex("Continue Watching")
if continueRowIndex <> invalid then
if continueRowIndex <> invalid
updateSizeArray(itemSize, continueRowIndex + 1)
homeRows.insertChild(row, continueRowIndex + 1)
else
@ -185,7 +182,7 @@ function updateNextUpItems()
end if
' consider home screen loaded when above rows are loaded
if m.global.app_loaded = false then
if m.global.app_loaded = false
m.top.signalBeacon("AppLaunchComplete") ' Roku Performance monitoring
m.global.app_loaded = true
end if
@ -195,7 +192,7 @@ function updateNextUpItems()
userConfig = m.top.userConfig
filteredLatest = filterNodeArray(m.libraryData, "id", userConfig.LatestItemsExcludes)
for each lib in filteredLatest
if lib.collectionType <> "livetv" and lib.collectionType <> "boxsets" then
if lib.collectionType <> "livetv" and lib.collectionType <> "boxsets"
loadLatest = createObject("roSGNode", "LoadItemsTask")
loadLatest.itemsToLoad = "latest"
loadLatest.itemId = lib.id
@ -208,24 +205,23 @@ function updateNextUpItems()
loadLatest.control = "RUN"
end if
end for
end function
end sub
function updateLatestItems(msg)
sub updateLatestItems(msg)
itemData = msg.GetData()
data = msg.getField()
node = msg.getRoSGNode()
node.unobserveField("content")
node.content = []
if itemData = invalid then return false
if itemData = invalid then return
homeRows = m.top.content
rowIndex = getRowIndex(tr("Latest in") + " " + node.metadata.title + " >")
if itemData.count() < 1 then
if itemData.count() < 1
' remove row
if rowIndex <> invalid then
if rowIndex <> invalid
deleteFromSizeArray(rowIndex)
homeRows.removeChildIndex(rowIndex)
end if
@ -235,10 +231,10 @@ function updateLatestItems(msg)
row.title = tr("Latest in") + " " + node.metadata.title + " >"
row.usePoster = true
' Handle specific types with different item widths
if node.metadata.contentType = "movies" then
if node.metadata.contentType = "movies"
row.imageWidth = 180
itemSize = [188, 331]
else if node.metadata.contentType = "music" then
else if node.metadata.contentType = "music"
row.imageWidth = 261
itemSize = [261, 331]
else
@ -252,7 +248,7 @@ function updateLatestItems(msg)
row.appendChild(item)
end for
if rowIndex = invalid then
if rowIndex = invalid
' append new row
updateSizeArray(itemSize)
homeRows.appendChild(row)
@ -262,14 +258,14 @@ function updateLatestItems(msg)
homeRows.replaceChild(row, rowIndex)
end if
end if
end function
end sub
function getRowIndex(rowTitle as string)
rowIndex = invalid
for i = 1 to m.top.content.getChildCount() - 1
' skip row 0 since it's always "My Media"
tmpRow = m.top.content.getChild(i)
if tmpRow.title = rowTitle then
if tmpRow.title = rowTitle
rowIndex = i
exit for
end if
@ -280,22 +276,22 @@ end function
sub updateSizeArray(rowItemSize, rowIndex = invalid, action = "insert")
sizeArray = m.top.rowItemSize
' append by default
if rowIndex = invalid then
if rowIndex = invalid
rowIndex = sizeArray.count()
end if
newSizeArray = []
for i = 0 to sizeArray.count()
if rowIndex = i then
if action = "replace" then
if rowIndex = i
if action = "replace"
newSizeArray.Push(rowItemSize)
else if action = "insert" then
else if action = "insert"
newSizeArray.Push(rowItemSize)
if sizeArray[i] <> invalid then
if sizeArray[i] <> invalid
newSizeArray.Push(sizeArray[i])
end if
end if
else if sizeArray[i] <> invalid then
else if sizeArray[i] <> invalid
newSizeArray.Push(sizeArray[i])
end if
end for
@ -306,16 +302,16 @@ sub deleteFromSizeArray(rowIndex)
updateSizeArray([0, 0], rowIndex, "delete")
end sub
function itemSelected()
sub itemSelected()
m.top.selectedItem = m.top.content.getChild(m.top.rowItemSelected[0]).getChild(m.top.rowItemSelected[1])
end function
end sub
function onKeyEvent(key as string, press as boolean) as boolean
handled = false
if press then
if key = "play" then
if press
if key = "play"
itemToPlay = m.top.content.getChild(m.top.rowItemFocused[0]).getChild(m.top.rowItemFocused[1])
if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode") then
if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
m.top.quickPlayNode = itemToPlay
end if
handled = true
@ -331,11 +327,11 @@ function filterNodeArray(nodeArray as object, nodeKey as string, excludeArray as
for each node in nodeArray
excludeThisNode = false
for each exclude in excludeArray
if node[nodeKey] = exclude then
if node[nodeKey] = exclude
excludeThisNode = true
end if
end for
if excludeThisNode = false then
if excludeThisNode = false
newNodeArray.Push(node)
end if
end for

View File

@ -17,7 +17,7 @@ sub init()
resp = APIRequest(url, params)
data = getJson(resp)
if data.TotalRecordCount = invalid then
if data.TotalRecordCount = invalid
m.top.channels = results
return
end if

View File

@ -17,15 +17,15 @@ sub loadProgramDetails()
resp = APIRequest(url, params)
data = getJson(resp)
if data = invalid then
if data = invalid
m.top.programDetails = {}
return
end if
program = createObject("roSGNode", "ScheduleProgramData")
program.json = data
program.channelIndex = ChannelIndex
program.programIndex = ProgramIndex
program.channelIndex = channelIndex
program.programIndex = programIndex
program.fullyLoaded = true
m.top.programDetails = program

View File

@ -22,7 +22,7 @@ sub init()
resp = APIRequest(url)
data = postJson(resp, FormatJson(params))
if data = invalid then
if data = invalid
m.top.schedule = results
return
end if

View File

@ -60,7 +60,7 @@ sub channelUpdated()
else
m.top.findNode("noInfoChannelName").text = m.top.channel.Title
m.channelName.text= m.top.channel.Title
if m.top.programDetails = invalid then
if m.top.programDetails = invalid
m.image.uri = m.top.channel.posterURL
end if
end if
@ -73,7 +73,7 @@ sub programUpdated()
prog = m.top.programDetails
' If no program selected, hide details view
if prog = invalid then
if prog = invalid
channelUpdated()
m.detailsView.visible = "false"
m.noInfoView.visible = "true"
@ -85,20 +85,20 @@ sub programUpdated()
m.episodeDetailsGroup.removeChildrenIndex(m.episodeDetailsGroup.getChildCount(), 0)
if prog.isLive then
if prog.isLive
m.episodeDetailsGroup.appendChild(m.isLiveGroup)
else if prog.isRepeat then
else if prog.isRepeat
m.episodeDetailsGroup.appendChild(m.isRepeatGroup)
end if
' Episode Number
if prog.seasonNumber > 0 and prog.episodeNumber > 0 then
if prog.seasonNumber > 0 and prog.episodeNumber > 0
m.episodeNumber.text = "S" + StrI(prog.seasonNumber).trim() + ":E" + StrI(prog.episodeNumber).trim()
if prog.episodeTitle <> "" then m.episodeNumber.text = m.episodeNumber.text + " -" ' Add a Dash if showing Episode Number and Title
m.episodeDetailsGroup.appendChild(m.episodeNumber)
end if
if prog.episodeTitle <> invalid and prog.episodeTitle <> "" then
if prog.episodeTitle <> invalid and prog.episodeTitle <> ""
m.episodeTitle.text = prog.episodeTitle
m.episodeTitle.visible = true
m.episodeDetailsGroup.appendChild(m.episodeTitle)
@ -120,20 +120,20 @@ sub programUpdated()
localStartDate.FromISO8601String(prog.StartDate)
localStartDate.ToLocalTime()
if startDate.AsSeconds() < now.AsSeconds() and endDate.AsSeconds() > now.AsSeconds() then
if day = "today" then
if startDate.AsSeconds() < now.AsSeconds() and endDate.AsSeconds() > now.AsSeconds()
if day = "today"
m.broadcastDetails.text = tr("Started at") + " " + formatTime(localStartDate)
else
m.broadcastDetails.text = tr("Started") + " " + tr(day) + ", " + formatTime(localStartDate)
end if
else if startDate.AsSeconds() > now.AsSeconds()
if day = "today" then
if day = "today"
m.broadcastDetails.text = tr("Starts at") + " " + formatTime(localStartDate)
else
m.broadcastDetails.text = tr("Starts") + " " + tr(day) + ", " + formatTime(localStartDate)
end if
else
if day = "today" then
if day = "today"
m.broadcastDetails.text = tr("Ended at") + " " + formatTime(localStartDate)
else
m.broadcastDetails.text = tr("Ended") + " " + tr(day) + ", " + formatTime(localStartDate)
@ -157,7 +157,7 @@ function getRelativeDayName(date) as string
now = createObject("roDateTime")
' Check for Today
if now.AsDateString("short-date-dashes") = date.AsDateString("short-date-dashes") then
if now.AsDateString("short-date-dashes") = date.AsDateString("short-date-dashes")
return "today"
end if
@ -165,11 +165,11 @@ function getRelativeDayName(date) as string
todayMidnight = now.AsSeconds() - (now.AsSeconds() MOD 86400)
dateMidnight = date.AsSeconds() - (date.AsSeconds() MOD 86400)
if todayMidnight - dateMidnight = 86400 then
if todayMidnight - dateMidnight = 86400
return "yesterday"
end if
if dateMidnight - todayMidnight = 86400 then
if dateMidnight - todayMidnight = 86400
return "tomorrow"
end if
@ -184,12 +184,12 @@ function getDurationStringFromSeconds(seconds) as string
hours = 0
minutes = seconds / 60.0
if minutes > 60 then
if minutes > 60
hours = (minutes - (minutes MOD 60)) / 60
minutes = minutes MOD 60
end if
if hours > 0 then
if hours > 0
return "%1h %2m".Replace("%1", StrI(hours).trim()).Replace("%2", StrI(minutes).trim())
else
return "%1m".Replace("%1", StrI(minutes).trim())
@ -200,7 +200,7 @@ end function
'
' Show view channel button when item has Focus
sub focusChanged()
if m.top.hasFocus = true then
if m.top.hasFocus = true
m.overview.maxLines = m.maxDetailLines
m.focusAnimationOpacity.keyValue = [0, 1]
else
@ -213,7 +213,7 @@ sub focusChanged()
end sub
sub onAnimationComplete()
if m.focusAnimation.state = "stopped" and m.top.hasFocus = false then
if m.focusAnimation.state = "stopped" and m.top.hasFocus = false
m.overview.maxLines = m.maxPreviewLines
end if
end sub
@ -221,12 +221,12 @@ end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if key = "OK" then
if key = "OK"
m.top.watchSelectedChannel = true
return true
end if
if key = "left" or key = "right" or key = "up" or key = "down" then
if key = "left" or key = "right" or key = "up" or key = "down"
return true
end if

View File

@ -66,10 +66,10 @@ sub onScheduleLoaded()
channel = m.scheduleGrid.content.GetChild(m.channelIndex[item.ChannelId])
if channel.PosterUrl <> "" then
if channel.PosterUrl <> ""
item.channelLogoUri = channel.PosterUrl
end if
if channel.Title <> "" then
if channel.Title <> ""
item.channelName = channel.Title
end if
@ -88,14 +88,14 @@ sub onProgramFocused()
m.detailsPane.channel = channel
' Exit if Channels not yet loaded
if channel.getChildCount() = 0 then
if channel.getChildCount() = 0
m.detailsPane.programDetails = invalid
return
end if
prog = channel.GetChild(m.scheduleGrid.programFocusedDetails.focusIndex)
if prog <> invalid and prog.fullyLoaded = false then
if prog <> invalid and prog.fullyLoaded = false
m.LoadProgramDetailsTask.programId = prog.Id
m.LoadProgramDetailsTask.channelIndex = m.scheduleGrid.programFocusedDetails.focusChannelIndex
m.LoadProgramDetailsTask.programIndex = m.scheduleGrid.programFocusedDetails.focusIndex
@ -111,7 +111,7 @@ sub onProgramDetailsLoaded()
channel = m.scheduleGrid.content.GetChild(m.LoadProgramDetailsTask.programDetails.channelIndex)
' If TV Show does not have its own image, use the channel logo
if m.LoadProgramDetailsTask.programDetails.PosterUrl = invalid or m.LoadProgramDetailsTask.programDetails.PosterUrl = "" then
if m.LoadProgramDetailsTask.programDetails.PosterUrl = invalid or m.LoadProgramDetailsTask.programDetails.PosterUrl = ""
m.LoadProgramDetailsTask.programDetails.PosterUrl = channel.PosterUrl
end if
@ -122,7 +122,7 @@ end sub
sub onProgramSelected()
' If there is no program data - view the channel
if m.detailsPane.programDetails = invalid then
if m.detailsPane.programDetails = invalid
m.top.watchChannel = m.scheduleGrid.content.GetChild(m.scheduleGrid.programFocusedDetails.focusChannelIndex)
return
end if
@ -138,7 +138,7 @@ sub focusProgramDetails(setFocused)
if h < 400 then h = 400
h = h + 160 + 80
if setFocused = true then
if setFocused = true
m.gridMoveAnimationPosition.keyValue = [ [0,600], [0, h] ]
m.detailsPane.setFocus(true)
m.detailsPane.hasFocus = true
@ -168,10 +168,10 @@ end sub
sub onGridScrolled()
' If we're within 12 hours of end of grid, load next 24hrs of data
if m.scheduleGrid.leftEdgeTargetTime + (12 * 60 * 60) > m.gridEndDate.AsSeconds() then
if m.scheduleGrid.leftEdgeTargetTime + (12 * 60 * 60) > m.gridEndDate.AsSeconds()
' Ensure the task is not already (still) running,
if m.LoadScheduleTask.state <> "run" then
if m.LoadScheduleTask.state <> "run"
m.LoadScheduleTask.startTime = m.gridEndDate.ToISOString()
m.gridEndDate.FromSeconds(m.gridEndDate.AsSeconds() + (24 * 60 * 60))
m.LoadScheduleTask.endTime = m.gridEndDate.ToISOString()
@ -183,7 +183,7 @@ end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if key = "back" and m.detailsPane.isInFocusChain() then
if key = "back" and m.detailsPane.isInFocusChain()
focusProgramDetails(false)
return true
end if

View File

@ -8,7 +8,7 @@ sub itemContentChanged()
profileImage = m.top.findNode("profileImage")
profileName = m.top.findNode("profileName")
if itemData.imageURL = "" then
if itemData.imageURL = ""
profileImage.uri = "pkg://images/baseline_person_white_48dp.png"
else
profileImage.uri = itemData.imageURL

View File

@ -8,12 +8,6 @@ sub init()
end sub
sub updateSize()
dimensions = m.top.getScene().currentDesignResolution
border = 200
'm.top.translation = [border, border + 115]
textHeight = 80
itemWidth = 300
itemHeight = 364
@ -32,7 +26,7 @@ end sub
function setData()
if m.top.itemContent = invalid then
if m.top.itemContent = invalid
data = CreateObject("roSGNode", "ContentNode")
return data
end if

View File

@ -14,7 +14,7 @@ sub redraw()
itemWidth = 300
itemSpacing = 40
if userCount < 5 then
if userCount < 5
leftBorder = (1920 - ((userCount * itemWidth) + ((userCount - 1) * itemSpacing))) / 2
end if
' break()
@ -24,15 +24,15 @@ end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if key = "back" then
if key = "back"
m.top.backPressed = true
else if key = "up" then
if m.top.focusedChild.isSubType("LabelList") then
else if key = "up"
if m.top.focusedChild.isSubType("LabelList")
m.top.findNode("UserRow").setFocus(true)
return true
end if
else if key = "down" then
if m.top.focusedChild.isSubType("UserRow") then
else if key = "down"
if m.top.focusedChild.isSubType("UserRow")
m.top.findNode("alternateOptions").setFocus(true)
return true
end if

View File

@ -1,30 +1,30 @@
function init()
sub init()
m.title = m.top.findNode("title")
m.description = m.top.findNode("description")
m.selectedIcon = m.top.findNode("selectedIcon")
end function
end sub
function itemContentChanged()
sub itemContentChanged()
m.title.text = m.top.itemContent.title
m.description.text = m.top.itemContent.description
if m.top.itemContent.description = "" then
if m.top.itemContent.description = ""
m.title.translation = [50, 20]
end if
if m.top.itemContent.selected then
if m.top.itemContent.selected
m.selectedIcon.uri = m.global.constants.icons.check_white
else
m.selectedIcon.uri = ""
end if
end function
end sub
'
'Scroll description if focused
sub focusChanged()
if m.top.itemHasFocus = true then
if m.top.itemHasFocus = true
m.description.repeatCount = -1
else
m.description.repeatCount = 0

View File

@ -21,7 +21,7 @@ sub itemContentChanged()
' Find first Audio Stream and set that as default
For i=0 To itemData.mediaStreams.Count() - 1
if itemData.mediaStreams[i].Type = "Audio" then
if itemData.mediaStreams[i].Type = "Audio"
m.top.selectedAudioStreamIndex = i
exit for
end if
@ -33,16 +33,16 @@ sub itemContentChanged()
setFieldText("officialRating", itemData.officialRating)
setFieldText("overview", itemData.overview)
if itemData.communityRating <> invalid then
if itemData.communityRating <> invalid
setFieldText("communityRating", itemData.communityRating)
else
' hide the star icon
m.top.findNode("communityRatingGroup").visible = false
end if
if itemData.CriticRating <> invalid then
if itemData.CriticRating <> invalid
setFieldText("criticRatingLabel" , itemData.criticRating)
if itemData.CriticRating > 60 then
if itemData.CriticRating > 60
tomato = "pkg:/images/fresh.png"
else
tomato = "pkg:/images/rotten.png"
@ -98,7 +98,7 @@ sub SetUpOptions(streams)
tracks = []
for i=0 To streams.Count() - 1
if streams[i].Type = "Audio" then
if streams[i].Type = "Audio"
tracks.push({"Title": streams[i].displayTitle, "Description" : streams[i].Title, "Selected" : m.top.selectedAudioStreamIndex = i, "StreamIndex" : i})
end if
end for
@ -115,11 +115,11 @@ sub setFieldText(field, value)
if node = invalid or value = invalid then return
' Handle non strings... Which _shouldn't_ happen, but hey
if type(value) = "roInt" or type(value) = "Integer" then
if type(value) = "roInt" or type(value) = "Integer"
value = str(value)
else if type(value) = "roFloat" or type(value) = "Float" then
else if type(value) = "roFloat" or type(value) = "Float"
value = str(value)
else if type(value) <> "roString" and type(value) <> "String" then
else if type(value) <> "roString" and type(value) <> "String"
value = ""
end if
@ -186,7 +186,7 @@ end function
'
'Check if options updated and any reloading required
sub optionsClosed()
if m.options.audioSteamIndex <> m.top.selectedAudioStreamIndex then
if m.options.audioSteamIndex <> m.top.selectedAudioStreamIndex
m.top.selectedAudioStreamIndex = m.options.audioSteamIndex
setFieldText("audio_codec", tr("Audio") + ": " + m.top.itemContent.json.mediaStreams[m.top.selectedAudioStreamIndex].displayTitle)
end if
@ -198,7 +198,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
' Due to the way the button pressed event works, need to catch the release for the button as the press is being sent
' directly to the main loop. Will get this sorted in the layout update for Movie Details
if (key = "OK" and m.top.findNode("audio-button").isInFocusChain())
if key = "OK" and m.top.findNode("audio-button").isInFocusChain()
m.options.visible = true
m.options.setFocus(true)
end if
@ -206,7 +206,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
if key = "options"
if m.options.visible = true then
if m.options.visible = true
m.options.visible = false
optionsClosed()
else
@ -214,8 +214,8 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.options.setFocus(true)
end if
return true
else if key = "back" then
if m.options.visible = true then
else if key = "back"
if m.options.visible = true
m.options.visible = false
optionsClosed()
return true

View File

@ -27,7 +27,7 @@ end sub
sub optionsSet()
' Views Tab
if m.top.options.views <> invalid then
if m.top.options.views <> invalid
viewContent = CreateObject("roSGNode", "ContentNode")
index = 0
selectedViewIndex = 0
@ -38,7 +38,7 @@ sub optionsSet()
entry.description = view.Description
entry.streamIndex = view.StreamIndex
m.viewNames.push(view.Name)
if view.Selected <> invalid and view.Selected = true then
if view.Selected <> invalid and view.Selected = true
selectedViewIndex = index
entry.selected = true
m.top.audioSteamIndex = view.streamIndex
@ -65,13 +65,13 @@ end sub
function onKeyEvent(key as string, press as boolean) as boolean
if key = "down" or (key = "OK" and m.top.findNode("buttons").hasFocus()) then
if key = "down" or (key = "OK" and m.top.findNode("buttons").hasFocus())
m.top.findNode("buttons").setFocus(false)
m.menus[m.selectedItem].setFocus(true)
m.menus[m.selectedItem].drawFocusFeedback = true
'If user presses down from button menu, focus first item. If OK, focus checked item
if key = "down" then
if key = "down"
m.menus[m.selectedItem].jumpToItem = 0
else
m.menus[m.selectedItem].jumpToItem = m.menus[m.selectedItem].itemSelected
@ -79,13 +79,12 @@ function onKeyEvent(key as string, press as boolean) as boolean
return true
else if key = "OK"
if(m.menus[m.selectedItem].isInFocusChain()) then
if m.menus[m.selectedItem].isInFocusChain()
selMenu = m.menus[m.selectedItem]
selIndex = selMenu.itemSelected
child = selMenu.content.GetChild(selIndex)
if m.selectedAudioIndex = selIndex then
if m.selectedAudioIndex = selIndex
else
selMenu.content.GetChild(m.selectedAudioIndex).selected = false
newSelection = selMenu.content.GetChild(selIndex)
@ -96,7 +95,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
return true
else if key = "back" or key = "up"
if m.menus[m.selectedItem].isInFocusChain() then
if m.menus[m.selectedItem].isInFocusChain()
m.buttons.setFocus(true)
m.menus[m.selectedItem].drawFocusFeedback = false
return true

View File

@ -1,4 +1,4 @@
function init()
sub init()
' backgroundUri must be set to an empty string before backgroundColor can be set
m.top.backgroundUri = ""
m.top.backgroundColor = "#000000"
@ -8,4 +8,4 @@ function init()
m.BounceAnimation = m.top.findNode("BounceAnimation")
m.BounceAnimation.control = "start" 'Start BounceAnimation
end function
end sub

View File

@ -35,13 +35,12 @@ sub updateSize()
end sub
function getData()
if m.top.itemData = invalid then
if m.top.itemData = invalid
data = CreateObject("roSGNode", "ContentNode")
return data
end if
itemData = m.top.itemData
rowSize = m.top.rowSize
' todo - Or get the old data? I can't remember...
data = CreateObject("roSGNode", "ContentNode")
@ -75,7 +74,7 @@ function getData()
return data
end function
function addRow(data, title, type_filter)
sub addRow(data, title, type_filter)
itemData = m.top.itemData
row = data.CreateChild("ContentNode")
row.title = title
@ -84,4 +83,4 @@ function addRow(data, title, type_filter)
row.appendChild(item)
end if
end for
end function
end sub

View File

@ -17,7 +17,6 @@ sub updateSize()
border = 96
m.top.translation = [border, 75 + 115]
textHeight = 80
itemWidth = (dimensions["width"] - border*2)
itemHeight = 300
@ -34,16 +33,16 @@ sub updateSize()
m.top.rowItemSpacing = [ 20, 0 ]
end sub
function setupRows()
sub setupRows()
updateSize()
objects = m.top.objects
m.top.numRows = objects.items.count()
m.top.content = setData()
end function
end sub
function setData()
data = CreateObject("roSGNode", "ContentNode")
if m.top.objects = invalid then
if m.top.objects = invalid
' Return an empty node just to return something; we'll update once we have data
return data
end if

View File

@ -8,10 +8,10 @@ end sub
function onKeyEvent(key as string, press as boolean) as boolean
handled = false
if press then
if key = "play" then
if press
if key = "play"
itemToPlay = m.top.focusedChild.content.getChild(m.top.focusedChild.rowItemFocused[0]).getChild(0)
if itemToPlay <> invalid and itemToPlay.id <> "" then
if itemToPlay <> invalid and itemToPlay.id <> ""
m.top.quickPlayNode = itemToPlay
end if
handled = true

View File

@ -3,10 +3,10 @@ sub init()
m.title.text = tr("Loading...")
end sub
function itemContentChanged() as void
sub itemContentChanged()
item = m.top.itemContent
itemData = item.json
if itemData.indexNumber <> invalid then
if itemData.indexNumber <> invalid
indexNumber = itemData.indexNumber.toStr() + ". "
else
indexNumber = ""
@ -19,13 +19,13 @@ function itemContentChanged() as void
m.top.findNode("runtime").text = stri(getRuntime()).trim() + " mins"
m.top.findNode("endtime").text = tr("Ends at %1").Replace("%1", getEndTime())
end if
if itemData.communityRating <> invalid then
if itemData.communityRating <> invalid
m.top.findNode("star").visible = true
m.top.findNode("communityRating").text = str(int(itemData.communityRating*10)/10)
else
m.top.findNode("star").visible = false
end if
end function
end sub
function getRuntime() as integer
itemData = m.top.itemContent.json

View File

@ -14,7 +14,6 @@ sub init()
end sub
sub updateSize()
textHeight = 80
itemWidth = 200
itemHeight = 380 ' width * 1.5 + text
@ -32,13 +31,12 @@ sub updateSize()
end sub
function getData()
if m.top.TVSeasonData = invalid then
if m.top.TVSeasonData = invalid
data = CreateObject("roSGNode", "ContentNode")
return data
end if
seasonData = m.top.TVSeasonData
rowsize = m.top.rowSize
data = CreateObject("roSGNode", "ContentNode")
row = data.CreateChild("ContentNode")
row.title = "Seasons"

View File

@ -34,17 +34,14 @@ sub itemContentChanged()
if itemData.genres.count() > 0
setFieldText("genres", itemData.genres.join(", "))
end if
director = invalid
for each person in itemData.people
if person.type = "Director"
director = person.name
exit for
end if
end for
if itemData.taglines.count() > 0
setFieldText("tagline", itemData.taglines[0])
end if
' m.top.findNode("TVSeasonSelect").TVSeasonData = m.top.itemContent.seasons
end sub
sub setFieldText(field, value)
@ -52,9 +49,9 @@ sub setFieldText(field, value)
if node = invalid or value = invalid then return
' Handle non strings... Which _shouldn't_ happen, but hey
if type(value) = "roInt" or type(value) = "Integer" then
if type(value) = "roInt" or type(value) = "Integer"
value = str(value)
else if type(value) <> "roString" and type(value) <> "String" then
else if type(value) <> "roString" and type(value) <> "String"
value = ""
end if
@ -77,7 +74,7 @@ function getEndTime() as string
date.fromSeconds(date.asSeconds() + duration_s)
date.toLocalTime()
formatTime(date)
return formatTime(date)
end function
function getHistory() as string

View File

@ -16,7 +16,7 @@ sub itemContentChanged()
m.top.overhangTitle = itemData.name
setFieldText("releaseYear", itemData.productionYear)
setFieldText("officialRating", itemData.officialRating)
if itemData.communityRating <> invalid then
if itemData.communityRating <> invalid
m.top.findNode("star").visible = true
setFieldText("communityRating", itemData.communityRating)
' m.top.findNode("communityRating").text = str(int(itemData.communityRating*10)/10)
@ -35,17 +35,14 @@ sub itemContentChanged()
if itemData.genres.count() > 0
setFieldText("genres", itemData.genres.join(", "))
end if
director = invalid
for each person in itemData.people
if person.type = "Director"
director = person.name
exit for
end if
end for
if itemData.taglines.count() > 0
setFieldText("tagline", itemData.taglines[0])
end if
' m.top.findNode("TVSeasonSelect").TVSeasonData = m.top.itemContent.seasons
end sub
sub setFieldText(field, value)
@ -53,11 +50,11 @@ sub setFieldText(field, value)
if node = invalid or value = invalid then return
' Handle non strings... Which _shouldn't_ happen, but hey
if type(value) = "roInt" or type(value) = "Integer" then
if type(value) = "roInt" or type(value) = "Integer"
value = str(value).trim()
else if type(value) = "roFloat" or type(value) = "Float" then
else if type(value) = "roFloat" or type(value) = "Float"
value = str(value).trim()
else if type(value) <> "roString" and type(value) <> "String" then
else if type(value) <> "roString" and type(value) <> "String"
value = ""
end if
@ -80,7 +77,7 @@ function getEndTime() as string
date.fromSeconds(date.asSeconds() + duration_s)
date.toLocalTime()
formatTime(date)
return formatTime(date)
end function
function getHistory() as string

962
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -7,12 +7,14 @@
"test": "tests"
},
"devDependencies": {
"brighterscript": "^0.30.1",
"@rokucommunity/bslint": "^0.4.0",
"brighterscript": "^0.30.9",
"rooibos-cli": "^1.0.1"
},
"scripts": {
"validate": "npx bsc --copy-to-staging=false --create-package=false",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "bslint"
},
"repository": {
"type": "git",
@ -28,4 +30,4 @@
"url": "https://github.com/jellyfin/jellyfin-roku/issues"
},
"homepage": "https://github.com/jellyfin/jellyfin-roku#readme"
}
}

View File

@ -1,8 +1,8 @@
function Main (args as Dynamic) as Void
sub Main (args as Dynamic) as Void
' If the Rooibos files are included in deployment, run tests
'bs:disable-next-line
if (type(Rooibos__Init) = "Function") then Rooibos__Init()
if type(Rooibos__Init) = "Function" then Rooibos__Init()
' The main function that runs when the application is launched.
m.screen = CreateObject("roSGScreen")
@ -54,7 +54,7 @@ function Main (args as Dynamic) as Void
if (args.mediaType <> invalid) and (args.contentId <> invalid)
video = CreateVideoPlayerGroup(args.contentId)
if video <> invalid then
if video <> invalid
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
@ -79,9 +79,9 @@ function Main (args as Dynamic) as Void
' This now only references m. fields so could be placed anywhere, in theory
' "group" is always "whats on the screen"
' m.scene's children is the "previous view" stack
while(true)
while true
msg = wait(0, m.port)
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed() then
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
print "CLOSING SCREEN"
return
@ -110,9 +110,9 @@ function Main (args as Dynamic) as Void
reportingNode = msg.getRoSGNode()
itemNode = reportingNode.quickPlayNode
if itemNode = invalid or itemNode.id = "" then return
if itemNode.type = "Episode" or itemNode.type = "Movie" or itemNode.type = "Video" then
if itemNode.type = "Episode" or itemNode.type = "Movie" or itemNode.type = "Video"
video = CreateVideoPlayerGroup(itemNode.id)
if video <> invalid then
if video <> invalid
group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
@ -135,12 +135,12 @@ function Main (args as Dynamic) as Void
group = CreateItemGrid(selectedItem)
group.overhangTitle = selectedItem.title
m.scene.appendChild(group)
else if selectedItem.type = "Episode" then
else if selectedItem.type = "Episode"
' play episode
' todo: create an episode page to link here
video_id = selectedItem.id
video = CreateVideoPlayerGroup(video_id)
if video <> invalid then
if video <> invalid
group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
@ -151,7 +151,7 @@ function Main (args as Dynamic) as Void
ReportPlayback(group, "start")
m.overhang.visible = false
end if
else if selectedItem.type = "Series" then
else if selectedItem.type = "Series"
group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
@ -162,7 +162,7 @@ function Main (args as Dynamic) as Void
group = CreateSeriesDetailsGroup(selectedItem.json)
group.overhangTitle = selectedItem.title
m.scene.appendChild(group)
else if selectedItem.type = "Movie" then
else if selectedItem.type = "Movie"
' open movie detail page
group.lastFocus = group.focusedChild
group.setFocus(false)
@ -175,7 +175,7 @@ function Main (args as Dynamic) as Void
group.overhangTitle = selectedItem.title
m.scene.appendChild(group)
else if selectedItem.type = "TvChannel" or selectedItem.type = "Video" then
else if selectedItem.type = "TvChannel" or selectedItem.type = "Video"
' play channel feed
video_id = selectedItem.id
@ -187,7 +187,7 @@ function Main (args as Dynamic) as Void
video = CreateVideoPlayerGroup(video_id)
dialog.close = true
if video <> invalid then
if video <> invalid
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
@ -209,7 +209,6 @@ function Main (args as Dynamic) as Void
else
' TODO - switch on more node types
message_dialog("This type is not yet supported: " + selectedItem.type + ".")
selectedItem = invalid
end if
else if isNodeEvent(msg, "movieSelected")
' If you select a movie from ANYWHERE, follow this flow
@ -260,7 +259,7 @@ function Main (args as Dynamic) as Void
node = getMsgPicker(msg, "picker")
video_id = node.id
video = CreateVideoPlayerGroup(video_id)
if video <> invalid then
if video <> invalid
group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
@ -294,7 +293,7 @@ function Main (args as Dynamic) as Void
' TODO - swap this based on target.mediatype
' types: [ Series (Show), Episode, Movie, Audio, Person, Studio, MusicArtist ]
if node.type = "Series" then
if node.type = "Series"
group = CreateSeriesDetailsGroup(node)
else
group = CreateMovieDetailsGroup(node)
@ -316,7 +315,7 @@ function Main (args as Dynamic) as Void
' This is currently page layout Group, button Group, then button
video_id = group.id
video = CreateVideoPlayerGroup(video_id, audio_stream_idx)
if video <> invalid then
if video <> invalid
group.lastFocus = group.focusedChild.focusedChild.focusedChild
group.setFocus(false)
group.visible = false
@ -346,7 +345,7 @@ function Main (args as Dynamic) as Void
else
' If there are no other button matches, check if this is a simple "OK" Dialog & Close if so
dialog = msg.getRoSGNode()
if dialog.id = "OKDialog" then
if dialog.id = "OKDialog"
dialog.unobserveField("buttonSelected")
dialog.close = true
end if
@ -384,9 +383,9 @@ function Main (args as Dynamic) as Void
end if
else if isNodeEvent(msg, "selectSubtitlePressed")
node = m.scene.focusedChild
if node.isSubType("JFVideo") then
if node.isSubType("JFVideo")
trackSelected = selectSubtitleTrack(node.Subtitles, node.SelectedSubtitle)
if trackSelected <> invalid and trackSelected <> -2 then
if trackSelected <> invalid and trackSelected <> -2
changeSubtitleDuringPlayback(trackSelected)
end if
end if
@ -394,22 +393,22 @@ function Main (args as Dynamic) as Void
ReportPlayback(group, "update")
else if isNodeEvent(msg, "state")
node = msg.getRoSGNode()
if node.state = "finished" then
if node.state = "finished"
stopPlayback()
if node.showID = invalid then
if node.showID = invalid
RemoveCurrentGroup()
else
nextEpisode =autoPlayNextEpisode(node.id, node.showID)
if nextEpisode <> invalid then group = nextEpisode
end if
else if node.state = "playing" or node.state = "paused" then
else if node.state = "playing" or node.state = "paused"
ReportPlayback(group, "update")
end if
else if type(msg) = "roDeviceInfoEvent" then
else if type(msg) = "roDeviceInfoEvent"
event = msg.GetInfo()
if event.exitedScreensaver = true then
if event.exitedScreensaver = true
m.overhang.callFunc("resetTime")
if group.subtype() = "Home" then
if group.subtype() = "Home"
currentTime = CreateObject("roDateTime").AsSeconds()
group.timeLastRefresh = currentTime
group.callFunc("refresh")
@ -424,7 +423,7 @@ function Main (args as Dynamic) as Void
info = msg.GetInfo()
if info.DoesExist("mediatype") and info.DoesExist("contentid")
video = CreateVideoPlayerGroup(info.contentId)
if video <> invalid then
if video <> invalid
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
@ -451,10 +450,10 @@ function Main (args as Dynamic) as Void
end if
end while
end function
end sub
function LoginFlow(startOver = false as boolean)
if m.scene <> invalid then
if m.scene <> invalid
m.scene.unobserveField("backPressed")
end if
'Collect Jellyfin server and user information
@ -462,52 +461,51 @@ function LoginFlow(startOver = false as boolean)
if get_setting("server") = invalid then startOver = true
if not startOver then
invalidServer = true
if not startOver
' Show Connecting to Server spinner
dialog = createObject("roSGNode", "ProgressDialog")
dialog.title = tr("Connecting to Server")
m.scene.dialog = dialog
serverInfoResult = ServerInfo()
invalidServer = ServerInfo().Error
dialog.close = true
end if
if startOver or serverInfoResult.Error then
if startOver or invalidServer
print "Get server details"
SendPerformanceBeacon("AppDialogInitiate") ' Roku Performance monitoring - Dialog Starting
serverSelection = CreateServerGroup()
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
if serverSelection = "backPressed" then
if serverSelection = "backPressed"
print "backPressed"
wipe_groups()
return false
end if
end if
if get_setting("active_user") = invalid then
if get_setting("active_user") = invalid
SendPerformanceBeacon("AppDialogInitiate") ' Roku Performance monitoring - Dialog Starting
publicUsers = GetPublicUsers()
if publicUsers.count() then
if publicUsers.count()
publicUsersNodes = []
for each item in publicUsers
user = CreateObject("roSGNode", "PublicUserData")
user.id = item.Id
user.name = item.Name
if item.PrimaryImageTag <> invalid then
if item.PrimaryImageTag <> invalid
user.ImageURL = UserImageURL(user.id, { "tag": item.PrimaryImageTag })
end if
publicUsersNodes.push(user)
end for
userSelected = CreateUserSelectGroup(publicUsersNodes)
m.scene.focusedChild.visible = false
if userSelected = "backPressed" then
if userSelected = "backPressed"
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
return LoginFlow(true)
else
'Try to login without password. If the token is valid, we're done
get_token(userSelected, "")
if get_setting("active_user") <> invalid then
if get_setting("active_user") <> invalid
m.user = AboutMe()
LoadUserPreferences()
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
@ -519,7 +517,7 @@ function LoginFlow(startOver = false as boolean)
end if
passwordEntry = CreateSigninGroup(userSelected)
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
if passwordEntry = "backPressed" then
if passwordEntry = "backPressed"
m.scene.focusedChild.visible = false
return LoginFlow(true)
end if
@ -549,12 +547,12 @@ sub RunScreenSaver()
m.port = createObject("roMessagePort")
screen.setMessagePort(m.port)
scene = screen.createScene("Screensaver")
screen.createScene("Screensaver")
screen.Show()
while(true)
while true
msg = wait(8000, m.port)
if (msg <> invalid)
if msg <> invalid
msgType = type(msg)
if msgType = "roSGScreenEvent"
if msg.isScreenClosed() then return
@ -566,7 +564,7 @@ end sub
sub wipe_groups()
' The 1 remaining child should be the overhang
while(m.scene.getChildCount() > 1)
while m.scene.getChildCount() > 1
m.scene.removeChildIndex(1)
end while
end sub
@ -580,8 +578,8 @@ sub RemoveCurrentGroup()
group = m.scene.getChild(n - 1)
m.overhang.title = group.overhangTitle
m.overhang.showOptions = group.optionsAvailable
if group.optionsAvailable <> prevOptionsAvailable then
if group.optionsAvailable = false then
if group.optionsAvailable <> prevOptionsAvailable
if group.optionsAvailable = false
m.scene.unobserveField("optionsPressed")
else
m.scene.observeField("optionsPressed", m.port)
@ -593,9 +591,9 @@ sub RemoveCurrentGroup()
else
group.setFocus(true)
end if
if group.subtype() = "Home" then
if group.subtype() = "Home"
currentTime = CreateObject("roDateTime").AsSeconds()
if group.timeLastRefresh = invalid or (currentTime - group.timeLastRefresh) > 20 then
if group.timeLastRefresh = invalid or (currentTime - group.timeLastRefresh) > 20
group.timeLastRefresh = currentTime
group.callFunc("refresh")
end if
@ -605,7 +603,7 @@ end sub
' Roku Performance monitoring
sub SendPerformanceBeacon(signalName as string)
if m.global.app_loaded = false then
if m.global.app_loaded = false
m.scene.signalBeacon(signalName)
end if
end sub

View File

@ -23,7 +23,7 @@ function CreateServerGroup()
server_hostname = config.content.getChild(0)
group.observeField("backPressed", port)
while(true)
while true
msg = wait(0, port)
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
return "false"
@ -36,9 +36,9 @@ function CreateServerGroup()
maxSlashes = 0
if left(lcase(server_hostname.value),8) = "https://" or left(lcase(server_hostname.value),7) = "http://" then maxSlashes = 2
'Check to make sure entry has no extra slashes before adding default ports.
if Instr(0, server_hostname.value, "/") = maxSlashes then
if server_hostname.value.len() > 5 and mid(server_hostname.value, server_hostname.value.len()-4,1) <> ":" and mid(server_hostname.value, server_hostname.value.len()-5,1) <> ":" then
if left(lcase(server_hostname.value) ,5) = "https" then
if Instr(0, server_hostname.value, "/") = maxSlashes
if server_hostname.value.len() > 5 and mid(server_hostname.value, server_hostname.value.len()-4,1) <> ":" and mid(server_hostname.value, server_hostname.value.len()-5,1) <> ":"
if left(lcase(server_hostname.value) ,5) = "https"
server_hostname.value = server_hostname.value + ":8920"
else
server_hostname.value = server_hostname.value + ":8096"
@ -48,7 +48,7 @@ function CreateServerGroup()
'Append http:// to server
if left(lcase(server_hostname.value),4) <> "http" then server_hostname.value = "http://" + server_hostname.value
'If this is a different server from what we know, reset username/password setting
if get_setting("server") <> server_hostname.value then
if get_setting("server") <> server_hostname.value
set_setting("username", "")
set_setting("password", "")
end if
@ -63,7 +63,7 @@ function CreateServerGroup()
dialog.close = true
if serverInfoResult = invalid then
if serverInfoResult = invalid
' Maybe don't unset setting, but offer as a prompt
' Server not found, is it online? New values / Retry
print "Server not found, is it online? New values / Retry"
@ -71,12 +71,12 @@ function CreateServerGroup()
SignOut()
else if serverInfoResult.Error <> invalid and serverInfoResult.Error
' If server redirected received, update the URL
if serverInfoResult.UpdatedUrl <> invalid then
if serverInfoResult.UpdatedUrl <> invalid
server_hostname.value = serverInfoResult.UpdatedUrl
end if
' Display Error Message to user
message = tr("Error: ")
if serverInfoResult.ErrorCode <> invalid then
if serverInfoResult.ErrorCode <> invalid
message = message + "[" + serverInfoResult.ErrorCode.toStr() + "] "
end if
group.findNode("alert").text = message + tr(serverInfoResult.ErrorMessage)
@ -91,10 +91,11 @@ function CreateServerGroup()
' Just hide it when done, in case we need to come back
group.visible = false
return ""
end function
function CreateUserSelectGroup(users = [])
if users.count() = 0 then
if users.count() = 0
return ""
end if
group = CreateObject("roSGNode", "UserSelect")
@ -105,7 +106,7 @@ function CreateUserSelectGroup(users = [])
group.findNode("userRow").observeField("userSelected", port)
group.findNode("alternateOptions").observeField("itemSelected", port)
group.observeField("backPressed", port)
while(true)
while true
msg = wait(0, port)
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
group.visible = false
@ -115,7 +116,7 @@ function CreateUserSelectGroup(users = [])
else if type(msg) = "roSGNodeEvent" and msg.getField() = "userSelected"
return msg.GetData()
else if type(msg) = "roSGNodeEvent" and msg.getField() = "itemSelected"
if msg.getData() = 0 then
if msg.getData() = 0
return ""
end if
end if
@ -123,6 +124,7 @@ function CreateUserSelectGroup(users = [])
' Just hide it when done, in case we need to come back
group.visible = false
return ""
end function
function CreateSigninGroup(user = "")
@ -163,7 +165,7 @@ function CreateSigninGroup(user = "")
group.observeField("backPressed", port)
while(true)
while true
msg = wait(0, port)
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
group.visible = false
@ -190,6 +192,7 @@ function CreateSigninGroup(user = "")
' Just hide it when done, in case we need to come back
group.visible = false
return ""
end function
function CreateHomeGroup()
@ -290,17 +293,16 @@ function CreateSearchPage()
return group
end function
function CreateSidePanel(buttons, options)
sub CreateSidePanel(buttons, options)
group = CreateObject("roSGNode", "OptionsSlider")
group.buttons = buttons
group.options = options
end function
end sub
function CreateVideoPlayerGroup(video_id, audio_stream_idx = 1)
' Video is Playing
video = VideoPlayer(video_id, audio_stream_idx)
if video = invalid return invalid
if video = invalid then return invalid
timer = video.findNode("playbackTimer")
video.observeField("backPressed", m.port)

View File

@ -21,7 +21,7 @@ sub AddVideoContent(video, audio_stream_idx = 1, subtitle_idx = -1, playbackPosi
video.content = createObject("RoSGNode", "ContentNode")
meta = ItemMetaData(video.id)
if meta = invalid then
if meta = invalid
video.content = invalid
return
end if
@ -29,19 +29,19 @@ sub AddVideoContent(video, audio_stream_idx = 1, subtitle_idx = -1, playbackPosi
video.content.title = meta.title
video.showID = meta.showID
if playbackPosition = -1 then
if playbackPosition = -1
playbackPosition = meta.json.UserData.PlaybackPositionTicks
if playbackPosition > 0 then
if playbackPosition > 0
dialogResult = startPlayBackOver(playbackPosition)
'Dialog returns -1 when back pressed, 0 for resume, and 1 for start over
if dialogResult = -1 then
if dialogResult = -1
'User pressed back, return invalid and don't load video
video.content = invalid
return
else if dialogResult = 1 then
else if dialogResult = 1
'Start Over selected, change position to 0
playbackPosition = 0
else if dialogResult = 2 then
else if dialogResult = 2
'Mark this item as watched, refresh the page, and return invalid so we don't load the video
MarkItemWatched(video.id)
video.content.watched = not video.content.watched
@ -64,7 +64,7 @@ sub AddVideoContent(video, audio_stream_idx = 1, subtitle_idx = -1, playbackPosi
video.mediaSourceId = video.id
video.audioIndex = audio_stream_idx
if playbackInfo = invalid then
if playbackInfo = invalid
video.content = invalid
return
end if
@ -72,7 +72,7 @@ sub AddVideoContent(video, audio_stream_idx = 1, subtitle_idx = -1, playbackPosi
params = {}
video.PlaySessionId = playbackInfo.PlaySessionId
if meta.live then
if meta.live
video.content.live = true
video.content.StreamFormat = "hls"
end if
@ -82,7 +82,7 @@ sub AddVideoContent(video, audio_stream_idx = 1, subtitle_idx = -1, playbackPosi
subtitles = sortSubtitles(meta.id, playbackInfo.MediaSources[0].MediaStreams)
video.Subtitles = subtitles["all"]
if meta.live then
if meta.live
video.transcodeParams = {
"MediaSourceId": playbackInfo.MediaSources[0].Id,
"LiveStreamId": playbackInfo.MediaSources[0].LiveStreamId,
@ -97,7 +97,7 @@ sub AddVideoContent(video, audio_stream_idx = 1, subtitle_idx = -1, playbackPosi
video.directPlaySupported = playbackInfo.MediaSources[0].SupportsDirectPlay
if video.directPlaySupported then
if video.directPlaySupported
params.append({
"Static": "true",
"Container": video.container,
@ -139,7 +139,7 @@ end function
'Opens dialog asking user if they want to resume video or start playback over
function startPlayBackOver(time as LongInteger) as integer
if m.scene.focusedChild.overhangTitle = "Home" then
if m.scene.focusedChild.overhangTitle = "Home"
return option_dialog([ "Resume playing at " + ticksToHuman(time) + ".", "Start over from the beginning.", "Watched"])
else
return option_dialog([ "Resume playing at " + ticksToHuman(time) + ".", "Start over from the beginning."])
@ -148,21 +148,21 @@ end function
function directPlaySupported(meta as object) as boolean
devinfo = CreateObject("roDeviceInfo")
if meta.json.MediaSources[0] <> invalid and meta.json.MediaSources[0].SupportsDirectPlay = false then
if meta.json.MediaSources[0] <> invalid and meta.json.MediaSources[0].SupportsDirectPlay = false
return false
end if
if meta.json.MediaStreams[0] = invalid then
if meta.json.MediaStreams[0] = invalid
return false
end if
streamInfo = { Codec: meta.json.MediaStreams[0].codec }
if meta.json.MediaStreams[0].Profile <> invalid and meta.json.MediaStreams[0].Profile.len() > 0 then
if meta.json.MediaStreams[0].Profile <> invalid and meta.json.MediaStreams[0].Profile.len() > 0
streamInfo.Profile = LCase(meta.json.MediaStreams[0].Profile)
end if
if meta.json.MediaSources[0].container <> invalid and meta.json.MediaSources[0].container.len() > 0 then
if meta.json.MediaSources[0].container <> invalid and meta.json.MediaSources[0].container.len() > 0
'CanDecodeVideo() requires the .container to be format: “mp4”, “hls”, “mkv”, “ism”, “dash”, “ts” if its to direct stream
if meta.json.MediaSources[0].container = "mov" then
if meta.json.MediaSources[0].container = "mov"
streamInfo.Container = "mp4"
else
streamInfo.Container = meta.json.MediaSources[0].container
@ -217,7 +217,7 @@ sub ReportPlayback(video, state = "update" as string)
"PositionTicks": int(video.position) * 10000000&, 'Ensure a LongInteger is used
"IsPaused": (video.state = "paused"),
}
if video.content.live then
if video.content.live
params.append({
"MediaSourceId": video.transcodeParams.MediaSourceId,
"LiveStreamId": video.transcodeParams.LiveStreamId
@ -226,17 +226,17 @@ sub ReportPlayback(video, state = "update" as string)
PlaystateUpdate(video.id, state, params)
end sub
function StopPlayback()
sub StopPlayback()
video = m.scene.focusedchild
video.control = "stop"
m.device.EnableAppFocusEvent(False)
video.findNode("playbackTimer").control = "stop"
ReportPlayback(video, "stop")
end function
end sub
function autoPlayNextEpisode(videoID as string, showID as string)
' use web client setting
if m.user.Configuration.EnableNextEpisodeAutoPlay then
if m.user.Configuration.EnableNextEpisodeAutoPlay
' query API for next episode ID
url = Substitute("Shows/{0}/Episodes", showID)
urlParams = { "UserId": get_setting("active_user")}
@ -245,7 +245,7 @@ function autoPlayNextEpisode(videoID as string, showID as string)
resp = APIRequest(url, urlParams)
data = getJson(resp)
if data <> invalid and data.Items.Count() = 2 then
if data <> invalid and data.Items.Count() = 2
' remove finished video node
n = m.scene.getChildCount() - 1
m.scene.removeChildIndex(n)

View File

@ -37,15 +37,15 @@ end function
function ImageURL(id, version = "Primary", params = {})
' set defaults
if params.maxHeight = invalid then
if params.maxHeight = invalid
param = { "maxHeight" : "384" }
params.append(param)
end if
if params.maxWidth = invalid then
if params.maxWidth = invalid
param = { "maxWidth" : "196" }
params.append(param)
end if
if params.quality = invalid then
if params.quality = invalid
param = { "quality" : "90" }
params.append(param)
end if
@ -56,13 +56,13 @@ end function
function UserImageURL(id, params = {})
' set defaults
if params.maxHeight = invalid then
if params.maxHeight = invalid
params.append({ "maxHeight" : "300" })
end if
if params.maxWidth = invalid then
if params.maxWidth = invalid
params.append({ "maxWidth" : "300" })
end if
if params.quality = invalid then
if params.quality = invalid
params.append({ "quality" : "90" })
end if

View File

@ -1,7 +1,7 @@
function ItemGetPlaybackInfo(id as string, StartTimeTicks = 0 as longinteger)
function ItemGetPlaybackInfo(id as string, startTimeTicks = 0 as longinteger)
params = {
"UserId": get_setting("active_user"),
"StartTimeTicks": StartTimeTicks,
"StartTimeTicks": startTimeTicks,
"IsPlayback": true,
"AutoOpenLiveStream": true,
"MaxStreamingBitrate": "140000000"
@ -16,7 +16,7 @@ function ItemPostPlaybackInfo(id as string, mediaSourceId = "" as string , audio
}
params = {
"UserId": get_setting("active_user"),
"StartTimeTicks": StartTimeTicks,
"StartTimeTicks": startTimeTicks,
"IsPlayback": true,
"AutoOpenLiveStream": true,
"MaxStreamingBitrate": "140000000",
@ -71,7 +71,7 @@ function ItemMetaData(id as string)
data = getJson(resp)
if data = invalid then return invalid
imgParams = {}
if data.UserData.PlayedPercentage <> invalid then
if data.UserData.PlayedPercentage <> invalid
param = { "PercentPlayed": data.UserData.PlayedPercentage }
imgParams.Append(param)
end if
@ -95,7 +95,7 @@ function ItemMetaData(id as string)
else if data.type = "BoxSet"
tmp = CreateObject("roSGNode", "CollectionData")
tmp.image = PosterImage(data.id, imgParams)
tmp.json = item
tmp.json = data
return tmp
else if data.type = "Season"
tmp = CreateObject("roSGNode", "TVSeasonData")
@ -117,7 +117,6 @@ function ItemMetaData(id as string)
' Return json if we don't know what it is
return data
end if
return data
end function
' Seasons for a TV Show
@ -129,7 +128,7 @@ function TVSeasons(id as string)
results = []
for each item in data.Items
imgParams = { "AddPlayedIndicator": item.UserData.Played }
if item.UserData.UnplayedItemCount > 0 then
if item.UserData.UnplayedItemCount > 0
param = { "UnplayedCount" : item.UserData.UnplayedItemCount }
imgParams.Append(param)
end if
@ -150,7 +149,7 @@ function TVEpisodes(show_id as string, season_id as string)
results = []
for each item in data.Items
imgParams = { "AddPlayedIndicator": item.UserData.Played, "maxWidth": 712, "maxheight": 400 }
if item.UserData.PlayedPercentage <> invalid then
if item.UserData.PlayedPercentage <> invalid
param = { "PercentPlayed": item.UserData.PlayedPercentage }
imgParams.Append(param)
end if

View File

@ -1,10 +1,13 @@
function PlaystateUpdate(id, state as string, params = {})
if state = "start" then
if state = "start"
url = "Sessions/Playing"
else if state = "stop" then
else if state = "stop"
url = "Sessions/Playing/Stopped"
else if state = "update"
url = "Sessions/Playing/Progress"
else
' Unknow State
return {}
end if
params = PlaystateDefaults(id, params)
resp = APIRequest(url)
@ -40,10 +43,9 @@ function PlaystateDefaults(id="" as string, params={} as object)
return FormatJson(new_params)
end function
function deleteTranscode(id)
sub deleteTranscode(id)
devinfo = CreateObject("roDeviceInfo")
device_id = devinfo.getChannelClientID()
req = APIRequest("/Videos/ActiveEncodings", { "deviceID" : devinfo.getChannelClientID(), "PlaySessionId": id })
req.setRequest("DELETE")
postVoid(req)
end function
end sub

View File

@ -11,7 +11,7 @@ function UnmarkItemFavorite(id as String)
return getJson(resp)
end function
function MarkItemWatched(id as String)
sub MarkItemWatched(id as String)
date = CreateObject("roDateTime")
dateStr = stri(date.getYear()).trim()
dateStr += leftPad(stri(date.getMonth()).trim(), "0", 2)
@ -21,9 +21,8 @@ function MarkItemWatched(id as String)
dateStr += leftPad(stri(date.getSeconds()).trim(), "0", 2)
url = Substitute("Users/{0}/PlayedItems/{1}", get_setting("active_user"), id)
resp = APIRequest(url, {"DatePlayed": dateStr})
data = postJson(resp)
end function
APIRequest(url, {"DatePlayed": dateStr})
end sub
function UnmarkItemWatched(id as String)
url = Substitute("Users/{0}/PlayedItems/{1}", get_setting("active_user"), id)

View File

@ -5,6 +5,7 @@ function buildParams(params={} as Object) as string
param_array = []
for each field in params.items()
item = ""
if type(field.value) = "String" or type(field.value) = "roString"
item = field.key + "=" + req.escape(field.value.trim())
'item = field.key + "=" + field.value.trim()
@ -30,7 +31,8 @@ function buildParams(params={} as Object) as string
item = field.key + "=" + req.escape(field.value)
'item = field.key + "=" + field.value
end if
param_array.push(item)
if item <> "" then param_array.push(item)
end for
return param_array.join("&")
@ -142,7 +144,7 @@ function authorize_request(request)
auth = auth + ", Version=" + Chr(34) + version + Chr(34)
user = get_setting("active_user")
if user <> invalid and user <> "" then
if user <> invalid and user <> ""
auth = auth + ", UserId=" + Chr(34) + user + Chr(34)
end if

View File

@ -2,10 +2,8 @@ function get_token(user as String, password as String)
url = "Users/AuthenticateByName?format=json"
req = APIRequest(url)
encPass = CreateObject("roUrlTransfer")
json = postJson(req, FormatJson({ "Username": user, "Pw": password }))
if json = invalid then return invalid
userdata = CreateObject("roSGNode", "UserData")
@ -23,7 +21,7 @@ function AboutMe()
return getJson(resp)
end function
function SignOut()
sub SignOut()
if get_setting("active_user") <> invalid
unset_user_setting("token")
unset_setting("username")
@ -33,30 +31,30 @@ function SignOut()
m.overhang.currentUser = ""
m.overhang.showOptions = false
m.scene.unobserveField("optionsPressed")
end function
end sub
function AvailableUsers()
users = parseJson(get_setting("available_users", "[]"))
return users
end function
function PickUser(id as string)
sub PickUser(id as string)
this_user = invalid
for each user in AvailableUsers()
if user.id = id then this_user = user
end for
if this_user = invalid then return invalid
if this_user = invalid then return
set_setting("active_user", this_user.id)
set_setting("server", this_user.server)
end function
end sub
function RemoveUser(id as string)
sub RemoveUser(id as string)
user = CreateObject("roSGNode", "UserData")
user.id = id
user.callFunc("removeFromRegistry")
if get_setting("active_user") = id then SignOut()
end function
end sub
function ServerInfo()
url = "System/Info/Public"
@ -75,14 +73,14 @@ function ServerInfo()
' check for a location redirect header in the response
headers = resp.GetResponseHeaders()
if headers <> invalid and headers.location <> invalid then
if headers <> invalid and headers.location <> invalid
' only follow redirect if it the API Endpoint path is the same (/System/Info/Public)
' set the server to new location and try again
if right(headers.location, 19) = "/System/Info/Public" then
if right(headers.location, 19) = "/System/Info/Public"
set_setting("server", left(headers.location, len(headers.location) - 19))
info = ServerInfo()
if info.Error then
if info.Error
info.UpdatedUrl = left(headers.location, len(headers.location) - 19)
info.ErrorMessage = info.ErrorMessage + " (Note: Server redirected us to " + info.UpdatedUrl + ")"
end if
@ -91,15 +89,15 @@ function ServerInfo()
end if
' handle any non 200 responses, returning the error code and message
if resp.GetResponseCode() <> 200 then
if resp.GetResponseCode() <> 200
return { "Error": true, "ErrorCode": resp.GetResponseCode(), "ErrorMessage": resp.GetFailureReason() }
end if
' return the parsed response string
responseString = resp.GetString()
if responseString <> invalid and responseString <> "" then
if responseString <> invalid and responseString <> ""
result = ParseJson(responseString)
if result <> invalid then
if result <> invalid
result.Error = false
return result
end if
@ -125,7 +123,7 @@ sub LoadUserPreferences()
resp = APIRequest(url)
jsonResponse = getJson(resp)
if jsonResponse <> invalid and jsonResponse.CustomPrefs <> invalid and jsonResponse.CustomPrefs["landing-livetv"] <> invalid then
if jsonResponse <> invalid and jsonResponse.CustomPrefs <> invalid and jsonResponse.CustomPrefs["landing-livetv"] <> invalid
set_user_setting("display.livetv.landing", jsonResponse.CustomPrefs["landing-livetv"])
else
unset_user_setting("display.livetv.landing")

View File

@ -2,7 +2,7 @@
function selectSubtitleTrack(tracks, current = -1) as integer
video = m.scene.focusedChild
trackSelected = selectSubtitleTrackDialog(video.Subtitles, video.SelectedSubtitle)
if trackSelected = invalid or trackSelected = -1 then ' back pressed in Dialog - no selection made
if trackSelected = invalid or trackSelected = -1 ' back pressed in Dialog - no selection made
return -2
else
return trackSelected - 1
@ -18,7 +18,7 @@ function selectSubtitleTrackDialog(tracks, currentTrack = -1)
default = ""
if item.IsForced then forced = " [Forced]"
if item.IsDefault then default = " - Default"
if item.Track.Language <> invalid then
if item.Track.Language <> invalid
language = iso6392.lookup(item.Track.Language)
if language = invalid then language = item.Track.Language
else
@ -32,7 +32,7 @@ end function
sub changeSubtitleDuringPlayback(newid)
' If no subtitles set
if newid = invalid or newid = -1 then
if newid = invalid or newid = -1
turnoffSubtitles()
return
end if
@ -40,12 +40,12 @@ sub changeSubtitleDuringPlayback(newid)
video = m.scene.focusedChild
' If no change of subtitle track, return
if newId = video.SelectedSubtitle then return
if newid = video.SelectedSubtitle then return
currentSubtitles = video.Subtitles[video.SelectedSubtitle]
newSubtitles = video.Subtitles[newid]
if newSubtitles.IsEncoded then
if newSubtitles.IsEncoded
' Switching to Encoded Subtitle stream
video.control = "stop"
@ -53,7 +53,7 @@ sub changeSubtitleDuringPlayback(newid)
video.control = "play"
video.globalCaptionMode = "Off" ' Using encoded subtitles - so turn off text subtitles
else if (currentSubtitles <> invalid AND currentSubtitles.IsEncoded) then
else if currentSubtitles <> invalid AND currentSubtitles.IsEncoded
' Switching from an Encoded stream to a text stream
video.control = "stop"
@ -69,35 +69,34 @@ sub changeSubtitleDuringPlayback(newid)
video.subtitleTrack = video.availableSubtitleTracks[newSubtitles.TextIndex].TrackName
end if
video.SelectedSubtitle = newId
video.SelectedSubtitle = newid
end sub
function turnoffSubtitles()
sub turnoffSubtitles()
video = m.scene.focusedChild
current = video.SelectedSubtitle
video.SelectedSubtitle = -1
video.globalCaptionMode = "Off"
m.device.EnableAppFocusEvent(false)
' Check if Enoded subtitles are being displayed, and turn off
if current > -1 and video.Subtitles[current].IsEncoded then
if current > -1 and video.Subtitles[current].IsEncoded
video.control = "stop"
AddVideoContent(video, video.audioIndex, -1, video.position * 10000000)
video.control = "play"
end if
end function
end sub
'Checks available subtitle tracks and puts subtitles in forced, default, and non-default/forced but preferred language at the top
function sortSubtitles(id as string, MediaStreams)
tracks = { "forced": [], "default": [], "normal": [] }
'Too many args for using substitute
dashedid = id.left(8) + "-" + id.mid(8,4) + "-" + id.mid(12,4) + "-" + id.mid(16,4) + "-" + id.right(12)
prefered_lang = m.user.Configuration.SubtitleLanguagePreference
for each stream in MediaStreams
if stream.type = "Subtitle" then
if stream.type = "Subtitle"
url = ""
if(stream.DeliveryUrl <> invalid) then
if stream.DeliveryUrl <> invalid
url = buildURL(stream.DeliveryUrl)
end if
@ -110,14 +109,14 @@ function sortSubtitles(id as string, MediaStreams)
"IsExternal": stream.IsExternal
"IsEncoded": stream.DeliveryMethod = "Encode"
}
if stream.isForced then
if stream.isForced
trackType = "forced"
else if stream.IsDefault then
else if stream.IsDefault
trackType = "default"
else
trackType = "normal"
end if
if prefered_lang <> "" and prefered_lang = stream.Track.Language then
if prefered_lang <> "" and prefered_lang = stream.Track.Language
tracks[trackType].unshift(stream)
else
tracks[trackType].push(stream)
@ -130,7 +129,7 @@ function sortSubtitles(id as string, MediaStreams)
textTracks = []
for i = 0 to tracks["forced"].count() - 1
if tracks["forced"][i].IsTextSubtitleStream then
if tracks["forced"][i].IsTextSubtitleStream
tracks["forced"][i].TextIndex = textTracks.count()
textTracks.push(tracks["forced"][i].Track)
end if

View File

@ -9,51 +9,51 @@ function registry_read(key, section=invalid)
return invalid
end function
function registry_write(key, value, section=invalid)
if section = invalid then return invalid
sub registry_write(key, value, section=invalid)
if section = invalid then return
reg = CreateObject("roRegistrySection", section)
reg.write(key, value)
reg.flush()
end function
end sub
function registry_delete(key, section=invalid)
if section = invalid then return invalid
sub registry_delete(key, section=invalid)
if section = invalid then return
reg = CreateObject("roRegistrySection", section)
reg.delete(key)
reg.flush()
end function
end sub
' "Jellyfin" registry accessors for the default global settings
function get_setting(key, default=invalid)
value = registry_read(key, "Jellyfin")
if value = invalid return default
if value = invalid then return default
return value
end function
function set_setting(key, value)
sub set_setting(key, value)
registry_write(key, value, "Jellyfin")
end function
end sub
function unset_setting(key)
sub unset_setting(key)
registry_delete(key, "Jellyfin")
end function
end sub
' User registry accessors for the currently active user
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 return default
if value = invalid then return default
return value
end function
function set_user_setting(key, value)
if get_setting("active_user") = invalid then return invalid
sub set_user_setting(key, value)
if get_setting("active_user") = invalid then return
registry_write(key, value, get_setting("active_user"))
end function
end sub
function unset_user_setting(key)
if get_setting("active_user") = invalid then return invalid
sub unset_user_setting(key)
if get_setting("active_user") = invalid then return
registry_delete(key, get_setting("active_user"))
end function
end sub

View File

@ -21,7 +21,7 @@ function getDeviceProfile() as object
'Check if 5.1 Audio Output connected
maxAudioChannels = 2
di = CreateObject("roDeviceInfo")
if di.GetAudioOutputChannel() = "5.1 surround" then
if di.GetAudioOutputChannel() = "5.1 surround"
maxAudioChannels = 6
end if
@ -155,51 +155,51 @@ function GetDirectPlayProfiles() as object
end if
' Check for supported Audio
if di.CanDecodeAudio({ Codec: "ac3"}).result then
if di.CanDecodeAudio({ Codec: "ac3"}).result
mkvAudio = mkvAudio + ",ac3"
mp4Audio = mp4Audio + ",ac3"
audio = audio + ",ac3"
end if
if di.CanDecodeAudio({ Codec: "wma"}).result then
if di.CanDecodeAudio({ Codec: "wma"}).result
audio = audio + ",wma"
end if
if di.CanDecodeAudio({ Codec: "flac"}).result then
if di.CanDecodeAudio({ Codec: "flac"}).result
mkvAudio = mkvAudio + ",flac"
audio = audio + ",flac"
end if
if di.CanDecodeAudio({ Codec: "alac"}).result then
if di.CanDecodeAudio({ Codec: "alac"}).result
mkvAudio = mkvAudio + ",alac"
mp4Audio = mp4Audio + ",alac"
audio = audio + ",alac"
end if
if di.CanDecodeAudio({ Codec: "aac"}).result then
if di.CanDecodeAudio({ Codec: "aac"}).result
mkvAudio = mkvAudio + ",aac"
mp4Audio = mp4Audio + ",aac"
audio = audio + ",aac"
end if
if di.CanDecodeAudio({ Codec: "opus"}).result then
if di.CanDecodeAudio({ Codec: "opus"}).result
mkvAudio = mkvAudio + ",opus"
end if
if di.CanDecodeAudio({ Codec: "dts"}).result then
if di.CanDecodeAudio({ Codec: "dts"}).result
mkvAudio = mkvAudio + ",dts"
audio = audio + ",dts"
end if
if di.CanDecodeAudio({ Codec: "wmapro"}).result then
if di.CanDecodeAudio({ Codec: "wmapro"}).result
audio = audio + ",wmapro"
end if
if di.CanDecodeAudio({ Codec: "vorbis"}).result then
if di.CanDecodeAudio({ Codec: "vorbis"}).result
mkvAudio = mkvAudio + ",vorbis"
end if
if di.CanDecodeAudio({ Codec: "eac3"}).result then
if di.CanDecodeAudio({ Codec: "eac3"}).result
mkvAudio = mkvAudio + ",eac3"
end if

View File

@ -1,15 +1,15 @@
function initGlobal()
sub initGlobal()
if m.globals = invalid
m.globals = CreateObject("roAssociativeArray")
end if
end function
end sub
function getGlobal(key="" as String) as Dynamic
initGlobal()
return m.globals[key]
end function
function setGlobal(key="" as String, value=invalid as Dynamic)
sub setGlobal(key="" as String, value=invalid as Dynamic)
initGlobal()
m.globals[key] = value
end function
end sub

View File

@ -16,7 +16,7 @@ end function
function getButton(msg, subnode = "buttons" as string) as object
buttons = msg.getRoSGNode().findNode(subnode)
if buttons = invalid return invalid
if buttons = invalid then return invalid
active_button = buttons.focusedChild
return active_button
end function
@ -46,7 +46,7 @@ function formatTime(time) as string
hours = time.getHours()
minHourDigits = 1
di = CreateObject("roDeviceInfo")
if di.GetClockFormat() = "12h" then
if di.GetClockFormat() = "12h"
meridian = "AM"
if hours = 0
hours = 12
@ -70,7 +70,7 @@ end function
function div_ceiling(a as integer, b as integer) as integer
if a < b then return 1
if int(a/b) = a/b then
if int(a/b) = a/b
return a/b
end if
return a/b + 1
@ -80,7 +80,7 @@ end function
function get_dialog_result(dialog, port)
while dialog <> invalid
msg = wait(0, port)
if isNodeEvent(msg, "backPressed") then
if isNodeEvent(msg, "backPressed")
return -1
else if isNodeEvent(msg, "itemSelected")
return dialog.findNode("optionList").itemSelected
@ -93,7 +93,7 @@ end function
function lastFocusedChild(obj as object) as object
child = obj
for i = 0 to obj.getChildCount()
if obj.focusedChild <> invalid then
if obj.focusedChild <> invalid
child = child.focusedChild
end if
end for
@ -101,14 +101,13 @@ function lastFocusedChild(obj as object) as object
end function
function show_dialog(message as string, options = [], defaultSelection = 0) as integer
group = m.scene.focusedChild
lastFocus = lastFocusedChild(m.scene)
'We want to handle backPressed instead of the main loop
m.scene.unobserveField("backPressed")
dialog = createObject("roSGNode", "JFMessageDialog")
if options.count() then dialog.options = options
if message.len() > 0 then
if message.len() > 0
reg = CreateObject("roFontRegistry")
font = reg.GetDefaultFont()
dialog.fontHeight = font.GetOneLineHeight()
@ -116,7 +115,7 @@ function show_dialog(message as string, options = [], defaultSelection = 0) as i
dialog.message = message
end if
if defaultSelection > 0 then
if defaultSelection > 0
dialog.findNode("optionList").jumpToItem = defaultSelection
end if