Merge pull request #459 from neilsb/add-brightscript-linter
Add brightscript linter to CI pipeline
This commit is contained in:
commit
09a1d87283
|
@ -6,5 +6,6 @@
|
|||
"images/**/*.*",
|
||||
"resources/**/*.*",
|
||||
"locale/**/*.*"
|
||||
]
|
||||
],
|
||||
"plugins": [ "@rokucommunity/bslint" ]
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
962
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user