diff --git a/components/ItemGrid/LoadVideoContentTask.bs b/components/ItemGrid/LoadVideoContentTask.bs index a63bb2b61..83cb4b0da 100644 --- a/components/ItemGrid/LoadVideoContentTask.bs +++ b/components/ItemGrid/LoadVideoContentTask.bs @@ -97,13 +97,27 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s end if end if + video.chapters = meta.json.Chapters + video.content.title = meta.title + video.showID = meta.showID + + logoLookupID = video.id + if videotype = "episode" or videotype = "series" video.content.contenttype = "episode" + video.seasonNumber = meta.json.ParentIndexNumber + video.episodeNumber = meta.json.IndexNumber + video.episodeNumberEnd = meta.json.IndexNumberEnd + + if isValid(meta.showID) + logoLookupID = meta.showID + end if end if - video.chapters = meta.json.Chapters - video.content.title = meta.title - video.showID = meta.showID + logoImageExists = api.items.HeadImageURLByName(logoLookupID, "logo") + if logoImageExists + video.logoImage = api.items.GetImageURL(logoLookupID, "logo", 0, { "maxHeight": 65, "maxWidth": 300, "quality": "90" }) + end if user = AboutMe() if user.Configuration.EnableNextEpisodeAutoPlay diff --git a/components/video/OSD.bs b/components/video/OSD.bs index 8904d04f3..4f687c7a4 100644 --- a/components/video/OSD.bs +++ b/components/video/OSD.bs @@ -1,10 +1,14 @@ import "pkg:/source/utils/misc.bs" +const LOGO_RIGHT_PADDING = 30 +const OPTIONCONTROLS_TOP_PADDING = 50 + sub init() m.videoControls = m.top.findNode("videoControls") m.optionControls = m.top.findNode("optionControls") m.inactivityTimer = m.top.findNode("inactivityTimer") + m.videoInfo = m.top.findNode("videoInfo") m.itemTitle = m.top.findNode("itemTitle") m.videoPlayPause = m.top.findNode("videoPlayPause") m.videoPositionTime = m.top.findNode("videoPositionTime") @@ -16,10 +20,16 @@ sub init() m.top.observeField("hasFocus", "onFocusChanged") m.top.observeField("progressPercentage", "onProgressPercentageChanged") m.top.observeField("playbackState", "onPlaybackStateChanged") + m.top.observeField("itemTitleText", "onItemTitleTextChanged") + m.top.observeField("seasonNumber", "onSeasonNumberChanged") + m.top.observeField("episodeNumber", "onEpisodeNumberChanged") + m.top.observeField("episodeNumberEnd", "onEpisodeNumberEndChanged") + m.top.observeField("logoImage", "onLogoImageChanged") m.defaultButtonIndex = 2 m.focusedButtonIndex = 2 + m.optionControlsMoved = false m.videoControls.buttonFocused = m.defaultButtonIndex m.optionControls.buttonFocused = m.optionControls.getChildCount() - 1 @@ -53,6 +63,92 @@ sub onItemTitleTextChanged() m.itemTitle.text = m.top.itemTitleText end sub +' onSeasonNumberChanged: Handler for changes to m.top.seasonNumber param. +' +sub onSeasonNumberChanged() + m.top.unobserveField("seasonNumber") + itemSeason = m.top.findNode("itemSeason") + itemSeason.font.size = 32 + itemSeason.text = `S${m.top.seasonNumber}` + + ' Move the option controls down to give room for season number + if not m.optionControlsMoved + moveOptionControls(0, OPTIONCONTROLS_TOP_PADDING) + m.optionControlsMoved = true + end if +end sub + +' onEpisodeNumberChanged: Handler for changes to m.top.episodeNumber param. +' +sub onEpisodeNumberChanged() + m.top.unobserveField("episodeNumber") + itemEpisode = m.top.findNode("itemEpisode") + itemEpisode.font.size = 32 + itemEpisode.text = `E${m.top.episodeNumber}` + + ' Move the option controls down to give room for episode number + if not m.optionControlsMoved + moveOptionControls(0, OPTIONCONTROLS_TOP_PADDING) + m.optionControlsMoved = true + end if +end sub + +' onEpisodeNumberEndChanged: Handler for changes to m.top.episodeNumberEnd param. +' +sub onEpisodeNumberEndChanged() + m.top.unobserveField("episodeNumberEnd") + itemEpisodeEnd = m.top.findNode("itemEpisodeEnd") + itemEpisodeEnd.font.size = 32 + itemEpisodeEnd.text = `-${m.top.episodeNumberEnd}` + + ' Move the option controls down to give room for episode number + if not m.optionControlsMoved + moveOptionControls(0, OPTIONCONTROLS_TOP_PADDING) + m.optionControlsMoved = true + end if +end sub + +' moveOptionControls: Moves option controls node based on passed pixel values +' +' @param {integer} horizontalPixels - Number of horizontal pixels to move option controls +' @param {integer} verticalPixels - Number of vertical pixels to move option controls +sub moveOptionControls(horizontalPixels as integer, verticalPixels as integer) + m.optionControls.translation = `[${m.optionControls.translation[0] + horizontalPixels}, ${m.optionControls.translation[1] + verticalPixels}]` +end sub + +' onLogoLoadStatusChanged: Handler for changes to logo image's status. +' +' @param {dynamic} event - field change event +sub onLogoLoadStatusChanged(event) + if LCase(event.GetData()) = "ready" + logoImage = event.getRoSGNode() + logoImage.unobserveField("loadStatus") + + ' Move video info to the right based on the logo width + m.videoInfo.translation = `[${m.videoInfo.translation[0] + logoImage.bitmapWidth + LOGO_RIGHT_PADDING}, ${m.videoInfo.translation[1]}]` + m.itemTitle.maxWidth = m.itemTitle.maxWidth - (logoImage.bitmapWidth + LOGO_RIGHT_PADDING) + + ' Move the option controls down based on the logo height + if not m.optionControlsMoved + moveOptionControls(0, OPTIONCONTROLS_TOP_PADDING) + m.optionControlsMoved = true + end if + end if +end sub + +' onLogoImageChanged: Handler for changes to m.top.logoImage param. +' +sub onLogoImageChanged() + if isValidAndNotEmpty(m.top.logoImage) + logoImage = createObject("roSGNode", "Poster") + logoImage.Id = "logoImage" + logoImage.observeField("loadStatus", "onLogoLoadStatusChanged") + logoImage.uri = m.top.logoImage + logoImage.translation = [103, 61] + m.top.appendChild(logoImage) + end if +end sub + ' resetFocusToDefaultButton: Reset focus back to the default button ' sub resetFocusToDefaultButton() diff --git a/components/video/OSD.xml b/components/video/OSD.xml index 241c69098..4093701d0 100644 --- a/components/video/OSD.xml +++ b/components/video/OSD.xml @@ -1,7 +1,17 @@ - + + + + + + + + @@ -30,6 +40,10 @@ + + + + diff --git a/components/video/VideoPlayerView.bs b/components/video/VideoPlayerView.bs index 7d347c539..90c48b171 100644 --- a/components/video/VideoPlayerView.bs +++ b/components/video/VideoPlayerView.bs @@ -400,6 +400,31 @@ sub onVideoContentLoaded() m.osd.itemTitleText = m.top.content.title + ' If video is an episode, attempt to add season and episode numbers to OSD + if m.top.content.contenttype = 4 + if isValid(videoContent[0].seasonNumber) + m.osd.seasonNumber = videoContent[0].seasonNumber + end if + + if isValid(videoContent[0].episodeNumber) + m.osd.episodeNumber = videoContent[0].episodeNumber + end if + + if isValid(videoContent[0].episodeNumberEnd) + m.osd.episodeNumberEnd = videoContent[0].episodeNumberEnd + end if + end if + + ' Attempt to add logo to OSD + if isValidAndNotEmpty(videoContent[0].logoImage) + m.osd.logoImage = videoContent[0].logoImage + + ' Don't show both the logo and the video title if this isn't an episode + if m.top.content.contenttype <> 4 + m.osd.itemTitleText = "" + end if + end if + populateChapterMenu() if m.LoadMetaDataTask.isIntro diff --git a/images/osdBackground.png b/images/osdBackground.png new file mode 100644 index 000000000..b812798d7 Binary files /dev/null and b/images/osdBackground.png differ