Skip to content

Commit

Permalink
Merge branch 'update-device-profile' of https://github.com/cewert/jel…
Browse files Browse the repository at this point in the history
…lyfin-roku into update-device-profile
  • Loading branch information
cewert committed Sep 1, 2023
2 parents 8a11eaa + 63efcec commit 0d67eb6
Show file tree
Hide file tree
Showing 45 changed files with 11,072 additions and 6,624 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/build-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ jobs:
dev:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
with:
node-version: "lts/*"
cache: "npm"
- name: NPM install
run: npm ci
- name: Install roku module dependencies
run: npx ropm install
run: npm run ropm
- name: Build app
run: npm run build
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3
with:
name: Jellyfin-Roku-dev-${{ github.sha }}
path: ${{ github.workspace }}/build/staging
if-no-files-found: error
if-no-files-found: error
12 changes: 6 additions & 6 deletions .github/workflows/build-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout master (the latest release)
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
with:
ref: master
- name: Install jq to parse json
Expand All @@ -33,7 +33,7 @@ jobs:
- name: Save old Makefile version
run: awk 'BEGIN { FS=" = " } /^VERSION/ { print "oldMakeVersion="$2; }' Makefile >> $GITHUB_ENV
- name: Checkout PR branch
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- name: Save new package.json version
run: echo "newPackVersion=$(jq -r ".version" package.json)" >> $GITHUB_ENV
- name: package.json version must be updated
Expand Down Expand Up @@ -61,19 +61,19 @@ jobs:
prod:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3
- uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
with:
node-version: "lts/*"
cache: "npm"
- name: NPM install
run: npm ci
- name: Install roku module dependencies
run: npx ropm install
run: npm run ropm
- name: Build app for production
run: npm run build-prod
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3
with:
name: Jellyfin-Roku-v${{ env.newManVersion }}-${{ github.sha }}
path: ${{ github.workspace }}/build/staging
if-no-files-found: error
if-no-files-found: error
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
[![Build Status](https://img.shields.io/github/actions/workflow/status/jellyfin/jellyfin-roku/build-dev.yml?logo=github&branch=unstable "Build Status")](https://github.com/jellyfin/jellyfin-roku/actions/workflows/build-dev.yml?query=branch%3Aunstable)
[![Current Release](https://img.shields.io/github/release/jellyfin/jellyfin-roku.svg?logo=github "Current Release")](https://github.com/jellyfin/jellyfin-roku/releases)
[![Translation Status](https://translate.jellyfin.org/widgets/jellyfin/-/jellyfin-roku/svg-badge.svg "Translation Status")](https://translate.jellyfin.org/projects/jellyfin/jellyfin-roku/?utm_source=widget)
[![Forum](https://img.shields.io/badge/forum-MyBB-00A4DC "Check out our forum!")](https://forum.jellyfin.org/f-roku-development)
[![Matrix](https://img.shields.io/matrix/jellyfin:matrix.org.svg?logo=matrix "Chat on Matrix")](https://matrix.to/#/#jellyfin-dev-roku:matrix.org)
[![Reddit](https://img.shields.io/badge/reddit-r%2Fjellyfin-%23FF5700.svg?logo=reddit "Join our Subreddit")](https://www.reddit.com/r/jellyfin)
[![License](https://img.shields.io/github/license/jellyfin/jellyfin-roku.svg "GPL 2.0 License")](LICENSE)

Jellyfin Roku is the official Jellyfin client for Roku devices. We welcome all contributions and pull requests! If you have a larger feature in mind please [open an issue](https://github.com/jellyfin/jellyfin-roku/issues/new?assignees=&labels=feature&template=feature_request.md&title=) so we can discuss the implementation before you start.
Expand Down
3 changes: 3 additions & 0 deletions components/GetPlaybackInfoTask.brs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ function GetTranscodingStats(deviceSession)
data = "<b>• " + tr("Audio Channels") + ":</b> " + Str(audioChannels)
sessionStats.data.push(data)
end if
else
sessionStats.data.push("<header>" + tr("Direct playing") + "</header>")
sessionStats.data.push("<b>" + tr("The source file is entirely compatible with this client and the session is receiving the file without modifications.") + "</b>")
end if

if havePlaybackInfo()
Expand Down
2 changes: 1 addition & 1 deletion components/ItemGrid/ItemGrid.brs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ sub loadInitialItems()
if m.sortField = invalid then m.sortField = "SortName"
if m.filter = invalid then m.filter = "All"

if sortAscendingStr = invalid or sortAscendingStr = "true"
if sortAscendingStr = invalid or sortAscendingStr = true
m.sortAscending = true
else
m.sortAscending = false
Expand Down
12 changes: 4 additions & 8 deletions components/ItemGrid/LoadVideoContentTask.brs
Original file line number Diff line number Diff line change
Expand Up @@ -276,13 +276,13 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
video.isTranscoded = true
end if

video.content.setCertificatesFile("common:/certs/ca-bundle.crt")
setCertificateAuthority(video.content)
video.audioTrack = (audio_stream_idx + 1).ToStr() ' Roku's track indexes count from 1. Our index is zero based

video.SelectedSubtitle = subtitle_idx

if not fully_external
video.content = authorize_request(video.content)
video.content = authRequest(video.content)
end if

print "video.directPlaySupported =", video.directPlaySupported
Expand All @@ -291,12 +291,8 @@ end sub
sub addVideoContentURL(video, mediaSourceId, audio_stream_idx, fully_external)
protocol = LCase(m.playbackInfo.MediaSources[0].Protocol)
if protocol <> "file"
uriRegex = CreateObject("roRegex", "^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$", "")
uri = uriRegex.Match(m.playbackInfo.MediaSources[0].Path)
' proto $1, host $2, port $3, the-rest $4
localhost = CreateObject("roRegex", "^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$", "i")
' https://stackoverflow.com/questions/8426171/what-regex-will-match-all-loopback-addresses
if localhost.isMatch(uri[2])
uri = parseUrl(m.playbackInfo.MediaSources[0].Path)
if isLocalhost(uri[2])
' if the domain of the URI is local to the server,
' create a new URI by appending the received path to the server URL
' later we will substitute the users provided URL for this case
Expand Down
1 change: 1 addition & 0 deletions components/data/TVEpisodeData.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<field id="type" type="string" value="Episode" />
<field id="startingPoint" type="longinteger" value="0" />
<field id="json" type="assocarray" onChange="setFields" />
<field id="selectedVideoStreamId" type="string" />
<field id="selectedAudioStreamIndex" type="integer" />
<field id="favorite" type="boolean" />
</interface>
Expand Down
2 changes: 1 addition & 1 deletion components/liveTv/ProgramDetails.brs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ sub setupLabels()
m.recordSeriesOutline.height = recordSeriesButtonBackground.height

m.userCanRecord = m.global.session.user.settings["livetv.canrecord"]
if m.userCanRecord = "false"
if m.userCanRecord = false
m.recordButton.visible = false
m.recordSeriesButton.visible = false
end if
Expand Down
18 changes: 12 additions & 6 deletions components/movies/MovieDetails.brs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ sub init()
m.options = m.top.findNode("movieOptions")
m.infoGroup = m.top.findNode("infoGroup")

m.main_group = m.top.findNode("main_group")

main = m.top.findNode("main_group")
main.translation = [96, 175]
overview = m.top.findNode("overview")
Expand All @@ -25,9 +23,6 @@ sub init()

m.spinner = m.top.findNode("spinner")

m.trailerButton = m.top.findNode("trailer-button")
m.trailerButton.text = tr("Play Trailer")

m.top.observeField("itemContent", "itemContentChanged")
end sub

Expand All @@ -41,7 +36,18 @@ sub OnScreenShown()
end sub

sub trailerAvailableChanged()
m.trailerButton.visible = m.top.trailerAvailable
if m.top.trailerAvailable
' add trailor button to button group
trailerButton = CreateObject("roSGNode", "JFButton")
trailerButton.id = "trailer-button"
trailerButton.text = tr("Play Trailer")
trailerButton.maxWidth = "300"
trailerButton.minWidth = "300"
m.buttonGrp.appendChild(trailerButton)
else
' remove trailor button from button group
m.buttonGrp.removeChild(m.top.findNode("trailer-button"))
end if
end sub

sub itemContentChanged()
Expand Down
1 change: 0 additions & 1 deletion components/movies/MovieDetails.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
<Button text="Options" id="options-button" iconUri="" focusedIconUri="" maxWidth="250" minWidth="250" />
<Button text="Watched" id="watched-button" iconUri="" focusedIconUri="" maxWidth="350" minWidth="300" />
<Button text="Favorite" id="favorite-button" iconUri="" focusedIconUri="" maxWidth="300" minWidth="300" />
<Button id="trailer-button" visible="false" iconUri="" focusedIconUri="" maxWidth="300" minWidth="300" />
</ButtonGroupHoriz>
<Label id="tagline" />
<Label id="overview" wrap="true" maxLines="8" />
Expand Down
8 changes: 4 additions & 4 deletions components/photos/PhotoDetails.brs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ sub onPhotoLoaded()
photo = m.top.findNode("photo")
photo.uri = m.LoadLibrariesTask.results

if m.slideshow = "true" or m.random = "true"
if m.slideshow = true or m.random = true
' user has requested either a slideshow or random...
m.slideshowTimer.control = "start"
end if
Expand All @@ -47,12 +47,12 @@ end sub
sub nextSlide()
m.slideshowTimer.control = "stop"

if m.slideshow = "true"
if m.slideshow = true
if isValidToContinue(m.top.itemIndex + 1)
m.top.itemIndex++
m.slideshowTimer.control = "start"
end if
else if m.random = "true"
else if m.random = true
index = rnd(m.top.items.content.getChildCount() - 1)
if isValidToContinue(index)
m.top.itemIndex = index
Expand Down Expand Up @@ -100,7 +100,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
if m.textBackground.opacity = 0
m.showStatusAnimation.control = "start"
end if
m.slideshow = "true"
m.slideshow = true
m.statusTimer.control = "start"
m.slideshowTimer.control = "start"
end if
Expand Down
74 changes: 65 additions & 9 deletions components/tvshows/TVEpisodeRowWithOptions.brs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import "pkg:/source/utils/misc.brs"

sub init()
m.rows = m.top.findNode("tvEpisodeRow")
m.tvListOptions = m.top.findNode("tvListOptions")
Expand All @@ -14,26 +16,55 @@ sub rowsDoneLoading()
m.top.doneLoading = true
end sub

sub SetUpAudioOptions(streams)
' List of video versions to choose from
sub SetUpVideoOptions(streams as object)
videos = []

for i = 0 to streams.Count() - 1
if LCase(streams[i].VideoType) = "videofile"
' Create options for user to switch between video tracks
videos.push({
"Title": streams[i].Name,
"Description": tr("Video"),
"Selected": m.top.objects.items[m.currentSelected].selectedVideoStreamId = streams[i].id,
"StreamID": streams[i].id,
"video_codec": streams[i].mediaStreams[0].displayTitle
})
end if
end for

if videos.count() >= 1
options = {}
options.videos = videos
m.tvListOptions.options = options
end if
end sub

' List of audio tracks to choose from
sub SetUpAudioOptions(streams as object)
tracks = []

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.objects.items[m.currentSelected].selectedAudioStreamIndex = i, "StreamIndex": i })
tracks.push({
"Title": streams[i].displayTitle,
"Description": streams[i].Title,
"Selected": m.top.objects.items[m.currentSelected].selectedAudioStreamIndex = i,
"StreamIndex": i
})
end if
end for

if tracks.count() > 1
if tracks.count() >= 1
options = {}
if isValid(m.tvListOptions.options) and isValid(m.tvListOptions.options.videos)
options.videos = m.tvListOptions.options.videos
end if
options.audios = tracks
m.tvListOptions.options = options
m.tvListOptions.visible = true
m.tvListOptions.setFocus(true)
end if
end sub

'
'Check if options updated and any reloading required
sub audioOptionsClosed()
if m.currentSelected <> invalid
' If the user opened the audio options, we report back even if they left the selection alone.
Expand All @@ -43,18 +74,43 @@ sub audioOptionsClosed()
end if
end sub

sub videoOptionsClosed()
if m.tvListOptions.videoStreamId <> m.top.objects.items[m.currentSelected].selectedVideoStreamId
m.rows.objects.items[m.currentSelected].selectedVideoStreamId = m.tvListOptions.videoStreamId
end if
end sub

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

if key = "options" and m.rows.focusedChild <> invalid and m.rows.focusedChild.rowItemFocused <> invalid
if key = "options" and isValid(m.rows.focusedChild) and isValid(m.rows.focusedChild.rowItemFocused)
m.currentSelected = m.rows.focusedChild.rowItemFocused[0]
mediaStreams = m.rows.objects.items[m.currentSelected].json.MediaStreams
SetUpAudioOptions(mediaStreams)
mediaSources = m.rows.objects.items[m.currentSelected].json.MediaSources
if m.rows.objects.items[m.currentSelected].selectedVideoStreamId <> ""
for each source in mediaSources
if source.id = m.rows.objects.items[m.currentSelected].selectedVideoStreamId
mediaStreams = source.MediaStreams
exit for
end if
end for
end if
if isValid(mediaSources)
SetUpVideoOptions(mediaSources)
end if
if isValid(mediaStreams)
SetUpAudioOptions(mediaStreams)
end if
if isValid(m.tvListOptions.options)
m.tvListOptions.visible = true
m.tvListOptions.setFocus(true)
end if
return true
else if m.tvListOptions.visible = true and key = "back" or key = "options"
m.tvListOptions.setFocus(false)
m.tvListOptions.visible = false
m.rows.setFocus(true)
videoOptionsClosed()
audioOptionsClosed()
return true
else if key = "up" and m.rows.hasFocus() = false
Expand Down
21 changes: 2 additions & 19 deletions components/tvshows/TVEpisodes.brs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ sub init()
m.rows = m.top.findNode("picker")
m.poster = m.top.findNode("seasonPoster")
m.Shuffle = m.top.findNode("Shuffle")
m.Random = m.top.findNode("Random")
m.tvEpisodeRow = m.top.findNode("tvEpisodeRow")

m.unplayedCount = m.top.findNode("unplayedCount")
Expand All @@ -34,40 +33,24 @@ sub updateSeason()

imgParams = { "maxHeight": 450, "maxWidth": 300 }
m.poster.uri = ImageURL(m.top.seasonData.Id, "Primary", imgParams)
m.Random.visible = true
m.Shuffle.visible = true
m.top.overhangTitle = m.top.seasonData.SeriesName + " - " + m.top.seasonData.name
end sub

function onKeyEvent(key as string, press as boolean) as boolean
handled = false

if key = "left" and not m.Shuffle.hasFocus()
if key = "left" and m.tvEpisodeRow.hasFocus()
m.Shuffle.setFocus(true)
return true
end if

if key = "down" and m.Shuffle.hasFocus()
m.Random.setFocus(true)
return true
end if

if key = "up" and m.Random.hasFocus()
m.Shuffle.setFocus(true)
return true
end if

if key = "right" and not m.tvEpisodeRow.hasFocus()
if key = "right" and (m.Shuffle.hasFocus())
m.tvEpisodeRow.setFocus(true)
return true
end if

if key = "OK" or key = "play"
if m.Random.hasFocus()
randomEpisode = Rnd(m.rows.getChild(0).objects.items.count()) - 1
m.top.quickPlayNode = m.rows.getChild(0).objects.items[randomEpisode]
return true
end if

if m.Shuffle.hasFocus()
episodeList = m.rows.getChild(0).objects.items
Expand Down
1 change: 0 additions & 1 deletion components/tvshows/TVEpisodes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
</Rectangle>
</Poster>
<JFButton id="Shuffle" minChars="10" text="Shuffle" translation="[90, 640]" visible="false"></JFButton>
<JFButton id="Random" minChars="12" text="Play Random" translation="[90, 740]" visible="false"></JFButton>
<TVEpisodeRowWithOptions id="picker" visible="true" />
</children>
<interface>
Expand Down
Loading

0 comments on commit 0d67eb6

Please sign in to comment.