Skip to content

Commit

Permalink
Merge pull request #223 from neilsb/initial-live-tv
Browse files Browse the repository at this point in the history
Initial Live TV Support
  • Loading branch information
anthonylavado authored Jun 16, 2020
2 parents 2fefdc4 + 7cea54b commit 93c64f7
Show file tree
Hide file tree
Showing 18 changed files with 525 additions and 17 deletions.
7 changes: 6 additions & 1 deletion components/ListPoster.brs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ sub init()
m.title = m.top.findNode("title")
m.staticTitle = m.top.findNode("staticTitle")
m.poster = m.top.findNode("poster")

m.backdrop = m.top.findNode("backdrop")
m.backdrop.color = "#404040FF"

' Randmomise the background colors
posterBackgrounds = [ "#5ccea9", "#d2b019", "#dd452b", "#338abb", "#6b689d" ]
m.backdrop.color = posterBackgrounds[rnd(posterBackgrounds.count()) - 1]

updateSize()
end sub

Expand Down
15 changes: 15 additions & 0 deletions components/data/ChannelData.brs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
sub setFields()
json = m.top.json

m.top.id = json.id
m.top.title = json.name
m.top.live = true
end sub

sub setPoster()
if m.top.image <> invalid
m.top.posterURL = m.top.image.url
else
m.top.posterURL = ""
end if
end sub
11 changes: 11 additions & 0 deletions components/data/ChannelData.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="ChannelData" extends="ContentNode">
<interface>
<field id="id" type="string" />
<field id="title" type="string" />
<field id="image" type="node" onChange="setPoster" />
<field id="posterURL" type="string" />
<field id="json" type="associativearray" onChange="setFields" />
</interface>
<script type="text/brightscript" uri="ChannelData.brs" />
</component>
6 changes: 6 additions & 0 deletions components/home/HomeItem.brs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ sub itemContentChanged()
m.itemText.maxWidth = imageWidth
itemTextExtra.width = imageWidth

' Randmomise the background colors
m.backdrop = m.top.findNode("backdrop")
posterBackgrounds = [ "#5ccea9", "#d2b019", "#dd452b", "#338abb", "#6b689d" ]
m.backdrop.color = posterBackgrounds[rnd(posterBackgrounds.count()) - 1]
m.backdrop.width = imageWidth

' Whether to use WidePoster or Thumbnail in this row
usePoster = m.top.GetParent().content.usePoster

Expand Down
1 change: 1 addition & 0 deletions components/home/HomeItem.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="HomeItem" extends="Group">
<children>
<Rectangle id="backdrop" width="464" height="261" translation="[8,5]" />
<Poster id="itemPoster" width="464" height="261" translation="[8,5]" />
<ScrollingLabel id="itemText" horizAlign="center" vertAlign="center" font="font:SmallBoldSystemFont" height="64" maxWidth="456" translation="[8,267]" repeatCount="0" />
<Label id="itemTextExtra" horizAlign="left" vertAlign="center" font="font:SmallBoldSystemFont" height="32" width="456" translation="[8,300]" visible="false" color="#777777FF" />
Expand Down
1 change: 1 addition & 0 deletions components/home/LoadItemsTask.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
<script type="text/brightscript" uri="pkg:/source/api/Items.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/utils/deviceCapabilities.brs" />
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
</component>
14 changes: 14 additions & 0 deletions components/livetv/Channels.brs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
sub init()

end sub

function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false

if key = "down"
m.top.lastFocus = m.top.focusedChild
m.top.findNode("paginator").setFocus(true)
end if

return false
end function
14 changes: 14 additions & 0 deletions components/livetv/Channels.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="Channels" extends="JFGroup">
<children>
<ItemGrid id="picker" visible="true" itemsPerRow="6" />
<OptionsSlider id="options" />
<Rectangle translation="[0,981]" width="1920" height="100" color="#101010" />
</children>
<interface>
<field id="channelSelected" alias="picker.itemSelected" />
<field id="objects" alias="picker.objects" />
<field id="pageNumber" type="integer" />
</interface>
<script type="text/brightscript" uri="Channels.brs" />
</component>
16 changes: 16 additions & 0 deletions locale/default/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,5 +213,21 @@
<source>Server</source>
<translation>Server</translation>
</message>

<message>
<source>Loading Channel Data</source>
<translation>Loading Channel Data</translation>
</message>

<message>
<source>Error loading Channel Data</source>
<translation>Error loading Channel Data</translation>
</message>

<message>
<source>Unable to load Channel Data from the server</source>
<translation>Unable to load Channel Data from the server</translation>
</message>

</context>
</TS>
16 changes: 16 additions & 0 deletions locale/en_GB/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,5 +213,21 @@
<source>Server</source>
<translation>Server</translation>
</message>

<message>
<source>Loading Channel Data</source>
<translation>Loading Channel Data</translation>
</message>

<message>
<source>Error loading Channel Data</source>
<translation>Error loading Channel Data</translation>
</message>

<message>
<source>Unable to load Channel Data from the server</source>
<translation>Unable to load Channel Data from the server</translation>
</message>

</context>
</TS>
16 changes: 16 additions & 0 deletions locale/en_US/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,5 +213,21 @@
<source>Server</source>
<translation>Server</translation>
</message>

<message>
<source>Loading Channel Data</source>
<translation>Loading Channel Data</translation>
</message>

