Remove optional chaining operators from code (#1085)

* remove optional chaining operators + use isValid() + remove extra white space
* address reviewer feedback
This commit is contained in:
Charles Ewert 2023-03-09 14:35:29 -05:00 committed by GitHub
parent 318668db5b
commit 25f03915ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 108 additions and 162 deletions

View File

@ -22,7 +22,7 @@ sub init()
'Parent is MarkupGrid and it's parent is the ItemGrid
m.topParent = m.top.GetParent().GetParent()
'Get the imageDisplayMode for these grid items
if m.topParent.imageDisplayMode <> invalid
if isValid(m.topParent.imageDisplayMode)
m.itemPoster.loadDisplayMode = m.topParent.imageDisplayMode
end if
@ -44,7 +44,7 @@ sub itemContentChanged()
m.itemText.text = itemData.Title
else if itemData.type = "Series"
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
if itemData?.json?.UserData?.UnplayedItemCount <> invalid
if isValid(itemData.json) and isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
if itemData.json.UserData.UnplayedItemCount > 0
m.unplayedCount.visible = true
m.unplayedEpisodeCount.text = itemData.json.UserData.UnplayedItemCount
@ -98,7 +98,7 @@ sub itemContentChanged()
m.posterText.height = 200
m.posterText.width = 280
else if itemData.json.type = "MusicAlbum"
else if isValid(itemData.json.type) and itemData.json.type = "MusicAlbum"
m.itemPoster.uri = itemData.PosterUrl
m.itemText.text = itemData.Title

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<component name="GridItem" extends="Group">
<children>
<maskGroup id="posterMask" maskUri="pkg:/images/postermask.png" scaleRotateCenter="[145, 212.5]" scale="[0.85,0.85]">
@ -20,4 +20,5 @@
</interface>
<script type="text/brightscript" uri="GridItem.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
</component>
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
</component>

View File

@ -4,7 +4,7 @@ sub init()
m.top.limit = 60
usersettingLimit = get_user_setting("itemgrid.Limit")
if usersettingLimit <> invalid
if isValid(usersettingLimit)
m.top.limit = usersettingLimit
end if
end sub
@ -135,7 +135,7 @@ sub LoadItems_AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtit
if m.playbackInfo.MediaSources[0].MediaStreams.Count() > 0 and meta.live = false
tryDirectPlay = get_user_setting("playback.tryDirect.h264ProfileLevel") = "true" and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
tryDirectPlay = tryDirectPlay or (get_user_setting("playback.tryDirect.hevcProfileLevel") = "true" and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
if tryDirectPlay and m.playbackInfo.MediaSources[0].TranscodingUrl <> invalid and forceTranscoding = false
if tryDirectPlay and isValid(m.playbackInfo.MediaSources[0].TranscodingUrl) and forceTranscoding = false
transcodingReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
if transcodingReasons.Count() = 1 and transcodingReasons[0] = "VideoLevelNotSupported"
video.directPlaySupported = true
@ -262,7 +262,7 @@ end function
function directPlaySupported(meta as object) as boolean
devinfo = CreateObject("roDeviceInfo")
if meta.json.MediaSources[0] <> invalid and meta.json.MediaSources[0].SupportsDirectPlay = false
if isValid(meta.json.MediaSources[0]) and meta.json.MediaSources[0].SupportsDirectPlay = false
return false
end if
@ -271,10 +271,10 @@ function directPlaySupported(meta as object) as boolean
end if
streamInfo = { Codec: meta.json.MediaStreams[0].codec }
if meta.json.MediaStreams[0].Profile <> invalid and meta.json.MediaStreams[0].Profile.len() > 0
if isValid(meta.json.MediaStreams[0].Profile) and meta.json.MediaStreams[0].Profile.len() > 0
streamInfo.Profile = LCase(meta.json.MediaStreams[0].Profile)
end if
if meta.json.MediaSources[0].container <> invalid and meta.json.MediaSources[0].container.len() > 0
if isValid(meta.json.MediaSources[0].container) and meta.json.MediaSources[0].container.len() > 0
'CanDecodeVideo() requires the .container to be format: “mp4”, “hls”, “mkv”, “ism”, “dash”, “ts” if its to direct stream
if meta.json.MediaSources[0].container = "mov"
streamInfo.Container = "mp4"
@ -333,12 +333,12 @@ sub autoPlayNextEpisode(videoID as string, showID as string)
resp = APIRequest(url, urlParams)
data = getJson(resp)
if data <> invalid and data.Items.Count() = 2
if isValid(data) and data.Items.Count() = 2
' setup new video node
nextVideo = invalid
' remove last videoplayer scene
m.global.sceneManager.callFunc("clearPreviousScene")
if nextVideo <> invalid
if isValid(nextVideo)
m.global.sceneManager.callFunc("pushScene", nextVideo)
else
m.global.sceneManager.callFunc("popScene")
@ -356,7 +356,7 @@ end sub
' In the future, with a custom playback info view, we can return an associated array.
function GetPlaybackInfo()
sessions = api_API().sessions.get()
if sessions <> invalid and sessions.Count() > 0
if isValid(sessions) and sessions.Count() > 0
return GetTranscodingStats(sessions[0])
end if
@ -507,7 +507,7 @@ end function
' returns the server-side track index for the appriate subtitle
function defaultSubtitleTrackFromVid(video_id) as integer
meta = ItemMetaData(video_id)
if meta?.json?.mediaSources <> invalid
if isValid(meta) and isValid(meta.json) and isValid(meta.json.mediaSources)
subtitles = sortSubtitles(meta.id, meta.json.MediaSources[0].MediaStreams)
default_text_subs = defaultSubtitleTrack(subtitles["all"], true) ' Find correct subtitle track (forced text)
if default_text_subs <> -1
@ -608,7 +608,7 @@ function sortSubtitles(id as string, MediaStreams)
if stream.type = "Subtitle"
url = ""
if stream.DeliveryUrl <> invalid
if isValid(stream.DeliveryUrl)
url = buildURL(stream.DeliveryUrl)
end if

View File

@ -18,9 +18,8 @@ sub init()
end sub
sub updateSize()
image = invalid
if m.top.itemContent <> invalid and m.top.itemContent.image <> invalid
if isValid(m.top.itemContent) and isValid(m.top.itemContent.image)
image = m.top.itemContent.image
end if
@ -49,7 +48,6 @@ sub updateSize()
m.backdrop.width = m.poster.width
m.backdrop.height = m.poster.height
end sub
sub itemContentChanged() as void
@ -58,7 +56,7 @@ sub itemContentChanged() as void
m.title.text = itemData.title
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
if itemData?.json?.UserData?.UnplayedItemCount <> invalid
if isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
if itemData.json.UserData.UnplayedItemCount > 0
m.unplayedCount.visible = true
m.unplayedEpisodeCount.text = itemData.json.UserData.UnplayedItemCount
@ -66,12 +64,11 @@ sub itemContentChanged() as void
end if
end if
if itemData.json.lookup("Type") = "Episode" and itemData.json.IndexNumber <> invalid
if itemData.json.lookup("Type") = "Episode" and isValid(itemData.json.IndexNumber)
m.title.text = StrI(itemData.json.IndexNumber) + ". " + m.title.text
m.series.text = itemData.json.Series
m.series.visible = true
else if itemData.json.lookup("Type") = "MusicAlbum"
m.title.font = "font:SmallestSystemFont"
m.staticTitle.font = "font:SmallestSystemFont"
@ -83,8 +80,7 @@ sub itemContentChanged() as void
imageUrl = itemData.posterURL
if get_user_setting("ui.tvshows.blurunwatched") = "true"
if itemData.json.lookup("Type") = "Episode" and itemData.json.userdata <> invalid
if itemData.json.lookup("Type") = "Episode" and isValid(itemData.json.userdata)
if not itemData.json.userdata.played
imageUrl = imageUrl + "&blur=15"
end if
@ -99,25 +95,21 @@ end sub
'
' Enable title scrolling based on item Focus
sub focusChanged()
if m.top.itemHasFocus = true
m.title.repeatCount = -1
m.series.repeatCount = -1
m.staticTitle.visible = false
m.title.visible = true
' text to speech for accessibility
if m.deviceInfo.IsAudioGuideEnabled() = true
txt2Speech = CreateObject("roTextToSpeech")
txt2Speech.Flush()
txt2Speech.Say(m.title.text)
end if
else
m.title.repeatCount = 0
m.series.repeatCount = 0
m.staticTitle.visible = true
m.title.visible = false
end if
end sub

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<component name="ListPoster" extends="Group">
<children>
<Rectangle id="backdrop" />
@ -12,10 +12,11 @@
<Label id="staticTitle" horizAlign="center" font="font:SmallSystemFont" wrap="false" />
</children>
<interface>
<field id="itemContent" type="node" onChange="itemContentChanged"/>
<field id="itemContent" type="node" onChange="itemContentChanged" />
<field id="itemWidth" type="integer" />
<field id="itemHasFocus" type="boolean" onChange="focusChanged" />
</interface>
<script type="text/brightscript" uri="ListPoster.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
</component>
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
</component>

View File

@ -33,13 +33,13 @@ sub itemContentChanged()
m.backdrop.width = itemData.imageWidth
if itemData.iconUrl <> invalid
if isValid(itemData.iconUrl)
m.itemIcon.uri = itemData.iconUrl
end if
if LCase(itemData.type) = "series"
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
if itemData?.json?.UserData?.UnplayedItemCount <> invalid
if isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
if itemData.json.UserData.UnplayedItemCount > 0
m.unplayedCount.visible = true
m.unplayedEpisodeCount.text = itemData.json.UserData.UnplayedItemCount
@ -84,7 +84,7 @@ sub itemContentChanged()
end if
' Set Episode title if available
if itemData.json.EpisodeTitle <> invalid
if isValid(itemData.json.EpisodeTitle)
m.itemTextExtra.text = itemData.json.EpisodeTitle
end if
@ -106,10 +106,10 @@ sub itemContentChanged()
' Set Series and Episode Number for Extra Text
extraPrefix = ""
if itemData.json.ParentIndexNumber <> invalid
if isValid(itemData.json.ParentIndexNumber)
extraPrefix = "S" + StrI(itemData.json.ParentIndexNumber).trim()
end if
if itemData.json.IndexNumber <> invalid
if isValid(itemData.json.IndexNumber)
extraPrefix = extraPrefix + "E" + StrI(itemData.json.IndexNumber).trim()
end if
if extraPrefix.len() > 0
@ -136,10 +136,10 @@ sub itemContentChanged()
' Set Release Year and Age Rating for Extra Text
textExtra = ""
if itemData.json.ProductionYear <> invalid
if isValid(itemData.json.ProductionYear)
textExtra = StrI(itemData.json.ProductionYear).trim()
end if
if itemData.json.OfficialRating <> invalid
if isValid(itemData.json.OfficialRating)
if textExtra <> ""
textExtra = textExtra + " - " + itemData.json.OfficialRating
else
@ -181,14 +181,14 @@ sub itemContentChanged()
end if
textExtra = ""
if itemData.json.ProductionYear <> invalid
if isValid(itemData.json.ProductionYear)
textExtra = StrI(itemData.json.ProductionYear).trim()
end if
' Set Years Run for Extra Text
if itemData.json.Status = "Continuing"
textExtra = textExtra + " - Present"
else if itemData.json.Status = "Ended" and itemData.json.EndDate <> invalid
else if itemData.json.Status = "Ended" and isValid(itemData.json.EndDate)
textExtra = textExtra + " - " + LEFT(itemData.json.EndDate, 4)
end if
m.itemTextExtra.text = textExtra

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<component name="HomeItem" extends="Group">
<children>
<Rectangle id="backdrop" width="464" height="261" translation="[8,5]" />
@ -26,4 +26,5 @@
<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" />
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
</component>

View File

@ -96,7 +96,7 @@ sub onLibrariesLoaded()
m.LoadFavoritesTask.control = "RUN"
' validate library data
if m.libraryData <> invalid and m.libraryData.count() > 0
if isValid(m.libraryData) and m.libraryData.count() > 0
userConfig = m.top.userConfig
' populate My Media row
@ -163,7 +163,7 @@ sub updateFavoritesItems()
rowIndex = getRowIndex("Favorites")
if itemData.count() < 1
if rowIndex <> invalid
if isValid(rowIndex)
' remove the row
deleteFromSizeArray(rowIndex)
homeRows.removeChildIndex(rowIndex)
@ -208,7 +208,7 @@ sub updateContinueItems()
continueRowIndex = getRowIndex("Continue Watching")
if itemData.count() < 1
if continueRowIndex <> invalid
if isValid(continueRowIndex)
' remove the row
deleteFromSizeArray(continueRowIndex)
homeRows.removeChildIndex(continueRowIndex)
@ -219,7 +219,7 @@ sub updateContinueItems()
row.title = tr("Continue Watching")
itemSize = [464, 331]
for each item in itemData
if item.json?.UserData?.PlayedPercentage <> invalid
if isValid(item.json) and isValid(item.json.UserData) and isValid(item.json.UserData.PlayedPercentage)
item.PlayedPercentage = item.json.UserData.PlayedPercentage
end if
@ -250,7 +250,7 @@ sub updateNextUpItems()
nextUpRowIndex = getRowIndex("Next Up >")
if itemData.count() < 1
if nextUpRowIndex <> invalid
if isValid(nextUpRowIndex)
' remove the row
deleteFromSizeArray(nextUpRowIndex)
homeRows.removeChildIndex(nextUpRowIndex)
@ -269,7 +269,7 @@ sub updateNextUpItems()
if nextUpRowIndex = invalid
' insert new row under "Continue Watching"
continueRowIndex = getRowIndex("Continue Watching")
if continueRowIndex <> invalid
if isValid(continueRowIndex)
updateSizeArray(itemSize, continueRowIndex + 1)
homeRows.insertChild(row, continueRowIndex + 1)
else
@ -305,7 +305,7 @@ sub updateLatestItems(msg)
if itemData.count() < 1
' remove row
if rowIndex <> invalid
if isValid(rowIndex)
deleteFromSizeArray(rowIndex)
homeRows.removeChildIndex(rowIndex)
end if
@ -355,7 +355,7 @@ sub updateOnNowItems()
onNowRowIndex = getRowIndex("On Now")
if itemData.count() < 1
if onNowRowIndex <> invalid
if isValid(onNowRowIndex)
' remove the row
deleteFromSizeArray(onNowRowIndex)
homeRows.removeChildIndex(onNowRowIndex)
@ -409,11 +409,11 @@ sub updateSizeArray(rowItemSize, rowIndex = invalid, action = "insert")
newSizeArray.Push(rowItemSize)
else if action = "insert"
newSizeArray.Push(rowItemSize)
if sizeArray[i] <> invalid
if isValid(sizeArray[i])
newSizeArray.Push(sizeArray[i])
end if
end if
else if sizeArray[i] <> invalid
else if isValid(sizeArray[i])
newSizeArray.Push(sizeArray[i])
end if
end for
@ -433,7 +433,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
if press
if key = "play"
itemToPlay = m.top.content.getChild(m.top.rowItemFocused[0]).getChild(m.top.rowItemFocused[1])
if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
if isValid(itemToPlay) and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
m.top.quickPlayNode = itemToPlay
end if
handled = true

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<component name="HomeRows" extends="RowList">
<interface>
<field id="selectedItem" type="node" alwaysNotify="true" />
@ -7,5 +7,6 @@
<function name="updateHomeRows" />
<function name="loadLibraries" />
</interface>
<script type="text/brightscript" uri="HomeRows.brs"/>
</component>
<script type="text/brightscript" uri="HomeRows.brs" />
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
</component>

View File

@ -4,7 +4,6 @@ sub init()
m.position = 0
end sub
'
' Clear all content from play queue
sub clear()
m.queue = []
@ -12,72 +11,52 @@ sub clear()
setPosition(0)
end sub
'
' Delete item from play queue at passed index
sub deleteAtIndex(index)
m.queue.Delete(index)
m.queueTypes.Delete(index)
end sub
'
' Return the number of items in the play queue
function getCount()
return m.queue.count()
end function
'
' Return the item currently in focus from the play queue
function getCurrentItem()
return getItemByIndex(m.position)
end function
'
' Return the item in the passed index from the play queue
function getItemByIndex(index)
return m.queue[index]
end function
'
' Returns current playback position within the queue
function getPosition()
return m.position
end function
'
' Move queue position back one
sub moveBack()
m.position--
end sub
'
' Move queue position ahead one
sub moveForward()
m.position++
end sub
'
' Return the current play queue
function getQueue()
return m.queue
end function
'
' Return the types of items in current play queue
function getQueueTypes()
return m.queueTypes
end function
'
' Return the unique types of items in current play queue
function getQueueUniqueTypes()
itemTypes = []
@ -91,15 +70,11 @@ function getQueueUniqueTypes()
return itemTypes
end function
'
' Return item at end of play queue without removing
function peek()
return m.queue.peek()
end function
'
' Play items in queue
sub playQueue()
nextItem = getCurrentItem()
@ -116,37 +91,28 @@ sub playQueue()
end if
end sub
'
' Remove item at end of play queue
sub pop()
m.queue.pop()
m.queueTypes.pop()
end sub
'
' Push new items to the play queue
sub push(newItem)
m.queue.push(newItem)
m.queueTypes.push(getItemType(newItem))
end sub
'
' Set the queue position
sub setPosition(newPosition)
m.position = newPosition
end sub
'
' Return the fitst item in the play queue
function top()
return getItemByIndex(0)
end function
'
' Replace play queue with passed array
sub set(items)
setPosition(0)
@ -157,10 +123,9 @@ sub set(items)
end sub
function getItemType(item) as string
if isValid(item?.json?.mediatype) and item.json.mediatype <> ""
if isValid(item) and isValid(item.json) and isValid(item.json.mediatype) and item.json.mediatype <> ""
return LCase(item.json.mediatype)
else if isValid(item?.type) and item.type <> ""
else if isValid(item) and isValid(item.type) and item.type <> ""
return LCase(item.type)
end if

View File

@ -1,7 +1,3 @@
'
' View Creators
' ----------------
' Play Audio
sub CreateAudioPlayerView()
m.view = CreateObject("roSGNode", "AudioPlayerView")
@ -26,14 +22,12 @@ sub CreateVideoPlayerView()
m.global.sceneManager.callFunc("pushScene", m.view)
end sub
'
' -----------------
' Event Handlers
' -----------------
' User requested subtitle selection popup
sub onSelectSubtitlePressed()
' None is always first in the subtitle list
subtitleData = {
data: [{ "description": "None", "type": "subtitleselection" }]
@ -80,9 +74,8 @@ end sub
' User requested playback info
sub onSelectPlaybackInfoPressed()
' Check if we already have playback info and show it in a popup
if isValid(m.playbackData?.playbackinfo)
if isValid(m.playbackData) and isValid(m.playbackData.playbackinfo)
m.global.sceneManager.callFunc("standardDialog", tr("Playback Info"), m.playbackData.playbackinfo)
return
end if
@ -95,12 +88,11 @@ sub onPlaybackInfoLoaded()
m.playbackData = m.getPlaybackInfoTask.data
' Check if we have playback info and show it in a popup
if isValid(m.playbackData?.playbackinfo)
if isValid(m.playbackData) and isValid(m.playbackData.playbackinfo)
m.global.sceneManager.callFunc("standardDialog", tr("Playback Info"), m.playbackData.playbackinfo)
end if
end sub
' Playback state change event handlers
sub onStateChange()
if LCase(m.view.state) = "finished"

View File

@ -19,7 +19,7 @@ end sub
sub updateSeason()
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
if m.top.seasonData?.UserData?.UnplayedItemCount <> invalid
if isValid(m.top.seasonData) and isValid(m.top.seasonData.UserData) and isValid(m.top.seasonData.UserData.UnplayedItemCount)
if m.top.seasonData.UserData.UnplayedItemCount > 0
m.unplayedCount.visible = true
m.unplayedEpisodeCount.text = m.top.seasonData.UserData.UnplayedItemCount
@ -57,7 +57,6 @@ function onKeyEvent(key as string, press as boolean) as boolean
return true
end if
if key = "OK" or key = "play"
if m.Random.hasFocus()
randomEpisode = Rnd(m.rows.getChild(0).objects.items.count()) - 1
@ -81,7 +80,6 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
end if
focusedChild = m.top.focusedChild.focusedChild
if focusedChild.content = invalid then return handled
@ -94,7 +92,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
if press and key = "play" or proceed = true
m.top.lastFocus = focusedChild
itemToPlay = focusedChild.content.getChild(focusedChild.rowItemFocused[0]).getChild(0)
if itemToPlay <> invalid and itemToPlay.id <> ""
if isValid(itemToPlay) and isValid(itemToPlay.id) and itemToPlay.id <> ""
itemToPlay.type = "Episode"
m.top.quickPlayNode = itemToPlay
end if

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<component name="TVEpisodes" extends="JFGroup">
<children>
<Poster id="seasonPoster" width="300" height="450" translation="[95,175]">
@ -20,4 +20,5 @@
<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>
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
</component>

View File

@ -18,7 +18,7 @@ end sub
sub itemContentChanged()
item = m.top.itemContent
itemData = item.json
if itemData.indexNumber <> invalid
if isValid(itemData.indexNumber)
indexNumber = itemData.indexNumber.toStr() + ". "
else
indexNumber = ""
@ -26,7 +26,7 @@ sub itemContentChanged()
m.title.text = indexNumber + item.title
m.overview.text = item.overview
if itemData.PremiereDate <> invalid
if isValid(itemData.PremiereDate)
airDate = CreateObject("roDateTime")
airDate.FromISO8601String(itemData.PremiereDate)
m.top.findNode("aired").text = tr("Aired") + ": " + airDate.AsDateString("short-month-no-weekday")
@ -70,12 +70,12 @@ sub itemContentChanged()
end if
' Add checkmark in corner (if applicable)
if isValid(itemData?.UserData?.Played) and itemData.UserData.Played = true
if isValid(itemData.UserData) and isValid(itemData.UserData.Played) and itemData.UserData.Played = true
m.playedIndicator.visible = true
end if
' Add progress bar on bottom (if applicable)
if isValid(itemData?.UserData?.PlayedPercentage) and itemData?.UserData?.PlayedPercentage > 0
if isValid(itemData.UserData) and isValid(itemData.UserData.PlayedPercentage) and itemData.UserData.PlayedPercentage > 0
m.progressBackground.width = m.poster.width
m.progressBackground.visible = true
progressWidthInPixels = int(m.progressBackground.width * itemData.UserData.PlayedPercentage / 100)
@ -86,7 +86,7 @@ sub itemContentChanged()
videoIdx = invalid
audioIdx = invalid
if itemData.MediaStreams <> invalid
if isValid(itemData.MediaStreams)
for i = 0 to itemData.MediaStreams.Count() - 1
if itemData.MediaStreams[i].Type = "Video" and videoIdx = invalid
videoIdx = i
@ -99,12 +99,12 @@ sub itemContentChanged()
end if
m.top.findNode("audio_codec").text = tr("Audio") + ": " + itemData.mediaStreams[audioIdx].DisplayTitle
end if
if videoIdx <> invalid and audioIdx <> invalid then exit for
if isValid(videoIdx) and isValid(audioIdx) then exit for
end for
end if
m.top.findNode("video_codec").visible = videoIdx <> invalid
if audioIdx <> invalid
m.top.findNode("video_codec").visible = isValid(videoIdx)
if isValid(audioIdx)
m.top.findNode("audio_codec").visible = true
DisplayAudioAvailable(itemData.mediaStreams)
else
@ -113,7 +113,6 @@ sub itemContentChanged()
end sub
sub DisplayAudioAvailable(streams)
count = 0
for i = 0 to streams.Count() - 1
if streams[i].Type = "Audio"
@ -124,7 +123,6 @@ sub DisplayAudioAvailable(streams)
if count > 1
m.top.findnode("audio_codec_count").text = "+" + stri(count - 1).trim()
end if
end sub
function getRuntime() as integer

View File

@ -17,7 +17,7 @@ sub itemContentChanged()
itemData = item.json
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
if itemData?.UserData?.UnplayedItemCount <> invalid
if isValid(itemData.UserData) and isValid(itemData.UserData.UnplayedItemCount)
if itemData.UserData.UnplayedItemCount > 0
m.unplayedCount.visible = true
m.unplayedEpisodeCount.text = itemData.UserData.UnplayedItemCount
@ -31,21 +31,21 @@ sub itemContentChanged()
m.top.overhangTitle = itemData.name
'Check production year, if invalid remove label
if itemData.productionYear <> invalid
if isValid(itemData.productionYear)
setFieldText("releaseYear", itemData.productionYear)
else
m.top.findNode("main_group").removeChild(m.top.findNode("releaseYear"))
end if
'Check officialRating, if invalid remove label
if itemData.officialRating <> invalid
if isValid(itemData.officialRating)
setFieldText("officialRating", itemData.officialRating)
else
m.top.findNode("main_group").removeChild(m.top.findNode("officialRating"))
end if
'Check communityRating, if invalid remove label
if itemData.communityRating <> invalid
if isValid(itemData.communityRating)
m.top.findNode("star").visible = true
setFieldText("communityRating", int(itemData.communityRating * 10) / 10)
else
@ -134,7 +134,7 @@ function getHistory() as string
airdays = itemData.airdays
airtime = itemData.airtime
if airtime <> invalid and airdays.count() = 1
if isValid(airtime) and airdays.count() = 1
airwords = airdays[0] + " at " + airtime
end if
@ -148,10 +148,10 @@ function getHistory() as string
end if
words = verb
if airwords <> invalid
if isValid(airwords)
words = words + " " + airwords
end if
if studio <> invalid
if isValid(studio)
words = words + " on " + studio
end if

View File

@ -31,10 +31,10 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
' Special handling for "Programs" or "Vidoes" launched from "On Now" or elsewhere on the home screen...
' basically anything that is a Live Channel.
if isValid(meta?.json?.ChannelId)
if meta.json.EpisodeTitle <> invalid
if isValid(meta.json) and isValid(meta.json.ChannelId)
if isValid(meta.json.EpisodeTitle)
meta.title = meta.json.EpisodeTitle
else if meta.json.Name <> invalid
else if isValid(meta.json.Name)
meta.title = meta.json.Name
end if
meta.showID = meta.json.id
@ -243,11 +243,9 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
video.content.SubtitleTracks = subtitles["text"]
' 'TODO: allow user selection of subtitle track before playback initiated, for now set to no subtitles
video.directPlaySupported = m.playbackInfo.MediaSources[0].SupportsDirectPlay
fully_external = false
' For h264/hevc video, Roku spec states that it supports specfic encoding levels
' The device can decode content with a Higher Encoding level but may play it back with certain
' artifacts. If the user preference is set, and the only reason the server says we need to
@ -256,7 +254,7 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
if m.playbackInfo.MediaSources[0].MediaStreams.Count() > 0 and meta.live = false
tryDirectPlay = get_user_setting("playback.tryDirect.h264ProfileLevel") = "true" and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
tryDirectPlay = tryDirectPlay or (get_user_setting("playback.tryDirect.hevcProfileLevel") = "true" and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
if tryDirectPlay and m.playbackInfo.MediaSources[0].TranscodingUrl <> invalid and forceTranscoding = false
if tryDirectPlay and isValid(m.playbackInfo.MediaSources[0].TranscodingUrl) and forceTranscoding = false
transcodingReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
if transcodingReasons.Count() = 1 and transcodingReasons[0] = "VideoLevelNotSupported"
video.directPlaySupported = true
@ -324,7 +322,6 @@ end sub
function PlayIntroVideo(video_id, audio_stream_idx) as boolean
' Intro videos only play if user has cinema mode setting enabled
if get_user_setting("playback.cinemamode") = "true"
' Check if server has intro videos setup and available
introVideos = GetIntroVideos(video_id)
@ -362,7 +359,6 @@ end function
' Extract array of Transcode Reasons from the content URL
' @returns Array of Strings
function getTranscodeReasons(url as string) as object
regex = CreateObject("roRegex", "&TranscodeReasons=([^&]*)", "")
match = regex.Match(url)
@ -384,19 +380,18 @@ end function
function directPlaySupported(meta as object) as boolean
devinfo = CreateObject("roDeviceInfo")
if meta.json.MediaSources[0] <> invalid and meta.json.MediaSources[0].SupportsDirectPlay = false
if isValid(meta.json.MediaSources[0]) and meta.json.MediaSources[0].SupportsDirectPlay = false
return false
end if
if meta.json.MediaStreams[0] = invalid
if not isValid(meta.json.MediaSources[0])
return false
end if
streamInfo = { Codec: meta.json.MediaStreams[0].codec }
if meta.json.MediaStreams[0].Profile <> invalid and meta.json.MediaStreams[0].Profile.len() > 0
if isValid(meta.json.MediaStreams[0].Profile) and meta.json.MediaStreams[0].Profile.len() > 0
streamInfo.Profile = LCase(meta.json.MediaStreams[0].Profile)
end if
if meta.json.MediaSources[0].container <> invalid and meta.json.MediaSources[0].container.len() > 0
if isValid(meta.json.MediaSources[0].container) and meta.json.MediaSources[0].container.len() > 0
'CanDecodeVideo() requires the .container to be format: “mp4”, “hls”, “mkv”, “ism”, “dash”, “ts” if its to direct stream
if meta.json.MediaSources[0].container = "mov"
streamInfo.Container = "mp4"
@ -406,8 +401,7 @@ function directPlaySupported(meta as object) as boolean
end if
decodeResult = devinfo.CanDecodeVideo(streamInfo)
return decodeResult <> invalid and decodeResult.result
return isValid(decodeResult) and decodeResult.result
end function
function getContainerType(meta as object) as string
@ -455,12 +449,12 @@ sub autoPlayNextEpisode(videoID as string, showID as string)
resp = APIRequest(url, urlParams)
data = getJson(resp)
if data <> invalid and data.Items.Count() = 2
if isValid(data) and data.Items.Count() = 2
' setup new video node
nextVideo = CreateVideoPlayerGroup(data.Items[1].Id, invalid, 1, false, false)
' remove last videoplayer scene
m.global.sceneManager.callFunc("clearPreviousScene")
if nextVideo <> invalid
if isValid(nextVideo)
m.global.sceneManager.callFunc("pushScene", nextVideo)
else
m.global.sceneManager.callFunc("popScene")
@ -478,7 +472,7 @@ end sub
' In the future, with a custom playback info view, we can return an associated array.
function GetPlaybackInfo()
sessions = api_API().sessions.get()
if sessions <> invalid and sessions.Count() > 0
if isValid(sessions) and sessions.Count() > 0
return GetTranscodingStats(sessions[0])
end if

View File

@ -38,7 +38,6 @@ function searchMedia(query as string)
' This appears to be done differently on the web now
' For each potential type, a separate query is done:
' varying item types, and artists, and people
if query <> ""
resp = APIRequest(Substitute("Search/Hints", get_setting("active_user")), {
"searchTerm": query,
@ -55,7 +54,6 @@ function searchMedia(query as string)
"limit": 100
})
data = getJson(resp)
results = []
for each item in data.SearchHints
@ -79,7 +77,7 @@ function ItemMetaData(id as string)
imgParams = {}
if data.type <> "Audio"
if data?.UserData?.PlayedPercentage <> invalid
if data.UserData <> invalid and data.UserData.PlayedPercentage <> invalid
param = { "PercentPlayed": data.UserData.PlayedPercentage }
imgParams.Append(param)
end if

View File

@ -21,7 +21,7 @@ end function
' returns the server-side track index for the appriate subtitle
function defaultSubtitleTrackFromVid(video_id) as integer
meta = ItemMetaData(video_id)
if meta?.json?.mediaSources <> invalid
if isValid(meta) and isValid(meta.json) and isValid(meta.json.mediaSources)
subtitles = sortSubtitles(meta.id, meta.json.MediaSources[0].MediaStreams)
default_text_subs = defaultSubtitleTrack(subtitles["all"], true) ' Find correct subtitle track (forced text)
if default_text_subs <> -1
@ -130,7 +130,7 @@ function selectSubtitleTrackDialog(tracks, currentTrack = -1)
default = ""
if item.IsForced then forced = " [Forced]"
if item.IsDefault then default = " - Default"
if item.Track.Language <> invalid
if isValid(item.Track.Language)
language = iso6392.lookup(item.Track.Language)
if language = invalid then language = item.Track.Language
else
@ -157,7 +157,7 @@ sub changeSubtitleDuringPlayback(newid)
currentSubtitles = video.Subtitles[video.SelectedSubtitle]
newSubtitles = video.Subtitles[newid]
if newSubtitles.IsEncoded or (currentSubtitles <> invalid and currentSubtitles.IsEncoded)
if newSubtitles.IsEncoded or (isValid(currentSubtitles) and currentSubtitles.IsEncoded)
' With encoded subtitles we need to stop/start playback
video.control = "stop"
AddVideoContent(video, video.mediaSourceId, video.audioIndex, newSubtitles.Index, video.position * 10000000)
@ -195,7 +195,7 @@ function sortSubtitles(id as string, MediaStreams)
if stream.type = "Subtitle"
url = ""
if stream.DeliveryUrl <> invalid
if isValid(stream.DeliveryUrl)
url = buildURL(stream.DeliveryUrl)
end if

View File

@ -91,19 +91,23 @@ function get_dialog_result(dialog, port)
end function
function lastFocusedChild(obj as object) as object
if LCase(obj.focusedChild.focusedChild.subType()) = "tvepisodes"
if isValid(obj?.focusedChild?.focusedChild?.lastFocus)
return obj.focusedChild.focusedChild.lastFocus
if isValid(obj)
if isValid(obj.focusedChild) and isValid(obj.focusedChild.focusedChild) and LCase(obj.focusedChild.focusedChild.subType()) = "tvepisodes"
if isValid(obj.focusedChild.focusedChild.lastFocus)
return obj.focusedChild.focusedChild.lastFocus
end if
end if
end if
child = obj
for i = 0 to obj.getChildCount()
if obj.focusedChild <> invalid
child = child.focusedChild
end if
end for
return child
child = obj
for i = 0 to obj.getChildCount()
if isValid(obj.focusedChild)
child = child.focusedChild
end if
end for
return child
else
return invalid
end if
end function
function show_dialog(message as string, options = [], defaultSelection = 0) as integer
@ -348,7 +352,7 @@ sub stopLoadingSpinner()
if isValid(m.spinner)
m.spinner.visible = false
end if
if isValid(m.scene?.dialog)
if isValid(m.scene) and isValid(m.scene.dialog)
m.scene.dialog.close = true
end if
end sub