commit
6bab4b719e
|
@ -1,6 +1,7 @@
|
||||||
sub init()
|
sub init()
|
||||||
|
|
||||||
m.options = m.top.findNode("options")
|
m.options = m.top.findNode("options")
|
||||||
|
m.tvGuide = invalid
|
||||||
|
|
||||||
m.itemGrid = m.top.findNode("itemGrid")
|
m.itemGrid = m.top.findNode("itemGrid")
|
||||||
m.backdrop = m.top.findNode("backdrop")
|
m.backdrop = m.top.findNode("backdrop")
|
||||||
|
@ -59,6 +60,11 @@ sub loadInitialItems()
|
||||||
|
|
||||||
'For LiveTV, we want to "Fit" the item images, not zoom
|
'For LiveTV, we want to "Fit" the item images, not zoom
|
||||||
m.top.imageDisplayMode = "scaleToFit"
|
m.top.imageDisplayMode = "scaleToFit"
|
||||||
|
|
||||||
|
if get_user_setting("display.livetv.landing") = "guide" then
|
||||||
|
showTvGuid()
|
||||||
|
end if
|
||||||
|
|
||||||
else if m.top.parentItem.collectionType = "CollectionFolder" then
|
else if m.top.parentItem.collectionType = "CollectionFolder" then
|
||||||
' Non-recursive, to not show subfolder contents
|
' Non-recursive, to not show subfolder contents
|
||||||
m.loadItemsTask.recursive = false
|
m.loadItemsTask.recursive = false
|
||||||
|
@ -78,6 +84,7 @@ end sub
|
||||||
sub SetUpOptions()
|
sub SetUpOptions()
|
||||||
|
|
||||||
options = {}
|
options = {}
|
||||||
|
options.filter = []
|
||||||
|
|
||||||
'Movies
|
'Movies
|
||||||
if m.top.parentItem.collectionType = "movies" then
|
if m.top.parentItem.collectionType = "movies" then
|
||||||
|
@ -113,13 +120,18 @@ sub SetUpOptions()
|
||||||
options.filter = []
|
options.filter = []
|
||||||
'Live TV
|
'Live TV
|
||||||
else if m.top.parentItem.collectionType = "livetv" then
|
else if m.top.parentItem.collectionType = "livetv" then
|
||||||
options.views = [{"Title": tr("Live TV"), "Name": "livetv" }]
|
options.views = [
|
||||||
|
{"Title": tr("Channels"), "Name": "livetv" },
|
||||||
|
{"Title": tr("TV Guide"), "Name": "tvGuide", "Selected": get_user_setting("display.livetv.landing") = "guide" }
|
||||||
|
]
|
||||||
options.sort = [
|
options.sort = [
|
||||||
{ "Title": tr("TITLE"), "Name": "SortName" }
|
{ "Title": tr("TITLE"), "Name": "SortName" }
|
||||||
]
|
]
|
||||||
options.filter = []
|
options.filter = []
|
||||||
else
|
else
|
||||||
options.views = [{ "Title": tr("Default"), "Name": "default" }]
|
options.views = [
|
||||||
|
{"Title": tr("Default"), "Name": "default" }
|
||||||
|
]
|
||||||
options.sort = [
|
options.sort = [
|
||||||
{ "Title": tr("TITLE"), "Name": "SortName" }
|
{ "Title": tr("TITLE"), "Name": "SortName" }
|
||||||
]
|
]
|
||||||
|
@ -259,6 +271,15 @@ end sub
|
||||||
'
|
'
|
||||||
'Check if options updated and any reloading required
|
'Check if options updated and any reloading required
|
||||||
sub optionsClosed()
|
sub optionsClosed()
|
||||||
|
|
||||||
|
if (m.options.view = "tvGuide") then
|
||||||
|
showTVGuid()
|
||||||
|
return
|
||||||
|
else if m.tvGuide <> invalid then
|
||||||
|
' Try to hide the TV Guide
|
||||||
|
m.top.removeChild(m.tvGuide)
|
||||||
|
end if
|
||||||
|
|
||||||
reload = false
|
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 then
|
||||||
m.sortField = m.options.sortField
|
m.sortField = m.options.sortField
|
||||||
|
@ -279,6 +300,24 @@ sub optionsClosed()
|
||||||
m.itemGrid.setFocus(true)
|
m.itemGrid.setFocus(true)
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
sub showTVGuid()
|
||||||
|
m.top.signalBeacon("EPGLaunchInitiate") ' Required Roku Performance monitoring
|
||||||
|
if m.tvGuide = invalid then
|
||||||
|
m.tvGuide = createObject("roSGNode", "Schedule")
|
||||||
|
endif
|
||||||
|
m.tvGuide.observeField("watchChannel", "onChannelSelected")
|
||||||
|
m.top.appendChild(m.tvGuide)
|
||||||
|
m.tvGuide.lastFocus.setFocus(true)
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub onChannelSelected(msg)
|
||||||
|
node = msg.getRoSGNode()
|
||||||
|
m.top.lastFocus = lastFocusedChild(node)
|
||||||
|
if node.watchChannel <> invalid then
|
||||||
|
' 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
|
||||||
|
end sub
|
||||||
|
|
||||||
function onKeyEvent(key as string, press as boolean) as boolean
|
function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
|
|
||||||
|
@ -287,9 +326,11 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
if key = "options"
|
if key = "options"
|
||||||
if m.options.visible = true then
|
if m.options.visible = true then
|
||||||
m.options.visible = false
|
m.options.visible = false
|
||||||
|
m.top.removeChild(m.options)
|
||||||
optionsClosed()
|
optionsClosed()
|
||||||
else
|
else
|
||||||
m.options.visible = true
|
m.options.visible = true
|
||||||
|
m.top.appendChild(m.options)
|
||||||
m.options.setFocus(true)
|
m.options.setFocus(true)
|
||||||
end if
|
end if
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -35,5 +35,7 @@
|
||||||
<field id="selectedItem" type="node" alwaysNotify="true" />
|
<field id="selectedItem" type="node" alwaysNotify="true" />
|
||||||
<field id="imageDisplayMode" type="string" value="scaleToZoom" />
|
<field id="imageDisplayMode" type="string" value="scaleToZoom" />
|
||||||
</interface>
|
</interface>
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
<script type="text/brightscript" uri="ItemGrid2.brs" />
|
<script type="text/brightscript" uri="ItemGrid2.brs" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -39,7 +39,7 @@ sub optionsSet()
|
||||||
entry = viewContent.CreateChild("ContentNode")
|
entry = viewContent.CreateChild("ContentNode")
|
||||||
entry.title = view.Title
|
entry.title = view.Title
|
||||||
m.viewNames.push(view.Name)
|
m.viewNames.push(view.Name)
|
||||||
if view.selected <> invalid and view.selected = true then
|
if (view.selected <> invalid and view.selected = true) or viewContent.Name = m.top.view then
|
||||||
selectedViewIndex = index
|
selectedViewIndex = index
|
||||||
end if
|
end if
|
||||||
index = index + 1
|
index = index + 1
|
||||||
|
@ -136,6 +136,12 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
return true
|
return true
|
||||||
else if key = "OK"
|
else if key = "OK"
|
||||||
if(m.menus[m.selectedItem].isInFocusChain()) then
|
if(m.menus[m.selectedItem].isInFocusChain()) then
|
||||||
|
' Handle View Screen
|
||||||
|
if(m.selectedItem = 0) then
|
||||||
|
m.selectedViewIndex = m.menus[0].itemSelected
|
||||||
|
m.top.view = m.viewNames[m.selectedViewIndex]
|
||||||
|
end if
|
||||||
|
|
||||||
' Handle Sort screen
|
' Handle Sort screen
|
||||||
if(m.selectedItem = 1) then
|
if(m.selectedItem = 1) then
|
||||||
if m.menus[1].itemSelected <> m.selectedSortIndex then
|
if m.menus[1].itemSelected <> m.selectedSortIndex then
|
||||||
|
|
|
@ -2,7 +2,7 @@ sub setFields()
|
||||||
json = m.top.json
|
json = m.top.json
|
||||||
|
|
||||||
m.top.id = json.id
|
m.top.id = json.id
|
||||||
m.top.Title = json.name
|
m.top.title = json.name
|
||||||
m.top.live = true
|
m.top.live = true
|
||||||
m.top.Type = "TvChannel"
|
m.top.Type = "TvChannel"
|
||||||
setPoster()
|
setPoster()
|
||||||
|
@ -11,7 +11,7 @@ end sub
|
||||||
sub setPoster()
|
sub setPoster()
|
||||||
if m.top.image <> invalid
|
if m.top.image <> invalid
|
||||||
m.top.posterURL = m.top.image.url
|
m.top.posterURL = m.top.image.url
|
||||||
else if m.top.json.ImageTags.Primary <> invalid then
|
else if m.top.json.ImageTags <> invalid and m.top.json.ImageTags.Primary <> invalid then
|
||||||
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
|
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
|
||||||
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
|
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
|
||||||
end if
|
end if
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
<component name="ChannelData" extends="JFContentItem">
|
<component name="ChannelData" extends="JFContentItem">
|
||||||
<interface>
|
<interface>
|
||||||
<field id="channelID" type="string" />
|
<field id="channelID" type="string" />
|
||||||
<field id="Title" type="string" />
|
|
||||||
</interface>
|
</interface>
|
||||||
<script type="text/brightscript" uri="ChannelData.brs" />
|
<script type="text/brightscript" uri="ChannelData.brs" />
|
||||||
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
|
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
|
||||||
|
|
|
@ -22,7 +22,7 @@ sub setData()
|
||||||
|
|
||||||
' Add Icon URLs for display if there is no Poster
|
' Add Icon URLs for display if there is no Poster
|
||||||
if datum.CollectionType = "livetv" then
|
if datum.CollectionType = "livetv" then
|
||||||
m.top.iconUrl = "pkg:/images/baseline_live_tv_white_48dp.png"
|
m.top.iconUrl = "pkg:/images/media_type_icons/live_tv_white.png"
|
||||||
end if
|
end if
|
||||||
|
|
||||||
else if datum.type = "Episode" then
|
else if datum.type = "Episode" then
|
||||||
|
@ -142,7 +142,7 @@ sub setData()
|
||||||
params = { "Tag" : datum.ImageTags.Primary, "maxHeight" : 261, "maxWidth" : 464 }
|
params = { "Tag" : datum.ImageTags.Primary, "maxHeight" : 261, "maxWidth" : 464 }
|
||||||
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
|
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
|
||||||
m.top.widePosterUrl = m.top.thumbnailURL
|
m.top.widePosterUrl = m.top.thumbnailURL
|
||||||
m.top.iconUrl = "pkg:/images/baseline_live_tv_white_48dp.png"
|
m.top.iconUrl = "pkg:/images/media_type_icons/live_tv_white.png"
|
||||||
end if
|
end if
|
||||||
|
|
||||||
end sub
|
end sub
|
43
components/data/ScheduleProgramData.brs
Normal file
43
components/data/ScheduleProgramData.brs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
sub setFields()
|
||||||
|
json = m.top.json
|
||||||
|
|
||||||
|
startDate = createObject("roDateTime")
|
||||||
|
endDate = createObject("roDateTime")
|
||||||
|
startDate.FromISO8601String(json.StartDate)
|
||||||
|
endDate.FromISO8601String(json.EndDate)
|
||||||
|
|
||||||
|
m.top.Title = json.Name
|
||||||
|
m.top.PlayStart = startDate.AsSeconds()
|
||||||
|
m.top.PlayDuration = endDate.AsSeconds() - m.top.PlayStart
|
||||||
|
m.top.Id = json.Id
|
||||||
|
m.top.Description = json.overview
|
||||||
|
m.top.EpisodeTitle = json.EpisodeTitle
|
||||||
|
m.top.isLive = json.isLive
|
||||||
|
m.top.isRepeat = json.isRepeat
|
||||||
|
m.top.startDate = json.startDate
|
||||||
|
m.top.endDate = json.endDate
|
||||||
|
m.top.channelId = json.channelId
|
||||||
|
|
||||||
|
if json.IsSeries <> invalid and json.IsSeries = true then
|
||||||
|
if json.IndexNumber <> invalid
|
||||||
|
m.top.episodeNumber = json.IndexNumber
|
||||||
|
end if
|
||||||
|
|
||||||
|
if json.ParentIndexNumber <> invalid
|
||||||
|
m.top.seasonNumber = json.ParentIndexNumber
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
|
||||||
|
setPoster()
|
||||||
|
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.Thumb <> invalid then
|
||||||
|
imgParams = { "maxHeight": 500, "maxWidth": 500, "Tag" : m.top.json.ImageTags.Thumb }
|
||||||
|
m.top.posterURL = ImageURL(m.top.json.id, "Thumb", imgParams)
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
end sub
|
22
components/data/ScheduleProgramData.xml
Normal file
22
components/data/ScheduleProgramData.xml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<component name="ScheduleProgramData" extends="JFContentItem">
|
||||||
|
<interface>
|
||||||
|
<field id="fullyLoaded" type="boolean" value="false" />
|
||||||
|
<field id="channelIndex" type="integer" />
|
||||||
|
<field id="programIndex" type="integer" />
|
||||||
|
<field id="episodeTitle" type="string" />
|
||||||
|
<field id="isLive" type="boolean" value="false" />
|
||||||
|
<field id="isRepeat" type="boolean" value="false" />
|
||||||
|
<field id="startDate" type="string" />
|
||||||
|
<field id="endDate" type="string" />
|
||||||
|
<field id="seasonNumber" type="integer" value="-1" />
|
||||||
|
<field id="episodeNumber" type="integer" value="-1" />
|
||||||
|
<field id="channelId" type="string" />
|
||||||
|
<field id="channelLogoUri" type="string" />
|
||||||
|
<field id="channelName" type="string" />
|
||||||
|
</interface>
|
||||||
|
<script type="text/brightscript" uri="ScheduleProgramData.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
</component>
|
34
components/liveTv/LoadChannelsTask.brs
Normal file
34
components/liveTv/LoadChannelsTask.brs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
sub init()
|
||||||
|
m.top.functionName = "loadChannels"
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub loadChannels()
|
||||||
|
|
||||||
|
results = []
|
||||||
|
|
||||||
|
params = {
|
||||||
|
UserId: get_setting("active_user")
|
||||||
|
limit: m.top.limit,
|
||||||
|
StartIndex: m.top.startIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
url = "LiveTv/Channels"
|
||||||
|
|
||||||
|
resp = APIRequest(url, params)
|
||||||
|
data = getJson(resp)
|
||||||
|
|
||||||
|
if data.TotalRecordCount = invalid then
|
||||||
|
m.top.channels = results
|
||||||
|
return
|
||||||
|
end if
|
||||||
|
|
||||||
|
|
||||||
|
for each item in data.Items
|
||||||
|
channel = createObject("roSGNode", "ChannelData")
|
||||||
|
channel.json = item
|
||||||
|
results.push(channel)
|
||||||
|
end for
|
||||||
|
|
||||||
|
m.top.channels = results
|
||||||
|
|
||||||
|
end sub
|
15
components/liveTv/LoadChannelsTask.xml
Normal file
15
components/liveTv/LoadChannelsTask.xml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<component name="LoadChannelsTask" extends="Task">
|
||||||
|
<interface>
|
||||||
|
<field id="limit" type="integer" value="500" />
|
||||||
|
<field id="startIndex" type="integer" value="0" />
|
||||||
|
|
||||||
|
<!-- Total records available from server-->
|
||||||
|
<field id="channels" type="array" />
|
||||||
|
</interface>
|
||||||
|
<script type="text/brightscript" uri="LoadChannelsTask.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
<!-- <script type="text/brightscript" uri="pkg:/source/api/Image.brs" /> -->
|
||||||
|
</component>
|
32
components/liveTv/LoadProgramDetailsTask.brs
Normal file
32
components/liveTv/LoadProgramDetailsTask.brs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
sub init()
|
||||||
|
m.top.functionName = "loadProgramDetails"
|
||||||
|
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub loadProgramDetails()
|
||||||
|
|
||||||
|
channelIndex = m.top.ChannelIndex
|
||||||
|
programIndex = m.top.ProgramIndex
|
||||||
|
|
||||||
|
params = {
|
||||||
|
UserId: get_setting("active_user"),
|
||||||
|
}
|
||||||
|
|
||||||
|
url = Substitute("LiveTv/Programs/{0}", m.top.programId)
|
||||||
|
|
||||||
|
resp = APIRequest(url, params)
|
||||||
|
data = getJson(resp)
|
||||||
|
|
||||||
|
if data = invalid then
|
||||||
|
m.top.programDetails = {}
|
||||||
|
return
|
||||||
|
end if
|
||||||
|
|
||||||
|
program = createObject("roSGNode", "ScheduleProgramData")
|
||||||
|
program.json = data
|
||||||
|
program.channelIndex = ChannelIndex
|
||||||
|
program.programIndex = ProgramIndex
|
||||||
|
program.fullyLoaded = true
|
||||||
|
m.top.programDetails = program
|
||||||
|
|
||||||
|
end sub
|
13
components/liveTv/LoadProgramDetailsTask.xml
Normal file
13
components/liveTv/LoadProgramDetailsTask.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<component name="LoadProgramDetailsTask" extends="Task">
|
||||||
|
<interface>
|
||||||
|
<field id="programId" type="string" />
|
||||||
|
<field id="ChannelIndex" type="integer" />
|
||||||
|
<field id="ProgramIndex" type="integer" />
|
||||||
|
<field id="programDetails" type="node" />
|
||||||
|
</interface>
|
||||||
|
<script type="text/brightscript" uri="LoadProgramDetailsTask.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
</component>
|
41
components/liveTv/LoadSheduleTask.brs
Normal file
41
components/liveTv/LoadSheduleTask.brs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
sub init()
|
||||||
|
m.top.functionName = "loadSchedule"
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub loadSchedule()
|
||||||
|
|
||||||
|
results = []
|
||||||
|
|
||||||
|
params = {
|
||||||
|
UserId: get_setting("active_user"),
|
||||||
|
SortBy: "startDate",
|
||||||
|
EnableImages: false
|
||||||
|
EnableTotalRecordCount: false,
|
||||||
|
EnableUserData: false
|
||||||
|
channelIds: m.top.channelIds
|
||||||
|
MaxStartDate: m.top.endTime,
|
||||||
|
MinEndDate: m.top.startTime
|
||||||
|
}
|
||||||
|
|
||||||
|
url = "LiveTv/Programs"
|
||||||
|
|
||||||
|
resp = APIRequest(url)
|
||||||
|
data = postJson(resp, FormatJson(params))
|
||||||
|
|
||||||
|
if data = invalid then
|
||||||
|
m.top.schedule = results
|
||||||
|
return
|
||||||
|
end if
|
||||||
|
|
||||||
|
results = []
|
||||||
|
|
||||||
|
for each item in data.Items
|
||||||
|
program = createObject("roSGNode", "ScheduleProgramData")
|
||||||
|
program.json = item
|
||||||
|
results.push(program)
|
||||||
|
end for
|
||||||
|
|
||||||
|
|
||||||
|
m.top.schedule = results
|
||||||
|
|
||||||
|
end sub
|
13
components/liveTv/LoadSheduleTask.xml
Normal file
13
components/liveTv/LoadSheduleTask.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<component name="LoadScheduleTask" extends="Task">
|
||||||
|
<interface>
|
||||||
|
<field id="startTime" type="string" />
|
||||||
|
<field id="endTime" type="string" />
|
||||||
|
<field id="channelIds" type="string" />
|
||||||
|
<field id="schedule" type="array" />
|
||||||
|
</interface>
|
||||||
|
<script type="text/brightscript" uri="LoadSheduleTask.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
</component>
|
230
components/liveTv/ProgramDetails.brs
Normal file
230
components/liveTv/ProgramDetails.brs
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
sub init()
|
||||||
|
|
||||||
|
' Max "Overview" lines to show in Preview and Detail
|
||||||
|
m.maxPreviewLines = 5
|
||||||
|
m.maxDetailLines = 14
|
||||||
|
|
||||||
|
m.detailsView = m.top.findNode("detailsView")
|
||||||
|
m.noInfoView = m.top.findNode("noInformation")
|
||||||
|
|
||||||
|
m.programName = m.top.findNode("programName")
|
||||||
|
m.episodeTitle = m.top.findNode("episodeTitle")
|
||||||
|
m.episodeNumber = m.top.findNode("episodeNumber")
|
||||||
|
m.overview = m.top.findNode("overview")
|
||||||
|
|
||||||
|
m.episodeDetailsGroup = m.top.findNode("episodeDetailsGroup")
|
||||||
|
m.isLiveGroup = m.top.findNode("isLive")
|
||||||
|
m.isRepeatGroup = m.top.findNode("isRepeat")
|
||||||
|
|
||||||
|
m.broadcastDetails = m.top.findNode("broadcastDetails")
|
||||||
|
m.duration = m.top.findNode("duration")
|
||||||
|
m.channelName = m.top.findNode("channelName")
|
||||||
|
m.image = m.top.findNode("image")
|
||||||
|
|
||||||
|
m.focusAnimationOpacity = m.top.findNode("focusAnimationOpacity")
|
||||||
|
m.focusAnimation = m.top.findNode("focusAnimation")
|
||||||
|
|
||||||
|
m.viewChannelButton = m.top.findNode("viewChannelButton")
|
||||||
|
|
||||||
|
m.focusAnimation.observeField("state", "onAnimationComplete")
|
||||||
|
|
||||||
|
setupLabels()
|
||||||
|
end sub
|
||||||
|
|
||||||
|
|
||||||
|
' Set up Live and Repeat label sizes
|
||||||
|
sub setupLabels()
|
||||||
|
|
||||||
|
boundingRect = m.top.findNode("isLiveText").boundingRect()
|
||||||
|
isLiveBackground = m.top.findNode("isLiveBackground")
|
||||||
|
isLiveBackground.width = boundingRect.width + 16
|
||||||
|
isLiveBackground.height = boundingRect.height + 8
|
||||||
|
m.episodeDetailsGroup.removeChildIndex(0)
|
||||||
|
|
||||||
|
boundingRect = m.top.findNode("isRepeatText").boundingRect()
|
||||||
|
isRepeatBackground = m.top.findNode("isRepeatBackground")
|
||||||
|
isRepeatBackground.width = boundingRect.width + 16
|
||||||
|
isRepeatBackground.height = boundingRect.height + 8
|
||||||
|
m.episodeDetailsGroup.removeChildIndex(0)
|
||||||
|
|
||||||
|
boundingRect = m.viewChannelButton.boundingRect()
|
||||||
|
buttonBackground = m.top.findNode("viewChannelButtonBackground")
|
||||||
|
buttonBackground.width = boundingRect.width + 20
|
||||||
|
buttonBackground.height = boundingRect.height + 20
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub channelUpdated()
|
||||||
|
if m.top.channel = invalid
|
||||||
|
m.top.findNode("noInfoChannelName").text = ""
|
||||||
|
m.channelName.text = ""
|
||||||
|
else
|
||||||
|
m.top.findNode("noInfoChannelName").text = m.top.channel.Title
|
||||||
|
m.channelName.text= m.top.channel.Title
|
||||||
|
if m.top.programDetails = invalid then
|
||||||
|
m.image.uri = m.top.channel.posterURL
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub programUpdated()
|
||||||
|
|
||||||
|
m.top.watchSelectedChannel = false
|
||||||
|
m.overview.maxLines = m.maxDetailLines
|
||||||
|
prog = m.top.programDetails
|
||||||
|
|
||||||
|
' If no program selected, hide details view
|
||||||
|
if prog = invalid then
|
||||||
|
channelUpdated()
|
||||||
|
m.detailsView.visible = "false"
|
||||||
|
m.noInfoView.visible = "true"
|
||||||
|
return
|
||||||
|
end if
|
||||||
|
|
||||||
|
m.programName.text = prog.Title
|
||||||
|
m.overview.text = prog.description
|
||||||
|
|
||||||
|
m.episodeDetailsGroup.removeChildrenIndex(m.episodeDetailsGroup.getChildCount(), 0)
|
||||||
|
|
||||||
|
if prog.isLive then
|
||||||
|
m.episodeDetailsGroup.appendChild(m.isLiveGroup)
|
||||||
|
else if prog.isRepeat then
|
||||||
|
m.episodeDetailsGroup.appendChild(m.isRepeatGroup)
|
||||||
|
end if
|
||||||
|
|
||||||
|
' Episode Number
|
||||||
|
if prog.seasonNumber > 0 and prog.episodeNumber > 0 then
|
||||||
|
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
|
||||||
|
m.episodeTitle.text = prog.episodeTitle
|
||||||
|
m.episodeTitle.visible = true
|
||||||
|
m.episodeDetailsGroup.appendChild(m.episodeTitle)
|
||||||
|
end if
|
||||||
|
|
||||||
|
m.duration.text = getDurationStringFromSeconds(prog.PlayDuration)
|
||||||
|
|
||||||
|
' Calculate Broadcast Details
|
||||||
|
now = createObject("roDateTime")
|
||||||
|
startDate = createObject("roDateTime")
|
||||||
|
endDate = createObject("roDateTime")
|
||||||
|
startDate.FromISO8601String(prog.StartDate)
|
||||||
|
endDate.FromISO8601String(prog.EndDate)
|
||||||
|
|
||||||
|
day = getRelativeDayName(startDate)
|
||||||
|
|
||||||
|
if startDate.AsSeconds() < now.AsSeconds() and endDate.AsSeconds() > now.AsSeconds() then
|
||||||
|
if day = "today" then
|
||||||
|
m.broadcastDetails.text = tr("Started at") + " " + formatTime(startDate)
|
||||||
|
else
|
||||||
|
m.broadcastDetails.text = tr("Started") + " " + tr(day) + ", " + formatTime(startDate)
|
||||||
|
end if
|
||||||
|
else if startDate.AsSeconds() > now.AsSeconds()
|
||||||
|
if day = "today" then
|
||||||
|
m.broadcastDetails.text = tr("Starts at") + " " + formatTime(startDate)
|
||||||
|
else
|
||||||
|
m.broadcastDetails.text = tr("Starts") + " " + tr(day) + ", " + formatTime(startDate)
|
||||||
|
end if
|
||||||
|
else
|
||||||
|
if day = "today" then
|
||||||
|
m.broadcastDetails.text = tr("Ended at") + " " + formatTime(endDate)
|
||||||
|
else
|
||||||
|
m.broadcastDetails.text = tr("Ended") + " " + tr(day) + ", " + formatTime(endDate)
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
|
||||||
|
m.image.uri = prog.PosterURL
|
||||||
|
|
||||||
|
|
||||||
|
m.detailsView.visible = "true"
|
||||||
|
m.noInfoView.visible = "false"
|
||||||
|
|
||||||
|
m.top.height = m.detailsView.boundingRect().height
|
||||||
|
m.overview.maxLines = m.maxPreviewLines
|
||||||
|
end sub
|
||||||
|
|
||||||
|
'
|
||||||
|
' Get relative date name for a date (yesterday, today, tomorrow, or otherwise weekday name )
|
||||||
|
function getRelativeDayName(date) as string
|
||||||
|
|
||||||
|
now = createObject("roDateTime")
|
||||||
|
|
||||||
|
' Check for Today
|
||||||
|
if now.AsDateString("short-date-dashes") = date.AsDateString("short-date-dashes") then
|
||||||
|
return "today"
|
||||||
|
end if
|
||||||
|
|
||||||
|
' Check for Yesterday
|
||||||
|
todayMidnight = now.AsSeconds() - (now.AsSeconds() MOD 86400)
|
||||||
|
dateMidnight = date.AsSeconds() - (date.AsSeconds() MOD 86400)
|
||||||
|
|
||||||
|
if todayMidnight - dateMidnight = 86400 then
|
||||||
|
return "yesterday"
|
||||||
|
end if
|
||||||
|
|
||||||
|
if dateMidnight - todayMidnight = 86400 then
|
||||||
|
return "tomorrow"
|
||||||
|
end if
|
||||||
|
|
||||||
|
return date.GetWeekday()
|
||||||
|
|
||||||
|
end function
|
||||||
|
|
||||||
|
'
|
||||||
|
' Get program duration string (e.g. 1h 20m)
|
||||||
|
function getDurationStringFromSeconds(seconds) as string
|
||||||
|
|
||||||
|
hours = 0
|
||||||
|
minutes = seconds / 60.0
|
||||||
|
|
||||||
|
if minutes > 60 then
|
||||||
|
hours = (minutes - (minutes MOD 60)) / 60
|
||||||
|
minutes = minutes MOD 60
|
||||||
|
end if
|
||||||
|
|
||||||
|
if hours > 0 then
|
||||||
|
return "%1h %2m".Replace("%1", StrI(hours).trim()).Replace("%2", StrI(minutes).trim())
|
||||||
|
else
|
||||||
|
return "%1m".Replace("%1", StrI(minutes).trim())
|
||||||
|
end if
|
||||||
|
|
||||||
|
end function
|
||||||
|
|
||||||
|
'
|
||||||
|
' Show view channel button when item has Focus
|
||||||
|
sub focusChanged()
|
||||||
|
if m.top.hasFocus = true then
|
||||||
|
m.overview.maxLines = m.maxDetailLines
|
||||||
|
m.focusAnimationOpacity.keyValue = [0, 1]
|
||||||
|
else
|
||||||
|
m.top.watchSelectedChannel = false
|
||||||
|
m.focusAnimationOpacity.keyValue = [1, 0]
|
||||||
|
end if
|
||||||
|
|
||||||
|
m.focusAnimation.control = "start"
|
||||||
|
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub onAnimationComplete()
|
||||||
|
if m.focusAnimation.state = "stopped" and m.top.hasFocus = false then
|
||||||
|
m.overview.maxLines = m.maxPreviewLines
|
||||||
|
end if
|
||||||
|
end sub
|
||||||
|
|
||||||
|
function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
|
if not press then return false
|
||||||
|
|
||||||
|
if key = "OK" then
|
||||||
|
m.top.watchSelectedChannel = true
|
||||||
|
return true
|
||||||
|
end if
|
||||||
|
|
||||||
|
if key = "left" or key = "right" or key = "up" or key = "down" then
|
||||||
|
return true
|
||||||
|
end if
|
||||||
|
|
||||||
|
return false
|
||||||
|
end function
|
||||||
|
|
65
components/liveTv/ProgramDetails.xml
Normal file
65
components/liveTv/ProgramDetails.xml
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<component name="ProgramDetails" extends="JFGroup">
|
||||||
|
<children>
|
||||||
|
|
||||||
|
<!-- Selected Item Details -->
|
||||||
|
<maskGroup id="backgroundMask" maskUri="pkg:/images/backgroundmask.png" translation="[1208, 127]" maskSize="[712,400]">
|
||||||
|
<Poster id="image" height="400" width="712" loadDisplayMode="scaleToFit" />
|
||||||
|
</maskGroup>
|
||||||
|
|
||||||
|
<Group id="detailsView" visible="false">
|
||||||
|
|
||||||
|
<Group translation = "[ 96, 160 ]">
|
||||||
|
<LayoutGroup itemSpacings="[4,20, 20, 20, 40]">
|
||||||
|
<Label id="programName" font="font:LargeBoldSystemFont" />
|
||||||
|
|
||||||
|
<LayoutGroup id="episodeDetailsGroup" layoutDirection="horiz" itemSpacings="[10]">
|
||||||
|
<Group id="isLive">
|
||||||
|
<Poster id="isLiveBackground" uri="pkg:/images/white.9.png" blendColor="#FF0000" />
|
||||||
|
<Label id="isLiveText" text="Live" font="font:SmallestBoldSystemFont" translation="[8,4]" />
|
||||||
|
</Group>
|
||||||
|
<Group id="isRepeat">
|
||||||
|
<Poster id="isRepeatBackground" uri="pkg:/images/white.9.png" blendColor="#009688" />
|
||||||
|
<Label id="isRepeatText" text="Repeat" font="font:SmallestBoldSystemFont" translation="[8,4]" />
|
||||||
|
</Group>
|
||||||
|
<Label id="episodeNumber" font="font:SmallSystemFont" />
|
||||||
|
<Label id="episodeTitle" font="font:SmallSystemFont" />
|
||||||
|
</LayoutGroup>
|
||||||
|
|
||||||
|
<LayoutGroup layoutDirection="horiz" itemSpacings="[30]">
|
||||||
|
<Label id="duration" />
|
||||||
|
<Label id="broadcastDetails" />
|
||||||
|
<Label id="channelName" />
|
||||||
|
</LayoutGroup>
|
||||||
|
|
||||||
|
<label id="overview" wrap="true" width="1250" font="font:SmallestSystemFont" />
|
||||||
|
|
||||||
|
<!-- View Channel button -->
|
||||||
|
<Group id="viewChannelButton" opacity="0">
|
||||||
|
<Poster id="viewChannelButtonBackground" uri="pkg:/images/white.9.png" blendColor="#006fab" />
|
||||||
|
<Label text="View Channel" translation="[20,20]" />
|
||||||
|
</Group>
|
||||||
|
|
||||||
|
</LayoutGroup>
|
||||||
|
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<!-- When no schedule information to display -->
|
||||||
|
<LayoutGroup id="noInformation" translation="[96, 300]">
|
||||||
|
<Label id="noInfoChannelName" font="font:LargeBoldSystemFont" />
|
||||||
|
<Label font="font:SmallSystemFont" text="No schedule information" />
|
||||||
|
</LayoutGroup>
|
||||||
|
<Animation id="focusAnimation" duration="0.66" repeat="false" easeFunction="linear" >
|
||||||
|
<FloatFieldInterpolator id="focusAnimationOpacity" key="[0.0, 1]" fieldToInterp="viewChannelButton.opacity" />
|
||||||
|
</Animation>
|
||||||
|
</children>
|
||||||
|
<interface>
|
||||||
|
<field id="WatchSelectedChannel" type="boolean" value="false" />
|
||||||
|
<field id="channel" type="node" onchange="channelUpdated" />
|
||||||
|
<field id="programDetails" type="node" onchange="programUpdated" />
|
||||||
|
<field id="height" type="integer" />
|
||||||
|
<field id="hasFocus" type="boolean" onChange="focusChanged" />
|
||||||
|
</interface>
|
||||||
|
<script type="text/brightscript" uri="ProgramDetails.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
|
||||||
|
</component>
|
189
components/liveTv/schedule.brs
Normal file
189
components/liveTv/schedule.brs
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
sub init()
|
||||||
|
|
||||||
|
m.scheduleGrid = m.top.findNode("scheduleGrid")
|
||||||
|
m.detailsPane = m.top.findNode("detailsPane")
|
||||||
|
|
||||||
|
m.detailsPane.observeField("watchSelectedChannel", "onWatchChannelSelected")
|
||||||
|
|
||||||
|
m.gridStartDate = CreateObject("roDateTime")
|
||||||
|
m.scheduleGrid.contentStartTime = m.gridStartDate.AsSeconds() - 1800
|
||||||
|
m.gridEndDate = createObject("roDateTime")
|
||||||
|
m.gridEndDate.FromSeconds(m.gridStartDate.AsSeconds() + (24 * 60 * 60))
|
||||||
|
|
||||||
|
m.scheduleGrid.observeField("programFocused", "onProgramFocused")
|
||||||
|
m.scheduleGrid.observeField("programSelected", "onProgramSelected")
|
||||||
|
m.scheduleGrid.observeField("leftEdgeTargetTime", "onGridScrolled")
|
||||||
|
m.scheduleGrid.channelInfoWidth = 350
|
||||||
|
|
||||||
|
m.gridMoveAnimation = m.top.findNode("gridMoveAnimation")
|
||||||
|
m.gridMoveAnimationPosition = m.top.findNode("gridMoveAnimationPosition")
|
||||||
|
|
||||||
|
m.LoadChannelsTask = createObject("roSGNode", "LoadChannelsTask")
|
||||||
|
m.LoadChannelsTask.observeField("channels", "onChannelsLoaded")
|
||||||
|
m.LoadChannelsTask.control = "RUN"
|
||||||
|
|
||||||
|
m.top.lastFocus = m.scheduleGrid
|
||||||
|
|
||||||
|
m.channelIndex = {}
|
||||||
|
end sub
|
||||||
|
|
||||||
|
' Initial list of channels loaded
|
||||||
|
sub onChannelsLoaded()
|
||||||
|
gridData = createObject("roSGNode", "ContentNode")
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
channelIdList = ""
|
||||||
|
|
||||||
|
for each item in m.LoadChannelsTask.channels
|
||||||
|
gridData.appendChild(item)
|
||||||
|
m.channelIndex[item.Id] = counter
|
||||||
|
counter = counter + 1
|
||||||
|
channelIdList = channelIdList + item.Id + ","
|
||||||
|
end for
|
||||||
|
|
||||||
|
m.scheduleGrid.content = gridData
|
||||||
|
|
||||||
|
m.LoadScheduleTask = createObject("roSGNode", "LoadScheduleTask")
|
||||||
|
m.LoadScheduleTask.observeField("schedule", "onScheduleLoaded")
|
||||||
|
|
||||||
|
m.LoadScheduleTask.startTime = m.gridStartDate.ToISOString()
|
||||||
|
m.LoadScheduleTask.endTime = m.gridEndDate.ToISOString()
|
||||||
|
m.LoadScheduleTask.channelIds = channelIdList
|
||||||
|
m.LoadScheduleTask.control = "RUN"
|
||||||
|
|
||||||
|
m.LoadProgramDetailsTask = createObject("roSGNode", "LoadProgramDetailsTask")
|
||||||
|
m.LoadProgramDetailsTask.observeField("programDetails", "onProgramDetailsLoaded")
|
||||||
|
|
||||||
|
m.scheduleGrid.setFocus(true)
|
||||||
|
m.top.signalBeacon("EPGLaunchComplete") ' Required Roku Performance monitoring
|
||||||
|
end sub
|
||||||
|
|
||||||
|
' When LoadScheduleTask completes (initial or more data) and we have a schedule to display
|
||||||
|
sub onScheduleLoaded()
|
||||||
|
|
||||||
|
for each item in m.LoadScheduleTask.schedule
|
||||||
|
|
||||||
|
channel = m.scheduleGrid.content.GetChild(m.channelIndex[item.ChannelId])
|
||||||
|
|
||||||
|
if channel.PosterUrl <> "" then
|
||||||
|
item.channelLogoUri = channel.PosterUrl
|
||||||
|
end if
|
||||||
|
if channel.Title <> "" then
|
||||||
|
item.channelName = channel.Title
|
||||||
|
end if
|
||||||
|
|
||||||
|
channel.appendChild(item)
|
||||||
|
end for
|
||||||
|
|
||||||
|
m.scheduleGrid.showLoadingDataFeedback = false
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub onProgramFocused()
|
||||||
|
|
||||||
|
m.top.watchChannel = invalid
|
||||||
|
channel = m.scheduleGrid.content.GetChild(m.scheduleGrid.programFocusedDetails.focusChannelIndex)
|
||||||
|
m.detailsPane.channel = channel
|
||||||
|
|
||||||
|
' Exit if Channels not yet loaded
|
||||||
|
if channel.getChildCount() = 0 then
|
||||||
|
m.detailsPane.programDetails = invalid
|
||||||
|
return
|
||||||
|
end if
|
||||||
|
|
||||||
|
prog = channel.GetChild(m.scheduleGrid.programFocusedDetails.focusIndex)
|
||||||
|
|
||||||
|
if prog <> invalid and prog.fullyLoaded = false then
|
||||||
|
m.LoadProgramDetailsTask.programId = prog.Id
|
||||||
|
m.LoadProgramDetailsTask.channelIndex = m.scheduleGrid.programFocusedDetails.focusChannelIndex
|
||||||
|
m.LoadProgramDetailsTask.programIndex = m.scheduleGrid.programFocusedDetails.focusIndex
|
||||||
|
m.LoadProgramDetailsTask.control = "RUN"
|
||||||
|
end if
|
||||||
|
|
||||||
|
m.detailsPane.programDetails = prog
|
||||||
|
end sub
|
||||||
|
|
||||||
|
' Update the Program Details with full information
|
||||||
|
sub onProgramDetailsLoaded()
|
||||||
|
if m.LoadProgramDetailsTask.programDetails = invalid then return
|
||||||
|
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
|
||||||
|
m.LoadProgramDetailsTask.programDetails.PosterUrl = channel.PosterUrl
|
||||||
|
end if
|
||||||
|
|
||||||
|
channel.ReplaceChild(m.LoadProgramDetailsTask.programDetails, m.LoadProgramDetailsTask.programDetails.programIndex)
|
||||||
|
end sub
|
||||||
|
|
||||||
|
|
||||||
|
sub onProgramSelected()
|
||||||
|
' If there is no program data - view the channel
|
||||||
|
if m.detailsPane.programDetails = invalid then
|
||||||
|
m.top.watchChannel = m.scheduleGrid.content.GetChild(m.scheduleGrid.programFocusedDetails.focusChannelIndex)
|
||||||
|
return
|
||||||
|
end if
|
||||||
|
|
||||||
|
' Move Grid Down
|
||||||
|
focusProgramDetails(true)
|
||||||
|
end sub
|
||||||
|
|
||||||
|
' Move the TV Guide Grid down or up depending whether details are selected
|
||||||
|
sub focusProgramDetails(setFocused)
|
||||||
|
|
||||||
|
h = m.detailsPane.height
|
||||||
|
if h < 400 then h = 400
|
||||||
|
h = h + 160 + 80
|
||||||
|
|
||||||
|
if setFocused = true then
|
||||||
|
m.gridMoveAnimationPosition.keyValue = [ [0,600], [0, h] ]
|
||||||
|
m.detailsPane.setFocus(true)
|
||||||
|
m.detailsPane.hasFocus = true
|
||||||
|
m.top.lastFocus = m.detailsPane
|
||||||
|
else
|
||||||
|
m.detailsPane.hasFocus = false
|
||||||
|
m.gridMoveAnimationPosition.keyValue = [ [0, h], [0,600] ]
|
||||||
|
m.scheduleGrid.setFocus(true)
|
||||||
|
m.top.lastFocus = m.scheduleGrid
|
||||||
|
end if
|
||||||
|
|
||||||
|
m.gridMoveAnimation.control = "start"
|
||||||
|
end sub
|
||||||
|
|
||||||
|
' Handle user selecting "Watch Channel" from Program Details
|
||||||
|
sub onWatchChannelSelected()
|
||||||
|
|
||||||
|
if m.detailsPane.watchSelectedChannel = false then return
|
||||||
|
|
||||||
|
' Set focus back to grid before showing channel, to ensure grid has focus when we return
|
||||||
|
focusProgramDetails(false)
|
||||||
|
|
||||||
|
m.top.watchChannel = m.scheduleGrid.content.GetChild(m.LoadProgramDetailsTask.programDetails.channelIndex)
|
||||||
|
|
||||||
|
end sub
|
||||||
|
|
||||||
|
' As user scrolls grid, check if more data requries to be loaded
|
||||||
|
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
|
||||||
|
|
||||||
|
' Ensure the task is not already (still) running,
|
||||||
|
if m.LoadScheduleTask.state <> "run" then
|
||||||
|
m.LoadScheduleTask.startTime = m.gridEndDate.ToISOString()
|
||||||
|
m.gridEndDate.FromSeconds(m.gridEndDate.AsSeconds() + (24 * 60 * 60))
|
||||||
|
m.LoadScheduleTask.endTime = m.gridEndDate.ToISOString()
|
||||||
|
m.LoadScheduleTask.control = "RUN"
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
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
|
||||||
|
focusProgramDetails(false)
|
||||||
|
return true
|
||||||
|
end if
|
||||||
|
|
||||||
|
return false
|
||||||
|
end function
|
23
components/liveTv/schedule.xml
Normal file
23
components/liveTv/schedule.xml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<component name="Schedule" extends="JFGroup">
|
||||||
|
<children>
|
||||||
|
<rectangle translation="[0,125]" width="1920" height="955" color="#262626" />
|
||||||
|
|
||||||
|
<!-- Selected Item Details -->
|
||||||
|
<ProgramDetails id="detailsPane" focusable="true" />
|
||||||
|
|
||||||
|
<TimeGrid id="scheduleGrid" translation="[0,600]"
|
||||||
|
automaticLoadingDataFeedback="false" showLoadingDataFeedback="true"
|
||||||
|
focusBitmapUri="pkg:/images/white.9.png" focusBitmapBlendColor="#006fab"
|
||||||
|
programTitleFocusedColor="#ffffff"
|
||||||
|
showPastTimeScreen="true" pastTimeScreenBlendColor="#555555"
|
||||||
|
/>
|
||||||
|
<Animation id="gridMoveAnimation" duration="1" repeat="false" easeFunction="outQuad" >
|
||||||
|
<Vector2DFieldInterpolator id="gridMoveAnimationPosition" key="[0.0, 0.5]" fieldToInterp="scheduleGrid.translation" />
|
||||||
|
</Animation>
|
||||||
|
</children>
|
||||||
|
<interface>
|
||||||
|
<field id="watchChannel" type="node" alwaysNotify="false" />
|
||||||
|
</interface>
|
||||||
|
<script type="text/brightscript" uri="schedule.brs" />
|
||||||
|
</component>
|
BIN
images/backgroundmask.png
Normal file
BIN
images/backgroundmask.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 810 KiB |
|
@ -200,5 +200,105 @@
|
||||||
<source>Unable to load Channel Data from the server</source>
|
<source>Unable to load Channel Data from the server</source>
|
||||||
<translation>Unable to load Channel Data from the server</translation>
|
<translation>Unable to load Channel Data from the server</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>today</source>
|
||||||
|
<translation>today</translation>
|
||||||
|
<extracomment>Current day</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>yesterday</source>
|
||||||
|
<translation>yesterday</translation>
|
||||||
|
<extracomment>Previous day</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>tomorrow</source>
|
||||||
|
<translation>tomorrow</translation>
|
||||||
|
<extracomment>Next day</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Sunday</source>
|
||||||
|
<translation>Sunday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Monday</source>
|
||||||
|
<translation>Monday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Tuesday</source>
|
||||||
|
<translation>Tuesday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Wednesday</source>
|
||||||
|
<translation>Wednesday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Thursday</source>
|
||||||
|
<translation>Thursday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Friday</source>
|
||||||
|
<translation>Friday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Saturday</source>
|
||||||
|
<translation>Saturday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Started at</source>
|
||||||
|
<translation>Started at</translation>
|
||||||
|
<extracomment>(Past Tense) For defining time when a program started today (e.g. Started at 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Started</source>
|
||||||
|
<translation>Started</translation>
|
||||||
|
<extracomment>(Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starts at</source>
|
||||||
|
<translation>Starts at</translation>
|
||||||
|
<extracomment>(Future Tense) For defining time when a program will start today (e.g. Starts at 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starts</source>
|
||||||
|
<translation>Starts</translation>
|
||||||
|
<extracomment>(Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Ended at</source>
|
||||||
|
<translation>Ended at</translation>
|
||||||
|
<extracomment>(Past Tense) For defining time when a program will ended (e.g. Ended at 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Ends at</source>
|
||||||
|
<translation>Ends at</translation>
|
||||||
|
<extracomment>(Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Live</source>
|
||||||
|
<translation>Live</translation>
|
||||||
|
<extracomment>If TV Show is being broadcast live (not pre-recorded)</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Repeat</source>
|
||||||
|
<translation>Repeat</translation>
|
||||||
|
<extracomment>If TV Shows has previously been broadcasted</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Channels</source>
|
||||||
|
<translation>Channels</translation>
|
||||||
|
<extracomment>Menu option for showing Live TV Channel List</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>TV Guide</source>
|
||||||
|
<translation>TV Guide</translation>
|
||||||
|
<extracomment>Menu option for showing Live TV Guide / Schedule</extracomment>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
|
@ -314,6 +314,106 @@
|
||||||
<source>TAB_FILTER</source>
|
<source>TAB_FILTER</source>
|
||||||
<translation>Filter</translation>
|
<translation>Filter</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>today</source>
|
||||||
|
<translation>today</translation>
|
||||||
|
<extracomment>Current day</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>yesterday</source>
|
||||||
|
<translation>yesterday</translation>
|
||||||
|
<extracomment>Previous day</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>tomorrow</source>
|
||||||
|
<translation>tomorrow</translation>
|
||||||
|
<extracomment>Next day</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Sunday</source>
|
||||||
|
<translation>Sunday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Monday</source>
|
||||||
|
<translation>Monday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Tuesday</source>
|
||||||
|
<translation>Tuesday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Wednesday</source>
|
||||||
|
<translation>Wednesday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Thursday</source>
|
||||||
|
<translation>Thursday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Friday</source>
|
||||||
|
<translation>Friday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Saturday</source>
|
||||||
|
<translation>Saturday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Started at</source>
|
||||||
|
<translation>Started at</translation>
|
||||||
|
<extracomment>(Past Tense) For defining time when a program started today (e.g. Started at 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Started</source>
|
||||||
|
<translation>Started</translation>
|
||||||
|
<extracomment>(Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starts at</source>
|
||||||
|
<translation>Starts at</translation>
|
||||||
|
<extracomment>(Future Tense) For defining time when a program will start today (e.g. Starts at 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starts</source>
|
||||||
|
<translation>Starts</translation>
|
||||||
|
<extracomment>(Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Ended at</source>
|
||||||
|
<translation>Ended at</translation>
|
||||||
|
<extracomment>(Past Tense) For defining time when a program will ended (e.g. Ended at 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Ends at</source>
|
||||||
|
<translation>Ends at</translation>
|
||||||
|
<extracomment>(Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Live</source>
|
||||||
|
<translation>Live</translation>
|
||||||
|
<extracomment>If TV Show is being broadcast live (not pre-recorded)</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Repeat</source>
|
||||||
|
<translation>Repeat</translation>
|
||||||
|
<extracomment>If TV Shows has previously been broadcasted</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Channels</source>
|
||||||
|
<translation>Channels</translation>
|
||||||
|
<extracomment>Menu option for showing Live TV Channel List</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>TV Guide</source>
|
||||||
|
<translation>TV Guide</translation>
|
||||||
|
<extracomment>Menu option for showing Live TV Guide / Schedule</extracomment>
|
||||||
|
</message>
|
||||||
|
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
|
@ -225,7 +225,7 @@
|
||||||
<translation>Error During Playback</translation>
|
<translation>Error During Playback</translation>
|
||||||
<extracomment>Dialog title when error occurs during playback</extracomment>
|
<extracomment>Dialog title when error occurs during playback</extracomment>
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
<message>
|
<message>
|
||||||
<source>There was an error retrieving the data for this item from the server.</source>
|
<source>There was an error retrieving the data for this item from the server.</source>
|
||||||
<translation>There was an error retrieving the data for this item from the server.</translation>
|
<translation>There was an error retrieving the data for this item from the server.</translation>
|
||||||
|
@ -237,7 +237,7 @@
|
||||||
<translation>An error was encountered while playing this item.</translation>
|
<translation>An error was encountered while playing this item.</translation>
|
||||||
<extracomment>Dialog detail when error occurs during playback</extracomment>
|
<extracomment>Dialog detail when error occurs during playback</extracomment>
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
<message>
|
<message>
|
||||||
<source>Loading Channel Data</source>
|
<source>Loading Channel Data</source>
|
||||||
<translation>Loading Channel Data</translation>
|
<translation>Loading Channel Data</translation>
|
||||||
|
@ -314,6 +314,106 @@
|
||||||
<source>TAB_FILTER</source>
|
<source>TAB_FILTER</source>
|
||||||
<translation>Filter</translation>
|
<translation>Filter</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>today</source>
|
||||||
|
<translation>today</translation>
|
||||||
|
<extracomment>Current day</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>yesterday</source>
|
||||||
|
<translation>yesterday</translation>
|
||||||
|
<extracomment>Previous day</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>tomorrow</source>
|
||||||
|
<translation>tomorrow</translation>
|
||||||
|
<extracomment>Next day</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Sunday</source>
|
||||||
|
<translation>Sunday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Monday</source>
|
||||||
|
<translation>Monday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Tuesday</source>
|
||||||
|
<translation>Tuesday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Wednesday</source>
|
||||||
|
<translation>Wednesday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Thursday</source>
|
||||||
|
<translation>Thursday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Friday</source>
|
||||||
|
<translation>Friday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Saturday</source>
|
||||||
|
<translation>Saturday</translation>
|
||||||
|
<extracomment>Day of Week</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Started at</source>
|
||||||
|
<translation>Started at</translation>
|
||||||
|
<extracomment>(Past Tense) For defining time when a program started today (e.g. Started at 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Started</source>
|
||||||
|
<translation>Started</translation>
|
||||||
|
<extracomment>(Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starts at</source>
|
||||||
|
<translation>Starts at</translation>
|
||||||
|
<extracomment>(Future Tense) For defining time when a program will start today (e.g. Starts at 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starts</source>
|
||||||
|
<translation>Starts</translation>
|
||||||
|
<extracomment>(Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Ended at</source>
|
||||||
|
<translation>Ended at</translation>
|
||||||
|
<extracomment>(Past Tense) For defining time when a program will ended (e.g. Ended at 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Ends at</source>
|
||||||
|
<translation>Ends at</translation>
|
||||||
|
<extracomment>(Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00) </extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Live</source>
|
||||||
|
<translation>Live</translation>
|
||||||
|
<extracomment>If TV Show is being broadcast live (not pre-recorded)</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Repeat</source>
|
||||||
|
<translation>Repeat</translation>
|
||||||
|
<extracomment>If TV Shows has previously been broadcasted</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Channels</source>
|
||||||
|
<translation>Channels</translation>
|
||||||
|
<extracomment>Menu option for showing Live TV Channel List</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>TV Guide</source>
|
||||||
|
<translation>TV Guide</translation>
|
||||||
|
<extracomment>Menu option for showing Live TV Guide / Schedule</extracomment>
|
||||||
|
</message>
|
||||||
|
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
|
@ -82,7 +82,7 @@ sub Main()
|
||||||
' If you select a library from ANYWHERE, follow this flow
|
' If you select a library from ANYWHERE, follow this flow
|
||||||
selectedItem = msg.getData()
|
selectedItem = msg.getData()
|
||||||
if (selectedItem.type = "CollectionFolder" OR selectedItem.type = "UserView" OR selectedItem.type = "Folder") AND ( selectedItem.collectionType = "movies" or selectedItem.collectionType = "CollectionFolder")
|
if (selectedItem.type = "CollectionFolder" OR selectedItem.type = "UserView" OR selectedItem.type = "Folder") AND ( selectedItem.collectionType = "movies" or selectedItem.collectionType = "CollectionFolder")
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
m.overhang.title = selectedItem.title
|
m.overhang.title = selectedItem.title
|
||||||
|
@ -90,7 +90,7 @@ sub Main()
|
||||||
group.overhangTitle = selectedItem.title
|
group.overhangTitle = selectedItem.title
|
||||||
m.scene.appendChild(group)
|
m.scene.appendChild(group)
|
||||||
else if (selectedItem.type = "CollectionFolder" OR selectedItem.type = "UserView") AND selectedItem.collectionType = "tvshows"
|
else if (selectedItem.type = "CollectionFolder" OR selectedItem.type = "UserView") AND selectedItem.collectionType = "tvshows"
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ sub Main()
|
||||||
group.overhangTitle = selectedItem.title
|
group.overhangTitle = selectedItem.title
|
||||||
m.scene.appendChild(group)
|
m.scene.appendChild(group)
|
||||||
else if (selectedItem.type = "CollectionFolder" OR selectedItem.type = "UserView") AND selectedItem.collectionType = "boxsets" OR selectedItem.type = "Boxset"
|
else if (selectedItem.type = "CollectionFolder" OR selectedItem.type = "UserView") AND selectedItem.collectionType = "boxsets" OR selectedItem.type = "Boxset"
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ sub Main()
|
||||||
group.overhangTitle = selectedItem.title
|
group.overhangTitle = selectedItem.title
|
||||||
m.scene.appendChild(group)
|
m.scene.appendChild(group)
|
||||||
else if ((selectedItem.type = "CollectionFolder" OR selectedItem.type = "UserView") AND selectedItem.collectionType = "livetv") OR selectedItem.type = "Channel"
|
else if ((selectedItem.type = "CollectionFolder" OR selectedItem.type = "UserView") AND selectedItem.collectionType = "livetv") OR selectedItem.type = "Channel"
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -116,9 +116,9 @@ sub Main()
|
||||||
group = CreateChannelList(selectedItem)
|
group = CreateChannelList(selectedItem)
|
||||||
group.overhangTitle = selectedItem.title
|
group.overhangTitle = selectedItem.title
|
||||||
m.scene.appendChild(group)
|
m.scene.appendChild(group)
|
||||||
else if selectedItem.type = "Boxset" then
|
else if selectedItem.type = "Boxset" or selectedItem.collectionType = "folders" then
|
||||||
|
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ sub Main()
|
||||||
video_id = selectedItem.id
|
video_id = selectedItem.id
|
||||||
video = CreateVideoPlayerGroup(video_id)
|
video = CreateVideoPlayerGroup(video_id)
|
||||||
if video <> invalid then
|
if video <> invalid then
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
group = video
|
group = video
|
||||||
|
@ -152,7 +152,7 @@ sub Main()
|
||||||
m.overhang.visible = false
|
m.overhang.visible = false
|
||||||
end if
|
end if
|
||||||
else if selectedItem.type = "Series" then
|
else if selectedItem.type = "Series" then
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ sub Main()
|
||||||
m.scene.appendChild(group)
|
m.scene.appendChild(group)
|
||||||
else if selectedItem.type = "Movie" then
|
else if selectedItem.type = "Movie" then
|
||||||
' open movie detail page
|
' open movie detail page
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ sub Main()
|
||||||
dialog.close = true
|
dialog.close = true
|
||||||
|
|
||||||
if video <> invalid then
|
if video <> invalid then
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
group = video
|
group = video
|
||||||
|
@ -217,7 +217,7 @@ sub Main()
|
||||||
' If you select a movie from ANYWHERE, follow this flow
|
' If you select a movie from ANYWHERE, follow this flow
|
||||||
node = getMsgPicker(msg, "picker")
|
node = getMsgPicker(msg, "picker")
|
||||||
|
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ sub Main()
|
||||||
' If you select a TV Series from ANYWHERE, follow this flow
|
' If you select a TV Series from ANYWHERE, follow this flow
|
||||||
node = getMsgPicker(msg, "picker")
|
node = getMsgPicker(msg, "picker")
|
||||||
|
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ sub Main()
|
||||||
series = msg.getRoSGNode()
|
series = msg.getRoSGNode()
|
||||||
node = series.seasonData.items[ptr[1]]
|
node = series.seasonData.items[ptr[1]]
|
||||||
|
|
||||||
group.lastFocus = group.focusedChild.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ sub Main()
|
||||||
video_id = node.id
|
video_id = node.id
|
||||||
video = CreateVideoPlayerGroup(video_id)
|
video = CreateVideoPlayerGroup(video_id)
|
||||||
if video <> invalid then
|
if video <> invalid then
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
group = video
|
group = video
|
||||||
|
@ -298,7 +298,7 @@ sub Main()
|
||||||
else if isNodeEvent(msg, "itemSelected")
|
else if isNodeEvent(msg, "itemSelected")
|
||||||
' Search item selected
|
' Search item selected
|
||||||
node = getMsgPicker(msg)
|
node = getMsgPicker(msg)
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ sub Main()
|
||||||
video_id = group.id
|
video_id = group.id
|
||||||
video = CreateVideoPlayerGroup(video_id, audio_stream_idx)
|
video = CreateVideoPlayerGroup(video_id, audio_stream_idx)
|
||||||
if video <> invalid then
|
if video <> invalid then
|
||||||
group.lastFocus = group.focusedChild.focusedChild.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild.focusedChild.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
group = video
|
group = video
|
||||||
|
@ -364,7 +364,7 @@ sub Main()
|
||||||
else
|
else
|
||||||
group.setFocus(true)
|
group.setFocus(true)
|
||||||
end if
|
end if
|
||||||
group.lastFocus = group.focusedChild
|
if group.lastFocus = invalid then group.lastFocus = group.focusedChild
|
||||||
group.setFocus(false)
|
group.setFocus(false)
|
||||||
group.visible = false
|
group.visible = false
|
||||||
m.overhang.showOptions = false
|
m.overhang.showOptions = false
|
||||||
|
@ -437,7 +437,7 @@ sub Main()
|
||||||
print msg.GetInfo()
|
print msg.GetInfo()
|
||||||
end if
|
end if
|
||||||
else
|
else
|
||||||
print type(msg)
|
print "Unhandled " type(msg)
|
||||||
print msg
|
print msg
|
||||||
end if
|
end if
|
||||||
end while
|
end while
|
||||||
|
@ -486,6 +486,7 @@ function LoginFlow(startOver = false as boolean)
|
||||||
get_token(userSelected, "")
|
get_token(userSelected, "")
|
||||||
if get_setting("active_user") <> invalid then
|
if get_setting("active_user") <> invalid then
|
||||||
m.user = AboutMe()
|
m.user = AboutMe()
|
||||||
|
LoadUserPreferences()
|
||||||
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
|
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
|
||||||
return true
|
return true
|
||||||
end if
|
end if
|
||||||
|
@ -508,6 +509,7 @@ function LoginFlow(startOver = false as boolean)
|
||||||
goto start_login
|
goto start_login
|
||||||
end if
|
end if
|
||||||
|
|
||||||
|
LoadUserPreferences()
|
||||||
wipe_groups()
|
wipe_groups()
|
||||||
|
|
||||||
'Send Device Profile information to server
|
'Send Device Profile information to server
|
||||||
|
|
|
@ -261,7 +261,6 @@ end function
|
||||||
|
|
||||||
function getContainerType(meta as object) as string
|
function getContainerType(meta as object) as string
|
||||||
' Determine the file type of the video file source
|
' Determine the file type of the video file source
|
||||||
print type(meta)
|
|
||||||
if meta.json.mediaSources = invalid then return ""
|
if meta.json.mediaSources = invalid then return ""
|
||||||
|
|
||||||
container = meta.json.mediaSources[0].container
|
container = meta.json.mediaSources[0].container
|
||||||
|
|
|
@ -67,3 +67,19 @@ function GetPublicUsers()
|
||||||
resp = APIRequest(url)
|
resp = APIRequest(url)
|
||||||
return getJson(resp)
|
return getJson(resp)
|
||||||
end function
|
end function
|
||||||
|
|
||||||
|
' Load and parse Display Settings from server
|
||||||
|
sub LoadUserPreferences()
|
||||||
|
id = get_setting("active_user")
|
||||||
|
' Currently using client "emby", which is what website uses so we get same Display prefs as web.
|
||||||
|
' May want to change to specific Roku display settings
|
||||||
|
url = Substitute("DisplayPreferences/usersettings?userId={0}&client=emby", id)
|
||||||
|
resp = APIRequest(url)
|
||||||
|
jsonResponse = getJson(resp)
|
||||||
|
|
||||||
|
if jsonResponse <> invalid and jsonResponse.CustomPrefs <> invalid and jsonResponse.CustomPrefs["landing-livetv"] <> invalid then
|
||||||
|
set_user_setting("display.livetv.landing", jsonResponse.CustomPrefs["landing-livetv"])
|
||||||
|
else
|
||||||
|
unset_user_setting("display.livetv.landing")
|
||||||
|
end if
|
||||||
|
end sub
|
|
@ -94,7 +94,7 @@ function lastFocusedChild(obj as object) as object
|
||||||
child = obj
|
child = obj
|
||||||
for i = 0 to obj.getChildCount()
|
for i = 0 to obj.getChildCount()
|
||||||
if obj.focusedChild <> invalid then
|
if obj.focusedChild <> invalid then
|
||||||
child = child.focusedChild
|
child = obj.focusedChild
|
||||||
end if
|
end if
|
||||||
end for
|
end for
|
||||||
return child
|
return child
|
||||||
|
@ -102,7 +102,7 @@ end function
|
||||||
|
|
||||||
function show_dialog(message as string, options = [], defaultSelection = 0) as integer
|
function show_dialog(message as string, options = [], defaultSelection = 0) as integer
|
||||||
group = m.scene.focusedChild
|
group = m.scene.focusedChild
|
||||||
lastFocus = lastFocusedChild(m.scene)
|
if group.lastFocus = invalid then lastFocus = lastFocusedChild(m.scene)
|
||||||
'We want to handle backPressed instead of the main loop
|
'We want to handle backPressed instead of the main loop
|
||||||
m.scene.unobserveField("backPressed")
|
m.scene.unobserveField("backPressed")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user