<message>
<source>Error loading Channel Data</source>
<translation>Error loading Channel Data</translation>
</message>

<message>
<source>Unable to load Channel Data from the server</source>
<translation>Unable to load Channel Data from the server</translation>
</message>

</context>
</TS>
50 changes: 49 additions & 1 deletion source/Main.brs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ sub Main()
group = CreateCollectionsList(selectedItem.Id)
group.overhangTitle = selectedItem.name
m.scene.appendChild(group)
else if (selectedItem.type = "CollectionFolder" OR selectedItem.type = "UserView") AND selectedItem.collectionType = "livetv"
group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false

m.overhang.title = selectedItem.name
group = CreateChannelList(selectedItem.Id)
group.overhangTitle = selectedItem.name
m.scene.appendChild(group)
else if selectedItem.type = "Episode" then
' play episode
' todo: create an episode page to link here
Expand Down Expand Up @@ -222,6 +231,37 @@ sub Main()
ReportPlayback(group, "start")
m.overhang.visible = false
end if
else if isNodeEvent(msg, "channelSelected")
' If you select a Channel from ANYWHERE, follow this flow
node = getMsgPicker(msg, "picker")
video_id = node.id

' Show Channel Loading spinner
dialog = createObject("roSGNode", "ProgressDialog")
dialog.title = tr("Loading Channel Data")
m.scene.dialog = dialog

video = CreateVideoPlayerGroup(video_id)
dialog.close = true

if video <> invalid then
group.lastFocus = group.focusedChild
group.setFocus(false)
group.visible = false
group = video
m.scene.appendChild(group)
group.setFocus(true)
group.control = "play"
ReportPlayback(group, "start")
m.overhang.visible = false
else
dialog = createObject("roSGNode", "Dialog")
dialog.title = tr("Error loading Channel Data")
dialog.message = tr("Unable to load Channel Data from the server")
dialog.buttons = [tr("OK")]
m.scene.dialog = dialog
end if

else if isNodeEvent(msg, "search_value")
query = msg.getRoSGNode().search_value
group.findNode("SearchBox").visible = false
Expand All @@ -239,6 +279,8 @@ sub Main()
CollectionLister(group, m.page_size)
else if collectionType = "TVShows"
SeriesLister(group, m.page_size)
else if collectionType = "Channels"
ChannelLister(group, m.page_size)
end if
' TODO - abstract away the "picker" node
group.findNode("picker").setFocus(true)
Expand Down Expand Up @@ -338,7 +380,7 @@ sub Main()
end if
else if isNodeEvent(msg, "position")
video = msg.getRoSGNode()
if video.position >= video.duration then
if video.position >= video.duration and not video.content.live then
stopPlayback()
end if
else if isNodeEvent(msg, "fire")
Expand Down Expand Up @@ -452,6 +494,12 @@ function LoginFlow(startOver = false as boolean)
end if

wipe_groups()

'Send Device Profile information to server
body = getDeviceCapabilities()
req = APIRequest("/Sessions/Capabilities/Full")
req.SetRequest("POST")
postJson(req, FormatJson(body))
return true
end function

Expand Down
63 changes: 63 additions & 0 deletions source/ShowScenes.brs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,57 @@ function CreateCollectionsList(libraryId)
return group
end function


function CreateChannelList(libraryId)
group = CreateObject("roSGNode", "Channels")
group.id = libraryId

group.observeField("channelSelected", m.port)


sidepanel = group.findNode("options")
channel_options = [
{"title": "Sort Field",
"base_title": "Sort Field",
"key": "channel_sort_field",
"default": "Name",
"values": [
{display: tr("Name"), value: "SortName"}
]},
{"title": "Sort Order",
"base_title": "Sort Order",
"key": "channel_sort_order",
"default": "Ascending",
"values": [
{display: tr("Descending"), value: "Descending"},
{display: tr("Ascending"), value: "Ascending"}
]}
]
new_options = []
for each opt in channel_options
o = CreateObject("roSGNode", "OptionsData")
o.title = tr(opt.title)
o.choices = opt.values
o.base_title = tr(opt.base_title)
o.config_key = opt.key
o.value = get_user_setting(opt.key, opt.default)
new_options.append([o])
end for

sidepanel.options = new_options
sidepanel.observeField("closeSidePanel", m.port)

p = CreatePaginator()
group.appendChild(p)

group.pageNumber = 1
p.currentPage = group.pageNumber

ChannelLister(group, m.page_size)

return group
end function

function CreateSearchPage()
' Search + Results Page
group = CreateObject("roSGNode", "SearchResults")
Expand Down Expand Up @@ -419,3 +470,15 @@ function CollectionLister(group, page_size)
p = group.findNode("paginator")
p.maxPages = div_ceiling(group.objects.TotalRecordCount, page_size)
end function

function ChannelLister(group, page_size)
sort_order = get_user_setting("channel_sort_order", "Ascending")
sort_field = get_user_setting("channel_sort_field", "SortName")
group.objects = Channels({"limit": page_size,
"StartIndex": page_size * (group.pageNumber - 1),
"SortBy": sort_field,
"SortOrder": sort_order,
})
p = group.findNode("paginator")
p.maxPages = div_ceiling(group.objects.TotalRecordCount, page_size)
end function
Loading

0 comments on commit 93c64f7

Please sign in to comment.