diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b44dda46..d53a8e72 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -6,16 +6,16 @@ on:
- 'locale/**'
jobs:
run:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3
- - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3
+ - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
+ - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
- node-version: "14.12.0"
+ node-version: "18.13.0"
- run: npm ci
- run: npx ropm install
- run: make dev
- - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3
+ - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3
with:
name: Jellyfin-Roku-dev-${{ github.sha }}
path: ${{ github.workspace }}/out/staging
diff --git a/.github/workflows/master-release.yml b/.github/workflows/master-release.yml
index 563c002e..3c9337fc 100644
--- a/.github/workflows/master-release.yml
+++ b/.github/workflows/master-release.yml
@@ -6,12 +6,12 @@ on:
jobs:
test-build-release:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
- node-version: "14.12.0"
+ node-version: "18.13.0"
- run: npm ci
- run: npx ropm install
- run: npm run validate
@@ -22,7 +22,7 @@ jobs:
run: awk 'BEGIN { FS="=" } /^minor_version/ { print "MINOR="$2; }' manifest >> $GITHUB_ENV
- name: "Find and save build_version from manifest"
run: awk 'BEGIN { FS="=" } /^build_version/ { print "BUILD="$2; }' manifest >> $GITHUB_ENV
- - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3
+ - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- uses: vimtor/action-zip@5f1c4aa587ea41db1110df6a99981dbe19cee310 # tag=v1
with:
recursive: false
@@ -36,7 +36,7 @@ jobs:
prerelease: false
title: v${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.BUILD }}
files: ${{ github.workspace }}/jellyfin_v${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.BUILD }}.zip
- - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3
+ - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3
with:
name: jellyfin_v${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.BUILD }}.zip
path: ${{ github.workspace }}/jellyfin_v${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.BUILD }}.zip
diff --git a/.github/workflows/unstable-release.yml b/.github/workflows/unstable-release.yml
index c038600a..a911782e 100644
--- a/.github/workflows/unstable-release.yml
+++ b/.github/workflows/unstable-release.yml
@@ -6,12 +6,12 @@ on:
jobs:
test-build-release:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
- node-version: "14.12.0"
+ node-version: "18.13.0"
- run: npm ci
- run: npx ropm install
- run: npm run validate
@@ -22,7 +22,7 @@ jobs:
run: awk 'BEGIN { FS="=" } /^minor_version/ { print "MINOR="$2; }' manifest >> $GITHUB_ENV
- name: "Find and save build_version from manifest"
run: awk 'BEGIN { FS="=" } /^build_version/ { print "BUILD="$2; }' manifest >> $GITHUB_ENV
- - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3
+ - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- uses: vimtor/action-zip@5f1c4aa587ea41db1110df6a99981dbe19cee310 # tag=v1
with:
recursive: false
@@ -35,7 +35,7 @@ jobs:
prerelease: true
title: v${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.BUILD }}
files: ${{ github.workspace }}/jellyfin_v${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.BUILD }}.zip
- - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3
+ - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3
with:
name: jellyfin_v${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.BUILD }}.zip
path: ${{ github.workspace }}/jellyfin_v${{ env.MAJOR }}.${{ env.MINOR }}.${{ env.BUILD }}.zip
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index 51d0210b..9ca7ff82 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -3,12 +3,12 @@ on: [push, pull_request]
jobs:
run:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
with:
- node-version: "14.12.0"
+ node-version: "18.13.0"
- run: npm ci
- run: npx ropm install
- run: npm run validate
diff --git a/components/ItemGrid/GridItem.brs b/components/ItemGrid/GridItem.brs
index ba02bb6c..162db0b9 100644
--- a/components/ItemGrid/GridItem.brs
+++ b/components/ItemGrid/GridItem.brs
@@ -8,6 +8,9 @@ sub init()
m.itemPoster.observeField("loadStatus", "onPosterLoadStatusChanged")
+ m.unplayedCount = m.top.findNode("unplayedCount")
+ m.unplayedEpisodeCount = m.top.findNode("unplayedEpisodeCount")
+
m.itemText.translation = [0, m.itemPoster.height + 7]
m.alwaysShowTitles = get_user_setting("itemgrid.alwaysShowTitles") = "true"
@@ -40,6 +43,13 @@ sub itemContentChanged()
m.itemIcon.uri = itemData.iconUrl
m.itemText.text = itemData.Title
else if itemData.type = "Series"
+ if itemData?.json?.UserData?.UnplayedItemCount <> invalid
+ if itemData.json.UserData.UnplayedItemCount > 0
+ m.unplayedCount.visible = true
+ m.unplayedEpisodeCount.text = itemData.json.UserData.UnplayedItemCount
+ end if
+ end if
+
m.itemPoster.uri = itemData.PosterUrl
m.itemIcon.uri = itemData.iconUrl
m.itemText.text = itemData.Title
diff --git a/components/ItemGrid/GridItem.xml b/components/ItemGrid/GridItem.xml
index c9c419e0..4b8b27ea 100644
--- a/components/ItemGrid/GridItem.xml
+++ b/components/ItemGrid/GridItem.xml
@@ -1,9 +1,13 @@
-
+
-
+
+
+
+
+
diff --git a/components/ItemGrid/GridItemSmall.brs b/components/ItemGrid/GridItemSmall.brs
index 776e496f..24b21bdc 100644
--- a/components/ItemGrid/GridItemSmall.brs
+++ b/components/ItemGrid/GridItemSmall.brs
@@ -1,7 +1,9 @@
sub init()
m.itemPoster = m.top.findNode("itemPoster")
m.posterText = m.top.findNode("posterText")
+ m.title = m.top.findNode("title")
m.posterText.font.size = 30
+ m.title.font.size = 25
m.backdrop = m.top.findNode("backdrop")
m.itemPoster.observeField("loadStatus", "onPosterLoadStatusChanged")
@@ -9,22 +11,32 @@ sub init()
'Parent is MarkupGrid and it's parent is the ItemGrid
m.topParent = m.top.GetParent().GetParent()
+ m.title.visible = false
+
'Get the imageDisplayMode for these grid items
if m.topParent.imageDisplayMode <> invalid
m.itemPoster.loadDisplayMode = m.topParent.imageDisplayMode
end if
-
end sub
sub itemContentChanged()
m.backdrop.blendColor = "#101010"
+ m.title.visible = false
+
+ if isValid(m.topParent.showItemTitles)
+ if LCase(m.topParent.showItemTitles) = "showalways"
+ m.title.visible = true
+ end if
+ end if
+
itemData = m.top.itemContent
if not isValid(itemData) then return
m.itemPoster.uri = itemData.PosterUrl
m.posterText.text = itemData.title
+ m.title.text = itemData.title
'If Poster not loaded, ensure "blue box" is shown until loaded
if m.itemPoster.loadStatus <> "ready"
@@ -33,6 +45,20 @@ sub itemContentChanged()
end if
end sub
+sub focusChanged()
+ if m.top.itemHasFocus = true
+ m.title.repeatCount = -1
+ else
+ m.title.repeatCount = 0
+ end if
+
+ if isValid(m.topParent.showItemTitles)
+ if LCase(m.topParent.showItemTitles) = "showonhover"
+ m.title.visible = m.top.itemHasFocus
+ end if
+ end if
+end sub
+
'Hide backdrop and text when poster loaded
sub onPosterLoadStatusChanged()
if m.itemPoster.loadStatus = "ready"
diff --git a/components/ItemGrid/GridItemSmall.xml b/components/ItemGrid/GridItemSmall.xml
index 6e2f9b1d..87423da4 100644
--- a/components/ItemGrid/GridItemSmall.xml
+++ b/components/ItemGrid/GridItemSmall.xml
@@ -3,12 +3,13 @@
+
-
+
diff --git a/components/ItemGrid/ItemGrid.brs b/components/ItemGrid/ItemGrid.brs
index 38e9aea0..7f902434 100644
--- a/components/ItemGrid/ItemGrid.brs
+++ b/components/ItemGrid/ItemGrid.brs
@@ -12,6 +12,11 @@ sub init()
m.newBackdrop = m.top.findNode("backdropTransition")
m.emptyText = m.top.findNode("emptyText")
+ m.genreList = m.top.findNode("genrelist")
+ m.genreList.observeField("itemSelected", "onGenreItemSelected")
+ m.genreData = CreateObject("roSGNode", "ContentNode")
+ m.genreList.content = m.genreData
+
m.swapAnimation = m.top.findNode("backroundSwapAnimation")
m.swapAnimation.observeField("state", "swapDone")
@@ -74,6 +79,12 @@ sub init()
end if
end sub
+'
+'Genre Item Selected
+sub onGenreItemSelected()
+ m.top.selectedItem = m.genreList.content.getChild(m.genreList.rowItemSelected[0]).getChild(m.genreList.rowItemSelected[1])
+end sub
+
'
'Load initial set of Data
sub loadInitialItems()
@@ -241,7 +252,10 @@ sub setMoviesOptions(options)
]
options.filter = [
{ "Title": tr("All"), "Name": "All" },
- { "Title": tr("Favorites"), "Name": "Favorites" }
+ { "Title": tr("Favorites"), "Name": "Favorites" },
+ { "Title": tr("Played"), "Name": "Played" },
+ { "Title": tr("Unplayed"), "Name": "Unplayed" },
+ { "Title": tr("Resumable"), "Name": "Resumable" }
]
end sub
@@ -256,7 +270,9 @@ sub setBoxsetsOptions(options)
]
options.filter = [
{ "Title": tr("All"), "Name": "All" },
- { "Title": tr("Favorites"), "Name": "Favorites" }
+ { "Title": tr("Favorites"), "Name": "Favorites" },
+ { "Title": tr("Played"), "Name": "Played" },
+ { "Title": tr("Unplayed"), "Name": "Unplayed" }
]
end sub
@@ -278,8 +294,18 @@ sub setTvShowsOptions(options)
]
options.filter = [
{ "Title": tr("All"), "Name": "All" },
- { "Title": tr("Favorites"), "Name": "Favorites" }
+ { "Title": tr("Favorites"), "Name": "Favorites" },
+ { "Title": tr("Played"), "Name": "Played" },
+ { "Title": tr("Unplayed"), "Name": "Unplayed" }
]
+
+ if isValid(m.view)
+ if LCase(m.options.view) = "genres" or LCase(m.view) = "genres"
+ options.sort = [{ "Title": tr("TITLE"), "Name": "SortName" }]
+ options.filter = []
+ end if
+ end if
+
end sub
' Set Live TV view, sort, and filter options
@@ -423,10 +449,32 @@ sub ItemDataLoaded(msg)
return
end if
+ if m.loadItemsTask.view = "Genres"
+ ' Reset genre list data
+ m.genreData.removeChildren(m.genreData.getChildren(-1, 0))
+
+ for each item in itemData
+ m.genreData.appendChild(item)
+ end for
+
+ m.itemGrid.opacity = "0"
+ m.genreList.opacity = "1"
+
+ m.itemGrid.setFocus(false)
+ m.genreList.setFocus(true)
+
+ m.loading = false
+ m.spinner.visible = false
+ return
+ end if
+
for each item in itemData
m.data.appendChild(item)
end for
+ m.itemGrid.opacity = "1"
+ m.genreList.opacity = "0"
+
'Update the stored counts
m.loadedItems = m.itemGrid.content.getChildCount()
m.loadedRows = m.loadedItems / m.itemGrid.numColumns
@@ -438,6 +486,7 @@ sub ItemDataLoaded(msg)
end if
m.itemGrid.setFocus(true)
+ m.genreList.setFocus(false)
m.spinner.visible = false
end sub
@@ -645,7 +694,10 @@ sub optionsClosed()
m.itemGrid.content = m.data
loadInitialItems()
end if
- m.itemGrid.setFocus(true)
+
+ m.itemGrid.setFocus(m.itemGrid.opacity = 1)
+ m.genreList.setFocus(m.genreList.opacity = 1)
+
if m.tvGuide <> invalid
m.tvGuide.lastFocus.setFocus(true)
end if
@@ -681,13 +733,19 @@ end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
- topGrp = m.top.findNode("itemGrid")
+
+ if m.itemGrid.opacity = 1
+ topGrp = m.itemGrid
+ else
+ topGrp = m.genreList
+ end if
searchGrp = m.top.findNode("voiceBox")
if key = "left" and searchGrp.isinFocusChain()
topGrp.setFocus(true)
searchGrp.setFocus(false)
end if
+
if key = "options"
if m.options.visible = true
m.options.visible = false
@@ -773,14 +831,16 @@ function onKeyEvent(key as string, press as boolean) as boolean
end function
sub updateTitle()
- if m.filter = "All"
- m.top.overhangTitle = m.top.parentItem.title
- else if m.filter = "Favorites"
+ m.top.overhangTitle = m.top.parentItem.title
+
+ if m.filter = "Favorites"
m.top.overhangTitle = m.top.parentItem.title + " " + tr("(Favorites)")
end if
+
if m.voiceBox.text <> ""
m.top.overhangTitle = m.top.parentItem.title + tr(" (Filtered by ") + m.loadItemsTask.searchTerm + ")"
end if
+
if m.top.alphaSelected <> ""
m.top.overhangTitle = m.top.parentItem.title + tr(" (Filtered by ") + m.loadItemsTask.nameStartsWith + ")"
end if
@@ -794,14 +854,18 @@ sub updateTitle()
if m.options.view = "Networks" or m.view = "Networks"
m.top.overhangTitle = "%s (%s)".Format(m.top.parentItem.title, tr("Networks"))
end if
+
if m.options.view = "Studios" or m.view = "Studios"
m.top.overhangTitle = "%s (%s)".Format(m.top.parentItem.title, tr("Studios"))
end if
+
if m.options.view = "Genres" or m.view = "Genres"
m.top.overhangTitle = "%s (%s)".Format(m.top.parentItem.title, tr("Genres"))
end if
+
actInt = m.itemGrid.itemFocused + 1
- if m.showItemCount and m.loadItemsTask.totalRecordCount > 0
+
+ if m.showItemCount and m.loadItemsTask.totalRecordCount > 0 and m.options.view <> "Genres" and m.view <> "Genres"
m.top.overhangTitle += " (" + tr("%1 of %2").Replace("%1", actInt.toStr()).Replace("%2", m.loadItemsTask.totalRecordCount.toStr()) + ")"
end if
diff --git a/components/ItemGrid/ItemGrid.xml b/components/ItemGrid/ItemGrid.xml
index ec528c44..9fcd213b 100644
--- a/components/ItemGrid/ItemGrid.xml
+++ b/components/ItemGrid/ItemGrid.xml
@@ -3,18 +3,8 @@
-
-
+
+
-
-
+
+
+
+
+
-
-
-
+
+
+
diff --git a/components/ItemGrid/LoadItemsTask2.brs b/components/ItemGrid/LoadItemsTask2.brs
index 25a6be09..daa3e050 100644
--- a/components/ItemGrid/LoadItemsTask2.brs
+++ b/components/ItemGrid/LoadItemsTask2.brs
@@ -75,6 +75,12 @@ sub loadItems()
else if filter = "favorites"
params.append({ Filters: "IsFavorite" })
params.append({ isFavorite: true })
+ else if filter = "unplayed"
+ params.append({ Filters: "IsUnplayed" })
+ else if filter = "played"
+ params.append({ Filters: "IsPlayed" })
+ else if filter = "resumable"
+ params.append({ Filters: "IsResumable" })
end if
if m.top.ItemType <> ""
@@ -89,13 +95,14 @@ sub loadItems()
params.append({ UserId: get_setting("active_user") })
else if m.top.view = "Genres"
url = "Genres"
- params.append({ UserId: get_setting("active_user") })
+ params.append({ UserId: get_setting("active_user"), includeItemTypes: m.top.itemType })
else if m.top.ItemType = "MusicArtist"
url = "Artists"
params.append({
- UserId: get_setting("active_user")
+ UserId: get_setting("active_user"),
+ Fields: "Genres"
})
- params.IncludeItemTypes = ""
+ params.IncludeItemTypes = "MusicAlbum,Audio"
else if m.top.ItemType = "MusicAlbum"
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
params.append({ ImageTypeLimit: 1 })
@@ -103,6 +110,7 @@ sub loadItems()
else
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
end if
+
resp = APIRequest(url, params)
data = getJson(resp)
if data <> invalid
@@ -121,7 +129,7 @@ sub loadItems()
tmp = CreateObject("roSGNode", "ChannelData")
else if item.Type = "Folder" or item.Type = "ChannelFolderItem" or item.Type = "CollectionFolder"
tmp = CreateObject("roSGNode", "FolderData")
- else if item.Type = "Video"
+ else if item.Type = "Video" or item.Type = "Recording"
tmp = CreateObject("roSGNode", "VideoData")
else if item.Type = "Photo"
tmp = CreateObject("roSGNode", "PhotoData")
@@ -136,7 +144,7 @@ sub loadItems()
genreData = api_API().users.getitemsbyquery(get_setting("active_user"), {
SortBy: "Random",
SortOrder: "Ascending",
- IncludeItemTypes: "Movie",
+ IncludeItemTypes: m.top.itemType,
Recursive: true,
Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo",
ImageTypeLimit: 1,
@@ -151,26 +159,38 @@ sub loadItems()
' Add View All item to the start of the row
row = tmp.createChild("FolderData")
row.parentFolder = m.top.itemId
- genreMovieImage = api_API().items.getimageurl(item.id)
- row.title = item.name
+ row.title = tr("View All") + " " + item.name
+ item.name = tr("View All") + " " + item.name
row.json = item
- row.FHDPOSTERURL = genreMovieImage
- row.HDPOSTERURL = genreMovieImage
- row.SDPOSTERURL = genreMovieImage
row.type = "Folder"
+
+ if LCase(m.top.itemType) = "movie"
+ genreItemImage = api_API().items.getimageurl(item.id)
+ else
+ genreItemImage = invalid
+ row.posterURL = invalid
+ end if
+
+ row.FHDPOSTERURL = genreItemImage
+ row.HDPOSTERURL = genreItemImage
+ row.SDPOSTERURL = genreItemImage
end if
- for each genreMovie in genreData.Items
- row = tmp.createChild("MovieData")
+ for each genreItem in genreData.Items
+ if LCase(m.top.itemType) = "movie"
+ row = tmp.createChild("MovieData")
+ else
+ row = tmp.createChild("SeriesData")
+ end if
- genreMovieImage = api_API().items.getimageurl(genreMovie.id)
- row.title = genreMovie.name
- row.FHDPOSTERURL = genreMovieImage
- row.HDPOSTERURL = genreMovieImage
- row.SDPOSTERURL = genreMovieImage
- row.json = genreMovie
- row.id = genreMovie.id
- row.type = genreMovie.type
+ genreItemImage = api_API().items.getimageurl(genreItem.id)
+ row.title = genreItem.name
+ row.FHDPOSTERURL = genreItemImage
+ row.HDPOSTERURL = genreItemImage
+ row.SDPOSTERURL = genreItemImage
+ row.json = genreItem
+ row.id = genreItem.id
+ row.type = genreItem.type
end for
else if item.Type = "Studio"
@@ -187,12 +207,20 @@ sub loadItems()
tmp = CreateObject("roSGNode", "MusicArtistData")
else if item.Type = "Audio"
tmp = CreateObject("roSGNode", "MusicSongData")
+ else if item.Type = "MusicGenre"
+ tmp = CreateObject("roSGNode", "FolderData")
+ tmp.title = item.name
+ tmp.parentFolder = m.top.itemId
+ tmp.json = item
+ tmp.type = "Folder"
+ tmp.posterUrl = api_API().items.getimageurl(item.id, "primary", 0, { "maxHeight": 280, "maxWidth": 280, "quality": "90" })
+
else
print "[LoadItems] Unknown Type: " item.Type
end if
if tmp <> invalid
- if item.Type <> "Genre"
+ if item.Type <> "Genre" and item.Type <> "MusicGenre"
tmp.parentFolder = m.top.itemId
tmp.json = item
if item.UserData <> invalid and item.UserData.isFavorite <> invalid
diff --git a/components/ItemGrid/MovieLibraryView.brs b/components/ItemGrid/MovieLibraryView.brs
index bf2c831b..ba8326bd 100644
--- a/components/ItemGrid/MovieLibraryView.brs
+++ b/components/ItemGrid/MovieLibraryView.brs
@@ -22,6 +22,7 @@ sub setupNodes()
m.overhang = m.top.getScene().findNode("overhang")
m.genreList = m.top.findNode("genrelist")
m.infoGroup = m.top.findNode("infoGroup")
+ m.star = m.top.findNode("star")
end sub
sub init()
@@ -124,9 +125,14 @@ sub loadInitialItems()
end if
m.sortField = get_user_setting("display." + m.top.parentItem.Id + ".sortField")
- sortAscendingStr = get_user_setting("display." + m.top.parentItem.Id + ".sortAscending")
m.filter = get_user_setting("display." + m.top.parentItem.Id + ".filter")
m.view = get_user_setting("display." + m.top.parentItem.Id + ".landing")
+ sortAscendingStr = get_user_setting("display." + m.top.parentItem.Id + ".sortAscending")
+
+ ' If user has not set a preferred view for this folder, check if they've set a default view
+ if not isValid(m.view)
+ m.view = get_user_setting("itemgrid.movieDefaultView")
+ end if
if not isValid(m.sortField) then m.sortField = "SortName"
if not isValid(m.filter) then m.filter = "All"
@@ -171,9 +177,12 @@ sub loadInitialItems()
m.loadItemsTask.studioIds = ""
m.loadItemsTask.view = "Movies"
m.itemGrid.translation = "[96, 650]"
+ m.itemGrid.itemSize = "[230, 310]"
+ m.itemGrid.rowHeights = "[310]"
m.itemGrid.numRows = "2"
m.selectedMovieOverview.visible = true
m.infoGroup.visible = true
+ m.top.showItemTitles = "hidealways"
if m.options.view = "Studios" or m.view = "Studios"
m.itemGrid.translation = "[96, 60]"
@@ -182,6 +191,19 @@ sub loadInitialItems()
m.top.imageDisplayMode = "scaleToFit"
m.selectedMovieOverview.visible = false
m.infoGroup.visible = false
+ else if LCase(m.options.view) = "moviesgrid" or LCase(m.view) = "moviesgrid"
+ m.itemGrid.translation = "[96, 60]"
+ m.itemGrid.numRows = "3"
+ m.selectedMovieOverview.visible = false
+ m.infoGroup.visible = false
+ m.top.showItemTitles = get_user_setting("itemgrid.movieGridTitles")
+ if LCase(m.top.showItemTitles) = "hidealways"
+ m.itemGrid.itemSize = "[230, 315]"
+ m.itemGrid.rowHeights = "[315]"
+ else
+ m.itemGrid.itemSize = "[230, 350]"
+ m.itemGrid.rowHeights = "[350]"
+ end if
else if m.options.view = "Genres" or m.view = "Genres"
m.loadItemsTask.StudioIds = m.top.parentItem.Id
m.loadItemsTask.view = "Genres"
@@ -201,14 +223,16 @@ end sub
sub setMoviesOptions(options)
options.views = [
- { "Title": tr("Movies"), "Name": "Movies" },
+ { "Title": tr("Movies (Presentation)"), "Name": "Movies" },
+ { "Title": tr("Movies (Grid)"), "Name": "MoviesGrid" },
{ "Title": tr("Studios"), "Name": "Studios" },
{ "Title": tr("Genres"), "Name": "Genres" }
]
if m.top.parentItem.json.type = "Genre"
options.views = [
- { "Title": tr("Movies"), "Name": "Movies" }
+ { "Title": tr("Movies (Presentation)"), "Name": "Movies" },
+ { "Title": tr("Movies (Grid)"), "Name": "MoviesGrid" },
]
end if
@@ -226,11 +250,14 @@ sub setMoviesOptions(options)
options.filter = [
{ "Title": tr("All"), "Name": "All" },
- { "Title": tr("Favorites"), "Name": "Favorites" }
+ { "Title": tr("Favorites"), "Name": "Favorites" },
+ { "Title": tr("Played"), "Name": "Played" },
+ { "Title": tr("Unplayed"), "Name": "Unplayed" },
+ { "Title": tr("Resumable"), "Name": "Resumable" }
]
if m.options.view = "Genres" or m.view = "Genres"
- options.sort = []
+ options.sort = [{ "Title": tr("TITLE"), "Name": "SortName" }]
options.filter = []
end if
@@ -239,6 +266,10 @@ sub setMoviesOptions(options)
{ "Title": tr("TITLE"), "Name": "SortName" },
{ "Title": tr("DATE_ADDED"), "Name": "DateCreated" },
]
+ options.filter = [
+ { "Title": tr("All"), "Name": "All" },
+ { "Title": tr("Favorites"), "Name": "Favorites" }
+ ]
end if
end sub
@@ -340,6 +371,10 @@ sub ItemDataLoaded(msg)
m.loading = false
m.spinner.visible = false
+ ' Return focus to options menu if it was opened while library was loading
+ if m.options.visible
+ m.options.setFocus(true)
+ end if
return
end if
@@ -359,11 +394,33 @@ sub ItemDataLoaded(msg)
m.Loading = false
'If there are no items to display, show message
if m.loadedItems = 0
+ m.selectedMovieOverview.visible = false
+ m.infoGroup.visible = false
+
+ m.movieLogo.visible = false
+ m.movieLogo.uri = ""
+
+ m.selectedMovieName.visible = false
+
+ SetName("")
+ SetOverview("")
+ SetOfficialRating("")
+ SetProductionYear("")
+ setFieldText("runtime", "")
+ setFieldText("communityRating", "")
+ setFieldText("criticRatingLabel", "")
+ m.criticRatingIcon.uri = ""
+ m.star.uri = ""
+
m.emptyText.text = tr("NO_ITEMS").Replace("%1", m.top.parentItem.Type)
m.emptyText.visible = true
end if
m.spinner.visible = false
+ ' Return focus to options menu if it was opened while library was loading
+ if m.options.visible
+ m.options.setFocus(true)
+ end if
end sub
'
@@ -430,12 +487,20 @@ sub onItemFocused()
m.communityRatingGroup.visible = false
m.criticRatingGroup.visible = false
- if m.options.view = "Studios" or m.view = "Studios"
+ if not isValid(m.selectedFavoriteItem)
+ return
+ end if
+
+ if LCase(m.options.view) = "studios" or LCase(m.view) = "studios"
+ return
+ else if LCase(m.options.view) = "moviesgrid" or LCase(m.view) = "moviesgrid"
return
end if
itemData = m.selectedFavoriteItem.json
+ m.star.uri = "pkg:/images/sharp_star_white_18dp.png"
+
if isValid(itemData.communityRating)
setFieldText("communityRating", int(itemData.communityRating * 10) / 10)
m.communityRatingGroup.visible = true
@@ -762,7 +827,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
else
m.itemGrid.jumpToItem = 0
end if
-
+ return true
else if key = "replay" and m.genreList.isinFocusChain()
if m.resetGrid = true
m.genreList.animateToItem = 0
diff --git a/components/ItemGrid/MovieLibraryView.xml b/components/ItemGrid/MovieLibraryView.xml
index 68a3c678..f92892e6 100644
--- a/components/ItemGrid/MovieLibraryView.xml
+++ b/components/ItemGrid/MovieLibraryView.xml
@@ -54,6 +54,7 @@
+
diff --git a/components/ItemGrid/MusicArtistGridItem.brs b/components/ItemGrid/MusicArtistGridItem.brs
new file mode 100644
index 00000000..438d7321
--- /dev/null
+++ b/components/ItemGrid/MusicArtistGridItem.brs
@@ -0,0 +1,48 @@
+sub init()
+ m.itemPoster = m.top.findNode("itemPoster")
+ m.posterText = m.top.findNode("posterText")
+ m.posterText.font.size = 30
+ m.backdrop = m.top.findNode("backdrop")
+
+ m.itemPoster.observeField("loadStatus", "onPosterLoadStatusChanged")
+
+ 'Parent is MarkupGrid and it's parent is the ItemGrid
+ m.topParent = m.top.GetParent().GetParent()
+
+ 'Get the imageDisplayMode for these grid items
+ if m.topParent.imageDisplayMode <> invalid
+ m.itemPoster.loadDisplayMode = m.topParent.imageDisplayMode
+ end if
+
+end sub
+
+sub itemContentChanged()
+ m.backdrop.blendColor = "#101010"
+
+ itemData = m.top.itemContent
+
+ if not isValid(itemData) then return
+
+ if LCase(itemData.type) = "musicalbum"
+ m.backdrop.uri = "pkg:/images/icons/album.png"
+ else if LCase(itemData.type) = "musicartist"
+ m.backdrop.uri = "pkg:/images/missingArtist.png"
+ else if LCase(itemData.json.type) = "musicgenre"
+ m.backdrop.uri = "pkg:/images/icons/musicFolder.png"
+ end if
+
+ m.itemPoster.uri = itemData.PosterUrl
+ m.posterText.text = itemData.title
+
+ 'If Poster not loaded, ensure "blue box" is shown until loaded
+ if m.itemPoster.loadStatus <> "ready"
+ m.backdrop.visible = true
+ end if
+end sub
+
+'Hide backdrop and text when poster loaded
+sub onPosterLoadStatusChanged()
+ if m.itemPoster.loadStatus = "ready"
+ m.backdrop.visible = false
+ end if
+end sub
diff --git a/components/ItemGrid/MusicArtistGridItem.xml b/components/ItemGrid/MusicArtistGridItem.xml
new file mode 100644
index 00000000..5533d515
--- /dev/null
+++ b/components/ItemGrid/MusicArtistGridItem.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ItemGrid/MusicLibraryView.brs b/components/ItemGrid/MusicLibraryView.brs
new file mode 100644
index 00000000..a1f18b66
--- /dev/null
+++ b/components/ItemGrid/MusicLibraryView.brs
@@ -0,0 +1,778 @@
+sub setupNodes()
+ m.options = m.top.findNode("options")
+ m.itemGrid = m.top.findNode("itemGrid")
+ m.voiceBox = m.top.findNode("voiceBox")
+ m.backdrop = m.top.findNode("backdrop")
+ m.newBackdrop = m.top.findNode("backdropTransition")
+ m.emptyText = m.top.findNode("emptyText")
+ m.selectedArtistName = m.top.findNode("selectedArtistName")
+ m.selectedArtistSongCount = m.top.findNode("selectedArtistSongCount")
+ m.selectedArtistAlbumCount = m.top.findNode("selectedArtistAlbumCount")
+ m.selectedArtistGenres = m.top.findNode("selectedArtistGenres")
+ m.artistLogo = m.top.findNode("artistLogo")
+ m.swapAnimation = m.top.findNode("backroundSwapAnimation")
+ m.spinner = m.top.findNode("spinner")
+ m.Alpha = m.top.findNode("AlphaMenu")
+ m.AlphaSelected = m.top.findNode("AlphaSelected")
+ m.micButton = m.top.findNode("micButton")
+ m.micButtonText = m.top.findNode("micButtonText")
+ m.overhang = m.top.getScene().findNode("overhang")
+ m.genreList = m.top.findNode("genrelist")
+end sub
+
+sub init()
+ setupNodes()
+
+ m.overhang.isVisible = false
+
+ m.showItemCount = get_user_setting("itemgrid.showItemCount") = "true"
+
+ m.swapAnimation.observeField("state", "swapDone")
+
+ m.loadedRows = 0
+ m.loadedItems = 0
+
+ m.data = CreateObject("roSGNode", "ContentNode")
+
+ m.itemGrid.content = m.data
+
+ m.genreData = CreateObject("roSGNode", "ContentNode")
+ m.genreList.observeField("itemSelected", "onGenreItemSelected")
+ m.genreList.observeField("itemFocused", "onGenreItemFocused")
+ m.genreList.content = m.genreData
+
+ m.itemGrid.observeField("itemFocused", "onItemFocused")
+ m.itemGrid.observeField("itemSelected", "onItemSelected")
+ m.itemGrid.observeField("alphaSelected", "onItemalphaSelected")
+
+ 'Voice filter setup
+ m.voiceBox.voiceEnabled = true
+ m.voiceBox.active = true
+ m.voiceBox.observeField("text", "onvoiceFilter")
+ 'set voice help text
+ m.voiceBox.hintText = tr("Use voice remote to search")
+
+ 'backdrop
+ m.newBackdrop.observeField("loadStatus", "newBGLoaded")
+
+ 'Background Image Queued for loading
+ m.queuedBGUri = ""
+
+ 'Item sort - maybe load defaults from user prefs?
+ m.sortField = "SortName"
+ m.sortAscending = true
+
+ m.filter = "All"
+ m.favorite = "Favorite"
+
+ m.loadItemsTask = createObject("roSGNode", "LoadItemsTask2")
+ m.loadLogoTask = createObject("roSGNode", "LoadItemsTask2")
+
+ 'set inital counts for overhang before content is loaded.
+ m.loadItemsTask.totalRecordCount = 0
+
+ m.spinner.visible = true
+
+ 'Get reset folder setting
+ m.resetGrid = get_user_setting("itemgrid.reset") = "true"
+
+ 'Check if device has voice remote
+ devinfo = CreateObject("roDeviceInfo")
+
+ 'Hide voice search if device does not have voice remote
+ if devinfo.HasFeature("voice_remote") = false
+ m.micButton.visible = false
+ m.micButtonText.visible = false
+ end if
+end sub
+
+sub OnScreenHidden()
+ if not m.overhang.isVisible
+ m.overhang.disableMoveAnimation = true
+ m.overhang.isVisible = true
+ m.overhang.disableMoveAnimation = false
+ end if
+end sub
+
+sub OnScreenShown()
+ m.overhang.isVisible = false
+
+ if m.top.lastFocus <> invalid
+ m.top.lastFocus.setFocus(true)
+ else
+ m.top.setFocus(true)
+ end if
+end sub
+
+'
+'Load initial set of Data
+sub loadInitialItems()
+ m.loadItemsTask.control = "stop"
+ m.spinner.visible = true
+
+ if LCase(m.top.parentItem.json.Type) = "collectionfolder"
+ m.top.HomeLibraryItem = m.top.parentItem.Id
+ end if
+
+ if m.top.parentItem.backdropUrl <> invalid
+ SetBackground(m.top.parentItem.backdropUrl)
+ else
+ SetBackground("")
+ end if
+
+ m.sortField = get_user_setting("display." + m.top.parentItem.Id + ".sortField")
+ sortAscendingStr = get_user_setting("display." + m.top.parentItem.Id + ".sortAscending")
+ m.filter = get_user_setting("display." + m.top.parentItem.Id + ".filter")
+ m.view = get_user_setting("display." + m.top.parentItem.Id + ".landing")
+
+ if not isValid(m.sortField) then m.sortField = "SortName"
+ if not isValid(m.filter) then m.filter = "All"
+ if not isValid(m.view) then m.view = "ArtistsPresentation"
+
+ if sortAscendingStr = invalid or LCase(sortAscendingStr) = "true"
+ m.sortAscending = true
+ else
+ m.sortAscending = false
+ end if
+
+ if LCase(m.top.parentItem.json.type) = "musicgenre"
+ m.itemGrid.translation = "[96, 60]"
+ m.loadItemsTask.itemType = "MusicAlbum"
+ m.loadItemsTask.recursive = true
+ m.loadItemsTask.genreIds = m.top.parentItem.id
+ m.loadItemsTask.itemId = m.top.parentItem.parentFolder
+ else if LCase(m.view) = "artistspresentation" or LCase(m.options.view) = "artistspresentation"
+ m.loadItemsTask.genreIds = ""
+ else if LCase(m.view) = "artistsgrid" or LCase(m.options.view) = "artistsgrid"
+ m.loadItemsTask.genreIds = ""
+ else
+ m.loadItemsTask.itemId = m.top.parentItem.Id
+ end if
+
+ m.loadItemsTask.nameStartsWith = m.top.alphaSelected
+ m.loadItemsTask.searchTerm = m.voiceBox.text
+ m.emptyText.visible = false
+ m.loadItemsTask.sortField = m.sortField
+ m.loadItemsTask.sortAscending = m.sortAscending
+ m.loadItemsTask.filter = m.filter
+ m.loadItemsTask.startIndex = 0
+
+ ' Load Item Types
+ if getCollectionType() = "music"
+ m.loadItemsTask.itemType = "MusicArtist"
+ m.loadItemsTask.itemId = m.top.parentItem.Id
+ end if
+
+ ' By default we load Artists
+ m.loadItemsTask.view = "Artists"
+ m.itemGrid.translation = "[96, 420]"
+ m.itemGrid.numRows = "3"
+
+ if LCase(m.options.view) = "albums" or LCase(m.view) = "albums"
+ m.itemGrid.translation = "[96, 60]"
+ m.itemGrid.numRows = "4"
+ m.loadItemsTask.itemType = "MusicAlbum"
+ m.top.imageDisplayMode = "scaleToFit"
+ else if LCase(m.options.view) = "artistsgrid" or LCase(m.view) = "artistsgrid"
+ m.itemGrid.translation = "[96, 60]"
+ m.itemGrid.numRows = "4"
+ else if LCase(m.options.view) = "genres" or LCase(m.view) = "genres"
+ m.loadItemsTask.itemType = ""
+ m.loadItemsTask.recursive = true
+ m.loadItemsTask.view = "Genres"
+ m.artistLogo.visible = false
+ m.selectedArtistName.visible = false
+ end if
+
+ if LCase(m.top.parentItem.json.type) = "musicgenre"
+ m.itemGrid.translation = "[96, 60]"
+ m.itemGrid.numRows = "4"
+ m.artistLogo.visible = false
+ m.selectedArtistName.visible = false
+ end if
+
+ m.loadItemsTask.observeField("content", "ItemDataLoaded")
+ m.spinner.visible = true
+ m.loadItemsTask.control = "RUN"
+ SetUpOptions()
+end sub
+
+' Set Music view, sort, and filter options
+sub setMusicOptions(options)
+
+ options.views = [
+ { "Title": tr("Artists (Presentation)"), "Name": "ArtistsPresentation" },
+ { "Title": tr("Artists (Grid)"), "Name": "ArtistsGrid" },
+ { "Title": tr("Albums"), "Name": "Albums" },
+ { "Title": tr("Genres"), "Name": "Genres" }
+ ]
+
+ if LCase(m.top.parentItem.json.type) = "musicgenre"
+ options.views = [
+ { "Title": tr("Albums"), "Name": "Albums" }
+ ]
+ end if
+
+ options.sort = [
+ { "Title": tr("TITLE"), "Name": "SortName" },
+ { "Title": tr("DATE_ADDED"), "Name": "DateCreated" },
+ { "Title": tr("DATE_PLAYED"), "Name": "DatePlayed" },
+ { "Title": tr("RELEASE_DATE"), "Name": "PremiereDate" },
+ ]
+
+ options.filter = [
+ { "Title": tr("All"), "Name": "All" },
+ { "Title": tr("Favorites"), "Name": "Favorites" }
+ ]
+
+ if LCase(m.options.view) = "genres" or LCase(m.view) = "genres"
+ options.sort = [
+ { "Title": tr("TITLE"), "Name": "SortName" },
+ ]
+ options.filter = []
+ end if
+
+ if LCase(m.options.view) = "albums" or LCase(m.view) = "albums"
+ options.sort = [
+ { "Title": tr("TITLE"), "Name": "SortName" },
+ { "Title": tr("DATE_ADDED"), "Name": "DateCreated" },
+ ]
+ end if
+end sub
+
+' Return parent collection type
+function getCollectionType() as string
+ if m.top.parentItem.collectionType = invalid
+ return LCase(m.top.parentItem.Type)
+ else
+ return LCase(m.top.parentItem.CollectionType)
+ end if
+end function
+
+' Search string array for search value. Return if it's found
+function inStringArray(array, searchValue) as boolean
+ for each item in array
+ if lcase(item) = lcase(searchValue) then return true
+ end for
+ return false
+end function
+
+' Data to display when options button selected
+sub SetUpOptions()
+ options = {}
+ options.filter = []
+ options.favorite = []
+
+ setMusicOptions(options)
+
+ ' Set selected view option
+ for each o in options.views
+ if LCase(o.Name) = LCase(m.view)
+ o.Selected = true
+ o.Ascending = m.sortAscending
+ m.options.view = o.Name
+ end if
+ end for
+
+ ' Set selected sort option
+ for each o in options.sort
+ if LCase(o.Name) = LCase(m.sortField)
+ o.Selected = true
+ o.Ascending = m.sortAscending
+ m.options.sortField = o.Name
+ end if
+ end for
+
+ ' Set selected filter option
+ for each o in options.filter
+ if LCase(o.Name) = LCase(m.filter)
+ o.Selected = true
+ m.options.filter = o.Name
+ end if
+ end for
+
+ m.options.options = options
+end sub
+
+'
+' Logo Image Loaded Event Handler
+sub LogoImageLoaded(msg)
+ data = msg.GetData()
+ m.loadLogoTask.unobserveField("content")
+ m.loadLogoTask.content = []
+
+ if data.Count() > 0
+ m.artistLogo.uri = data[0]
+ m.artistLogo.visible = true
+ else
+ m.selectedArtistName.visible = true
+ end if
+end sub
+
+'
+'Handle loaded data, and add to Grid
+sub ItemDataLoaded(msg)
+ m.top.alphaActive = false
+ itemData = msg.GetData()
+ m.loadItemsTask.unobserveField("content")
+ m.loadItemsTask.content = []
+
+ if itemData = invalid
+ m.Loading = false
+ return
+ end if
+
+ if LCase(m.loadItemsTask.view) = "genres"
+ for each item in itemData
+ m.genreData.appendChild(item)
+ end for
+
+ m.itemGrid.opacity = "0"
+ m.genreList.opacity = "1"
+
+ m.itemGrid.setFocus(false)
+ m.genreList.setFocus(true)
+
+ m.loadedItems = m.genreList.content.getChildCount()
+ m.loadedRows = m.loadedItems / m.genreList.numColumns
+
+ m.loading = false
+ m.spinner.visible = false
+ return
+ end if
+
+ m.itemGrid.opacity = "1"
+ m.genreList.opacity = "0"
+
+ m.itemGrid.setFocus(true)
+ m.genreList.setFocus(false)
+
+ for each item in itemData
+ m.data.appendChild(item)
+ end for
+
+ 'Update the stored counts
+ m.loadedItems = m.itemGrid.content.getChildCount()
+ m.loadedRows = m.loadedItems / m.itemGrid.numColumns
+ m.Loading = false
+ 'If there are no items to display, show message
+ if m.loadedItems = 0
+ m.emptyText.text = tr("NO_ITEMS").Replace("%1", m.top.parentItem.Type)
+ m.emptyText.visible = true
+ end if
+
+ m.spinner.visible = false
+end sub
+
+'
+'Set Selected Artist Name
+sub SetName(artistName as string)
+ m.selectedArtistName.text = artistName
+end sub
+
+'
+'Set Selected Artist Song Count
+sub SetSongCount(totalCount)
+ appendText = " " + tr("Songs")
+ if totalCount = 1
+ appendText = " " + tr("Song")
+ end if
+
+ m.selectedArtistSongCount.text = totalCount.tostr() + appendText
+end sub
+'
+'Set Selected Artist Album Count
+sub SetAlbumCount(totalCount)
+ appendText = " " + tr("Albums")
+ if totalCount = 1
+ appendText = " " + tr("Album")
+ end if
+
+ m.selectedArtistAlbumCount.text = totalCount.tostr() + appendText
+end sub
+
+'
+'Set Selected Artist Genres
+sub SetGenres(artistGenres)
+ m.selectedArtistGenres.text = artistGenres.join(", ")
+end sub
+
+'
+'Set Background Image
+sub SetBackground(backgroundUri as string)
+ if backgroundUri = ""
+ m.backdrop.opacity = 0
+ end if
+
+ 'If a new image is being loaded, or transitioned to, store URL to load next
+ if LCase(m.swapAnimation.state) <> "stopped" or LCase(m.newBackdrop.loadStatus) = "loading"
+ m.queuedBGUri = backgroundUri
+ return
+ end if
+
+ m.newBackdrop.uri = backgroundUri
+end sub
+
+'
+'Handle new item being focused
+sub onItemFocused()
+ focusedRow = m.itemGrid.currFocusRow
+
+ itemInt = m.itemGrid.itemFocused
+
+ ' If no selected item, set background to parent backdrop
+ if itemInt = -1
+ return
+ end if
+
+ m.artistLogo.visible = false
+ m.selectedArtistName.visible = false
+ m.selectedArtistGenres.visible = false
+ m.selectedArtistSongCount.visible = false
+ m.selectedArtistAlbumCount.visible = false
+
+ ' Load more data if focus is within last 5 rows, and there are more items to load
+ if focusedRow >= m.loadedRows - 5 and m.loadeditems < m.loadItemsTask.totalRecordCount
+ loadMoreData()
+ end if
+
+ m.selectedFavoriteItem = getItemFocused()
+
+ if LCase(m.options.view) = "albums" or LCase(m.view) = "albums" or LCase(m.top.parentItem.json.type) = "musicgenre"
+ return
+ end if
+
+ if LCase(m.options.view) = "artistsgrid" or LCase(m.view) = "artistsgrid"
+ return
+ end if
+
+ if not m.selectedArtistGenres.visible
+ m.selectedArtistGenres.visible = true
+ end if
+
+ if not m.selectedArtistSongCount.visible
+ m.selectedArtistSongCount.visible = true
+ end if
+
+ if not m.selectedArtistAlbumCount.visible
+ m.selectedArtistAlbumCount.visible = true
+ end if
+
+ itemData = m.selectedFavoriteItem.json
+
+ if isValid(itemData.SongCount)
+ SetSongCount(itemData.SongCount)
+ else
+ SetSongCount("")
+ end if
+
+ if isValid(itemData.AlbumCount)
+ SetAlbumCount(itemData.AlbumCount)
+ else
+ SetAlbumCount("")
+ end if
+
+ if isValid(itemData.Genres)
+ SetGenres(itemData.Genres)
+ else
+ SetGenres([])
+ end if
+
+ if isValid(itemData.Name)
+ SetName(itemData.Name)
+ else
+ SetName("")
+ end if
+
+ m.loadLogoTask.itemId = itemData.id
+ m.loadLogoTask.itemType = "LogoImage"
+ m.loadLogoTask.observeField("content", "LogoImageLoaded")
+ m.loadLogoTask.control = "RUN"
+
+ ' Set Background to item backdrop
+ SetBackground(m.selectedFavoriteItem.backdropUrl)
+end sub
+
+sub setFieldText(field, value)
+ node = m.top.findNode(field)
+ if node = invalid or value = invalid then return
+
+ ' Handle non strings... Which _shouldn't_ happen, but hey
+ if type(value) = "roInt" or type(value) = "Integer"
+ value = str(value)
+ else if type(value) = "roFloat" or type(value) = "Float"
+ value = str(value)
+ else if type(value) <> "roString" and type(value) <> "String"
+ value = ""
+ end if
+
+ node.text = value
+end sub
+
+'
+'When Image Loading Status changes
+sub newBGLoaded()
+ 'If image load was sucessful, start the fade swap
+ if LCase(m.newBackdrop.loadStatus) = "ready"
+ m.swapAnimation.control = "start"
+ end if
+end sub
+
+'
+'Swap Complete
+sub swapDone()
+ if LCase(m.swapAnimation.state) = "stopped"
+ 'Set main BG node image and hide transitioning node
+ m.backdrop.uri = m.newBackdrop.uri
+ m.backdrop.opacity = 1
+ m.newBackdrop.opacity = 0
+
+ 'If there is another one to load
+ if m.newBackdrop.uri <> m.queuedBGUri and m.queuedBGUri <> ""
+ SetBackground(m.queuedBGUri)
+ m.queuedBGUri = ""
+ end if
+ end if
+end sub
+
+'
+'Load next set of items
+sub loadMoreData()
+ m.spinner.visible = true
+ if m.Loading = true then return
+ m.Loading = true
+ m.loadItemsTask.startIndex = m.loadedItems
+ m.loadItemsTask.observeField("content", "ItemDataLoaded")
+ m.loadItemsTask.control = "RUN"
+end sub
+
+'
+'Item Selected
+sub onItemSelected()
+ m.top.selectedItem = m.itemGrid.content.getChild(m.itemGrid.itemSelected)
+end sub
+
+'
+'Returns Focused Item
+function getItemFocused()
+ return m.itemGrid.content.getChild(m.itemGrid.itemFocused)
+end function
+
+'
+'Genre Item Selected
+sub onGenreItemSelected()
+ m.top.selectedItem = m.genreList.content.getChild(m.genreList.itemSelected)
+end sub
+
+'
+'Genre Item Focused
+sub onGenreItemFocused()
+ focusedRow = m.genreList.currFocusRow
+
+ ' Load more data if focus is within last 5 rows, and there are more items to load
+ if focusedRow >= m.loadedRows - 5 and m.loadeditems < m.loadItemsTask.totalRecordCount
+ loadMoreData()
+ end if
+end sub
+
+sub onItemalphaSelected()
+ if m.top.alphaSelected <> ""
+ m.loadedRows = 0
+ m.loadedItems = 0
+
+ m.data = CreateObject("roSGNode", "ContentNode")
+ m.itemGrid.content = m.data
+
+ m.genreData = CreateObject("roSGNode", "ContentNode")
+ m.genreList.content = m.genreData
+
+ m.loadItemsTask.searchTerm = ""
+ m.VoiceBox.text = ""
+ m.loadItemsTask.nameStartsWith = m.alpha.itemAlphaSelected
+ m.spinner.visible = true
+ loadInitialItems()
+ end if
+end sub
+
+sub onvoiceFilter()
+ if m.VoiceBox.text <> ""
+ m.loadedRows = 0
+ m.loadedItems = 0
+ m.data = CreateObject("roSGNode", "ContentNode")
+ m.itemGrid.content = m.data
+ m.top.alphaSelected = ""
+ m.loadItemsTask.NameStartsWith = " "
+ m.loadItemsTask.searchTerm = m.voiceBox.text
+ m.loadItemsTask.recursive = true
+ m.spinner.visible = true
+ loadInitialItems()
+ end if
+end sub
+
+
+'
+'Check if options updated and any reloading required
+sub optionsClosed()
+ reload = false
+
+ if m.options.sortField <> m.sortField or m.options.sortAscending <> m.sortAscending
+ m.sortField = m.options.sortField
+ m.sortAscending = m.options.sortAscending
+ reload = true
+
+ sortAscendingStr = "true"
+
+ 'Store sort settings
+ if not m.sortAscending
+ sortAscendingStr = "false"
+ end if
+
+ set_user_setting("display." + m.top.parentItem.Id + ".sortField", m.sortField)
+ set_user_setting("display." + m.top.parentItem.Id + ".sortAscending", sortAscendingStr)
+ end if
+
+ if m.options.filter <> m.filter
+ m.filter = m.options.filter
+ reload = true
+ set_user_setting("display." + m.top.parentItem.Id + ".filter", m.options.filter)
+ end if
+
+ m.view = get_user_setting("display." + m.top.parentItem.Id + ".landing")
+
+ if m.options.view <> m.view
+ m.view = m.options.view
+ m.top.view = m.view
+ set_user_setting("display." + m.top.parentItem.Id + ".landing", m.view)
+
+ ' Reset any filtering or search terms
+ m.top.alphaSelected = ""
+ m.loadItemsTask.NameStartsWith = " "
+ m.loadItemsTask.searchTerm = ""
+ m.filter = "All"
+ m.sortField = "SortName"
+ m.sortAscending = true
+
+ ' Reset view to defaults
+ set_user_setting("display." + m.top.parentItem.Id + ".sortField", m.sortField)
+ set_user_setting("display." + m.top.parentItem.Id + ".sortAscending", "true")
+ set_user_setting("display." + m.top.parentItem.Id + ".filter", m.filter)
+
+ reload = true
+ end if
+
+ if reload
+ m.loadedRows = 0
+ m.loadedItems = 0
+ m.data = CreateObject("roSGNode", "ContentNode")
+ m.genreData = CreateObject("roSGNode", "ContentNode")
+ m.itemGrid.content = m.data
+ m.genreList.content = m.genreData
+ loadInitialItems()
+ end if
+
+ m.itemGrid.setFocus(m.itemGrid.opacity = 1)
+ m.genreList.setFocus(m.genreList.opacity = 1)
+end sub
+
+sub onChannelSelected(msg)
+ node = msg.getRoSGNode()
+ m.top.lastFocus = lastFocusedChild(node)
+ if node.watchChannel <> invalid
+ ' Clone the node when it's reused/update in the TimeGrid it doesn't automatically start playing
+ m.top.selectedItem = node.watchChannel.clone(false)
+ end if
+end sub
+
+function onKeyEvent(key as string, press as boolean) as boolean
+ if not press then return false
+
+ if key = "left" and m.voiceBox.isinFocusChain()
+ m.itemGrid.setFocus(m.itemGrid.opacity = 1)
+ m.genreList.setFocus(m.genreList.opacity = 1)
+ m.voiceBox.setFocus(false)
+ end if
+
+ if key = "options"
+ if m.options.visible = true
+ m.options.visible = false
+ m.top.removeChild(m.options)
+ optionsClosed()
+ else
+
+ itemSelected = m.selectedFavoriteItem
+ if itemSelected <> invalid
+ m.options.selectedFavoriteItem = itemSelected
+ end if
+
+ m.options.visible = true
+ m.top.appendChild(m.options)
+ m.options.setFocus(true)
+ end if
+ return true
+ else if key = "back"
+ if m.options.visible = true
+ m.options.visible = false
+ optionsClosed()
+ return true
+ else
+ m.global.sceneManager.callfunc("popScene")
+ m.loadItemsTask.control = "stop"
+ return true
+ end if
+ else if key = "left"
+ if m.itemGrid.isinFocusChain()
+ m.top.alphaActive = true
+ m.itemGrid.setFocus(false)
+ alpha = m.alpha.getChild(0).findNode("Alphamenu")
+ alpha.setFocus(true)
+ return true
+ else if m.genreList.isinFocusChain()
+ m.top.alphaActive = true
+ m.genreList.setFocus(false)
+ alpha = m.alpha.getChild(0).findNode("Alphamenu")
+ alpha.setFocus(true)
+ return true
+ end if
+
+ else if key = "right" and m.Alpha.isinFocusChain()
+ m.top.alphaActive = false
+ m.Alpha.setFocus(false)
+ m.Alpha.visible = true
+
+ m.itemGrid.setFocus(m.itemGrid.opacity = 1)
+ m.genreList.setFocus(m.genreList.opacity = 1)
+
+ return true
+
+ else if key = "replay" and m.itemGrid.isinFocusChain()
+ if m.resetGrid = true
+ m.itemGrid.animateToItem = 0
+ else
+ m.itemGrid.jumpToItem = 0
+ end if
+
+ else if key = "replay" and m.genreList.isinFocusChain()
+ if m.resetGrid = true
+ m.genreList.animateToItem = 0
+ else
+ m.genreList.jumpToItem = 0
+ end if
+ return true
+ end if
+
+ if key = "replay"
+ m.spinner.visible = true
+ m.loadItemsTask.searchTerm = ""
+ m.loadItemsTask.nameStartsWith = ""
+ m.voiceBox.text = ""
+ m.top.alphaSelected = ""
+ m.loadItemsTask.filter = "All"
+ m.filter = "All"
+ m.data = CreateObject("roSGNode", "ContentNode")
+ m.itemGrid.content = m.data
+ loadInitialItems()
+ return true
+ end if
+
+ return false
+end function
diff --git a/components/ItemGrid/MusicLibraryView.xml b/components/ItemGrid/MusicLibraryView.xml
new file mode 100644
index 00000000..5f2ec51c
--- /dev/null
+++ b/components/ItemGrid/MusicLibraryView.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/JFScene.brs b/components/JFScene.brs
index 6454349f..e2ff69c9 100644
--- a/components/JFScene.brs
+++ b/components/JFScene.brs
@@ -11,7 +11,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
return true
else if key = "options"
group = m.global.sceneManager.callFunc("getActiveScene")
- if group <> invalid and group.optionsAvailable
+ if isValid(group) and isValid(group.optionsAvailable) and group.optionsAvailable
group.lastFocus = group.focusedChild
panel = group.findNode("options")
panel.visible = true
diff --git a/components/JFScene.xml b/components/JFScene.xml
index 7f6a82c9..c0e4f0a0 100644
--- a/components/JFScene.xml
+++ b/components/JFScene.xml
@@ -8,4 +8,5 @@
+
diff --git a/components/ListPoster.brs b/components/ListPoster.brs
index ef4179f5..ae04ef18 100644
--- a/components/ListPoster.brs
+++ b/components/ListPoster.brs
@@ -3,6 +3,8 @@ sub init()
m.staticTitle = m.top.findNode("staticTitle")
m.series = m.top.findNode("Series")
m.poster = m.top.findNode("poster")
+ m.unplayedCount = m.top.findNode("unplayedCount")
+ m.unplayedEpisodeCount = m.top.findNode("unplayedEpisodeCount")
m.backdrop = m.top.findNode("backdrop")
@@ -55,6 +57,13 @@ sub itemContentChanged() as void
itemData = m.top.itemContent
m.title.text = itemData.title
+ if itemData?.json?.UserData?.UnplayedItemCount <> invalid
+ if itemData.json.UserData.UnplayedItemCount > 0
+ m.unplayedCount.visible = true
+ m.unplayedEpisodeCount.text = itemData.json.UserData.UnplayedItemCount
+ end if
+ end if
+
if itemData.json.lookup("Type") = "Episode" and itemData.json.IndexNumber <> invalid
m.title.text = StrI(itemData.json.IndexNumber) + ". " + m.title.text
diff --git a/components/ListPoster.xml b/components/ListPoster.xml
index fe512c3b..55ae1285 100644
--- a/components/ListPoster.xml
+++ b/components/ListPoster.xml
@@ -2,32 +2,20 @@
-
-
-
-
+
+
+
+
+
+
+
+
-
-
diff --git a/components/WhatsNewDialog.brs b/components/WhatsNewDialog.brs
new file mode 100644
index 00000000..5718377b
--- /dev/null
+++ b/components/WhatsNewDialog.brs
@@ -0,0 +1,46 @@
+sub init()
+ m.content = m.top.findNode("content")
+
+ setPalette()
+
+ m.top.id = "OKDialog"
+ m.top.height = 900
+ m.top.title = "What's New?"
+ m.top.buttons = [tr("OK")]
+
+ dialogStyles = {
+ "default": {
+ "fontSize": 27,
+ "fontUri": "font:SystemFontFile",
+ "color": "#EFEFEFFF"
+ },
+ "author": {
+ "fontSize": 27,
+ "fontUri": "font:SystemFontFile",
+ "color": "#00a4dcFF"
+ }
+ }
+
+ whatsNewList = ParseJSON(ReadAsciiFile("pkg:/source/static/whatsNew.json"))
+
+ for each item in whatsNewList
+ textLine = m.content.CreateChild("StdDlgMultiStyleTextItem")
+ textLine.drawingStyles = dialogStyles
+ textLine.text = "• " + item.description + " " + item.author + ""
+ end for
+
+end sub
+
+sub setPalette()
+ dlgPalette = createObject("roSGNode", "RSGPalette")
+ dlgPalette.colors = {
+ DialogBackgroundColor: "0x262828FF",
+ DialogFocusColor: "0xcececeFF",
+ DialogFocusItemColor: "0x202020FF",
+ DialogSecondaryTextColor: "0xf8f8f8ff",
+ DialogSecondaryItemColor: "#00a4dcFF",
+ DialogTextColor: "0xeeeeeeFF"
+ }
+
+ m.top.palette = dlgPalette
+end sub
diff --git a/components/WhatsNewDialog.xml b/components/WhatsNewDialog.xml
new file mode 100644
index 00000000..87847569
--- /dev/null
+++ b/components/WhatsNewDialog.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/data/ChannelData.brs b/components/data/ChannelData.brs
index 34cd9602..fd5fb68e 100644
--- a/components/data/ChannelData.brs
+++ b/components/data/ChannelData.brs
@@ -11,10 +11,10 @@ sub setPoster()
if m.top.image <> invalid
m.top.posterURL = m.top.image.url
else if m.top.json.ImageTags <> invalid and m.top.json.ImageTags.Primary <> invalid
- imgParams = { "maxHeight": 60 }
+ imgParams = { "maxHeight": 60, "Tag": m.top.json.ImageTags.Primary }
m.top.hdsmalliconurl = ImageURL(m.top.json.id, "Primary", imgParams)
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
end if
end sub
diff --git a/components/data/CollectionData.brs b/components/data/CollectionData.brs
index 5cc1d245..3a37949d 100644
--- a/components/data/CollectionData.brs
+++ b/components/data/CollectionData.brs
@@ -18,16 +18,16 @@ sub setPoster()
else
if m.top.json.ImageTags.Primary <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
else if m.top.json.BackdropImageTags <> invalid
- imgParams = { "maxHeight": 440 }
+ imgParams = { "maxHeight": 440, "Tag": m.top.json.BackdropImageTags[0] }
m.top.posterURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
' Add Backdrop Image
if m.top.json.BackdropImageTags <> invalid
- imgParams = { "maxHeight": 720, "maxWidth": 1280 }
+ imgParams = { "maxHeight": 720, "maxWidth": 1280, "Tag": m.top.json.BackdropImageTags[0] }
m.top.backdropURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
diff --git a/components/data/FolderData.brs b/components/data/FolderData.brs
index 4239de2a..5a441007 100644
--- a/components/data/FolderData.brs
+++ b/components/data/FolderData.brs
@@ -21,7 +21,7 @@ sub setPoster()
imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ParentThumbImageTag }
m.top.posterURL = ImageURL(m.top.json.id, "Thumb", imgParams)
else if m.top.json.ImageTags.Primary <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
end if
end sub
diff --git a/components/data/HomeData.brs b/components/data/HomeData.brs
index 66ecbb82..1426bf6b 100644
--- a/components/data/HomeData.brs
+++ b/components/data/HomeData.brs
@@ -16,7 +16,7 @@ sub setData()
' Set appropriate Images for Wide and Tall based on type
if datum.type = "CollectionFolder" or datum.type = "UserView"
- params = { "maxHeight": 261, "maxWidth": 464 }
+ params = { "Tag": datum.ImageTags.Primary, "maxHeight": 261, "maxWidth": 464 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
@@ -33,14 +33,22 @@ sub setData()
imgParams.Append({ "maxHeight": 261 })
imgParams.Append({ "maxWidth": 464 })
+ if datum.ImageTags.Primary <> invalid
+ param = { "Tag": datum.ImageTags.Primary }
+ imgParams.Append(param)
+ end if
+
m.top.thumbnailURL = ImageURL(datum.id, "Primary", imgParams)
' Add Wide Poster (Series Backdrop)
if datum.ParentThumbImageTag <> invalid
+ imgParams["Tag"] = datum.ParentThumbImageTag
m.top.widePosterUrl = ImageURL(datum.ParentThumbItemId, "Thumb", imgParams)
else if datum.ParentBackdropImageTags <> invalid
+ imgParams["Tag"] = datum.ParentBackdropImageTags[0]
m.top.widePosterUrl = ImageURL(datum.ParentBackdropItemId, "Backdrop", imgParams)
else if datum.ImageTags.Primary <> invalid
+ imgParams["Tag"] = datum.SeriesPrimaryImageTag
m.top.widePosterUrl = ImageURL(datum.id, "Primary", imgParams)
end if
@@ -48,16 +56,14 @@ sub setData()
imgParams = { "maxHeight": 261 }
imgParams.Append({ "maxWidth": 464 })
- if datum.UserData.UnplayedItemCount > 0
- imgParams["UnplayedCount"] = datum.UserData.UnplayedItemCount
- end if
-
m.top.posterURL = ImageURL(datum.id, "Primary", imgParams)
' Add Wide Poster (Series Backdrop)
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid
+ imgParams["Tag"] = datum.imageTags.Thumb
m.top.widePosterUrl = ImageURL(datum.Id, "Thumb", imgParams)
else if datum.BackdropImageTags <> invalid
+ imgParams["Tag"] = datum.BackdropImageTags[0]
m.top.widePosterUrl = ImageURL(datum.Id, "Backdrop", imgParams)
end if
@@ -67,14 +73,21 @@ sub setData()
imgParams.Append({ "maxHeight": 261 })
imgParams.Append({ "maxWidth": 175 })
+ if datum.ImageTags.Primary <> invalid
+ param = { "Tag": datum.ImageTags.Primary }
+ imgParams.Append(param)
+ end if
+
m.top.posterURL = ImageURL(datum.id, "Primary", imgParams)
' For wide image, use backdrop
imgParams["maxWidth"] = 464
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid
+ imgParams["Tag"] = datum.imageTags.Thumb
m.top.thumbnailUrl = ImageURL(datum.Id, "Thumb", imgParams)
else if datum.BackdropImageTags[0] <> invalid
+ imgParams["Tag"] = datum.BackdropImageTags[0]
m.top.thumbnailUrl = ImageURL(datum.id, "Backdrop", imgParams)
end if
@@ -84,24 +97,31 @@ sub setData()
imgParams.Append({ "maxHeight": 261 })
imgParams.Append({ "maxWidth": 175 })
+ if datum.ImageTags.Primary <> invalid
+ param = { "Tag": datum.ImageTags.Primary }
+ imgParams.Append(param)
+ end if
+
m.top.posterURL = ImageURL(datum.id, "Primary", imgParams)
' For wide image, use backdrop
imgParams["maxWidth"] = 464
if datum.ImageTags <> invalid and datum.imageTags.Thumb <> invalid
+ imgParams["Tag"] = datum.imageTags.Thumb
m.top.thumbnailUrl = ImageURL(datum.Id, "Thumb", imgParams)
else if datum.BackdropImageTags[0] <> invalid
+ imgParams["Tag"] = datum.BackdropImageTags[0]
m.top.thumbnailUrl = ImageURL(datum.id, "Backdrop", imgParams)
end if
else if datum.type = "MusicAlbum"
- params = { "maxHeight": 261, "maxWidth": 261 }
+ params = { "Tag": datum.ImageTags.Primary, "maxHeight": 261, "maxWidth": 261 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
m.top.posterUrl = m.top.thumbnailURL
else if datum.type = "TvChannel" or datum.type = "Channel"
- params = { "maxHeight": 261, "maxWidth": 464 }
+ params = { "Tag": datum.ImageTags.Primary, "maxHeight": 261, "maxWidth": 464 }
m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
m.top.widePosterUrl = m.top.thumbnailURL
m.top.iconUrl = "pkg:/images/media_type_icons/live_tv_white.png"
diff --git a/components/data/MovieData.brs b/components/data/MovieData.brs
index b1bcaa61..ef27b97c 100644
--- a/components/data/MovieData.brs
+++ b/components/data/MovieData.brs
@@ -40,20 +40,20 @@ sub setPoster()
else
if m.top.json.ImageTags.Primary <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
else if m.top.json.BackdropImageTags[0] <> invalid
- imgParams = { "maxHeight": 440 }
+ imgParams = { "maxHeight": 440, "Tag": m.top.json.BackdropImageTags[0] }
m.top.posterURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
else if m.top.json.ParentThumbImageTag <> invalid and m.top.json.ParentThumbItemId <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ParentThumbImageTag }
m.top.posterURL = ImageURL(m.top.json.ParentThumbItemId, "Thumb", imgParams)
end if
' Add Backdrop Image
if m.top.json.BackdropImageTags <> invalid
if m.top.json.BackdropImageTags[0] <> invalid
- imgParams = { "maxHeight": 720, "maxWidth": 1280 }
+ imgParams = { "maxHeight": 720, "maxWidth": 1280, "Tag": m.top.json.BackdropImageTags[0] }
m.top.backdropURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
end if
diff --git a/components/data/PersonData.brs b/components/data/PersonData.brs
index fcf21d51..7e9b3d66 100644
--- a/components/data/PersonData.brs
+++ b/components/data/PersonData.brs
@@ -12,19 +12,19 @@ sub setPoster()
else
if m.top.json.ImageTags.Primary <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
else if m.top.json.BackdropImageTags[0] <> invalid
- imgParams = { "maxHeight": 440 }
+ imgParams = { "maxHeight": 440, "Tag": m.top.json.BackdropImageTags[0] }
m.top.posterURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
else if m.top.json.ParentThumbImageTag <> invalid and m.top.json.ParentThumbItemId <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ParentThumbImageTag }
m.top.posterURL = ImageURL(m.top.json.ParentThumbItemId, "Thumb", imgParams)
end if
' Add Backdrop Image
if m.top.json.BackdropImageTags[0] <> invalid
- imgParams = { "maxHeight": 720, "maxWidth": 1280 }
+ imgParams = { "maxHeight": 720, "maxWidth": 1280, "Tag": m.top.json.BackdropImageTags[0] }
m.top.backdropURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
diff --git a/components/data/PhotoData.brs b/components/data/PhotoData.brs
index 2cd741e2..9afb0076 100644
--- a/components/data/PhotoData.brs
+++ b/components/data/PhotoData.brs
@@ -14,19 +14,19 @@ sub setPoster()
else
if m.top.json.ImageTags.Primary <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
else if m.top.json.BackdropImageTags[0] <> invalid
- imgParams = { "maxHeight": 440 }
+ imgParams = { "maxHeight": 440, "Tag": m.top.json.BackdropImageTags[0] }
m.top.posterURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
else if m.top.json.ParentThumbImageTag <> invalid and m.top.json.ParentThumbItemId <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ParentThumbImageTag }
m.top.posterURL = ImageURL(m.top.json.ParentThumbItemId, "Thumb", imgParams)
end if
' Add Backdrop Image
if m.top.json.BackdropImageTags[0] <> invalid
- imgParams = { "maxHeight": 720, "maxWidth": 1280 }
+ imgParams = { "maxHeight": 720, "maxWidth": 1280, "Tag": m.top.json.BackdropImageTags[0] }
m.top.backdropURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
diff --git a/components/data/ScheduleProgramData.brs b/components/data/ScheduleProgramData.brs
index b4ff9656..bb07251a 100644
--- a/components/data/ScheduleProgramData.brs
+++ b/components/data/ScheduleProgramData.brs
@@ -36,7 +36,7 @@ sub setPoster()
m.top.posterURL = m.top.image.url
else
if m.top.json.ImageTags <> invalid and m.top.json.ImageTags.Thumb <> invalid
- imgParams = { "maxHeight": 500, "maxWidth": 500 }
+ imgParams = { "maxHeight": 500, "maxWidth": 500, "Tag": m.top.json.ImageTags.Thumb }
m.top.posterURL = ImageURL(m.top.json.id, "Thumb", imgParams)
end if
end if
diff --git a/components/data/SeriesData.brs b/components/data/SeriesData.brs
index 28023cc0..8c765b74 100644
--- a/components/data/SeriesData.brs
+++ b/components/data/SeriesData.brs
@@ -32,16 +32,16 @@ sub setPoster()
if m.top.json.ImageTags.Primary <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
else if m.top.json.BackdropImageTags <> invalid
- imgParams = { "maxHeight": 440 }
+ imgParams = { "maxHeight": 440, "Tag": m.top.json.BackdropImageTags[0] }
m.top.posterURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
' Add Backdrop Image
if m.top.json.BackdropImageTags <> invalid
- imgParams = { "maxHeight": 720, "maxWidth": 1280 }
+ imgParams = { "maxHeight": 720, "maxWidth": 1280, "Tag": m.top.json.BackdropImageTags[0] }
m.top.backdropURL = ImageURL(m.top.json.id, "Backdrop", imgParams)
end if
diff --git a/components/data/VideoData.brs b/components/data/VideoData.brs
index bcfad50a..5cec5192 100644
--- a/components/data/VideoData.brs
+++ b/components/data/VideoData.brs
@@ -15,7 +15,7 @@ sub setPoster()
if m.top.image <> invalid
m.top.posterURL = m.top.image.url
else if m.top.json.ImageTags.Primary <> invalid
- imgParams = { "maxHeight": 440, "maxWidth": 295 }
+ imgParams = { "maxHeight": 440, "maxWidth": 295, "Tag": m.top.json.ImageTags.Primary }
m.top.posterURL = ImageURL(m.top.json.id, "Primary", imgParams)
end if
end sub
diff --git a/components/home/Home.xml b/components/home/Home.xml
index 3909bb0c..6a07969f 100644
--- a/components/home/Home.xml
+++ b/components/home/Home.xml
@@ -16,4 +16,5 @@
+
diff --git a/components/home/HomeItem.brs b/components/home/HomeItem.brs
index 5b0e081e..42830c01 100644
--- a/components/home/HomeItem.brs
+++ b/components/home/HomeItem.brs
@@ -7,6 +7,8 @@ sub init()
m.itemIcon = m.top.findNode("itemIcon")
m.itemTextExtra = m.top.findNode("itemTextExtra")
m.itemPoster.observeField("loadStatus", "onPosterLoadStatusChanged")
+ m.unplayedCount = m.top.findNode("unplayedCount")
+ m.unplayedEpisodeCount = m.top.findNode("unplayedEpisodeCount")
m.showProgressBarAnimation = m.top.findNode("showProgressBar")
m.showProgressBarField = m.top.findNode("showProgressBarField")
@@ -24,19 +26,26 @@ sub itemContentChanged()
if itemData = invalid then return
itemData.Title = itemData.name ' Temporarily required while we move from "HomeItem" to "JFContentItem"
-
m.itemPoster.width = itemData.imageWidth
m.itemText.maxWidth = itemData.imageWidth
m.itemTextExtra.width = itemData.imageWidth
m.itemTextExtra.visible = true
-
m.backdrop.width = itemData.imageWidth
if itemData.iconUrl <> invalid
m.itemIcon.uri = itemData.iconUrl
end if
+ if LCase(itemData.type) = "series"
+ if itemData?.json?.UserData?.UnplayedItemCount <> invalid
+ if itemData.json.UserData.UnplayedItemCount > 0
+ m.unplayedCount.visible = true
+ m.unplayedEpisodeCount.text = itemData.json.UserData.UnplayedItemCount
+ end if
+ end if
+ end if
+
' Format the Data based on the type of Home Data
if itemData.type = "CollectionFolder" or itemData.type = "UserView" or itemData.type = "Channel"
m.itemText.text = itemData.name
@@ -64,8 +73,12 @@ sub itemContentChanged()
' "Program" is from clicking on an "On Now" item on the Home Screen
if itemData.type = "Program"
m.itemText.Text = itemData.json.name
- if itemData.json.ImageURL <> invalid
- m.itemPoster.uri = itemData.json.ImageURL
+ m.itemTextExtra.Text = itemData.json.ChannelName
+ if itemData.widePosterURL <> ""
+ m.itemPoster.uri = ImageURL(itemData.widePosterURL)
+ else
+ m.itemPoster.uri = ImageURL(itemData.json.ChannelId)
+ m.itemPoster.loadDisplayMode = "scaleToFill"
end if
' Set Episode title if available
diff --git a/components/home/HomeItem.xml b/components/home/HomeItem.xml
index 3fb36250..74d9f064 100644
--- a/components/home/HomeItem.xml
+++ b/components/home/HomeItem.xml
@@ -3,12 +3,14 @@
-
-
+
+
+
+
+
-
diff --git a/components/home/HomeRows.brs b/components/home/HomeRows.brs
index a21675b0..30250c9f 100644
--- a/components/home/HomeRows.brs
+++ b/components/home/HomeRows.brs
@@ -61,10 +61,13 @@ sub onLibrariesLoaded()
m.LoadLibrariesTask.content = []
' create My Media, Continue Watching, and Next Up rows
content = CreateObject("roSGNode", "ContentNode")
+
mediaRow = content.CreateChild("HomeRow")
mediaRow.title = tr("My Media")
+
continueRow = content.CreateChild("HomeRow")
continueRow.title = tr("Continue Watching")
+
nextUpRow = content.CreateChild("HomeRow")
nextUpRow.title = tr("Next Up >")
@@ -79,6 +82,19 @@ sub onLibrariesLoaded()
]
haveLiveTV = false
+
+ ' Load the NextUp Data
+ m.LoadNextUpTask.observeField("content", "updateNextUpItems")
+ m.LoadNextUpTask.control = "RUN"
+
+ ' Load the Continue Watching Data
+ m.LoadContinueTask.observeField("content", "updateContinueItems")
+ m.LoadContinueTask.control = "RUN"
+
+ ' Load the Favorites Data
+ m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
+ m.LoadFavoritesTask.control = "RUN"
+
' validate library data
if m.libraryData <> invalid and m.libraryData.count() > 0
userConfig = m.top.userConfig
@@ -92,36 +108,38 @@ sub onLibrariesLoaded()
' create a "Latest In" row for each library
filteredLatest = filterNodeArray(m.libraryData, "id", userConfig.LatestItemsExcludes)
for each lib in filteredLatest
- if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv"
+ if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv" and lib.json.CollectionType <> "Program"
latestInRow = content.CreateChild("HomeRow")
latestInRow.title = tr("Latest in") + " " + lib.name + " >"
sizeArray.Push([464, 331])
+
+ loadLatest = createObject("roSGNode", "LoadItemsTask")
+ loadLatest.itemsToLoad = "latest"
+ loadLatest.itemId = lib.id
+
+ metadata = { "title": lib.name }
+ metadata.Append({ "contentType": lib.json.CollectionType })
+ loadLatest.metadata = metadata
+
+ loadLatest.observeField("content", "updateLatestItems")
+ loadLatest.control = "RUN"
else if lib.collectionType = "livetv"
' If we have Live TV, add "On Now"
onNowRow = content.CreateChild("HomeRow")
onNowRow.title = tr("On Now")
sizeArray.Push([464, 331])
haveLiveTV = true
+ ' If we have Live TV access, load "On Now" data
+ if haveLiveTV
+ m.LoadOnNowTask.observeField("content", "updateOnNowItems")
+ m.LoadOnNowTask.control = "RUN"
+ end if
end if
end for
end if
m.top.rowItemSize = sizeArray
m.top.content = content
-
- ' Load the Continue Watching Data
- m.LoadContinueTask.observeField("content", "updateContinueItems")
- m.LoadContinueTask.control = "RUN"
-
- ' Load the Favorites Data
- m.LoadFavoritesTask.observeField("content", "updateFavoritesItems")
- m.LoadFavoritesTask.control = "RUN"
-
- ' If we have Live TV access, load "On Now" data
- if haveLiveTV
- m.LoadOnNowTask.observeField("content", "updateOnNowItems")
- m.LoadOnNowTask.control = "RUN"
- end if
end sub
sub updateHomeRows()
@@ -219,9 +237,6 @@ sub updateContinueItems()
homeRows.replaceChild(row, continueRowIndex)
end if
end if
-
- m.LoadNextUpTask.observeField("content", "updateNextUpItems")
- m.LoadNextUpTask.control = "RUN"
end sub
sub updateNextUpItems()
@@ -274,24 +289,6 @@ sub updateNextUpItems()
m.global.app_loaded = true
end if
-
- ' create task nodes for "Latest In" rows
- userConfig = m.top.userConfig
- filteredLatest = filterNodeArray(m.libraryData, "id", userConfig.LatestItemsExcludes)
- for each lib in filteredLatest
- if lib.collectionType <> "livetv" and lib.collectionType <> "boxsets" and lib.json.CollectionType <> "Program"
- loadLatest = createObject("roSGNode", "LoadItemsTask")
- loadLatest.itemsToLoad = "latest"
- loadLatest.itemId = lib.id
-
- metadata = { "title": lib.name }
- metadata.Append({ "contentType": lib.json.CollectionType })
- loadLatest.metadata = metadata
-
- loadLatest.observeField("content", "updateLatestItems")
- loadLatest.control = "RUN"
- end if
- end for
end sub
sub updateLatestItems(msg)
diff --git a/components/home/LoadItemsTask.brs b/components/home/LoadItemsTask.brs
index 3ac51aec..0d111119 100644
--- a/components/home/LoadItemsTask.brs
+++ b/components/home/LoadItemsTask.brs
@@ -30,6 +30,7 @@ sub loadItems()
params["ParentId"] = m.top.itemId
params["EnableImageTypes"] = "Primary,Backdrop,Thumb"
params["ImageTypeLimit"] = 1
+ params["EnableTotalRecordCount"] = false
resp = APIRequest(url, params)
data = getJson(resp)
@@ -53,6 +54,10 @@ sub loadItems()
params["SortOrder"] = "Descending"
params["ImageTypeLimit"] = 1
params["UserId"] = get_setting("active_user")
+ params["EnableRewatching"] = false
+ params["DisableFirstEpisode"] = false
+ params["limit"] = 24
+ params["EnableTotalRecordCount"] = false
maxDaysInNextUp = get_user_setting("ui.details.maxdaysnextup", "365")
if isValid(maxDaysInNextUp)
@@ -64,9 +69,6 @@ sub loadItems()
dateCutoff.FromSeconds(dateToday.AsSeconds() - (maxDaysInNextUp * 86400))
params["NextUpDateCutoff"] = dateCutoff.ToISOString()
- params["EnableRewatching"] = false
- params["DisableFirstEpisode"] = false
- params["limit"] = 24
end if
end if
@@ -88,6 +90,7 @@ sub loadItems()
params["SortBy"] = "DatePlayed"
params["SortOrder"] = "Descending"
params["Filters"] = "IsResumable"
+ params["EnableTotalRecordCount"] = false
resp = APIRequest(url, params)
data = getJson(resp)
@@ -109,6 +112,7 @@ sub loadItems()
params["Limit"] = 20
params["recursive"] = true
params["sortby"] = "random"
+ params["EnableTotalRecordCount"] = false
resp = APIRequest(url, params)
data = getJson(resp)
diff --git a/components/liveTv/ProgramDetails.brs b/components/liveTv/ProgramDetails.brs
index 527215ef..9ca0ee68 100644
--- a/components/liveTv/ProgramDetails.brs
+++ b/components/liveTv/ProgramDetails.brs
@@ -243,8 +243,8 @@ function getRelativeDayName(date) as string
end if
' Check for Yesterday
- todayMidnight = now.AsSeconds() - (now.AsSeconds() MOD 86400)
- dateMidnight = date.AsSeconds() - (date.AsSeconds() MOD 86400)
+ todayMidnight = now.AsSeconds() - (now.AsSeconds() mod 86400)
+ dateMidnight = date.AsSeconds() - (date.AsSeconds() mod 86400)
if todayMidnight - dateMidnight = 86400
return "yesterday"
@@ -266,8 +266,8 @@ function getDurationStringFromSeconds(seconds) as string
minutes = seconds / 60.0
if minutes > 60
- hours = (minutes - (minutes MOD 60)) / 60
- minutes = minutes MOD 60
+ hours = (minutes - (minutes mod 60)) / 60
+ minutes = minutes mod 60
end if
if hours > 0
diff --git a/components/manager/QueueManager.brs b/components/manager/QueueManager.brs
new file mode 100644
index 00000000..51da9521
--- /dev/null
+++ b/components/manager/QueueManager.brs
@@ -0,0 +1,129 @@
+sub init()
+ m.queue = []
+ m.position = 0
+end sub
+
+'
+' Clear all content from play queue
+sub clear()
+ m.queue = []
+ setPosition(0)
+end sub
+
+
+'
+' Delete item from play queue at passed index
+sub deleteAtIndex(index)
+ m.queue.Delete(index)
+end sub
+
+
+'
+' Return the number of items in the play queue
+function getCount()
+ return m.queue.count()
+end function
+
+
+'
+' Return the item currently in focus from the play queue
+function getCurrentItem()
+ return getItemByIndex(m.position)
+end function
+
+
+'
+' Return the item in the passed index from the play queue
+function getItemByIndex(index)
+ return m.queue[index]
+end function
+
+
+'
+' Returns current playback position within the queue
+function getPosition()
+ return m.position
+end function
+
+
+'
+' Move queue position back one
+sub moveBack()
+ m.position--
+end sub
+
+
+'
+' Move queue position ahead one
+sub moveForward()
+ m.position++
+end sub
+
+
+'
+' Return the current play queue
+function getQueue()
+ return m.queue
+end function
+
+
+'
+' Return item at end of play queue without removing
+function peek()
+ return m.queue.peek()
+end function
+
+
+'
+' Play items in queue
+sub playQueue()
+ nextItem = top()
+ nextItemMediaType = invalid
+
+ if isValid(nextItem?.json?.mediatype) and nextItem.json.mediatype <> ""
+ nextItemMediaType = LCase(nextItem.json.mediatype)
+ else if isValid(nextItem?.type) and nextItem.type <> ""
+ nextItemMediaType = LCase(nextItem.type)
+ end if
+
+ if not isValid(nextItemMediaType) then return
+
+ if nextItemMediaType = "audio"
+ CreateAudioPlayerView()
+ end if
+end sub
+
+
+'
+' Remove item at end of play queue
+sub pop()
+ m.queue.pop()
+end sub
+
+
+'
+' Push new items to the play queue
+sub push(newItem)
+ m.queue.push(newItem)
+end sub
+
+'
+' Set the queue position
+sub setPosition(newPosition)
+ m.position = newPosition
+end sub
+
+
+'
+' Return the fitst item in the play queue
+function top()
+ return getItemByIndex(0)
+end function
+
+
+'
+' Replace play queue with passed array
+sub set(items)
+ setPosition(0)
+ m.queue = items
+end sub
diff --git a/components/manager/QueueManager.xml b/components/manager/QueueManager.xml
new file mode 100644
index 00000000..33ee9342
--- /dev/null
+++ b/components/manager/QueueManager.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/manager/ViewCreator.brs b/components/manager/ViewCreator.brs
new file mode 100644
index 00000000..1a6ade7a
--- /dev/null
+++ b/components/manager/ViewCreator.brs
@@ -0,0 +1,6 @@
+' Play Audio
+sub CreateAudioPlayerView()
+ view = CreateObject("roSGNode", "AudioPlayerView")
+ view.observeField("state", m.port)
+ m.global.sceneManager.callFunc("pushScene", view)
+end sub
diff --git a/components/music/NowPlaying.brs b/components/music/AudioPlayerView.brs
similarity index 81%
rename from components/music/NowPlaying.brs
rename to components/music/AudioPlayerView.brs
index ecf3323e..e654436f 100644
--- a/components/music/NowPlaying.brs
+++ b/components/music/AudioPlayerView.brs
@@ -8,11 +8,8 @@ sub init()
setupDataTasks()
setupScreenSaver()
- m.currentSongIndex = 0
- m.buttonsNeedToBeLoaded = true
m.shuffleEnabled = false
m.loopMode = ""
- m.shuffleEvent = ""
m.buttonCount = m.buttons.getChildCount()
m.playReported = false
@@ -26,6 +23,9 @@ sub init()
' Write screen tracker for screensaver
WriteAsciiFile("tmp:/scene.temp", "nowplaying")
MoveFile("tmp:/scene.temp", "tmp:/scene")
+
+ loadButtons()
+ pageContentChanged()
end sub
sub onScreensaverTimeoutLoaded()
@@ -62,7 +62,7 @@ sub setupAnimationTasks()
m.screenSaverStartAnimation = m.top.FindNode("screenSaverStartAnimation")
end sub
-' Creates tasks to gather data needed to renger NowPlaying Scene and play song
+' Creates tasks to gather data needed to render Scene and play song
sub setupDataTasks()
' Load meta data
m.LoadMetaDataTask = CreateObject("roSGNode", "LoadItemsTask")
@@ -219,18 +219,25 @@ sub audioStateChanged()
' Song Finished, attempt to move to next song
if m.top.audio.state = "finished"
+ ' User has enabled single song loop, play current song again
if m.loopMode = "one"
playAction()
return
- else if m.loopMode = "all"
- m.currentSongIndex = -1
- LoadNextSong()
- return
end if
- if m.currentSongIndex < m.top.pageContent.count() - 1
+ if m.global.queueManager.callFunc("getPosition") < m.global.queueManager.callFunc("getCount") - 1
+ ' We are not at the end of the song queue, advance to next song
LoadNextSong()
else
+ ' We are at the end of the song queue
+
+ ' User has enabled loop for entire song queue, move back to first song
+ if m.loopMode = "all"
+ m.global.queueManager.callFunc("setPosition", -1)
+ LoadNextSong()
+ return
+ end if
+
' Return to previous screen
m.top.state = "finished"
end if
@@ -263,8 +270,8 @@ function previousClicked() as boolean
m.top.audio.control = "stop"
end if
- if m.currentSongIndex > 0
- m.currentSongIndex--
+ if m.global.queueManager.callFunc("getPosition") > 0
+ m.global.queueManager.callFunc("moveBack")
pageContentChanged()
end if
@@ -289,7 +296,7 @@ function loopClicked() as boolean
end function
function nextClicked() as boolean
- if m.currentSongIndex < m.top.pageContent.count() - 1
+ if m.global.queueManager.callFunc("getPosition") < m.global.queueManager.callFunc("getCount") - 1
LoadNextSong()
end if
@@ -302,7 +309,7 @@ end sub
function findCurrentSongIndex(songList) as integer
for i = 0 to songList.count() - 1
- if songList[i] = m.top.pageContent[m.currentSongIndex]
+ if songList[i].id = m.global.queueManager.callFunc("getCurrentItem").id
return i
end if
end for
@@ -318,10 +325,10 @@ function shuffleClicked() as boolean
m.shuffleIndicator.opacity = ".4"
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-on", "-off")
- m.shuffleEvent = "enabled"
- m.currentSongIndex = findCurrentSongIndex(m.originalSongList)
- m.top.pageContent = m.originalSongList
- setFieldTextValue("numberofsongs", "Track " + stri(m.currentSongIndex + 1) + "/" + stri(m.top.pageContent.count()))
+ currentSongIndex = findCurrentSongIndex(m.originalSongList)
+ m.global.queueManager.callFunc("set", m.originalSongList)
+ m.global.queueManager.callFunc("setPosition", currentSongIndex)
+ setFieldTextValue("numberofsongs", "Track " + stri(m.global.queueManager.callFunc("getPosition") + 1) + "/" + stri(m.global.queueManager.callFunc("getCount")))
return true
end if
@@ -329,14 +336,14 @@ function shuffleClicked() as boolean
m.shuffleIndicator.opacity = "1"
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-off", "-on")
- m.originalSongList = m.top.pageContent
+ m.originalSongList = m.global.queueManager.callFunc("getQueue")
- songIDArray = m.top.pageContent
+ songIDArray = m.global.queueManager.callFunc("getQueue")
' Move the currently playing song to the front of the queue
- temp = m.top.pageContent[0]
- songIDArray[0] = m.top.pageContent[m.currentSongIndex]
- songIDArray[m.currentSongIndex] = temp
+ temp = m.global.queueManager.callFunc("top")
+ songIDArray[0] = m.global.queueManager.callFunc("getCurrentItem")
+ songIDArray[m.global.queueManager.callFunc("getPosition")] = temp
for i = 1 to songIDArray.count() - 1
j = Rnd(songIDArray.count() - 1)
@@ -345,10 +352,7 @@ function shuffleClicked() as boolean
songIDArray[j] = temp
end for
- m.currentSongIndex = 0
- m.shuffleEvent = "enabled"
-
- m.top.pageContent = songIDArray
+ m.global.queueManager.callFunc("set", songIDArray)
return true
end function
@@ -360,30 +364,64 @@ sub LoadNextSong()
' Reset playPosition bar without animation
m.playPosition.width = 0
- m.currentSongIndex++
+ m.global.queueManager.callFunc("moveForward")
pageContentChanged()
end sub
' Update values on screen when page content changes
sub pageContentChanged()
- ' pageContent Changed due to shuffle event, don't update screen values
- if m.shuffleEvent = "enabled"
- m.shuffleEvent = ""
- return
- end if
' Reset buffer bar without animation
m.bufferPosition.width = 0
- m.LoadMetaDataTask.itemId = m.top.pageContent[m.currentSongIndex]
- m.LoadMetaDataTask.observeField("content", "onMetaDataLoaded")
- m.LoadMetaDataTask.control = "RUN"
+ useMetaTask = false
+ currentItem = m.global.queueManager.callFunc("getCurrentItem")
- m.LoadAudioStreamTask.itemId = m.top.pageContent[m.currentSongIndex]
+ if not isValid(currentItem.RunTimeTicks)
+ useMetaTask = true
+ end if
+
+ if not isValid(currentItem.AlbumArtist)
+ useMetaTask = true
+ end if
+
+ if not isValid(currentItem.name)
+ useMetaTask = true
+ end if
+
+ if not isValid(currentItem.Artists)
+ useMetaTask = true
+ end if
+
+ if useMetaTask
+ m.LoadMetaDataTask.itemId = currentItem.id
+ m.LoadMetaDataTask.observeField("content", "onMetaDataLoaded")
+ m.LoadMetaDataTask.control = "RUN"
+ else
+ if isValid(currentItem.ParentBackdropItemId)
+ setBackdropImage(ImageURL(currentItem.ParentBackdropItemId, "Backdrop", { "maxHeight": "720", "maxWidth": "1280" }))
+ end if
+
+ setPosterImage(ImageURL(currentItem.id, "Primary", { "maxHeight": 500, "maxWidth": 500 }))
+ setScreenTitle(currentItem)
+ setOnScreenTextValues(currentItem)
+ m.songDuration = currentItem.RunTimeTicks / 10000000.0
+ end if
+
+ m.LoadAudioStreamTask.itemId = currentItem.id
m.LoadAudioStreamTask.observeField("content", "onAudioStreamLoaded")
m.LoadAudioStreamTask.control = "RUN"
end sub
+' If we have more and 1 song to play, fade in the next and previous controls
+sub loadButtons()
+ if m.global.queueManager.callFunc("getCount") > 1
+ m.shuffleIndicator.opacity = ".4"
+ m.loopIndicator.opacity = ".4"
+ m.displayButtonsAnimation.control = "start"
+ end if
+end sub
+
sub onAudioStreamLoaded()
data = m.LoadAudioStreamTask.content[0]
m.LoadAudioStreamTask.unobserveField("content")
@@ -425,16 +463,6 @@ sub onMetaDataLoaded()
setOnScreenTextValues(data.json)
m.songDuration = data.json.RunTimeTicks / 10000000.0
-
- ' If we have more and 1 song to play, fade in the next and previous controls
- if m.buttonsNeedToBeLoaded
- if m.top.pageContent.count() > 1
- m.shuffleIndicator.opacity = ".4"
- m.loopIndicator.opacity = ".4"
- m.displayButtonsAnimation.control = "start"
- end if
- m.buttonsNeedToBeLoaded = false
- end if
end if
end sub
@@ -471,12 +499,12 @@ end sub
' Populate on screen text variables
sub setOnScreenTextValues(json)
if isValid(json)
- currentSongIndex = m.currentSongIndex
+ currentSongIndex = m.global.queueManager.callFunc("getPosition")
if m.shuffleEnabled
currentSongIndex = findCurrentSongIndex(m.originalSongList)
end if
- setFieldTextValue("numberofsongs", "Track " + stri(currentSongIndex + 1) + "/" + stri(m.top.pageContent.count()))
+ setFieldTextValue("numberofsongs", "Track " + stri(currentSongIndex + 1) + "/" + stri(m.global.queueManager.callFunc("getCount")))
setFieldTextValue("artist", json.Artists[0])
setFieldTextValue("song", json.name)
end if
@@ -511,7 +539,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
else if key = "fastforward"
return nextClicked()
else if key = "left"
- if m.top.pageContent.count() = 1 then return false
+ if m.global.queueManager.callFunc("getCount") = 1 then return false
if m.top.selectedButtonIndex > 0
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
@@ -519,7 +547,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
return true
else if key = "right"
- if m.top.pageContent.count() = 1 then return false
+ if m.global.queueManager.callFunc("getCount") = 1 then return false
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
if m.top.selectedButtonIndex < m.buttonCount - 1 then m.top.selectedButtonIndex = m.top.selectedButtonIndex + 1
@@ -554,7 +582,7 @@ sub ReportPlayback(state = "update" as string)
if m.top.audio.position = invalid then return
params = {
- "ItemId": m.top.pageContent[m.currentSongIndex],
+ "ItemId": m.global.queueManager.callFunc("getCurrentItem").id,
"PlaySessionId": m.top.audio.content.id,
"PositionTicks": int(m.top.audio.position) * 10000000&, 'Ensure a LongInteger is used
"IsPaused": (m.top.audio.state = "paused")
diff --git a/components/music/NowPlaying.xml b/components/music/AudioPlayerView.xml
similarity index 97%
rename from components/music/NowPlaying.xml
rename to components/music/AudioPlayerView.xml
index a6417e41..bf5d8b27 100644
--- a/components/music/NowPlaying.xml
+++ b/components/music/AudioPlayerView.xml
@@ -1,5 +1,5 @@
-
+
@@ -8,7 +8,7 @@
-
+
@@ -77,7 +77,7 @@
-
+
@@ -119,13 +119,12 @@
-
-
+
diff --git a/components/settings/settings.brs b/components/settings/settings.brs
index f02629d7..8f637292 100644
--- a/components/settings/settings.brs
+++ b/components/settings/settings.brs
@@ -13,6 +13,8 @@ sub init()
m.boolSetting = m.top.findNode("boolSetting")
m.integerSetting = m.top.findNode("integerSetting")
+ m.radioSetting = m.top.findNode("radioSetting")
+
m.integerSetting.observeField("submit", "onKeyGridSubmit")
m.integerSetting.observeField("escape", "onKeyGridEscape")
@@ -21,6 +23,7 @@ sub init()
m.settingsMenu.observeField("itemSelected", "settingSelected")
m.boolSetting.observeField("checkedItem", "boolSettingChanged")
+ m.radioSetting.observeField("checkedItem", "radioSettingChanged")
' Load Configuration Tree
m.configTree = GetConfigTree()
@@ -40,7 +43,6 @@ sub onKeyGridEscape()
end sub
sub LoadMenu(configSection)
-
if configSection.children = invalid
' Load parent menu
m.userLocation.pop()
@@ -81,6 +83,7 @@ sub settingFocused()
' Hide Settings
m.boolSetting.visible = false
m.integerSetting.visible = false
+ m.radioSetting.visible = false
if selectedSetting.type = invalid
return
@@ -99,6 +102,26 @@ sub settingFocused()
m.integerSetting.text = integerValue
end if
m.integerSetting.visible = true
+ else if LCase(selectedSetting.type) = "radio"
+
+ selectedValue = get_user_setting(selectedSetting.settingName, selectedSetting.default)
+
+ radioContent = CreateObject("roSGNode", "ContentNode")
+
+ itemIndex = 0
+ for each item in m.userLocation.peek().children[m.settingsMenu.itemFocused].options
+ listItem = radioContent.CreateChild("ContentNode")
+ listItem.title = tr(item.title)
+ listItem.id = item.id
+ if selectedValue = item.id
+ m.radioSetting.checkedItem = itemIndex
+ end if
+ itemIndex++
+ end for
+
+ m.radioSetting.content = radioContent
+
+ m.radioSetting.visible = true
else
print "Unknown setting type " + selectedSetting.type
end if
@@ -117,6 +140,9 @@ sub settingSelected()
if selectedItem.type = "integer"
m.integerSetting.setFocus(true)
end if
+ if (selectedItem.type) = "radio"
+ m.radioSetting.setFocus(true)
+ end if
else if selectedItem.children <> invalid and selectedItem.children.Count() > 0 ' Show sub menu
LoadMenu(selectedItem)
m.settingsMenu.setFocus(true)
@@ -139,9 +165,13 @@ sub boolSettingChanged()
else
set_user_setting(selectedSetting.settingName, "false")
end if
-
end sub
+sub radioSettingChanged()
+ if m.radioSetting.focusedChild = invalid then return
+ selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]
+ set_user_setting(selectedSetting.settingName, m.radioSetting.content.getChild(m.radioSetting.checkedItem).id)
+end sub
function onKeyEvent(key as string, press as boolean) as boolean
if not press then return false
@@ -152,6 +182,9 @@ function onKeyEvent(key as string, press as boolean) as boolean
else if (key = "back" or key = "left") and m.settingDetail.focusedChild <> invalid
m.settingsMenu.setFocus(true)
return true
+ else if (key = "back" or key = "left") and m.radioSetting.hasFocus()
+ m.settingsMenu.setFocus(true)
+ return true
end if
if key = "right"
diff --git a/components/settings/settings.xml b/components/settings/settings.xml
index d114b0db..15ab0c7f 100644
--- a/components/settings/settings.xml
+++ b/components/settings/settings.xml
@@ -31,6 +31,7 @@
+
diff --git a/components/tvshows/TVEpisodes.brs b/components/tvshows/TVEpisodes.brs
index 915aeb97..fb69f9eb 100644
--- a/components/tvshows/TVEpisodes.brs
+++ b/components/tvshows/TVEpisodes.brs
@@ -6,6 +6,8 @@ sub init()
m.Random = m.top.findNode("Random")
m.tvEpisodeRow = m.top.findNode("tvEpisodeRow")
+ m.unplayedCount = m.top.findNode("unplayedCount")
+ m.unplayedEpisodeCount = m.top.findNode("unplayedEpisodeCount")
m.rows.observeField("doneLoading", "updateSeason")
end sub
@@ -15,6 +17,13 @@ sub setSeasonLoading()
end sub
sub updateSeason()
+ if m.top.seasonData?.UserData?.UnplayedItemCount <> invalid
+ if m.top.seasonData.UserData.UnplayedItemCount > 0
+ m.unplayedCount.visible = true
+ m.unplayedEpisodeCount.text = m.top.seasonData.UserData.UnplayedItemCount
+ end if
+ end if
+
imgParams = { "maxHeight": 450, "maxWidth": 300 }
m.poster.uri = ImageURL(m.top.seasonData.Id, "Primary", imgParams)
m.Random.visible = true
@@ -54,8 +63,10 @@ function onKeyEvent(key as string, press as boolean) as boolean
end if
if press and key = "play" or proceed = true
+ m.top.lastFocus = focusedChild
itemToPlay = focusedChild.content.getChild(focusedChild.rowItemFocused[0]).getChild(0)
if itemToPlay <> invalid and itemToPlay.id <> ""
+ itemToPlay.type = "Episode"
m.top.quickPlayNode = itemToPlay
end if
handled = true
diff --git a/components/tvshows/TVEpisodes.xml b/components/tvshows/TVEpisodes.xml
index f1522694..243e697e 100644
--- a/components/tvshows/TVEpisodes.xml
+++ b/components/tvshows/TVEpisodes.xml
@@ -1,7 +1,11 @@
-
+
+
+
+
+
diff --git a/components/tvshows/TVListDetails.brs b/components/tvshows/TVListDetails.brs
index f886b23d..f92724e9 100644
--- a/components/tvshows/TVListDetails.brs
+++ b/components/tvshows/TVListDetails.brs
@@ -8,6 +8,11 @@ sub init()
m.rating = m.top.findnode("rating")
m.infoBar = m.top.findnode("infoBar")
+ m.progressBackground = m.top.findNode("progressBackground")
+ m.progressBar = m.top.findnode("progressBar")
+ m.playedIndicator = m.top.findNode("playedIndicator")
+ m.checkmark = m.top.findNode("checkmark")
+ m.checkmark.font.size = 35
end sub
sub itemContentChanged()
@@ -52,11 +57,30 @@ sub itemContentChanged()
end if
end if
- if isValid(itemData.communityRating)
- m.top.findNode("star").visible = true
- m.top.findNode("communityRating").text = str(int(itemData.communityRating * 10) / 10)
+ if get_user_setting("ui.tvshows.disableCommunityRating") = "false"
+ if isValid(itemData.communityRating)
+ m.top.findNode("star").visible = true
+ m.top.findNode("communityRating").text = str(int(itemData.communityRating * 10) / 10)
+ else
+ m.top.findNode("star").visible = false
+ end if
else
- m.top.findNode("star").visible = false
+ m.rating.visible = false
+ m.infoBar.itemSpacings = [20, -25, 20, 20]
+ end if
+
+ ' Add checkmark in corner (if applicable)
+ if isValid(itemData?.UserData?.Played) and itemData.UserData.Played = true
+ m.playedIndicator.visible = true
+ end if
+
+ ' Add progress bar on bottom (if applicable)
+ if isValid(itemData?.UserData?.PlayedPercentage) and itemData?.UserData?.PlayedPercentage > 0
+ m.progressBackground.width = m.poster.width
+ m.progressBackground.visible = true
+ progressWidthInPixels = int(m.progressBackground.width * itemData.UserData.PlayedPercentage / 100)
+ m.progressBar.width = progressWidthInPixels
+ m.progressBar.visible = true
end if
videoIdx = invalid
diff --git a/components/tvshows/TVListDetails.xml b/components/tvshows/TVListDetails.xml
index 4cb79d61..aaf504de 100644
--- a/components/tvshows/TVListDetails.xml
+++ b/components/tvshows/TVListDetails.xml
@@ -2,8 +2,15 @@
-
-
+
+
+
+
+
+
+
+
+
diff --git a/components/tvshows/TVShowDetails.brs b/components/tvshows/TVShowDetails.brs
index 0c538671..fc39755b 100644
--- a/components/tvshows/TVShowDetails.brs
+++ b/components/tvshows/TVShowDetails.brs
@@ -3,6 +3,8 @@ sub init()
main = m.top.findNode("toplevel")
main.translation = [96, 175]
m.extrasSlider = m.top.findNode("tvSeasonExtras")
+ m.unplayedCount = m.top.findNode("unplayedCount")
+ m.unplayedEpisodeCount = m.top.findNode("unplayedEpisodeCount")
'm.extrasSlider.translation = [30,1014]
m.extrasSlider.visible = true
end sub
@@ -13,6 +15,13 @@ sub itemContentChanged()
item = m.top.itemContent
itemData = item.json
+ if itemData?.UserData?.UnplayedItemCount <> invalid
+ if itemData.UserData.UnplayedItemCount > 0
+ m.unplayedCount.visible = true
+ m.unplayedEpisodeCount.text = itemData.UserData.UnplayedItemCount
+ end if
+ end if
+
m.top.findNode("tvshowPoster").uri = m.top.itemContent.posterURL
' Handle all "As Is" fields
diff --git a/components/tvshows/TVShowDetails.xml b/components/tvshows/TVShowDetails.xml
index 199210e8..7bdc7d8b 100644
--- a/components/tvshows/TVShowDetails.xml
+++ b/components/tvshows/TVShowDetails.xml
@@ -1,9 +1,13 @@
-
-
-
+
+
+
+
+
+
+
diff --git a/images/icons/musicFolder.png b/images/icons/musicFolder.png
new file mode 100644
index 00000000..5c2272e2
Binary files /dev/null and b/images/icons/musicFolder.png differ
diff --git a/locale/cs/translations.ts b/locale/cs/translations.ts
index 67806c93..13e7456f 100644
--- a/locale/cs/translations.ts
+++ b/locale/cs/translations.ts
@@ -3656,5 +3656,737 @@
Uložit přihlašovací údaje?
+
+
+ K tomuto interpretovi nebyly nalezeny žádné skladby ani alba
+ Popup message when we find no audio data for an artist
+
+
+
+ Pouze textové titulky
+ Name of a setting - should we hide subtitles that might transcode
+
+
+
+ Zobrazit pouze textové titulky pro minimalizaci překódování.
+ Description of a setting - should we hide subtitles that might transcode
+
+
+
+ Vysíláno
+ Aired date label
+
+
+
+ Audio kanály
+
+
+
+ Úroveň
+ Video profile level
+
+
+
+ Datový tok
+ Video streaming bit rate
+
+
+ Name or Title field of media item
+
+ Název
+
+
+
+ Hodnocení IMDb
+
+
+
+ Datum přehrání
+
+
+
+ Délka
+
+
+
+ Skončilo v
+ (Past Tense) For defining time when a program will ended (e.g. Ended at 08:00)
+
+
+
+ Nepodařilo se získat informace o přehrávání
+ Dialog Title: Received error from server when trying to get information about the selected item for playback
+
+
+
+ Přejít k sérii
+ Continue Watching Popup Menu - Navigate to the Season Page
+
+
+
+ Můžete hledat názvy, osoby, kanály živého vysílání a mnohem více
+ Help text in search results
+
+
+
+ Rychle připojit
+
+
+
+ Zde je Váš kód pro rychlé připojení:
+
+
+
+ (Dialog se automaticky zavře)
+
+
+
+ vše
+ all will reset the searchTerm so all data will be availible
+
+
+
+ Slideshow zapnuto
+
+
+
+ Náhodné zapnout
+
+
+
+ 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).
+ Description for option in Setting Screen
+
+
+
+ Skrýt text sloganu na stránce s podrobnostmi.
+
+
+
+ Rozmazat neshlédnuté epizody
+ Option Title in user setting screen
+
+
+
+ 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.
+ Description for option in Setting Screen
+
+
+
+ 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.
+ Settings Menu - Description for option
+
+
+
+ Skrýt všechny hodiny v Jellyfinu. Aby se změna projevila, je potřeba zavřít a znovu otevřít Jellyfin.
+ Settings Menu - Description for option
+
+
+
+ Zadejte název serveru nebo IP adresu
+ Title of KeyboardDialog when manually entering a server URL
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Tato %1 neobsahuje žádné položky
+
+
+
+ Datum přidání
+
+
+
+ Rodičovské hodnocení
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Pohled
+
+
+
+ Narozen
+
+
+
+ Úmrtí
+
+
+
+ Obsazení & štáb
+
+
+
+ Úterý
+ Day of Week
+
+
+
+ Při přehrávání této položky došlo k chybě. Server neposkytl požadovaná data pro překódování.
+ Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url
+
+
+
+ **EXPERIMENTÁLNÍ** Podpora přímého přehrávání obsahu AV1, pokud to toto zařízení Roku podporuje.
+ Settings Menu - Description for option
+
+
+
+ přímý
+
+
+
+ Vždy zobrazovat názvy pod obrázky plakátů. (Pokud je zakázáno, název se zobrazí pouze pod zvýrazněnou položkou).
+ Description for option in Setting Screen
+
+
+
+ Skrýt hodiny
+ Option Title in user setting screen
+
+
+
+ Dříve než selže překódování pokusit se o přímé přehrání H.264 média s nepodporovanými úrovněmi profilu.
+ Settings Menu - Description for option
+
+
+
+ Uložit přihlašovací údaje?
+
+
+
+ Datum vydání
+
+
+
+ Dříve než selže překódování pokusit se o přímé přehrání HEVC média s nepodporovanými úrovněmi profilu.
+ Settings Menu - Description for option
+
+
+
+ Možností domovské stránky.
+ Description for Home Page user settings.
+
+
+
+ Nastavení maximálního počtu dní, pro setrvání pořadu v seznamu "Další díly", aniž by byl zhlédnut.
+ Settings Menu - Description for option
+
+
+
+ Slideshow vypnuto
+
+
+
+ Podpora přímého přehrávání obsahu MPEG-4. Toto může být nutné deaktivovat pro přehrávání videí kódovaných v DIVX.
+ Settings Menu - Description for option
+
+
+
+ Podpora MPEG-4
+ Settings Menu - Title for option
+
+
+
+ Důvod
+
+
+
+ Informace o překódování
+
+
+
+ Režim Cinema
+ Settings Menu - Title for option
+
+
+
+ Použít Splashscreen jako pozadí domovské stránky
+ Option Title in user setting screen
+
+
+
+ Honocení kritiků
+
+
+
+ Více podobných
+
+
+
+ Nahrávat
+
+
+
+ Přehrávání
+ Title for Playback section in user setting screen.
+
+
+
+ Uživatelské prostředí
+ Title for User Interface section in user setting screen.
+
+
+
+ Povoleno
+
+
+
+ Studia
+
+
+
+ Věk
+
+
+
+ Nyní
+
+
+
+ Smazat uložené
+
+
+
+ Sítě
+
+
+
+ Počet přehrání
+
+
+
+ Pro zavření stiskni 'OK'
+
+
+
+ Speciální funkce
+
+
+
+ Další části
+ Additional parts of a video
+
+
+
+ FIlmy
+
+
+
+ Začalo
+ (Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00)
+
+
+
+ Začíná v
+ (Future Tense) For defining time when a program will start today (e.g. Starts at 08:00)
+
+
+
+ Začíná
+ (Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00)
+
+
+
+ Kanály
+ Menu option for showing Live TV Channel List
+
+
+
+ Programový průvodce
+ Menu option for showing Live TV Guide / Schedule
+
+
+
+ Nahrávat řady
+
+
+
+ Nenalezeno
+ Title of message box when the requested content is not found on the server
+
+
+
+ Neznámý
+ Title for a cast member for which we have no information for
+
+
+
+ Vyberte server Jellyfin z místní sítě:
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ Podpora MPEG-2
+ Settings Menu - Title for option
+
+
+
+ Podpora přímého přehrávání obsahu MPEG-2 (např. živé TV). To zabrání překódování obsahu MPEG-2, ale využívá podstatně větší šířku pásma.
+ Settings Menu - Description for option
+
+
+
+ Podpora AV1
+ Settings Menu - Title for option
+
+
+
+ Mřížka s médii
+ UI -> Media Grid section in user setting screen.
+
+
+
+ Názvy položek
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Volby pro mřížku s médii.
+
+
+
+ Počet položek
+ UI -> Media Grid -> Item Count in user setting screen.
+
+
+
+ Zobrazit počet položek v knihovně a ukazatel označených položek.
+ Description for option in Setting Screen
+
+
+
+ Označit jako shlédnuté
+ Button Text - When pressed, marks item as Warched
+
+
+
+ Nastavit jako oblíbené
+ Button Text - When pressed, sets item as Favorite
+
+
+
+ Přejít k epizodě
+ Continue Watching Popup Menu - Navigate to the Episode Detail Page
+
+
+
+ K hledání použít hlasové ovládání
+ Help text in search voice text box
+
+
+
+ Hledat teď
+ Help text in search Box
+
+
+
+ Při ověřování přes rychlé připojení se vyskytla chyba.
+
+
+
+ Pořady
+
+
+
+ Návrat nahoru
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Možnosti pro stránky s podrobnostmi.
+ Description for Details page user settings.
+
+
+
+ Skrýt slogany
+ Option Title in user setting screen
+
+
+
+ Předvolby pro TV pořady.
+ Description for TV Shows user settings.
+
+
+
+ Pokud je povoleno, obrázky nezobrazených epizod budou zobrazeny rozmazaně.
+
+
+
+ Spořič obrazovky
+
+
+
+ Možnosti spořiče obrazovky Jellyfin.
+ Description for Screensaver user settings.
+
+
+
+ Použít Splashscreen jako pozadí spořiče obrazovky
+ Option Title in user setting screen
+
+
+
+ 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.
+
+
+
+ Prvky vzhledu
+
+
+
+ Možnosti, které mění vzhled Jellyfin.
+ Description for Design Elements user settings.
+
+
+
+ Další epizoda
+
+
+
+ Přehrát trailer
+
+
+
+ Přímé přehrávání nepodporovaných úrovní profilu H.264
+ Settings Menu - Title for option
+
+
+
+ Přímé přehrání nepodporovaných úrovní profilu HEVC
+ Settings Menu - Title for option
+
+
+
+ Nastavení, která se týkají přehrávání, podporovanému kodeku a typům médií.
+
+
+
+ Nastavení související se vzhledem aplikace.
+
+
+
+ Domovská stránka
+
+
+
+ Maximum dní pro další díly
+ Option Title in user setting screen
+
+
+
+ Celkový datový tok
+
+
+
+ Informace o přehrávání
+
+
+
+ Audio kodek
+
+
+
+ Informace o streamu
+
+
+
+ Kodek
+
+
+
+ Tag kodeku
+
+
+
+ Kontejner
+ Video streaming container
+
+
+
+ Velikost
+ Video size
+
+
+
+ Typ rozsahu videa
+
+
+
+ Formát pixelu
+ Video pixel format
+
+
+
+ ŠxV
+ Video width x height
+
+
+
+ Slideshow obnoveno
+
+
+
+ Slideshow pozastaveno
+
+
+
+ Náhodné vypnout
+
+
+
+ %1 z %2
+ Item position and count. %1 = current item. %2 = total number of items
+
+
+
+ Přejít k seriálům
+ Continue Watching Popup Menu - Navigate to the Series Detail Page
+
+
+
+ Stránka s podrobnostmi
+
+
+
+ Video kodek
+
+
+
+ Verze
+
+
+
+ …nebo zadejte URL serveru ručně:
+ Instructions on initial app launch when the user is asked to manually enter a server URL
+
+
+
+ Požadovaný obsah na serveru neexistuje
+ Content of message box when the requested content is not found on the server
+
+
+
+ Zavřít
+
+
+ Title of Tab for options to sort library content
+
+ Třídit
+
+
+ Title of Tab for options to filter library content
+
+ Filtr
+
+
+
+ Čtvrtek
+ Day of Week
+
+
+
+ Pátek
+ Day of Week
+
+
+
+ Živě
+ If TV Show is being broadcast live (not pre-recorded)
+
+
+
+ Skončilo v
+ (Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00)
+
+
+
+ Opakovat
+ If TV Shows has previously been broadcasted
+
+
+
+ Připojování k serveru
+ Message to display to user while client is attempting to connect to the server
+
+
+
+ Zakázáno
+
+
+
+ Zrušit nahrávání sérií
+
+
+
+ Zrušit nahrávání
+
+
+
+ Zobrazit kanál
+
+
+
+ Neděle
+ Day of Week
+
+
+
+ Začátek v
+ (Past Tense) For defining time when a program started today (e.g. Started at 08:00)
+
+
+
+ Sobota
+ Day of Week
+
+
+
+ Středa
+ Day of Week
+
+
+
+ Pondělí
+ Day of Week
+
+
+
+ TV pořady
+
+
+
+ dnes
+ Current day
+
+
+
+ včera
+ Previous day
+
+
+
+ zítra
+ Next day
+
+
+
+ Podpora přímého přehrávání obsahu MPEG-4. Toto může být nutné deaktivovat pro přehrávání videí kódovaných v DIVX.
+ Settings Menu - Description for option
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Smazat uložené
+
+
+
+ Uložit přihlašovací údaje?
+
diff --git a/locale/de_DE/translations.ts b/locale/de_DE/translations.ts
index 19681c3c..b3a18909 100644
--- a/locale/de_DE/translations.ts
+++ b/locale/de_DE/translations.ts
@@ -8436,5 +8436,1435 @@
Gespeicherte löschen
+
+
+ Server wechseln
+
+
+
+ Zugangsdaten speichern?
+
+
+
+ Fehler beim Abrufen des Inhaltes
+ Dialog title when unable to load Content from Server
+
+
+
+ Fehler bei der Wiedergabe
+ Dialog title when error occurs during playback
+
+
+
+ Es ist ein Fehler beim Abrufen der Daten vom Server aufgetreten.
+ Dialog detail when unable to load Content from Server
+
+
+
+ Bei der Wiedergabe dieses Elements ist ein Fehler aufgetreten.
+ Dialog detail when error occurs during playback
+
+
+
+ Lade Daten des Kanals
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Dieser %1 enthält keine Dateien
+
+
+
+ Kritikerbewertung
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Übersicht
+
+
+ Title of Tab for options to filter library content
+
+ Filter
+
+
+
+ Gestorben am
+
+
+ Name or Title field of media item
+
+ Name
+
+
+
+ Besetzung & Mitwirkende
+
+
+
+ 'OK' klicken zum Schließen
+
+
+
+ Dienstag
+ Day of Week
+
+
+
+ Alter
+
+
+
+ Ausloggen
+
+
+
+ Gespeicherte löschen
+
+
+
+ Jetzt verfügbar
+
+
+
+ Fehler beim Laden der Kanalinformationen
+
+
+
+ Ähnliches
+
+
+
+ Kanaldaten können nicht vom Server geladen werden
+
+
+
+ Veröffentlichungsdatum
+
+
+ Title of Tab for options to sort library content
+
+ Sortierung
+
+
+
+ Geboren am
+
+
+
+ Spezialbesetzung
+
+
+
+ Zusätzliche Inhalte
+ Additional parts of a video
+
+
+
+ Gestern
+ Previous day
+
+
+
+ Heute
+ Current day
+
+
+
+ Morgen
+ Next day
+
+
+
+ Sonntag
+ Day of Week
+
+
+
+ Montag
+ Day of Week
+
+
+
+ Donnerstag
+ Day of Week
+
+
+
+ Samstag
+ Day of Week
+
+
+
+ Gestartet um
+ (Past Tense) For defining time when a program started today (e.g. Started at 08:00)
+
+
+
+ Freitag
+ Day of Week
+
+
+
+ Filme
+
+
+
+ Laufzeit
+
+
+
+ Altersfreigabe
+
+
+
+ IMDb Bewertung
+
+
+
+ Wiedergabezähler
+
+
+
+ Serien
+
+
+
+ Abgespielt am
+
+
+
+ Hinzugefügt am
+
+
+
+ Mittwoch
+ Day of Week
+
+
+
+ Live
+ If TV Show is being broadcast live (not pre-recorded)
+
+
+
+ Wiederholung
+ If TV Shows has previously been broadcasted
+
+
+
+ Sender
+ Menu option for showing Live TV Channel List
+
+
+
+ Kanal anschauen
+
+
+
+ Aufnehmen
+
+
+
+ Serie aufnehmen
+
+
+
+ Aufnahme abbrechen
+
+
+
+ Schließen
+
+
+
+ Nicht gefunden
+ Title of message box when the requested content is not found on the server
+
+
+
+ Der gewünschte Inhalt exisitiert nicht auf dem Server
+ Content of message box when the requested content is not found on the server
+
+
+
+ Serien-Aufnahme abbrechen
+
+
+
+ Gestartet
+ (Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00)
+
+
+
+ Startet um
+ (Future Tense) For defining time when a program will start today (e.g. Starts at 08:00)
+
+
+
+ Startet
+ (Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00)
+
+
+
+ Endete
+ (Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00)
+
+
+
+ TV Programm
+ Menu option for showing Live TV Guide / Schedule
+
+
+
+ Verbinde zum Server
+ Message to display to user while client is attempting to connect to the server
+
+
+
+ Unbekannt
+ Title for a cast member for which we have no information for
+
+
+
+ Geben Sie den Servernamen oder die IP Adresse ein
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ Wählen Sie einen verfügbaren Jellyfin Server aus ihrem Lokalen Netzwerk aus:
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ Endet um
+ (Past Tense) For defining time when a program will ended (e.g. Ended at 08:00)
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ %1 beinhaltet keine Elemente
+
+
+
+ Laufzeit
+
+
+
+ Lösche Gespeicherte
+
+
+
+ Kanaldaten können nicht vom Server geladen werden
+
+
+
+ Veröffentlichungsdatum
+
+
+
+ Anmeldedaten speichern?
+
+
+
+ Fehler beim laden des Inhaltes vom Server
+ Dialog title when unable to load Content from Server
+
+
+
+ Laden des Inhalts nicht möglich
+ Dialog detail when unable to load Content from Server
+
+
+
+ Fehler bei der Wiedergabe
+ Dialog detail when error occurs during playback
+
+
+
+ Lade Kanaldaten
+
+
+
+ Fehler beim Laden der Kanaldaten
+
+
+ Name or Title field of media item
+
+ Name
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Übersicht
+
+
+
+ Altersfreigabe
+
+
+
+ IMDb Bewertung
+
+
+
+ Wiedergabeanzahl
+
+
+
+ Datum hinzugefügt
+
+
+
+ heute
+ Current day
+
+
+
+ Filme (Präsentation)
+ Movie library view option
+
+
+
+ Laufzeit
+
+
+
+ Fehler beim Laden der Kanaldaten
+
+
+
+ Abmelden
+
+
+
+ Gespeicherte löschen
+
+
+
+ Jetzt live
+
+
+
+ Ähnliches
+
+
+
+ Ein Fehler ist beim Abspielen des Gegenstands aufgetreten.
+ Dialog detail when error occurs during playback
+
+
+
+ Lade Kanaldaten
+
+
+
+ Kanaldaten können nicht vom Server geladen werden
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Diese(s) %1 enthält keine Gegenstände
+
+
+
+ Filme (Raster)
+ Movie library view option
+
+
+
+ Veröffentlichungsdatum
+
+
+
+ Extras
+
+
+
+ gestern
+ Previous day
+
+
+
+ morgen
+ Next day
+
+
+
+ Server wechseln
+
+
+
+ Logindaten speichern?
+
+
+
+ Fehler beim Abrufen des Inhalts
+ Dialog title when unable to load Content from Server
+
+
+
+ Fehler während des Abspielens
+ Dialog title when error occurs during playback
+
+
+
+ Ein Fehler ist beim Aufrufen der Daten für diesen Gegenstand vom Server aufgetreten.
+ Dialog detail when unable to load Content from Server
+
+
+ Name or Title field of media item
+
+ Name
+
+
+
+ Kritikerbewertung
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Ansicht
+
+
+ Title of Tab for options to sort library content
+
+ Sortierung
+
+
+ Title of Tab for options to filter library content
+
+ Filter
+
+
+
+ Geboren am
+
+
+
+ Gestorben am
+
+
+
+ Alter
+
+
+
+ Besetzung & Mitwirkende
+
+
+
+ 'OK' zum Schließen klicken
+
+
+
+ Zusätzliche Inhalte
+ Additional parts of a video
+
+
+
+ Sonntag
+ Day of Week
+
+
+
+ Montag
+ Day of Week
+
+
+
+ Filme
+
+
+
+ Altersfreigabe
+
+
+
+ IMDb-Bewertung
+
+
+
+ Wiedergabeanzahl
+
+
+
+ Serien
+
+
+
+ Abgespielt am
+
+
+
+ Datum hinzugefügt
+
+
+
+ Gespeicherte löschen
+
+
+
+ Ein Fehler ist beim Aufrufen der Daten für diesen Gegenstand vom Server aufgetreten.
+ Dialog detail when unable to load Content from Server
+
+
+
+ heute
+ Current day
+
+
+
+ Sonntag
+ Day of Week
+
+
+
+ Samstag
+ Day of Week
+
+
+
+ Schließen
+
+
+
+ Nicht gefunden
+ Title of message box when the requested content is not found on the server
+
+
+
+ Wählen Sie einen verfügbaren Jellyfin Server aus ihrem Lokalen Netzwerk aus:
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ Bei der Wiedergabe dieses Elements ist ein Fehler aufgetreten. Der Server hat die erforderlichen Transkodierungsdaten nicht bereitgestellt.
+ Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url
+
+
+
+ Logindaten speichern?
+
+
+
+ Fehler beim Abrufen des Inhalts
+ Dialog title when unable to load Content from Server
+
+
+
+ Fehler während des Abspielens
+ Dialog title when error occurs during playback
+
+
+
+ Fehler beim Laden der Kanaldaten
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Ansicht
+
+
+ Title of Tab for options to sort library content
+
+ Sortierung
+
+
+ Title of Tab for options to filter library content
+
+ Filter
+
+
+
+ Laufzeit
+
+
+
+ Geboren am
+
+
+
+ Filme (Präsentation)
+
+
+
+ Abmelden
+
+
+
+ Jetzt live
+
+
+
+ Ähnliches
+
+
+
+ Sollte der Server nicht aufgelistet sein, fügen Sie bitte die URL manuell ein:
+ Instructions on initial app launch when the user is asked to manually enter a server URL
+
+
+
+ Wiedergabe
+ Title for Playback section in user setting screen.
+
+
+
+ Ein Fehler ist beim Abspielen des Gegenstands aufgetreten.
+ Dialog detail when error occurs during playback
+
+
+
+ Lade Kanaldaten
+
+
+
+ Kanaldaten können nicht vom Server geladen werden
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Diese(s) %1 enthält keine Gegenstände
+
+
+
+ Filme (Raster)
+
+
+
+ Dienstag
+ Day of Week
+
+
+
+ Gestartet um
+ (Past Tense) For defining time when a program started today (e.g. Started at 08:00)
+
+
+
+ Version
+
+
+
+ Veröffentlichungsdatum
+
+
+
+ Extras
+
+
+
+ gestern
+ Previous day
+
+
+
+ morgen
+ Next day
+
+
+
+ Live
+ If TV Show is being broadcast live (not pre-recorded)
+
+
+
+ Fehler beim Einsehen der Abspielinformation
+ Dialog Title: Received error from server when trying to get information about the selected item for playback
+
+
+
+ Server wechseln
+
+
+ Name or Title field of media item
+
+ Name
+
+
+
+ Kritikerbewertung
+
+
+
+ Gestorben am
+
+
+
+ Alter
+
+
+
+ Besetzung & Mitwirkende
+
+
+
+ 'OK' zum Schließen klicken
+
+
+
+ Zusätzliche Inhalte
+ Additional parts of a video
+
+
+
+ Montag
+ Day of Week
+
+
+
+ Donnerstag
+ Day of Week
+
+
+
+ Gestartet
+ (Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00)
+
+
+
+ Endete
+ (Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00)
+
+
+
+ Sender
+ Menu option for showing Live TV Channel List
+
+
+
+ Kanal anschauen
+
+
+
+ Wiederholung
+ If TV Shows has previously been broadcasted
+
+
+
+ Serie aufnehmen
+
+
+
+ Aufnahme abbrechen
+
+
+
+ Der gewünschte Inhalt exisitiert nicht auf dem Server
+ Content of message box when the requested content is not found on the server
+
+
+
+ Serien-Aufnahme abbrechen
+
+
+
+ Freitag
+ Day of Week
+
+
+
+ Filme
+
+
+
+ Altersfreigabe
+
+
+
+ IMDb-Bewertung
+
+
+
+ Wiedergabeanzahl
+
+
+
+ Serien
+
+
+
+ Startet um
+ (Future Tense) For defining time when a program will start today (e.g. Starts at 08:00)
+
+
+
+ TV Programm
+ Menu option for showing Live TV Guide / Schedule
+
+
+
+ Verbinde zum Server
+ Message to display to user while client is attempting to connect to the server
+
+
+
+ Unbekannt
+ Title for a cast member for which we have no information for
+
+
+
+ Geben Sie den Servernamen oder die IP Adresse ein
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ Aufnehmen
+
+
+
+ Startet
+ (Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00)
+
+
+
+ Abgespielt am
+
+
+
+ Endet um
+ (Past Tense) For defining time when a program will ended (e.g. Ended at 08:00)
+
+
+
+ Hinzugefügt am
+
+
+
+ Mittwoch
+ Day of Week
+
+
+
+ Aktiviere oder deaktiviere Direkte Wiedergabe für optionale Codecs
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ MPEG-2
+ Name of codec used in settings menu
+
+
+
+ MPEG-4
+ Name of codec used in settings menu
+
+
+
+ Unterstütze Direkte Wiedergabe von MPEG-2-Inhalten (z. B. Live-TV). Dies verhindert die Transkodierung von MPEG-2-Inhalten, verbraucht aber deutlich mehr Bandbreite.
+ Settings Menu - Description for option
+
+
+
+ Codec Unterstützung
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Unterstützt direktes Abspielen von MPEG-4 Inhalten. Das muss ggf. deaktiviert werden um DIVX-Dateien abzuspielen.
+ Settings Menu - Description for option
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Titel werden immer unter den Posterbildern angezeigt. (Wenn deaktiviert, wird der Titel nur unter dem hervorgehobenen Element angezeigt).
+ Description for option in Setting Screen
+
+
+
+ Anzahl der Elemente in der Bibliothek und im Index des gewählten Elements anzeigen.
+ Description for option in Setting Screen
+
+
+
+ Springe zur Serie
+ Continue Watching Popup Menu - Navigate to the Series Detail Page
+
+
+
+ Sie können nach Titeln, Personen, Live-TV-Kanälen und noch mehr suchen
+ Help text in search results
+
+
+
+ Zurück nach oben
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Detail-Seiten Einstellungen.
+ Description for Details page user settings.
+
+
+
+ Splashscreen als Bildschirmschoner verwenden
+ Option Title in user setting screen
+
+
+
+ Schnellverbindung
+
+
+
+ Aktiviert
+
+
+
+ Als Favorit festlegen
+ Button Text - When pressed, sets item as Favorite
+
+
+
+ Springe zur Staffel
+ Continue Watching Popup Menu - Navigate to the Season Page
+
+
+
+ Benutze Sprachfernbedienung zum Suchen
+ Help text in search voice text box
+
+
+
+ Jetzt suchen
+ Help text in search Box
+
+
+
+ %1 von %2
+ Item position and count. %1 = current item. %2 = total number of items
+
+
+
+ Netzwerke
+
+
+
+ Studios
+
+
+
+ Bei der Authentifizierung über Quick Connect ist ein Fehler aufgetreten.
+
+
+
+ Serien
+
+
+
+ Detailseite
+
+
+
+ Markierungen verstecken
+ Option Title in user setting screen
+
+
+
+ Markierungs-Text auf der Detailseite verstecken.
+
+
+
+ Ungesehene Folgen verpixeln
+ Option Title in user setting screen
+
+
+
+ Details für einzelne Staffeln überspringen
+ Settings Menu - Title for option
+
+
+
+ Wenn diese Option aktiviert ist, werden Bilder von nicht angesehenen Folgen unscharf dargestellt.
+
+
+
+ Bildschirmschoner
+
+
+
+ Einstellungen für Jellyfins Bildschirmschoner.
+ Description for Screensaver user settings.
+
+
+
+ **EXPERIMENTELL** Unterstützt direktes Abspielen von AV1 Inhalten falls das Roku-Gerät das unterstützt.
+ Description of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Benutzerschnittstelle
+ Title for User Interface section in user setting screen.
+
+
+
+ Als gesehen markieren
+ Button Text - When pressed, marks item as Warched
+
+
+
+ Springe zur Folge
+ Continue Watching Popup Menu - Navigate to the Episode Detail Page
+
+
+
+ Ihr Schnellverbindungscode lautet:
+
+
+
+ (Dialog schließt sich automatisch)
+
+
+
+ Deaktiviert
+
+
+
+ Standard Ansicht für Film Sammlungen.
+ Settings Menu - Description for option
+
+
+
+ Film Sammlung Grid Titel
+ Settings Menu - Title for option
+
+
+
+ Wähle aus wann Serientitel gezeigt werden sollen.
+ Settings Menu - Description for option
+
+
+
+ Beim Hovern anzeigen
+
+
+
+ Immer zeigen
+
+
+
+ Niemals anzeigen
+
+
+
+ Medien Anordnung
+ UI -> Media Grid section in user setting screen.
+
+
+
+ Verwenden Sie "Wiederholen", um langsam zum ersten Element im Ordner zu überblenden. (Wenn diese Funktion deaktiviert ist, wird der Ordner sofort zum ersten Element zurückgesetzt).
+ Description for option in Setting Screen
+
+
+
+ Wenn diese Option aktiviert ist, führt die Auswahl einer TV-Serie mit nur einer Staffel direkt zur Episodenliste und nicht zu den Showdetails und der Staffelliste.
+ Settings Menu - Description for option
+
+
+
+ Generierten Splashscreen als Jellyfin's Bildschirmschoner verwenden. Jellyfin muss neu geöffnet werden, damit die Änderung wirksam wird.
+
+
+
+ Startbildschirm als Hintergrund verwenden
+ Option Title in user setting screen
+
+
+
+ Generierten Startbildschirm als Jellyfins Hintergrund verwenden. Jellyfin muss neu geöffnet werden, damit die Änderung wirksam wird.
+ Description for option in Setting Screen
+
+
+
+ Nächste Folge
+
+
+
+ Legen Sie die maximale Anzahl von Tagen fest, die eine Serie in der Liste "Als Nächstes" verbleiben soll, ohne dass sie angesehen wird.
+ Settings Menu - Description for option
+
+
+
+ Nur Text Untertitel
+ Name of a setting - should we hide subtitles that might transcode
+
+
+
+ Zeige Was ist neu Popup nach einem Jellyfin update.
+ Settings Menu - Description for option
+
+
+
+ fortsetzen
+
+
+
+ Film Sammlung standard Ansicht
+ Settings Menu - Title for option
+
+
+
+ Wenn ausgewählt, wird das Sterne und Benutzerbewertungssystem entfernt. Dies ist um spoilern vorzubeugen.
+
+
+
+ Einstellungen für das Aussehen Jellyfins.
+ Description for Design Elements user settings.
+
+
+
+ Kinomodus
+ Settings Menu - Title for option
+
+
+
+ Der Kinomodus bringt das Kinoerlebnis direkt in Ihr Wohnzimmer und bietet die Möglichkeit, benutzerdefinierte Intros vor dem Hauptfilm abzuspielen.
+ Settings Menu - Description for option
+
+
+
+ Uhr ausblenden
+ Option Title in user setting screen
+
+
+
+ Blendet alle Uhren in Jellyfin aus. Jellyfin muss neu gestartet werden, damit die Änderung wirksam wird.
+ Settings Menu - Description for option
+
+
+
+ Trailer abspielen
+
+
+
+ H.264
+ Name of codec used in settings menu
+
+
+
+ HEVC
+ Name of codec used in settings menu
+
+
+
+ Transkodierung-Information
+
+
+
+ Video-Codec
+
+
+
+ Audio-Codec
+
+
+
+ direkt
+
+
+
+ Audiokanäle
+
+
+
+ Codec-Tag
+
+
+
+ Bitrate
+ Video streaming bit rate
+
+
+
+ Container
+ Video streaming container
+
+
+
+ Video-Spektrum
+
+
+
+ Pixelformat
+ Video pixel format
+
+
+
+ Es konnten keine Alben oder Lieder dieses Künstlers gefunden werden
+ Popup message when we find no audio data for an artist
+
+
+
+ Zeige nur Text Untertitel um Transkodierungen zu minimieren.
+ Description of a setting - should we hide subtitles that might transcode
+
+
+
+ Diashow aus
+
+
+
+ Diashow an
+
+
+
+ Diashow pausiert
+
+
+
+ Diashow fortgesetzt
+
+
+
+ MPEG-4 Unterstützung
+ Settings Menu - Title for option
+
+
+
+ Serie Was ist neu Popup
+ Settings Menu - Title for option
+
+
+
+ Serien-Einstellungen.
+ Description for TV Shows user settings.
+
+
+
+ Startseite
+
+
+
+ Max. Tage im "Als Nächstes" Bereich
+ Option Title in user setting screen
+
+
+
+ Wiedergabeinformation
+
+
+
+ Stream Informationen
+
+
+
+ Breite x Höhe
+ Video width x height
+
+
+
+ Alle
+ all will reset the searchTerm so all data will be availible
+
+
+
+ Ausgestrahlt
+ Aired date label
+
+
+
+ Künstlerinnenvorstellung
+
+
+
+ Musiktitel
+
+
+
+ Lieder
+
+
+
+ Album
+
+
+
+ Alben
+
+
+
+ Alle anzeigen
+
+
+
+ Deaktiviere Community Bewertungen für Episoden
+
+
+
+ Künstler (Gitter)
+
+
+
+ Dateien-Anzahl
+ UI -> Media Grid -> Item Count in user setting screen.
+
+
+
+ Medien Anordnung Optionen.
+
+
+
+ Designelemente
+
+
+
+ Einstellungen zum Aussehen des Programms.
+
+
+
+ Einstellungen für die Wiedergabe und unterstützte Codec- und Medientypen.
+
+
+
+ Grund
+
+
+
+ Gesamte Bitrate
+
+
+
+ Codec
+
+
+
+ Größe
+ Video size
+
+
+
+ Zufällig an
+
+
+
+ Zufällig aus
+
+
+
+ gespielt
+
+
+
+ nicht gespielt
+
+
+
+ Dateien-Titel
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Level
+ Video profile level
+
+
+
+ Einstellungen für die Startseite.
+ Description for Home Page user settings.
+
diff --git a/locale/en_GB/translations.ts b/locale/en_GB/translations.ts
index 0856c2e5..50d8ad19 100644
--- a/locale/en_GB/translations.ts
+++ b/locale/en_GB/translations.ts
@@ -2188,5 +2188,832 @@
Cancel Series Recording
+
+
+ Save Credentials?
+
+
+
+ Delete Saved
+
+
+
+ On Now
+
+
+
+ Age
+
+
+
+ Died
+
+
+
+ Born
+
+
+
+ Cast & Crew
+
+
+
+ More Like This
+
+
+
+ Delete Saved
+
+
+
+ More Like This
+
+
+
+ Cast & Crew
+
+
+
+ Age
+
+
+
+ Additional Parts
+ Additional parts of a video
+
+
+
+ Died
+
+
+
+ Born
+
+
+
+ Save Credentials?
+
+
+
+ On Now
+
+
+
+ Press 'OK' to Close
+
+
+
+ Special Features
+
+
+
+ Delete Saved
+
+
+
+ Special Features
+
+
+
+ More Like This
+
+
+
+ Age
+
+
+
+ Additional Parts
+ Additional parts of a video
+
+
+
+ Died
+
+
+
+ Born
+
+
+
+ Save Credentials?
+
+
+
+ Press 'OK' to Close
+
+
+
+ On Now
+
+
+
+ Cast & Crew
+
+
+
+ Delete Saved
+
+
+
+ On Now
+
+
+
+ More Like This
+
+
+
+ Age
+
+
+
+ Additional Parts
+ Additional parts of a video
+
+
+
+ Died
+
+
+
+ Born
+
+
+
+ Special Features
+
+
+
+ Save Credentials?
+
+
+
+ Press 'OK' to Close
+
+
+
+ Cast & Crew
+
+
+
+ Delete Saved
+
+
+
+ On Now
+
+
+
+ Age
+
+
+
+ Died
+
+
+
+ Born
+
+
+
+ Save Credentials?
+
+
+
+ Cast & Crew
+
+
+
+ Additional Parts
+ Additional parts of a video
+
+
+
+ More Like This
+
+
+
+ Special Features
+
+
+
+ Press 'OK' to Close
+
+
+
+ TV Shows
+
+
+
+ View Channel
+
+
+
+ Record
+
+
+
+ Cancel Recording
+
+
+
+ Record Series
+
+
+
+ Enter the server name or IP address
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ Select an available Jellyfin server from your local network:
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ Error Getting Playback Information
+ Dialog Title: Received error from server when trying to get information about the selected item for playback
+
+
+
+ An error was encountered while playing this item. Server did not provide required transcoding data.
+ Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url
+
+
+
+ Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.
+ Settings Menu - Description for option
+
+
+
+ MPEG-4
+ Name of codec used in settings menu
+
+
+
+ Support Direct Play of MPEG-4 content. This may need to be disabled for playback of DIVX encoded video files.
+ Settings Menu - Description for option
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec
+
+
+
+ You can search for Titles, People, Live TV Channels and more
+ Help text in search results
+
+
+
+ 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).
+ Description for option in Setting Screen
+
+
+
+ If enabled, selecting a TV series with only one season will go straight to the episode list rather than the show details and season list.
+ Settings Menu - Description for option
+
+
+
+ If enabled, images of unwatched episodes will be blurred.
+
+
+
+ Options for Jellyfin's screensaver.
+ Description for Screensaver user settings.
+
+
+
+ Use Splashscreen as Screensaver Background
+ Option Title in user setting screen
+
+
+
+ Use generated splashscreen image as Jellyfin's screensaver background. Jellyfin will need to be closed and reopened for change to take effect.
+
+
+
+ Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.
+ Description for option in Setting Screen
+
+
+
+ Hide Clock
+ Option Title in user setting screen
+
+
+
+ Hides all clocks in Jellyfin. Jellyfin will need to be closed and reopened for change to take effect.
+ Settings Menu - Description for option
+
+
+
+ Options for Home Page.
+ Description for Home Page user settings.
+
+
+
+ direct
+
+
+
+ Details Page
+
+
+
+ Video Codec
+
+
+
+ Level
+ Video profile level
+
+
+
+ Size
+ Video size
+
+
+
+ WxH
+ Video width x height
+
+
+
+ Codec Tag
+
+
+
+ Movies (Presentation)
+
+
+
+ Movies (Grid)
+
+
+
+ Cancel Series Recording
+
+
+
+ Close
+
+
+
+ Unknown
+ Title for a cast member for which we have no information for
+
+
+
+ If no server is listed above, you may also enter the server URL manually:
+ Instructions on initial app launch when the user is asked to manually enter a server URL
+
+
+
+ Media Grid
+ UI -> Media Grid section in user setting screen.
+
+
+
+ Media Grid options.
+
+
+
+ Always show the titles below the poster images. (If disabled, the title will be shown under the highlighted item only).
+ Description for option in Setting Screen
+
+
+
+ Show item count in the library and index of selected item.
+ Description for option in Setting Screen
+
+
+
+ Use voice remote to search
+ Help text in search voice text box
+
+
+
+ Quick Connect
+
+
+
+ (Dialogue will close automatically)
+
+
+
+ Return to Top
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Max Days Next Up
+ Option Title in user setting screen
+
+
+
+ Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.
+ Settings Menu - Description for option
+
+
+
+ Playback Information
+
+
+
+ Audio Codec
+
+
+
+ Total Bitrate
+
+
+
+ Bit Rate
+ Video streaming bit rate
+
+
+
+ Pixel format
+ Video pixel format
+
+
+
+ Unable to find any albums or songs belonging to this artist
+ Popup message when we find no audio data for an artist
+
+
+
+ Films
+
+
+
+ Version
+
+
+
+ Playback
+ Title for Playback section in user setting screen.
+
+
+
+ User Interface
+ Title for User Interface section in user setting screen.
+
+
+
+ Item Count
+ UI -> Media Grid -> Item Count in user setting screen.
+
+
+
+ Set Watched
+ Button Text - When pressed, marks item as Warched
+
+
+
+ Here is your Quick Connect code:
+
+
+
+ Networks
+
+
+
+ Options that alter the design of Jellyfin.
+ Description for Design Elements user settings.
+
+
+
+ Play Trailer
+
+
+
+ Settings relating to playback and supported codec and media types.
+
+
+
+ Home Page
+
+
+
+ Transcoding Information
+
+
+
+ Reason
+
+
+
+ Audio Channels
+
+
+
+ Codec Support
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ MPEG-2
+ Name of codec used in settings menu
+
+
+
+ Enable or disable Direct Play for optional codecs
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Disabled
+
+
+
+ ** EXPERIMENTAL** Support Direct Play of AV1 content if this Roku device supports it.
+ Description of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Item Titles
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Set Favourite
+ Button Text - When pressed, sets item as Favorite
+
+
+
+ Go to series
+ Continue Watching Popup Menu - Navigate to the Series Detail Page
+
+
+
+ Go to season
+ Continue Watching Popup Menu - Navigate to the Season Page
+
+
+
+ %1 of %2
+ Item position and count. %1 = current item. %2 = total number of items
+
+
+
+ There was an error authenticating via Quick Connect.
+
+
+
+ Studios
+
+
+
+ Options for Details pages.
+ Description for Details page user settings.
+
+
+
+ Hide Taglines
+ Option Title in user setting screen
+
+
+
+ Hides tagline text on details pages.
+
+
+
+ Options for TV Shows.
+ Description for TV Shows user settings.
+
+
+
+ Skip Details for Single Seasons
+ Settings Menu - Title for option
+
+
+
+ Blur Unwatched Episodes
+ Option Title in user setting screen
+
+
+
+ Cinema Mode brings the cinema experience straight to your living room with the ability to play custom intros before the main feature.
+ Settings Menu - Description for option
+
+
+
+ Settings relating to how the application looks.
+
+
+
+ Stream Information
+
+
+
+ Codec
+
+
+
+ Container
+ Video streaming container
+
+
+
+ Video range type
+
+
+
+ Cinema Mode
+ Settings Menu - Title for option
+
+
+
+ Use Splashscreen as Home Background
+ Option Title in user setting screen
+
+
+
+ Design Elements
+
+
+
+ Screensaver
+
+
+
+ Search now
+ Help text in search Box
+
+
+
+ Go to episode
+ Continue Watching Popup Menu - Navigate to the Episode Detail Page
+
+
+
+ Shows
+
+
+
+ Enabled
+
+
+
+ Text Subtitles Only
+ Name of a setting - should we hide subtitles that might transcode
+
+
+
+ Attempt Direct Play for H.264 media with unsupported profile levels before falling back to transcoding if it fails.
+ Settings Menu - Description for option
+
+
+
+ Next episode
+
+
+
+ HEVC
+ Name of codec used in settings menu
+
+
+
+ H.264
+ Name of codec used in settings menu
+
+
+
+ Attempt Direct Play for H.264 media with unsupported profile levels before falling back to transcoding if it fails.
+ Settings Menu - Description for option
+
+
+
+ Attempt Direct Play for HEVC media with unsupported profile levels before falling back to transcoding if it fails.
+ Settings Menu - Description for option
+
+
+
+ Only display text subtitles to minimise transcoding.
+ Description of a setting - should we hide subtitles that might transcode
+
+
+
+ Aired
+ Aired date label
+
+
+
+ Slideshow Off
+
+
+
+ Show What's New Popup
+ Settings Menu - Title for option
+
+
+
+ Show What's New popup when Jellyfin is updated to a new version.
+ Settings Menu - Description for option
+
+
+
+ Unplayed
+
+
+
+ Resumable
+
+
+
+ Slideshow On
+
+
+
+ Slideshow Resumed
+
+
+
+ Random On
+
+
+
+ Random Off
+
+
+
+ all
+ all will reset the searchTerm so all data will be availible
+
+
+
+ Slideshow Paused
+
+
+
+ MPEG-4 Support
+ Settings Menu - Title for option
+
+
+
+ Played
+
+
+
+ If enabled, the star and community rating for episodes of a TV show will be removed. This is to prevent spoilers of an upcoming good/bad episode.
+
+
+
+ H.264
+ Name of codec used in settings menu
+
+
+
+ Disable Community Rating for Episodes
+
+
+
+ View All
+
+
+
+ Select when to show titles.
+ Settings Menu - Description for option
+
+
+
+ Show On Hover
+
+
+
+ Always Show
+
+
+
+ Always Hide
+
+
+
+ Album
+
+
+
+ Artists (Grid)
+
+
+
+ Song
+
+
+
+ Artists (Presentation)
+
+
+
+ Songs
+
+
+
+ Albums
+
diff --git a/locale/en_US/translations.ts b/locale/en_US/translations.ts
index fc02235b..00be207c 100644
--- a/locale/en_US/translations.ts
+++ b/locale/en_US/translations.ts
@@ -302,6 +302,16 @@
Movies
+
+
+ Movies (Presentation)
+ Movie library view option
+
+
+
+ Movies (Grid)
+ Movie library view option
+ TV Shows
@@ -484,10 +494,21 @@
PlaybackTitle for Playback section in user setting screen.
+
-
- MPEG-2 Support
- Settings Menu - Title for option
+
+ Codec Support
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Enable or disable Direct Play for optional codecs
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ MPEG-2
+ Name of codec used in settings menu
@@ -495,14 +516,24 @@
Settings Menu - Description for option
-
- AV1 Support
- Settings Menu - Title for option
+
+ MPEG-4
+ Name of codec used in settings menu
+
+
+
+ Support Direct Play of MPEG-4 content. This may need to be disabled for playback of DIVX encoded video files.
+ Settings Menu - Description for option
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec** EXPERIMENTAL** Support Direct Play of AV1 content if this Roku device supports it.
- Settings Menu - Description for option
+ Description of a setting - should we try to direct play experimental av1 codec
@@ -657,6 +688,16 @@
Blur Unwatched EpisodesOption Title in user setting screen
+
+
+ Skip Details for Single Seasons
+ Settings Menu - Title for option
+
+
+
+ If enabled, selecting a TV series with only one season will go straight to the episode list rather than the show details and season list.
+ Settings Menu - Description for option
+ If enabled, images of unwatched episodes will be blurred.
@@ -727,9 +768,9 @@
Play Trailer
-
- Direct Play H.264 Unsupported Profile Levels
- Settings Menu - Title for option
+
+ H.264
+ Name of codec used in settings menu
@@ -737,9 +778,9 @@
Settings Menu - Description for option
-
- Direct Play HEVC Unsupported Profile Levels
- Settings Menu - Title for option
+
+ HEVC
+ Name of codec used in settings menu
@@ -865,7 +906,7 @@
Only display text subtitles to minimize transcoding.Description of a setting - should we hide subtitles that might transcode
-
+
all
@@ -910,5 +951,103 @@
Support Direct Play of MPEG-4 content. This may need to be disabled for playback of DIVX encoded video files.Settings Menu - Description for option
+
+
+ Show What's New Popup
+ Settings Menu - Title for option
+
+
+
+ Show What's New popup when Jellyfin is updated to a new version.
+ Settings Menu - Description for option
+
+
+
+ Unplayed
+
+
+
+ Played
+
+
+
+ Resumable
+
+
+
+ Movie Library Default View
+ Settings Menu - Title for option
+
+
+
+ Default view for Movie Libraries.
+ Settings Menu - Description for option
+
+
+
+ Movies (Presentation)
+
+
+
+ Movies (Grid)
+
+
+
+ Movie Library Grid Titles
+ Settings Menu - Title for option
+
+
+
+ Select when to show titles.
+ Settings Menu - Description for option
+
+
+
+ Show On Hover
+
+
+
+ Always Show
+
+
+
+ Always Hide
+
+
+
+ Artists (Presentation)
+
+
+
+ Artists (Grid)
+
+
+
+ Song
+
+
+
+ Songs
+
+
+
+ Album
+
+
+
+ Albums
+
+
+
+ View All
+
+
+
+ Disable Community Rating for Episodes
+
+
+
+ If enabled, the star and community rating for episodes of a TV show will be removed. This is to prevent spoilers of an upcoming good/bad episode.
+
diff --git a/locale/es_ES/translations.ts b/locale/es_ES/translations.ts
index d160ddd0..dc19651c 100644
--- a/locale/es_ES/translations.ts
+++ b/locale/es_ES/translations.ts
@@ -2199,5 +2199,496 @@
Este %1 no contiene elementos
+
+
+ Cambiar Servidor
+
+
+
+ Borrar Credenciales
+
+
+
+ Puntuación de la crítica
+
+
+
+ Edad
+
+
+
+ hoy
+ Current day
+
+
+
+ Muerto/a
+
+
+
+ Puntuación de IMDb
+
+
+
+ Reparto y equipo
+
+
+
+ Sábado
+ Day of Week
+
+
+
+ Repetir
+ If TV Shows has previously been broadcasted
+
+
+
+ Cuadrícula de medios
+ UI -> Media Grid section in user setting screen.
+
+
+
+ Cerrar sesión
+
+
+
+ ¿Guardar credenciales?
+
+
+
+ Error durante la reproducción
+ Dialog title when error occurs during playback
+
+
+
+ Ha ocurrido un error al reproducir este contenido.
+ Dialog detail when error occurs during playback
+
+
+
+ Reproduciendo contenido del canal
+
+
+
+ Error de reproducción de contenido del canal
+
+
+ Name or Title field of media item
+
+ Nombre
+
+
+
+ Fecha en que se agregó
+
+
+
+ Fecha de reproducción
+
+
+
+ Control Parental
+
+
+
+ Fecha de estreno
+
+
+
+ Tiempo de duración
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Vista
+
+
+ Title of Tab for options to sort library content
+
+ Clasificar
+
+
+ Title of Tab for options to filter library content
+
+ Filtro
+
+
+
+ Funciones especiales
+
+
+
+ No se ha podido reproducir el contenido del canal de este servidor
+
+
+
+ Conteo de reproducción
+
+
+
+ En directo ahora
+
+
+
+ Error recuperando contenido
+ Dialog title when unable to load Content from Server
+
+
+
+ Ha ocurrido un error al tratar de recuperar la información de este contenido desde el servidor.
+ Dialog detail when unable to load Content from Server
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Este %1 no contiene elementos
+
+
+
+ Nacido/a
+
+
+
+ Mas de este estilo
+
+
+
+ Se ha encontrado un error al reproducir este elemento. El servidor no proveyó la información necesaria para la transcodificación.
+ Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url
+
+
+
+ Utilizar la búsqueda remota por voz
+ Help text in search voice text box
+
+
+
+ Películas (presentación)
+
+
+
+ Películas (cuadrícula)
+
+
+
+ Programas de televisión
+
+
+
+ ayer
+ Previous day
+
+
+
+ mañana
+ Next day
+
+
+
+ Jueves
+ Day of Week
+
+
+
+ Viernes
+ Day of Week
+
+
+
+ Comenzó a las
+ (Past Tense) For defining time when a program started today (e.g. Started at 08:00)
+
+
+
+ Comienza a las
+ (Future Tense) For defining time when a program will start today (e.g. Starts at 08:00)
+
+
+
+ En vivo
+ If TV Show is being broadcast live (not pre-recorded)
+
+
+
+ Guía de televisión
+ Menu option for showing Live TV Guide / Schedule
+
+
+
+ Grabar serie
+
+
+
+ Cancelar la grabación
+
+
+
+ Cancelar la grabación de la serie
+
+
+
+ Cerrar
+
+
+
+ Conectando con el servidor
+ Message to display to user while client is attempting to connect to the server
+
+
+
+ No se ha encontrado
+ Title of message box when the requested content is not found on the server
+
+
+
+ Desconocido
+ Title for a cast member for which we have no information for
+
+
+
+ El contenido solicitado no existe en el servidor
+ Content of message box when the requested content is not found on the server
+
+
+
+ Agregar el nombre del servidor o su dirección de IP
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ Elige un servidor Jellyfin disponible en la red local:
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ Soporte de reproducción directa para contenido MPEG-2 (ej., televisión en vivo). Esto previene la transcodificación de contenido MPEG-2, pero a mayor uso de ancho de banda.
+ Settings Menu - Description for option
+
+
+
+ Soporte de reproducción directa para contenido MPEG-4. Esto podría requerir ser deshabilitado para poder reproducir los archivos de video con encodificación DIVX.
+ Settings Menu - Description for option
+
+
+
+ **EXPERIMENTAL** Soporte de reproducción directa para contenido AV1 si este dispositivo Roku es compatible.
+ Description of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Siempre mostrar los títulos por debajo de las imágenes de cartelera. (Si se deshabilita, el título se mostrará debajo del elemento resaltado solamente).
+ Description for option in Setting Screen
+
+
+
+ Conteo de elementos
+ UI -> Media Grid -> Item Count in user setting screen.
+
+
+
+ Mostrar el conteo de elementos en la biblioteca y en el índice del elemento seleccionado.
+ Description for option in Setting Screen
+
+
+
+ Agregar a favoritos
+ Button Text - When pressed, sets item as Favorite
+
+
+
+ Marcar como visto
+ Button Text - When pressed, marks item as Warched
+
+
+
+ Ir a serie
+ Continue Watching Popup Menu - Navigate to the Series Detail Page
+
+
+
+ Ir a la temporada
+ Continue Watching Popup Menu - Navigate to the Season Page
+
+
+
+ Ir al episodio
+ Continue Watching Popup Menu - Navigate to the Episode Detail Page
+
+
+
+ Buscar ahora
+ Help text in search Box
+
+
+
+ Presiona 'OK' para cerrar
+
+
+
+ Partes adicionales
+ Additional parts of a video
+
+
+
+ Películas
+
+
+
+ Domingo
+ Day of Week
+
+
+
+ Lunes
+ Day of Week
+
+
+
+ Martes
+ Day of Week
+
+
+
+ Miércoles
+ Day of Week
+
+
+
+ Comienza a las
+ (Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00)
+
+
+
+ Terminó a las
+ (Past Tense) For defining time when a program will ended (e.g. Ended at 08:00)
+
+
+
+ Termina a las
+ (Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00)
+
+
+
+ Canales
+ Menu option for showing Live TV Channel List
+
+
+
+ Ver Canal
+
+
+
+ Grabar
+
+
+
+ Si no hay servidores disponibles, puedes agregar manualmente la URL:
+ Instructions on initial app launch when the user is asked to manually enter a server URL
+
+
+
+ Error obteniendo la Información de reproducción
+ Dialog Title: Received error from server when trying to get information about the selected item for playback
+
+
+
+ Versión
+
+
+
+ Reproducción
+ Title for Playback section in user setting screen.
+
+
+
+ Interfaz de usuario
+ Title for User Interface section in user setting screen.
+
+
+
+ Opciones de la cuadrícula de medios.
+
+
+
+ Soporte de Codec
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Habilitar o desactivar la reproducción directa para codecs opcionales
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ MPEG-2
+ Name of codec used in settings menu
+
+
+
+ MPEG-4
+ Name of codec used in settings menu
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Títulos de elementos
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Comenzó a las
+ (Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00)
+
+
+
+ Activado
+
+
+
+ Desactivado
+
+
+
+ espectáculos
+
+
+
+ Conexión rápida
+
+
+
+ (El diálogo se cerrará automáticamente)
+
+
+
+ Vuelva a la parte superior
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Puede buscar títulos, personas, canales de TV en vivo y más
+ Help text in search results
+
+
+
+ Aquí está su código de conexión rápida:
+
+
+
+ Hubo un error al autenticarse a través de Quick Connect.
+
+
+
+ Redes
+
+
+
+ Estudios
+
diff --git a/locale/fr/translations.ts b/locale/fr/translations.ts
index 08a8232c..244197ec 100644
--- a/locale/fr/translations.ts
+++ b/locale/fr/translations.ts
@@ -4041,5 +4041,1677 @@
Différents types de vidéo
+
+
+ En ce moment
+
+
+
+ Une erreur s'est produite lors de la lecture de cet élément.
+ Dialog detail when error occurs during playback
+
+
+
+ Note des critiques
+
+
+
+ Nombre de lecture
+
+
+ Title of Tab for options to sort library content
+
+ Trier
+
+
+
+ Âge
+
+
+
+ Commencé à
+ (Past Tense) For defining time when a program started today (e.g. Started at 08:00)
+
+
+
+ Annuler l'enregistrement de la Série
+
+
+
+ Lundi
+ Day of Week
+
+
+
+ Prise en charge de la lecture directe du codec MPEG-2 (ex., Live TV). Cela empêchera le transcodage du contenu MPEG-2 mais utilisera sensiblement plus de bande passante.
+ Settings Menu - Description for option
+
+
+
+ Grille Média
+ UI -> Media Grid section in user setting screen.
+
+
+
+ Diaporama Activé
+
+
+
+ Erreur dans la récupération du contenus
+ Dialog title when unable to load Content from Server
+
+
+
+ Erreur lors de la lecture
+ Dialog title when error occurs during playback
+
+
+
+ Une erreur s'est produite lors de la récupération des données de cet élément à partir du serveur.
+ Dialog detail when unable to load Content from Server
+
+
+
+ Chaînes
+ Menu option for showing Live TV Channel List
+
+
+
+ Voir la Chaîne
+
+
+
+ Toujours afficher les titres sous les images des affiches. (Si désactivé, les titres s'afficherons uniquement sous les éléments en surbrillance).
+ Description for option in Setting Screen
+
+
+
+ Nombre d'éléments
+ UI -> Media Grid -> Item Count in user setting screen.
+
+
+
+ Afficher le nombre d'éléments dans la bibliotèque et l'index de l'élément sélectionné.
+ Description for option in Setting Screen
+
+
+
+ Une erreur s'est produite lors de l'autentification via Quick Connect.
+
+
+
+ Utiliser la touche Replay pour lentement animer la sélection du première élément du dossier. (Si désactivé, le premier élément du dossier sera immédiatement sélectionné).
+ Description for option in Setting Screen
+
+
+
+ Si activé, les images des épisodes non visionnés seront floutées.
+
+
+
+ Utiliser le Splash Screen comme fond d'écran de veille
+ Option Title in user setting screen
+
+
+
+ Élements de Désign
+
+
+
+ Annuler l'enregistrement
+
+
+
+ Page de Détails
+
+
+
+ Connexion Rapide
+
+
+
+ Le Mode Cinéma vous fait vivre l'expérience du cinéma directement dans votre salon en vous permettant de diffuser des intros personnalisées avant le film.
+ Settings Menu - Description for option
+
+
+
+ Masquer l'Horloge
+ Option Title in user setting screen
+
+
+
+ Masquer toutes les horloges dans Jellyfin. Jellyfin devra être fermé et rouvert pour que le changement prenne effet.
+ Settings Menu - Description for option
+
+
+
+ Différents types de vidéo
+
+
+
+ Activer Direct Play pour les contenus MPEG-4. Vous devrez peut-être désactivé cette fonctione pour les fichiers vidéo DIVX.
+ Settings Menu - Description for option
+
+
+
+ **EXPÉRIMENTAL** Activer Direct Play pour fichier AV1 si ROKU le supporte.
+ Description of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Sauter les détails pour une seul saison
+ Settings Menu - Title for option
+
+
+
+ Erreur lors du chargement des données de la chaîne
+
+
+
+ Classification parentale
+
+
+
+ Né/Née
+
+
+
+ Mort le
+
+
+
+ Casting et équipe
+
+
+
+ Films
+
+
+
+ Si activé, choisir une série télé avec seulement une saison, affichera la liste des épisodes au lieu des détails de la série et la liste des saisons.
+ Settings Menu - Description for option
+
+
+
+ Essayer Direct Play for les fichier h.264 avec profile non supporté avant le transcodage.
+ Settings Menu - Description for option
+
+
+
+ HEVC
+ Name of codec used in settings menu
+
+
+
+ Essayer Direct Play for les fichier HEVC avec profile non supporté avant le transcodage.
+ Settings Menu - Description for option
+
+
+
+ Seulement afficher le texte des sous-titres
+ Name of a setting - should we hide subtitles that might transcode
+
+
+
+ Seulement afficher le texte des sous-titres afin de minimzer le transcodage.
+ Description of a setting - should we hide subtitles that might transcode
+
+
+
+ Redémarrer le diaporama
+
+
+
+ Épisode suivant
+
+
+
+ Raison
+
+
+
+ Afficher la fenêtre contextuelle des nouveautés lorsque que Jellyfin est mise à joura avec la dernière version.
+ Settings Menu - Description for option
+
+
+
+ Utiliser le Splash Screen généré comme fond d'écran de veille. Jellyfin devra être fermé et rouvert pour que le changement prenne effet.
+
+
+
+ Utiliser l'écran de démarrage généré comme arrière plan principal. Jellyfin devra être fermé et rouvert pour que le changement prenne effet.
+ Description for option in Setting Screen
+
+
+
+ Films (Présentation)
+ Movie library view option
+
+
+
+ Films (Grille)
+ Movie library view option
+
+
+
+ Samedi
+ Day of Week
+
+
+
+ A débuté
+ (Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00)
+
+
+
+ Commence à
+ (Future Tense) For defining time when a program will start today (e.g. Starts at 08:00)
+
+
+
+ Répéter
+ If TV Shows has previously been broadcasted
+
+
+
+ Guide Télé
+ Menu option for showing Live TV Guide / Schedule
+
+
+
+ Enregistrer la Série
+
+
+
+ Connexion au Serveur
+ Message to display to user while client is attempting to connect to the server
+
+
+
+ Entrer le nom du serveur ou son adresse IP
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ Si aucun serveur n'est affiché ci-dessus vous pouvez également saisir l'adresse IP du serveur manuellement :
+ Instructions on initial app launch when the user is asked to manually enter a server URL
+
+
+
+ Une erreur a été rencontrée lors de la lecture de ce fichier. Le serveur n'a pas communiqué les données nécessaires pour le transcodage.
+ Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url
+
+
+
+ Support de Codec
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Activer our désactiver Direct Play pour les codecs optionnels
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Interface Utilisateur
+ Title for User Interface section in user setting screen.
+
+
+
+ Options de la Grille Média.
+
+
+
+ Titres des éléments
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Mettre en Favori
+ Button Text - When pressed, sets item as Favorite
+
+
+
+ Mettre en Visionné
+ Button Text - When pressed, marks item as Warched
+
+
+
+ Aller à la série
+ Continue Watching Popup Menu - Navigate to the Series Detail Page
+
+
+
+ Aller à l'épisode
+ Continue Watching Popup Menu - Navigate to the Episode Detail Page
+
+
+
+ Utiliser la télécomande vocale pour rechercher
+ Help text in search voice text box
+
+
+
+ Vous pouvez rechercher des titres, des personnes, des chaînes de télévision en direct et plus encore
+ Help text in search results
+
+
+
+ %1 sur %2
+ Item position and count. %1 = current item. %2 = total number of items
+
+
+
+ Voici votre code Quick Connect :
+
+
+
+ (La boîte de dialogue se fermera automatiquement)
+
+
+
+ Séries
+
+
+
+ Retour en haut
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Flouter les épisodes non visionnés
+ Option Title in user setting screen
+
+
+
+ Options de l'écran de veille de Jellyfin.
+ Description for Screensaver user settings.
+
+
+
+ Mode Cinéma
+ Settings Menu - Title for option
+
+
+
+ H.264
+ Name of codec used in settings menu
+
+
+
+ Informations de Lecture
+
+
+
+ Codec Vidéo
+
+
+
+ Débit Total
+
+
+
+ Canaux Audio
+
+
+
+ Informations du Flux
+
+
+
+ Codec
+
+
+
+ Balise de Codec
+
+
+
+ Niveau
+ Video profile level
+
+
+
+ Taille
+ Video size
+
+
+
+ Appuyez sur 'OK' pour fermer
+
+
+
+ Caractéristiques spéciales
+
+
+
+ Hier
+ Previous day
+
+
+
+ Demain
+ Next day
+
+
+
+ Parties additionelles
+ Additional parts of a video
+
+
+
+ Séries télé
+
+
+
+ Dimanche
+ Day of Week
+
+
+
+ Mardi
+ Day of Week
+
+
+
+ Mercredi
+ Day of Week
+
+
+
+ Jeudi
+ Day of Week
+
+
+
+ Vendredi
+ Day of Week
+
+
+
+ Débute
+ (Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00)
+
+
+
+ Termine à
+ (Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00)
+
+
+
+ Enregistrer
+
+
+
+ Fermer
+
+
+
+ Introuvable
+ Title of message box when the requested content is not found on the server
+
+
+
+ Le contenu demandé n'existe pas sur le serveur
+ Content of message box when the requested content is not found on the server
+
+
+
+ Sélectionnez un serveur Jellyfin disponible sur votre réseau local :
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ Erreur lors de l'obtention des informations de lecture
+ Dialog Title: Received error from server when trying to get information about the selected item for playback
+
+
+
+ Diaporama désactivé
+
+
+
+ Interrompre le diaporama
+
+
+
+ Support pour MPEG-4
+ Settings Menu - Title for option
+
+
+
+ Aller à la saison
+ Continue Watching Popup Menu - Navigate to the Season Page
+
+
+
+ Afficher la fenêtre contextuelle des nouveautés
+ Settings Menu - Title for option
+
+
+
+ Rechercher maintenant
+ Help text in search Box
+
+
+
+ Non lu
+
+
+
+ Les Studios
+
+
+
+ Masquer les étiquettes
+ Option Title in user setting screen
+
+
+
+ Options pour les Séries Télévisée.
+ Description for TV Shows user settings.
+
+
+
+ Nombre Max de jours dans Suivant
+ Option Title in user setting screen
+
+
+
+ Définir le nombre maximum de jours une émission doit rester dans la liste "Suivant" sans la regarder.
+ Settings Menu - Description for option
+
+
+
+ Débit
+ Video streaming bit rate
+
+
+
+ Conteneur
+ Video streaming container
+
+
+
+ Diffusé
+ Aired date label
+
+
+
+ MPEG-2
+ Name of codec used in settings menu
+
+
+
+ MPEG-4
+ Name of codec used in settings menu
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Réseaux
+
+
+
+ Options des Pages de Détails.
+ Description for Details page user settings.
+
+
+
+ Écran de veille
+
+
+
+ Utiliser le Splash Screen comme arrière-plan principal
+ Option Title in user setting screen
+
+
+
+ Réglages relatifs à l'apparence de l'application.
+
+
+
+ Réglages relatifs à la lecture, aux codecs pris en charges et aux types de médias.
+
+
+
+ Page d'Accueil
+
+
+
+ Options pour la Page d'Accueil.
+ Description for Home Page user settings.
+
+
+
+ Codec Audio
+
+
+
+ Direct
+
+
+
+ LxH
+ Video width x height
+
+
+
+ Format des pixels
+ Video pixel format
+
+
+
+ Aucuns n'albums ni chansons ont été trouvés pour cet artiste
+ Popup message when we find no audio data for an artist
+
+
+
+ Tout
+ all will reset the searchTerm so all data will be availible
+
+
+
+ Lecture aléatoire actvée
+
+
+
+ Lecture aléatoire désactivée
+
+
+
+ Lu
+
+
+
+ Reprise possible
+
+
+
+ Informations de Transcodage
+
+
+
+ Lire la bande-annonce
+
+
+
+ Options qui modifient le design de Jellyfin.
+ Description for Design Elements user settings.
+
+
+
+ Version
+
+
+
+ Masquer les étiquettes sur la page des détails.
+
+
+
+ Chargement des données de la chaîne
+
+
+
+ Impossible de charger les données de la chaîne à partir du serveur
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Ce %1 ne contient aucun élément
+
+
+ Name or Title field of media item
+
+ Nom
+
+
+
+ Classement IMDb
+
+
+
+ date d'ajout
+
+
+
+ Date de lecture
+
+
+
+ Durée
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Voir
+
+
+ Title of Tab for options to filter library content
+
+ Filtrer
+
+
+
+ Plus du même genre
+
+
+
+ Aujourd'hui
+ Current day
+
+
+
+ Termine à
+ (Past Tense) For defining time when a program will ended (e.g. Ended at 08:00)
+
+
+
+ En direct
+ If TV Show is being broadcast live (not pre-recorded)
+
+
+
+ Date de sortie
+
+
+
+ Inconnu
+ Title for a cast member for which we have no information for
+
+
+
+ Lecture
+ Title for Playback section in user setting screen.
+
+
+
+ Activé
+
+
+
+ Désactivé
+
+
+
+ Supression sauvgardée
+
+
+
+ Sauvegarder les informations d'identification ?
+
+
+
+ En ce moment
+
+
+
+ Lundi
+ Day of Week
+
+
+
+ Une erreur s'est produite lors de la récupération des données de cet élément à partir du serveur.
+ Dialog detail when unable to load Content from Server
+
+
+
+ Une erreur s'est produite lors de la lecture de cet élément.
+ Dialog detail when error occurs during playback
+
+
+
+ Erreur lors du chargement des données de la chaîne
+
+
+
+ Impossible de charger les données de la chaîne à partir du serveur
+
+
+
+ Nombre de lectures
+
+
+
+ Commence à
+ (Future Tense) For defining time when a program will start today (e.g. Starts at 08:00)
+
+
+
+ Terminé à
+ (Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00)
+
+
+
+ Connexion au Server
+ Message to display to user while client is attempting to connect to the server
+
+
+
+ Si aucun serveur n'est affiché ci-dessus vous pouvez également saisir l'adresse IP du serveur manuellement :
+ Instructions on initial app launch when the user is asked to manually enter a server URL
+
+
+
+ Une erreur a été rencontrée lors de la lecture de ce fichier. Le serveur n'a pas communiqué les données nécessaires pour le transcodage.
+ Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url
+
+
+
+ Erreur lors de la récupération du contenu
+ Dialog title when unable to load Content from Server
+
+
+
+ Chaînes
+ Menu option for showing Live TV Channel List
+
+
+
+ Nombre d'éléments
+ UI -> Media Grid -> Item Count in user setting screen.
+
+
+
+ Annuler l'enregistrement
+
+
+
+ Connexion Rapide
+
+
+
+ Voir la Chaîne
+
+
+
+ Mort le
+
+
+
+ Guide TV
+ Menu option for showing Live TV Guide / Schedule
+
+
+
+ Enregistrer la série
+
+
+
+ Films (Grille)
+
+
+
+ Interface Utilisateur
+ Title for User Interface section in user setting screen.
+
+
+
+ Options de la Grille Média.
+
+
+
+ Titres des éléments
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Mettre en Favori
+ Button Text - When pressed, sets item as Favorite
+
+
+
+ Aller à la série
+ Continue Watching Popup Menu - Navigate to the Series Detail Page
+
+
+
+ Aller à l'épisode
+ Continue Watching Popup Menu - Navigate to the Episode Detail Page
+
+
+
+ Vous pouvez rechercher des titres, des personnes, des chaînes de télévision en direct et plus encore
+ Help text in search results
+
+
+
+ %1 sur %2
+ Item position and count. %1 = current item. %2 = total number of items
+
+
+
+ Erreur lors de la lecture
+ Dialog title when error occurs during playback
+
+
+
+ Note des critiques
+
+
+
+ Classification parentale
+
+
+ Title of Tab for options to sort library content
+
+ Tri
+
+
+
+ Né le
+
+
+
+ Âge
+
+
+
+ Parties additionelles
+ Additional parts of a video
+
+
+
+ Films
+
+
+
+ Films (Présentation)
+
+
+
+ Séries TV
+
+
+
+ hier
+ Previous day
+
+
+
+ demain
+ Next day
+
+
+
+ Samedi
+ Day of Week
+
+
+
+ Commencé à
+ (Past Tense) For defining time when a program started today (e.g. Started at 08:00)
+
+
+
+ Rediffusion
+ If TV Shows has previously been broadcasted
+
+
+
+ Annuler l'enregistrement de la Série
+
+
+
+ Entrer le nom du serveur ou son adresse IP
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ Grille Média
+ UI -> Media Grid section in user setting screen.
+
+
+
+ Toujours afficher les titres sous les images des affiches. (Si désactivé, les titres s'afficheront uniquement sous les éléments en surbrillance).
+ Description for option in Setting Screen
+
+
+
+ Afficher le nombre d'éléments dans la bibliotèque et l'index de l'élément sélectionné.
+ Description for option in Setting Screen
+
+
+
+ Marquer comme vu
+ Button Text - When pressed, marks item as Warched
+
+
+
+ Utilisez la télécommande vocale pour rechercher
+ Help text in search voice text box
+
+
+
+ Voici votre code Quick Connect :
+
+
+
+ (La boîte de dialogue se fermera automatiquement)
+
+
+
+ Une erreur s'est produite lors de l'authentification via Quick Connect.
+
+
+
+ Séries
+
+
+
+ Appuyez sur 'OK' pour fermer
+
+
+
+ Bonus
+
+
+
+ Dimanche
+ Day of Week
+
+
+
+ Mardi
+ Day of Week
+
+
+
+ Mercredi
+ Day of Week
+
+
+
+ Jeudi
+ Day of Week
+
+
+
+ Vendredi
+ Day of Week
+
+
+
+ Débute
+ (Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00)
+
+
+
+ Enregistrer
+
+
+
+ Fermer
+
+
+
+ Introuvable
+ Title of message box when the requested content is not found on the server
+
+
+
+ Le contenu demandé n'existe pas sur le serveur
+ Content of message box when the requested content is not found on the server
+
+
+
+ Sélectionnez un serveur Jellyfin disponible sur votre réseau local :
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ Erreur lors de l'obtention des informations de lecture
+ Dialog Title: Received error from server when trying to get information about the selected item for playback
+
+
+
+ Aller à la saison
+ Continue Watching Popup Menu - Navigate to the Season Page
+
+
+
+ Rechercher maintenant
+ Help text in search Box
+
+
+
+ Studios
+
+
+
+ MPEG-2
+ Name of codec used in settings menu
+
+
+
+ MPEG-4
+ Name of codec used in settings menu
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Réseaux
+
+
+
+ Version
+
+
+
+ Chargement des données de la chaîne
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Ce %1 ne contient aucun élément
+
+
+ Name or Title field of media item
+
+ Nom
+
+
+
+ Note IMDb
+
+
+
+ Date d'ajout
+
+
+
+ Date de lecture
+
+
+
+ Durée
+
+
+ Title of Tab for options to filter library content
+
+ Filtre
+
+
+
+ Similaires
+
+
+
+ aujourd'hui
+ Current day
+
+
+
+ Termine à
+ (Past Tense) For defining time when a program will ended (e.g. Ended at 08:00)
+
+
+
+ En direct
+ If TV Show is being broadcast live (not pre-recorded)
+
+
+
+ Date de sortie
+
+
+
+ Inconnu
+ Title for a cast member for which we have no information for
+
+
+
+ Lecture
+ Title for Playback section in user setting screen.
+
+
+
+ Activé
+
+
+
+ Désactivé
+
+
+
+ Sauvegarder les informations d'identification ?
+
+
+
+ Supprimer les valeurs enregistrées
+
+
+
+ Permet la lecture directe du codec MPEG-2 (ex. Live TV). Cela empêchera le transcodage du contenu MPEG-2 mais utilisera sensiblement plus de bande passante.
+ Settings Menu - Description for option
+
+
+
+ La touche 'Replay' utilise une animation douce afin de sélectionner le premier élément du dossier. (Si cette option est désactivée, le premier élément du dossier sera immédiatement sélectionné).
+ Description for option in Setting Screen
+
+
+
+ Page de détails
+
+
+
+ Support de codec
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Retourner en haut
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Distribution et équipe
+
+
+
+ Commencé
+ (Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00)
+
+
+
+ Activer ou désactiver la lecture directe pour les codecs optionnels
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Permet la lecture directe du codec MPEG-4. Il sera peut-être nécessaire de désactiver cette option pour lire les fichiers vidéo DIVX.
+ Settings Menu - Description for option
+
+
+
+ **EXPÉRIMENTAL** Permet la lecture directe du codec AV1 si l'appareil Roku le prend en charge.
+ Description of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Cela cache les étiquettes sur les pages de détails.
+
+
+
+ Cacher les étiquettes
+ Option Title in user setting screen
+
+
+
+ Options pour les pages de détails.
+ Description for Details page user settings.
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Vue
+
+
+
+ Vue par défaut pour la médiathèque de films
+ Settings Menu - Title for option
+
+
+
+ Titres des médiathèques de films
+ Settings Menu - Title for option
+
+
+
+ Afficher au survol
+
+
+
+ Toujours afficher
+
+
+
+ Voir tout
+
+
+
+ Épisode suivant
+
+
+
+ Motif
+
+
+
+ Sauter les détails pour les saisons uniques
+ Settings Menu - Title for option
+
+
+
+ Si activé, sélectionner une série TV ne comportant qu'une seule saison affichera directement la liste des épisodes plutôt que les détails et la liste des saisons.
+ Settings Menu - Description for option
+
+
+
+ Utilise une image de présentation générée en tant qu'écran de veille de Jellyfin. L'activation de cette option nécessite le redémarrage de Jellyfin.
+
+
+
+ Utilise une image de présentation générée en tant que fond d'écran d’accueil de Jellyfin. L'activation de cette option nécessite le redémarrage de Jellyfin.
+ Description for option in Setting Screen
+
+
+
+ Masque toutes les horloges dans Jellyfin. L'activation de cette option nécessite le redémarrage de Jellyfin.
+ Settings Menu - Description for option
+
+
+
+ Tente la lecture directe du codec HEVC comportant des niveaux de profils incompatibles avant de transcoder si cela échoue.
+ Settings Menu - Description for option
+
+
+
+ Définit le nombre maximal de jours qu'une série TV peut rester dans la section 'À suivre' si elle n'est plus regardée.
+ Settings Menu - Description for option
+
+
+
+ Type de plage vidéo
+
+
+
+ Diaporama activé
+
+
+
+ Affiche la fenêtre contextuelle des nouveautés quand Jellyfin est mis à jour.
+ Settings Menu - Description for option
+
+
+
+ Affiche la vue par défaut dans les médiathèques de films.
+ Settings Menu - Description for option
+
+
+
+ Sélectionnez quand les titres devraient s'afficher.
+ Settings Menu - Description for option
+
+
+
+ Toujours masquer
+
+
+
+ Si activée, la notation de la communauté pour les épisodes de séries TV ne sera pas affichée. Cela permet d'empêcher de dévoiler les bons ou mauvais épisodes à venir.
+
+
+
+ Apparence
+
+
+
+ Texte des sous-titres uniquement
+ Name of a setting - should we hide subtitles that might transcode
+
+
+
+ Diaporama relancé
+
+
+
+ Options pour l'écran de veille de Jellyfin.
+ Description for Screensaver user settings.
+
+
+
+ H.264
+ Name of codec used in settings menu
+
+
+
+ Flouter les épisodes non visionnés
+ Option Title in user setting screen
+
+
+
+ Options pour les séries TV.
+ Description for TV Shows user settings.
+
+
+
+ Si activé, les illustrations des épisodes non visionnés seront floutées.
+
+
+
+ Utiliser une image de présentation comme fond d'écran de veille
+ Option Title in user setting screen
+
+
+
+ Options qui modifient l'apparence de Jellyfin.
+ Description for Design Elements user settings.
+
+
+
+ Mode cinéma
+ Settings Menu - Title for option
+
+
+
+ Le mode cinéma apporte l'expérience du cinéma directement dans votre salon grâce à la possibilité de lire des bandes-annonces et des introductions personnalisées avant le film principal.
+ Settings Menu - Description for option
+
+
+
+ Masquer l'horloge
+ Option Title in user setting screen
+
+
+
+ Lire la bande-annonce
+
+
+
+ Tente la lecture directe du codec H.264 comportant des niveaux de profils incompatibles avant de transcoder si cela échoue.
+ Settings Menu - Description for option
+
+
+
+ HEVC
+ Name of codec used in settings menu
+
+
+
+ Réglages relatifs à la lecture et à la prise en charge des différents codecs et types de médias.
+
+
+
+ Codec vidéo
+
+
+
+ Canaux audio
+
+
+
+ Informations de flux
+
+
+
+ Codec
+
+
+
+ Niveau
+ Video profile level
+
+
+
+ Taille
+ Video size
+
+
+
+ Affiche seulement le texte des sous-titres pour minimiser l'impact du transcodage.
+ Description of a setting - should we hide subtitles that might transcode
+
+
+
+ Informations de lecture
+
+
+
+ Afficher la fenêtre contextuelle des nouveautés
+ Settings Menu - Title for option
+
+
+
+ Débit total
+
+
+
+ Artistes (liste)
+
+
+
+ Chanson
+
+
+
+ Artistes (diaporama)
+
+
+
+ Chansons
+
+
+
+ Album
+
+
+
+ Albums
+
+
+
+ Étiquette du codec
+
+
+
+ Désactiver la notation de la communauté pour les épisodes
+
+
+
+ Diaporama désactivé
+
+
+
+ Diaporama mis en pause
+
+
+
+ Prise en charge du codec MPEG-4
+ Settings Menu - Title for option
+
+
+
+ Non lu
+
+
+
+ Nombre maximal de jours dans la section 'À suivre'
+ Option Title in user setting screen
+
+
+
+ Débit
+ Video streaming bit rate
+
+
+
+ Conteneur
+ Video streaming container
+
+
+
+ Diffusé
+ Aired date label
+
+
+
+ Écran de veille
+
+
+
+ Utiliser une image de présentation comme fond d'écran d’accueil
+ Option Title in user setting screen
+
+
+
+ Réglages relatifs à l'apparence de l'application.
+
+
+
+ Page d'accueil
+
+
+
+ Options pour la page d’accueil.
+ Description for Home Page user settings.
+
+
+
+ Codec audio
+
+
+
+ direct
+
+
+
+ Format de pixel
+ Video pixel format
+
+
+
+ L × H
+ Video width x height
+
+
+
+ Aucun album ou chanson de cet artiste n'a été trouvé
+ Popup message when we find no audio data for an artist
+
+
+
+ tout
+ all will reset the searchTerm so all data will be availible
+
+
+
+ Lecture aléatoire désactivée
+
+
+
+ Lecture aléatoire activée
+
+
+
+ Lu
+
+
+
+ Reprise possible
+
+
+
+ Informations de transcodage
+
diff --git a/locale/fr_CA/translations.ts b/locale/fr_CA/translations.ts
index acba06f5..41a2008c 100644
--- a/locale/fr_CA/translations.ts
+++ b/locale/fr_CA/translations.ts
@@ -1124,5 +1124,53 @@
Changer de serveur
+
+
+ Chargement des données de la chaîne
+
+
+
+ Erreur lors du chargement des données de la chaîne
+
+
+
+ En ce moment
+
+
+
+ Erreur lors de la récupération du contenu
+ Dialog title when unable to load Content from Server
+
+
+
+ Une erreur s'est produite lors de la lecture de cet élément.
+ Dialog detail when error occurs during playback
+
+
+
+ Changer de serveur
+
+
+
+ Se déconnecter
+
+
+
+ Sauvegarder les informations d'authentification ?
+
+
+
+ Supprimer les valeurs enregistrées
+
+
+
+ Erreur lors de la lecture
+ Dialog title when error occurs during playback
+
+
+
+ Une erreur s'est produite lors de la récupération des données de cet élément depuis le serveur.
+ Dialog detail when unable to load Content from Server
+
diff --git a/locale/hu/translations.ts b/locale/hu/translations.ts
index d5de9202..f2d7e577 100644
--- a/locale/hu/translations.ts
+++ b/locale/hu/translations.ts
@@ -6,7 +6,7 @@
default
- alapértelmezetten 192.168.1.100:8096 vagy https://example.com/jellyfin
+ Alapértelmezetten: 192.168.1.100:8096 vagy https://example.com/jellyfin
@@ -7681,5 +7681,2503 @@ elemeket
Hiba történt a lejátszás közbenDialog title when error occurs during playback
+
+
+ Mented a hitelesítő adatokat?
+
+
+
+ Hiba történt a lejátszás közben
+ Dialog title when error occurs during playback
+
+
+
+ Média rács beállítások.
+
+
+
+ Hiba történt az elem(ek) betöltése során a szerverről.
+ Dialog detail when unable to load Content from Server
+
+
+
+ Hétfő
+ Day of Week
+
+
+
+ Hiba történt az elem lejátszása közben.
+ Dialog detail when error occurs during playback
+
+
+
+ Hiba történt a csatornaadatok betöltésekor
+
+
+
+ Nem lehet betölteni a csatornaadatokat a szerverről
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Ez a(z) %1 nem tartalmaz elemeket
+
+
+
+ Kritikusok Értékelése
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Nézet
+
+
+
+ Vége volt
+ (Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00)
+
+
+
+ Hiba történt az elem lejátszása közben. A szerver nem biztosította a szükséges transzkódolási adatokat.
+ Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url
+
+
+
+ A Direct Play engedélyezése vagy letiltása az opcionális kodekekhez
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Csak szöveges feliratok
+ Name of a setting - should we hide subtitles that might transcode
+
+
+
+ Támogatja az MPEG-2 tartalom közvetlen lejátszását (például élő tévéadás). Ez megakadályozza az MPEG-2 tartalom átkódolását, de lényegesen nagyobb sávszélességet használ.
+ Settings Menu - Description for option
+
+
+
+ **KÍSÉRLETI** Az AV1 tartalom közvetlen lejátszásának támogatása, ha ez a Roku eszköz támogatja.
+ Description of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Használja a generált splashscreen képet Jellyfin képernyővédő háttereként. A Jellyfint újra meg kell nyitni, hogy a változás életbe lépjen.
+
+
+
+ A Mozi Mód a moziélményt egyenesen a nappaliba viszi azzal a lehetőséggel, hogy egyéni bevezetőket játszhat le a fő funkció előtt.
+ Settings Menu - Description for option
+
+
+
+ Elrejti az összes órát a Jellyfinben. A Jellyfint újra kell nyitni, hogy a változás életbe lépjen.
+ Settings Menu - Description for option
+
+
+
+ A lejátszással, valamint a támogatott kodekekkel és médiatípusokkal kapcsolatos beállítások.
+
+
+
+ Az alkalmazás megjelenésével kapcsolatos beállítások.
+
+
+
+ Bitráta
+ Video streaming bit rate
+
+
+
+ Próbálja meg a nem támogatott profilszintű H.264-es adathordozók közvetlen lejátszását, mielőtt visszaállna az átkódolásra, ha az sikertelen.
+ Settings Menu - Description for option
+
+
+
+ Csak a szöveges feliratokat jelenítse meg az átkódolás minimalizálása érdekében.
+ Description of a setting - should we hide subtitles that might transcode
+
+
+
+ Stúdiók
+
+
+
+ %1 a %2 -ból
+ Item position and count. %1 = current item. %2 = total number of items
+
+
+
+ Elhunyt
+
+
+
+ Hiba a tartalom lekérésekor
+ Dialog title when unable to load Content from Server
+
+
+
+ Csatornaadatok betöltése
+
+
+ Name or Title field of media item
+
+ Név
+
+
+
+ IMDb Értékelés
+
+
+
+ Hozzáadva
+
+
+
+ Utoljára lejátszva
+
+
+
+ Korhatár
+
+
+
+ Lejátszások Száma
+
+
+
+ Megjelenés dátuma
+
+
+
+ Játékidő
+
+
+ Title of Tab for options to sort library content
+
+ Rendezés
+
+
+ Title of Tab for options to filter library content
+
+ Szűrő
+
+
+
+ Született
+
+
+
+ Kor
+
+
+
+ Szereplők & Stáb
+
+
+
+ Több hasonló
+
+
+
+ Lejátszás
+ Title for Playback section in user setting screen.
+
+
+
+ Óra elrejtése
+ Option Title in user setting screen
+
+
+
+ Előzetes lejátszása
+
+
+
+ Mentettek Törlése
+
+
+
+ Most
+
+
+
+ Nyomd meg az „OK” gombot a bezáráshoz
+
+
+
+ Sajátosságok
+
+
+
+ További részek
+ Additional parts of a video
+
+
+
+ TV Sorozatok
+
+
+
+ ma
+ Current day
+
+
+
+ Vasárnap
+ Day of Week
+
+
+
+ Kedd
+ Day of Week
+
+
+
+ Szerda
+ Day of Week
+
+
+
+ Csütörtök
+ Day of Week
+
+
+
+ Szombat
+ Day of Week
+
+
+
+ Ekkor kezdődött
+ (Past Tense) For defining time when a program started today (e.g. Started at 08:00)
+
+
+
+ Kezdődik majd
+ (Future Tense) For defining time when a program will start today (e.g. Starts at 08:00)
+
+
+
+ Kezdődni fog
+ (Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00)
+
+
+
+ Vége lett
+ (Past Tense) For defining time when a program will ended (e.g. Ended at 08:00)
+
+
+
+ Élő
+ If TV Show is being broadcast live (not pre-recorded)
+
+
+
+ Műsorújság
+ Menu option for showing Live TV Guide / Schedule
+
+
+
+ Sorozat felvétele
+
+
+
+ Felvétel megállítása
+
+
+
+ Bezárás
+
+
+
+ Add meg a szerver nevét vagy IP-címét
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ Válassz ki egy Jellyfin szervert a helyi hálózatról:
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ …vagy add meg kézzel a szerver URL-jét:
+ Instructions on initial app launch when the user is asked to manually enter a server URL
+
+
+
+ Hiba a lejátszási információk lekérésekor
+ Dialog Title: Received error from server when trying to get information about the selected item for playback
+
+
+
+ Íme a Gyorscsatlakozási kódod:
+
+
+
+ Címsorok elrejtése
+ Option Title in user setting screen
+
+
+
+ Jellyfin képernyőkímélőjének beállításai.
+ Description for Screensaver user settings.
+
+
+
+ Dizájn elemek
+
+
+
+ Következő rész
+
+
+
+ Próbálja meg a közvetlen lejátszást nem támogatott profilszintű HEVC-média esetén, mielőtt visszaállna az átkódolásra, ha az sikertelen.
+ Settings Menu - Description for option
+
+
+
+ Filmek (bemutató)
+ Movie library view option
+
+
+
+ Filmek (Rács)
+ Movie library view option
+
+
+
+ Péntek
+ Day of Week
+
+
+
+ Kezdődött
+ (Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00)
+
+
+
+ Sorozatfelvétel leállítása
+
+
+
+ Csatlakozás a szerverhez
+ Message to display to user while client is attempting to connect to the server
+
+
+
+ Verzió
+
+
+
+ Kodek támogatás
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Média Rács
+ UI -> Media Grid section in user setting screen.
+
+
+
+ MPEG-2
+ Name of codec used in settings menu
+
+
+
+ Megnézve
+ Button Text - When pressed, marks item as Warched
+
+
+
+ Részletező oldal
+
+
+
+ A megtekintetlen epizódok elhomályosítása
+ Option Title in user setting screen
+
+
+
+ Ha engedélyezve van, a megtekintetlen epizódok képei elmosódnak.
+
+
+
+ MPEG-4
+ Name of codec used in settings menu
+
+
+
+ Támogatja az MPEG-4 tartalom közvetlen lejátszását. Lehet, hogy ezt ki kell kapcsolni a DIVX kódolású videofájlok lejátszásához.
+ Settings Menu - Description for option
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Felhasználói felület
+ Title for User Interface section in user setting screen.
+
+
+
+ Fájl Címek
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Mindig jelenítse meg a címeket a poszterképek alatt. (Ha le van tiltva, a cím csak a kiemelt elem alatt jelenik meg).
+ Description for option in Setting Screen
+
+
+
+ Elemek száma
+ UI -> Media Grid -> Item Count in user setting screen.
+
+
+
+ Elemszám megjelenítése a könyvtárban és a kiválasztott elem indexében.
+ Description for option in Setting Screen
+
+
+
+ Kedvenc hozzáadása
+ Button Text - When pressed, sets item as Favorite
+
+
+
+ Ugrás a sorozatra
+ Continue Watching Popup Menu - Navigate to the Series Detail Page
+
+
+
+ Ugrás az évadra
+ Continue Watching Popup Menu - Navigate to the Season Page
+
+
+
+ Ugrás az epizódra
+ Continue Watching Popup Menu - Navigate to the Episode Detail Page
+
+
+
+ Használja a távirányító hangbevitelét a kereséshez
+ Help text in search voice text box
+
+
+
+ Keresés most
+ Help text in search Box
+
+
+
+ Kereshet Címekre, Személyekre, Élő TV-csatornákra és egyebekre
+ Help text in search results
+
+
+
+ Gyorscsatlakozás
+
+
+
+ (A párbeszédablak automatikusan bezárul)
+
+
+
+ Hiba történt a Gyorscsatlakozás segítségével történő hitelesítés során.
+
+
+
+ Hálózatok
+
+
+
+ Műsorok
+
+
+
+ Vissza a tetejére
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Mozi Mód
+ Settings Menu - Title for option
+
+
+
+ A visszajátszás gombbal lassan animálhat a mappa első elemére. (Ha le van tiltva, a mappa azonnal visszaáll az első elemre).
+ Description for option in Setting Screen
+
+
+
+ Részletek oldal beállításai.
+ Description for Details page user settings.
+
+
+
+ Elrejti a címszó szövegét a részletező oldalakon.
+
+
+
+ TV-műsorok beállításai.
+ Description for TV Shows user settings.
+
+
+
+ Képernyőkímélő
+
+
+
+ Használja a Splashscreent képernyővédő háttereként
+ Option Title in user setting screen
+
+
+
+ Videókodek
+
+
+
+ Ha engedélyezve van, a csak egy évadot tartalmazó tévésorozat kiválasztása közvetlenül az epizódlistába kerül, nem pedig a műsor részleteinek és évadlistájának.
+ Settings Menu - Description for option
+
+
+
+ Kodek
+
+
+
+ Kodek jelölés
+
+
+
+ Opciók, amelyek megváltoztatják a Jellyfin dizájnját.
+ Description for Design Elements user settings.
+
+
+
+ Használja a Splashscreent a kezdőképernyő háttereként
+ Option Title in user setting screen
+
+
+
+ Konténer
+ Video streaming container
+
+
+
+ Használja a generált indítóképernyős képet Jellyfin otthoni háttereként. A Jellyfint újra kell nyitni, hogy a változás életbe lépjen.
+ Description for option in Setting Screen
+
+
+
+ Diavetítés kikapcsolva
+
+
+
+ H.264
+ Name of codec used in settings menu
+
+
+
+ Sugározva
+ Aired date label
+
+
+
+ HEVC
+ Name of codec used in settings menu
+
+
+
+ Kezdőlap
+
+
+
+ A kezdőlap beállításai.
+ Description for Home Page user settings.
+
+
+
+ Véletlenszerű kikapcsolva
+
+
+
+ MPEG-4 Támogatás
+ Settings Menu - Title for option
+
+
+
+ Véletlenszerű bekapcsolva
+
+
+
+ Folytatható
+
+
+
+ Játszott
+
+
+
+ Állítsa be, hogy egy műsor mennyi ideig maradjon a „Következő” listában anélkül, hogy megnézné.
+ Settings Menu - Description for option
+
+
+
+ Lejátszási információk
+
+
+
+ Transzkódolási információk
+
+
+
+ Oka
+
+
+
+ Audiókodek
+
+
+
+ direkt
+
+
+
+ Teljes Bitráta
+
+
+
+ Audiocsatornák
+
+
+
+ Adatfolyam információ
+
+
+
+ Szint
+ Video profile level
+
+
+
+ Méret
+ Video size
+
+
+
+ Videó tartomány típusa
+
+
+
+ Pixel formátum
+ Video pixel format
+
+
+
+ Szélesség x Magasság
+ Video width x height
+
+
+
+ Nem találhatók ehhez az előadóhoz tartozó albumok vagy dalok
+ Popup message when we find no audio data for an artist
+
+
+
+ összes
+ all will reset the searchTerm so all data will be availible
+
+
+
+ Diavetítés bekapcsolva
+
+
+
+ Diavetítés szüneteltetve
+
+
+
+ Diavetítés folytatódik
+
+
+
+ Az Újdonságok előugró ablak megjelenítése, amikor a Jellyfin új verzióra frissül.
+ Settings Menu - Description for option
+
+
+
+ Nem játszott
+
+
+
+ Az újdonságok előugró ablaka
+ Settings Menu - Title for option
+
+
+
+ Maximális napok száma a Következőhöz
+ Option Title in user setting screen
+
+
+
+ Filmek
+
+
+
+ tegnap
+ Previous day
+
+
+
+ holnap
+ Next day
+
+
+
+ Ismétlés
+ If TV Shows has previously been broadcasted
+
+
+
+ Csatornák
+ Menu option for showing Live TV Channel List
+
+
+
+ Csatorna Megtekintése
+
+
+
+ Felvétel
+
+
+
+ Nem található
+ Title of message box when the requested content is not found on the server
+
+
+
+ Ismeretlen
+ Title for a cast member for which we have no information for
+
+
+
+ A kért tartalom nem található a szerveren
+ Content of message box when the requested content is not found on the server
+
+
+
+ Engedélyezve
+
+
+
+ Kikapcsolva
+
+
+
+ Részletek kihagyása a külön évadokhoz
+ Settings Menu - Title for option
+
+
+
+ Mented a hitelesítő adatokat?
+
+
+
+ Mentettek Törlése
+
+
+
+ Most
+
+
+
+ Hiba történt a lejátszás közben
+ Dialog title when error occurs during playback
+
+
+
+ Lejátszások Száma
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Nézet
+
+
+
+ Több hasonló
+
+
+
+ Kezdődik majd
+ (Future Tense) For defining time when a program will start today (e.g. Starts at 08:00)
+
+
+
+ Add meg a szerver nevét vagy IP-címét
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ Hétfő
+ Day of Week
+
+
+
+ Vége volt
+ (Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00)
+
+
+
+ Hiba történt a csatornaadatok betöltésekor
+
+
+
+ Kritikusok Értékelése
+
+
+
+ Elhunyt
+
+
+
+ Hiba a tartalom lekérésekor
+ Dialog title when unable to load Content from Server
+
+
+
+ Csatornaadatok betöltése
+
+
+ Name or Title field of media item
+
+ Név
+
+
+
+ Korhatár
+
+
+
+ Játékidő
+
+
+ Title of Tab for options to filter library content
+
+ Szűrő
+
+
+
+ IMDb Értékelés
+
+
+
+ Hozzáadva
+
+
+
+ Megjelenés dátuma
+
+
+ Title of Tab for options to sort library content
+
+ Rendezés
+
+
+
+ Filmek (Rács)
+ Movie library view option
+
+
+
+ Szerda
+ Day of Week
+
+
+
+ Kezdődött
+ (Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00)
+
+
+
+ Hiba történt az elem(ek) betöltése során a szerverről.
+ Dialog detail when unable to load Content from Server
+
+
+
+ Hiba történt az elem lejátszása közben.
+ Dialog detail when error occurs during playback
+
+
+
+ Nem lehet betölteni a csatornaadatokat a szerverről
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Ez a(z) %1 nem tartalmaz elemeket
+
+
+
+ Utoljára lejátszva
+
+
+
+ Született
+
+
+
+ Kor
+
+
+
+ Szereplők & Stáb
+
+
+
+ Nyomd meg az „OK” gombot a bezáráshoz
+
+
+
+ További részek
+ Additional parts of a video
+
+
+
+ Sajátosságok
+
+
+
+ TV Sorozatok
+
+
+
+ ma
+ Current day
+
+
+
+ Vasárnap
+ Day of Week
+
+
+
+ Kedd
+ Day of Week
+
+
+
+ Csütörtök
+ Day of Week
+
+
+
+ Szombat
+ Day of Week
+
+
+
+ Ekkor kezdődött
+ (Past Tense) For defining time when a program started today (e.g. Started at 08:00)
+
+
+
+ Kezdődni fog
+ (Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00)
+
+
+
+ Vége lett
+ (Past Tense) For defining time when a program will ended (e.g. Ended at 08:00)
+
+
+
+ Élő
+ If TV Show is being broadcast live (not pre-recorded)
+
+
+
+ Műsorújság
+ Menu option for showing Live TV Guide / Schedule
+
+
+
+ Sorozat felvétele
+
+
+
+ Felvétel megállítása
+
+
+
+ Bezárás
+
+
+
+ Filmek (bemutató)
+ Movie library view option
+
+
+
+ Péntek
+ Day of Week
+
+
+
+ Sorozatfelvétel leállítása
+
+
+
+ Csatlakozás a szerverhez
+ Message to display to user while client is attempting to connect to the server
+
+
+
+ Filmek
+
+
+
+ tegnap
+ Previous day
+
+
+
+ holnap
+ Next day
+
+
+
+ Ismétlés
+ If TV Shows has previously been broadcasted
+
+
+
+ Csatornák
+ Menu option for showing Live TV Channel List
+
+
+
+ Csatorna Megtekintése
+
+
+
+ Felvétel
+
+
+
+ Nem található
+ Title of message box when the requested content is not found on the server
+
+
+
+ Ismeretlen
+ Title for a cast member for which we have no information for
+
+
+
+ A kért tartalom nem található a szerveren
+ Content of message box when the requested content is not found on the server
+
+
+
+ …vagy add meg kézzel a szerver URL-jét:
+ Instructions on initial app launch when the user is asked to manually enter a server URL
+
+
+
+ Hiba történt az elem lejátszása közben. A szerver nem biztosította a szükséges transzkódolási adatokat.
+ Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url
+
+
+
+ Lejátszás
+ Title for Playback section in user setting screen.
+
+
+
+ Támogatja az MPEG-2 tartalom közvetlen lejátszását (például élő tévéadás). Ez megakadályozza az MPEG-2 tartalom átkódolását, de lényegesen nagyobb sávszélességet használ.
+ Settings Menu - Description for option
+
+
+
+ Válassz ki egy Jellyfin szervert a helyi hálózatról:
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ A Direct Play engedélyezése vagy letiltása az opcionális kodekekhez
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Támogatja az MPEG-4 tartalom közvetlen lejátszását. Lehet, hogy ezt ki kell kapcsolni a DIVX kódolású videofájlok lejátszásához.
+ Settings Menu - Description for option
+
+
+
+ **KÍSÉRLETI** Az AV1 tartalom közvetlen lejátszásának támogatása, ha ez a Roku eszköz támogatja.
+ Description of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Hiba a lejátszási információk lekérésekor
+ Dialog Title: Received error from server when trying to get information about the selected item for playback
+
+
+
+ Verzió
+
+
+
+ Kodek támogatás
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Média Rács
+ UI -> Media Grid section in user setting screen.
+
+
+
+ MPEG-2
+ Name of codec used in settings menu
+
+
+
+ MPEG-4
+ Name of codec used in settings menu
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Felhasználói felület
+ Title for User Interface section in user setting screen.
+
+
+
+ Engedélyezve
+
+
+
+ Kikapcsolva
+
+
+
+ Média rács beállítások.
+
+
+
+ Mindig jelenítse meg a címeket a poszterképek alatt. (Ha le van tiltva, a cím csak a kiemelt elem alatt jelenik meg).
+ Description for option in Setting Screen
+
+
+
+ Ugrás a sorozatra
+ Continue Watching Popup Menu - Navigate to the Series Detail Page
+
+
+
+ Íme a Gyorscsatlakozási kódod:
+
+
+
+ Ha engedélyezve van, a csak egy évadot tartalmazó tévésorozat kiválasztása közvetlenül az epizódlistába kerül, nem pedig a műsor részleteinek és évadlistájának.
+ Settings Menu - Description for option
+
+
+
+ Maximális napok száma a Következőhöz
+ Option Title in user setting screen
+
+
+
+ Stúdiók
+
+
+
+ Óra elrejtése
+ Option Title in user setting screen
+
+
+
+ Előzetes lejátszása
+
+
+
+ Próbálja meg a nem támogatott profilszintű H.264-es adathordozók közvetlen lejátszását, mielőtt visszaállna az átkódolásra, ha az sikertelen.
+ Settings Menu - Description for option
+
+
+
+ Használja a távirányító hangbevitelét a kereséshez
+ Help text in search voice text box
+
+
+
+ (A párbeszédablak automatikusan bezárul)
+
+
+
+ Fájl Címek
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Elemek száma
+ UI -> Media Grid -> Item Count in user setting screen.
+
+
+
+ Elemszám megjelenítése a könyvtárban és a kiválasztott elem indexében.
+ Description for option in Setting Screen
+
+
+
+ Kedvenc hozzáadása
+ Button Text - When pressed, sets item as Favorite
+
+
+
+ Ugrás az epizódra
+ Continue Watching Popup Menu - Navigate to the Episode Detail Page
+
+
+
+ Kereshet Címekre, Személyekre, Élő TV-csatornákra és egyebekre
+ Help text in search results
+
+
+
+ %1 a %2 -ból
+ Item position and count. %1 = current item. %2 = total number of items
+
+
+
+ Műsorok
+
+
+
+ Használja a generált splashscreen képet Jellyfin képernyővédő háttereként. A Jellyfint újra meg kell nyitni, hogy a változás életbe lépjen.
+
+
+
+ Használja a Splashscreent a kezdőképernyő háttereként
+ Option Title in user setting screen
+
+
+
+ A Mozi Mód a moziélményt egyenesen a nappaliba viszi azzal a lehetőséggel, hogy egyéni bevezetőket játszhat le a fő funkció előtt.
+ Settings Menu - Description for option
+
+
+
+ Elrejti az összes órát a Jellyfinben. A Jellyfint újra kell nyitni, hogy a változás életbe lépjen.
+ Settings Menu - Description for option
+
+
+
+ A lejátszással, valamint a támogatott kodekekkel és médiatípusokkal kapcsolatos beállítások.
+
+
+
+ Az alkalmazás megjelenésével kapcsolatos beállítások.
+
+
+
+ Címsorok elrejtése
+ Option Title in user setting screen
+
+
+
+ Jellyfin képernyőkímélőjének beállításai.
+ Description for Screensaver user settings.
+
+
+
+ Dizájn elemek
+
+
+
+ Következő rész
+
+
+
+ Próbálja meg a közvetlen lejátszást nem támogatott profilszintű HEVC-média esetén, mielőtt visszaállna az átkódolásra, ha az sikertelen.
+ Settings Menu - Description for option
+
+
+
+ Megnézve
+ Button Text - When pressed, marks item as Warched
+
+
+
+ Részletező oldal
+
+
+
+ A megtekintetlen epizódok elhomályosítása
+ Option Title in user setting screen
+
+
+
+ Ha engedélyezve van, a megtekintetlen epizódok képei elmosódnak.
+
+
+
+ Ugrás az évadra
+ Continue Watching Popup Menu - Navigate to the Season Page
+
+
+
+ Keresés most
+ Help text in search Box
+
+
+
+ Gyorscsatlakozás
+
+
+
+ Hiba történt a Gyorscsatlakozás segítségével történő hitelesítés során.
+
+
+
+ Hálózatok
+
+
+
+ Vissza a tetejére
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Mozi Mód
+ Settings Menu - Title for option
+
+
+
+ A visszajátszás gombbal lassan animálhat a mappa első elemére. (Ha le van tiltva, a mappa azonnal visszaáll az első elemre).
+ Description for option in Setting Screen
+
+
+
+ Részletek oldal beállításai.
+ Description for Details page user settings.
+
+
+
+ Elrejti a címszó szövegét a részletező oldalakon.
+
+
+
+ TV-műsorok beállításai.
+ Description for TV Shows user settings.
+
+
+
+ Képernyőkímélő
+
+
+
+ Használja a Splashscreent képernyővédő háttereként
+ Option Title in user setting screen
+
+
+
+ Videókodek
+
+
+
+ Opciók, amelyek megváltoztatják a Jellyfin dizájnját.
+ Description for Design Elements user settings.
+
+
+
+ Használja a generált indítóképernyős képet Jellyfin otthoni háttereként. A Jellyfint újra kell nyitni, hogy a változás életbe lépjen.
+ Description for option in Setting Screen
+
+
+
+ H.264
+ Name of codec used in settings menu
+
+
+
+ HEVC
+ Name of codec used in settings menu
+
+
+
+ Kezdőlap
+
+
+
+ A kezdőlap beállításai.
+ Description for Home Page user settings.
+
+
+
+ Állítsa be, hogy egy műsor mennyi ideig maradjon a „Következő” listában anélkül, hogy megnézné.
+ Settings Menu - Description for option
+
+
+
+ Lejátszási információk
+
+
+
+ Transzkódolási információk
+
+
+
+ Oka
+
+
+
+ Csak a szöveges feliratokat jelenítse meg az átkódolás minimalizálása érdekében.
+ Description of a setting - should we hide subtitles that might transcode
+
+
+
+ Bitráta
+ Video streaming bit rate
+
+
+
+ Az újdonságok előugró ablaka
+ Settings Menu - Title for option
+
+
+
+ Kodek jelölés
+
+
+
+ Csak szöveges feliratok
+ Name of a setting - should we hide subtitles that might transcode
+
+
+
+ összes
+ all will reset the searchTerm so all data will be availible
+
+
+
+ Diavetítés bekapcsolva
+
+
+
+ Diavetítés szüneteltetve
+
+
+
+ Diavetítés folytatódik
+
+
+
+ Véletlenszerű kikapcsolva
+
+
+
+ Az Újdonságok előugró ablak megjelenítése, amikor a Jellyfin új verzióra frissül.
+ Settings Menu - Description for option
+
+
+
+ Kodek
+
+
+
+ Konténer
+ Video streaming container
+
+
+
+ Sugározva
+ Aired date label
+
+
+
+ Diavetítés kikapcsolva
+
+
+
+ Véletlenszerű bekapcsolva
+
+
+
+ MPEG-4 Támogatás
+ Settings Menu - Title for option
+
+
+
+ Játszott
+
+
+
+ Folytatható
+
+
+
+ Audiókodek
+
+
+
+ direkt
+
+
+
+ Teljes Bitráta
+
+
+
+ Audiocsatornák
+
+
+
+ Adatfolyam információ
+
+
+
+ Szint
+ Video profile level
+
+
+
+ Méret
+ Video size
+
+
+
+ Videó tartomány típusa
+
+
+
+ Pixel formátum
+ Video pixel format
+
+
+
+ Szélesség x Magasság
+ Video width x height
+
+
+
+ Nem találhatók ehhez az előadóhoz tartozó albumok vagy dalok
+ Popup message when we find no audio data for an artist
+
+
+
+ Nem játszott
+
+
+
+ Ha engedélyezve van, a tévéműsorok epizódjainak csillaga és közösségi besorolása el lesz távolítva. Ez azért van így, hogy elkerüljük egy közelgő jó/rossz epizód spoilereit.
+
+
+
+ Dal
+
+
+
+ Dalok
+
+
+
+ Album
+
+
+
+ Albumok
+
+
+
+ Összes megtekintése
+
+
+
+ Előadó (Bemutató)
+
+
+
+ Előadó (Rács)
+
+
+
+ Az epizódok közösségi értékelésének letiltása
+
+
+
+ Lejátszások Száma
+
+
+
+ Több hasonló
+
+
+
+ Kor
+
+
+
+ Mented a hitelesítő adatokat?
+
+
+
+ Kedvenc hozzáadása
+ Button Text - When pressed, sets item as Favorite
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Nézet
+
+
+
+ Nyomd meg az „OK” gombot a bezáráshoz
+
+
+
+ Felvétel megállítása
+
+
+
+ Válassz ki egy Jellyfin szervert a helyi hálózatról:
+ Instructions on initial app launch when the user is asked to pick a server from a list
+
+
+
+ Média rács beállítások.
+
+
+
+ Hiba történt a lejátszás közben
+ Dialog title when error occurs during playback
+
+
+
+ Hiba történt az elem lejátszása közben.
+ Dialog detail when error occurs during playback
+
+
+
+ Nem lehet betölteni a csatornaadatokat a szerverről
+
+
+
+ Korhatár
+
+
+
+ Hétfő
+ Day of Week
+
+
+
+ Kezdődik majd
+ (Future Tense) For defining time when a program will start today (e.g. Starts at 08:00)
+
+
+
+ Vége volt
+ (Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00)
+
+
+
+ Add meg a szerver nevét vagy IP-címét
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ …vagy add meg kézzel a szerver URL-jét:
+ Instructions on initial app launch when the user is asked to manually enter a server URL
+
+
+
+ Hiba történt az elem lejátszása közben. A szerver nem biztosította a szükséges transzkódolási adatokat.
+ Content of message box when trying to play an item which requires transcoding, and the server did not provide transcode url
+
+
+
+ Lejátszás
+ Title for Playback section in user setting screen.
+
+
+
+ A Direct Play engedélyezése vagy letiltása az opcionális kodekekhez
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ Támogatja az MPEG-2 tartalom közvetlen lejátszását (például élő tévéadás). Ez megakadályozza az MPEG-2 tartalom átkódolását, de lényegesen nagyobb sávszélességet használ.
+ Settings Menu - Description for option
+
+
+
+ **KÍSÉRLETI** Az AV1 tartalom közvetlen lejátszásának támogatása, ha ez a Roku eszköz támogatja.
+ Description of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Mindig jelenítse meg a címeket a poszterképek alatt. (Ha le van tiltva, a cím csak a kiemelt elem alatt jelenik meg).
+ Description for option in Setting Screen
+
+
+
+ Hiba történt a csatornaadatok betöltésekor
+
+
+
+ Kritikusok Értékelése
+
+
+
+ Elhunyt
+
+
+
+ Hiba a tartalom lekérésekor
+ Dialog title when unable to load Content from Server
+
+
+
+ Csatornaadatok betöltése
+
+
+ Name or Title field of media item
+
+ Név
+
+
+
+ Játékidő
+
+
+ Title of Tab for options to filter library content
+
+ Szűrő
+
+
+
+ IMDb Értékelés
+
+
+
+ Hozzáadva
+
+
+
+ Megjelenés dátuma
+
+
+ Title of Tab for options to sort library content
+
+ Rendezés
+
+
+
+ Filmek (Rács)
+
+
+
+ Szerda
+ Day of Week
+
+
+
+ Kezdődött
+ (Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00)
+
+
+
+ Hiba történt az elem(ek) betöltése során a szerverről.
+ Dialog detail when unable to load Content from Server
+
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Ez a(z) %1 nem tartalmaz elemeket
+
+
+
+ Utoljára lejátszva
+
+
+
+ Született
+
+
+
+ Szereplők & Stáb
+
+
+
+ További részek
+ Additional parts of a video
+
+
+
+ Támogatja az MPEG-4 tartalom közvetlen lejátszását. Lehet, hogy ezt ki kell kapcsolni a DIVX kódolású videofájlok lejátszásához.
+ Settings Menu - Description for option
+
+
+
+ Fájl Címek
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Elemek száma
+ UI -> Media Grid -> Item Count in user setting screen.
+
+
+
+ Elemszám megjelenítése a könyvtárban és a kiválasztott elem indexében.
+ Description for option in Setting Screen
+
+
+
+ Mentettek Törlése
+
+
+
+ Most
+
+
+
+ Sajátosságok
+
+
+
+ TV Sorozatok
+
+
+
+ ma
+ Current day
+
+
+
+ Vasárnap
+ Day of Week
+
+
+
+ Kedd
+ Day of Week
+
+
+
+ Csütörtök
+ Day of Week
+
+
+
+ Szombat
+ Day of Week
+
+
+
+ Ekkor kezdődött
+ (Past Tense) For defining time when a program started today (e.g. Started at 08:00)
+
+
+
+ Kezdődni fog
+ (Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00)
+
+
+
+ Vége lett
+ (Past Tense) For defining time when a program will ended (e.g. Ended at 08:00)
+
+
+
+ Élő
+ If TV Show is being broadcast live (not pre-recorded)
+
+
+
+ Műsorújság
+ Menu option for showing Live TV Guide / Schedule
+
+
+
+ Sorozat felvétele
+
+
+
+ Bezárás
+
+
+
+ Hiba a lejátszási információk lekérésekor
+ Dialog Title: Received error from server when trying to get information about the selected item for playback
+
+
+
+ Filmek (bemutató)
+
+
+
+ Péntek
+ Day of Week
+
+
+
+ Sorozatfelvétel leállítása
+
+
+
+ Csatlakozás a szerverhez
+ Message to display to user while client is attempting to connect to the server
+
+
+
+ Verzió
+
+
+
+ Média Rács
+ UI -> Media Grid section in user setting screen.
+
+
+
+ Kodek támogatás
+ Settings Menu - Title for settings group related to codec support
+
+
+
+ MPEG-2
+ Name of codec used in settings menu
+
+
+
+ Megnézve
+ Button Text - When pressed, marks item as Warched
+
+
+
+ MPEG-4
+ Name of codec used in settings menu
+
+
+
+ AV1
+ Name of a setting - should we try to direct play experimental av1 codec
+
+
+
+ Felhasználói felület
+ Title for User Interface section in user setting screen.
+
+
+
+ Filmek
+
+
+
+ tegnap
+ Previous day
+
+
+
+ holnap
+ Next day
+
+
+
+ Ismétlés
+ If TV Shows has previously been broadcasted
+
+
+
+ Csatornák
+ Menu option for showing Live TV Channel List
+
+
+
+ Csatorna Megtekintése
+
+
+
+ Felvétel
+
+
+
+ Nem található
+ Title of message box when the requested content is not found on the server
+
+
+
+ Ismeretlen
+ Title for a cast member for which we have no information for
+
+
+
+ A kért tartalom nem található a szerveren
+ Content of message box when the requested content is not found on the server
+
+
+
+ Engedélyezve
+
+
+
+ Kikapcsolva
+
+
+
+ Ugrás a sorozatra
+ Continue Watching Popup Menu - Navigate to the Series Detail Page
+
+
+
+ A visszajátszás gombbal lassan animálhat a mappa első elemére. (Ha le van tiltva, a mappa azonnal visszaáll az első elemre).
+ Description for option in Setting Screen
+
+
+
+ Ha engedélyezve van, a csak egy évadot tartalmazó tévésorozat kiválasztása közvetlenül az epizódlistába kerül, nem pedig a műsor részleteinek és évadlistájának.
+ Settings Menu - Description for option
+
+
+
+ Használja a Splashscreent képernyővédő háttereként
+ Option Title in user setting screen
+
+
+
+ Használja a generált splashscreen képet Jellyfin képernyővédő háttereként. A Jellyfint újra meg kell nyitni, hogy a változás életbe lépjen.
+
+
+
+ Elrejti az összes órát a Jellyfinben. A Jellyfint újra kell nyitni, hogy a változás életbe lépjen.
+ Settings Menu - Description for option
+
+
+
+ Az alkalmazás megjelenésével kapcsolatos beállítások.
+
+
+
+ Óra elrejtése
+ Option Title in user setting screen
+
+
+
+ Íme a Gyorscsatlakozási kódod:
+
+
+
+ Elrejti a címszó szövegét a részletező oldalakon.
+
+
+
+ A kezdőlap beállításai.
+ Description for Home Page user settings.
+
+
+
+ Maximális napok száma a Következőhöz
+ Option Title in user setting screen
+
+
+
+ Stúdiók
+
+
+
+ Előzetes lejátszása
+
+
+
+ Próbálja meg a nem támogatott profilszintű H.264-es adathordozók közvetlen lejátszását, mielőtt visszaállna az átkódolásra, ha az sikertelen.
+ Settings Menu - Description for option
+
+
+
+ Használja a távirányító hangbevitelét a kereséshez
+ Help text in search voice text box
+
+
+
+ (A párbeszédablak automatikusan bezárul)
+
+
+
+ Ugrás az epizódra
+ Continue Watching Popup Menu - Navigate to the Episode Detail Page
+
+
+
+ Kereshet Címekre, Személyekre, Élő TV-csatornákra és egyebekre
+ Help text in search results
+
+
+
+ %1 a %2 -ból
+ Item position and count. %1 = current item. %2 = total number of items
+
+
+
+ Műsorok
+
+
+
+ Használja a Splashscreent a kezdőképernyő háttereként
+ Option Title in user setting screen
+
+
+
+ A Mozi Mód a moziélményt egyenesen a nappaliba viszi azzal a lehetőséggel, hogy egyéni bevezetőket játszhat le a fő funkció előtt.
+ Settings Menu - Description for option
+
+
+
+ A lejátszással, valamint a támogatott kodekekkel és médiatípusokkal kapcsolatos beállítások.
+
+
+
+ Címsorok elrejtése
+ Option Title in user setting screen
+
+
+
+ Jellyfin képernyőkímélőjének beállításai.
+ Description for Screensaver user settings.
+
+
+
+ Dizájn elemek
+
+
+
+ Következő rész
+
+
+
+ Próbálja meg a közvetlen lejátszást nem támogatott profilszintű HEVC-média esetén, mielőtt visszaállna az átkódolásra, ha az sikertelen.
+ Settings Menu - Description for option
+
+
+
+ Részletező oldal
+
+
+
+ A megtekintetlen epizódok elhomályosítása
+ Option Title in user setting screen
+
+
+
+ Ha engedélyezve van, a megtekintetlen epizódok képei elmosódnak.
+
+
+
+ Ugrás az évadra
+ Continue Watching Popup Menu - Navigate to the Season Page
+
+
+
+ Keresés most
+ Help text in search Box
+
+
+
+ Gyorscsatlakozás
+
+
+
+ Hiba történt a Gyorscsatlakozás segítségével történő hitelesítés során.
+
+
+
+ Hálózatok
+
+
+
+ Vissza a tetejére
+ UI -> Media Grid -> Item Title in user setting screen.
+
+
+
+ Mozi Mód
+ Settings Menu - Title for option
+
+
+
+ Részletek oldal beállításai.
+ Description for Details page user settings.
+
+
+
+ TV-műsorok beállításai.
+ Description for TV Shows user settings.
+
+
+
+ Részletek kihagyása a külön évadokhoz
+ Settings Menu - Title for option
+
+
+
+ Képernyőkímélő
+
+
+
+ Opciók, amelyek megváltoztatják a Jellyfin dizájnját.
+ Description for Design Elements user settings.
+
+
+
+ Használja a generált indítóképernyős képet Jellyfin otthoni háttereként. A Jellyfint újra kell nyitni, hogy a változás életbe lépjen.
+ Description for option in Setting Screen
+
+
+
+ H.264
+ Name of codec used in settings menu
+
+
+
+ HEVC
+ Name of codec used in settings menu
+
+
+
+ Kezdőlap
+
+
+
+ Állítsa be, hogy egy műsor mennyi ideig maradjon a „Következő” listában anélkül, hogy megnézné.
+ Settings Menu - Description for option
+
+
+
+ Lejátszási információk
+
+
+
+ Csak a szöveges feliratokat jelenítse meg az átkódolás minimalizálása érdekében.
+ Description of a setting - should we hide subtitles that might transcode
+
+
+
+ Pixel formátum
+ Video pixel format
+
+
+
+ Bitráta
+ Video streaming bit rate
+
+
+
+ Kodek jelölés
+
+
+
+ Csak szöveges feliratok
+ Name of a setting - should we hide subtitles that might transcode
+
+
+
+ Videókodek
+
+
+
+ Kodek
+
+
+
+ Konténer
+ Video streaming container
+
+
+
+ Transzkódolási információk
+
+
+
+ Oka
+
+
+
+ Audiókodek
+
+
+
+ direkt
+
+
+
+ Teljes Bitráta
+
+
+
+ Audiocsatornák
+
+
+
+ Adatfolyam információ
+
+
+
+ Szint
+ Video profile level
+
+
+
+ Méret
+ Video size
+
+
+
+ Videó tartomány típusa
+
+
+
+ Szélesség x Magasság
+ Video width x height
+
+
+
+ Nem találhatók ehhez az előadóhoz tartozó albumok vagy dalok
+ Popup message when we find no audio data for an artist
+
+
+
+ Diavetítés szüneteltetve
+
+
+
+ Az újdonságok előugró ablaka
+ Settings Menu - Title for option
+
+
+
+ összes
+ all will reset the searchTerm so all data will be availible
+
+
+
+ Diavetítés bekapcsolva
+
+
+
+ Diavetítés folytatódik
+
+
+
+ Véletlenszerű kikapcsolva
+
+
+
+ Sugározva
+ Aired date label
+
+
+
+ Diavetítés kikapcsolva
+
+
+
+ Véletlenszerű bekapcsolva
+
+
+
+ MPEG-4 Támogatás
+ Settings Menu - Title for option
+
+
+
+ Album
+
+
+
+ Mutassa Mind
+
+
+
+ Alapértelmezett nézet Filmkönyvtáraknak.
+ Settings Menu - Description for option
+
+
+
+ Filmkönyvtár Rácscímek
+ Settings Menu - Title for option
+
+
+
+ Mutassa Rámutatáskor
+
+
+
+ Mindig Mutassa
+
+
+
+ Sose Mutassa
+
+
+
+ Albumok
+
+
+
+ Újdonságok felugró ablak mutatása miután a Jellyfin a legújabb verzióra frissült.
+ Settings Menu - Description for option
+
+
+
+ Filmkönyvtár Alapértelmezett Nézet
+ Settings Menu - Title for option
+
+
+
+ Válaszd ki mikor mutassa a címeket.
+ Settings Menu - Description for option
+
+
+
+ Ha bekapcsolja, akkor a csillagok és a közösség általi értékelések el lesznek rejtve a sorozatok epizódjainál, hogy elkerülhetőek legyenek a spoilerek a közelgő jó/rossz epizódoknál.
+
+
+
+ Zene
+
+
+
+ Zenék
+
+
+
+ Közösségi Minősítés Kikapcsolása az Epizódoknál
+
+
+
+ Lejátszott
+
+
+
+ Folytatható
+
+
+
+ Nem játszott
+
diff --git a/locale/it_IT/translations.ts b/locale/it_IT/translations.ts
index e9ba4bfc..f8405190 100644
--- a/locale/it_IT/translations.ts
+++ b/locale/it_IT/translations.ts
@@ -1921,5 +1921,36 @@
Errore durante la riproduzioneDialog title when error occurs during playback
+
+
+ Errore durante la riproduzione
+ Dialog title when error occurs during playback
+
+
+
+ Esci
+
+
+
+ C'è stato un errore nel recupero dei dati per questo elemento dal server.
+ Dialog detail when unable to load Content from Server
+
+
+
+ È stato riscontrato un errore durante la riproduzione di questo oggetto.
+ Dialog detail when error occurs during playback
+
+
+
+ Caricamento dati del canale
+
+
+
+ Salvare le credenziali?
+
+
+
+ Cambia server
+
diff --git a/locale/pt_BR/translations.ts b/locale/pt_BR/translations.ts
index ad52f7d2..301100fb 100644
--- a/locale/pt_BR/translations.ts
+++ b/locale/pt_BR/translations.ts
@@ -2643,5 +2643,53 @@ não contém itens
Classificação Etária
+
+
+ Sair
+
+
+
+ Salvar Credenciais?
+
+
+
+ Deletar Salvos
+
+
+
+ Erro Durante a Reprodução
+ Dialog title when error occurs during playback
+
+
+
+ Mudar Servidor
+
+
+
+ Erro ao Carregar Conteúdo
+ Dialog title when unable to load Content from Server
+
+
+
+ Carregando Dados do Canal
+
+
+
+ Foi encontrado um erro na reprodução deste item.
+ Dialog detail when error occurs during playback
+
+
+
+ Em Exibição
+
+
+
+ Houve um erro ao recuperar os dados deste item do servidor.
+ Dialog detail when unable to load Content from Server
+
+
+
+ Erro ao carregar os Dados do Canal
+
diff --git a/locale/sk/translations.ts b/locale/sk/translations.ts
index 8e2024a2..4e72b54c 100644
--- a/locale/sk/translations.ts
+++ b/locale/sk/translations.ts
@@ -958,5 +958,169 @@
PrehrávanieTitle for Playback section in user setting screen.
+
+ Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)
+
+ Tento %1 neobsahuje žiadne položky
+
+
+
+ utorok
+ Day of Week
+
+
+
+ piatok
+ Day of Week
+
+
+
+ Hodnotenie IMDb
+
+
+
+ Dátum vydania
+
+
+ Title of Tab for switching "views" when looking at a library
+
+ Zobrazenie
+
+
+
+ Uložiť prihlasovacie údaje?
+
+
+
+ Dátum prehrania
+
+
+
+ Obsadenie a štáb
+
+
+
+ Filmy
+
+
+ Name or Title field of media item
+
+ Meno
+
+
+
+ Odstrániť uložené
+
+
+
+ Dátum pridania
+
+
+
+ Rodičovské hodnotenie
+
+
+
+ Počet prehraní
+
+
+
+ Dĺžka
+
+
+ Title of Tab for options to sort library content
+
+ Zoradenie
+
+
+ Title of Tab for options to filter library content
+
+ Filter
+
+
+
+ Dátum narodenia
+
+
+
+ Dátum úmrtia
+
+
+
+ Vek
+
+
+
+ Viac podobných
+
+
+
+ Hodnotenie kritikov
+
+
+
+ Zatvorte stlačením tlačidla 'OK'
+
+
+
+ Špeciálne Funkcie
+
+
+
+ Dodatočné Časti
+ Additional parts of a video
+
+
+
+ včera
+ Previous day
+
+
+
+ nedeľa
+ Day of Week
+
+
+
+ pondelok
+ Day of Week
+
+
+
+ streda
+ Day of Week
+
+
+
+ štvrtok
+ Day of Week
+
+
+
+ sobota
+ Day of Week
+
+
+
+ Filmy (prezentácia)
+
+
+
+ Filmy (mriežka)
+
+
+
+ TV Seriály
+
+
+
+ dnes
+ Current day
+
+
+
+ zajtra
+ Next day
+
diff --git a/package-lock.json b/package-lock.json
index 81dc9295..0b7b2e69 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,9 +17,9 @@
"sob": "npm:slide-out-button@^1.0.1"
},
"devDependencies": {
- "@rokucommunity/bslint": "0.8.0",
- "brighterscript": "0.61.2",
- "ropm": "0.10.10"
+ "@rokucommunity/bslint": "0.8.1",
+ "brighterscript": "0.61.3",
+ "ropm": "0.10.11"
}
},
"node_modules/@nodelib/fs.scandir": {
@@ -60,9 +60,9 @@
"integrity": "sha512-2ox6EUL+UTtccTbD4dbVjZK3QHa0PHCqpoKMF8lZz9ayzzEP3iVPF8KZR6hOi6bxsIcbGXVjqmtCVkpC4P9SrA=="
},
"node_modules/@rokucommunity/bslint": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@rokucommunity/bslint/-/bslint-0.8.0.tgz",
- "integrity": "sha512-fqTiBMczZa6YmJix0b81cDm2n9c7GlumFirwLGJSHpCEvnxwNTf0tIo3efnd4N5aJq7kpg8Y3GEbWnKs58BhFg==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@rokucommunity/bslint/-/bslint-0.8.1.tgz",
+ "integrity": "sha512-G4XhWHMZzq6HJiNazd3Vpg8mstYkbOk6dQC4JD7vmBlSVqm0KkITmZRNlumn/x1v60E9dGONP89MkoBz3/DHaA==",
"dev": true,
"dependencies": {
"fs-extra": "^10.0.0",
@@ -371,9 +371,9 @@
}
},
"node_modules/brighterscript": {
- "version": "0.61.2",
- "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.61.2.tgz",
- "integrity": "sha512-QNawTRD9DHlyVc/lwD0pSJQIzFf1JsjL9CHu4jmv+41/o+/DzSAHAjQhgIa9dQWroIAwHPUVKMya+0jXlIrIvw==",
+ "version": "0.61.3",
+ "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.61.3.tgz",
+ "integrity": "sha512-8BDpOSCdmkS/QcTdPTUW/99nCBypuoa/Zz6PZHI6OiVylqTBidtrGI7lBZotqY6yvQ3KJl24thhLHK5XuIT/6w==",
"dev": true,
"dependencies": {
"@rokucommunity/bslib": "^0.1.1",
@@ -391,15 +391,15 @@
"fs-extra": "^8.0.0",
"jsonc-parser": "^2.3.0",
"long": "^3.2.0",
- "luxon": "^1.8.3",
+ "luxon": "^2.5.2",
"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.9.2",
+ "roku-deploy": "^3.9.3",
"serialize-error": "^7.0.1",
- "source-map": "^0.7.3",
+ "source-map": "^0.7.4",
"vscode-languageserver": "7.0.0",
"vscode-languageserver-protocol": "3.16.0",
"vscode-languageserver-textdocument": "^1.0.1",
@@ -520,6 +520,15 @@
"node": ">=6 <7 || >=8"
}
},
+ "node_modules/brighterscript/node_modules/luxon": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.5.2.tgz",
+ "integrity": "sha512-Yg7/RDp4nedqmLgyH0LwgGRvMEKVzKbUdkBYyCosbHgJ+kaOUx0qzSiSatVc3DFygnirTPYnMM2P5dg2uH1WvA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/brighterscript/node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
@@ -1398,9 +1407,9 @@
}
},
"node_modules/luxon": {
- "version": "1.17.2",
- "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.17.2.tgz",
- "integrity": "sha512-qELKtIj3HD41N+MvgoxArk8DZGUb4Gpiijs91oi+ZmKJzRlxY6CoyTwNoUwnogCVs4p8HuxVJDik9JbnYgrCng==",
+ "version": "1.28.1",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.1.tgz",
+ "integrity": "sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw==",
"engines": {
"node": "*"
}
@@ -1794,9 +1803,9 @@
}
},
"node_modules/roku-deploy": {
- "version": "3.9.2",
- "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.9.2.tgz",
- "integrity": "sha512-2LZyR4EhaFrka1gVmcuJO/f42tqz4clGImboVLCNem1q/PcFV5cnXNZRfqDI+MZ/n8eJto71JlZkcc7TDLt/EQ==",
+ "version": "3.9.3",
+ "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.9.3.tgz",
+ "integrity": "sha512-cjTx5ffZNt07rQS+0s2sTBHkZKUk283y9f6UnbI77X03lQ60vYlCnqsKswWisFYMHPIdvsTLLSfKsshAPwKHEQ==",
"dependencies": {
"chalk": "^2.4.2",
"dateformat": "^3.0.3",
@@ -1831,20 +1840,20 @@
}
},
"node_modules/ropm": {
- "version": "0.10.10",
- "resolved": "https://registry.npmjs.org/ropm/-/ropm-0.10.10.tgz",
- "integrity": "sha512-tkPuDwP/Mva9IXIuTf4pnH1DC27WLeLfu8QJ70WwaX9tepNMZeDi4eEQdWQ7kalXxxlwXGnG4jUaaA1B4v8zWw==",
+ "version": "0.10.11",
+ "resolved": "https://registry.npmjs.org/ropm/-/ropm-0.10.11.tgz",
+ "integrity": "sha512-D9Nfi2tuB32d9gJFdyBdUw6+sBo4lwG2trkL9S0jHJCKqAQWs6tgkmDRd+pp6ZrKEKSK1V2y0bi8xFOi2Rjr+Q==",
"dev": true,
"dependencies": {
"@xml-tools/ast": "^5.0.5",
"@xml-tools/parser": "1.0.10",
- "brighterscript": "^0.57.2",
+ "brighterscript": "^0.61.3",
"del": "6.0.0",
"fs-extra": "9.1.0",
"glob-all": "3.2.1",
"latinize": "0.5.0",
"npm-packlist": "2.1.4",
- "roku-deploy": "^3.8.1",
+ "roku-deploy": "^3.9.3",
"semver": "7.3.4",
"yargs": "16.2.0"
},
@@ -1864,79 +1873,6 @@
"chevrotain": "7.1.1"
}
},
- "node_modules/ropm/node_modules/brighterscript": {
- "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",
- "@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/brighterscript/node_modules/jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
- "dev": true,
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/ropm/node_modules/brighterscript/node_modules/universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
- "dev": true,
- "engines": {
- "node": ">= 4.0.0"
- }
- },
"node_modules/ropm/node_modules/chevrotain": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.1.tgz",
@@ -2438,9 +2374,9 @@
"integrity": "sha512-2ox6EUL+UTtccTbD4dbVjZK3QHa0PHCqpoKMF8lZz9ayzzEP3iVPF8KZR6hOi6bxsIcbGXVjqmtCVkpC4P9SrA=="
},
"@rokucommunity/bslint": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@rokucommunity/bslint/-/bslint-0.8.0.tgz",
- "integrity": "sha512-fqTiBMczZa6YmJix0b81cDm2n9c7GlumFirwLGJSHpCEvnxwNTf0tIo3efnd4N5aJq7kpg8Y3GEbWnKs58BhFg==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@rokucommunity/bslint/-/bslint-0.8.1.tgz",
+ "integrity": "sha512-G4XhWHMZzq6HJiNazd3Vpg8mstYkbOk6dQC4JD7vmBlSVqm0KkITmZRNlumn/x1v60E9dGONP89MkoBz3/DHaA==",
"dev": true,
"requires": {
"fs-extra": "^10.0.0",
@@ -2695,9 +2631,9 @@
}
},
"brighterscript": {
- "version": "0.61.2",
- "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.61.2.tgz",
- "integrity": "sha512-QNawTRD9DHlyVc/lwD0pSJQIzFf1JsjL9CHu4jmv+41/o+/DzSAHAjQhgIa9dQWroIAwHPUVKMya+0jXlIrIvw==",
+ "version": "0.61.3",
+ "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.61.3.tgz",
+ "integrity": "sha512-8BDpOSCdmkS/QcTdPTUW/99nCBypuoa/Zz6PZHI6OiVylqTBidtrGI7lBZotqY6yvQ3KJl24thhLHK5XuIT/6w==",
"dev": true,
"requires": {
"@rokucommunity/bslib": "^0.1.1",
@@ -2715,15 +2651,15 @@
"fs-extra": "^8.0.0",
"jsonc-parser": "^2.3.0",
"long": "^3.2.0",
- "luxon": "^1.8.3",
+ "luxon": "^2.5.2",
"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.9.2",
+ "roku-deploy": "^3.9.3",
"serialize-error": "^7.0.1",
- "source-map": "^0.7.3",
+ "source-map": "^0.7.4",
"vscode-languageserver": "7.0.0",
"vscode-languageserver-protocol": "3.16.0",
"vscode-languageserver-textdocument": "^1.0.1",
@@ -2743,6 +2679,12 @@
"universalify": "^0.1.0"
}
},
+ "luxon": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.5.2.tgz",
+ "integrity": "sha512-Yg7/RDp4nedqmLgyH0LwgGRvMEKVzKbUdkBYyCosbHgJ+kaOUx0qzSiSatVc3DFygnirTPYnMM2P5dg2uH1WvA==",
+ "dev": true
+ },
"yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
@@ -3533,9 +3475,9 @@
}
},
"luxon": {
- "version": "1.17.2",
- "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.17.2.tgz",
- "integrity": "sha512-qELKtIj3HD41N+MvgoxArk8DZGUb4Gpiijs91oi+ZmKJzRlxY6CoyTwNoUwnogCVs4p8HuxVJDik9JbnYgrCng=="
+ "version": "1.28.1",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.1.tgz",
+ "integrity": "sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw=="
},
"merge2": {
"version": "1.4.1",
@@ -3813,9 +3755,9 @@
}
},
"roku-deploy": {
- "version": "3.9.2",
- "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.9.2.tgz",
- "integrity": "sha512-2LZyR4EhaFrka1gVmcuJO/f42tqz4clGImboVLCNem1q/PcFV5cnXNZRfqDI+MZ/n8eJto71JlZkcc7TDLt/EQ==",
+ "version": "3.9.3",
+ "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.9.3.tgz",
+ "integrity": "sha512-cjTx5ffZNt07rQS+0s2sTBHkZKUk283y9f6UnbI77X03lQ60vYlCnqsKswWisFYMHPIdvsTLLSfKsshAPwKHEQ==",
"requires": {
"chalk": "^2.4.2",
"dateformat": "^3.0.3",
@@ -3846,20 +3788,20 @@
}
},
"ropm": {
- "version": "0.10.10",
- "resolved": "https://registry.npmjs.org/ropm/-/ropm-0.10.10.tgz",
- "integrity": "sha512-tkPuDwP/Mva9IXIuTf4pnH1DC27WLeLfu8QJ70WwaX9tepNMZeDi4eEQdWQ7kalXxxlwXGnG4jUaaA1B4v8zWw==",
+ "version": "0.10.11",
+ "resolved": "https://registry.npmjs.org/ropm/-/ropm-0.10.11.tgz",
+ "integrity": "sha512-D9Nfi2tuB32d9gJFdyBdUw6+sBo4lwG2trkL9S0jHJCKqAQWs6tgkmDRd+pp6ZrKEKSK1V2y0bi8xFOi2Rjr+Q==",
"dev": true,
"requires": {
"@xml-tools/ast": "^5.0.5",
"@xml-tools/parser": "1.0.10",
- "brighterscript": "^0.57.2",
+ "brighterscript": "^0.61.3",
"del": "6.0.0",
"fs-extra": "9.1.0",
"glob-all": "3.2.1",
"latinize": "0.5.0",
"npm-packlist": "2.1.4",
- "roku-deploy": "^3.8.1",
+ "roku-deploy": "^3.9.3",
"semver": "7.3.4",
"yargs": "16.2.0"
},
@@ -3873,72 +3815,6 @@
"chevrotain": "7.1.1"
}
},
- "brighterscript": {
- "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",
- "@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"
- }
- },
- "jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.6"
- }
- },
- "universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
- "dev": true
- }
- }
- },
"chevrotain": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.1.tgz",
diff --git a/package.json b/package.json
index f5b4687e..24588000 100644
--- a/package.json
+++ b/package.json
@@ -4,9 +4,9 @@
"description": "Roku app for Jellyfin media server",
"main": "index.js",
"devDependencies": {
- "@rokucommunity/bslint": "0.8.0",
- "brighterscript": "0.61.2",
- "ropm": "0.10.10"
+ "@rokucommunity/bslint": "0.8.1",
+ "brighterscript": "0.61.3",
+ "ropm": "0.10.11"
},
"scripts": {
"postinstall": "npx ropm copy",
diff --git a/settings/settings.json b/settings/settings.json
index 9e5878e1..8dabaf52 100644
--- a/settings/settings.json
+++ b/settings/settings.json
@@ -4,39 +4,51 @@
"description": "Settings relating to playback and supported codec and media types.",
"children": [
{
- "title": "AV1 Support",
- "description": "** EXPERIMENTAL** Support Direct Play of AV1 content if this Roku device supports it.",
- "settingName": "playback.av1",
- "type": "bool",
- "default": "false"
+ "title": "Codec Support",
+ "description": "Enable or disable Direct Play support for certain codecs",
+ "children": [
+ {
+ "title": "AV1",
+ "description": "** EXPERIMENTAL** Support Direct Play of AV1 content if this Roku device supports it.",
+ "settingName": "playback.av1",
+ "type": "bool",
+ "default": "false"
+ },
+ {
+ "title": "MPEG-2",
+ "description": "Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.",
+ "settingName": "playback.mpeg2",
+ "type": "bool",
+ "default": "false"
+ },
+ {
+ "title": "MPEG-4",
+ "description": "Support Direct Play of MPEG-4 content. This may need to be disabled for playback of DIVX encoded video files.",
+ "settingName": "playback.mpeg4",
+ "type": "bool",
+ "default": "true"
+ }
+ ]
},
{
- "title": "MPEG-2 Support",
- "description": "Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.",
- "settingName": "playback.mpeg2",
- "type": "bool",
- "default": "false"
- },
- {
- "title": "MPEG-4 Support",
- "description": "Support Direct Play of MPEG-4 content. This may need to be disabled for playback of DIVX encoded video files.",
- "settingName": "playback.mpeg4",
- "type": "bool",
- "default": "true"
- },
- {
- "title": "Direct Play H.264 Unsupported Profile Levels",
- "description": "Attempt Direct Play for H.264 media with unsupported profile levels before falling back to transcoding if it fails.",
- "settingName": "playback.tryDirect.h264ProfileLevel",
- "type": "bool",
- "default": "true"
- },
- {
- "title": "Direct Play HEVC Unsupported Profile Levels",
- "description": "Attempt Direct Play for HEVC media with unsupported profile levels before falling back to trancoding if it fails.",
- "settingName": "playback.tryDirect.hevcProfileLevel",
- "type": "bool",
- "default": "true"
+ "title": "Profile Level Support",
+ "description": "Attempt Direct Play of potentially unsupported profile levels",
+ "children": [
+ {
+ "title": "H.264",
+ "description": "Attempt Direct Play for H.264 media with unsupported profile levels before falling back to transcoding if it fails.",
+ "settingName": "playback.tryDirect.h264ProfileLevel",
+ "type": "bool",
+ "default": "true"
+ },
+ {
+ "title": "HEVC",
+ "description": "Attempt Direct Play for HEVC media with unsupported profile levels before falling back to trancoding if it fails.",
+ "settingName": "playback.tryDirect.hevcProfileLevel",
+ "type": "bool",
+ "default": "true"
+ }
+ ]
},
{
"title": "Cinema Mode",
@@ -54,6 +66,13 @@
}
]
},
+ {
+ "title": "Show What's New Popup",
+ "description": "Show What's New popup when Jellyfin is updated to a new version.",
+ "settingName": "load.allowwhatsnew",
+ "type": "bool",
+ "default": "true"
+ },
{
"title": "User Interface",
"description": "Settings relating to how the application looks.",
@@ -68,6 +87,13 @@
"settingName": "ui.details.maxdaysnextup",
"type": "integer",
"default": "365"
+ },
+ {
+ "title": "Use Splashscreen as Home Background",
+ "description": "Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.",
+ "settingName": "ui.home.splashBackground",
+ "type": "bool",
+ "default": "false"
}
]
},
@@ -94,6 +120,20 @@
"settingName": "ui.tvshows.blurunwatched",
"type": "bool",
"default": "false"
+ },
+ {
+ "title": "Skip Details for Single Seasons",
+ "description": "If enabled, selecting a TV series with only one season will go straight to the episode list rather than the show details and season list.",
+ "settingName": "ui.tvshows.goStraightToEpisodeListing",
+ "type": "bool",
+ "default": "false"
+ },
+ {
+ "title":"Disable Community Rating for Episodes",
+ "description": "If enabled, the star and community rating for episodes of a TV show will be removed. This is to prevent spoilers of an upcoming good/bad episode.",
+ "settingName": "ui.tvshows.disableCommunityRating",
+ "type":"bool",
+ "default":"false"
}
]
},
@@ -120,13 +160,6 @@
"settingName": "ui.design.hideclock",
"type": "bool",
"default": "false"
- },
- {
- "title": "Use Splashscreen as Home Background",
- "description": "Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.",
- "settingName": "ui.home.splashBackground",
- "type": "bool",
- "default": "false"
}
]
},
@@ -134,6 +167,44 @@
"title": "Media Grid",
"description": "Media Grid options.",
"children": [
+ {
+ "title": "Movie Library Default View",
+ "description": "Default view for Movie Libraries.",
+ "settingName": "itemgrid.movieDefaultView",
+ "type": "radio",
+ "default": "movies",
+ "options": [
+ {
+ "title": "Movies (Presentation)",
+ "id": "Movies"
+ },
+ {
+ "title": "Movies (Grid)",
+ "id": "MoviesGrid"
+ }
+ ]
+ },
+ {
+ "title": "Movie Library Grid Titles",
+ "description": "Select when to show titles.",
+ "settingName": "itemgrid.movieGridTitles",
+ "type": "radio",
+ "default": "showonhover",
+ "options": [
+ {
+ "title": "Show On Hover",
+ "id": "showonhover"
+ },
+ {
+ "title": "Always Show",
+ "id": "showalways"
+ },
+ {
+ "title": "Always Hide",
+ "id": "hidealways"
+ }
+ ]
+ },
{
"title": "Item Count",
"description": "Show item count in the library and index of selected item.",
diff --git a/source/Main.brs b/source/Main.brs
index 33ba5e35..d006d12b 100644
--- a/source/Main.brs
+++ b/source/Main.brs
@@ -41,6 +41,7 @@ sub Main (args as dynamic) as void
sceneManager = CreateObject("roSGNode", "SceneManager")
m.global.addFields({ app_loaded: false, playstateTask: playstateTask, sceneManager: sceneManager })
+ m.global.addFields({ queueManager: CreateObject("roSGNode", "QueueManager") })
app_start:
' First thing to do is validate the ability to use the API
@@ -56,6 +57,17 @@ sub Main (args as dynamic) as void
m.scene.observeField("exit", m.port)
+ ' Only show the Whats New popup the first time a user runs a new client version.
+ if appInfo.GetVersion() <> get_setting("LastRunVersion")
+ ' Ensure the user hasn't disabled Whats New popups
+ if get_user_setting("load.allowwhatsnew") = "true"
+ set_setting("LastRunVersion", appInfo.GetVersion())
+ dialog = createObject("roSGNode", "WhatsNewDialog")
+ m.scene.dialog = dialog
+ m.scene.dialog.observeField("buttonSelected", m.port)
+ end if
+ end if
+
' Handle input messages
input = CreateObject("roInput")
input.SetMessagePort(m.port)
@@ -66,10 +78,10 @@ sub Main (args as dynamic) as void
m.device.EnableAppFocusEvent(false)
' Check if we were sent content to play with the startup command (Deep Link)
- if (args.mediaType <> invalid) and (args.contentId <> invalid)
+ if isValidAndNotEmpty(args.mediaType) and isValidAndNotEmpty(args.contentId)
video = CreateVideoPlayerGroup(args.contentId)
- if video <> invalid and video.errorMsg <> "introaborted"
+ if isValid(video) and video.errorMsg <> "introaborted"
sceneManager.callFunc("pushScene", video)
else
dialog = createObject("roSGNode", "Dialog")
@@ -101,6 +113,7 @@ sub Main (args as dynamic) as void
group.setFocus(true)
end if
else if isNodeEvent(msg, "quickPlayNode")
+ group = sceneManager.callFunc("getActiveScene")
reportingNode = msg.getRoSGNode()
itemNode = reportingNode.quickPlayNode
if itemNode = invalid or itemNode.id = "" then return
@@ -113,22 +126,40 @@ sub Main (args as dynamic) as void
if video <> invalid and video.errorMsg <> "introaborted"
sceneManager.callFunc("pushScene", video)
end if
+
+ if LCase(group.subtype()) = "tvepisodes"
+ if isValid(group.lastFocus)
+ group.lastFocus.setFocus(true)
+ end if
+ end if
+
+ reportingNode.quickPlayNode.type = ""
end if
else if isNodeEvent(msg, "selectedItem")
' If you select a library from ANYWHERE, follow this flow
selectedItem = msg.getData()
m.selectedItemType = selectedItem.type
- '
+
if selectedItem.type = "CollectionFolder"
if selectedItem.collectionType = "movies"
group = CreateMovieLibraryView(selectedItem)
+ else if selectedItem.collectionType = "music"
+ group = CreateMusicLibraryView(selectedItem)
else
group = CreateItemGrid(selectedItem)
end if
sceneManager.callFunc("pushScene", group)
else if selectedItem.type = "Folder" and selectedItem.json.type = "Genre"
- group = CreateMovieLibraryView(selectedItem)
+ ' User clicked on a genre folder
+ if selectedItem.json.MovieCount > 0
+ group = CreateMovieLibraryView(selectedItem)
+ else
+ group = CreateItemGrid(selectedItem)
+ end if
+ sceneManager.callFunc("pushScene", group)
+ else if selectedItem.type = "Folder" and selectedItem.json.type = "MusicGenre"
+ group = CreateMusicLibraryView(selectedItem)
sceneManager.callFunc("pushScene", group)
else if selectedItem.type = "UserView" or selectedItem.type = "Folder" or selectedItem.type = "Channel" or selectedItem.type = "Boxset"
group = CreateItemGrid(selectedItem)
@@ -192,7 +223,9 @@ sub Main (args as dynamic) as void
else if selectedItem.type = "MusicAlbum"
group = CreateAlbumView(selectedItem.json)
else if selectedItem.type = "Audio"
- group = CreateAudioPlayerGroup([selectedItem.json])
+ m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("push", selectedItem.json)
+ m.global.queueManager.callFunc("playQueue")
else
' TODO - switch on more node types
message_dialog("This type is not yet supported: " + selectedItem.type + ".")
@@ -228,17 +261,27 @@ sub Main (args as dynamic) as void
' User has selected audio they want us to play
selectedIndex = msg.getData()
screenContent = msg.getRoSGNode()
- group = CreateAudioPlayerGroup([screenContent.albumData.items[selectedIndex]])
+
+ m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("push", screenContent.albumData.items[selectedIndex])
+ m.global.queueManager.callFunc("playQueue")
else if isNodeEvent(msg, "playAllSelected")
' User has selected playlist of of audio they want us to play
screenContent = msg.getRoSGNode()
m.spinner = screenContent.findNode("spinner")
m.spinner.visible = true
- group = CreateAudioPlayerGroup(screenContent.albumData.items)
+
+ m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("set", screenContent.albumData.items)
+ m.global.queueManager.callFunc("playQueue")
else if isNodeEvent(msg, "playArtistSelected")
' User has selected playlist of of audio they want us to play
screenContent = msg.getRoSGNode()
- group = CreateArtistMixGroup(screenContent.pageContent.id)
+
+ m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("set", CreateArtistMix(screenContent.pageContent.id).Items)
+ m.global.queueManager.callFunc("playQueue")
+
else if isNodeEvent(msg, "instantMixSelected")
' User has selected instant mix
' User has selected playlist of of audio they want us to play
@@ -248,20 +291,26 @@ sub Main (args as dynamic) as void
m.spinner.visible = true
end if
- group = invalid
+ viewHandled = false
' Create instant mix based on selected album
if isValid(screenContent.albumData)
if isValid(screenContent.albumData.items)
if screenContent.albumData.items.count() > 0
- group = CreateInstantMixGroup(screenContent.albumData.items)
+ m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("set", CreateInstantMix(screenContent.albumData.items[0].id).Items)
+ m.global.queueManager.callFunc("playQueue")
+
+ viewHandled = true
end if
end if
end if
- ' Create instant mix based on selected artist
- if not isValid(group)
- group = CreateInstantMixGroup([{ id: screenContent.pageContent.id }])
+ if not viewHandled
+ ' Create instant mix based on selected artist
+ m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("set", CreateInstantMix(screenContent.pageContent.id).Items)
+ m.global.queueManager.callFunc("playQueue")
end if
else if isNodeEvent(msg, "episodeSelected")
@@ -306,7 +355,9 @@ sub Main (args as dynamic) as void
else if node.type = "MusicAlbum"
group = CreateAlbumView(node.json)
else if node.type = "Audio"
- group = CreateAudioPlayerGroup([node.json])
+ m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("push", node.json)
+ m.global.queueManager.callFunc("playQueue")
else if node.type = "Person"
group = CreatePersonView(node)
else if node.type = "TvChannel"
@@ -318,7 +369,9 @@ sub Main (args as dynamic) as void
else if node.type = "Audio"
selectedIndex = msg.getData()
screenContent = msg.getRoSGNode()
- group = CreateAudioPlayerGroup([screenContent.albumData.items[node.id]])
+ m.global.queueManager.callFunc("clear")
+ m.global.queueManager.callFunc("push", screenContent.albumData.items[node.id])
+ m.global.queueManager.callFunc("playQueue")
else
' TODO - switch on more node types
message_dialog("This type is not yet supported: " + node.type + ".")
diff --git a/source/ShowScenes.brs b/source/ShowScenes.brs
index 90042322..a0da9296 100644
--- a/source/ShowScenes.brs
+++ b/source/ShowScenes.brs
@@ -358,12 +358,18 @@ function CreateMovieDetailsGroup(movie)
end function
function CreateSeriesDetailsGroup(series)
+ ' Get season data early in the function so we can check number of seasons.
+ seasonData = TVSeasons(series.id)
+ ' Divert to season details if user setting goStraightToEpisodeListing is enabled and only one season exists.
+ if get_user_setting("ui.tvshows.goStraightToEpisodeListing") = "true" and seasonData.Items.Count() = 1
+ return CreateSeasonDetailsGroupByID(series.id, seasonData.Items[0].id)
+ end if
group = CreateObject("roSGNode", "TVShowDetails")
group.optionsAvailable = false
m.global.sceneManager.callFunc("pushScene", group)
group.itemContent = ItemMetaData(series.id)
- group.seasonData = TVSeasons(series.id)
+ group.seasonData = seasonData ' Re-use variable from beginning of function
group.observeField("seasonSelected", m.port)
@@ -483,6 +489,14 @@ function CreateMovieLibraryView(libraryItem)
return group
end function
+function CreateMusicLibraryView(libraryItem)
+ group = CreateObject("roSGNode", "MusicLibraryView")
+ group.parentItem = libraryItem
+ group.optionsAvailable = true
+ group.observeField("selectedItem", m.port)
+ return group
+end function
+
function CreateSearchPage()
' Search + Results Page
group = CreateObject("roSGNode", "searchResults")
@@ -512,72 +526,6 @@ function CreateVideoPlayerGroup(video_id, mediaSourceId = invalid, audio_stream_
return video
end function
-' Play Audio
-function CreateAudioPlayerGroup(audiodata)
-
- group = CreateObject("roSGNode", "NowPlaying")
- group.observeField("state", m.port)
- songIDArray = CreateObject("roArray", 0, true)
-
- ' All we need is an array of Song IDs the user selected to play.
- for each song in audiodata
- songIDArray.push(song.id)
- end for
-
- group.pageContent = songIDArray
- group.musicArtistAlbumData = audiodata
-
- m.global.sceneManager.callFunc("pushScene", group)
-
- return group
-end function
-
-' Play Instant Mix
-function CreateInstantMixGroup(audiodata)
-
- songList = CreateInstantMix(audiodata[0].id)
-
- group = CreateObject("roSGNode", "NowPlaying")
- group.observeField("state", m.port)
- songIDArray = CreateObject("roArray", 0, true)
-
- ' All we need is an array of Song IDs the user selected to play.
- for each song in songList.items
- songIDArray.push(song.id)
- end for
-
- songIDArray.shift()
-
- group.pageContent = songIDArray
- group.musicArtistAlbumData = songList.items
-
- m.global.sceneManager.callFunc("pushScene", group)
-
- return group
-end function
-
-' Play Artist
-function CreateArtistMixGroup(artistID)
-
- songList = CreateArtistMix(artistID)
-
- group = CreateObject("roSGNode", "NowPlaying")
- group.observeField("state", m.port)
- songIDArray = CreateObject("roArray", 0, true)
-
- ' All we need is an array of Song IDs the user selected to play.
- for each song in songList.items
- songIDArray.push(song.id)
- end for
-
- group.pageContent = songIDArray
- group.musicArtistAlbumData = songList.items
-
- m.global.sceneManager.callFunc("pushScene", group)
-
- return group
-end function
-
function CreatePersonView(personData as object) as object
person = CreateObject("roSGNode", "PersonDetails")
m.global.SceneManager.callFunc("pushScene", person)
diff --git a/source/VideoPlayer.brs b/source/VideoPlayer.brs
index ea72f39e..051fe47c 100644
--- a/source/VideoPlayer.brs
+++ b/source/VideoPlayer.brs
@@ -22,15 +22,15 @@ end function
sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -1, playbackPosition = -1, forceTranscoding = false, showIntro = true, allowResumeDialog = true)
video.content = createObject("RoSGNode", "ContentNode")
meta = ItemMetaData(video.id)
- m.videotype = meta.type
if meta = invalid
video.content = invalid
return
end if
+ m.videotype = meta.type
' Special handling for "Programs" or "Vidoes" launched from "On Now" or elsewhere on the home screen...
' basically anything that is a Live Channel.
- if meta.json.ChannelId <> invalid
+ if isValid(meta?.json?.ChannelId)
if meta.json.EpisodeTitle <> invalid
meta.title = meta.json.EpisodeTitle
else if meta.json.Name <> invalid
@@ -53,7 +53,7 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
video.content.title = meta.title
video.showID = meta.showID
- if playbackPosition = -1
+ if playbackPosition = -1 and isValid(meta.json)
playbackPosition = meta.json.UserData.PlaybackPositionTicks
if allowResumeDialog
if playbackPosition > 0
@@ -175,7 +175,17 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
if mediaSourceId = invalid
mediaSourceId = video.id
end if
- if meta.live then mediaSourceId = "" ' Don't send mediaSourceId for Live media
+
+ ' Don't send mediaSourceId for Live Media
+ ' Note: Recordings in progress will have meta.live = invalid, but we still don't want to send mediaSourceId
+ if not isValid(meta.live)
+ meta.live = false
+ mediaSourceId = ""
+ else
+ if meta.live
+ mediaSourceId = ""
+ end if
+ end if
m.playbackInfo = ItemPostPlaybackInfo(video.id, mediaSourceId, audio_stream_idx, subtitle_idx, playbackPosition)
video.videoId = video.id
@@ -197,7 +207,7 @@ sub AddVideoContent(video, mediaSourceId, audio_stream_idx = 1, subtitle_idx = -
video.container = getContainerType(meta)
- if m.playbackInfo.MediaSources[0] = invalid
+ if not isValid(m.playbackInfo.MediaSources[0]) and isValid(meta.json)
m.playbackInfo = meta.json
end if
@@ -395,7 +405,7 @@ end function
function getContainerType(meta as object) as string
' Determine the file type of the video file source
- if meta.json.mediaSources = invalid then return ""
+ if not IsValid(meta.json) or not isValid(meta.json.mediaSources) then return ""
container = meta.json.mediaSources[0].container
if container = invalid
diff --git a/source/api/Items.brs b/source/api/Items.brs
index 4cdf4b8e..5786425c 100644
--- a/source/api/Items.brs
+++ b/source/api/Items.brs
@@ -147,15 +147,19 @@ function ItemMetaData(id as string)
tmp = CreateObject("roSGNode", "MusicSongData")
' Try using song's parent for poster image
- tmp.image = PosterImage(data.ParentId)
+ tmp.image = PosterImage(data.ParentId, { "MaxWidth": 500, "MaxHeight": 500 })
' Song's parent poster image is no good, try using the song's poster image
if tmp.image = invalid
- tmp.image = PosterImage(data.id)
+ tmp.image = PosterImage(data.id, { "MaxWidth": 500, "MaxHeight": 500 })
end if
tmp.json = data
return tmp
+ else if data.type = "Recording"
+ ' We know it's "Recording", but we don't do any special preprocessing
+ ' for this data type at the moment, so just return the json.
+ return data
else
print "Items.brs::ItemMetaData processed unhandled type: " data.type
' Return json if we don't know what it is
@@ -369,10 +373,6 @@ function TVSeasons(id as string)
results = []
for each item in data.Items
imgParams = { "AddPlayedIndicator": item.UserData.Played }
- if item.UserData.UnplayedItemCount > 0
- param = { "UnplayedCount": item.UserData.UnplayedItemCount }
- imgParams.Append(param)
- end if
tmp = CreateObject("roSGNode", "TVEpisodeData")
tmp.image = PosterImage(item.id, imgParams)
tmp.json = item
@@ -389,11 +389,7 @@ function TVEpisodes(show_id as string, season_id as string)
data = getJson(resp)
results = []
for each item in data.Items
- imgParams = { "AddPlayedIndicator": item.UserData.Played, "maxWidth": 400, "maxheight": 250 }
- if item.UserData.PlayedPercentage <> invalid
- param = { "PercentPlayed": item.UserData.PlayedPercentage }
- imgParams.Append(param)
- end if
+ imgParams = { "maxWidth": 400, "maxheight": 250 }
tmp = CreateObject("roSGNode", "TVEpisodeData")
tmp.image = PosterImage(item.id, imgParams)
if tmp.image <> invalid
diff --git a/source/static/whatsNew.json b/source/static/whatsNew.json
new file mode 100644
index 00000000..af549b75
--- /dev/null
+++ b/source/static/whatsNew.json
@@ -0,0 +1,98 @@
+[
+ {
+ "description": "Bug Fix: Don't crash when viewing in progress recording.",
+ "author": "jimdogx"
+ },
+ {
+ "description": "New Setting: Disable Community Rating for Episodes of TV shows.",
+ "author": "dezchai"
+ },
+ {
+ "description": "New View: Music Grid View",
+ "author": "1hitsong"
+ },
+ {
+ "description": "New Setting: Movie Grid Title Display",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Updated View: TV Library Genre View",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Bug Fix: Fix Crash When Options Button Pressed, but Options Are Not Available",
+ "author": "ApexArray"
+ },
+ {
+ "description": "Bug Fix: Fix Crash When Invalid Deep Link Arguments Are Passed",
+ "author": "ApexArray"
+ },
+ {
+ "description": "New Setting: Go straight to episode listing (if only 1 season available)",
+ "author": "ApexArray"
+ },
+ {
+ "description": "Feature: Create What's New Popup that tells users what's changed the first time they run a new version.",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Feature: Toggle video playback when OK button is pressed",
+ "author": "ApexArray"
+ },
+ {
+ "description": "Bug Fix: Fix TV Season List Crash when showing 27+ Episodes",
+ "author": "1hitsong"
+ },
+ {
+ "description": "New View: Create Movie Grid View and new default setting",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Core: Set Maximum Bitrates values based on Roku Guidelines",
+ "author": "ApexArray"
+ },
+ {
+ "description": "Core: Reorganize Roku Settings",
+ "author": "sevenrats"
+ },
+ {
+ "description": "Updated View: Add resumable filter to Movies",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Updated View: Filter Movies & Series by Played/Unplayed status",
+ "author": "1hitsong"
+ },
+ {
+ "description": "New Setting: Hide subtitles that might transcode",
+ "author": "sevenrats"
+ },
+ {
+ "description": "Bug Fix: Show Unwatched Episode Count",
+ "author": "1hitsong"
+ },
+ {
+ "description": "New View: Add Artist Presentation View & Genre View to Music Library",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Core: Draw Homepage Continue Watching percent complete bar instead of using image API",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Bug Fix: Fix TV Episode focus issues",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Bug Fix: Fix Movie Detail View lost focus bug when going back from resume dialog",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Core: Add new questions to GitHub bug template",
+ "author": "1hitsong"
+ },
+ {
+ "description": "Core: Create Queue Manager and use for Music",
+ "author": "1hitsong"
+ }
+]
\ No newline at end of file
diff --git a/source/utils/Subtitles.brs b/source/utils/Subtitles.brs
index 51949e22..4be995a5 100644
--- a/source/utils/Subtitles.brs
+++ b/source/utils/Subtitles.brs
@@ -21,7 +21,7 @@ end function
' returns the server-side track index for the appriate subtitle
function defaultSubtitleTrackFromVid(video_id) as integer
meta = ItemMetaData(video_id)
- if meta.json.mediaSources <> invalid
+ if meta?.json?.mediaSources <> invalid
subtitles = sortSubtitles(meta.id, meta.json.MediaSources[0].MediaStreams)
default_text_subs = defaultSubtitleTrack(subtitles["all"], true) ' Find correct subtitle track (forced text)
if default_text_subs <> -1
diff --git a/source/utils/deviceCapabilities.brs b/source/utils/deviceCapabilities.brs
index ceb5bebe..8df2374b 100644
--- a/source/utils/deviceCapabilities.brs
+++ b/source/utils/deviceCapabilities.brs
@@ -170,6 +170,13 @@ function getDeviceProfile() as object
"Property": "VideoLevel",
"Value": "41",
"IsRequired": false
+ },
+ ' Roku only supports h264 up to 10Mpbs
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "10000000",
+ IsRequired: true
}
]
}
@@ -203,6 +210,13 @@ function getDeviceProfile() as object
"Property": "VideoRangeType",
"Value": av1VideoRangeTypes,
"IsRequired": false
+ },
+ ' Roku only supports AVI up to 40Mpbs
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "40000000",
+ IsRequired: true
}
]
})
@@ -229,6 +243,13 @@ function getDeviceProfile() as object
"Property": "VideoLevel",
"Value": (120 * 5.1).ToStr(),
"IsRequired": false
+ },
+ ' Roku only supports h265 up to 40Mpbs
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "40000000",
+ IsRequired: true
}
]
})
@@ -243,6 +264,13 @@ function getDeviceProfile() as object
"Property": "VideoRangeType",
"Value": vp9VideoRangeTypes,
"IsRequired": false
+ },
+ ' Roku only supports VP9 up to 40Mpbs
+ {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "40000000",
+ IsRequired: true
}
]
})
diff --git a/source/utils/misc.brs b/source/utils/misc.brs
index 31b80f36..7521ce49 100644
--- a/source/utils/misc.brs
+++ b/source/utils/misc.brs
@@ -91,6 +91,12 @@ function get_dialog_result(dialog, port)
end function
function lastFocusedChild(obj as object) as object
+ if LCase(obj.focusedChild.focusedChild.subType()) = "tvepisodes"
+ if isValid(obj?.focusedChild?.focusedChild?.lastFocus)
+ return obj.focusedChild.focusedChild.lastFocus
+ end if
+ end if
+
child = obj
for i = 0 to obj.getChildCount()
if obj.focusedChild <> invalid
@@ -189,6 +195,24 @@ function isValid(input) as boolean
return input <> invalid
end function
+' Returns whether or not passed value is valid and not empty
+' Accepts a string, or any countable type (arrays and lists)
+function isValidAndNotEmpty(input) as boolean
+ if not isValid(input) then return false
+ ' Use roAssociativeArray instead of list so we get access to the doesExist() method
+ countableTypes = { "array": 1, "list": 1, "roarray": 1, "roassociativearray": 1, "rolist": 1 }
+ inputType = LCase(type(input))
+ if inputType = "string" or inputType = "rostring"
+ trimmedInput = input.trim()
+ return trimmedInput <> ""
+ else if countableTypes.doesExist(inputType)
+ return input.count() > 0
+ else
+ print "Called isValidAndNotEmpty() with invalid type: ", inputType
+ return false
+ end if
+end function
+
' Rounds number to nearest integer
function roundNumber(f as float) as integer
' BrightScript only has a "floor" round