mirror of
https://github.com/jellyfin/jellyfin-roku.git
synced 2024-12-03 11:50:56 +00:00
Merge branch 'unstable' into Next-UP-Button
This commit is contained in:
commit
a35f476bfd
20
.github/workflows/auto-close-stale-pr.yml
vendored
Normal file
20
.github/workflows/auto-close-stale-pr.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
name: "Close stale Pull Requests"
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 1 * * *"
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@3de2653986ebd134983c79fe2be5d45cc3d9f4e1 # tag=v6
|
||||
with:
|
||||
days-before-issue-stale: -1
|
||||
days-before-issue-close: -1
|
||||
stale-pr-message: "This pull request has been inactive for 21 days and will be automatically closed in 7 days if there is no further activity."
|
||||
close-pr-message: "This pull request has been closed because it has been inactive for 28 days. You may submit a new pull request if desired."
|
||||
days-before-pr-stale: 21
|
||||
days-before-pr-close: 7
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -8,8 +8,8 @@ jobs:
|
||||
run:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
|
||||
- uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3
|
||||
with:
|
||||
node-version: "14.12.0"
|
||||
- run: npm ci
|
||||
|
@ -9,11 +9,11 @@ sub init()
|
||||
m.top.observeField("height", "onHeightChanged")
|
||||
m.top.observeField("width", "onWidthChanged")
|
||||
m.top.observeField("padding", "onPaddingChanged")
|
||||
m.top.observeField("focusedChild", "onFocusChanged")
|
||||
m.top.observeField("focus", "onFocusChanged")
|
||||
end sub
|
||||
|
||||
sub onFocusChanged()
|
||||
if m.top.hasFocus()
|
||||
if m.top.focus
|
||||
m.buttonBackground.blendColor = m.top.focusBackground
|
||||
else
|
||||
m.buttonBackground.blendColor = m.top.background
|
||||
@ -69,10 +69,12 @@ end sub
|
||||
function onKeyEvent(key as string, press as boolean) as boolean
|
||||
if not press then return false
|
||||
|
||||
if key = "OK" and m.top.hasFocus()
|
||||
' Simply toggle the selected field to trigger the next event
|
||||
m.top.selected = not m.top.selected
|
||||
return true
|
||||
if key = "right" and m.top.focus
|
||||
m.top.escape = "right"
|
||||
end if
|
||||
|
||||
if key = "left" and m.top.focus
|
||||
m.top.escape = "left"
|
||||
end if
|
||||
|
||||
return false
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<component name="IconButton" extends="Group">
|
||||
<children>
|
||||
<Poster id="buttonBackground" uri="pkg:/images/white.9.png" />
|
||||
<Poster id="buttonIcon" />
|
||||
<Label id="buttonText" color="#aaaaaa" font="font:SmallestSystemFont" horizAlign="center" />
|
||||
<Poster id="buttonBackground" uri="pkg:/images/white.9.png" />
|
||||
<Poster id="buttonIcon" />
|
||||
<Label id="buttonText" color="#aaaaaa" font="font:SmallestSystemFont" horizAlign="center" />
|
||||
</children>
|
||||
<interface>
|
||||
<field id="background" type="color" value="" />
|
||||
@ -14,6 +14,8 @@
|
||||
<field id="width" type="integer" value="" />
|
||||
<field id="icon" type="string" value="" />
|
||||
<field id="selected" type="boolean" value="false" />
|
||||
<field id="focus" type="boolean" />
|
||||
<field id="escape" type="string" value="" />
|
||||
</interface>
|
||||
<script type="text/brightscript" uri="IconButton.brs" />
|
||||
</component>
|
||||
|
@ -80,6 +80,20 @@ sub itemContentChanged()
|
||||
m.backdrop.height = 290
|
||||
m.backdrop.width = 290
|
||||
|
||||
m.posterText.height = 200
|
||||
m.posterText.width = 280
|
||||
else if itemData.json.type = "MusicAlbum"
|
||||
m.itemPoster.uri = itemData.PosterUrl
|
||||
m.itemText.text = itemData.Title
|
||||
|
||||
m.itemPoster.height = 290
|
||||
m.itemPoster.width = 290
|
||||
|
||||
m.itemText.translation = [0, m.itemPoster.height + 7]
|
||||
|
||||
m.backdrop.height = 290
|
||||
m.backdrop.width = 290
|
||||
|
||||
m.posterText.height = 200
|
||||
m.posterText.width = 280
|
||||
else
|
||||
|
@ -163,25 +163,16 @@ sub loadInitialItems()
|
||||
m.loadItemsTask.itemId = m.top.parentItem.Id
|
||||
else if getCollectionType() = "music"
|
||||
' Default Settings
|
||||
m.loadItemsTask.recursive = true
|
||||
m.itemGrid.itemSize = "[290, 290]"
|
||||
|
||||
if m.voiceBox.text <> ""
|
||||
m.loadItemsTask.recursive = true
|
||||
else
|
||||
m.loadItemsTask.recursive = false
|
||||
m.itemGrid.itemSize = "[290, 290]"
|
||||
end if
|
||||
|
||||
m.loadItemsTask.itemType = "MusicArtist,MusicAlbum"
|
||||
m.loadItemsTask.itemType = "MusicArtist"
|
||||
m.loadItemsTask.itemId = m.top.parentItem.Id
|
||||
|
||||
m.view = get_user_setting("display.music.view")
|
||||
|
||||
if m.view = "music-artist"
|
||||
m.loadItemsTask.recursive = true
|
||||
m.loadItemsTask.itemType = "MusicArtist"
|
||||
else if m.view = "music-album"
|
||||
if m.view = "music-album"
|
||||
m.loadItemsTask.itemType = "MusicAlbum"
|
||||
m.loadItemsTask.recursive = true
|
||||
end if
|
||||
else if m.top.parentItem.collectionType = "livetv"
|
||||
m.loadItemsTask.itemType = "TvChannel"
|
||||
@ -312,7 +303,6 @@ end sub
|
||||
' Set Music view, sort, and filter options
|
||||
sub setMusicOptions(options)
|
||||
options.views = [
|
||||
{ "Title": tr("Default"), "Name": "music-default" },
|
||||
{ "Title": tr("Artists"), "Name": "music-artist" },
|
||||
{ "Title": tr("Albums"), "Name": "music-album" },
|
||||
]
|
||||
@ -599,13 +589,7 @@ sub optionsClosed()
|
||||
|
||||
if m.top.parentItem.collectionType = "music"
|
||||
if m.options.view <> m.view
|
||||
if m.options.view = "music-artist"
|
||||
m.view = "music-artist"
|
||||
else if m.options.view = "music-album"
|
||||
m.view = "music-album"
|
||||
else
|
||||
m.view = "music-default"
|
||||
end if
|
||||
m.view = m.options.view
|
||||
set_user_setting("display.music.view", m.view)
|
||||
reload = true
|
||||
end if
|
||||
@ -796,6 +780,12 @@ sub updateTitle()
|
||||
m.top.overhangTitle = m.top.parentItem.title + tr(" (Filtered by ") + m.loadItemsTask.nameStartsWith + ")"
|
||||
end if
|
||||
|
||||
if m.view = "music-artist"
|
||||
m.top.overhangTitle = "%s (%s)".Format(m.top.parentItem.title, tr("Artists"))
|
||||
else if m.view = "music-album"
|
||||
m.top.overhangTitle = "%s (%s)".Format(m.top.parentItem.title, tr("Albums"))
|
||||
end if
|
||||
|
||||
if m.options.view = "Networks" or m.view = "Networks"
|
||||
m.top.overhangTitle = "%s (%s)".Format(m.top.parentItem.title, tr("Networks"))
|
||||
end if
|
||||
|
@ -77,6 +77,16 @@ sub loadItems()
|
||||
else if m.top.view = "Genres"
|
||||
url = "Genres"
|
||||
params.append({ UserId: get_setting("active_user") })
|
||||
else if m.top.ItemType = "MusicArtist"
|
||||
url = "Artists"
|
||||
params.append({
|
||||
UserId: get_setting("active_user")
|
||||
})
|
||||
params.IncludeItemTypes = ""
|
||||
else if m.top.ItemType = "MusicAlbum"
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
params.append({ ImageTypeLimit: 1 })
|
||||
params.append({ EnableImageTypes: "Primary,Backdrop,Banner,Thumb" })
|
||||
else
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
end if
|
||||
@ -88,7 +98,7 @@ sub loadItems()
|
||||
|
||||
for each item in data.Items
|
||||
tmp = invalid
|
||||
if item.Type = "Movie"
|
||||
if item.Type = "Movie" or item.Type = "MusicVideo"
|
||||
tmp = CreateObject("roSGNode", "MovieData")
|
||||
else if item.Type = "Series"
|
||||
tmp = CreateObject("roSGNode", "SeriesData")
|
||||
@ -110,7 +120,15 @@ sub loadItems()
|
||||
tmp = CreateObject("roSGNode", "FolderData")
|
||||
else if item.Type = "Studio"
|
||||
tmp = CreateObject("roSGNode", "FolderData")
|
||||
else if item.Type = "MusicArtist" or item.Type = "MusicAlbum"
|
||||
else if item.Type = "MusicAlbum"
|
||||
tmp = CreateObject("roSGNode", "MusicAlbumData")
|
||||
tmp.type = "MusicAlbum"
|
||||
if api_API().items.headimageurlbyname(item.id, "primary")
|
||||
tmp.posterURL = ImageURL(item.id, "Primary")
|
||||
else
|
||||
tmp.posterURL = ImageURL(item.id, "backdrop")
|
||||
end if
|
||||
else if item.Type = "MusicArtist"
|
||||
tmp = CreateObject("roSGNode", "MusicArtistData")
|
||||
else if item.Type = "Audio"
|
||||
tmp = CreateObject("roSGNode", "MusicSongData")
|
||||
|
@ -22,6 +22,7 @@
|
||||
</interface>
|
||||
<script type="text/brightscript" uri="LoadItemsTask2.brs" />
|
||||
<script type="text/brightscript" uri="pkg:/source/api/Items.brs" />
|
||||
<script type="text/brightscript" uri="pkg:/source/roku_modules/api/api.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/api/Image.brs" />
|
||||
|
@ -18,6 +18,9 @@ sub init()
|
||||
m.overlayRightGroup = m.top.findNode("overlayRightGroup")
|
||||
m.overlayTimeGroup = m.top.findNode("overlayTimeGroup")
|
||||
|
||||
m.slideDownAnimation = m.top.findNode("slideDown")
|
||||
m.slideUpAnimation = m.top.findNode("slideUp")
|
||||
|
||||
if not m.hideClock
|
||||
' get system preference clock format (12/24hr)
|
||||
di = CreateObject("roDeviceInfo")
|
||||
@ -40,6 +43,19 @@ sub init()
|
||||
setClockVisibility()
|
||||
end sub
|
||||
|
||||
sub onVisibleChange()
|
||||
if m.top.disableMoveAnimation
|
||||
m.top.translation = [0, 0]
|
||||
return
|
||||
end if
|
||||
if m.top.isVisible
|
||||
m.slideDownAnimation.control = "start"
|
||||
return
|
||||
end if
|
||||
|
||||
m.slideUpAnimation.control = "start"
|
||||
end sub
|
||||
|
||||
sub updateTitle()
|
||||
leftSeperator = m.top.findNode("overlayLeftSeperator")
|
||||
if m.top.title <> ""
|
||||
|
@ -1,27 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<component name="JFOverhang" extends="Group">
|
||||
<children>
|
||||
<Poster id="overlayLogo"
|
||||
uri="pkg:/images/logo.png"
|
||||
translation="[70, 53]"
|
||||
width="270" height="72" />
|
||||
<LayoutGroup id="overlayLeftGroup" layoutDirection="horiz" translation="[375, 53]" itemSpacings="30" >
|
||||
<Rectangle
|
||||
id="overlayLeftSeperator"
|
||||
color="#666666"
|
||||
width="2"
|
||||
height="64"/>
|
||||
<Poster id="overlayLogo" uri="pkg:/images/logo.png" translation="[70, 53]" width="270" height="72" />
|
||||
<LayoutGroup id="overlayLeftGroup" layoutDirection="horiz" translation="[375, 53]" itemSpacings="30">
|
||||
<Rectangle id="overlayLeftSeperator" color="#666666" width="2" height="64"/>
|
||||
<ScrollingLabel id="overlayTitle" font="font:LargeSystemFont" vertAlign="center" height="64" maxWidth="1100" repeatCount="0" />
|
||||
</LayoutGroup>
|
||||
<LayoutGroup id="overlayRightGroup" layoutDirection="horiz" itemSpacings="30" translation="[1820, 53]" horizAlignment="right" >
|
||||
<LayoutGroup id="overlayRightGroup" layoutDirection="horiz" itemSpacings="30" translation="[1820, 53]" horizAlignment="right">
|
||||
<Label id="overlayCurrentUser" font="font:MediumSystemFont" width="300" horizAlign="right" vertAlign="center" height="64" />
|
||||
<Rectangle
|
||||
id="overlayRightSeperator"
|
||||
color="#666666"
|
||||
width="2"
|
||||
height="64"
|
||||
visible="false"/>
|
||||
<LayoutGroup id="overlayTimeGroup" layoutDirection="horiz" horizAlignment="right" itemSpacings="0" >
|
||||
<Rectangle id="overlayRightSeperator" color="#666666" width="2" height="64" visible="false"/>
|
||||
<LayoutGroup id="overlayTimeGroup" layoutDirection="horiz" horizAlignment="right" itemSpacings="0">
|
||||
<Label id="overlayHours" font="font:MediumSystemFont" vertAlign="center" height="64" />
|
||||
<Label font="font:MediumSystemFont" text=":" vertAlign="center" height="64" />
|
||||
<Label id="overlayMinutes" font="font:MediumSystemFont" vertAlign="center" height="64" />
|
||||
@ -30,19 +18,26 @@
|
||||
</LayoutGroup>
|
||||
|
||||
<LayoutGroup layoutDirection="horiz" horizAlignment="right" translation="[1820, 125]" vertAlignment="custom">
|
||||
<Label id="overlayOptionsStar" font="font:LargeSystemFont" text="*" />
|
||||
<Label id="overlayOptionsText" font="font:SmallSystemFont" text="Options" translation="[0,6]" />
|
||||
<Label id="overlayOptionsStar" font="font:LargeSystemFont" text="*" />
|
||||
<Label id="overlayOptionsText" font="font:SmallSystemFont" text="Options" translation="[0,6]" />
|
||||
</LayoutGroup>
|
||||
<Timer
|
||||
id="currentTimeTimer"
|
||||
repeat="true"
|
||||
duration="60" />
|
||||
<Timer id="currentTimeTimer" repeat="true" duration="60" />
|
||||
|
||||
<Animation id="slideUp" duration=".5" repeat="false">
|
||||
<Vector2DFieldInterpolator key="[0.0, .5]" keyValue="[[0, 0], [0, -200]]" fieldToInterp="overhang.translation" />
|
||||
</Animation>
|
||||
|
||||
<Animation id="slideDown" delay=".2" duration=".5" repeat="false">
|
||||
<Vector2DFieldInterpolator key="[0.0, .5]" keyValue="[[0, -200], [0, 0]]" fieldToInterp="overhang.translation" />
|
||||
</Animation>
|
||||
</children>
|
||||
<interface>
|
||||
<field id="id" type="string" />
|
||||
<field id="currentUser" type="string" onChange="updateUser" />
|
||||
<field id="title" type="string" onChange="updateTitle" />
|
||||
<field id="showOptions" value="true" type="boolean" onChange="updateOptions" />
|
||||
<field id="isVisible" value="true" type="boolean" onChange="onVisibleChange" />
|
||||
<field id="disableMoveAnimation" value="false" type="boolean" />
|
||||
<function name="resetTime" />
|
||||
</interface>
|
||||
<script type="text/brightscript" uri="JFOverhang.brs" />
|
||||
|
@ -2,29 +2,18 @@ sub init()
|
||||
m.playbackTimer = m.top.findNode("playbackTimer")
|
||||
m.bufferCheckTimer = m.top.findNode("bufferCheckTimer")
|
||||
m.top.observeField("state", "onState")
|
||||
m.top.observeField("position", "onPositionChanged")
|
||||
m.top.trickPlayBar.observeField("visible", "onTrickPlayBarVisibilityChange")
|
||||
m.playbackTimer.observeField("fire", "ReportPlayback")
|
||||
m.bufferPercentage = 0 ' Track whether content is being loaded
|
||||
m.playReported = false
|
||||
m.top.transcodeReasons = []
|
||||
m.bufferCheckTimer.duration = 10
|
||||
m.bufferCheckTimer.duration = 30
|
||||
|
||||
if get_user_setting("ui.design.hideclock") = "true"
|
||||
clockNode = findNodeBySubtype(m.top, "clock")
|
||||
if clockNode[0] <> invalid then clockNode[0].parent.removeChild(clockNode[0].node)
|
||||
end if
|
||||
|
||||
' Skip Intro Button
|
||||
m.skipIntroButton = m.top.findNode("skipIntro")
|
||||
m.skipIntroButton.text = tr("Skip Intro")
|
||||
m.introCompleted = false
|
||||
m.showskipIntroButtonAnimation = m.top.findNode("showskipIntroButton")
|
||||
m.hideskipIntroButtonAnimation = m.top.findNode("hideskipIntroButton")
|
||||
m.moveUpskipIntroButtonAnimation = m.top.findNode("moveUpskipIntroButton")
|
||||
m.moveDownskipIntroButtonAnimation = m.top.findNode("moveDownskipIntroButton")
|
||||
|
||||
'Play Next Episode button
|
||||
'Play Next Episode button
|
||||
m.nextEpisodeButton = m.top.findNode("nextEpisode")
|
||||
m.nextEpisodeButton.text = tr("Next Episode")
|
||||
m.nextEpisodeButton.setFocus(false)
|
||||
@ -34,107 +23,6 @@ sub init()
|
||||
m.moveDownnextEpisodeButtonAnimation = m.top.findNode("moveDownnextEpisodeButton")
|
||||
end sub
|
||||
|
||||
'
|
||||
' Checks if we have valid skip intro param data
|
||||
function haveSkipIntroParams() as boolean
|
||||
'check current position
|
||||
if int(m.top.position) >= (m.top.runTime - 30)
|
||||
shownextEpisode()
|
||||
updateCount()
|
||||
end if
|
||||
' Intro data is invalid, skip
|
||||
if not isValid(m.top.skipIntroParams?.Valid)
|
||||
return false
|
||||
end if
|
||||
|
||||
' Returned intro data is not valid, return
|
||||
if not m.top.skipIntroParams.Valid
|
||||
return false
|
||||
end if
|
||||
|
||||
return true
|
||||
end function
|
||||
|
||||
'
|
||||
' Handles showing / hiding the skip intro button
|
||||
sub handleSkipIntro()
|
||||
' We've already shown the intro, return
|
||||
if m.introCompleted then return
|
||||
|
||||
' We don't have valid data, return
|
||||
if not haveSkipIntroParams() then return
|
||||
|
||||
' Check if it's time to hide the skip prompt
|
||||
if m.top.position >= m.top.skipIntroParams.HideSkipPromptAt
|
||||
if skipIntroButtonVisible()
|
||||
hideSkipIntro()
|
||||
end if
|
||||
return
|
||||
end if
|
||||
|
||||
' Check if it's time to show the skip prompt
|
||||
if m.top.position >= m.top.skipIntroParams.ShowSkipPromptAt
|
||||
if not skipIntroButtonVisible()
|
||||
showSkipIntro()
|
||||
end if
|
||||
return
|
||||
end if
|
||||
end sub
|
||||
|
||||
'
|
||||
' When Trick Playbar Visibility changes
|
||||
sub onTrickPlayBarVisibilityChange()
|
||||
' Skip Intro button isn't visible, return
|
||||
if not skipIntroButtonVisible() then return
|
||||
|
||||
' Trick Playbar is visible, move the skip intro button up and fade it out
|
||||
if m.top.trickPlayBar.visible
|
||||
m.moveUpskipIntroButtonAnimation.control = "start"
|
||||
|
||||
m.skipIntroButton.setFocus(false)
|
||||
m.top.setFocus(true)
|
||||
|
||||
return
|
||||
end if
|
||||
|
||||
' Trick Playbar is not visible, move the skip intro button down and fade it in
|
||||
m.moveDownskipIntroButtonAnimation.control = "start"
|
||||
m.skipIntroButton.setFocus(true)
|
||||
|
||||
end sub
|
||||
|
||||
'
|
||||
' When Video Player state changes
|
||||
sub onPositionChanged()
|
||||
' Check if content is episode
|
||||
if m.top.content.contenttype = 4
|
||||
handleSkipIntro()
|
||||
end if
|
||||
end sub
|
||||
|
||||
'
|
||||
' Returns if skip intro button is currently visible
|
||||
function skipIntroButtonVisible() as boolean
|
||||
return m.skipIntroButton.opacity > 0
|
||||
end function
|
||||
|
||||
'
|
||||
' Runs skip intro button animation and sets focus to button
|
||||
sub showSkipIntro()
|
||||
m.showskipIntroButtonAnimation.control = "start"
|
||||
m.skipIntroButton.setFocus(true)
|
||||
end sub
|
||||
|
||||
'
|
||||
' Runs hide intro button animation and sets focus back to video
|
||||
sub hideSkipIntro()
|
||||
m.top.trickPlayBar.unobserveField("visible")
|
||||
m.hideskipIntroButtonAnimation.control = "start"
|
||||
m.introCompleted = true
|
||||
m.skipIntroButton.setFocus(false)
|
||||
m.top.setFocus(true)
|
||||
end sub
|
||||
|
||||
'
|
||||
' Runs Next Episode button animation and sets focus to button
|
||||
sub shownextEpisode()
|
||||
@ -163,7 +51,6 @@ end sub
|
||||
'
|
||||
' When Video Player state changes
|
||||
sub onState(msg)
|
||||
|
||||
' When buffering, start timer to monitor buffering process
|
||||
if m.top.state = "buffering" and m.bufferCheckTimer <> invalid
|
||||
|
||||
@ -191,9 +78,9 @@ sub onState(msg)
|
||||
ReportPlayback("start")
|
||||
m.playReported = true
|
||||
else
|
||||
m.playbackTimer.control = "start"
|
||||
ReportPlayback()
|
||||
end if
|
||||
m.playbackTimer.control = "start"
|
||||
else if m.top.state = "paused"
|
||||
m.playbackTimer.control = "stop"
|
||||
ReportPlayback()
|
||||
@ -276,13 +163,8 @@ end sub
|
||||
|
||||
|
||||
function onKeyEvent(key as string, press as boolean) as boolean
|
||||
if key = "OK"
|
||||
if not m.top.trickPlayBar.visible
|
||||
if m.skipIntroButton.hasFocus()
|
||||
m.top.seek = m.top.skipIntroParams.IntroEnd
|
||||
hideSkipIntro()
|
||||
return true
|
||||
else if m.nextEpisodeButton.hasFocus()
|
||||
|
||||
if key = "OK" and m.nextEpisodeButton.hasFocus()
|
||||
m.top.state = "finished"
|
||||
hidenextEpisode()
|
||||
return true
|
||||
@ -295,6 +177,9 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||
if key = "down"
|
||||
m.top.selectSubtitlePressed = true
|
||||
return true
|
||||
else if key = "up"
|
||||
m.top.selectPlaybackInfoPressed = true
|
||||
return true
|
||||
end if
|
||||
|
||||
return false
|
||||
|
@ -3,6 +3,7 @@
|
||||
<interface>
|
||||
<field id="backPressed" type="boolean" alwaysNotify="true" />
|
||||
<field id="selectSubtitlePressed" type="boolean" alwaysNotify="true" />
|
||||
<field id="selectPlaybackInfoPressed" type="boolean" alwaysNotify="true" />
|
||||
<field id="PlaySessionId" type="string" />
|
||||
<field id="Subtitles" type="array" />
|
||||
<field id="SelectedSubtitle" type="integer" />
|
||||
@ -21,8 +22,6 @@
|
||||
<field id="videoId" type="string" />
|
||||
<field id="mediaSourceId" type="string" />
|
||||
<field id="audioIndex" type="integer" />
|
||||
|
||||
<field id="skipIntroParams" type="assocarray" />
|
||||
<field id="runTime" type="integer" />
|
||||
</interface>
|
||||
<script type="text/brightscript" uri="JFVideo.brs" />
|
||||
@ -30,29 +29,9 @@
|
||||
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||
<script type="text/brightscript" uri="pkg:/source/api/Items.brs" />
|
||||
<children>
|
||||
<JFButton id="skipIntro" opacity="0" textColor="#f0f0f0" focusedTextColor="#202020" focusFootprintBitmapUri="pkg:/images/option-menu-bg.9.png" focusBitmapUri="pkg:/images/white.9.png" translation="[1575, 900]" />
|
||||
<JFButton id="nextEpisode" opacity="0" textColor="#f0f0f0" focusedTextColor="#202020" focusFootprintBitmapUri="pkg:/images/option-menu-bg.9.png" focusBitmapUri="pkg:/images/white.9.png" translation="[1500, 900]" />
|
||||
|
||||
<timer id="playbackTimer" repeat="true" duration="30" />
|
||||
<timer id="bufferCheckTimer" repeat="true" />
|
||||
<timer id="episodeButton" repeat="false" duration="15" />
|
||||
|
||||
<Animation id="moveUpskipIntroButton" duration=".1" repeat="false" easeFunction="linear">
|
||||
<Vector2DFieldInterpolator key="[0.0,1.0]" keyValue="[[1575, 900], [1575, 825]]" fieldToInterp="skipIntro.translation"/>
|
||||
<FloatFieldInterpolator key="[0.0, 1.0]" keyValue="[.9, .1]" fieldToInterp="skipIntro.opacity" />
|
||||
</Animation>
|
||||
<Animation id="moveDownskipIntroButton" duration=".1" repeat="false" easeFunction="linear">
|
||||
<Vector2DFieldInterpolator key="[0.0,1.0]" keyValue="[[1575, 825], [1575, 900]]" fieldToInterp="skipIntro.translation"/>
|
||||
<FloatFieldInterpolator key="[0.0, 1.0]" keyValue="[.1, .9]" fieldToInterp="skipIntro.opacity" />
|
||||
</Animation>
|
||||
|
||||
<Animation id="showskipIntroButton" duration="1.0" repeat="false" easeFunction="inQuad">
|
||||
<FloatFieldInterpolator key="[0.0, 1.0]" keyValue="[0.0, .9]" fieldToInterp="skipIntro.opacity" />
|
||||
</Animation>
|
||||
<Animation id="hideskipIntroButton" duration=".2" repeat="false" easeFunction="inQuad">
|
||||
<FloatFieldInterpolator key="[0.0, 1.0]" keyValue="[.9, 0]" fieldToInterp="skipIntro.opacity" />
|
||||
</Animation>
|
||||
<!--same animation but for the play next episode button-->
|
||||
<!--animation for the play next episode button-->
|
||||
<Animation id="moveUpnextEpisodeButton" duration=".1" repeat="false" easeFunction="linear">
|
||||
<Vector2DFieldInterpolator key="[0.0,1.0]" keyValue="[[1500, 900], [1500, 825]]" fieldToInterp="nextEpisode.translation"/>
|
||||
<FloatFieldInterpolator key="[0.0, 1.0]" keyValue="[.9, .1]" fieldToInterp="nextEpisode.opacity" />
|
||||
@ -68,5 +47,8 @@
|
||||
<Animation id="hidenextEpisodeButton" duration=".2" repeat="false" easeFunction="inQuad">
|
||||
<FloatFieldInterpolator key="[0.0, 1.0]" keyValue="[.9, 0]" fieldToInterp="nextEpisode.opacity" />
|
||||
</Animation>
|
||||
<timer id="episodeButton" repeat="false" duration="15" />
|
||||
<timer id="playbackTimer" repeat="true" duration="30" />
|
||||
<timer id="bufferCheckTimer" repeat="true" />
|
||||
</children>
|
||||
</component>
|
||||
|
@ -2,5 +2,5 @@ sub init()
|
||||
m.top.poster.uri = "pkg:/images/spinner.png"
|
||||
m.top.control = "start"
|
||||
m.top.clockwise = true
|
||||
m.top.spinInterval = 2
|
||||
m.top.spinInterval = 3
|
||||
end sub
|
||||
|
@ -8,7 +8,7 @@ sub init()
|
||||
m.name.vertAlign = "center"
|
||||
m.name.horizAlign = "center"
|
||||
|
||||
m.value.hintText = tr("Enter a value...")
|
||||
m.value.hintText = tr("Enter a username")
|
||||
m.value.maxTextLength = 120
|
||||
end sub
|
||||
|
||||
@ -17,6 +17,7 @@ sub itemContentChanged()
|
||||
|
||||
m.name.text = data.label
|
||||
if data.type = "password"
|
||||
m.value.hintText = tr("Enter a password")
|
||||
m.value.secureMode = true
|
||||
end if
|
||||
|
||||
|
@ -47,7 +47,7 @@ end function
|
||||
sub show_dialog(configField)
|
||||
dialog = createObject("roSGNode", "StandardKeyboardDialog")
|
||||
m.configField = configField
|
||||
dialog.title = "Enter the " + configField.label
|
||||
dialog.title = configField.label
|
||||
dialog.buttons = [tr("OK"), tr("Cancel")]
|
||||
m.greenPalette = createObject("roSGNode", "RSGPalette")
|
||||
m.greenPalette.colors = {
|
||||
|
@ -23,12 +23,18 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||
else if key = "down" and submit.focusedChild = invalid
|
||||
submit.setFocus(true)
|
||||
return true
|
||||
else if key = "up" and submit.focusedChild <> invalid or quickConnect.focusedChild <> invalid
|
||||
else if key = "up" and submit.focusedChild <> invalid
|
||||
checkbox.setFocus(true)
|
||||
return true
|
||||
else if key = "up" and quickConnect.focusedChild <> invalid
|
||||
checkbox.setFocus(true)
|
||||
return true
|
||||
else if key = "up" and checkbox.focusedChild <> invalid
|
||||
list.setFocus(true)
|
||||
return true
|
||||
else if key = "right" and checkbox.focusedChild <> invalid
|
||||
quickConnect.setFocus(true)
|
||||
return true
|
||||
else if key = "right" and submit.focusedChild <> invalid
|
||||
quickConnect.setFocus(true)
|
||||
return true
|
||||
|
@ -29,9 +29,21 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||
'user navigating up to the server picker from the input box (it's only focusable if it has items)
|
||||
else if key = "up" and m.serverUrlContainer.hasFocus() and m.servers.Count() > 0
|
||||
m.serverPicker.setFocus(true)
|
||||
else if key = "up" and m.serverUrlContainer.hasFocus() and m.servers.Count() = 0
|
||||
ScanForServers()
|
||||
else if key = "back" and m.serverUrlContainer.hasFocus() and m.servers.Count() > 0
|
||||
m.serverPicker.setFocus(true)
|
||||
else if key = "OK" and m.serverUrlContainer.hasFocus()
|
||||
ShowKeyboard()
|
||||
'focus the serverUrl input from submit button
|
||||
else if key = "back" and m.submit.hasFocus() and m.servers.Count() > 0
|
||||
m.serverPicker.setFocus(true)
|
||||
else if key = "back" and m.submit.hasFocus() and m.servers.Count() = 0
|
||||
m.serverUrlContainer.setFocus(true)
|
||||
else if key = "back" and m.serverUrlContainer.hasFocus() and m.servers.Count() = 0
|
||||
ScanForServers()
|
||||
else if key = "back" and m.serverPicker.hasFocus() and m.servers.Count() > 0
|
||||
ScanForServers()
|
||||
' On "back" with or without available local servers, will rescan for servers
|
||||
else if key = "up" and m.submit.hasFocus()
|
||||
m.serverUrlContainer.setFocus(true)
|
||||
'focus the submit button from serverUrl
|
||||
@ -60,6 +72,7 @@ sub ScanForServers()
|
||||
'run the task
|
||||
m.ssdpScanner.observeField("content", "ScanForServersComplete")
|
||||
m.ssdpScanner.control = "RUN"
|
||||
m.spinner.visible = true
|
||||
end sub
|
||||
|
||||
sub ScanForServersComplete(event)
|
||||
|
@ -1,13 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<component name="MusicAlbumData" extends="ContentNode">
|
||||
<component name="MusicAlbumData" extends="JFContentItem">
|
||||
<interface>
|
||||
<field id="id" type="string" />
|
||||
<field id="title" type="string" />
|
||||
<field id="image" type="node" onChange="setPoster" />
|
||||
<field id="posterURL" type="string" />
|
||||
<field id="overview" type="string" />
|
||||
<field id="type" type="string" value="Episode" />
|
||||
<field id="json" type="assocarray" onChange="setFields" />
|
||||
</interface>
|
||||
<script type="text/brightscript" uri="MusicAlbumData.brs" />
|
||||
</component>
|
||||
|
@ -1,15 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<component name="MusicSongData" extends="ContentNode">
|
||||
<component name="MusicSongData" extends="JFContentItem">
|
||||
<interface>
|
||||
<field id="id" type="string" />
|
||||
<field id="title" type="string" />
|
||||
<field id="trackNumber" type="integer" />
|
||||
<field id="image" type="node" onChange="setPoster" />
|
||||
<field id="posterURL" type="string" />
|
||||
<field id="overview" type="string" />
|
||||
<field id="type" type="string" value="Song" />
|
||||
<field id="json" type="assocarray" onChange="setFields" />
|
||||
<field id="favorite" type="boolean" />
|
||||
</interface>
|
||||
<script type="text/brightscript" uri="MusicSongData.brs" />
|
||||
</component>
|
||||
|
@ -59,6 +59,7 @@ sub onPeopleLoaded()
|
||||
end for
|
||||
end if
|
||||
m.top.content = data
|
||||
m.top.translation = "[75,10]"
|
||||
m.top.rowItemSize = [[234, 396]]
|
||||
m.LikeThisTask.itemId = m.top.parentId
|
||||
m.LikeThisTask.control = "RUN"
|
||||
|
@ -107,6 +107,11 @@ sub onLibrariesLoaded()
|
||||
end sub
|
||||
|
||||
sub updateHomeRows()
|
||||
if m.global.playstateTask.state = "run"
|
||||
m.global.playstateTask.observeField("state", "updateHomeRows")
|
||||
else
|
||||
m.global.playstateTask.unobserveField("state")
|
||||
end if
|
||||
m.LoadContinueTask.observeField("content", "updateContinueItems")
|
||||
m.LoadContinueTask.control = "RUN"
|
||||
end sub
|
||||
|
@ -1,6 +1,5 @@
|
||||
sub init()
|
||||
getData()
|
||||
m.top.infocus = false
|
||||
end sub
|
||||
|
||||
function getData()
|
||||
@ -16,10 +15,15 @@ function getData()
|
||||
|
||||
for each album in albumData.items
|
||||
gridAlbum = CreateObject("roSGNode", "ContentNode")
|
||||
|
||||
if not isValid(album.posterURL) or album.posterURL = ""
|
||||
album.posterURL = "pkg:/images/icons/album.png"
|
||||
end if
|
||||
|
||||
gridAlbum.shortdescriptionline1 = album.title
|
||||
gridAlbum.HDGRIDPOSTERURL = album.posterURL
|
||||
gridAlbum.hdposterurl = album.posterURL
|
||||
gridAlbum.SDGRIDPOSTERURL = album.SDGRIDPOSTERURL
|
||||
gridAlbum.SDGRIDPOSTERURL = album.posterURL
|
||||
gridAlbum.sdposterurl = album.posterURL
|
||||
|
||||
data.appendChild(gridAlbum)
|
||||
@ -35,7 +39,26 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||
|
||||
if key = "up"
|
||||
if m.top.itemFocused <= 4
|
||||
m.top.infocus = false
|
||||
m.top.escape = key
|
||||
return true
|
||||
end if
|
||||
else if key = "left"
|
||||
if m.top.itemFocused mod 5 = 0
|
||||
m.top.escape = key
|
||||
return true
|
||||
end if
|
||||
else if key = "right"
|
||||
if m.top.itemFocused + 1 mod 5 = 0
|
||||
m.top.escape = key
|
||||
return true
|
||||
end if
|
||||
else if key = "down"
|
||||
totalCount = m.top.MusicArtistAlbumData.items.count()
|
||||
totalRows = div_ceiling(totalCount, 5)
|
||||
currentRow = div_ceiling(m.top.itemFocused + 1, 5)
|
||||
|
||||
if currentRow = totalRows
|
||||
m.top.escape = key
|
||||
return true
|
||||
end if
|
||||
end if
|
||||
|
@ -2,7 +2,8 @@
|
||||
<component name="AlbumGrid" extends="PosterGrid">
|
||||
<interface>
|
||||
<field id="MusicArtistAlbumData" type="assocarray" onChange="getData" />
|
||||
<field id="infocus" type="boolean" />
|
||||
<field id="escape" type="string" alwaysNotify="true" />
|
||||
</interface>
|
||||
<script type="text/brightscript" uri="AlbumGrid.brs" />
|
||||
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
|
||||
</component>
|
||||
|
@ -3,22 +3,33 @@ sub init()
|
||||
setupMainNode()
|
||||
setupButtons()
|
||||
|
||||
m.remoteButtonsActive = true
|
||||
|
||||
m.albumHeader = m.top.findNode("albumHeader")
|
||||
m.albumHeader.text = tr("Albums")
|
||||
|
||||
m.appearsOnHeader = m.top.findNode("appearsOnHeader")
|
||||
m.appearsOnHeader.text = tr("AppearsOn")
|
||||
|
||||
m.appearsOn = m.top.findNode("appearsOn")
|
||||
m.appearsOn.observeField("escape", "onAppearsOnEscape")
|
||||
m.appearsOn.observeField("MusicArtistAlbumData", "onAppearsOnData")
|
||||
|
||||
m.albums = m.top.findNode("albums")
|
||||
m.albums.observeField("infocus", "onAlbumFocusChange")
|
||||
m.albums.observeField("escape", "onAlbumsEscape")
|
||||
m.albums.observeField("MusicArtistAlbumData", "onAlbumsData")
|
||||
|
||||
m.pageLoadAnimation = m.top.findNode("pageLoad")
|
||||
m.pageLoadAnimation.control = "start"
|
||||
|
||||
m.showAlbumsAnimation = m.top.findNode("showAlbums")
|
||||
m.hideAlbumsAnimation = m.top.findNode("hideAlbums")
|
||||
|
||||
m.sectionNavigation = m.top.findNode("sectionNavigation")
|
||||
m.sectionNavigation.observeField("escape", "onSectionNavigationEscape")
|
||||
m.sectionNavigation.observeField("selected", "onSectionNavigationSelected")
|
||||
|
||||
m.sectionScroller = m.top.findNode("sectionScroller")
|
||||
m.sectionScroller.observeField("displayedIndex", "onSectionScrollerChange")
|
||||
m.overhang = m.top.getScene().findNode("overhang")
|
||||
|
||||
' Load background image
|
||||
m.LoadBackdropImageTask = CreateObject("roSGNode", "LoadItemsTask")
|
||||
m.LoadBackdropImageTask.itemsToLoad = "backdropImage"
|
||||
@ -30,6 +41,70 @@ sub init()
|
||||
createDialogPallete()
|
||||
end sub
|
||||
|
||||
sub onAlbumsData()
|
||||
' We have no album data
|
||||
if m.albums.MusicArtistAlbumData.TotalRecordCount = 0
|
||||
m.sectionScroller.removeChild(m.top.findNode("albumsSlide"))
|
||||
m.sectionNavigation.removeChild(m.top.findNode("albumsLink"))
|
||||
m.top.findNode("appearsOnSlide").callFunc("scrollUpToOnDeck")
|
||||
end if
|
||||
end sub
|
||||
|
||||
sub onAppearsOnData()
|
||||
' We have no appears on data
|
||||
if m.appearsOn.MusicArtistAlbumData.TotalRecordCount = 0
|
||||
m.sectionScroller.removeChild(m.top.findNode("appearsOnSlide"))
|
||||
m.sectionNavigation.removeChild(m.top.findNode("appearsOnLink"))
|
||||
end if
|
||||
end sub
|
||||
|
||||
sub onSectionScrollerChange()
|
||||
m.overhang.isVisible = (m.sectionScroller.displayedIndex = 0)
|
||||
end sub
|
||||
|
||||
sub OnScreenShown()
|
||||
m.sectionScroller.focus = true
|
||||
|
||||
if m.sectionScroller.displayedIndex = 0
|
||||
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
|
||||
m.top.selectedButtonIndex = 0
|
||||
m.buttonGrp.setFocus(true)
|
||||
else
|
||||
m.overhang.opacity = "0"
|
||||
m.overhang.isVisible = false
|
||||
m.overhang.opacity = "1"
|
||||
end if
|
||||
end sub
|
||||
|
||||
sub OnScreenHidden()
|
||||
if not m.overhang.isVisible
|
||||
m.overhang.disableMoveAnimation = true
|
||||
m.overhang.isVisible = true
|
||||
m.overhang.disableMoveAnimation = false
|
||||
m.overhang.opacity = "1"
|
||||
end if
|
||||
end sub
|
||||
|
||||
sub onAlbumsEscape()
|
||||
if m.albums.escape = "up"
|
||||
m.sectionNavigation.selected = m.sectionScroller.displayedIndex - 1
|
||||
else if m.albums.escape = "left"
|
||||
m.sectionNavigation.setFocus(true)
|
||||
else if m.albums.escape = "down"
|
||||
if m.sectionScroller.displayedIndex + 1 < m.sectionNavigation.getChildCount()
|
||||
m.sectionNavigation.selected = m.sectionScroller.displayedIndex + 1
|
||||
end if
|
||||
end if
|
||||
end sub
|
||||
|
||||
sub onAppearsOnEscape()
|
||||
if m.appearsOn.escape = "up"
|
||||
m.sectionNavigation.selected = m.sectionScroller.displayedIndex - 1
|
||||
else if m.appearsOn.escape = "left"
|
||||
m.sectionNavigation.setFocus(true)
|
||||
end if
|
||||
end sub
|
||||
|
||||
' Setup playback buttons, default to Play button selected
|
||||
sub setupButtons()
|
||||
m.buttonGrp = m.top.findNode("buttons")
|
||||
@ -46,13 +121,13 @@ end sub
|
||||
sub onButtonSelectedChange()
|
||||
' Change previously selected button back to default image
|
||||
if m.previouslySelectedButtonIndex > -1
|
||||
selectedButton = m.buttonGrp.getChild(m.previouslySelectedButtonIndex)
|
||||
selectedButton.setFocus(false)
|
||||
previousSelectedButton = m.buttonGrp.getChild(m.previouslySelectedButtonIndex)
|
||||
previousSelectedButton.focus = false
|
||||
end if
|
||||
|
||||
' Change selected button image to selected image
|
||||
selectedButton = m.buttonGrp.getChild(m.top.selectedButtonIndex)
|
||||
selectedButton.setFocus(true)
|
||||
selectedButton.focus = true
|
||||
end sub
|
||||
|
||||
sub setupMainNode()
|
||||
@ -72,7 +147,6 @@ sub pageContentChanged()
|
||||
' Populate scene data
|
||||
setScreenTitle(item.json)
|
||||
setPosterImage(item.posterURL)
|
||||
setOnScreenTextValues(item.json)
|
||||
end sub
|
||||
|
||||
sub setScreenTitle(json)
|
||||
@ -106,10 +180,12 @@ sub setBackdropImage(data)
|
||||
end if
|
||||
end sub
|
||||
|
||||
' Populate on screen text variables
|
||||
sub setOnScreenTextValues(json)
|
||||
if isValid(json)
|
||||
setFieldTextValue("overview", json.overview)
|
||||
' Event fired when page data is loaded
|
||||
sub artistOverviewChanged()
|
||||
overviewContent = m.top.artistOverview
|
||||
|
||||
if isValid(overviewContent)
|
||||
setFieldTextValue("overview", overviewContent)
|
||||
end if
|
||||
end sub
|
||||
|
||||
@ -119,36 +195,16 @@ sub onEllipsisChanged()
|
||||
end if
|
||||
end sub
|
||||
|
||||
sub onAlbumFocusChange()
|
||||
if m.albums.infocus
|
||||
m.albums.setFocus(true)
|
||||
m.showAlbumsAnimation.control = "start"
|
||||
return
|
||||
end if
|
||||
|
||||
' Change selected button image to selected image
|
||||
selectedButton = m.buttonGrp.getChild(m.top.selectedButtonIndex)
|
||||
selectedButton.setFocus(true)
|
||||
|
||||
m.albums.setFocus(false)
|
||||
m.hideAlbumsAnimation.control = "start"
|
||||
end sub
|
||||
|
||||
sub onSectionNavigationEscape()
|
||||
if m.sectionNavigation.escape = "right"
|
||||
|
||||
if m.albums.infocus
|
||||
m.albums.setFocus(true)
|
||||
return
|
||||
end if
|
||||
|
||||
selectedButton = m.buttonGrp.getChild(0)
|
||||
selectedButton.setFocus(true)
|
||||
m.sectionNavigation.setFocus(false)
|
||||
m.remoteButtonsActive = false
|
||||
m.sectionScroller.focus = true
|
||||
end if
|
||||
end sub
|
||||
|
||||
sub onSectionNavigationSelected()
|
||||
m.albums.infocus = (m.sectionNavigation.selected = 1)
|
||||
m.sectionScroller.displayedIndex = m.sectionNavigation.selected
|
||||
end sub
|
||||
|
||||
sub dscrShowFocus()
|
||||
@ -192,8 +248,17 @@ sub createDialogPallete()
|
||||
end sub
|
||||
|
||||
function onKeyEvent(key as string, press as boolean) as boolean
|
||||
if key = "left"
|
||||
if m.buttonGrp.isInFocusChain()
|
||||
|
||||
if m.buttonGrp.isInFocusChain()
|
||||
if key = "OK"
|
||||
if press
|
||||
selectedButton = m.buttonGrp.getChild(m.top.selectedButtonIndex)
|
||||
selectedButton.selected = not selectedButton.selected
|
||||
return true
|
||||
end if
|
||||
end if
|
||||
|
||||
if key = "left"
|
||||
if m.top.selectedButtonIndex > 0
|
||||
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
|
||||
m.top.selectedButtonIndex = m.top.selectedButtonIndex - 1
|
||||
@ -201,7 +266,9 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||
end if
|
||||
|
||||
if press
|
||||
m.buttonGrp.setFocus(false)
|
||||
selectedButton = m.buttonGrp.getChild(m.top.selectedButtonIndex)
|
||||
selectedButton.focus = false
|
||||
|
||||
m.sectionNavigation.setFocus(true)
|
||||
return true
|
||||
end if
|
||||
@ -209,29 +276,29 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||
return false
|
||||
end if
|
||||
|
||||
if m.albums.isInFocusChain()
|
||||
if m.albums.itemFocused mod 5 = 0
|
||||
m.sectionNavigation.setFocus(true)
|
||||
if key = "right"
|
||||
if m.top.pageContent.count() = 1 then return false
|
||||
|
||||
if m.buttonGrp.getChild(m.top.selectedButtonIndex).escape = "right"
|
||||
m.buttonGrp.getChild(m.top.selectedButtonIndex).escape = ""
|
||||
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
|
||||
|
||||
if m.top.selectedButtonIndex < m.buttonCount - 1
|
||||
m.top.selectedButtonIndex = m.top.selectedButtonIndex + 1
|
||||
end if
|
||||
|
||||
return true
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
|
||||
if m.buttonGrp.isInFocusChain()
|
||||
if key = "down"
|
||||
m.albums.infocus = true
|
||||
return true
|
||||
else if key = "right"
|
||||
if m.sectionNavigation.escape = "right"
|
||||
m.sectionNavigation.escape = ""
|
||||
return true
|
||||
if m.sectionNavigation.getChildCount() > 1
|
||||
selectedButton = m.buttonGrp.getChild(m.top.selectedButtonIndex)
|
||||
selectedButton.focus = false
|
||||
|
||||
m.top.selectedButtonIndex = 0
|
||||
m.sectionNavigation.selected = m.sectionScroller.displayedIndex + 1
|
||||
end if
|
||||
|
||||
if m.top.pageContent.count() = 1 then return false
|
||||
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
|
||||
if m.top.selectedButtonIndex < m.buttonCount - 1 then m.top.selectedButtonIndex = m.top.selectedButtonIndex + 1
|
||||
|
||||
return true
|
||||
end if
|
||||
end if
|
||||
|
||||
|
@ -1,54 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<component name="ArtistView" extends="JFGroup">
|
||||
<component name="ArtistView" extends="JFScreen">
|
||||
<children>
|
||||
<Poster id="backdrop" opacity=".4" loadDisplayMode="scaleToZoom" width="1920" height="1200" blendColor="#3f3f3f" />
|
||||
<LayoutGroup id="toplevel" layoutDirection="vert" itemSpacings="[75]">
|
||||
<LayoutGroup id="main_group" layoutDirection="horiz" itemSpacings="[125]">
|
||||
<LayoutGroup layoutDirection="vert" itemSpacings="[75]">
|
||||
<Label id="overview" wrap="true" lineSpacing="25" maxLines="6" width="1080" ellipsisText=" ... (Press * to read more)" />
|
||||
<ButtonGroupHoriz id="buttons" itemSpacings="[20]">
|
||||
<IconButton id="play" background="#070707" focusBackground="#00a4dc" padding="35" icon="pkg:/images/icons/play.png" text="Play" height="85" width="150" />
|
||||
<IconButton id="instantMix" background="#070707" focusBackground="#00a4dc" padding="35" icon="pkg:/images/icons/instantMix.png" text="Instant Mix" height="85" width="150" />
|
||||
</ButtonGroupHoriz>
|
||||
|
||||
<SectionScroller id="sectionScroller">
|
||||
<Section id="slide-1" defaultFocusID="play">
|
||||
<LayoutGroup id="toplevel" layoutDirection="vert" itemSpacings="[75]">
|
||||
<LayoutGroup id="main_group" layoutDirection="horiz" itemSpacings="[125]">
|
||||
<LayoutGroup layoutDirection="vert" itemSpacings="[75]">
|
||||
<Label id="overview" wrap="true" lineSpacing="25" maxLines="6" width="1080" ellipsisText=" ... (Press * to read more)" />
|
||||
<ButtonGroupHoriz id="buttons" itemSpacings="[20]">
|
||||
<IconButton id="play" background="#070707" focusBackground="#00a4dc" padding="35" icon="pkg:/images/icons/play.png" text="Play" height="85" width="150" />
|
||||
<IconButton id="instantMix" background="#070707" focusBackground="#00a4dc" padding="35" icon="pkg:/images/icons/instantMix.png" text="Instant Mix" height="85" width="150" />
|
||||
</ButtonGroupHoriz>
|
||||
</LayoutGroup>
|
||||
<Poster id="artistImage" width="500" height="500" />
|
||||
</LayoutGroup>
|
||||
</LayoutGroup>
|
||||
<Poster id="artistImage" width="500" height="500" />
|
||||
</LayoutGroup>
|
||||
</LayoutGroup>
|
||||
<Rectangle id='albumRect' translation="[0, 1050]" width="1920" height="1080" color="#000000" opacity=".75" />
|
||||
<Label id="albumHeader" translation="[120, 1100]" font="font:LargeSystemFont" />
|
||||
<AlbumGrid id="albums" translation="[120, 1200]" vertFocusAnimationStyle="fixedFocus" basePosterSize="[300, 300]" numColumns="5" numRows="99" caption1NumLines="1" itemSpacing="[50, 50]" />
|
||||
</Section>
|
||||
|
||||
<Section id="albumsSlide" translation="[0, 950]" defaultFocusID="albums">
|
||||
<Rectangle id='albumRect' translation="[0, 0]" width="1920" height="1080" color="#000000" opacity=".75" />
|
||||
<Label id="albumHeader" translation="[120, 50]" font="font:LargeSystemFont" />
|
||||
<AlbumGrid id="albums" translation="[120, 150]" vertFocusAnimationStyle="fixedFocus" basePosterSize="[300, 300]" numColumns="5" numRows="99" caption1NumLines="1" itemSpacing="[50, 50]" />
|
||||
</Section>
|
||||
|
||||
<Section id="appearsOnSlide" translation="[0, 1100]" defaultFocusID="appearsOn">
|
||||
<Rectangle id='appearsOnRect' translation="[0, 0]" width="1920" height="1080" color="#000000" opacity=".75" />
|
||||
<Label id="appearsOnHeader" translation="[120, 50]" font="font:LargeSystemFont" />
|
||||
<AlbumGrid id="appearsOn" translation="[120, 150]" vertFocusAnimationStyle="fixedFocus" basePosterSize="[300, 300]" numColumns="5" numRows="99" caption1NumLines="1" itemSpacing="[50, 50]" />
|
||||
</Section>
|
||||
|
||||
</SectionScroller>
|
||||
|
||||
<bgv_ButtonGroupVert id="sectionNavigation" translation="[-100, 175]" itemSpacings="[10]">
|
||||
<sob_SlideOutButton background="#070707" focusBackground="#00a4dc" highlightBackground="#555555" padding="20" icon="pkg:/images/icons/details.png" text="Details" height="50" width="60" />
|
||||
<sob_SlideOutButton background="#070707" focusBackground="#00a4dc" highlightBackground="#555555" padding="20" icon="pkg:/images/icons/cd.png" text="Albums" height="50" width="60" />
|
||||
<sob_SlideOutButton id="albumsLink" background="#070707" focusBackground="#00a4dc" highlightBackground="#555555" padding="20" icon="pkg:/images/icons/cd.png" text="Albums" height="50" width="60" />
|
||||
<sob_SlideOutButton id="appearsOnLink" background="#070707" focusBackground="#00a4dc" highlightBackground="#555555" padding="20" icon="pkg:/images/icons/cassette.png" text="Appears On" height="50" width="60" />
|
||||
</bgv_ButtonGroupVert>
|
||||
|
||||
<Animation id="pageLoad" duration=".5" repeat="false">
|
||||
<Vector2DFieldInterpolator key="[0.0, 1.0]" keyValue="[[0, 1050], [0, 750]]" fieldToInterp="albumRect.translation" />
|
||||
<Vector2DFieldInterpolator key="[0.0, 1.0]" keyValue="[[120, 1100], [120, 800]]" fieldToInterp="albumHeader.translation" />
|
||||
<Vector2DFieldInterpolator key="[0.0, 1.0]" keyValue="[[120, 1200], [120, 900]]" fieldToInterp="albums.translation" />
|
||||
<Animation id="pageLoad" duration="1" repeat="false">
|
||||
<Vector2DFieldInterpolator key="[0.5, 1.0]" keyValue="[[-100, 175], [40, 175]]" fieldToInterp="sectionNavigation.translation" />
|
||||
</Animation>
|
||||
|
||||
<Animation id="showAlbums" duration="0.5" repeat="false">
|
||||
<Vector2DFieldInterpolator key="[0.0, 1.0]" keyValue="[[0, 750], [0, 0]]" fieldToInterp="albumRect.translation" />
|
||||
<Vector2DFieldInterpolator key="[0.0, 1.0]" keyValue="[[120, 800], [120, 175]]" fieldToInterp="albumHeader.translation" />
|
||||
<Vector2DFieldInterpolator key="[0.0, 1.0]" keyValue="[[120, 900], [120, 275]]" fieldToInterp="albums.translation" />
|
||||
<FloatFieldInterpolator key="[0.0, 1.0]" keyValue="[0.75, 0.95]" fieldToInterp="albumRect.opacity" />
|
||||
</Animation>
|
||||
|
||||
<Animation id="hideAlbums" duration="0.5" repeat="false">
|
||||
<Vector2DFieldInterpolator key="[0.0, 1.0]" keyValue="[[0, 0], [0, 750]]" fieldToInterp="albumRect.translation" />
|
||||
<Vector2DFieldInterpolator key="[0.0, 1.0]" keyValue="[[120, 175], [120, 800]]" fieldToInterp="albumHeader.translation" />
|
||||
<Vector2DFieldInterpolator key="[0.0, 1.0]" keyValue="[[120, 275], [120, 900]]" fieldToInterp="albums.translation" />
|
||||
<FloatFieldInterpolator key="[0.0, 1.0]" keyValue="[0.95, 0.75]" fieldToInterp="albumRect.opacity" />
|
||||
</Animation>
|
||||
|
||||
</children>
|
||||
<interface>
|
||||
<field id="pageContent" type="node" onChange="pageContentChanged" />
|
||||
<field id="musicArtistAlbumData" type="assocarray" alias="albums.MusicArtistAlbumData" />
|
||||
<field id="musicArtistAppearsOnData" type="assocarray" alias="appearsOn.MusicArtistAlbumData" />
|
||||
<field id="artistOverview" type="string" onChange="artistOverviewChanged" />
|
||||
<field id="musicAlbumSelected" alias="albums.itemSelected" />
|
||||
<field id="appearsOnSelected" alias="appearsOn.itemSelected" />
|
||||
<field id="playArtistSelected" alias="play.selected" />
|
||||
<field id="instantMixSelected" alias="instantMix.selected" />
|
||||
<field id="selectedButtonIndex" type="integer" value="-1" />
|
||||
|
@ -408,10 +408,16 @@ sub onMetaDataLoaded()
|
||||
if data <> invalid and data.count() > 0
|
||||
|
||||
' Use metadata to load backdrop image
|
||||
if isvalid(data?.json?.ArtistItems?[0]?.id)
|
||||
m.LoadBackdropImageTask.itemId = data.json.ArtistItems[0].id
|
||||
m.LoadBackdropImageTask.observeField("content", "onBackdropImageLoaded")
|
||||
m.LoadBackdropImageTask.control = "RUN"
|
||||
if isvalid(data.json)
|
||||
if isValid(data.json.ArtistItems)
|
||||
if data.json.ArtistItems.count() > 0
|
||||
if isValid(data.json.ArtistItems[0].id)
|
||||
m.LoadBackdropImageTask.itemId = data.json.ArtistItems[0].id
|
||||
m.LoadBackdropImageTask.observeField("content", "onBackdropImageLoaded")
|
||||
m.LoadBackdropImageTask.control = "RUN"
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
|
||||
setPosterImage(data.posterURL)
|
||||
|
95
components/section/section.brs
Normal file
95
components/section/section.brs
Normal file
@ -0,0 +1,95 @@
|
||||
sub init()
|
||||
m.showFromBottomAnimation = m.top.findNode("showFromBottomAnimation")
|
||||
m.showFromBottomPosition = m.top.findNode("showFromBottomPosition")
|
||||
m.showFromBottomOpacity = m.top.findNode("showFromBottomOpacity")
|
||||
|
||||
m.showFromTopAnimation = m.top.findNode("showFromTopAnimation")
|
||||
m.showFromTopPosition = m.top.findNode("showFromTopPosition")
|
||||
m.showFromTopOpacity = m.top.findNode("showFromTopOpacity")
|
||||
|
||||
m.scrollOffTopAnimation = m.top.findNode("scrollOffTopAnimation")
|
||||
m.scrollOffTopPosition = m.top.findNode("scrollOffTopPosition")
|
||||
m.scrollOffTopOpacity = m.top.findNode("scrollOffTopOpacity")
|
||||
|
||||
m.scrollOffBottomAnimation = m.top.findNode("scrollOffBottomAnimation")
|
||||
m.scrollOffBottomPosition = m.top.findNode("scrollOffBottomPosition")
|
||||
m.scrollOffBottomOpacity = m.top.findNode("scrollOffBottomOpacity")
|
||||
|
||||
m.scrollUpToOnDeckAnimation = m.top.findNode("scrollUpToOnDeckAnimation")
|
||||
m.scrollUpToOnDeckPosition = m.top.findNode("scrollUpToOnDeckPosition")
|
||||
|
||||
m.scrollDownToOnDeckAnimation = m.top.findNode("scrollDownToOnDeckAnimation")
|
||||
m.scrollDownToOnDeckPosition = m.top.findNode("scrollDownToOnDeckPosition")
|
||||
|
||||
m.scrollOffOnDeckAnimation = m.top.findNode("scrollOffOnDeckAnimation")
|
||||
m.scrollOffOnDeckPosition = m.top.findNode("scrollOffOnDeckPosition")
|
||||
|
||||
m.top.observeField("translation", "onTranslationChange")
|
||||
m.top.observeField("id", "onIDChange")
|
||||
m.top.observeField("focusedChild", "onFocusChange")
|
||||
end sub
|
||||
|
||||
sub onIDChange()
|
||||
m.showFromBottomPosition.fieldToInterp = m.top.id + ".translation"
|
||||
m.showFromBottomOpacity.fieldToInterp = m.top.id + ".opacity"
|
||||
|
||||
m.showFromTopPosition.fieldToInterp = m.top.id + ".translation"
|
||||
m.showFromTopOpacity.fieldToInterp = m.top.id + ".opacity"
|
||||
|
||||
m.scrollOffTopPosition.fieldToInterp = m.top.id + ".translation"
|
||||
m.scrollOffTopOpacity.fieldToInterp = m.top.id + ".opacity"
|
||||
|
||||
m.scrollOffBottomPosition.fieldToInterp = m.top.id + ".translation"
|
||||
m.scrollOffBottomOpacity.fieldToInterp = m.top.id + ".opacity"
|
||||
|
||||
m.scrollUpToOnDeckPosition.fieldToInterp = m.top.id + ".translation"
|
||||
|
||||
m.scrollDownToOnDeckPosition.fieldToInterp = m.top.id + ".translation"
|
||||
|
||||
m.scrollOffOnDeckPosition.fieldToInterp = m.top.id + ".translation"
|
||||
end sub
|
||||
|
||||
sub onTranslationChange()
|
||||
m.startingPosition = m.top.translation
|
||||
m.scrollOffBottomPosition.keyValue = "[[0, 0], [" + str(m.startingPosition[0]) + ", " + str(m.startingPosition[1]) + "]]"
|
||||
m.top.unobserveField("translation")
|
||||
end sub
|
||||
|
||||
sub showFromTop()
|
||||
m.showFromTopAnimation.control = "start"
|
||||
end sub
|
||||
|
||||
sub showFromBottom()
|
||||
m.showFromBottomAnimation.control = "start"
|
||||
end sub
|
||||
|
||||
sub scrollOffBottom()
|
||||
m.scrollOffBottomAnimation.control = "start"
|
||||
end sub
|
||||
|
||||
sub scrollOffTop()
|
||||
m.scrollOffTopAnimation.control = "start"
|
||||
end sub
|
||||
|
||||
sub scrollUpToOnDeck()
|
||||
m.scrollUpToOnDeckAnimation.control = "start"
|
||||
end sub
|
||||
|
||||
sub scrollDownToOnDeck()
|
||||
m.scrollDownToOnDeckAnimation.control = "start"
|
||||
end sub
|
||||
|
||||
sub scrollOffOnDeck()
|
||||
m.scrollOffOnDeckAnimation.control = "start"
|
||||
end sub
|
||||
|
||||
sub onFocusChange()
|
||||
defaultFocusElement = m.top.findNode(m.top.defaultFocusID)
|
||||
|
||||
if isValid(defaultFocusElement)
|
||||
defaultFocusElement.setFocus(m.top.isInFocusChain())
|
||||
if isValid(defaultFocusElement.focus)
|
||||
defaultFocusElement.focus = m.top.isInFocusChain()
|
||||
end if
|
||||
end if
|
||||
end sub
|
42
components/section/section.xml
Normal file
42
components/section/section.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<component name="Section" extends="JFGroup">
|
||||
<children>
|
||||
<Animation id="showFromBottomAnimation" duration="0.5" repeat="false">
|
||||
<Vector2DFieldInterpolator id="showFromBottomPosition" key="[0.0, 1.0]" keyValue="[[0, 750], [0, 0]]" fieldToInterp="" />
|
||||
<FloatFieldInterpolator id="showFromBottomOpacity" key="[0.0, 1.0]" keyValue="[0.55, 0.95]" fieldToInterp="" />
|
||||
</Animation>
|
||||
<Animation id="showFromTopAnimation" duration="0.5" repeat="false">
|
||||
<Vector2DFieldInterpolator id="showFromTopPosition" key="[0.0, 1.0]" keyValue="[[0, -1080], [0, 0]]" fieldToInterp="" />
|
||||
<FloatFieldInterpolator id="showFromTopOpacity" key="[0.0, 1.0]" keyValue="[0.55, 0.95]" fieldToInterp="" />
|
||||
</Animation>
|
||||
<Animation id="scrollOffBottomAnimation" duration="0.5" repeat="false">
|
||||
<Vector2DFieldInterpolator id="scrollOffBottomPosition" key="[0.0, 1.0]" keyValue="[]" fieldToInterp="" />
|
||||
<FloatFieldInterpolator id="scrollOffBottomOpacity" key="[0.0, 1.0]" keyValue="[0.95, 0.55]" fieldToInterp="" />
|
||||
</Animation>
|
||||
<Animation id="scrollOffTopAnimation" duration="0.5" repeat="false">
|
||||
<Vector2DFieldInterpolator id="scrollOffTopPosition" key="[0.0, 1.0]" keyValue="[[0, 0], [0, -1080]]" fieldToInterp="" />
|
||||
<FloatFieldInterpolator id="scrollOffTopOpacity" key="[0.0, 1.0]" keyValue="[0.95, 0.55]" fieldToInterp="" />
|
||||
</Animation>
|
||||
<Animation id="scrollUpToOnDeckAnimation" duration="0.5" repeat="false">
|
||||
<Vector2DFieldInterpolator id="scrollUpToOnDeckPosition" key="[0.0, 1.0]" keyValue="[[0, 1100], [0, 950]]" fieldToInterp="" />
|
||||
</Animation>
|
||||
<Animation id="scrollDownToOnDeckAnimation" duration="0.5" repeat="false">
|
||||
<Vector2DFieldInterpolator id="scrollDownToOnDeckPosition" key="[0.0, 1.0]" keyValue="[[0, 0], [0, 950]]" fieldToInterp="" />
|
||||
</Animation>
|
||||
<Animation id="scrollOffOnDeckAnimation" duration="0.5" repeat="false">
|
||||
<Vector2DFieldInterpolator id="scrollOffOnDeckPosition" key="[0.0, 1.0]" keyValue="[[0, 950], [0, 1080]]" fieldToInterp="" />
|
||||
</Animation>
|
||||
</children>
|
||||
<interface>
|
||||
<field id="defaultFocusID" type="string" />
|
||||
<function name="showFromTop" />
|
||||
<function name="showFromBottom" />
|
||||
<function name="scrollOffTop" />
|
||||
<function name="scrollOffBottom" />
|
||||
<function name="scrollUpToOnDeck" />
|
||||
<function name="scrollDownToOnDeck" />
|
||||
<function name="scrollOffOnDeck" />
|
||||
</interface>
|
||||
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
|
||||
<script type="text/brightscript" uri="section.brs" />
|
||||
</component>
|
58
components/section/sectionScroller.brs
Normal file
58
components/section/sectionScroller.brs
Normal file
@ -0,0 +1,58 @@
|
||||
sub init()
|
||||
m.previouslyDisplayedSection = 0
|
||||
end sub
|
||||
|
||||
sub onFocusChange()
|
||||
if m.top.focus
|
||||
m.top.getChild(m.top.displayedIndex).setFocus(true)
|
||||
end if
|
||||
end sub
|
||||
|
||||
sub displayedIndexChanged()
|
||||
if not m.top.affectsFocus then return
|
||||
|
||||
if m.top.displayedIndex < 0
|
||||
return
|
||||
end if
|
||||
|
||||
if m.top.displayedIndex > (m.top.getChildCount() - 1)
|
||||
return
|
||||
end if
|
||||
|
||||
m.top.getChild(m.previouslyDisplayedSection).setFocus(false)
|
||||
|
||||
displayedSection = m.top.getChild(m.top.displayedIndex)
|
||||
displayedSection.setFocus(true)
|
||||
|
||||
onDeckSection = invalid
|
||||
previouslyOnDeckSection = invalid
|
||||
|
||||
if m.top.displayedIndex + 1 <= (m.top.getChildCount() - 1)
|
||||
onDeckSection = m.top.getChild(m.top.displayedIndex + 1)
|
||||
end if
|
||||
|
||||
if m.top.displayedIndex + 2 <= (m.top.getChildCount() - 1)
|
||||
previouslyOnDeckSection = m.top.getChild(m.top.displayedIndex + 2)
|
||||
end if
|
||||
|
||||
' Move sections either up or down depending on what index we're moving to
|
||||
if m.top.displayedIndex > m.previouslyDisplayedSection
|
||||
for i = m.previouslyDisplayedSection to m.top.displayedIndex - 1
|
||||
m.top.getChild(i).callFunc("scrollOffTop")
|
||||
end for
|
||||
|
||||
displayedSection.callFunc("showFromBottom")
|
||||
if isValid(onDeckSection)
|
||||
onDeckSection.callFunc("scrollUpToOnDeck")
|
||||
end if
|
||||
else if m.top.displayedIndex < m.previouslyDisplayedSection
|
||||
m.top.getChild(m.top.displayedIndex + 1).callFunc("scrollDownToOnDeck")
|
||||
displayedSection.callFunc("showFromTop")
|
||||
|
||||
if isValid(previouslyOnDeckSection)
|
||||
previouslyOnDeckSection.callFunc("scrollOffOnDeck")
|
||||
end if
|
||||
end if
|
||||
|
||||
m.previouslyDisplayedSection = m.top.displayedIndex
|
||||
end sub
|
12
components/section/sectionScroller.xml
Normal file
12
components/section/sectionScroller.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<component name="SectionScroller" extends="JFGroup">
|
||||
<children>
|
||||
</children>
|
||||
<interface>
|
||||
<field id="focus" type="boolean" value="true" alwaysNotify="true" onChange="onFocusChange" />
|
||||
<field id="affectsFocus" type="boolean" value="true" />
|
||||
<field id="displayedIndex" type="integer" value="0" onChange="displayedIndexChanged" />
|
||||
</interface>
|
||||
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
|
||||
<script type="text/brightscript" uri="sectionScroller.brs" />
|
||||
</component>
|
@ -20,7 +20,7 @@ sub updateSize()
|
||||
m.top.visible = true
|
||||
|
||||
' size of the whole row
|
||||
m.top.itemSize = [1800, (itemHeight + 40)]
|
||||
m.top.itemSize = [1680, (itemHeight + 40)]
|
||||
' spacing between rows
|
||||
m.top.itemSpacing = [0, 0]
|
||||
|
||||
|
BIN
images/icons/album.png
Normal file
BIN
images/icons/album.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
BIN
images/icons/cassette.png
Normal file
BIN
images/icons/cassette.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
@ -112,9 +112,17 @@
|
||||
<source>Home</source>
|
||||
<translation>Основен</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Въведете потребителско име</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Въведете паролата</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Въведете стойност…</translation>
|
||||
<translation>Въведете стойност...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort Field</source>
|
||||
|
@ -112,9 +112,17 @@
|
||||
<source>Home</source>
|
||||
<translation>Domů</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Zadejte jméno</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Zadejte heslo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Zadejte hodnotu…</translation>
|
||||
<translation>Zadejte hodnotu...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort Field</source>
|
||||
@ -3471,5 +3479,169 @@
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Uložit přihlašovací údaje?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)</comment>
|
||||
<source>NO_ITEMS</source>
|
||||
<translation>Tato %1 neobsahuje žádné položky</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>CRITIC_RATING</source>
|
||||
<translation>Honocení kritiků</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>IMDB_RATING</source>
|
||||
<translation>Hodnocení IMDb</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Name or Title field of media item</comment>
|
||||
<source>TITLE</source>
|
||||
<translation>Název</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>On Now</source>
|
||||
<translation>Nyní</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Delete Saved</source>
|
||||
<translation>Smazat uložené</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Uložit přihlašovací údaje?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>direct</source>
|
||||
<translation>přímý</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio Codec</source>
|
||||
<translation>Audio kodek</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Video Codec</source>
|
||||
<translation>Video kodek</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reason</source>
|
||||
<translation>Důvod</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Transcoding Information</source>
|
||||
<translation>Informace o překódování</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Playback Information</source>
|
||||
<translation>Informace o přehrávání</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</source>
|
||||
<translation>Nastavení maximálního počtu dní, pro setrvání pořadu v seznamu "Další díly", aniž by byl zhlédnut.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Max Days Next Up</source>
|
||||
<translation>Maximum dní pro další díly</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Home Page.</source>
|
||||
<translation>Možností domovské stránky.</translation>
|
||||
<extracomment>Description for Home Page user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Home Page</source>
|
||||
<translation>Domovská stránka</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Settings relating to how the application looks.</source>
|
||||
<translation>Nastavení související se vzhledem aplikace.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Settings relating to playback and supported codec and media types.</source>
|
||||
<translation>Nastavení, která se týkají přehrávání, podporovanému kodeku a typům médií.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Play Trailer</source>
|
||||
<translation>Přehrát trailer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cinema Mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.</source>
|
||||
<translation>Režim Cinema přináší zážitek z kina přímo do vašeho obývacího pokoje díky možnosti přehrávání vlastních úvodů před hlavním titulem.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cinema Mode</source>
|
||||
<translation>Režim Cinema</translation>
|
||||
<extracomment>Settings Menu - Title for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Použijte vygenerovaný obrázek úvodní obrazovky jako pozadí domovské stránky Jellyfin. Aby se změna projevila, bude třeba Jellyfin zavřít a znovu otevřít.</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use generated splashscreen image as Jellyfin's screensaver background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Použijte vygenerovaný obrázek úvodní obrazovky jako pozadí spořiče obrazovky Jellyfin. Aby se změna projevila, bude třeba Jellyfin zavřít a znovu otevřít.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If enabled, images of unwatched episodes will be blurred.</source>
|
||||
<translation>Pokud je povoleno, obrázky nezobrazených epizod budou zobrazeny rozmazaně.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide Taglines</source>
|
||||
<translation>Skrýt slogany</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Details pages.</source>
|
||||
<translation>Možnosti pro stránky s podrobnostmi.</translation>
|
||||
<extracomment>Description for Details page user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Details Page</source>
|
||||
<translation>Stránka s podrobnostmi</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use the replay button to slowly animate to the first item in the folder. (If disabled, the folder will reset to the first item immediately).</source>
|
||||
<translation>Pomocí tlačítka pro přehrávání se můžete pomalu pohybovat k první položce ve složce. (Pokud je vypnuto, složka se znovu hned nastaví na první položku).</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>(Dialog will close automatically)</source>
|
||||
<translation>(Dialog se automaticky zavře)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Here is your Quick Connect code:</source>
|
||||
<translation>Zde je Váš kód pro rychlé připojení:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Quick Connect</source>
|
||||
<translation>Rychle připojit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>%1 of %2</source>
|
||||
<translation>%1 z %2</translation>
|
||||
<extracomment>Item position and count. %1 = current item. %2 = total number of items</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>You can search for Titles, People, Live TV Channels and more</source>
|
||||
<translation>Můžete hledat názvy, osoby, kanály živého vysílání a mnohem více</translation>
|
||||
<extracomment>Help text in search results</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search now</source>
|
||||
<translation>Hledat teď</translation>
|
||||
<extracomment>Help text in search Box</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use voice remote to search</source>
|
||||
<translation>K hledání použít hlasové ovládání</translation>
|
||||
<extracomment>Help text in search voice text box</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to episode</source>
|
||||
<translation>Přejít k epizodě</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Episode Detail Page</extracomment>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -113,8 +113,12 @@
|
||||
<translation>Home</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Enter a value…</translation>
|
||||
<source>Enter a username</source>
|
||||
<translation>Enter a username</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Enter a password</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Name</source>
|
||||
@ -374,7 +378,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>Pick a Jellyfin server from the local network</source>
|
||||
<translation>Pick a Jellyfin server from the local network</translation>
|
||||
<translation>Select an available Jellyfin server from your local network:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to pick a server from a list</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
@ -384,7 +388,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>...or enter server URL manually:</source>
|
||||
<translation>…or enter server URL manually:</translation>
|
||||
<translation>If no server is listed above, you may also enter the server URL manually:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to manually enter a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
@ -844,5 +848,823 @@
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Save Credentials?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</source>
|
||||
<translation>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Max Days Next Up</source>
|
||||
<translation>Max Days Next Up</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Home Page.</source>
|
||||
<translation>Options for Home Page.</translation>
|
||||
<extracomment>Description for Home Page user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Home Page</source>
|
||||
<translation>Home Page</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Settings relating to how the application looks.</source>
|
||||
<translation>Settings relating to how the application looks.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Settings relating to playback and supported codec and media types.</source>
|
||||
<translation>Settings relating to playback and supported codec and media types.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Play Trailer</source>
|
||||
<translation>Play Trailer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Skip Intro</source>
|
||||
<translation>Skip Intro</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hides all clocks in Jellyfin. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Hides all clocks in Jellyfin. Jellyfin will need to be closed and reopened for change to take effect.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide Clock</source>
|
||||
<translation>Hide Clock</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cinema Mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.</source>
|
||||
<translation>Cinema Mode brings the theatre experience straight to your living room with the ability to play custom intros before the main feature.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cinema Mode</source>
|
||||
<translation>Cinema Mode</translation>
|
||||
<extracomment>Settings Menu - Title for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use Splashscreen as Home Background</source>
|
||||
<translation>Use Splashscreen as Home Background</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options that alter the design of Jellyfin.</source>
|
||||
<translation>Options that alter the design of Jellyfin.</translation>
|
||||
<extracomment>Description for Design Elements user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Design Elements</source>
|
||||
<translation>Design Elements</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use generated splashscreen image as Jellyfin's screensaver background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Use generated splashscreen image as Jellyfin's screensaver background. Jellyfin will need to be closed and reopened for change to take effect.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use Splashscreen as Screensaver Background</source>
|
||||
<translation>Use Splashscreen as Screensaver Background</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Jellyfin's screensaver.</source>
|
||||
<translation>Options for Jellyfin's screensaver.</translation>
|
||||
<extracomment>Description for Screensaver user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Screensaver</source>
|
||||
<translation>Screensaver</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If enabled, images of unwatched episodes will be blurred.</source>
|
||||
<translation>If enabled, images of unwatched episodes will be blurred.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Blur Unwatched Episodes</source>
|
||||
<translation>Blur Unwatched Episodes</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for TV Shows.</source>
|
||||
<translation>Options for TV Shows.</translation>
|
||||
<extracomment>Description for TV Shows user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hides tagline text on details pages.</source>
|
||||
<translation>Hides tagline text on details pages.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide Taglines</source>
|
||||
<translation>Hide Taglines</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Details pages.</source>
|
||||
<translation>Options for Details pages.</translation>
|
||||
<extracomment>Description for Details page user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Details Page</source>
|
||||
<translation>Details Page</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use the replay button to slowly animate to the first item in the folder. (If disabled, the folder will reset to the first item immediately).</source>
|
||||
<translation>Use the replay button to slowly animate to the first item in the folder. (If disabled, the folder will reset to the first item immediately).</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Return to Top</source>
|
||||
<translation>Return to Top</translation>
|
||||
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Shows</source>
|
||||
<translation>Shows</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Studios</source>
|
||||
<translation>Studios</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Networks</source>
|
||||
<translation>Networks</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>There was an error authenticating via Quick Connect.</source>
|
||||
<translation>There was an error authenticating via Quick Connect.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>(Dialog will close automatically)</source>
|
||||
<translation>(Dialog will close automatically)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Here is your Quick Connect code:</source>
|
||||
<translation>Here is your Quick Connect code:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Quick Connect</source>
|
||||
<translation>Quick Connect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>%1 of %2</source>
|
||||
<translation>%1 of %2</translation>
|
||||
<extracomment>Item position and count. %1 = current item. %2 = total number of items</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>You can search for Titles, People, Live TV Channels and more</source>
|
||||
<translation>You can search for Titles, People, Live TV Channels and more</translation>
|
||||
<extracomment>Help text in search results</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search now</source>
|
||||
<translation>Search now</translation>
|
||||
<extracomment>Help text in search Box</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use voice remote to search</source>
|
||||
<translation>Use voice remote to search</translation>
|
||||
<extracomment>Help text in search voice text box</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to episode</source>
|
||||
<translation>Go to episode</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Episode Detail Page</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to season</source>
|
||||
<translation>Go to season</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Season Page</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to series</source>
|
||||
<translation>Go to series</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Series Detail Page</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set Watched</source>
|
||||
<translation>Set Watched</translation>
|
||||
<extracomment>Button Text - When pressed, marks item as Warched</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set Favorite</source>
|
||||
<translation>Set Favourite</translation>
|
||||
<extracomment>Button Text - When pressed, sets item as Favorite</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show item count in the library and index of selected item.</source>
|
||||
<translation>Show item count in the library and index of selected item.</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Item Count</source>
|
||||
<translation>Item Count</translation>
|
||||
<extracomment>UI -> Media Grid -> Item Count in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Always show the titles below the poster images. (If disabled, the title will be shown under the highlighted item only).</source>
|
||||
<translation>Always show the titles below the poster images. (If disabled, the title will be shown under the highlighted item only).</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Item Titles</source>
|
||||
<translation>Item Titles</translation>
|
||||
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Media Grid options.</source>
|
||||
<translation>Media Grid options.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Media Grid</source>
|
||||
<translation>Media Grid</translation>
|
||||
<extracomment>UI -> Media Grid section in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>User Interface</source>
|
||||
<translation>User Interface</translation>
|
||||
<extracomment>Title for User Interface section in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Disabled</source>
|
||||
<translation>Disabled</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabled</source>
|
||||
<translation>Enabled</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.</source>
|
||||
<translation>Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>MPEG-2 Support</source>
|
||||
<translation>MPEG-2 Support</translation>
|
||||
<extracomment>Settings Menu - Title for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Playback</source>
|
||||
<translation>Playback</translation>
|
||||
<extracomment>Title for Playback section in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Version</source>
|
||||
<translation>Version</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error was encountered while playing this item. Server did not provide required transcoding data.</source>
|
||||
<translation>An error was encountered while playing this item. Server did not provide required transcoding data.</translation>
|
||||
<extracomment>Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error Getting Playback Information</source>
|
||||
<translation>Error Getting Playback Information</translation>
|
||||
<extracomment>Dialog Title: Received error from server when trying to get information about the selected item for playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>...or enter server URL manually:</source>
|
||||
<translation>If no server is listed above, you may also enter the server URL manually:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to manually enter a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pick a Jellyfin server from the local network</source>
|
||||
<translation>Select an available Jellyfin server from your local network:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to pick a server from a list</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter the server name or ip address</source>
|
||||
<translation>Enter the server name or ip address</translation>
|
||||
<extracomment>Title of KeyboardDialog when manually entering a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unknown</source>
|
||||
<translation>Unknown</translation>
|
||||
<extracomment>Title for a cast member for which we have no information for</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Close</source>
|
||||
<translation>Close</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel Series Recording</source>
|
||||
<translation>Cancel Series Recording</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel Recording</source>
|
||||
<translation>Cancel Recording</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Record Series</source>
|
||||
<translation>Record Series</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Record</source>
|
||||
<translation>Record</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>View Channel</source>
|
||||
<translation>View Channel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>TV Shows</source>
|
||||
<translation>TV Shows</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Movies</source>
|
||||
<translation>Movies</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Special Features</source>
|
||||
<translation>Special Features</translation>
|
||||
<message>
|
||||
<source>Press 'OK' to Close</source>
|
||||
<translation>Press 'OK' to Close</translation>
|
||||
</message>
|
||||
</message>
|
||||
<message>
|
||||
<source>More Like This</source>
|
||||
<translation>More Like This</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cast & Crew</source>
|
||||
<translation>Cast & Crew</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Age</source>
|
||||
<translation>Age</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Died</source>
|
||||
<translation>Died</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Born</source>
|
||||
<translation>Born</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Enter a value...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>On Now</source>
|
||||
<translation>On Now</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Delete Saved</source>
|
||||
<translation>Delete Saved</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Save Credentials?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WxH</source>
|
||||
<translation>WxH</translation>
|
||||
<extracomment>Video width x height</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pixel format</source>
|
||||
<translation>Pixel format</translation>
|
||||
<extracomment>Video pixel format</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Video range type</source>
|
||||
<translation>Video range type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Size</source>
|
||||
<translation>Size</translation>
|
||||
<extracomment>Video size</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Container</source>
|
||||
<translation>Container</translation>
|
||||
<extracomment>Video streaming container</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Bit Rate</source>
|
||||
<translation>Bit Rate</translation>
|
||||
<extracomment>Video streaming bit rate</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Level</source>
|
||||
<translation>Level</translation>
|
||||
<extracomment>Video profile level</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Codec Tag</source>
|
||||
<translation>Codec Tag</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Codec</source>
|
||||
<translation>Codec</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stream Information</source>
|
||||
<translation>Stream Information</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio Channels</source>
|
||||
<translation>Audio Channels</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Total Bitrate</source>
|
||||
<translation>Total Bitrate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>direct</source>
|
||||
<translation>direct</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio Codec</source>
|
||||
<translation>Audio Codec</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Video Codec</source>
|
||||
<translation>Video Codec</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reason</source>
|
||||
<translation>Reason</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Transcoding Information</source>
|
||||
<translation>Transcoding Information</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Playback Information</source>
|
||||
<translation>Playback Information</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</source>
|
||||
<translation>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Max Days Next Up</source>
|
||||
<translation>Max Days Next Up</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Home Page.</source>
|
||||
<translation>Options for Home Page.</translation>
|
||||
<extracomment>Description for Home Page user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Home Page</source>
|
||||
<translation>Home Page</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Settings relating to how the application looks.</source>
|
||||
<translation>Settings relating to how the application looks.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Settings relating to playback and supported codec and media types.</source>
|
||||
<translation>Settings relating to playback and supported codec and media types.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Play Trailer</source>
|
||||
<translation>Play Trailer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hides all clocks in Jellyfin. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Hides all clocks in Jellyfin. Jellyfin will need to be closed and reopened for change to take effect.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide Clock</source>
|
||||
<translation>Hide Clock</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cinema Mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.</source>
|
||||
<translation>Cinema Mode brings the theatre experience straight to your living room with the ability to play custom intros before the main feature.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cinema Mode</source>
|
||||
<translation>Cinema Mode</translation>
|
||||
<extracomment>Settings Menu - Title for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use Splashscreen as Home Background</source>
|
||||
<translation>Use Splashscreen as Home Background</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options that alter the design of Jellyfin.</source>
|
||||
<translation>Options that alter the design of Jellyfin.</translation>
|
||||
<extracomment>Description for Design Elements user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Design Elements</source>
|
||||
<translation>Design Elements</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use generated splashscreen image as Jellyfin's screensaver background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Use generated splashscreen image as Jellyfin's screensaver background. Jellyfin will need to be closed and reopened for change to take effect.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use Splashscreen as Screensaver Background</source>
|
||||
<translation>Use Splashscreen as Screensaver Background</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Jellyfin's screensaver.</source>
|
||||
<translation>Options for Jellyfin's screensaver.</translation>
|
||||
<extracomment>Description for Screensaver user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Screensaver</source>
|
||||
<translation>Screensaver</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If enabled, images of unwatched episodes will be blurred.</source>
|
||||
<translation>If enabled, images of unwatched episodes will be blurred.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Blur Unwatched Episodes</source>
|
||||
<translation>Blur Unwatched Episodes</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for TV Shows.</source>
|
||||
<translation>Options for TV Shows.</translation>
|
||||
<extracomment>Description for TV Shows user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hides tagline text on details pages.</source>
|
||||
<translation>Hides tagline text on details pages.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide Taglines</source>
|
||||
<translation>Hide Taglines</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Details pages.</source>
|
||||
<translation>Options for Details pages.</translation>
|
||||
<extracomment>Description for Details page user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Details Page</source>
|
||||
<translation>Details Page</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use the replay button to slowly animate to the first item in the folder. (If disabled, the folder will reset to the first item immediately).</source>
|
||||
<translation>Use the replay button to slowly animate to the first item in the folder. (If disabled, the folder will reset to the first item immediately).</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Return to Top</source>
|
||||
<translation>Return to Top</translation>
|
||||
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Shows</source>
|
||||
<translation>Shows</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Studios</source>
|
||||
<translation>Studios</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Networks</source>
|
||||
<translation>Networks</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>There was an error authenticating via Quick Connect.</source>
|
||||
<translation>There was an error authenticating via Quick Connect.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>(Dialog will close automatically)</source>
|
||||
<translation>(Dialog will close automatically)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Here is your Quick Connect code:</source>
|
||||
<translation>Here is your Quick Connect code:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Quick Connect</source>
|
||||
<translation>Quick Connect</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>%1 of %2</source>
|
||||
<translation>%1 of %2</translation>
|
||||
<extracomment>Item position and count. %1 = current item. %2 = total number of items</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>You can search for Titles, People, Live TV Channels and more</source>
|
||||
<translation>You can search for Titles, People, Live TV Channels and more</translation>
|
||||
<extracomment>Help text in search results</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search now</source>
|
||||
<translation>Search now</translation>
|
||||
<extracomment>Help text in search Box</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use voice remote to search</source>
|
||||
<translation>Use voice remote to search</translation>
|
||||
<extracomment>Help text in search voice text box</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to episode</source>
|
||||
<translation>Go to episode</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Episode Detail Page</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to season</source>
|
||||
<translation>Go to season</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Season Page</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to series</source>
|
||||
<translation>Go to series</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Series Detail Page</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set Watched</source>
|
||||
<translation>Set Watched</translation>
|
||||
<extracomment>Button Text - When pressed, marks item as Warched</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set Favorite</source>
|
||||
<translation>Set Favourite</translation>
|
||||
<extracomment>Button Text - When pressed, sets item as Favorite</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show item count in the library and index of selected item.</source>
|
||||
<translation>Show item count in the library and index of selected item.</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Item Count</source>
|
||||
<translation>Item Count</translation>
|
||||
<extracomment>UI -> Media Grid -> Item Count in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Always show the titles below the poster images. (If disabled, the title will be shown under the highlighted item only).</source>
|
||||
<translation>Always show the titles below the poster images. (If disabled, the title will be shown under the highlighted item only).</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Item Titles</source>
|
||||
<translation>Item Titles</translation>
|
||||
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Media Grid options.</source>
|
||||
<translation>Media Grid options.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Media Grid</source>
|
||||
<translation>Media Grid</translation>
|
||||
<extracomment>UI -> Media Grid section in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>User Interface</source>
|
||||
<translation>User Interface</translation>
|
||||
<extracomment>Title for User Interface section in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Disabled</source>
|
||||
<translation>Disabled</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabled</source>
|
||||
<translation>Enabled</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.</source>
|
||||
<translation>Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>MPEG-2 Support</source>
|
||||
<translation>MPEG-2 Support</translation>
|
||||
<extracomment>Settings Menu - Title for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Playback</source>
|
||||
<translation>Playback</translation>
|
||||
<extracomment>Title for Playback section in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Version</source>
|
||||
<translation>Version</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error was encountered while playing this item. Server did not provide required transcoding data.</source>
|
||||
<translation>An error was encountered while playing this item. Server did not provide required transcoding data.</translation>
|
||||
<extracomment>Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error Getting Playback Information</source>
|
||||
<translation>Error Getting Playback Information</translation>
|
||||
<extracomment>Dialog Title: Received error from server when trying to get information about the selected item for playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>...or enter server URL manually:</source>
|
||||
<translation>If no server is listed above, you may also enter the server URL manually:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to manually enter a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pick a Jellyfin server from the local network</source>
|
||||
<translation>Select an available Jellyfin server from your local network:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to pick a server from a list</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter the server name or ip address</source>
|
||||
<translation>Enter the server name or IP address</translation>
|
||||
<extracomment>Title of KeyboardDialog when manually entering a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unknown</source>
|
||||
<translation>Unknown</translation>
|
||||
<extracomment>Title for a cast member for which we have no information for</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Close</source>
|
||||
<translation>Close</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel Series Recording</source>
|
||||
<translation>Cancel Series Recording</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel Recording</source>
|
||||
<translation>Cancel Recording</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Record Series</source>
|
||||
<translation>Record Series</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Record</source>
|
||||
<translation>Record</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>View Channel</source>
|
||||
<translation>View Channel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>TV Shows</source>
|
||||
<translation>TV Shows</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Movies</source>
|
||||
<translation>Movies</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Special Features</source>
|
||||
<translation>Special Features</translation>
|
||||
<message>
|
||||
<source>Press 'OK' to Close</source>
|
||||
<translation>Press 'OK' to Close</translation>
|
||||
</message>
|
||||
</message>
|
||||
<message>
|
||||
<source>More Like This</source>
|
||||
<translation>More Like This</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cast & Crew</source>
|
||||
<translation>Cast & Crew</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Age</source>
|
||||
<translation>Age</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Died</source>
|
||||
<translation>Died</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Born</source>
|
||||
<translation>Born</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>On Now</source>
|
||||
<translation>On Now</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Delete Saved</source>
|
||||
<translation>Delete Saved</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Save Credentials?</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
@ -125,8 +125,12 @@
|
||||
<translation>Home</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Enter a value…</translation>
|
||||
<source>Enter a username</source>
|
||||
<translation>Enter a username</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Enter a password</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Name</source>
|
||||
@ -350,32 +354,32 @@
|
||||
<message>
|
||||
<source>Started at</source>
|
||||
<translation>Started at</translation>
|
||||
<extracomment>(Past Tense) For defining time when a program started today (e.g. Started at 08:00) </extracomment>
|
||||
<extracomment>(Past Tense) For defining time when a program started today (e.g. Started at 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Started</source>
|
||||
<translation>Started</translation>
|
||||
<extracomment>(Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00) </extracomment>
|
||||
<extracomment>(Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Starts at</source>
|
||||
<translation>Starts at</translation>
|
||||
<extracomment>(Future Tense) For defining time when a program will start today (e.g. Starts at 08:00) </extracomment>
|
||||
<extracomment>(Future Tense) For defining time when a program will start today (e.g. Starts at 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Starts</source>
|
||||
<translation>Starts</translation>
|
||||
<extracomment>(Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00) </extracomment>
|
||||
<extracomment>(Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ended at</source>
|
||||
<translation>Ended at</translation>
|
||||
<extracomment>(Past Tense) For defining time when a program will ended (e.g. Ended at 08:00) </extracomment>
|
||||
<extracomment>(Past Tense) For defining time when a program will ended (e.g. Ended at 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ends at</source>
|
||||
<translation>Ends at</translation>
|
||||
<extracomment>(Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00) </extracomment>
|
||||
<extracomment>(Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Live</source>
|
||||
@ -442,18 +446,18 @@
|
||||
<extracomment>Content of message box when the requested content is not found on the server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter the server name or ip address</source>
|
||||
<translation>Enter the server name or ip address</translation>
|
||||
<source>Enter the server name or IP address</source>
|
||||
<translation>Enter the server name or IP address</translation>
|
||||
<extracomment>Title of KeyboardDialog when manually entering a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pick a Jellyfin server from the local network</source>
|
||||
<translation>Pick a Jellyfin server from the local network</translation>
|
||||
<translation>Select an available Jellyfin server from your local network:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to pick a server from a list</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>...or enter server URL manually:</source>
|
||||
<translation>…or enter server URL manually:</translation>
|
||||
<translation>If no server is listed above, you may also enter the server URL manually:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to manually enter a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
@ -462,8 +466,8 @@
|
||||
<extracomment>Dialog Title: Received error from server when trying to get information about the selected item for playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error was encountered while playing this item. Server did not provide required transcoding data.</source>
|
||||
<translation>An error was encountered while playing this item. Server did not provide required transcoding data.</translation>
|
||||
<source>An error was encountered while playing this item. Server did not provide required transcoding data.</source>
|
||||
<translation>An error was encountered while playing this item. Server did not provide required transcoding data.</translation>
|
||||
<extracomment>Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
@ -570,7 +574,7 @@
|
||||
<message>
|
||||
<source>%1 of %2</source>
|
||||
<translation>%1 of %2</translation>
|
||||
<extracomment>Item position and count. %1 = current item. %2 = total number of items</extracomment>
|
||||
<extracomment>Item position and count. %1 = current item. %2 = total number of items</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Quick Connect</source>
|
||||
@ -703,11 +707,6 @@
|
||||
<source>Next episode</source>
|
||||
<translation>Next episode</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Skip Intro</source>
|
||||
<translation>Skip Intro</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Play Trailer</source>
|
||||
<translation>Play Trailer</translation>
|
||||
</message>
|
||||
@ -738,5 +737,88 @@
|
||||
<translation>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Playback Information</source>
|
||||
<translation>Playback Information</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Transcoding Information</source>
|
||||
<translation>Transcoding Information</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reason</source>
|
||||
<translation>Reason</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Video Codec</source>
|
||||
<translation>Video Codec</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio Codec</source>
|
||||
<translation>Audio Codec</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>direct</source>
|
||||
<translation>direct</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Total Bitrate</source>
|
||||
<translation>Total Bitrate</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio Channels</source>
|
||||
<translation>Audio Channels</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stream Information</source>
|
||||
<translation>Stream Information</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Codec</source>
|
||||
<translation>Codec</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Codec Tag</source>
|
||||
<translation>Codec Tag</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Level</source>
|
||||
<translation>Level</translation>
|
||||
<extracomment>Video profile level</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Bit Rate</source>
|
||||
<translation>Bit Rate</translation>
|
||||
<extracomment>Video streaming bit rate</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Container</source>
|
||||
<translation>Container</translation>
|
||||
<extracomment>Video streaming container</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Size</source>
|
||||
<translation>Size</translation>
|
||||
<extracomment>Video size</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Video range type</source>
|
||||
<translation>Video range type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pixel format</source>
|
||||
<translation>Pixel format</translation>
|
||||
<extracomment>Video pixel format</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>WxH</source>
|
||||
<translation>WxH</translation>
|
||||
<extracomment>Video width x height</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unable to find any albums or songs belonging to this artist</source>
|
||||
<translation>Unable to find any albums or songs belonging to this artist</translation>
|
||||
<extracomment>Popup message when we find no audio data for an artist</extracomment>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
@ -112,9 +112,17 @@
|
||||
<source>Home</source>
|
||||
<translation>Inicio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Ingresar nombre de usuario</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Ingresar la contraseña</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Ingresar un valor…</translation>
|
||||
<translation>Ingresar un valor...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort Field</source>
|
||||
|
@ -112,9 +112,17 @@
|
||||
<source>Home</source>
|
||||
<translation>Inicio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Ingres nombre de usuario</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Ingres la contraseña</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Ingrese un valor…</translation>
|
||||
<translation>Ingres un valor...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort Field</source>
|
||||
|
@ -113,8 +113,12 @@
|
||||
<translation>Inicio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Enter a value...</translation>
|
||||
<source>Enter a username</source>
|
||||
<translation>Ingres nombre de usuario</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Ingres la contraseña</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort Field</source>
|
||||
@ -168,9 +172,17 @@
|
||||
<source>Audio</source>
|
||||
<translation>Audio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Ingresar nombre de usuario</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Ingresar la contraseña</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Introduce un valor…</translation>
|
||||
<translation>Ingresar un valor...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort Field</source>
|
||||
@ -1867,5 +1879,10 @@
|
||||
<source>Change Server</source>
|
||||
<translation>Cambiar de Servidor</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Name or Title field of media item</comment>
|
||||
<source>TITLE</source>
|
||||
<translation>Nombre</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
@ -112,6 +112,14 @@
|
||||
<source>Home</source>
|
||||
<translation>Accueil</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Entrez votre nom d'utilisateur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Entrer le mot de passe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Entrer une valeur…</translation>
|
||||
@ -2639,7 +2647,7 @@
|
||||
<translation>Bonus</translation>
|
||||
<message>
|
||||
<source>Press 'OK' to Close</source>
|
||||
<translation>Press 'OK' to Close</translation>
|
||||
<translation>Appuyez sur 'OK' pour fermer</translation>
|
||||
</message>
|
||||
</message>
|
||||
<message>
|
||||
@ -2717,5 +2725,653 @@
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Enregistrer les identifiants ?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>More Like This</source>
|
||||
<translation>Similaires</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Age</source>
|
||||
<translation>Âge</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Title of Tab for options to filter library content</comment>
|
||||
<source>TAB_FILTER</source>
|
||||
<translation>Filtrer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Title of Tab for options to sort library content</comment>
|
||||
<source>TAB_SORT</source>
|
||||
<translation>Trier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RUNTIME</source>
|
||||
<translation>Durée</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RELEASE_DATE</source>
|
||||
<translation>Date de sortie</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>PLAY_COUNT</source>
|
||||
<translation>Nombre de lecture</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>OFFICIAL_RATING</source>
|
||||
<translation>Classification parentale</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DATE_PLAYED</source>
|
||||
<translation>Date de lecture</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DATE_ADDED</source>
|
||||
<translation>Date d'ajout</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>IMDB_RATING</source>
|
||||
<translation>Classement IMDb</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Name or Title field of media item</comment>
|
||||
<source>TITLE</source>
|
||||
<translation>Nom</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unable to load Channel Data from the server</source>
|
||||
<translation>Impossible de charger les données de la chaîne à partir du serveur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error loading Channel Data</source>
|
||||
<translation>Erreur lors du chargement des données de la chaîne</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Loading Channel Data</source>
|
||||
<translation>Chargement des données de la chaîne</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error was encountered while playing this item.</source>
|
||||
<translation>Une erreur s'est produite lors de la lecture de cet élément.</translation>
|
||||
<extracomment>Dialog detail when error occurs during playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>There was an error retrieving the data for this item from the server.</source>
|
||||
<translation>Une erreur s'est produite lors de la récupération des données de cet élément à partir du serveur.</translation>
|
||||
<extracomment>Dialog detail when unable to load Content from Server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error During Playback</source>
|
||||
<translation>Erreur lors de la lecture</translation>
|
||||
<extracomment>Dialog title when error occurs during playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error Retrieving Content</source>
|
||||
<translation>Erreur lors de la récupération du contenu</translation>
|
||||
<extracomment>Dialog title when unable to load Content from Server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>On Now</source>
|
||||
<translation>Maintenant</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Enregistrer les identifiants ?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Delete Saved</source>
|
||||
<translation>Supprimer les informations enregistrées</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Special Features</source>
|
||||
<translation>Caractéristiques spéciales</translation>
|
||||
<message>
|
||||
<source>Press 'OK' to Close</source>
|
||||
<translation>Press 'OK' to Close</translation>
|
||||
</message>
|
||||
</message>
|
||||
<message>
|
||||
<source>WxH</source>
|
||||
<translation>WxH</translation>
|
||||
<extracomment>Video width x height</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pixel format</source>
|
||||
<translation>Format pixel</translation>
|
||||
<extracomment>Video pixel format</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Video range type</source>
|
||||
<translation>Type de plage vidéo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Size</source>
|
||||
<translation>Taille</translation>
|
||||
<extracomment>Video size</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Container</source>
|
||||
<translation>Conteneur</translation>
|
||||
<extracomment>Video streaming container</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Bit Rate</source>
|
||||
<translation>Débit Binaire</translation>
|
||||
<extracomment>Video streaming bit rate</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Level</source>
|
||||
<translation>Niveau</translation>
|
||||
<extracomment>Video profile level</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Codec Tag</source>
|
||||
<translation>Balise de Codec</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Codec</source>
|
||||
<translation>Codec</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Stream Information</source>
|
||||
<translation>Informations sur le Flux</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio Channels</source>
|
||||
<translation>Canaux Audio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Total Bitrate</source>
|
||||
<translation>Débit Total</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>direct</source>
|
||||
<translation>direct</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Video Codec</source>
|
||||
<translation>Codec Vidéo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Audio Codec</source>
|
||||
<translation>Codec Audio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reason</source>
|
||||
<translation>Raison</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Transcoding Information</source>
|
||||
<translation>Informations de transcodage</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Playback Information</source>
|
||||
<translation>Informations de lecture</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</source>
|
||||
<translation>Définissez le nombre maximum de jours pendant lesquels une émission doit rester dans la liste "Next Up" sans la regarder.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Max Days Next Up</source>
|
||||
<translation>Max jours suivant</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Home Page.</source>
|
||||
<translation>Options pour la page d'accueil.</translation>
|
||||
<extracomment>Description for Home Page user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Home Page</source>
|
||||
<translation>Page d'accueil</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Settings relating to how the application looks.</source>
|
||||
<translation>Paramètres relatifs à l'apparence de l'application.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Settings relating to playback and supported codec and media types.</source>
|
||||
<translation>Paramètres relatifs à la lecture et aux types de codec et de média pris en charge.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Play Trailer</source>
|
||||
<translation>Lire la bande-annonce</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hides all clocks in Jellyfin. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Masque toutes les horloges de Jellyfin. Jellyfin devra être fermé et rouvert pour que le changement prenne effet.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide Clock</source>
|
||||
<translation>Masquer l'horloge</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cinema Mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.</source>
|
||||
<translation>Le Mode Cinéma apporte l'expérience théâtrale directement dans votre salon avec la possibilité de jouer des intros personnalisées avant la fonctionnalité principale.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cinema Mode</source>
|
||||
<translation>Mode Cinéma</translation>
|
||||
<extracomment>Settings Menu - Title for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Utilisez générer une image d'écran de démarrage comme arrière-plan d'accueil de Jellyfin. Jellyfin devra être fermé et rouvert pour que le changement prenne effet.</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use Splashscreen as Home Background</source>
|
||||
<translation>Utiliser l'écran de démarrage comme arrière-plan d'accueil</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options that alter the design of Jellyfin.</source>
|
||||
<translation>Options qui modifient la conception de Jellyfin.</translation>
|
||||
<extracomment>Description for Design Elements user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Design Elements</source>
|
||||
<translation>Éléments de design</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use generated splashscreen image as Jellyfin's screensaver background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||
<translation>Utilisez générer une image d'écran de démarrage comme fond d'écran de Jellyfin. Jellyfin devra être fermé et rouvert pour que le changement prenne effet.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use Splashscreen as Screensaver Background</source>
|
||||
<translation>Utiliser Splashscreen comme fond d'écran de veille</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Jellyfin's screensaver.</source>
|
||||
<translation>Options de l'écran de veille de Jellyfin.</translation>
|
||||
<extracomment>Description for Screensaver user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Screensaver</source>
|
||||
<translation>Écran de veille</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>If enabled, images of unwatched episodes will be blurred.</source>
|
||||
<translation>Si activé, les images des épisodes non regardés seront floues.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Blur Unwatched Episodes</source>
|
||||
<translation>Flouter les épisodes non visionnés</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for TV Shows.</source>
|
||||
<translation>Options pour les Séries Télé.</translation>
|
||||
<extracomment>Description for TV Shows user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hides tagline text on details pages.</source>
|
||||
<translation>Masque le texte du slogan sur les pages de détails.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Hide Taglines</source>
|
||||
<translation>Masquer les slogans</translation>
|
||||
<extracomment>Option Title in user setting screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options for Details pages.</source>
|
||||
<translation>Options des pages Détails.</translation>
|
||||
<extracomment>Description for Details page user settings.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Return to Top</source>
|
||||
<translation>Retourner en Haut</translation>
|
||||
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Details Page</source>
|
||||
<translation>Page de Détails</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use the replay button to slowly animate to the first item in the folder. (If disabled, the folder will reset to the first item immediately).</source>
|
||||
<translation>Utilisez le bouton de relecture pour animer lentement le premier élément du dossier. (Si désactivé, le dossier sera immédiatement réinitialisé au premier élément).</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Shows</source>
|
||||
<translation>Série</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Studios</source>
|
||||
<translation>Studios</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Networks</source>
|
||||
<translation>Réseaux</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>There was an error authenticating via Quick Connect.</source>
|
||||
<translation>Une erreur s'est produite lors de l'authentification à l'aide de connexion rapide.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>(Dialog will close automatically)</source>
|
||||
<translation>(La boîte de dialogue se fermera automatiquement)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Here is your Quick Connect code:</source>
|
||||
<translation>Voici votre code de connexion rapide :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Quick Connect</source>
|
||||
<translation>Connexion rapide</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>%1 of %2</source>
|
||||
<translation>%1 sur %2</translation>
|
||||
<extracomment>Item position and count. %1 = current item. %2 = total number of items</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>You can search for Titles, People, Live TV Channels and more</source>
|
||||
<translation>Vous pouvez rechercher des titres, des personnes, des chaînes de télévision en direct et plus encore</translation>
|
||||
<extracomment>Help text in search results</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search now</source>
|
||||
<translation>Rechercher maintenant</translation>
|
||||
<extracomment>Help text in search Box</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use voice remote to search</source>
|
||||
<translation>Utilisez la télécommande vocale pour rechercher</translation>
|
||||
<extracomment>Help text in search voice text box</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to episode</source>
|
||||
<translation>Aller à l'épisode</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Episode Detail Page</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to season</source>
|
||||
<translation>Aller à la saison</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Season Page</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Go to series</source>
|
||||
<translation>Aller à la série</translation>
|
||||
<extracomment>Continue Watching Popup Menu - Navigate to the Series Detail Page</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set Watched</source>
|
||||
<translation>Définir regardé</translation>
|
||||
<extracomment>Button Text - When pressed, marks item as Warched</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Set Favorite</source>
|
||||
<translation>Définir le favori</translation>
|
||||
<extracomment>Button Text - When pressed, sets item as Favorite</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show item count in the library and index of selected item.</source>
|
||||
<translation>Afficher le nombre d'éléments dans la bibliothèque et l'index de l'élément sélectionné.</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Item Count</source>
|
||||
<translation>Nombre d'éléments</translation>
|
||||
<extracomment>UI -> Media Grid -> Item Count in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Always show the titles below the poster images. (If disabled, the title will be shown under the highlighted item only).</source>
|
||||
<translation>Affichez toujours les titres sous les images des affiches. (Si désactivé, le titre s'affichera uniquement sous l'élément en surbrillance).</translation>
|
||||
<extracomment>Description for option in Setting Screen</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Item Titles</source>
|
||||
<translation>Titres des éléments</translation>
|
||||
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Media Grid options.</source>
|
||||
<translation>Options de la grille média.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Media Grid</source>
|
||||
<translation>Grille des médias</translation>
|
||||
<extracomment>UI -> Media Grid section in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>User Interface</source>
|
||||
<translation>Interface utilisateur</translation>
|
||||
<extracomment>Title for User Interface section in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Disabled</source>
|
||||
<translation>Désactivée</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enabled</source>
|
||||
<translation>Activé</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.</source>
|
||||
<translation>Prise en charge de la lecture directe du contenu MPEG-2 (par exemple, Live TV). Cela empêchera le transcodage du contenu MPEG-2, mais utilisera beaucoup plus de bande passante.</translation>
|
||||
<extracomment>Settings Menu - Description for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>MPEG-2 Support</source>
|
||||
<translation>Prise en charge MPEG-2</translation>
|
||||
<extracomment>Settings Menu - Title for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Playback</source>
|
||||
<translation>Lecture</translation>
|
||||
<extracomment>Title for Playback section in user setting screen.</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Version</source>
|
||||
<translation>Version</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error was encountered while playing this item. Server did not provide required transcoding data.</source>
|
||||
<translation>Une erreur s'est produite lors de la lecture de cet élément. Le serveur n'a pas fourni les données de transcodage requises.</translation>
|
||||
<extracomment>Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error Getting Playback Information</source>
|
||||
<translation>Erreur lors de l'obtention des informations de lecture</translation>
|
||||
<extracomment>Dialog Title: Received error from server when trying to get information about the selected item for playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>...or enter server URL manually:</source>
|
||||
<translation>Si aucun serveur n'est répertorié ci-dessus, vous pouvez également saisir manuellement l'URL du serveur :</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to manually enter a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Pick a Jellyfin server from the local network</source>
|
||||
<translation>Sélectionnez un serveur Jellyfin disponible sur votre réseau local :</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to pick a server from a list</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter the server name or ip address</source>
|
||||
<translation>Entrez le nom du serveur ou l'adresse IP</translation>
|
||||
<extracomment>Title of KeyboardDialog when manually entering a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>The requested content does not exist on the server</source>
|
||||
<translation>Le contenu demandé n'existe pas sur le serveur</translation>
|
||||
<extracomment>Content of message box when the requested content is not found on the server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unknown</source>
|
||||
<translation>Inconnue</translation>
|
||||
<extracomment>Title for a cast member for which we have no information for</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Not found</source>
|
||||
<translation>Pas trouvé</translation>
|
||||
<extracomment>Title of message box when the requested content is not found on the server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Connecting to Server</source>
|
||||
<translation>Connexion au Serveur</translation>
|
||||
<extracomment>Message to display to user while client is attempting to connect to the server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Close</source>
|
||||
<translation>Fermer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel Series Recording</source>
|
||||
<translation>Annuler l'enregistrement de la série</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cancel Recording</source>
|
||||
<translation>Annuler l'enregistrement</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Record Series</source>
|
||||
<translation>Record la série</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Record</source>
|
||||
<translation>Record</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>View Channel</source>
|
||||
<translation>Voir le canal</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>TV Guide</source>
|
||||
<translation>Guide télé</translation>
|
||||
<extracomment>Menu option for showing Live TV Guide / Schedule</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Channels</source>
|
||||
<translation>Canals</translation>
|
||||
<extracomment>Menu option for showing Live TV Channel List</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Repeat</source>
|
||||
<translation>Répéter</translation>
|
||||
<extracomment>If TV Shows has previously been broadcasted</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Live</source>
|
||||
<translation>En direct</translation>
|
||||
<extracomment>If TV Show is being broadcast live (not pre-recorded)</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ended at</source>
|
||||
<translation>Fini à</translation>
|
||||
<extracomment>(Past Tense) For defining time when a program will ended (e.g. Ended at 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ends at</source>
|
||||
<translation>Fini à</translation>
|
||||
<extracomment>(Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Starts</source>
|
||||
<translation>Débute</translation>
|
||||
<extracomment>(Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Starts at</source>
|
||||
<translation>Commence à</translation>
|
||||
<extracomment>(Future Tense) For defining time when a program will start today (e.g. Starts at 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Started</source>
|
||||
<translation>Commencé</translation>
|
||||
<extracomment>(Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Started at</source>
|
||||
<translation>Commencé à</translation>
|
||||
<extracomment>(Past Tense) For defining time when a program started today (e.g. Started at 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Saturday</source>
|
||||
<translation>Samedi</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Friday</source>
|
||||
<translation>Vendredi</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Thursday</source>
|
||||
<translation>Jeudi</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Wednesday</source>
|
||||
<translation>Mercredi</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Tuesday</source>
|
||||
<translation>Mardi</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Monday</source>
|
||||
<translation>Lundi</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sunday</source>
|
||||
<translation>Dimanche</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>tomorrow</source>
|
||||
<translation>demain</translation>
|
||||
<extracomment>Next day</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>yesterday</source>
|
||||
<translation>hier</translation>
|
||||
<extracomment>Previous day</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>today</source>
|
||||
<translation>aujourd'hui</translation>
|
||||
<extracomment>Current day</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>TV Shows</source>
|
||||
<translation>Séries télé</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Movies</source>
|
||||
<translation>Films</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cast & Crew</source>
|
||||
<translation>Casting et équipe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Born</source>
|
||||
<translation>Né\Née</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Died</source>
|
||||
<translation>Mort</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Title of Tab for switching "views" when looking at a library</comment>
|
||||
<source>TAB_VIEW</source>
|
||||
<translation>Visualiser</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>CRITIC_RATING</source>
|
||||
<translation>Note des critiques</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)</comment>
|
||||
<source>NO_ITEMS</source>
|
||||
<translation>Ce %1 ne contient pas d'éléments</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
@ -112,6 +112,14 @@
|
||||
<source>Home</source>
|
||||
<translation>Accueil</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Entrez votre nom d'utilisateur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Entrer le mot de passe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Entrez une valeur…</translation>
|
||||
@ -1076,5 +1084,45 @@
|
||||
<translation>...ou entrer l'adresse URL du serveur manuellement:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to manually enter a server URL</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error was encountered while playing this item.</source>
|
||||
<translation>Une erreur s'est produite lors de la lecture de cet élément.</translation>
|
||||
<extracomment>Dialog detail when error occurs during playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>There was an error retrieving the data for this item from the server.</source>
|
||||
<translation>Il y a eu une erreur pendant la recherche de donnnées pour cet item provenant du serveur.</translation>
|
||||
<extracomment>Dialog detail when unable to load Content from Server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error During Playback</source>
|
||||
<translation>Erreur durant la lecture</translation>
|
||||
<extracomment>Dialog title when error occurs during playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error Retrieving Content</source>
|
||||
<translation>Erreur lors de la récupération du contenu</translation>
|
||||
<extracomment>Dialog title when unable to load Content from Server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>On Now</source>
|
||||
<translation type="unfinished">Jouant maintenant</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Delete Saved</source>
|
||||
<translation>Effacer sauvegardés</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Enregistrer les identifiants ?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sign Out</source>
|
||||
<translation>Se déconnecter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Change Server</source>
|
||||
<translation>Changer de serveur</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -112,6 +112,14 @@
|
||||
<source>Home</source>
|
||||
<translation>Home</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Inserisci il tuo cognome</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Inserisci la password</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Inserire un valore…</translation>
|
||||
|
@ -112,6 +112,14 @@
|
||||
<source>Home</source>
|
||||
<translation>Mājas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Ievadiet lietotājvārdu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Ievadiet paroli</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Ievadi vērtību…</translation>
|
||||
|
@ -112,6 +112,14 @@
|
||||
<source>Home</source>
|
||||
<translation>Início</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Insira nome de usuário</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Insira um senha</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Insira um valor…</translation>
|
||||
|
@ -112,6 +112,14 @@
|
||||
<source>Home</source>
|
||||
<translation>Acasă</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Introduceți un nume de utilizator</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Introduceți o parolă</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Introduceți o valoare…</translation>
|
||||
|
@ -112,6 +112,14 @@
|
||||
<source>Home</source>
|
||||
<translation>Domov</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Zadajte používateľské meno</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Zadajte heslo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Zadajte hodnotu…</translation>
|
||||
|
@ -112,6 +112,14 @@
|
||||
<source>Home</source>
|
||||
<translation>Domov</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Vnesite svoje uporabniško ime</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Vnesite geslo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation>Vnesite vrednost…</translation>
|
||||
|
@ -112,9 +112,17 @@
|
||||
<source>Home</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a username</source>
|
||||
<translation>Faka igama lomsebenzisi</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a password</source>
|
||||
<translation>Faka iphasiwedi</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Enter a value...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Faka inani...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sort Field</source>
|
||||
|
517
package-lock.json
generated
517
package-lock.json
generated
@ -7,19 +7,20 @@
|
||||
"": {
|
||||
"name": "jellyfin-roku",
|
||||
"version": "1.4.12",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-2.0",
|
||||
"dependencies": {
|
||||
"api": "npm:jellyfin-api-bs-client@^1.0.5",
|
||||
"bgv": "npm:button-group-vert@^1.0.1",
|
||||
"bgv": "npm:button-group-vert@^1.0.2",
|
||||
"brighterscript-formatter": "^1.6.8",
|
||||
"sob": "npm:slide-out-button@^1.0.1",
|
||||
"intKeyboard": "npm:integer-keyboard@^1.0.12"
|
||||
"intKeyboard": "npm:integer-keyboard@^1.0.12",
|
||||
"sob": "npm:slide-out-button@^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rokucommunity/bslint": "0.7.5",
|
||||
"brighterscript": "0.57.0",
|
||||
"brighterscript": "0.57.2",
|
||||
"rooibos-cli": "1.4.0",
|
||||
"ropm": "0.10.9"
|
||||
"ropm": "0.10.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
@ -783,9 +784,9 @@
|
||||
},
|
||||
"node_modules/bgv": {
|
||||
"name": "button-group-vert",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/button-group-vert/-/button-group-vert-1.0.1.tgz",
|
||||
"integrity": "sha512-PtOAglZ7w1ebPR5PVxtPNfADydhwU9pJ8X4KKkaqvuDwNMOcD2LkwpgCH0nuGm/yzrws9Kqkqf86IC5mZh8xsQ=="
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/button-group-vert/-/button-group-vert-1.0.2.tgz",
|
||||
"integrity": "sha512-pfrUYI/aFubtjhA8I08qNCtDluyIScksldR15icR7Pj24tNELYCYXE7M0jaU7xgdiFAhZJcYuB3aCXzyI1CoMw=="
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "1.13.1",
|
||||
@ -828,9 +829,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/brighterscript": {
|
||||
"version": "0.57.0",
|
||||
"resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.57.0.tgz",
|
||||
"integrity": "sha512-lv7/qIBLrF62fnukTQUR7OZlzKugMSDkSpdtMTZKElTCY/CqU3Kueprg+fKC4zuQeFdZlKnVrD5fpSYZiOhe2A==",
|
||||
"version": "0.57.2",
|
||||
"resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.57.2.tgz",
|
||||
"integrity": "sha512-idvz7lVLSN1mM/VoDt4/uJPFqdydSgCro2eIwT9vqV8z/1iNLpUtvXCWfeAbWxsbJkXWtmQq4GPkklCxc4OjrQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rokucommunity/bslib": "^0.1.1",
|
||||
@ -5235,14 +5236,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ropm": {
|
||||
"version": "0.10.9",
|
||||
"resolved": "https://registry.npmjs.org/ropm/-/ropm-0.10.9.tgz",
|
||||
"integrity": "sha512-HuYCFi90rCsiBYe8+0I6ym2QGeWbmfZkSv3ubL/eAmZQoJl0ebGXcjg6P44IeOIR5tZRyJ6TDiiST+6m2GyUNg==",
|
||||
"version": "0.10.10",
|
||||
"resolved": "https://registry.npmjs.org/ropm/-/ropm-0.10.10.tgz",
|
||||
"integrity": "sha512-tkPuDwP/Mva9IXIuTf4pnH1DC27WLeLfu8QJ70WwaX9tepNMZeDi4eEQdWQ7kalXxxlwXGnG4jUaaA1B4v8zWw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@xml-tools/ast": "^5.0.5",
|
||||
"@xml-tools/parser": "1.0.10",
|
||||
"brighterscript": "^0.57.0",
|
||||
"brighterscript": "^0.57.2",
|
||||
"del": "6.0.0",
|
||||
"fs-extra": "9.1.0",
|
||||
"glob-all": "3.2.1",
|
||||
@ -5268,121 +5269,6 @@
|
||||
"chevrotain": "7.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/brighterscript": {
|
||||
"version": "0.57.0",
|
||||
"resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.57.0.tgz",
|
||||
"integrity": "sha512-lv7/qIBLrF62fnukTQUR7OZlzKugMSDkSpdtMTZKElTCY/CqU3Kueprg+fKC4zuQeFdZlKnVrD5fpSYZiOhe2A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rokucommunity/bslib": "^0.1.1",
|
||||
"@xml-tools/parser": "^1.0.7",
|
||||
"array-flat-polyfill": "^1.0.1",
|
||||
"chalk": "^2.4.2",
|
||||
"chevrotain": "^7.0.1",
|
||||
"chokidar": "^3.5.1",
|
||||
"clear": "^0.1.0",
|
||||
"cross-platform-clear-console": "^2.3.0",
|
||||
"debounce-promise": "^3.1.0",
|
||||
"eventemitter3": "^4.0.0",
|
||||
"fast-glob": "^3.2.11",
|
||||
"file-url": "^3.0.0",
|
||||
"fs-extra": "^8.0.0",
|
||||
"jsonc-parser": "^2.3.0",
|
||||
"long": "^3.2.0",
|
||||
"luxon": "^1.8.3",
|
||||
"minimatch": "^3.0.4",
|
||||
"moment": "^2.23.0",
|
||||
"p-settle": "^2.1.0",
|
||||
"parse-ms": "^2.1.0",
|
||||
"require-relative": "^0.8.7",
|
||||
"roku-deploy": "^3.8.1",
|
||||
"serialize-error": "^7.0.1",
|
||||
"source-map": "^0.7.3",
|
||||
"vscode-languageserver": "7.0.0",
|
||||
"vscode-languageserver-protocol": "3.16.0",
|
||||
"vscode-languageserver-textdocument": "^1.0.1",
|
||||
"vscode-uri": "^2.1.1",
|
||||
"xml2js": "^0.4.19",
|
||||
"yargs": "^16.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"bsc": "dist/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/brighterscript/node_modules/fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6 <7 || >=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/chevrotain": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.1.tgz",
|
||||
@ -5392,45 +5278,6 @@
|
||||
"regexp-to-ast": "0.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/fs-extra": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
@ -5446,7 +5293,7 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/fs-extra/node_modules/jsonfile": {
|
||||
"node_modules/ropm/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
@ -5458,7 +5305,7 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/fs-extra/node_modules/universalify": {
|
||||
"node_modules/ropm/node_modules/universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
@ -5467,102 +5314,6 @@
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ropm/node_modules/yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
@ -7176,9 +6927,9 @@
|
||||
}
|
||||
},
|
||||
"bgv": {
|
||||
"version": "npm:button-group-vert@1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/button-group-vert/-/button-group-vert-1.0.1.tgz",
|
||||
"integrity": "sha512-PtOAglZ7w1ebPR5PVxtPNfADydhwU9pJ8X4KKkaqvuDwNMOcD2LkwpgCH0nuGm/yzrws9Kqkqf86IC5mZh8xsQ=="
|
||||
"version": "npm:button-group-vert@1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/button-group-vert/-/button-group-vert-1.0.2.tgz",
|
||||
"integrity": "sha512-pfrUYI/aFubtjhA8I08qNCtDluyIScksldR15icR7Pj24tNELYCYXE7M0jaU7xgdiFAhZJcYuB3aCXzyI1CoMw=="
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "1.13.1",
|
||||
@ -7215,9 +6966,9 @@
|
||||
}
|
||||
},
|
||||
"brighterscript": {
|
||||
"version": "0.57.0",
|
||||
"resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.57.0.tgz",
|
||||
"integrity": "sha512-lv7/qIBLrF62fnukTQUR7OZlzKugMSDkSpdtMTZKElTCY/CqU3Kueprg+fKC4zuQeFdZlKnVrD5fpSYZiOhe2A==",
|
||||
"version": "0.57.2",
|
||||
"resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.57.2.tgz",
|
||||
"integrity": "sha512-idvz7lVLSN1mM/VoDt4/uJPFqdydSgCro2eIwT9vqV8z/1iNLpUtvXCWfeAbWxsbJkXWtmQq4GPkklCxc4OjrQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@rokucommunity/bslib": "^0.1.1",
|
||||
@ -10677,14 +10428,14 @@
|
||||
}
|
||||
},
|
||||
"ropm": {
|
||||
"version": "0.10.9",
|
||||
"resolved": "https://registry.npmjs.org/ropm/-/ropm-0.10.9.tgz",
|
||||
"integrity": "sha512-HuYCFi90rCsiBYe8+0I6ym2QGeWbmfZkSv3ubL/eAmZQoJl0ebGXcjg6P44IeOIR5tZRyJ6TDiiST+6m2GyUNg==",
|
||||
"version": "0.10.10",
|
||||
"resolved": "https://registry.npmjs.org/ropm/-/ropm-0.10.10.tgz",
|
||||
"integrity": "sha512-tkPuDwP/Mva9IXIuTf4pnH1DC27WLeLfu8QJ70WwaX9tepNMZeDi4eEQdWQ7kalXxxlwXGnG4jUaaA1B4v8zWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@xml-tools/ast": "^5.0.5",
|
||||
"@xml-tools/parser": "1.0.10",
|
||||
"brighterscript": "^0.57.0",
|
||||
"brighterscript": "^0.57.2",
|
||||
"del": "6.0.0",
|
||||
"fs-extra": "9.1.0",
|
||||
"glob-all": "3.2.1",
|
||||
@ -10704,102 +10455,6 @@
|
||||
"chevrotain": "7.1.1"
|
||||
}
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"brighterscript": {
|
||||
"version": "0.57.0",
|
||||
"resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.57.0.tgz",
|
||||
"integrity": "sha512-lv7/qIBLrF62fnukTQUR7OZlzKugMSDkSpdtMTZKElTCY/CqU3Kueprg+fKC4zuQeFdZlKnVrD5fpSYZiOhe2A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@rokucommunity/bslib": "^0.1.1",
|
||||
"@xml-tools/parser": "^1.0.7",
|
||||
"array-flat-polyfill": "^1.0.1",
|
||||
"chalk": "^2.4.2",
|
||||
"chevrotain": "^7.0.1",
|
||||
"chokidar": "^3.5.1",
|
||||
"clear": "^0.1.0",
|
||||
"cross-platform-clear-console": "^2.3.0",
|
||||
"debounce-promise": "^3.1.0",
|
||||
"eventemitter3": "^4.0.0",
|
||||
"fast-glob": "^3.2.11",
|
||||
"file-url": "^3.0.0",
|
||||
"fs-extra": "^8.0.0",
|
||||
"jsonc-parser": "^2.3.0",
|
||||
"long": "^3.2.0",
|
||||
"luxon": "^1.8.3",
|
||||
"minimatch": "^3.0.4",
|
||||
"moment": "^2.23.0",
|
||||
"p-settle": "^2.1.0",
|
||||
"parse-ms": "^2.1.0",
|
||||
"require-relative": "^0.8.7",
|
||||
"roku-deploy": "^3.8.1",
|
||||
"serialize-error": "^7.0.1",
|
||||
"source-map": "^0.7.3",
|
||||
"vscode-languageserver": "7.0.0",
|
||||
"vscode-languageserver-protocol": "3.16.0",
|
||||
"vscode-languageserver-textdocument": "^1.0.1",
|
||||
"vscode-uri": "^2.1.1",
|
||||
"xml2js": "^0.4.19",
|
||||
"yargs": "^16.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"chevrotain": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.1.tgz",
|
||||
@ -10809,31 +10464,6 @@
|
||||
"regexp-to-ast": "0.5.0"
|
||||
}
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.3.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
|
||||
@ -10844,95 +10474,24 @@
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
|
@ -8,9 +8,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rokucommunity/bslint": "0.7.5",
|
||||
"brighterscript": "0.57.0",
|
||||
"brighterscript": "0.57.2",
|
||||
"rooibos-cli": "1.4.0",
|
||||
"ropm": "0.10.9"
|
||||
"ropm": "0.10.10"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "npx ropm copy",
|
||||
@ -36,7 +36,7 @@
|
||||
"homepage": "https://github.com/jellyfin/jellyfin-roku#readme",
|
||||
"dependencies": {
|
||||
"api": "npm:jellyfin-api-bs-client@^1.0.5",
|
||||
"bgv": "npm:button-group-vert@^1.0.1",
|
||||
"bgv": "npm:button-group-vert@^1.0.2",
|
||||
"brighterscript-formatter": "^1.6.8",
|
||||
"sob": "npm:slide-out-button@^1.0.1",
|
||||
"intKeyboard": "npm:integer-keyboard@^1.0.12"
|
||||
|
@ -9,7 +9,6 @@ sub Main (args as dynamic) as void
|
||||
|
||||
' Set global constants
|
||||
setConstants()
|
||||
|
||||
' Write screen tracker for screensaver
|
||||
WriteAsciiFile("tmp:/scene.temp", "")
|
||||
MoveFile("tmp:/scene.temp", "tmp:/scene")
|
||||
@ -160,6 +159,9 @@ sub Main (args as dynamic) as void
|
||||
' Nothing to do here, handled in ItemGrid
|
||||
else if selectedItem.type = "MusicArtist"
|
||||
group = CreateArtistView(selectedItem.json)
|
||||
if not isValid(group)
|
||||
message_dialog(tr("Unable to find any albums or songs belonging to this artist"))
|
||||
end if
|
||||
else if selectedItem.type = "MusicAlbum"
|
||||
group = CreateAlbumView(selectedItem.json)
|
||||
else if selectedItem.type = "Audio"
|
||||
@ -189,6 +191,12 @@ sub Main (args as dynamic) as void
|
||||
albums = msg.getRoSGNode()
|
||||
node = albums.musicArtistAlbumData.items[ptr]
|
||||
group = CreateAlbumView(node)
|
||||
else if isNodeEvent(msg, "appearsOnSelected")
|
||||
' If you select a Music Album from ANYWHERE, follow this flow
|
||||
ptr = msg.getData()
|
||||
albums = msg.getRoSGNode()
|
||||
node = albums.musicArtistAppearsOnData.items[ptr]
|
||||
group = CreateAlbumView(node)
|
||||
else if isNodeEvent(msg, "playSong")
|
||||
' User has selected audio they want us to play
|
||||
selectedIndex = msg.getData()
|
||||
@ -212,11 +220,23 @@ sub Main (args as dynamic) as void
|
||||
if isValid(m.spinner)
|
||||
m.spinner.visible = true
|
||||
end if
|
||||
|
||||
group = invalid
|
||||
|
||||
' Create instant mix based on selected album
|
||||
if isValid(screenContent.albumData)
|
||||
group = CreateInstantMixGroup(screenContent.albumData.items)
|
||||
else if isValid(screenContent.pageContent)
|
||||
group = CreateInstantMixGroup([{ id: screenContent.musicArtistAlbumData.items[0].json.id }])
|
||||
if isValid(screenContent.albumData.items)
|
||||
if screenContent.albumData.items.count() > 0
|
||||
group = CreateInstantMixGroup(screenContent.albumData.items)
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
|
||||
' Create instant mix based on selected artist
|
||||
if not isValid(group)
|
||||
group = CreateInstantMixGroup([{ id: screenContent.pageContent.id }])
|
||||
end if
|
||||
|
||||
else if isNodeEvent(msg, "episodeSelected")
|
||||
' If you select a TV Episode from ANYWHERE, follow this flow
|
||||
node = getMsgPicker(msg, "picker")
|
||||
@ -386,9 +406,19 @@ sub Main (args as dynamic) as void
|
||||
changeSubtitleDuringPlayback(trackSelected)
|
||||
end if
|
||||
end if
|
||||
else if isNodeEvent(msg, "selectPlaybackInfoPressed")
|
||||
node = m.scene.focusedChild
|
||||
if node.focusedChild <> invalid and node.focusedChild.isSubType("JFVideo")
|
||||
info = GetPlaybackInfo()
|
||||
show_dialog(tr("Playback Information"), info)
|
||||
end if
|
||||
else if isNodeEvent(msg, "state")
|
||||
node = msg.getRoSGNode()
|
||||
if node.state = "finished"
|
||||
if selectedItem.Type = "TvChannel" and node.state = "finished"
|
||||
video = CreateVideoPlayerGroup(node.id)
|
||||
m.global.sceneManager.callFunc("pushScene", video)
|
||||
m.global.sceneManager.callFunc("clearPreviousScene")
|
||||
else if node.state = "finished"
|
||||
node.control = "stop"
|
||||
|
||||
' If node allows retrying using Transcode Url, give that shot
|
||||
|
@ -377,13 +377,26 @@ end function
|
||||
' Shows details on selected artist. Bio, image, and list of available albums
|
||||
function CreateArtistView(musicartist)
|
||||
musicData = MusicAlbumList(musicartist.id)
|
||||
appearsOnData = AppearsOnList(musicartist.id)
|
||||
|
||||
' User only has songs under artists
|
||||
if musicData = invalid or musicData.Items.Count() = 0
|
||||
if (musicData = invalid or musicData.Items.Count() = 0) and (appearsOnData = invalid or appearsOnData.Items.Count() = 0)
|
||||
' Just songs under artists...
|
||||
group = CreateObject("roSGNode", "AlbumView")
|
||||
group.pageContent = ItemMetaData(musicartist.id)
|
||||
group.albumData = MusicSongList(musicartist.id)
|
||||
|
||||
' Lookup songs based on artist id
|
||||
songList = GetSongsByArtist(musicartist.id)
|
||||
|
||||
if not isValid(songList)
|
||||
' Lookup songs based on folder parent / child relationship
|
||||
songList = MusicSongList(musicartist.id)
|
||||
end if
|
||||
|
||||
if not isValid(songList)
|
||||
return invalid
|
||||
end if
|
||||
|
||||
group.albumData = songList
|
||||
group.observeField("playSong", m.port)
|
||||
group.observeField("playAllSelected", m.port)
|
||||
group.observeField("instantMixSelected", m.port)
|
||||
@ -392,9 +405,13 @@ function CreateArtistView(musicartist)
|
||||
group = CreateObject("roSGNode", "ArtistView")
|
||||
group.pageContent = ItemMetaData(musicartist.id)
|
||||
group.musicArtistAlbumData = musicData
|
||||
group.musicArtistAppearsOnData = appearsOnData
|
||||
group.artistOverview = ArtistOverview(musicartist.name)
|
||||
|
||||
group.observeField("musicAlbumSelected", m.port)
|
||||
group.observeField("playArtistSelected", m.port)
|
||||
group.observeField("instantMixSelected", m.port)
|
||||
group.observeField("appearsOnSelected", m.port)
|
||||
end if
|
||||
|
||||
m.global.sceneManager.callFunc("pushScene", group)
|
||||
@ -467,6 +484,7 @@ function CreateVideoPlayerGroup(video_id, mediaSourceId = invalid, audio_stream_
|
||||
if video = invalid then return invalid
|
||||
if video.errorMsg = "introaborted" then return video
|
||||
video.observeField("selectSubtitlePressed", m.port)
|
||||
video.observeField("selectPlaybackInfoPressed", m.port)
|
||||
video.observeField("state", m.port)
|
||||
|
||||
return video
|
||||
@ -530,8 +548,6 @@ function CreateArtistMixGroup(artistID)
|
||||
songIDArray.push(song.id)
|
||||
end for
|
||||
|
||||
songIDArray.shift()
|
||||
|
||||
group.pageContent = songIDArray
|
||||
group.musicArtistAlbumData = songList.items
|
||||
|
||||
|
@ -45,13 +45,6 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
|
||||
end if
|
||||
end if
|
||||
|
||||
if m.videotype = "Episode" or m.videotype = "Series"
|
||||
video.skipIntroParams = api_API().introskipper.get(video.id)
|
||||
'print (meta.json.RunTimeTicks / 10000000) / 60
|
||||
video.runTime = (meta.json.RunTimeTicks / 10000000.0)
|
||||
video.content.contenttype = "episode"
|
||||
end if
|
||||
|
||||
video.content.title = meta.title
|
||||
video.showID = meta.showID
|
||||
|
||||
@ -177,18 +170,18 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
|
||||
end if
|
||||
if meta.live then mediaSourceId = "" ' Don't send mediaSourceId for Live media
|
||||
|
||||
playbackInfo = ItemPostPlaybackInfo(video.id, mediaSourceId, audio_stream_idx, subtitle_idx, playbackPosition)
|
||||
m.playbackInfo = ItemPostPlaybackInfo(video.id, mediaSourceId, audio_stream_idx, subtitle_idx, playbackPosition)
|
||||
video.videoId = video.id
|
||||
video.mediaSourceId = mediaSourceId
|
||||
video.audioIndex = audio_stream_idx
|
||||
|
||||
if playbackInfo = invalid
|
||||
if m.playbackInfo = invalid
|
||||
video.content = invalid
|
||||
return
|
||||
end if
|
||||
|
||||
params = {}
|
||||
video.PlaySessionId = playbackInfo.PlaySessionId
|
||||
video.PlaySessionId = m.playbackInfo.PlaySessionId
|
||||
|
||||
if meta.live
|
||||
video.content.live = true
|
||||
@ -197,17 +190,17 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
|
||||
|
||||
video.container = getContainerType(meta)
|
||||
|
||||
if playbackInfo.MediaSources[0] = invalid
|
||||
playbackInfo = meta.json
|
||||
if m.playbackInfo.MediaSources[0] = invalid
|
||||
m.playbackInfo = meta.json
|
||||
end if
|
||||
|
||||
subtitles = sortSubtitles(meta.id, playbackInfo.MediaSources[0].MediaStreams)
|
||||
subtitles = sortSubtitles(meta.id, m.playbackInfo.MediaSources[0].MediaStreams)
|
||||
video.Subtitles = subtitles["all"]
|
||||
|
||||
if meta.live
|
||||
video.transcodeParams = {
|
||||
"MediaSourceId": playbackInfo.MediaSources[0].Id,
|
||||
"LiveStreamId": playbackInfo.MediaSources[0].LiveStreamId,
|
||||
"MediaSourceId": m.playbackInfo.MediaSources[0].Id,
|
||||
"LiveStreamId": m.playbackInfo.MediaSources[0].LiveStreamId,
|
||||
"PlaySessionId": video.PlaySessionId
|
||||
}
|
||||
end if
|
||||
@ -216,7 +209,7 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
|
||||
|
||||
' 'TODO: allow user selection of subtitle track before playback initiated, for now set to no subtitles
|
||||
|
||||
video.directPlaySupported = playbackInfo.MediaSources[0].SupportsDirectPlay
|
||||
video.directPlaySupported = m.playbackInfo.MediaSources[0].SupportsDirectPlay
|
||||
fully_external = false
|
||||
|
||||
|
||||
@ -225,8 +218,8 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
|
||||
' artifacts. If the user preference is set, and the only reason the server says we need to
|
||||
' transcode is that the Envoding Level is not supported, then try to direct play but silently
|
||||
' fall back to the transcode if that fails.
|
||||
if meta.live = false and get_user_setting("playback.tryDirect.h264ProfileLevel") = "true" and playbackInfo.MediaSources[0].TranscodingUrl <> invalid and forceTranscoding = false and playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
|
||||
transcodingReasons = getTranscodeReasons(playbackInfo.MediaSources[0].TranscodingUrl)
|
||||
if meta.live = false and get_user_setting("playback.tryDirect.h264ProfileLevel") = "true" and m.playbackInfo.MediaSources[0].TranscodingUrl <> invalid and forceTranscoding = false and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
|
||||
transcodingReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
|
||||
if transcodingReasons.Count() = 1 and transcodingReasons[0] = "VideoLevelNotSupported"
|
||||
video.directPlaySupported = true
|
||||
video.transcodeAvailable = true
|
||||
@ -234,10 +227,10 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
|
||||
end if
|
||||
|
||||
if video.directPlaySupported
|
||||
protocol = LCase(playbackInfo.MediaSources[0].Protocol)
|
||||
protocol = LCase(m.playbackInfo.MediaSources[0].Protocol)
|
||||
if protocol <> "file"
|
||||
uriRegex = CreateObject("roRegex", "^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$", "")
|
||||
uri = uriRegex.Match(playbackInfo.MediaSources[0].Path)
|
||||
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
|
||||
@ -248,7 +241,7 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
|
||||
video.content.url = buildURL(uri[4])
|
||||
else
|
||||
fully_external = true
|
||||
video.content.url = playbackInfo.MediaSources[0].Path
|
||||
video.content.url = m.playbackInfo.MediaSources[0].Path
|
||||
end if
|
||||
else:
|
||||
params.append({
|
||||
@ -265,15 +258,15 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
|
||||
end if
|
||||
video.isTranscoded = false
|
||||
else
|
||||
if playbackInfo.MediaSources[0].TranscodingUrl = invalid
|
||||
if m.playbackInfo.MediaSources[0].TranscodingUrl = invalid
|
||||
' If server does not provide a transcode URL, display a message to the user
|
||||
m.global.sceneManager.callFunc("userMessage", tr("Error Getting Playback Information"), tr("An error was encountered while playing this item. Server did not provide required transcoding data."))
|
||||
video.content = invalid
|
||||
return
|
||||
end if
|
||||
' Get transcoding reason
|
||||
video.transcodeReasons = getTranscodeReasons(playbackInfo.MediaSources[0].TranscodingUrl)
|
||||
video.content.url = buildURL(playbackInfo.MediaSources[0].TranscodingUrl)
|
||||
video.transcodeReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
|
||||
video.content.url = buildURL(m.playbackInfo.MediaSources[0].TranscodingUrl)
|
||||
video.isTranscoded = true
|
||||
end if
|
||||
|
||||
@ -284,10 +277,6 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
|
||||
' is enabled/will be enabled, indexed on the provided list of subtitles
|
||||
video.SelectedSubtitle = setupSubtitle(video, video.Subtitles, subtitle_idx)
|
||||
|
||||
video.content.SDBifUrl = api_API().jellyscrub.get(video.id)
|
||||
video.content.HDBifUrl = api_API().jellyscrub.get(video.id)
|
||||
video.content.FHDBifUrl = api_API().jellyscrub.get(video.id)
|
||||
|
||||
if not fully_external
|
||||
video.content = authorize_request(video.content)
|
||||
end if
|
||||
@ -346,9 +335,9 @@ function getTranscodeReasons(url as string) as object
|
||||
return []
|
||||
end function
|
||||
|
||||
'Opens dialog asking user if they want to resume video or start playback over
|
||||
'Opens dialog asking user if they want to resume video or start playback over only on the home screen
|
||||
function startPlayBackOver(time as longinteger) as integer
|
||||
if m.videotype = "Episode" or m.videotype = "Series"
|
||||
if m.scene.focusedChild.focusedChild.overhangTitle = tr("Home") and (m.videotype = "Episode" or m.videotype = "Series")
|
||||
return option_dialog([tr("Resume playing at ") + ticksToHuman(time) + ".", tr("Start over from the beginning."), tr("Watched"), tr("Go to series"), tr("Go to season"), tr("Go to episode")])
|
||||
else
|
||||
return option_dialog(["Resume playing at " + ticksToHuman(time) + ".", "Start over from the beginning."])
|
||||
@ -432,6 +421,7 @@ sub autoPlayNextEpisode(videoID as string, showID as string)
|
||||
' 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
|
||||
m.global.sceneManager.callFunc("pushScene", nextVideo)
|
||||
@ -446,3 +436,135 @@ sub autoPlayNextEpisode(videoID as string, showID as string)
|
||||
m.global.sceneManager.callFunc("popScene")
|
||||
end if
|
||||
end sub
|
||||
|
||||
' Returns an array of playback info to be displayed during playback.
|
||||
' 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
|
||||
return GetTranscodingStats(sessions[0])
|
||||
end if
|
||||
|
||||
errMsg = tr("Unable to get playback information")
|
||||
return [errMsg]
|
||||
end function
|
||||
|
||||
function GetTranscodingStats(session)
|
||||
sessionStats = []
|
||||
|
||||
if isValid(session.TranscodingInfo) and session.TranscodingInfo.Count() > 0
|
||||
transcodingReasons = session.TranscodingInfo.TranscodeReasons
|
||||
videoCodec = session.TranscodingInfo.VideoCodec
|
||||
audioCodec = session.TranscodingInfo.AudioCodec
|
||||
totalBitrate = session.TranscodingInfo.Bitrate
|
||||
audioChannels = session.TranscodingInfo.AudioChannels
|
||||
|
||||
if isValid(transcodingReasons) and transcodingReasons.Count() > 0
|
||||
sessionStats.push("** " + tr("Transcoding Information") + " **")
|
||||
for each item in transcodingReasons
|
||||
sessionStats.push(tr("Reason") + ": " + item)
|
||||
end for
|
||||
end if
|
||||
|
||||
if isValid(videoCodec)
|
||||
data = tr("Video Codec") + ": " + videoCodec
|
||||
if session.TranscodingInfo.IsVideoDirect
|
||||
data = data + " (" + tr("direct") + ")"
|
||||
end if
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
|
||||
if isValid(audioCodec)
|
||||
data = tr("Audio Codec") + ": " + audioCodec
|
||||
if session.TranscodingInfo.IsAudioDirect
|
||||
data = data + " (" + tr("direct") + ")"
|
||||
end if
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
|
||||
if isValid(totalBitrate)
|
||||
data = tr("Total Bitrate") + ": " + getDisplayBitrate(totalBitrate)
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
|
||||
if isValid(audioChannels)
|
||||
data = tr("Audio Channels") + ": " + Str(audioChannels)
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
end if
|
||||
|
||||
if havePlaybackInfo()
|
||||
stream = m.playbackInfo.mediaSources[0].MediaStreams[0]
|
||||
sessionStats.push("** " + tr("Stream Information") + " **")
|
||||
if isValid(stream.Container)
|
||||
data = tr("Container") + ": " + stream.Container
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
if isValid(stream.Size)
|
||||
data = tr("Size") + ": " + stream.Size
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
if isValid(stream.BitRate)
|
||||
data = tr("Bit Rate") + ": " + getDisplayBitrate(stream.BitRate)
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
if isValid(stream.Codec)
|
||||
data = tr("Codec") + ": " + stream.Codec
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
if isValid(stream.CodecTag)
|
||||
data = tr("Codec Tag") + ": " + stream.CodecTag
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
if isValid(stream.VideoRangeType)
|
||||
data = tr("Video range type") + ": " + stream.VideoRangeType
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
if isValid(stream.PixelFormat)
|
||||
data = tr("Pixel format") + ": " + stream.PixelFormat
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
if isValid(stream.Width) and isValid(stream.Height)
|
||||
data = tr("WxH") + ": " + Str(stream.Width) + " x " + Str(stream.Height)
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
if isValid(stream.Level)
|
||||
data = tr("Level") + ": " + Str(stream.Level)
|
||||
sessionStats.push(data)
|
||||
end if
|
||||
end if
|
||||
|
||||
return sessionStats
|
||||
end function
|
||||
|
||||
function havePlaybackInfo()
|
||||
if not isValid(m.playbackInfo)
|
||||
return false
|
||||
end if
|
||||
|
||||
if not isValid(m.playbackInfo.mediaSources)
|
||||
return false
|
||||
end if
|
||||
|
||||
if m.playbackInfo.mediaSources.Count() <= 0
|
||||
return false
|
||||
end if
|
||||
|
||||
if not isValid(m.playbackInfo.mediaSources[0].MediaStreams)
|
||||
return false
|
||||
end if
|
||||
|
||||
if m.playbackInfo.mediaSources[0].MediaStreams.Count() <= 0
|
||||
return false
|
||||
end if
|
||||
|
||||
return true
|
||||
end function
|
||||
|
||||
function getDisplayBitrate(bitrate)
|
||||
if bitrate > 1000000
|
||||
return Str(Fix(bitrate / 1000000)) + " Mbps"
|
||||
else
|
||||
return Str(Fix(bitrate / 1000)) + " Kbps"
|
||||
end if
|
||||
end function
|
||||
|
@ -78,12 +78,12 @@ function ItemMetaData(id as string)
|
||||
if data = invalid then return invalid
|
||||
imgParams = {}
|
||||
if data.type <> "Audio"
|
||||
if data.UserData.PlayedPercentage <> invalid
|
||||
if data?.UserData?.PlayedPercentage <> invalid
|
||||
param = { "PercentPlayed": data.UserData.PlayedPercentage }
|
||||
imgParams.Append(param)
|
||||
end if
|
||||
end if
|
||||
if data.type = "Movie"
|
||||
if data.type = "Movie" or data.type = "MusicVideo"
|
||||
tmp = CreateObject("roSGNode", "MovieData")
|
||||
tmp.image = PosterImage(data.id, imgParams)
|
||||
tmp.json = data
|
||||
@ -163,21 +163,82 @@ function ItemMetaData(id as string)
|
||||
end if
|
||||
end function
|
||||
|
||||
' Music Artist Data
|
||||
function ArtistOverview(name as string)
|
||||
req = createObject("roUrlTransfer")
|
||||
url = Substitute("Artists/{0}", req.escape(name))
|
||||
resp = APIRequest(url)
|
||||
data = getJson(resp)
|
||||
if data = invalid then return invalid
|
||||
return data.overview
|
||||
end function
|
||||
|
||||
' Get list of albums belonging to an artist
|
||||
function MusicAlbumList(id as string)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
resp = APIRequest(url, {
|
||||
"UserId": get_setting("active_user"),
|
||||
"parentId": id,
|
||||
"AlbumArtistIds": id,
|
||||
"includeitemtypes": "MusicAlbum",
|
||||
"sortBy": "SortName"
|
||||
"sortBy": "SortName",
|
||||
"Recursive": true
|
||||
})
|
||||
|
||||
data = getJson(resp)
|
||||
results = []
|
||||
for each item in data.Items
|
||||
tmp = CreateObject("roSGNode", "MusicAlbumData")
|
||||
tmp.image = PosterImage(item.id, { "maxHeight": "500", "maxWidth": "500" })
|
||||
tmp.image = PosterImage(item.id)
|
||||
tmp.json = item
|
||||
results.push(tmp)
|
||||
end for
|
||||
data.Items = results
|
||||
return data
|
||||
end function
|
||||
|
||||
' Get list of albums an artist appears on
|
||||
function AppearsOnList(id as string)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
resp = APIRequest(url, {
|
||||
"ContributingArtistIds": id,
|
||||
"ExcludeItemIds": id,
|
||||
"includeitemtypes": "MusicAlbum",
|
||||
"sortBy": "PremiereDate,ProductionYear,SortName",
|
||||
"SortOrder": "Descending",
|
||||
"Recursive": true
|
||||
})
|
||||
|
||||
data = getJson(resp)
|
||||
results = []
|
||||
for each item in data.Items
|
||||
tmp = CreateObject("roSGNode", "MusicAlbumData")
|
||||
tmp.image = PosterImage(item.id)
|
||||
tmp.json = item
|
||||
results.push(tmp)
|
||||
end for
|
||||
data.Items = results
|
||||
return data
|
||||
end function
|
||||
|
||||
' Get list of songs belonging to an artist
|
||||
function GetSongsByArtist(id as string)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
resp = APIRequest(url, {
|
||||
"AlbumArtistIds": id,
|
||||
"includeitemtypes": "Audio",
|
||||
"sortBy": "SortName",
|
||||
"Recursive": true
|
||||
})
|
||||
|
||||
data = getJson(resp)
|
||||
results = []
|
||||
|
||||
if data = invalid then return invalid
|
||||
if data.Items = invalid then return invalid
|
||||
if data.Items.Count() = 0 then return invalid
|
||||
|
||||
for each item in data.Items
|
||||
tmp = CreateObject("roSGNode", "MusicAlbumData")
|
||||
tmp.image = PosterImage(item.id)
|
||||
tmp.json = item
|
||||
results.push(tmp)
|
||||
end for
|
||||
@ -195,8 +256,13 @@ function MusicSongList(id as string)
|
||||
"sortBy": "SortName"
|
||||
})
|
||||
|
||||
data = getJson(resp)
|
||||
results = []
|
||||
data = getJson(resp)
|
||||
|
||||
if data = invalid then return invalid
|
||||
if data.Items = invalid then return invalid
|
||||
if data.Items.Count() = 0 then return invalid
|
||||
|
||||
for each item in data.Items
|
||||
tmp = CreateObject("roSGNode", "MusicSongData")
|
||||
tmp.image = PosterImage(item.id)
|
||||
@ -232,15 +298,18 @@ end function
|
||||
|
||||
' Get Instant Mix based on item
|
||||
function CreateArtistMix(id as string)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
resp = APIRequest(url, {
|
||||
"UserId": get_setting("active_user"),
|
||||
"parentId": id,
|
||||
"Filters": "IsNotFolder",
|
||||
"Recursive": true,
|
||||
"SortBy": "SortName",
|
||||
"ArtistIds": id,
|
||||
"Recursive": "true",
|
||||
"MediaTypes": "Audio",
|
||||
"Limit": 300
|
||||
"Filters": "IsNotFolder",
|
||||
"SortBy": "SortName",
|
||||
"Limit": 300,
|
||||
"Fields": "Chapters",
|
||||
"ExcludeLocationTypes": "Virtual",
|
||||
"EnableTotalRecordCount": false,
|
||||
"CollapseBoxSetItems": false
|
||||
})
|
||||
|
||||
return getJson(resp)
|
||||
|
@ -177,7 +177,7 @@ end function
|
||||
|
||||
function GetDirectPlayProfiles() as object
|
||||
|
||||
mp4Video = "h264"
|
||||
mp4Video = "h264,mpeg4"
|
||||
mp4Audio = "mp3,pcm,lpcm,wav"
|
||||
mkvVideo = "h264,vp8"
|
||||
mkvAudio = "mp3,pcm,lpcm,wav"
|
||||
|
Loading…
Reference in New Issue
Block a user