diff --git a/components/ItemGrid/GridItem.brs b/components/ItemGrid/GridItem.brs
index 77c7a6c3..9c0ebec1 100644
--- a/components/ItemGrid/GridItem.brs
+++ b/components/ItemGrid/GridItem.brs
@@ -43,10 +43,12 @@ 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
+ if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
+ 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
diff --git a/components/ListPoster.brs b/components/ListPoster.brs
index ae04ef18..738d7402 100644
--- a/components/ListPoster.brs
+++ b/components/ListPoster.brs
@@ -57,10 +57,12 @@ 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
+ if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
+ 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
diff --git a/components/home/HomeItem.brs b/components/home/HomeItem.brs
index 42830c01..98e501c1 100644
--- a/components/home/HomeItem.brs
+++ b/components/home/HomeItem.brs
@@ -38,10 +38,12 @@ sub itemContentChanged()
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
+ if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
+ 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
end if
diff --git a/components/tvshows/TVEpisodes.brs b/components/tvshows/TVEpisodes.brs
index fb69f9eb..5cb412f9 100644
--- a/components/tvshows/TVEpisodes.brs
+++ b/components/tvshows/TVEpisodes.brs
@@ -17,10 +17,12 @@ 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
+ if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
+ 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
end if
diff --git a/components/tvshows/TVShowDetails.brs b/components/tvshows/TVShowDetails.brs
index fc39755b..6e578814 100644
--- a/components/tvshows/TVShowDetails.brs
+++ b/components/tvshows/TVShowDetails.brs
@@ -15,10 +15,12 @@ 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
+ if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
+ if itemData?.UserData?.UnplayedItemCount <> invalid
+ if itemData.UserData.UnplayedItemCount > 0
+ m.unplayedCount.visible = true
+ m.unplayedEpisodeCount.text = itemData.UserData.UnplayedItemCount
+ end if
end if
end if
diff --git a/components/tvshows/TVShowDetails.xml b/components/tvshows/TVShowDetails.xml
index 7bdc7d8b..cf058566 100644
--- a/components/tvshows/TVShowDetails.xml
+++ b/components/tvshows/TVShowDetails.xml
@@ -33,5 +33,6 @@
+
diff --git a/locale/en_GB/translations.ts b/locale/en_GB/translations.ts
index 8dc04333..3f3a8ab1 100644
--- a/locale/en_GB/translations.ts
+++ b/locale/en_GB/translations.ts
@@ -3055,5 +3055,53 @@
Cast & Crew
+
+
+ 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
+
+
+
+ Enter the server name or IP address
+ Title of KeyboardDialog when manually entering a server URL
+
+
+
+ TV Shows
+
+
+
+ Cancel Recording
+
+
+
+ Additional Parts
+ Additional parts of a video
+
+
+
+ View Channel
+
+
+
+ Record
+
+
+
+ Cancel Series Recording
+
+
+
+ Close
+
+
+
+ Unknown
+ Title for a cast member for which we have no information for
+
+
+
+ Record Series
+
diff --git a/locale/en_US/translations.ts b/locale/en_US/translations.ts
index 796968b3..e5b0b3d6 100644
--- a/locale/en_US/translations.ts
+++ b/locale/en_US/translations.ts
@@ -1021,6 +1021,30 @@
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.
+
+
+ Playback Bitrate Limits
+
+
+
+ Set limits for how high playback bitrates are allowed to be.
+
+
+
+ Limits Enabled
+
+
+
+ If enabled, playback bitrates will be limited based on the 'Playback Bitrate Limit' setting.
+
+
+
+ Playback Bitrate Limit
+
+
+
+ Max bitrate (Mbps) allowed if limits are enabled. Set to 0 to use Roku's specifications.
+ Libraries
@@ -1063,5 +1087,16 @@
GridTitle of an option - name of grid view
+
+
+
+ Disable Unwatched Episode Count
+ Settings Menu - Title for option
+
+
+
+ If enabled, the number of unwatched episodes in a series/season will be removed.
+ Settings Menu - Description for option
+
diff --git a/settings/settings.json b/settings/settings.json
index 3dd36467..bb645058 100644
--- a/settings/settings.json
+++ b/settings/settings.json
@@ -3,6 +3,13 @@
"title": "Playback",
"description": "Settings relating to playback and supported codec and media types.",
"children": [
+ {
+ "title": "Cinema Mode",
+ "description": "Cinema Mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.",
+ "settingName": "playback.cinemamode",
+ "type": "bool",
+ "default": "false"
+ },
{
"title": "Codec Support",
"description": "Enable or disable Direct Play support for certain codecs",
@@ -30,6 +37,26 @@
}
]
},
+ {
+ "title": "Playback Bitrate Limits",
+ "description": "Set limits for how high playback bitrates are allowed to be.",
+ "children": [
+ {
+ "title": "Limits Enabled",
+ "description": "If enabled, playback bitrates will be limited based on the 'Playback Bitrate Limit' setting.",
+ "settingName": "playback.bitrate.maxlimited",
+ "type": "bool",
+ "default": "true"
+ },
+ {
+ "title": "Playback Bitrate Limit",
+ "description": "Max bitrate (Mbps) allowed if limits are enabled. Set to 0 to use Roku's specifications.",
+ "settingName": "playback.bitrate.limit",
+ "type": "integer",
+ "default": "0"
+ }
+ ]
+ },
{
"title": "Profile Level Support",
"description": "Attempt Direct Play of potentially unsupported profile levels",
@@ -50,13 +77,6 @@
}
]
},
- {
- "title": "Cinema Mode",
- "description": "Cinema Mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.",
- "settingName": "playback.cinemamode",
- "type": "bool",
- "default": "false"
- },
{
"title": "Text Subtitles Only",
"description": "Only display text subtitles to minimize transcoding.",
@@ -204,16 +224,23 @@
"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",
+ "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"
},
{
- "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",
+ "title": "Disable Unwatched Episode Count",
+ "description": "If enabled, the number of unwatched episodes in a series/season will be removed.",
+ "settingName": "ui.tvshows.disableUnwatchedEpisodeCount",
+ "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"
}
diff --git a/source/utils/deviceCapabilities.brs b/source/utils/deviceCapabilities.brs
index 8df2374b..501b8910 100644
--- a/source/utils/deviceCapabilities.brs
+++ b/source/utils/deviceCapabilities.brs
@@ -171,13 +171,7 @@ function getDeviceProfile() as object
"Value": "41",
"IsRequired": false
},
- ' Roku only supports h264 up to 10Mpbs
- {
- "Condition": "LessThanEqual",
- "Property": "VideoBitrate",
- "Value": "10000000",
- IsRequired: true
- }
+ GetBitRateLimit("H264")
]
}
],
@@ -211,13 +205,7 @@ function getDeviceProfile() as object
"Value": av1VideoRangeTypes,
"IsRequired": false
},
- ' Roku only supports AVI up to 40Mpbs
- {
- "Condition": "LessThanEqual",
- "Property": "VideoBitrate",
- "Value": "40000000",
- IsRequired: true
- }
+ GetBitRateLimit("AV1")
]
})
end if
@@ -244,13 +232,7 @@ function getDeviceProfile() as object
"Value": (120 * 5.1).ToStr(),
"IsRequired": false
},
- ' Roku only supports h265 up to 40Mpbs
- {
- "Condition": "LessThanEqual",
- "Property": "VideoBitrate",
- "Value": "40000000",
- IsRequired: true
- }
+ GetBitRateLimit("H265")
]
})
end if
@@ -265,13 +247,7 @@ function getDeviceProfile() as object
"Value": vp9VideoRangeTypes,
"IsRequired": false
},
- ' Roku only supports VP9 up to 40Mpbs
- {
- "Condition": "LessThanEqual",
- "Property": "VideoBitrate",
- "Value": "40000000",
- IsRequired: true
- }
+ GetBitRateLimit("VP9")
]
})
end if
@@ -382,3 +358,56 @@ function GetDirectPlayProfiles() as object
]
end function
+
+function GetBitRateLimit(codec as string)
+ if get_user_setting("playback.bitrate.maxlimited") = "true"
+ userSetLimit = get_user_setting("playback.bitrate.limit").ToInt()
+ userSetLimit *= 1000000
+
+ if userSetLimit > 0
+ return {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": userSetLimit.ToStr(),
+ IsRequired: true
+ }
+ else
+ ' Some repeated values (e.g. same "40mbps" for several codecs)
+ ' but this makes it easy to update in the future if the bitrates start to deviate.
+ if codec = "H264"
+ ' Roku only supports h264 up to 10Mpbs
+ return {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "10000000",
+ IsRequired: true
+ }
+ else if codec = "AV1"
+ ' Roku only supports AV1 up to 40Mpbs
+ return {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "40000000",
+ IsRequired: true
+ }
+ else if codec = "H265"
+ ' Roku only supports h265 up to 40Mpbs
+ return {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "40000000",
+ IsRequired: true
+ }
+ else if codec = "VP9"
+ ' Roku only supports VP9 up to 40Mpbs
+ return {
+ "Condition": "LessThanEqual",
+ "Property": "VideoBitrate",
+ "Value": "40000000",
+ IsRequired: true
+ }
+ end if
+ end if
+ end if
+ return {}
+end function