2019-05-03 12:48:59 +00:00
|
|
|
sub init()
|
2022-03-13 08:46:03 +00:00
|
|
|
m.extrasGrp = m.top.findnode("extrasGrp")
|
|
|
|
m.extrasGrid = m.top.findNode("extrasGrid")
|
2021-07-09 20:08:32 +00:00
|
|
|
m.top.optionsAvailable = false
|
2022-03-13 11:49:36 +00:00
|
|
|
|
2022-04-07 06:31:16 +00:00
|
|
|
m.options = m.top.findNode("movieOptions")
|
2020-03-01 01:41:57 +00:00
|
|
|
|
2022-03-13 08:46:03 +00:00
|
|
|
m.main_group = m.top.findNode("main_group")
|
2022-03-13 11:49:36 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
main = m.top.findNode("main_group")
|
|
|
|
main.translation = [96, 175]
|
|
|
|
overview = m.top.findNode("overview")
|
|
|
|
overview.width = 1920 - 96 - 300 - 96 - 30
|
2019-05-03 12:48:59 +00:00
|
|
|
|
2022-06-18 19:07:07 +00:00
|
|
|
m.details = m.top.findNode("details")
|
|
|
|
m.tagline = m.top.findNode("tagline")
|
|
|
|
|
2022-03-13 08:46:03 +00:00
|
|
|
m.buttonGrp = m.top.findNode("buttons")
|
|
|
|
m.buttonGrp.setFocus(true)
|
2022-05-10 07:04:23 +00:00
|
|
|
m.top.lastFocus = m.buttonGrp
|
2022-03-13 02:18:54 +00:00
|
|
|
|
2022-10-27 04:04:44 +00:00
|
|
|
m.spinner = m.top.findNode("spinner")
|
|
|
|
|
2022-09-03 07:31:15 +00:00
|
|
|
m.trailerButton = m.top.findNode("trailer-button")
|
|
|
|
m.trailerButton.text = tr("Play Trailer")
|
|
|
|
|
2022-03-13 02:18:54 +00:00
|
|
|
m.top.observeField("itemContent", "itemContentChanged")
|
2022-10-27 04:04:44 +00:00
|
|
|
m.top.findNode("communityRatingGroup").visible = false
|
2019-05-03 12:48:59 +00:00
|
|
|
end sub
|
|
|
|
|
2022-05-10 07:25:38 +00:00
|
|
|
sub OnScreenShown()
|
2022-05-10 07:05:02 +00:00
|
|
|
' set focus to button group
|
2022-08-20 08:54:36 +00:00
|
|
|
if m.extrasGrp.opacity = 1
|
|
|
|
m.top.lastFocus.setFocus(true)
|
|
|
|
else
|
|
|
|
m.buttonGrp.setFocus(true)
|
|
|
|
end if
|
2022-05-10 07:05:02 +00:00
|
|
|
end sub
|
2022-05-10 07:25:38 +00:00
|
|
|
|
2022-09-03 07:31:15 +00:00
|
|
|
sub trailerAvailableChanged()
|
|
|
|
m.trailerButton.visible = m.top.trailerAvailable
|
|
|
|
end sub
|
2022-05-10 07:05:02 +00:00
|
|
|
|
2019-03-14 17:11:51 +00:00
|
|
|
sub itemContentChanged()
|
2021-07-09 20:08:32 +00:00
|
|
|
' Updates video metadata
|
|
|
|
item = m.top.itemContent
|
|
|
|
itemData = item.json
|
|
|
|
m.top.id = itemData.id
|
|
|
|
m.top.findNode("moviePoster").uri = m.top.itemContent.posterURL
|
|
|
|
|
2022-03-13 00:36:11 +00:00
|
|
|
' Set default video source
|
2022-09-05 06:50:13 +00:00
|
|
|
if itemData.MediaSources <> invalid
|
|
|
|
m.top.selectedVideoStreamId = itemData.MediaSources[0].id
|
|
|
|
end if
|
2021-07-09 20:08:32 +00:00
|
|
|
' Find first Audio Stream and set that as default
|
2022-03-13 02:18:54 +00:00
|
|
|
SetDefaultAudioTrack(itemData)
|
2021-07-09 20:08:32 +00:00
|
|
|
|
|
|
|
' Handle all "As Is" fields
|
|
|
|
m.top.overhangTitle = itemData.name
|
|
|
|
setFieldText("releaseYear", itemData.productionYear)
|
|
|
|
setFieldText("officialRating", itemData.officialRating)
|
|
|
|
setFieldText("overview", itemData.overview)
|
|
|
|
|
|
|
|
if itemData.communityRating <> invalid
|
2022-08-27 15:28:31 +00:00
|
|
|
setFieldText("communityRating", int(itemData.communityRating * 10) / 10)
|
2022-10-27 04:04:44 +00:00
|
|
|
m.top.findNode("communityRatingGroup").visible = true
|
2021-07-09 20:08:32 +00:00
|
|
|
end if
|
|
|
|
|
|
|
|
if itemData.CriticRating <> invalid
|
|
|
|
setFieldText("criticRatingLabel", itemData.criticRating)
|
|
|
|
if itemData.CriticRating > 60
|
|
|
|
tomato = "pkg:/images/fresh.png"
|
|
|
|
else
|
|
|
|
tomato = "pkg:/images/rotten.png"
|
|
|
|
end if
|
|
|
|
m.top.findNode("criticRatingIcon").uri = tomato
|
|
|
|
else
|
|
|
|
m.top.findNode("infoGroup").removeChild(m.top.findNode("criticRatingGroup"))
|
|
|
|
end if
|
|
|
|
|
|
|
|
if type(itemData.RunTimeTicks) = "LongInteger"
|
|
|
|
setFieldText("runtime", stri(getRuntime()) + " mins")
|
2022-07-16 02:28:59 +00:00
|
|
|
if get_user_setting("ui.design.hideclock") <> "true"
|
|
|
|
setFieldText("ends-at", tr("Ends at %1").Replace("%1", getEndTime()))
|
|
|
|
end if
|
2021-07-09 20:08:32 +00:00
|
|
|
end if
|
|
|
|
|
|
|
|
if itemData.genres.count() > 0
|
|
|
|
setFieldText("genres", tr("Genres") + ": " + itemData.genres.join(", "))
|
|
|
|
end if
|
|
|
|
|
|
|
|
' show tags if there are no genres to display
|
|
|
|
if itemData.genres.count() = 0 and itemData.tags.count() > 0
|
|
|
|
setFieldText("genres", tr("Tags") + ": " + itemData.tags.join(", "))
|
|
|
|
end if
|
|
|
|
|
|
|
|
directors = []
|
|
|
|
for each person in itemData.people
|
|
|
|
if person.type = "Director"
|
|
|
|
directors.push(person.name)
|
|
|
|
end if
|
|
|
|
end for
|
|
|
|
if directors.count() > 0
|
|
|
|
setFieldText("director", tr("Director") + ": " + directors.join(", "))
|
|
|
|
end if
|
|
|
|
|
|
|
|
if itemData.mediaStreams[0] <> invalid
|
|
|
|
setFieldText("video_codec", tr("Video") + ": " + itemData.mediaStreams[0].displayTitle)
|
|
|
|
end if
|
2022-06-18 19:07:07 +00:00
|
|
|
|
|
|
|
if get_user_setting("ui.details.hidetagline") = "false"
|
|
|
|
if itemData.taglines.count() > 0
|
|
|
|
setFieldText("tagline", itemData.taglines[0])
|
|
|
|
end if
|
|
|
|
else
|
|
|
|
m.details.removeChild(m.tagline)
|
2021-07-09 20:08:32 +00:00
|
|
|
end if
|
2022-03-13 08:46:03 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
setFavoriteColor()
|
|
|
|
setWatchedColor()
|
2022-03-13 00:36:11 +00:00
|
|
|
SetUpVideoOptions(itemData.mediaSources)
|
|
|
|
SetUpAudioOptions(itemData.mediaStreams)
|
2022-10-27 04:04:44 +00:00
|
|
|
m.buttonGrp.visible = true
|
|
|
|
m.spinner.visible = false
|
2022-03-13 00:36:11 +00:00
|
|
|
end sub
|
|
|
|
|
|
|
|
|
|
|
|
sub SetUpVideoOptions(streams)
|
|
|
|
|
|
|
|
videos = []
|
|
|
|
|
|
|
|
for i = 0 to streams.Count() - 1
|
|
|
|
if streams[i].VideoType = "VideoFile"
|
2022-04-26 16:35:40 +00:00
|
|
|
codec = ""
|
|
|
|
if streams[i].mediaStreams <> invalid and streams[i].mediaStreams.Count() > 0 then codec = streams[i].mediaStreams[0].displayTitle
|
2022-04-26 16:45:40 +00:00
|
|
|
videos.push({
|
|
|
|
"Title": streams[i].Name,
|
|
|
|
"Description": tr("Video"),
|
|
|
|
"Selected": m.top.selectedVideoStreamId = streams[i].id,
|
|
|
|
"StreamID": streams[i].id,
|
2022-04-26 16:35:40 +00:00
|
|
|
"video_codec": codec
|
|
|
|
})
|
2022-03-13 00:36:11 +00:00
|
|
|
end if
|
|
|
|
end for
|
|
|
|
|
2022-04-07 06:31:16 +00:00
|
|
|
if streams.count() > 1
|
|
|
|
m.top.findnode("video_codec_count").text = "+" + stri(streams.Count() - 1).trim()
|
|
|
|
end if
|
|
|
|
|
2022-03-13 00:36:11 +00:00
|
|
|
options = {}
|
2022-04-07 06:31:16 +00:00
|
|
|
options.videos = videos
|
|
|
|
m.options.options = options
|
2022-03-13 00:36:11 +00:00
|
|
|
|
2020-10-24 13:56:33 +00:00
|
|
|
end sub
|
|
|
|
|
|
|
|
|
2022-03-13 00:36:11 +00:00
|
|
|
sub SetUpAudioOptions(streams)
|
2021-07-09 20:08:32 +00:00
|
|
|
tracks = []
|
2020-10-24 13:56:33 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
for i = 0 to streams.Count() - 1
|
|
|
|
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
|
2020-10-24 13:56:33 +00:00
|
|
|
|
2022-04-07 06:31:16 +00:00
|
|
|
if tracks.count() > 1
|
|
|
|
m.top.findnode("audio_codec_count").text = "+" + stri(tracks.Count() - 1).trim()
|
|
|
|
end if
|
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
options = {}
|
2022-04-07 06:31:16 +00:00
|
|
|
if m.options.options.videos <> invalid
|
|
|
|
options.videos = m.options.options.videos
|
|
|
|
end if
|
|
|
|
options.audios = tracks
|
|
|
|
m.options.options = options
|
2020-10-24 13:56:33 +00:00
|
|
|
|
2019-03-14 17:11:51 +00:00
|
|
|
end sub
|
|
|
|
|
2020-10-24 13:56:33 +00:00
|
|
|
|
2022-03-13 02:18:54 +00:00
|
|
|
sub SetDefaultAudioTrack(itemData)
|
|
|
|
for i = 0 to itemData.mediaStreams.Count() - 1
|
|
|
|
if itemData.mediaStreams[i].Type = "Audio"
|
|
|
|
m.top.selectedAudioStreamIndex = i
|
|
|
|
setFieldText("audio_codec", tr("Audio") + ": " + itemData.mediaStreams[i].displayTitle)
|
|
|
|
exit for
|
|
|
|
end if
|
|
|
|
end for
|
|
|
|
end sub
|
|
|
|
|
2019-09-24 04:35:26 +00:00
|
|
|
sub setFieldText(field, value)
|
2021-07-09 20:08:32 +00:00
|
|
|
node = m.top.findNode(field)
|
|
|
|
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"
|
|
|
|
value = str(value)
|
|
|
|
else if type(value) = "roFloat" or type(value) = "Float"
|
|
|
|
value = str(value)
|
|
|
|
else if type(value) <> "roString" and type(value) <> "String"
|
|
|
|
value = ""
|
|
|
|
end if
|
|
|
|
|
|
|
|
node.text = value
|
2019-03-14 17:11:51 +00:00
|
|
|
end sub
|
|
|
|
|
2019-05-03 12:48:59 +00:00
|
|
|
function getRuntime() as integer
|
2022-03-13 08:46:03 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
itemData = m.top.itemContent.json
|
2019-03-14 17:11:51 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
' A tick is .1ms, so 1/10,000,000 for ticks to seconds,
|
|
|
|
' then 1/60 for seconds to minutess... 1/600,000,000
|
|
|
|
return round(itemData.RunTimeTicks / 600000000.0)
|
2019-03-14 17:11:51 +00:00
|
|
|
end function
|
|
|
|
|
|
|
|
function getEndTime() as string
|
2021-07-09 20:08:32 +00:00
|
|
|
itemData = m.top.itemContent.json
|
2019-03-14 17:11:51 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
date = CreateObject("roDateTime")
|
|
|
|
duration_s = int(itemData.RunTimeTicks / 10000000.0)
|
|
|
|
date.fromSeconds(date.asSeconds() + duration_s)
|
|
|
|
date.toLocalTime()
|
2019-03-14 17:11:51 +00:00
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
return formatTime(date)
|
2019-03-14 17:11:51 +00:00
|
|
|
end function
|
|
|
|
|
|
|
|
sub setFavoriteColor()
|
2021-07-09 20:08:32 +00:00
|
|
|
fave = m.top.itemContent.favorite
|
|
|
|
fave_button = m.top.findNode("favorite-button")
|
|
|
|
if fave <> invalid and fave
|
|
|
|
fave_button.textColor = "#00ff00ff"
|
|
|
|
fave_button.focusedTextColor = "#269926ff"
|
2022-05-11 16:07:38 +00:00
|
|
|
fave_button.text = tr("Favorite")
|
2021-07-09 20:08:32 +00:00
|
|
|
else
|
|
|
|
fave_button.textColor = "0xddddddff"
|
|
|
|
fave_button.focusedTextColor = "#262626ff"
|
2022-05-11 16:07:38 +00:00
|
|
|
fave_button.text = tr("Set Favorite")
|
2021-07-09 20:08:32 +00:00
|
|
|
end if
|
2019-03-14 17:11:51 +00:00
|
|
|
end sub
|
|
|
|
|
|
|
|
sub setWatchedColor()
|
2021-07-09 20:08:32 +00:00
|
|
|
watched = m.top.itemContent.watched
|
|
|
|
watched_button = m.top.findNode("watched-button")
|
|
|
|
if watched
|
|
|
|
watched_button.textColor = "#ff0000ff"
|
|
|
|
watched_button.focusedTextColor = "#992626ff"
|
2022-05-11 16:07:38 +00:00
|
|
|
watched_button.text = tr("Watched")
|
2021-07-09 20:08:32 +00:00
|
|
|
else
|
|
|
|
watched_button.textColor = "0xddddddff"
|
|
|
|
watched_button.focusedTextColor = "#262626ff"
|
2022-05-11 16:07:38 +00:00
|
|
|
watched_button.text = tr("Set Watched")
|
2021-07-09 20:08:32 +00:00
|
|
|
end if
|
2019-03-14 17:11:51 +00:00
|
|
|
end sub
|
|
|
|
|
2019-05-03 12:48:59 +00:00
|
|
|
function round(f as float) as integer
|
2021-07-09 20:08:32 +00:00
|
|
|
' BrightScript only has a "floor" round
|
|
|
|
' This compares floor to floor + 1 to find which is closer
|
|
|
|
m = int(f)
|
|
|
|
n = m + 1
|
|
|
|
x = abs(f - m)
|
|
|
|
y = abs(f - n)
|
|
|
|
if y > x
|
|
|
|
return m
|
|
|
|
else
|
|
|
|
return n
|
|
|
|
end if
|
2019-03-14 17:11:51 +00:00
|
|
|
end function
|
2020-10-24 13:56:33 +00:00
|
|
|
|
|
|
|
'
|
|
|
|
'Check if options updated and any reloading required
|
2022-03-13 00:36:11 +00:00
|
|
|
sub audioOptionsClosed()
|
2022-04-07 06:31:16 +00:00
|
|
|
if m.options.audioStreamIndex <> m.top.selectedAudioStreamIndex
|
|
|
|
m.top.selectedAudioStreamIndex = m.options.audioStreamIndex
|
2021-07-09 20:08:32 +00:00
|
|
|
setFieldText("audio_codec", tr("Audio") + ": " + m.top.itemContent.json.mediaStreams[m.top.selectedAudioStreamIndex].displayTitle)
|
|
|
|
end if
|
|
|
|
m.top.findNode("buttons").setFocus(true)
|
2020-10-24 13:56:33 +00:00
|
|
|
end sub
|
|
|
|
|
2022-03-13 02:18:54 +00:00
|
|
|
'
|
|
|
|
' Check if options were updated and if any reloding is needed...
|
2022-03-13 00:36:11 +00:00
|
|
|
sub videoOptionsClosed()
|
2022-04-07 06:31:16 +00:00
|
|
|
if m.options.videoStreamId <> m.top.selectedVideoStreamId
|
|
|
|
m.top.selectedVideoStreamId = m.options.videoStreamId
|
|
|
|
setFieldText("video_codec", tr("Video") + ": " + m.options.video_codec)
|
2022-03-13 02:18:54 +00:00
|
|
|
' Because the video stream has changed (i.e. the actual video)... we need to reload the audio stream choices for that video
|
|
|
|
m.top.unobservefield("itemContent")
|
|
|
|
itemData = m.top.itemContent.json
|
|
|
|
for each mediaSource in itemData.mediaSources
|
|
|
|
if mediaSource.id = m.top.selectedVideoStreamId
|
|
|
|
itemData.mediaStreams = []
|
|
|
|
for i = 0 to mediaSource.mediaStreams.Count() - 1
|
|
|
|
itemData.mediaStreams.push(mediaSource.mediaStreams[i])
|
|
|
|
end for
|
|
|
|
SetDefaultAudioTrack(itemData)
|
|
|
|
SetUpAudioOptions(itemData.mediaStreams)
|
|
|
|
exit for
|
|
|
|
end if
|
2022-03-13 02:20:21 +00:00
|
|
|
end for
|
2022-03-13 02:18:54 +00:00
|
|
|
m.top.itemContent.json = itemData
|
|
|
|
m.top.observeField("itemContent", "itemContentChanged")
|
2022-03-13 00:36:11 +00:00
|
|
|
end if
|
|
|
|
m.top.findNode("buttons").setFocus(true)
|
|
|
|
end sub
|
2020-10-24 13:56:33 +00:00
|
|
|
|
|
|
|
function onKeyEvent(key as string, press as boolean) as boolean
|
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
' 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
|
2022-04-07 06:31:16 +00:00
|
|
|
if key = "OK" and m.top.findNode("options-button").isInFocusChain()
|
|
|
|
m.options.visible = true
|
|
|
|
m.options.setFocus(true)
|
2021-07-09 20:08:32 +00:00
|
|
|
end if
|
2020-10-24 13:56:33 +00:00
|
|
|
|
2022-03-13 08:46:03 +00:00
|
|
|
if key = "down" and m.buttonGrp.isInFocusChain()
|
2022-08-20 08:54:36 +00:00
|
|
|
m.top.lastFocus = m.extrasGrid
|
2022-03-13 08:46:03 +00:00
|
|
|
m.extrasGrid.setFocus(true)
|
|
|
|
m.top.findNode("VertSlider").reverse = false
|
|
|
|
m.top.findNode("extrasFader").reverse = false
|
|
|
|
m.top.findNode("pplAnime").control = "start"
|
|
|
|
return true
|
|
|
|
end if
|
|
|
|
|
|
|
|
if key = "up" and m.top.findNode("extrasGrid").isInFocusChain()
|
|
|
|
if m.extrasGrid.itemFocused = 0
|
2022-08-20 08:54:36 +00:00
|
|
|
m.top.lastFocus = m.buttonGrp
|
2022-03-13 08:46:03 +00:00
|
|
|
m.top.findNode("VertSlider").reverse = true
|
|
|
|
m.top.findNode("extrasFader").reverse = true
|
|
|
|
m.top.findNode("pplAnime").control = "start"
|
|
|
|
m.buttonGrp.setFocus(true)
|
|
|
|
return true
|
|
|
|
end if
|
|
|
|
end if
|
|
|
|
|
2021-07-09 20:08:32 +00:00
|
|
|
if not press then return false
|
|
|
|
|
2022-03-13 00:36:11 +00:00
|
|
|
if key = "back"
|
2022-04-07 06:31:16 +00:00
|
|
|
if m.options.visible = true
|
|
|
|
m.options.visible = false
|
2022-03-13 00:36:11 +00:00
|
|
|
videoOptionsClosed()
|
2022-04-07 06:31:16 +00:00
|
|
|
audioOptionsClosed()
|
2021-07-09 20:08:32 +00:00
|
|
|
return true
|
|
|
|
end if
|
|
|
|
end if
|
|
|
|
return false
|
2022-03-13 08:46:03 +00:00
|
|
|
end function
|