From d2c60e13646079210209141032a5fd3412fe7dd2 Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Sat, 3 Aug 2024 22:01:58 -0400 Subject: [PATCH 01/14] remove backdrop when alpha menu is active and add a bunch of debug logging --- components/ItemGrid/ItemGrid.bs | 42 +++++++++++++++++++++++++++---- components/ItemGrid/ItemGrid.xml | 2 +- images/1px-262626.png | Bin 0 -> 70 bytes 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 images/1px-262626.png diff --git a/components/ItemGrid/ItemGrid.bs b/components/ItemGrid/ItemGrid.bs index 16840b773..b67b21787 100644 --- a/components/ItemGrid/ItemGrid.bs +++ b/components/ItemGrid/ItemGrid.bs @@ -6,6 +6,7 @@ import "pkg:/source/roku_modules/log/LogMixin.brs" sub init() m.log = log.Logger("ItemGrid") + m.log.debug("start init()") m.options = m.top.findNode("options") m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"] @@ -70,6 +71,7 @@ sub init() m.resetGrid = m.global.session.user.settings["itemgrid.reset"] m.top.gridTitles = m.global.session.user.settings["itemgrid.gridTitles"] + m.log.debug("end init()") end sub 'Genre Item Selected @@ -79,6 +81,7 @@ end sub 'Load initial set of Data sub loadInitialItems() + m.log.debug("start loadInitialItems()") m.loadItemsTask.control = "stop" startLoadingSpinner() @@ -227,6 +230,7 @@ sub loadInitialItems() startLoadingSpinner(false) m.loadItemsTask.control = "RUN" SetUpOptions() + m.log.debug("end loadInitialItems()") end sub ' Set Movies view, sort, and filter options @@ -438,6 +442,7 @@ end sub 'Handle loaded data, and add to Grid sub ItemDataLoaded(msg) + m.log.debug("start ItemDataLoaded()") itemData = msg.GetData() m.loadItemsTask.unobserveField("content") m.loadItemsTask.content = [] @@ -494,22 +499,28 @@ sub ItemDataLoaded(msg) end if stopLoadingSpinner() + m.log.debug("end ItemDataLoaded()") end sub 'Set Background Image sub SetBackground(backgroundUri as string) - + m.log.debug("start SetBackground()", backgroundUri, m.swapAnimation.state, m.newBackdrop.loadStatus) 'If a new image is being loaded, or transitioned to, store URL to load next - if m.swapAnimation.state <> "stopped" or m.newBackdrop.loadStatus = "loading" - m.queuedBGUri = backgroundUri - return + if not m.top.alphaActive + if m.swapAnimation.state <> "stopped" or m.newBackdrop.loadStatus = "loading" + m.log.debug("caching new background URI") + m.queuedBGUri = backgroundUri + return + end if end if m.newBackdrop.uri = backgroundUri + m.log.debug("end SetBackground()") end sub 'Handle new item being focused sub onItemFocused() + m.log.debug("start onItemFocused()", m.itemGrid.currFocusRow, m.itemGrid.itemFocused) focusedRow = m.itemGrid.currFocusRow @@ -518,7 +529,7 @@ sub onItemFocused() updateTitle() ' If no selected item, set background to parent backdrop - if itemInt = -1 + if itemInt = -1 or focusedRow = -1 return end if @@ -531,6 +542,7 @@ sub onItemFocused() if focusedRow >= m.loadedRows - 5 and m.loadeditems < m.loadItemsTask.totalRecordCount loadMoreData() end if + m.log.debug("end onItemFocused()") end sub 'When Image Loading Status changes @@ -551,6 +563,7 @@ sub swapDone() 'If there is another one to load if m.newBackdrop.uri <> m.queuedBGUri and m.queuedBGUri <> "" + m.log.debug("Loading queued backdrop image", m.queuedBGUri) SetBackground(m.queuedBGUri) m.queuedBGUri = "" end if @@ -559,6 +572,7 @@ end sub 'Load next set of items sub loadMoreData() + m.log.debug("start loadMoreData()") if m.Loading = true then return startLoadingSpinner(false) @@ -566,6 +580,7 @@ sub loadMoreData() m.loadItemsTask.startIndex = m.loadedItems m.loadItemsTask.observeField("content", "ItemDataLoaded") m.loadItemsTask.control = "RUN" + m.log.debug("end loadMoreData()") end sub 'Item Selected @@ -760,6 +775,20 @@ function getItemFocused() return invalid end function +sub alphaActiveChanged() + m.log.debug("start alphaActiveChanged()", m.top.alphaActive) + + if m.top.alphaActive + ' fade into an empty backdrop + m.swapAnimation.state = "stop" + m.queuedBGUri = "" + ' use a 1px image because we can't use the animation to fade into a blank uri string + SetBackground("pkg:/images/1px-262626.png") + end if + + m.log.debug("end alphaActiveChanged()") +end sub + function onKeyEvent(key as string, press as boolean) as boolean if not press then return false @@ -826,11 +855,14 @@ function onKeyEvent(key as string, press as boolean) as boolean return true end if else if key = "left" and topGrp.isinFocusChain() + m.log.debug("Now entering alpha menu") m.top.alphaActive = true topGrp.setFocus(false) m.alphaMenu.setFocus(true) + return true else if key = "right" and m.alpha.isinFocusChain() + m.log.debug("Now leaving alpha menu") m.top.alphaActive = false m.alphaMenu.setFocus(false) topGrp.setFocus(true) diff --git a/components/ItemGrid/ItemGrid.xml b/components/ItemGrid/ItemGrid.xml index bea6a14a6..74b8665c6 100644 --- a/components/ItemGrid/ItemGrid.xml +++ b/components/ItemGrid/ItemGrid.xml @@ -33,7 +33,7 @@ - + diff --git a/images/1px-262626.png b/images/1px-262626.png new file mode 100644 index 0000000000000000000000000000000000000000..5122799ac5ca75c2acfd3beba2690000ebe72b6e GIT binary patch literal 70 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}1TpU9 Date: Sun, 4 Aug 2024 21:38:38 +0000 Subject: [PATCH 02/14] Bump build version --- Makefile | 2 +- manifest | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index bd07230e7..b22a6d4da 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # If you want to get_images, you'll also need convert from ImageMagick ########################################################################## -VERSION := 2.1.4 +VERSION := 2.1.5 ## usage diff --git a/manifest b/manifest index 6dac4b714..47de6e805 100644 --- a/manifest +++ b/manifest @@ -3,7 +3,7 @@ title=Jellyfin major_version=2 minor_version=1 -build_version=4 +build_version=5 ### Main Menu Icons / Channel Poster Artwork diff --git a/package-lock.json b/package-lock.json index 4c36e9189..63f2aa011 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jellyfin-roku", - "version": "2.1.4", + "version": "2.1.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jellyfin-roku", - "version": "2.1.4", + "version": "2.1.5", "hasInstallScript": true, "license": "GPL-2.0", "dependencies": { diff --git a/package.json b/package.json index 73ac85177..6ff6fed7b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jellyfin-roku", "type": "module", - "version": "2.1.4", + "version": "2.1.5", "description": "Roku app for Jellyfin media server", "dependencies": { "@rokucommunity/bslib": "0.1.1", From 9e5ae3aa1f4685049736fc74de1b3cb5e0d6bd76 Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Wed, 25 Sep 2024 13:14:20 -0400 Subject: [PATCH 03/14] stop trying to direct play AAC profile "main" --- source/utils/deviceCapabilities.bs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/source/utils/deviceCapabilities.bs b/source/utils/deviceCapabilities.bs index 3dd234dce..05bec80b5 100644 --- a/source/utils/deviceCapabilities.bs +++ b/source/utils/deviceCapabilities.bs @@ -440,7 +440,26 @@ function getCodecProfiles() as object if di.CanDecodeAudio({ Codec: audioCodec, ChCnt: audioChannel }).Result channelSupportFound = true for each codecType in ["VideoAudio", "Audio"] - if audioCodec = "opus" and codecType = "Audio" + if audioCodec = "aac" + codecProfiles.push({ + "Type": codecType, + "Codec": audioCodec, + "Conditions": [ + { + "Condition": "NotEquals", + "Property": "AudioProfile", + "Value": "Main", + "IsRequired": true + }, + { + "Condition": "LessThanEqual", + "Property": "AudioChannels", + "Value": audioChannel, + "IsRequired": true + } + ] + }) + else if audioCodec = "opus" and codecType = "Audio" ' opus audio files not supported by roku else codecProfiles.push({ From a24df3dfebaed0156e4bf78aed43f603fc480596 Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Thu, 26 Sep 2024 11:18:11 -0400 Subject: [PATCH 04/14] wait until we have data from itemGrid to set itemText visibility --- components/ItemGrid/GridItem.bs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/ItemGrid/GridItem.bs b/components/ItemGrid/GridItem.bs index 5dae0e13b..248f43024 100644 --- a/components/ItemGrid/GridItem.bs +++ b/components/ItemGrid/GridItem.bs @@ -20,9 +20,6 @@ sub init() m.checkmark.width = 90 m.checkmark.height = 60 - m.itemText.translation = [0, m.itemPoster.height + 7] - m.itemText.visible = m.gridTitles = "showalways" - ' Add some padding space when Item Titles are always showing if m.itemText.visible then m.itemText.maxWidth = 250 @@ -38,6 +35,9 @@ sub init() end if end if + m.itemText.translation = [0, m.itemPoster.height + 7] + m.itemText.visible = m.gridTitles = "showalways" + end sub sub itemContentChanged() From 065f81cf6cabf7f3ca9fe3cc66a703c5cea9bd28 Mon Sep 17 00:00:00 2001 From: Jimi Date: Fri, 20 Sep 2024 19:28:04 -0600 Subject: [PATCH 05/14] Add missing field --- components/data/ChannelData.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/components/data/ChannelData.xml b/components/data/ChannelData.xml index b7a2feb51..2d0667b58 100644 --- a/components/data/ChannelData.xml +++ b/components/data/ChannelData.xml @@ -1,6 +1,7 @@ + From f399d699d315336240c8474edbd44dfc0341e89e Mon Sep 17 00:00:00 2001 From: Jimi Date: Fri, 27 Sep 2024 09:12:10 -0600 Subject: [PATCH 06/14] Allow for remux of LiveTV --- source/api/Items.bs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/api/Items.bs b/source/api/Items.bs index 6b5db4ead..f4262dc29 100644 --- a/source/api/Items.bs +++ b/source/api/Items.bs @@ -26,7 +26,17 @@ function ItemPostPlaybackInfo(id as string, mediaSourceId = "" as string, audioT "SubtitleStreamIndex": subtitleTrackIndex } - if mediaSourceId <> "" then params.MediaSourceId = mediaSourceId + ' Note: Jellyfin v10.9+ now remuxs LiveTV and does not allow DirectPlay anymore. + ' Because of this, we need to tell the server "EnableDirectPlay = false" so that we receive the + ' transcoding URL (which is just a remux and not a transcode; unless it is) + ' The web handles this by disabling EnableDirectPlay on a Retry, but we don't currently Retry a Live + ' TV stream, thus we just turn it off on the first try here. + if mediaSourceId <> "" + params.MediaSourceId = mediaSourceId + else + ' No mediaSourceId? Must be LiveTV... + params.EnableDirectPlay = false + end if if audioTrackIndex > -1 then params.AudioStreamIndex = audioTrackIndex From 1cb0eb9e1b9cfd24588cde92afac990f60d8bb47 Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Sat, 28 Sep 2024 13:20:27 -0400 Subject: [PATCH 07/14] report "finished" video state to server --- components/PlaystateTask.bs | 2 +- components/video/VideoPlayerView.bs | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/components/PlaystateTask.bs b/components/PlaystateTask.bs index fc06ae3e1..556ab52f2 100644 --- a/components/PlaystateTask.bs +++ b/components/PlaystateTask.bs @@ -8,7 +8,7 @@ end sub sub PlaystateUpdate() if m.top.status = "start" url = "Sessions/Playing" - else if m.top.status = "stop" + else if m.top.status = "stop" or m.top.status = "finished" url = "Sessions/Playing/Stopped" else if m.top.status = "update" url = "Sessions/Playing/Progress" diff --git a/components/video/VideoPlayerView.bs b/components/video/VideoPlayerView.bs index 56f230ee8..a9b708d79 100644 --- a/components/video/VideoPlayerView.bs +++ b/components/video/VideoPlayerView.bs @@ -1,7 +1,9 @@ import "pkg:/source/utils/misc.bs" import "pkg:/source/utils/config.bs" +import "pkg:/source/roku_modules/log/LogMixin.brs" sub init() + m.log = log.Logger("VideoPlayerView") ' Hide the overhang on init to prevent showing 2 clocks m.top.getScene().findNode("overhang").visible = false m.currentItem = m.global.queueManager.callFunc("getCurrentItem") @@ -600,6 +602,7 @@ end sub ' ' When Video Player state changes sub onState(msg) + m.log.debug("start onState()", m.top.state) if isValid(m.captionTask) m.captionTask.playerState = m.top.state + m.top.globalCaptionMode end if @@ -649,16 +652,22 @@ sub onState(msg) m.playbackTimer.control = "stop" ReportPlayback("stop") m.playReported = false + else if m.top.state = "finished" + m.playbackTimer.control = "stop" + ReportPlayback("finished") + m.top.control = "stop" + m.top.backPressed = true ' exit video player end if - + m.log.debug("end onState()", m.top.state) end sub ' ' Report playback to server sub ReportPlayback(state = "update" as string) - if m.top.position = invalid then return + m.log.debug("start ReportPlayback()", state, int(m.top.position)) + params = { "ItemId": m.top.id, "PlaySessionId": m.top.PlaySessionId, @@ -677,6 +686,8 @@ sub ReportPlayback(state = "update" as string) playstateTask = m.global.playstateTask playstateTask.setFields({ status: state, params: params }) playstateTask.control = "RUN" + + m.log.debug("end ReportPlayback()", state, int(m.top.position)) end sub ' From 16eb0a601ad7267f1c2734c236c66639fae83acc Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Sat, 28 Sep 2024 14:56:26 -0400 Subject: [PATCH 08/14] change api endpoint --- components/PlaystateTask.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/PlaystateTask.bs b/components/PlaystateTask.bs index 556ab52f2..ff8d8f5e8 100644 --- a/components/PlaystateTask.bs +++ b/components/PlaystateTask.bs @@ -8,9 +8,9 @@ end sub sub PlaystateUpdate() if m.top.status = "start" url = "Sessions/Playing" - else if m.top.status = "stop" or m.top.status = "finished" + else if m.top.status = "stop" url = "Sessions/Playing/Stopped" - else if m.top.status = "update" + else if m.top.status = "update" or m.top.status = "finished" url = "Sessions/Playing/Progress" else ' Unknown State From ecba5333acd01ace88f1ef2148b0f12c0cbe2c80 Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Sat, 28 Sep 2024 14:57:07 -0400 Subject: [PATCH 09/14] don't manually stop and exit player when state = finished --- components/video/VideoPlayerView.bs | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/video/VideoPlayerView.bs b/components/video/VideoPlayerView.bs index a9b708d79..c3588448b 100644 --- a/components/video/VideoPlayerView.bs +++ b/components/video/VideoPlayerView.bs @@ -655,8 +655,6 @@ sub onState(msg) else if m.top.state = "finished" m.playbackTimer.control = "stop" ReportPlayback("finished") - m.top.control = "stop" - m.top.backPressed = true ' exit video player end if m.log.debug("end onState()", m.top.state) end sub From b6a65e63ef3e457b026b7c01984c1d5a888b303a Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Sat, 28 Sep 2024 15:34:24 -0400 Subject: [PATCH 10/14] update server when starting in buffered state --- components/video/VideoPlayerView.bs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/components/video/VideoPlayerView.bs b/components/video/VideoPlayerView.bs index c3588448b..b3ebc0f2e 100644 --- a/components/video/VideoPlayerView.bs +++ b/components/video/VideoPlayerView.bs @@ -611,11 +611,18 @@ sub onState(msg) m.osd.playbackState = m.top.state ' When buffering, start timer to monitor buffering process - if m.top.state = "buffering" and m.bufferCheckTimer <> invalid + if m.top.state = "buffering" + ' start buffer timer + if isValid(m.bufferCheckTimer) + m.bufferCheckTimer.control = "start" + m.bufferCheckTimer.ObserveField("fire", "bufferCheck") + end if - ' start timer - m.bufferCheckTimer.control = "start" - m.bufferCheckTimer.ObserveField("fire", "bufferCheck") + ' update server if needed + if not m.playReported + m.playReported = true + ReportPlayback("start") + end if else if m.top.state = "error" if not m.playReported and m.top.transcodeAvailable m.top.retryWithTranscoding = true ' If playback was not reported, retry with transcoding From 4fd7d42039cea05e89eec7cf90a0cf1ab5cb575d Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Sat, 28 Sep 2024 17:08:39 -0400 Subject: [PATCH 11/14] add debugging for video errors --- components/video/VideoPlayerView.bs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/video/VideoPlayerView.bs b/components/video/VideoPlayerView.bs index b3ebc0f2e..53a2cf111 100644 --- a/components/video/VideoPlayerView.bs +++ b/components/video/VideoPlayerView.bs @@ -624,6 +624,10 @@ sub onState(msg) ReportPlayback("start") end if else if m.top.state = "error" + m.log.error(m.top.errorCode, m.top.errorMsg, m.top.errorStr, m.top.errorCode) + + print m.top.errorInfo + if not m.playReported and m.top.transcodeAvailable m.top.retryWithTranscoding = true ' If playback was not reported, retry with transcoding else From 5e35ffa49f6b2fb8e04d878f9c807c1fec4b3185 Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Sat, 28 Sep 2024 17:12:26 -0400 Subject: [PATCH 12/14] force exit from video player when finished to set TV back to SDR --- components/video/VideoPlayerView.bs | 1 + 1 file changed, 1 insertion(+) diff --git a/components/video/VideoPlayerView.bs b/components/video/VideoPlayerView.bs index 53a2cf111..bf6026db5 100644 --- a/components/video/VideoPlayerView.bs +++ b/components/video/VideoPlayerView.bs @@ -666,6 +666,7 @@ sub onState(msg) else if m.top.state = "finished" m.playbackTimer.control = "stop" ReportPlayback("finished") + m.top.backPressed = true ' force exit from video player to set TV back to SDR end if m.log.debug("end onState()", m.top.state) end sub From d23a77e572df8c02fe23c89fe8b3e2f383575c1c Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Sat, 28 Sep 2024 19:40:14 -0400 Subject: [PATCH 13/14] fix api endpoint for finished state --- components/PlaystateTask.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/PlaystateTask.bs b/components/PlaystateTask.bs index ff8d8f5e8..556ab52f2 100644 --- a/components/PlaystateTask.bs +++ b/components/PlaystateTask.bs @@ -8,9 +8,9 @@ end sub sub PlaystateUpdate() if m.top.status = "start" url = "Sessions/Playing" - else if m.top.status = "stop" + else if m.top.status = "stop" or m.top.status = "finished" url = "Sessions/Playing/Stopped" - else if m.top.status = "update" or m.top.status = "finished" + else if m.top.status = "update" url = "Sessions/Playing/Progress" else ' Unknown State From c90645777a1785f0dc90a5a53a0ae0f27c7fb341 Mon Sep 17 00:00:00 2001 From: Charles Ewert Date: Sun, 29 Sep 2024 10:57:49 -0400 Subject: [PATCH 14/14] log unhandled state and remove unused var --- components/video/VideoPlayerView.bs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/video/VideoPlayerView.bs b/components/video/VideoPlayerView.bs index bf6026db5..5850bbd94 100644 --- a/components/video/VideoPlayerView.bs +++ b/components/video/VideoPlayerView.bs @@ -637,7 +637,6 @@ sub onState(msg) ' Stop playback and exit player m.top.control = "stop" - m.top.backPressed = true else if m.top.state = "playing" ' Check if next episode is available @@ -666,7 +665,8 @@ sub onState(msg) else if m.top.state = "finished" m.playbackTimer.control = "stop" ReportPlayback("finished") - m.top.backPressed = true ' force exit from video player to set TV back to SDR + else + m.log.warning("Unhandled state", m.top.state, m.playReported, m.playFinished) end if m.log.debug("end onState()", m.top.state) end sub @@ -723,7 +723,6 @@ sub bufferCheck(msg) ' Stop playback and exit player m.top.control = "stop" - m.top.backPressed = true end if end if