Merge branch 'unstable' into jf-video-stats
This commit is contained in:
commit
e02afad161
|
@ -19,6 +19,13 @@ Open up the new folder:
|
||||||
cd jellyfin-roku
|
cd jellyfin-roku
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Install Dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Method 1: Visual Studio Code
|
## Method 1: Visual Studio Code
|
||||||
We recommend using Visual Studio Code when working on this project. The [BrightScript Language extension](https://marketplace.visualstudio.com/items?itemName=RokuCommunity.brightscript) provides a rich debugging experience, including in-editor syntax checking, debugging/breakpoint support, variable inspection at runtime, auto-formatting, an integrated remote control mode, and [much more](https://rokucommunity.github.io/vscode-brightscript-language/features.html).
|
We recommend using Visual Studio Code when working on this project. The [BrightScript Language extension](https://marketplace.visualstudio.com/items?itemName=RokuCommunity.brightscript) provides a rich debugging experience, including in-editor syntax checking, debugging/breakpoint support, variable inspection at runtime, auto-formatting, an integrated remote control mode, and [much more](https://rokucommunity.github.io/vscode-brightscript-language/features.html).
|
||||||
|
|
|
@ -25,7 +25,17 @@ sub init()
|
||||||
|
|
||||||
m.itemGrid.observeField("itemFocused", "onItemFocused")
|
m.itemGrid.observeField("itemFocused", "onItemFocused")
|
||||||
m.itemGrid.observeField("itemSelected", "onItemSelected")
|
m.itemGrid.observeField("itemSelected", "onItemSelected")
|
||||||
m.itemGrid.observeField("AlphaSelected", "onItemAlphaSelected")
|
m.itemGrid.observeField("alphaSelected", "onItemalphaSelected")
|
||||||
|
|
||||||
|
'Voice filter setup
|
||||||
|
m.voiceBox = m.top.findNode("voiceBox")
|
||||||
|
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")
|
m.newBackdrop.observeField("loadStatus", "newBGLoaded")
|
||||||
|
|
||||||
'Background Image Queued for loading
|
'Background Image Queued for loading
|
||||||
|
@ -45,19 +55,35 @@ sub init()
|
||||||
|
|
||||||
m.spinner = m.top.findNode("spinner")
|
m.spinner = m.top.findNode("spinner")
|
||||||
m.spinner.visible = true
|
m.spinner.visible = true
|
||||||
|
|
||||||
m.Alpha = m.top.findNode("AlphaMenu")
|
m.Alpha = m.top.findNode("AlphaMenu")
|
||||||
m.AlphaSelected = m.top.findNode("AlphaSelected")
|
m.AlphaSelected = m.top.findNode("AlphaSelected")
|
||||||
|
|
||||||
'Get reset folder setting
|
'Get reset folder setting
|
||||||
m.resetGrid = get_user_setting("itemgrid.reset") = "true"
|
m.resetGrid = get_user_setting("itemgrid.reset") = "true"
|
||||||
|
|
||||||
|
'Check if device has voice remote
|
||||||
|
devinfo = CreateObject("roDeviceInfo")
|
||||||
|
m.deviFeature = devinfo.HasFeature("voice_remote")
|
||||||
|
m.micButton = m.top.findNode("micButton")
|
||||||
|
m.micButtonText = m.top.findNode("micButtonText")
|
||||||
|
'Hide voice search if device does not have voice remote
|
||||||
|
if m.deviFeature = false
|
||||||
|
m.micButton.visible = false
|
||||||
|
m.micButtonText.visible = false
|
||||||
|
end if
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
'
|
'
|
||||||
'Load initial set of Data
|
'Load initial set of Data
|
||||||
sub loadInitialItems()
|
sub loadInitialItems()
|
||||||
|
m.loadItemsTask.control = "stop"
|
||||||
|
m.spinner.visible = true
|
||||||
|
|
||||||
if m.top.parentItem.json.Type = "CollectionFolder" 'or m.top.parentItem.json.Type = "Folder"
|
if m.top.parentItem.json.Type = "CollectionFolder" 'or m.top.parentItem.json.Type = "Folder"
|
||||||
m.top.HomeLibraryItem = m.top.parentItem.Id
|
m.top.HomeLibraryItem = m.top.parentItem.Id
|
||||||
end if
|
end if
|
||||||
|
|
||||||
if m.top.parentItem.backdropUrl <> invalid
|
if m.top.parentItem.backdropUrl <> invalid
|
||||||
SetBackground(m.top.parentItem.backdropUrl)
|
SetBackground(m.top.parentItem.backdropUrl)
|
||||||
end if
|
end if
|
||||||
|
@ -66,6 +92,14 @@ sub loadInitialItems()
|
||||||
if m.top.parentItem.collectionType = "livetv"
|
if m.top.parentItem.collectionType = "livetv"
|
||||||
' Translate between app and server nomenclature
|
' Translate between app and server nomenclature
|
||||||
viewSetting = get_user_setting("display.livetv.landing")
|
viewSetting = get_user_setting("display.livetv.landing")
|
||||||
|
'Move mic to be visiable on TV Guide screen
|
||||||
|
if m.deviFeature = true
|
||||||
|
m.micButton.translation = "[1540, 92]"
|
||||||
|
m.micButtonText.visible = true
|
||||||
|
m.micButtonText.translation = "[1600,130]"
|
||||||
|
m.micButtonText.font.size = 22
|
||||||
|
m.micButtonText.text = tr("Search")
|
||||||
|
end if
|
||||||
if viewSetting = "guide"
|
if viewSetting = "guide"
|
||||||
m.view = "tvGuide"
|
m.view = "tvGuide"
|
||||||
else
|
else
|
||||||
|
@ -112,24 +146,31 @@ sub loadInitialItems()
|
||||||
end if
|
end if
|
||||||
updateTitle()
|
updateTitle()
|
||||||
|
|
||||||
m.loadItemsTask.nameStartsWith = m.top.AlphaSelected
|
m.loadItemsTask.nameStartsWith = m.top.alphaSelected
|
||||||
|
m.loadItemsTask.searchTerm = m.voiceBox.text
|
||||||
m.emptyText.visible = false
|
m.emptyText.visible = false
|
||||||
m.loadItemsTask.sortField = m.sortField
|
m.loadItemsTask.sortField = m.sortField
|
||||||
m.loadItemsTask.sortAscending = m.sortAscending
|
m.loadItemsTask.sortAscending = m.sortAscending
|
||||||
m.loadItemsTask.filter = m.filter
|
m.loadItemsTask.filter = m.filter
|
||||||
m.loadItemsTask.startIndex = 0
|
m.loadItemsTask.startIndex = 0
|
||||||
|
|
||||||
' Load Item Types
|
' Load Item Types
|
||||||
if m.top.parentItem.collectionType = "movies"
|
if getCollectionType() = "movies"
|
||||||
m.loadItemsTask.itemType = "Movie"
|
m.loadItemsTask.itemType = "Movie"
|
||||||
m.loadItemsTask.itemId = m.top.parentItem.Id
|
m.loadItemsTask.itemId = m.top.parentItem.Id
|
||||||
else if m.top.parentItem.collectionType = "tvshows"
|
else if getCollectionType() = "tvshows"
|
||||||
m.loadItemsTask.itemType = "Series"
|
m.loadItemsTask.itemType = "Series"
|
||||||
m.loadItemsTask.itemId = m.top.parentItem.Id
|
m.loadItemsTask.itemId = m.top.parentItem.Id
|
||||||
else if m.top.parentItem.collectionType = "music"
|
else if getCollectionType() = "music"
|
||||||
' Default Settings
|
' Default Settings
|
||||||
m.loadItemsTask.recursive = false
|
|
||||||
m.itemGrid.itemSize = "[290, 290]"
|
if m.voiceBox.text <> ""
|
||||||
m.itemGrid.itemSpacing = "[ 0, 20]"
|
m.loadItemsTask.recursive = true
|
||||||
|
else
|
||||||
|
m.loadItemsTask.recursive = false
|
||||||
|
m.itemGrid.itemSize = "[290, 290]"
|
||||||
|
end if
|
||||||
|
|
||||||
m.loadItemsTask.itemType = "MusicArtist,MusicAlbum"
|
m.loadItemsTask.itemType = "MusicArtist,MusicAlbum"
|
||||||
m.loadItemsTask.itemId = m.top.parentItem.Id
|
m.loadItemsTask.itemId = m.top.parentItem.Id
|
||||||
|
|
||||||
|
@ -143,19 +184,21 @@ sub loadInitialItems()
|
||||||
m.loadItemsTask.recursive = true
|
m.loadItemsTask.recursive = true
|
||||||
end if
|
end if
|
||||||
else if m.top.parentItem.collectionType = "livetv"
|
else if m.top.parentItem.collectionType = "livetv"
|
||||||
m.loadItemsTask.itemType = "LiveTV"
|
m.loadItemsTask.itemType = "TvChannel"
|
||||||
|
m.loadItemsTask.itemId = " "
|
||||||
' For LiveTV, we want to "Fit" the item images, not zoom
|
' For LiveTV, we want to "Fit" the item images, not zoom
|
||||||
m.top.imageDisplayMode = "scaleToFit"
|
m.top.imageDisplayMode = "scaleToFit"
|
||||||
|
|
||||||
if get_user_setting("display.livetv.landing") = "guide" and m.options.view <> "livetv"
|
if get_user_setting("display.livetv.landing") = "guide" and m.options.view <> "livetv"
|
||||||
showTvGuide()
|
showTvGuide()
|
||||||
end if
|
end if
|
||||||
else if m.top.parentItem.collectionType = "CollectionFolder" or m.top.parentItem.type = "CollectionFolder" or m.top.parentItem.collectionType = "boxsets" or m.top.parentItem.Type = "Boxset" or m.top.parentItem.Type = "Folder" or m.top.parentItem.Type = "Channel"
|
else if m.top.parentItem.collectionType = "CollectionFolder" or m.top.parentItem.type = "CollectionFolder" or m.top.parentItem.collectionType = "boxsets" or m.top.parentItem.Type = "Boxset" or m.top.parentItem.Type = "Boxsets" or m.top.parentItem.Type = "Folder" or m.top.parentItem.Type = "Channel"
|
||||||
' Non-recursive, to not show subfolder contents
|
if m.voiceBox.text <> ""
|
||||||
m.loadItemsTask.recursive = false
|
m.loadItemsTask.recursive = true
|
||||||
else if m.top.parentItem.Type = "Channel"
|
else
|
||||||
m.top.imageDisplayMode = "scaleToFit"
|
' non recursive for collections (folders, boxsets, photo albums, etc)
|
||||||
|
m.loadItemsTask.recursive = false
|
||||||
|
end if
|
||||||
else if m.top.parentItem.json.type = "Studio"
|
else if m.top.parentItem.json.type = "Studio"
|
||||||
m.loadItemsTask.itemId = m.top.parentItem.parentFolder
|
m.loadItemsTask.itemId = m.top.parentItem.parentFolder
|
||||||
m.loadItemsTask.itemType = "Series,Movie"
|
m.loadItemsTask.itemType = "Series,Movie"
|
||||||
|
@ -491,13 +534,33 @@ sub onItemSelected()
|
||||||
m.top.selectedItem = m.itemGrid.content.getChild(m.itemGrid.itemSelected)
|
m.top.selectedItem = m.itemGrid.content.getChild(m.itemGrid.itemSelected)
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub onItemAlphaSelected()
|
sub onItemalphaSelected()
|
||||||
m.loadedRows = 0
|
if m.top.alphaSelected <> ""
|
||||||
m.loadedItems = 0
|
m.loadedRows = 0
|
||||||
m.data = CreateObject("roSGNode", "ContentNode")
|
m.loadedItems = 0
|
||||||
m.itemGrid.content = m.data
|
m.data = CreateObject("roSGNode", "ContentNode")
|
||||||
m.spinner.visible = true
|
m.itemGrid.content = m.data
|
||||||
loadInitialItems()
|
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
|
end sub
|
||||||
|
|
||||||
|
|
||||||
|
@ -598,6 +661,7 @@ sub optionsClosed()
|
||||||
if m.tvGuide <> invalid
|
if m.tvGuide <> invalid
|
||||||
m.tvGuide.lastFocus.setFocus(true)
|
m.tvGuide.lastFocus.setFocus(true)
|
||||||
end if
|
end if
|
||||||
|
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub showTVGuide()
|
sub showTVGuide()
|
||||||
|
@ -608,6 +672,7 @@ sub showTVGuide()
|
||||||
m.tvGuide.observeField("focusedChannel", "onChannelFocused")
|
m.tvGuide.observeField("focusedChannel", "onChannelFocused")
|
||||||
end if
|
end if
|
||||||
m.tvGuide.filter = m.filter
|
m.tvGuide.filter = m.filter
|
||||||
|
m.tvGuide.searchTerm = m.voiceBox.text
|
||||||
m.top.appendChild(m.tvGuide)
|
m.top.appendChild(m.tvGuide)
|
||||||
m.tvGuide.lastFocus.setFocus(true)
|
m.tvGuide.lastFocus.setFocus(true)
|
||||||
end sub
|
end sub
|
||||||
|
@ -629,6 +694,12 @@ end sub
|
||||||
function onKeyEvent(key as string, press as boolean) as boolean
|
function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
if not press then return false
|
if not press then return false
|
||||||
topGrp = m.top.findNode("itemGrid")
|
topGrp = m.top.findNode("itemGrid")
|
||||||
|
searchGrp = m.top.findNode("voiceBox")
|
||||||
|
|
||||||
|
if key = "left" and searchGrp.isinFocusChain()
|
||||||
|
topGrp.setFocus(true)
|
||||||
|
searchGrp.setFocus(false)
|
||||||
|
end if
|
||||||
if key = "options"
|
if key = "options"
|
||||||
if m.options.visible = true
|
if m.options.visible = true
|
||||||
m.options.visible = false
|
m.options.visible = false
|
||||||
|
@ -655,9 +726,13 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
m.options.visible = false
|
m.options.visible = false
|
||||||
optionsClosed()
|
optionsClosed()
|
||||||
return true
|
return true
|
||||||
|
else
|
||||||
|
m.global.sceneManager.callfunc("popScene")
|
||||||
|
m.loadItemsTask.control = "stop"
|
||||||
|
return true
|
||||||
end if
|
end if
|
||||||
else if key = "play" or key = "OK"
|
else if key = "play" or key = "OK"
|
||||||
markupGrid = m.top.getChild(2)
|
markupGrid = m.top.findNode("itemGrid")
|
||||||
itemToPlay = markupGrid.content.getChild(markupGrid.itemFocused)
|
itemToPlay = markupGrid.content.getChild(markupGrid.itemFocused)
|
||||||
|
|
||||||
if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
|
if itemToPlay <> invalid and (itemToPlay.type = "Movie" or itemToPlay.type = "Episode")
|
||||||
|
@ -673,9 +748,10 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
else if key = "left" and topGrp.isinFocusChain()
|
else if key = "left" and topGrp.isinFocusChain()
|
||||||
m.top.alphaActive = true
|
m.top.alphaActive = true
|
||||||
topGrp.setFocus(false)
|
topGrp.setFocus(false)
|
||||||
alpha = m.Alpha.getChild(0).findNode("Alphamenu")
|
alpha = m.alpha.getChild(0).findNode("Alphamenu")
|
||||||
alpha.setFocus(true)
|
alpha.setFocus(true)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
else if key = "right" and m.Alpha.isinFocusChain()
|
else if key = "right" and m.Alpha.isinFocusChain()
|
||||||
m.top.alphaActive = false
|
m.top.alphaActive = false
|
||||||
m.Alpha.setFocus(false)
|
m.Alpha.setFocus(false)
|
||||||
|
@ -690,6 +766,20 @@ function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
end if
|
end if
|
||||||
end if
|
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
|
return false
|
||||||
end function
|
end function
|
||||||
|
|
||||||
|
@ -699,9 +789,11 @@ sub updateTitle()
|
||||||
else if m.filter = "Favorites"
|
else if m.filter = "Favorites"
|
||||||
m.top.overhangTitle = m.top.parentItem.title + " " + tr("(Favorites)")
|
m.top.overhangTitle = m.top.parentItem.title + " " + tr("(Favorites)")
|
||||||
end if
|
end if
|
||||||
|
if m.voiceBox.text <> ""
|
||||||
if m.top.AlphaSelected <> ""
|
m.top.overhangTitle = m.top.parentItem.title + tr(" (Filtered by ") + m.loadItemsTask.searchTerm + ")"
|
||||||
m.top.overhangTitle = m.top.parentItem.title + " " + tr("(Filtered)")
|
end if
|
||||||
|
if m.top.alphaSelected <> ""
|
||||||
|
m.top.overhangTitle = m.top.parentItem.title + tr(" (Filtered by ") + m.loadItemsTask.nameStartsWith + ")"
|
||||||
end if
|
end if
|
||||||
|
|
||||||
if m.options.view = "Networks" or m.view = "Networks"
|
if m.options.view = "Networks" or m.view = "Networks"
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<component name="ItemGrid" extends="JFGroup">
|
<component name="ItemGrid" extends="JFGroup">
|
||||||
<children>
|
<children>
|
||||||
|
<VoiceTextEditBox id="VoiceBox" visible="true" width = "40" translation = "[52, 120]" />
|
||||||
|
<Rectangle id="VoiceBoxCover" height="240" width="100" color="0x262626ff" translation = "[25, 75]" />
|
||||||
<poster id="backdrop"
|
<poster id="backdrop"
|
||||||
loadDisplayMode="scaleToFill"
|
loadDisplayMode="scaleToFill"
|
||||||
width="1920"
|
width="1920"
|
||||||
|
@ -23,10 +24,12 @@
|
||||||
vertFocusAnimationStyle = "fixed"
|
vertFocusAnimationStyle = "fixed"
|
||||||
itemSize = "[ 290, 425 ]"
|
itemSize = "[ 290, 425 ]"
|
||||||
itemSpacing = "[ 0, 45 ]"
|
itemSpacing = "[ 0, 45 ]"
|
||||||
drawFocusFeedback = "false" />
|
drawFocusFeedback = "false" />
|
||||||
<Label translation="[0,540]" id="emptyText" font="font:LargeSystemFont" width="1920" horizAlign="center" vertAlign="center" height="64" visible="false" />
|
<Label id="micButtonText" font="font:SmallSystemFont" visible="false" />
|
||||||
|
<Button id = "micButton" maxWidth = "20" translation = "[20, 120]" iconUri = "pkg:/images/icons/mic_icon.png"/>
|
||||||
|
<Label translation="[0,540]" id="emptyText" font="font:LargeSystemFont" width="1910" horizAlign="center" vertAlign="center" height="64" visible="false" />
|
||||||
<ItemGridOptions id="options" visible="false" />
|
<ItemGridOptions id="options" visible="false" />
|
||||||
<Spinner id="spinner" translation="[920, 540]" />
|
<Spinner id="spinner" translation="[900, 450]" />
|
||||||
<Animation id="backroundSwapAnimation" duration="1" repeat="false" easeFunction="linear" >
|
<Animation id="backroundSwapAnimation" duration="1" repeat="false" easeFunction="linear" >
|
||||||
<FloatFieldInterpolator id = "fadeinLoading" key="[0.0, 1.0]" keyValue="[ 0.00, 0.25 ]" fieldToInterp="backdropTransition.opacity" />
|
<FloatFieldInterpolator id = "fadeinLoading" key="[0.0, 1.0]" keyValue="[ 0.00, 0.25 ]" fieldToInterp="backdropTransition.opacity" />
|
||||||
<FloatFieldInterpolator id = "fadeoutLoaded" key="[0.0, 1.0]" keyValue="[ 0.25, 0.00 ]" fieldToInterp="backdrop.opacity" />
|
<FloatFieldInterpolator id = "fadeoutLoaded" key="[0.0, 1.0]" keyValue="[ 0.25, 0.00 ]" fieldToInterp="backdrop.opacity" />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
sub init()
|
sub init()
|
||||||
|
|
||||||
m.buttons = m.top.findNode("buttons")
|
m.buttons = m.top.findNode("buttons")
|
||||||
m.buttons.buttons = [tr("TAB_VIEW"), tr("TAB_SORT"), tr("TAB_FILTER")]
|
m.buttons.buttons = [tr("View"), tr("Sort"), tr("Filter")]
|
||||||
m.buttons.selectedIndex = 1
|
m.buttons.selectedIndex = 1
|
||||||
m.buttons.setFocus(true)
|
m.buttons.setFocus(true)
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
sub init()
|
sub init()
|
||||||
m.top.functionName = "loadItems"
|
m.top.functionName = "loadItems"
|
||||||
|
|
||||||
|
m.top.limit = 60
|
||||||
|
usersettingLimit = get_user_setting("itemgrid.Limit")
|
||||||
|
|
||||||
|
if usersettingLimit <> invalid
|
||||||
|
m.top.limit = usersettingLimit
|
||||||
|
end if
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub loadItems()
|
sub loadItems()
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
sort_field = m.top.sortField
|
sort_field = m.top.sortField
|
||||||
|
@ -26,15 +32,30 @@ sub loadItems()
|
||||||
StudioIds: m.top.studioIds,
|
StudioIds: m.top.studioIds,
|
||||||
genreIds: m.top.genreIds
|
genreIds: m.top.genreIds
|
||||||
}
|
}
|
||||||
|
|
||||||
' Handle special case when getting names starting with numeral
|
' Handle special case when getting names starting with numeral
|
||||||
if m.top.NameStartsWith <> ""
|
if m.top.NameStartsWith <> ""
|
||||||
if m.top.NameStartsWith = "#"
|
if m.top.NameStartsWith = "#"
|
||||||
params.NameLessThan = "A"
|
if m.top.ItemType = "LiveTV" or m.top.ItemType = "TvChannel"
|
||||||
|
params.searchterm = "A"
|
||||||
|
params.append({ parentid: " " })
|
||||||
|
else
|
||||||
|
params.NameLessThan = "A"
|
||||||
|
end if
|
||||||
else
|
else
|
||||||
params.NameStartsWith = m.top.nameStartsWith
|
if m.top.ItemType = "LiveTV" or m.top.ItemType = "TvChannel"
|
||||||
|
params.searchterm = m.top.nameStartsWith
|
||||||
|
params.append({ parentid: " " })
|
||||||
|
else
|
||||||
|
params.NameStartsWith = m.top.nameStartsWith
|
||||||
|
end if
|
||||||
end if
|
end if
|
||||||
end if
|
end if
|
||||||
|
|
||||||
|
if m.top.searchTerm <> ""
|
||||||
|
params.searchTerm = m.top.searchTerm
|
||||||
|
end if
|
||||||
|
|
||||||
filter = m.top.filter
|
filter = m.top.filter
|
||||||
if filter = "All" or filter = "all"
|
if filter = "All" or filter = "all"
|
||||||
' do nothing
|
' do nothing
|
||||||
|
@ -71,7 +92,7 @@ sub loadItems()
|
||||||
tmp = CreateObject("roSGNode", "MovieData")
|
tmp = CreateObject("roSGNode", "MovieData")
|
||||||
else if item.Type = "Series"
|
else if item.Type = "Series"
|
||||||
tmp = CreateObject("roSGNode", "SeriesData")
|
tmp = CreateObject("roSGNode", "SeriesData")
|
||||||
else if item.Type = "BoxSet"
|
else if item.Type = "BoxSet" or item.Type = "ManualPlaylistsFolder"
|
||||||
tmp = CreateObject("roSGNode", "CollectionData")
|
tmp = CreateObject("roSGNode", "CollectionData")
|
||||||
else if item.Type = "TvChannel"
|
else if item.Type = "TvChannel"
|
||||||
tmp = CreateObject("roSGNode", "ChannelData")
|
tmp = CreateObject("roSGNode", "ChannelData")
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
<field id="nameStartsWith" type="string" value="" />
|
<field id="nameStartsWith" type="string" value="" />
|
||||||
<field id="recursive" type="boolean" value="true" />
|
<field id="recursive" type="boolean" value="true" />
|
||||||
<field id="filter" type="string" value="All" />
|
<field id="filter" type="string" value="All" />
|
||||||
|
<field id="searchTerm" type="string" value="" />
|
||||||
<field id="studioIds" type="string" value="" />
|
<field id="studioIds" type="string" value="" />
|
||||||
<field id="genreIds" type="string" value="" />
|
<field id="genreIds" type="string" value="" />
|
||||||
<field id="view" type="string" value="" />
|
<field id="view" type="string" value="" />
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
sub init()
|
sub init()
|
||||||
m.title = m.top.findNode("title")
|
m.title = m.top.findNode("title")
|
||||||
m.staticTitle = m.top.findNode("staticTitle")
|
m.staticTitle = m.top.findNode("staticTitle")
|
||||||
|
m.series = m.top.findNode("Series")
|
||||||
m.poster = m.top.findNode("poster")
|
m.poster = m.top.findNode("poster")
|
||||||
|
|
||||||
m.backdrop = m.top.findNode("backdrop")
|
m.backdrop = m.top.findNode("backdrop")
|
||||||
|
@ -39,6 +40,8 @@ sub updateSize()
|
||||||
m.staticTitle.height = m.title.height
|
m.staticTitle.height = m.title.height
|
||||||
m.staticTitle.translation = m.title.translation
|
m.staticTitle.translation = m.title.translation
|
||||||
|
|
||||||
|
m.series.maxWidth = maxSize[0]
|
||||||
|
|
||||||
m.poster.width = int(maxSize[0]) - 4
|
m.poster.width = int(maxSize[0]) - 4
|
||||||
m.poster.height = int(maxSize[1]) - m.title.height 'Set poster height to available space
|
m.poster.height = int(maxSize[1]) - m.title.height 'Set poster height to available space
|
||||||
|
|
||||||
|
@ -54,9 +57,14 @@ sub itemContentChanged() as void
|
||||||
|
|
||||||
if itemData.json.lookup("Type") = "Episode" and itemData.json.IndexNumber <> invalid
|
if itemData.json.lookup("Type") = "Episode" and itemData.json.IndexNumber <> invalid
|
||||||
m.title.text = StrI(itemData.json.IndexNumber) + ". " + m.title.text
|
m.title.text = StrI(itemData.json.IndexNumber) + ". " + m.title.text
|
||||||
|
|
||||||
|
m.series.text = itemData.json.Series
|
||||||
|
m.series.visible = true
|
||||||
|
|
||||||
else if itemData.json.lookup("Type") = "MusicAlbum"
|
else if itemData.json.lookup("Type") = "MusicAlbum"
|
||||||
m.title.font = "font:SmallestSystemFont"
|
m.title.font = "font:SmallestSystemFont"
|
||||||
m.staticTitle.font = "font:SmallestSystemFont"
|
m.staticTitle.font = "font:SmallestSystemFont"
|
||||||
|
|
||||||
end if
|
end if
|
||||||
m.staticTitle.text = m.title.text
|
m.staticTitle.text = m.title.text
|
||||||
|
|
||||||
|
@ -64,7 +72,7 @@ sub itemContentChanged() as void
|
||||||
|
|
||||||
if get_user_setting("ui.tvshows.blurunwatched") = "true"
|
if get_user_setting("ui.tvshows.blurunwatched") = "true"
|
||||||
|
|
||||||
if itemData.json.lookup("Type") = "Episode"
|
if itemData.json.lookup("Type") = "Episode" and itemData.json.userdata <> invalid
|
||||||
if not itemData.json.userdata.played
|
if not itemData.json.userdata.played
|
||||||
imageUrl = imageUrl + "&blur=15"
|
imageUrl = imageUrl + "&blur=15"
|
||||||
end if
|
end if
|
||||||
|
@ -82,6 +90,7 @@ sub focusChanged()
|
||||||
|
|
||||||
if m.top.itemHasFocus = true
|
if m.top.itemHasFocus = true
|
||||||
m.title.repeatCount = -1
|
m.title.repeatCount = -1
|
||||||
|
m.series.repeatCount = -1
|
||||||
m.staticTitle.visible = false
|
m.staticTitle.visible = false
|
||||||
m.title.visible = true
|
m.title.visible = true
|
||||||
|
|
||||||
|
@ -94,6 +103,7 @@ sub focusChanged()
|
||||||
|
|
||||||
else
|
else
|
||||||
m.title.repeatCount = 0
|
m.title.repeatCount = 0
|
||||||
|
m.series.repeatCount = 0
|
||||||
m.staticTitle.visible = true
|
m.staticTitle.visible = true
|
||||||
m.title.visible = false
|
m.title.visible = false
|
||||||
end if
|
end if
|
||||||
|
|
|
@ -2,6 +2,12 @@
|
||||||
<component name="ListPoster" extends="Group">
|
<component name="ListPoster" extends="Group">
|
||||||
<children>
|
<children>
|
||||||
<Rectangle id="backdrop" />
|
<Rectangle id="backdrop" />
|
||||||
|
<ScrollingLabel id="Series"
|
||||||
|
horizAlign="center"
|
||||||
|
font="font:SmallSystemFont"
|
||||||
|
repeatCount="0"
|
||||||
|
visible="false"
|
||||||
|
/>
|
||||||
<Poster id="poster" translation="[2,0]" loadDisplayMode="scaleToFit" />
|
<Poster id="poster" translation="[2,0]" loadDisplayMode="scaleToFit" />
|
||||||
<ScrollingLabel id="title"
|
<ScrollingLabel id="title"
|
||||||
horizAlign="center"
|
horizAlign="center"
|
||||||
|
|
|
@ -154,7 +154,7 @@ sub createDialogPallete()
|
||||||
DialogSecondaryTextColor: "0xf8f8f8ff",
|
DialogSecondaryTextColor: "0xf8f8f8ff",
|
||||||
DialogSecondaryItemColor: "0xcc7ecc4D",
|
DialogSecondaryItemColor: "0xcc7ecc4D",
|
||||||
DialogInputFieldColor: "0x80FF8080",
|
DialogInputFieldColor: "0x80FF8080",
|
||||||
DialogKeyboardColor: "0x80FF804D",
|
KeyboardDialogColor: "0x80FF804D",
|
||||||
DialogFootprintColor: "0x80FF804D"
|
DialogFootprintColor: "0x80FF804D"
|
||||||
}
|
}
|
||||||
end sub
|
end sub
|
||||||
|
|
|
@ -3,48 +3,25 @@ sub init()
|
||||||
m.top.horizAlignment = "center"
|
m.top.horizAlignment = "center"
|
||||||
m.top.vertAlignment = "top"
|
m.top.vertAlignment = "top"
|
||||||
m.top.visible = false
|
m.top.visible = false
|
||||||
|
m.searchText = m.top.findNode("search_Key")
|
||||||
|
m.searchText.textEditBox.hintText = tr("Search")
|
||||||
|
m.searchText.keyGrid.keyDefinitionUri = "pkg:/components/data/CustomAddressKDF.json"
|
||||||
|
m.searchText.textEditBox.voiceEnabled = true
|
||||||
|
m.searchText.textEditBox.active = true
|
||||||
|
m.searchText.ObserveField("text", "searchMedias")
|
||||||
|
m.searchSelect = m.top.findNode("searchSelect")
|
||||||
|
|
||||||
|
'set lable text
|
||||||
|
m.label = m.top.findNode("text")
|
||||||
|
m.label.text = tr("Search now")
|
||||||
|
|
||||||
show_dialog()
|
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
function onKeyEvent(key as string, press as boolean) as boolean
|
sub searchMedias()
|
||||||
if not press then return false
|
m.top.search_values = m.searchText.text
|
||||||
|
if m.top.search_values.len() > 1
|
||||||
if key = "OK"
|
m.searchText.textEditBox.leadingEllipsis = true
|
||||||
' Make a Keyboard Dialog here
|
else
|
||||||
show_dialog()
|
m.searchText.textEditBox.leadingEllipsis = false
|
||||||
return true
|
|
||||||
end if
|
end if
|
||||||
|
|
||||||
return false
|
|
||||||
end function
|
|
||||||
|
|
||||||
function onDialogButton()
|
|
||||||
d = m.top.getScene().dialog
|
|
||||||
button_text = d.buttons[d.buttonSelected]
|
|
||||||
|
|
||||||
if button_text = tr("Search")
|
|
||||||
m.top.search_value = d.text
|
|
||||||
dismiss_dialog()
|
|
||||||
return true
|
|
||||||
else if button_text = tr("Cancel")
|
|
||||||
dismiss_dialog()
|
|
||||||
return true
|
|
||||||
end if
|
|
||||||
|
|
||||||
return false
|
|
||||||
end function
|
|
||||||
|
|
||||||
sub show_dialog()
|
|
||||||
dialog = CreateObject("roSGNode", "KeyboardDialog")
|
|
||||||
dialog.title = tr("Search")
|
|
||||||
dialog.buttons = [tr("Search"), tr("Cancel")]
|
|
||||||
|
|
||||||
m.top.getScene().dialog = dialog
|
|
||||||
|
|
||||||
dialog.observeField("buttonselected", "onDialogButton")
|
|
||||||
end sub
|
|
||||||
|
|
||||||
sub dismiss_dialog()
|
|
||||||
m.top.getScene().dialog.close = true
|
|
||||||
end sub
|
end sub
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<component name="SearchBox" extends="LayoutGroup">
|
<component name="SearchBox" extends="LayoutGroup">
|
||||||
<children>
|
<children>
|
||||||
<Label text="Search" />
|
<Label id = "text" text="" visible="false" />
|
||||||
<TextEditBox id="search-input" width="800" maxTextLength="75" />
|
<DynamicMiniKeyboard id="search_Key" />
|
||||||
</children>
|
</children>
|
||||||
<interface>
|
<interface>
|
||||||
<field id="search_value" type="string" alwaysNotify="true" />
|
<field id="search_values" type="string" alwaysNotify="true" />
|
||||||
</interface>
|
</interface>
|
||||||
<script type="text/brightscript" uri="SearchBox.brs" />
|
<script type="text/brightscript" uri="SearchBox.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/Items.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/deviceCapabilities.brs" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -45,13 +45,18 @@ end function
|
||||||
|
|
||||||
|
|
||||||
sub show_dialog(configField)
|
sub show_dialog(configField)
|
||||||
dialog = createObject("roSGNode", "KeyboardDialog")
|
dialog = createObject("roSGNode", "StandardKeyboardDialog")
|
||||||
m.configField = configField
|
m.configField = configField
|
||||||
dialog.title = "Enter the " + configField.label
|
dialog.title = "Enter the " + configField.label
|
||||||
dialog.buttons = [tr("OK"), tr("Cancel")]
|
dialog.buttons = [tr("OK"), tr("Cancel")]
|
||||||
|
m.greenPalette = createObject("roSGNode", "RSGPalette")
|
||||||
|
m.greenPalette.colors = {
|
||||||
|
DialogBackgroundColor: "#2A2B2A"
|
||||||
|
}
|
||||||
|
dialog.palette = m.greenPalette
|
||||||
|
|
||||||
if configField.type = "password"
|
if configField.type = "password"
|
||||||
dialog.keyboard.textEditBox.secureMode = true
|
dialog.textEditBox.secureMode = true
|
||||||
end if
|
end if
|
||||||
|
|
||||||
if configField.value <> ""
|
if configField.value <> ""
|
||||||
|
|
|
@ -107,10 +107,13 @@ sub ScanForServersComplete(event)
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub ShowKeyboard()
|
sub ShowKeyboard()
|
||||||
dialog = createObject("roSGNode", "KeyboardDialog")
|
dialog = createObject("roSGNode", "StandardKeyboardDialog")
|
||||||
dialog.title = tr("Enter the server name or ip address")
|
dialog.title = tr("Enter the server name or ip address")
|
||||||
dialog.buttons = [tr("OK"), tr("Cancel")]
|
dialog.buttons = [tr("OK"), tr("Cancel")]
|
||||||
dialog.text = m.serverUrlTextbox.text
|
dialog.text = m.serverUrlTextbox.text
|
||||||
|
greenPalette = createObject("roSGNode", "RSGPalette")
|
||||||
|
greenPalette.colors = { DialogBackgroundColor: "#2A2B2A" }
|
||||||
|
dialog.palette = greenPalette
|
||||||
|
|
||||||
m.top.getscene().dialog = dialog
|
m.top.getscene().dialog = dialog
|
||||||
m.dialog = dialog
|
m.dialog = dialog
|
||||||
|
|
96
components/data/CustomAddressKDF.json
Normal file
96
components/data/CustomAddressKDF.json
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{
|
||||||
|
"keyboardWidthFHD": 374,
|
||||||
|
"keyboardHeightFHD": 409,
|
||||||
|
"keyboardWidthHD": 250,
|
||||||
|
"keyboardHeightHD": 273,
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"grids": [
|
||||||
|
{
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{ "label": "a" },
|
||||||
|
{ "label": "b" },
|
||||||
|
{ "label": "c" },
|
||||||
|
{ "label": "d" },
|
||||||
|
{ "label": "e" },
|
||||||
|
{ "label": "f" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{ "label": "g" },
|
||||||
|
{ "label": "h" },
|
||||||
|
{ "label": "i" },
|
||||||
|
{ "label": "j" },
|
||||||
|
{ "label": "k" },
|
||||||
|
{ "label": "l" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{ "label": "m" },
|
||||||
|
{ "label": "n" },
|
||||||
|
{ "label": "o" },
|
||||||
|
{ "label": "p" },
|
||||||
|
{ "label": "q" },
|
||||||
|
{ "label": "r" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{ "label": "s" },
|
||||||
|
{ "label": "t" },
|
||||||
|
{ "label": "u" },
|
||||||
|
{ "label": "v" },
|
||||||
|
{ "label": "w" },
|
||||||
|
{ "label": "x" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{ "label": "y" },
|
||||||
|
{ "label": "z" },
|
||||||
|
{ "label": "1" },
|
||||||
|
{ "label": "2" },
|
||||||
|
{ "label": "3" },
|
||||||
|
{ "label": "4" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{ "label": "5" },
|
||||||
|
{ "label": "6" },
|
||||||
|
{ "label": "7" },
|
||||||
|
{ "label": "8" },
|
||||||
|
{ "label": "9" },
|
||||||
|
{ "label": "0" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"icon": "theme:DKB_ClearKeyBitmap",
|
||||||
|
"focusIcon": "theme:DKB_ClearKeyFocusBitmap",
|
||||||
|
"strOut": "clear"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "theme:DKB_SpaceKeyBitmap",
|
||||||
|
"focusIcon": "theme:DKB_SpaceKeyFocusBitmap",
|
||||||
|
"strOut": "space"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "theme:DKB_DeleteKeyBitmap",
|
||||||
|
"focusIcon": "theme:DKB_DeleteKeyFocusBitmap",
|
||||||
|
"autoRepeat": 1,
|
||||||
|
"strOut": "backspace"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
<field id="type" type="string" value="Episode" />
|
<field id="type" type="string" value="Episode" />
|
||||||
<field id="json" type="assocarray" onChange="setFields" />
|
<field id="json" type="assocarray" onChange="setFields" />
|
||||||
<field id="selectedAudioStreamIndex" type="integer" />
|
<field id="selectedAudioStreamIndex" type="integer" />
|
||||||
|
<field id="favorite" type="boolean" />
|
||||||
</interface>
|
</interface>
|
||||||
<script type="text/brightscript" uri="TVEpisodeData.brs" />
|
<script type="text/brightscript" uri="TVEpisodeData.brs" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -54,6 +54,22 @@ sub loadItems()
|
||||||
params["ImageTypeLimit"] = 1
|
params["ImageTypeLimit"] = 1
|
||||||
params["UserId"] = get_setting("active_user")
|
params["UserId"] = get_setting("active_user")
|
||||||
|
|
||||||
|
maxDaysInNextUp = get_user_setting("ui.details.maxdaysnextup", "365")
|
||||||
|
if isValid(maxDaysInNextUp)
|
||||||
|
maxDaysInNextUp = Val(maxDaysInNextUp)
|
||||||
|
if maxDaysInNextUp > 0
|
||||||
|
dateToday = CreateObject("roDateTime")
|
||||||
|
dateCutoff = CreateObject("roDateTime")
|
||||||
|
|
||||||
|
dateCutoff.FromSeconds(dateToday.AsSeconds() - (maxDaysInNextUp * 86400))
|
||||||
|
|
||||||
|
params["NextUpDateCutoff"] = dateCutoff.ToISOString()
|
||||||
|
params["EnableRewatching"] = false
|
||||||
|
params["DisableFirstEpisode"] = false
|
||||||
|
params["limit"] = 24
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
|
||||||
resp = APIRequest(url, params)
|
resp = APIRequest(url, params)
|
||||||
data = getJson(resp)
|
data = getJson(resp)
|
||||||
for each item in data.Items
|
for each item in data.Items
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
<script type="text/brightscript" uri="pkg:/source/api/Items.brs" />
|
<script type="text/brightscript" uri="pkg:/source/api/Items.brs" />
|
||||||
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
||||||
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
|
||||||
<script type="text/brightscript" uri="pkg:/source/utils/deviceCapabilities.brs" />
|
<script type="text/brightscript" uri="pkg:/source/utils/deviceCapabilities.brs" />
|
||||||
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
|
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -6,15 +6,41 @@ sub loadChannels()
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
|
sort_field = m.top.sortField
|
||||||
|
|
||||||
|
if m.top.sortAscending = true
|
||||||
|
sort_order = "Ascending"
|
||||||
|
else
|
||||||
|
sort_order = "Descending"
|
||||||
|
end if
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
|
includeItemTypes: "LiveTvChannel",
|
||||||
|
SortBy: sort_field,
|
||||||
|
SortOrder: sort_order,
|
||||||
|
recursive: m.top.recursive,
|
||||||
UserId: get_setting("active_user")
|
UserId: get_setting("active_user")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
' Handle special case when getting names starting with numeral
|
||||||
|
if m.top.NameStartsWith <> ""
|
||||||
|
if m.top.NameStartsWith = "#"
|
||||||
|
params.searchterm = "A"
|
||||||
|
else
|
||||||
|
params.searchterm = m.top.nameStartsWith
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
|
||||||
|
'Append voice search when there is text
|
||||||
|
if m.top.searchTerm <> ""
|
||||||
|
params.searchTerm = m.top.searchTerm
|
||||||
|
end if
|
||||||
|
|
||||||
if m.top.filter = "Favorites"
|
if m.top.filter = "Favorites"
|
||||||
params.append({ isFavorite: true })
|
params.append({ isFavorite: true })
|
||||||
end if
|
end if
|
||||||
|
|
||||||
url = "LiveTv/Channels"
|
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||||
|
|
||||||
resp = APIRequest(url, params)
|
resp = APIRequest(url, params)
|
||||||
data = getJson(resp)
|
data = getJson(resp)
|
||||||
|
@ -39,7 +65,5 @@ sub loadChannels()
|
||||||
results.push(channel)
|
results.push(channel)
|
||||||
end if
|
end if
|
||||||
end for
|
end for
|
||||||
|
|
||||||
m.top.channels = results
|
m.top.channels = results
|
||||||
|
|
||||||
end sub
|
end sub
|
||||||
|
|
|
@ -5,7 +5,11 @@
|
||||||
<field id="limit" type="integer" value="" />
|
<field id="limit" type="integer" value="" />
|
||||||
<field id="startIndex" type="integer" value="0" />
|
<field id="startIndex" type="integer" value="0" />
|
||||||
<field id="filter" type="string" value="All" />
|
<field id="filter" type="string" value="All" />
|
||||||
|
<field id="searchTerm" type="string" value="" />
|
||||||
|
<field id="sortField" type="string" value="SortName" />
|
||||||
|
<field id="sortAscending" type="boolean" value="true" />
|
||||||
|
<field id="nameStartsWith" type="string" value="" />
|
||||||
|
<field id="recursive" type="boolean" value="true" />
|
||||||
<!-- Total records available from server-->
|
<!-- Total records available from server-->
|
||||||
<field id="channels" type="array" />
|
<field id="channels" type="array" />
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
sub init()
|
sub init()
|
||||||
|
|
||||||
m.EPGLaunchCompleteSignaled = false
|
m.EPGLaunchCompleteSignaled = false
|
||||||
m.scheduleGrid = m.top.findNode("scheduleGrid")
|
m.scheduleGrid = m.top.findNode("scheduleGrid")
|
||||||
m.detailsPane = m.top.findNode("detailsPane")
|
m.detailsPane = m.top.findNode("detailsPane")
|
||||||
|
@ -7,7 +6,6 @@ sub init()
|
||||||
m.detailsPane.observeField("watchSelectedChannel", "onWatchChannelSelected")
|
m.detailsPane.observeField("watchSelectedChannel", "onWatchChannelSelected")
|
||||||
m.detailsPane.observeField("recordSelectedChannel", "onRecordChannelSelected")
|
m.detailsPane.observeField("recordSelectedChannel", "onRecordChannelSelected")
|
||||||
m.detailsPane.observeField("recordSeriesSelectedChannel", "onRecordSeriesChannelSelected")
|
m.detailsPane.observeField("recordSeriesSelectedChannel", "onRecordSeriesChannelSelected")
|
||||||
|
|
||||||
m.gridStartDate = CreateObject("roDateTime")
|
m.gridStartDate = CreateObject("roDateTime")
|
||||||
m.scheduleGrid.contentStartTime = m.gridStartDate.AsSeconds() - 1800
|
m.scheduleGrid.contentStartTime = m.gridStartDate.AsSeconds() - 1800
|
||||||
m.gridEndDate = createObject("roDateTime")
|
m.gridEndDate = createObject("roDateTime")
|
||||||
|
@ -28,10 +26,11 @@ sub init()
|
||||||
m.top.lastFocus = m.scheduleGrid
|
m.top.lastFocus = m.scheduleGrid
|
||||||
|
|
||||||
m.channelIndex = {}
|
m.channelIndex = {}
|
||||||
|
|
||||||
|
m.spinner = m.top.findNode("spinner")
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub channelFilterSet()
|
sub channelFilterSet()
|
||||||
print "Channel Filter set"
|
|
||||||
m.scheduleGrid.jumpToChannel = 0
|
m.scheduleGrid.jumpToChannel = 0
|
||||||
if m.top.filter <> invalid and m.LoadChannelsTask.filter <> m.top.filter
|
if m.top.filter <> invalid and m.LoadChannelsTask.filter <> m.top.filter
|
||||||
if m.LoadChannelsTask.state = "run" then m.LoadChannelsTask.control = "stop"
|
if m.LoadChannelsTask.state = "run" then m.LoadChannelsTask.control = "stop"
|
||||||
|
@ -42,6 +41,19 @@ sub channelFilterSet()
|
||||||
|
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
'Voice Search set
|
||||||
|
sub channelsearchTermSet()
|
||||||
|
m.scheduleGrid.jumpToChannel = 0
|
||||||
|
if m.top.searchTerm <> invalid and m.LoadChannelsTask.searchTerm <> m.top.searchTerm
|
||||||
|
if m.LoadChannelsTask.state = "run" then m.LoadChannelsTask.control = "stop"
|
||||||
|
|
||||||
|
m.LoadChannelsTask.searchTerm = m.top.searchTerm
|
||||||
|
m.spinner.visible = true
|
||||||
|
m.LoadChannelsTask.control = "RUN"
|
||||||
|
end if
|
||||||
|
|
||||||
|
end sub
|
||||||
|
|
||||||
' Initial list of channels loaded
|
' Initial list of channels loaded
|
||||||
sub onChannelsLoaded()
|
sub onChannelsLoaded()
|
||||||
gridData = createObject("roSGNode", "ContentNode")
|
gridData = createObject("roSGNode", "ContentNode")
|
||||||
|
@ -49,32 +61,36 @@ sub onChannelsLoaded()
|
||||||
counter = 0
|
counter = 0
|
||||||
channelIdList = ""
|
channelIdList = ""
|
||||||
|
|
||||||
for each item in m.LoadChannelsTask.channels
|
'if search returns channels
|
||||||
gridData.appendChild(item)
|
if m.LoadChannelsTask.channels.count() > 0
|
||||||
m.channelIndex[item.Id] = counter
|
for each item in m.LoadChannelsTask.channels
|
||||||
counter = counter + 1
|
gridData.appendChild(item)
|
||||||
channelIdList = channelIdList + item.Id + ","
|
m.channelIndex[item.Id] = counter
|
||||||
end for
|
counter = counter + 1
|
||||||
|
channelIdList = channelIdList + item.Id + ","
|
||||||
|
end for
|
||||||
|
m.scheduleGrid.content = gridData
|
||||||
|
|
||||||
m.scheduleGrid.content = gridData
|
m.LoadScheduleTask = createObject("roSGNode", "LoadScheduleTask")
|
||||||
|
m.LoadScheduleTask.observeField("schedule", "onScheduleLoaded")
|
||||||
|
|
||||||
m.LoadScheduleTask = createObject("roSGNode", "LoadScheduleTask")
|
m.LoadScheduleTask.startTime = m.gridStartDate.ToISOString()
|
||||||
m.LoadScheduleTask.observeField("schedule", "onScheduleLoaded")
|
m.LoadScheduleTask.endTime = m.gridEndDate.ToISOString()
|
||||||
|
m.LoadScheduleTask.channelIds = channelIdList
|
||||||
|
m.LoadScheduleTask.control = "RUN"
|
||||||
|
|
||||||
m.LoadScheduleTask.startTime = m.gridStartDate.ToISOString()
|
m.LoadProgramDetailsTask = createObject("roSGNode", "LoadProgramDetailsTask")
|
||||||
m.LoadScheduleTask.endTime = m.gridEndDate.ToISOString()
|
m.LoadProgramDetailsTask.observeField("programDetails", "onProgramDetailsLoaded")
|
||||||
m.LoadScheduleTask.channelIds = channelIdList
|
|
||||||
m.LoadScheduleTask.control = "RUN"
|
|
||||||
|
|
||||||
m.LoadProgramDetailsTask = createObject("roSGNode", "LoadProgramDetailsTask")
|
m.scheduleGrid.setFocus(true)
|
||||||
m.LoadProgramDetailsTask.observeField("programDetails", "onProgramDetailsLoaded")
|
if m.EPGLaunchCompleteSignaled = false
|
||||||
|
m.top.signalBeacon("EPGLaunchComplete") ' Required Roku Performance monitoring
|
||||||
|
m.EPGLaunchCompleteSignaled = true
|
||||||
|
end if
|
||||||
|
m.LoadChannelsTask.channels = []
|
||||||
|
|
||||||
m.scheduleGrid.setFocus(true)
|
|
||||||
if m.EPGLaunchCompleteSignaled = false
|
|
||||||
m.top.signalBeacon("EPGLaunchComplete") ' Required Roku Performance monitoring
|
|
||||||
m.EPGLaunchCompleteSignaled = true
|
|
||||||
end if
|
end if
|
||||||
m.LoadChannelsTask.channels = []
|
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
' When LoadScheduleTask completes (initial or more data) and we have a schedule to display
|
' When LoadScheduleTask completes (initial or more data) and we have a schedule to display
|
||||||
|
@ -102,6 +118,7 @@ sub onScheduleLoaded()
|
||||||
m.scheduleGrid.showLoadingDataFeedback = false
|
m.scheduleGrid.showLoadingDataFeedback = false
|
||||||
m.scheduleGrid.setFocus(true)
|
m.scheduleGrid.setFocus(true)
|
||||||
m.LoadScheduleTask.schedule = []
|
m.LoadScheduleTask.schedule = []
|
||||||
|
m.spinner.visible = false
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub onProgramFocused()
|
sub onProgramFocused()
|
||||||
|
@ -118,7 +135,9 @@ sub onProgramFocused()
|
||||||
m.top.focusedChannel = channel
|
m.top.focusedChannel = channel
|
||||||
|
|
||||||
' Exit if Channels not yet loaded
|
' Exit if Channels not yet loaded
|
||||||
|
|
||||||
if channel = invalid or channel.getChildCount() = 0
|
if channel = invalid or channel.getChildCount() = 0
|
||||||
|
|
||||||
m.detailsPane.programDetails = invalid
|
m.detailsPane.programDetails = invalid
|
||||||
return
|
return
|
||||||
end if
|
end if
|
||||||
|
@ -195,6 +214,22 @@ sub onWatchChannelSelected()
|
||||||
m.top.watchChannel = m.detailsPane.channel
|
m.top.watchChannel = m.detailsPane.channel
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
' As user scrolls grid, check if more data requries to be loaded
|
||||||
|
sub onGridScrolled()
|
||||||
|
|
||||||
|
' If we're within 12 hours of end of grid, load next 24hrs of data
|
||||||
|
if m.scheduleGrid.leftEdgeTargetTime + (12 * 60 * 60) > m.gridEndDate.AsSeconds()
|
||||||
|
|
||||||
|
' Ensure the task is not already (still) running,
|
||||||
|
if m.LoadScheduleTask.state <> "run"
|
||||||
|
m.LoadScheduleTask.startTime = m.gridEndDate.ToISOString()
|
||||||
|
m.gridEndDate.FromSeconds(m.gridEndDate.AsSeconds() + (24 * 60 * 60))
|
||||||
|
m.LoadScheduleTask.endTime = m.gridEndDate.ToISOString()
|
||||||
|
m.LoadScheduleTask.control = "RUN"
|
||||||
|
end if
|
||||||
|
end if
|
||||||
|
end sub
|
||||||
|
|
||||||
' Handle user selecting "Record Channel" from Program Details
|
' Handle user selecting "Record Channel" from Program Details
|
||||||
sub onRecordChannelSelected()
|
sub onRecordChannelSelected()
|
||||||
if m.detailsPane.recordSelectedChannel = false then return
|
if m.detailsPane.recordSelectedChannel = false then return
|
||||||
|
@ -242,27 +277,18 @@ sub onRecordOperationDone()
|
||||||
end if
|
end if
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
' As user scrolls grid, check if more data requries to be loaded
|
|
||||||
sub onGridScrolled()
|
|
||||||
|
|
||||||
' If we're within 12 hours of end of grid, load next 24hrs of data
|
|
||||||
if m.scheduleGrid.leftEdgeTargetTime + (12 * 60 * 60) > m.gridEndDate.AsSeconds()
|
|
||||||
|
|
||||||
' Ensure the task is not already (still) running,
|
|
||||||
if m.LoadScheduleTask.state <> "run"
|
|
||||||
m.LoadScheduleTask.startTime = m.gridEndDate.ToISOString()
|
|
||||||
m.gridEndDate.FromSeconds(m.gridEndDate.AsSeconds() + (24 * 60 * 60))
|
|
||||||
m.LoadScheduleTask.endTime = m.gridEndDate.ToISOString()
|
|
||||||
m.LoadScheduleTask.control = "RUN"
|
|
||||||
end if
|
|
||||||
end if
|
|
||||||
end sub
|
|
||||||
|
|
||||||
function onKeyEvent(key as string, press as boolean) as boolean
|
function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
if not press then return false
|
if not press then return false
|
||||||
|
detailsGrp = m.top.findNode("detailsPane")
|
||||||
|
gridGrp = m.top.findNode("scheduleGrid")
|
||||||
|
|
||||||
if key = "back" and m.detailsPane.isInFocusChain()
|
if key = "back" and detailsGrp.isInFocusChain()
|
||||||
focusProgramDetails(false)
|
focusProgramDetails(false)
|
||||||
|
detailsGrp.setFocus(false)
|
||||||
|
gridGrp.setFocus(true)
|
||||||
|
return true
|
||||||
|
else if key = "back"
|
||||||
|
m.global.sceneManager.callFunc("popScene")
|
||||||
return true
|
return true
|
||||||
end if
|
end if
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
programTitleFocusedColor="#ffffff" iconFocusedColor="#ff0000"
|
programTitleFocusedColor="#ffffff" iconFocusedColor="#ff0000"
|
||||||
showPastTimeScreen="true" pastTimeScreenBlendColor="#555555"
|
showPastTimeScreen="true" pastTimeScreenBlendColor="#555555"
|
||||||
/>
|
/>
|
||||||
|
<Spinner id="spinner" translation="[900, 450]" />
|
||||||
<Animation id="gridMoveAnimation" duration="1" repeat="false" easeFunction="outQuad" >
|
<Animation id="gridMoveAnimation" duration="1" repeat="false" easeFunction="outQuad" >
|
||||||
<Vector2DFieldInterpolator id="gridMoveAnimationPosition" key="[0.0, 0.5]" fieldToInterp="scheduleGrid.translation" />
|
<Vector2DFieldInterpolator id="gridMoveAnimationPosition" key="[0.0, 0.5]" fieldToInterp="scheduleGrid.translation" />
|
||||||
</Animation>
|
</Animation>
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
<field id="watchChannel" type="node" alwaysNotify="false" />
|
<field id="watchChannel" type="node" alwaysNotify="false" />
|
||||||
<field id="focusedChannel" type="node" alwaysNotify="false" />
|
<field id="focusedChannel" type="node" alwaysNotify="false" />
|
||||||
<field id="filter" type="string" value="All" onChange="channelFilterSet" />
|
<field id="filter" type="string" value="All" onChange="channelFilterSet" />
|
||||||
|
<field id="searchTerm" type="string" value="" onChange="channelsearchTermSet" />
|
||||||
</interface>
|
</interface>
|
||||||
<script type="text/brightscript" uri="schedule.brs" />
|
<script type="text/brightscript" uri="schedule.brs" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -46,8 +46,9 @@ sub itemContentChanged()
|
||||||
m.top.findNode("moviePoster").uri = m.top.itemContent.posterURL
|
m.top.findNode("moviePoster").uri = m.top.itemContent.posterURL
|
||||||
|
|
||||||
' Set default video source
|
' Set default video source
|
||||||
m.top.selectedVideoStreamId = itemData.MediaSources[0].id
|
if itemData.MediaSources <> invalid
|
||||||
|
m.top.selectedVideoStreamId = itemData.MediaSources[0].id
|
||||||
|
end if
|
||||||
' Find first Audio Stream and set that as default
|
' Find first Audio Stream and set that as default
|
||||||
SetDefaultAudioTrack(itemData)
|
SetDefaultAudioTrack(itemData)
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ sub init()
|
||||||
m.loopMode = ""
|
m.loopMode = ""
|
||||||
m.shuffleEvent = ""
|
m.shuffleEvent = ""
|
||||||
m.buttonCount = m.buttons.getChildCount()
|
m.buttonCount = m.buttons.getChildCount()
|
||||||
|
m.playReported = false
|
||||||
|
|
||||||
m.screenSaverTimeout = 300
|
m.screenSaverTimeout = 300
|
||||||
|
|
||||||
|
@ -198,6 +199,24 @@ sub endScreenSaver()
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub audioStateChanged()
|
sub audioStateChanged()
|
||||||
|
|
||||||
|
if m.top.audio.state = "playing"
|
||||||
|
if m.playReported
|
||||||
|
ReportPlayback()
|
||||||
|
else
|
||||||
|
ReportPlayback("start")
|
||||||
|
m.playReported = true
|
||||||
|
end if
|
||||||
|
else if m.top.audio.state = "paused"
|
||||||
|
ReportPlayback()
|
||||||
|
else if m.top.audio.state = "stopped"
|
||||||
|
ReportPlayback("stop")
|
||||||
|
m.playReported = false
|
||||||
|
else if m.top.audio.state = "finished"
|
||||||
|
ReportPlayback("stop")
|
||||||
|
m.playReported = false
|
||||||
|
end if
|
||||||
|
|
||||||
' Song Finished, attempt to move to next song
|
' Song Finished, attempt to move to next song
|
||||||
if m.top.audio.state = "finished"
|
if m.top.audio.state = "finished"
|
||||||
if m.loopMode = "one"
|
if m.loopMode = "one"
|
||||||
|
@ -240,6 +259,10 @@ function playAction() as boolean
|
||||||
end function
|
end function
|
||||||
|
|
||||||
function previousClicked() as boolean
|
function previousClicked() as boolean
|
||||||
|
if m.top.audio.state = "playing"
|
||||||
|
m.top.audio.control = "stop"
|
||||||
|
end if
|
||||||
|
|
||||||
if m.currentSongIndex > 0
|
if m.currentSongIndex > 0
|
||||||
m.currentSongIndex--
|
m.currentSongIndex--
|
||||||
pageContentChanged()
|
pageContentChanged()
|
||||||
|
@ -331,6 +354,10 @@ function shuffleClicked() as boolean
|
||||||
end function
|
end function
|
||||||
|
|
||||||
sub LoadNextSong()
|
sub LoadNextSong()
|
||||||
|
if m.top.audio.state = "playing"
|
||||||
|
m.top.audio.control = "stop"
|
||||||
|
end if
|
||||||
|
|
||||||
' Reset playPosition bar without animation
|
' Reset playPosition bar without animation
|
||||||
m.playPosition.width = 0
|
m.playPosition.width = 0
|
||||||
m.currentSongIndex++
|
m.currentSongIndex++
|
||||||
|
@ -362,7 +389,6 @@ sub onAudioStreamLoaded()
|
||||||
m.LoadAudioStreamTask.unobserveField("content")
|
m.LoadAudioStreamTask.unobserveField("content")
|
||||||
if data <> invalid and data.count() > 0
|
if data <> invalid and data.count() > 0
|
||||||
m.top.audio.content = data
|
m.top.audio.content = data
|
||||||
m.top.audio.control = "stop"
|
|
||||||
m.top.audio.control = "none"
|
m.top.audio.control = "none"
|
||||||
m.top.audio.control = "play"
|
m.top.audio.control = "play"
|
||||||
end if
|
end if
|
||||||
|
@ -382,7 +408,7 @@ sub onMetaDataLoaded()
|
||||||
if data <> invalid and data.count() > 0
|
if data <> invalid and data.count() > 0
|
||||||
|
|
||||||
' Use metadata to load backdrop image
|
' Use metadata to load backdrop image
|
||||||
if isvalid(data?.json?.ArtistItems?[0].id)
|
if isvalid(data?.json?.ArtistItems?[0]?.id)
|
||||||
m.LoadBackdropImageTask.itemId = data.json.ArtistItems[0].id
|
m.LoadBackdropImageTask.itemId = data.json.ArtistItems[0].id
|
||||||
m.LoadBackdropImageTask.observeField("content", "onBackdropImageLoaded")
|
m.LoadBackdropImageTask.observeField("content", "onBackdropImageLoaded")
|
||||||
m.LoadBackdropImageTask.control = "RUN"
|
m.LoadBackdropImageTask.control = "RUN"
|
||||||
|
@ -515,3 +541,21 @@ sub OnScreenHidden()
|
||||||
WriteAsciiFile("tmp:/scene.temp", "")
|
WriteAsciiFile("tmp:/scene.temp", "")
|
||||||
MoveFile("tmp:/scene.temp", "tmp:/scene")
|
MoveFile("tmp:/scene.temp", "tmp:/scene")
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
' Report playback to server
|
||||||
|
sub ReportPlayback(state = "update" as string)
|
||||||
|
|
||||||
|
if m.top.audio.position = invalid then return
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"ItemId": m.top.pageContent[m.currentSongIndex],
|
||||||
|
"PlaySessionId": m.top.audio.content.id,
|
||||||
|
"PositionTicks": int(m.top.audio.position) * 10000000&, 'Ensure a LongInteger is used
|
||||||
|
"IsPaused": (m.top.audio.state = "paused")
|
||||||
|
}
|
||||||
|
|
||||||
|
' Report playstate via worker task
|
||||||
|
playstateTask = m.global.playstateTask
|
||||||
|
playstateTask.setFields({ status: state, params: params })
|
||||||
|
playstateTask.control = "RUN"
|
||||||
|
end sub
|
||||||
|
|
|
@ -1,3 +1,60 @@
|
||||||
sub init()
|
sub init()
|
||||||
m.top.optionsAvailable = false
|
m.top.optionsAvailable = false
|
||||||
|
m.searchSpinner = m.top.findnode("searchSpinner")
|
||||||
|
m.searchSelect = m.top.findnode("searchSelect")
|
||||||
|
m.searchTask = CreateObject("roSGNode", "SearchTask")
|
||||||
|
|
||||||
|
'set label text
|
||||||
|
m.searchHelpText = m.top.findNode("SearchHelpText")
|
||||||
|
m.searchHelpText.text = tr("You can search for Titles, People, Live TV Channels and more")
|
||||||
|
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
sub searchMedias()
|
||||||
|
query = m.top.searchAlpha
|
||||||
|
'if user deletes the search string hide the spinner
|
||||||
|
if query.len() = 0
|
||||||
|
m.searchSpinner.visible = false
|
||||||
|
end if
|
||||||
|
'if search task is running and user selectes another letter stop the search and load the next letter
|
||||||
|
m.searchTask.control = "stop"
|
||||||
|
if query <> invalid and query <> ""
|
||||||
|
m.searchSpinner.visible = true
|
||||||
|
end if
|
||||||
|
m.searchTask.observeField("results", "loadResults")
|
||||||
|
m.searchTask.query = query
|
||||||
|
m.top.overhangTitle = tr("Search") + ": " + query
|
||||||
|
m.searchTask.control = "RUN"
|
||||||
|
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub loadResults()
|
||||||
|
m.searchTask.unobserveField("results")
|
||||||
|
|
||||||
|
m.searchSpinner.visible = false
|
||||||
|
m.searchSelect.itemdata = m.searchTask.results
|
||||||
|
m.searchSelect.query = m.top.SearchAlpha
|
||||||
|
m.searchHelpText.visible = false
|
||||||
|
m.searchAlphabox = m.top.findnode("searchResults")
|
||||||
|
m.searchAlphabox.translation = "[470, 85]"
|
||||||
|
end sub
|
||||||
|
|
||||||
|
function onKeyEvent(key as string, press as boolean) as boolean
|
||||||
|
|
||||||
|
m.searchAlphabox = m.top.findNode("search_Key")
|
||||||
|
if m.searchAlphabox.textEditBox.hasFocus()
|
||||||
|
m.searchAlphabox.textEditBox.translation = "[0, -150]"
|
||||||
|
else
|
||||||
|
m.searchAlphabox.textEditBox.translation = "[0, 0]"
|
||||||
|
end if
|
||||||
|
|
||||||
|
if key = "left" and m.searchSelect.isinFocusChain() and (m.searchSelect.currFocusColumn = -1 or m.searchSelect.currFocusColumn = 0)
|
||||||
|
m.searchAlphabox.setFocus(true)
|
||||||
|
return true
|
||||||
|
else if key = "right"
|
||||||
|
m.searchSelect.setFocus(true)
|
||||||
|
return true
|
||||||
|
end if
|
||||||
|
return false
|
||||||
|
|
||||||
|
end function
|
||||||
|
|
|
@ -1,13 +1,28 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<component name="SearchResults" extends="JFGroup">
|
<component name="searchResults" extends="JFGroup">
|
||||||
<children>
|
<children>
|
||||||
<SearchBox id="SearchBox" visible="true" translation="[960, 145]" />
|
<Rectangle width="1920" height="1080" color="#000000" opacity="0.75" />
|
||||||
<SearchRow id="SearchSelect" visible="false" />
|
<LayoutGroup layoutDirection="horiz" id="SearchAlphabox" translation="[70, 120]">
|
||||||
|
<SearchBox id="SearchBox" visible="true" focusable="true"/>
|
||||||
|
</LayoutGroup>
|
||||||
|
<LayoutGroup layoutDirection="vert" id="searchResults" translation="[470, 150]" >
|
||||||
|
<Label id = "SearchHelpText" text=""/>
|
||||||
|
<SearchRow id="searchSelect" visible="true" focusable="true"/>
|
||||||
|
</LayoutGroup>
|
||||||
<OptionsSlider id="options" />
|
<OptionsSlider id="options" />
|
||||||
|
<Spinner id = "searchSpinner" visible="false" translation="[1050, 500]"/>
|
||||||
</children>
|
</children>
|
||||||
<interface>
|
<interface>
|
||||||
<field id="query" type="string" alwaysNotify="true" />
|
<field id="query" type="string" alwaysNotify="true" />
|
||||||
|
<field id="selectedItem" type="node" alwaysNotify="true" />
|
||||||
|
<field id="quickPlayNode" type="node" alwaysNotify="true" />
|
||||||
|
<field id="imageDisplayMode" type="string" value="scaleToZoom" />
|
||||||
|
<field id="searchAlpha" type="string" alias="SearchBox.search_values" alwaysNotify="true" onChange="searchMedias" />
|
||||||
</interface>
|
</interface>
|
||||||
<script type="text/brightscript" uri="SearchResults.brs" />
|
<script type="text/brightscript" uri="SearchResults.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/Items.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/deviceCapabilities.brs" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -11,27 +11,28 @@ sub init()
|
||||||
' TODO - Define a failed to load image background
|
' TODO - Define a failed to load image background
|
||||||
' m.top.failedBitmapURI
|
' m.top.failedBitmapURI
|
||||||
|
|
||||||
m.top.setFocus(true)
|
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
sub updateSize()
|
sub updateSize()
|
||||||
' In search results, rowSize only dictates how many are on screen at once
|
' In search results, rowSize only dictates how many are on screen at once
|
||||||
m.top.rowSize = 5
|
m.top.rowSize = 3
|
||||||
|
|
||||||
dimensions = m.top.getScene().currentDesignResolution
|
dimensions = m.top.getScene().currentDesignResolution
|
||||||
|
|
||||||
border = 75
|
border = 50
|
||||||
m.top.translation = [border, border + 115]
|
m.top.translation = [border, border + 115]
|
||||||
|
|
||||||
textHeight = 80
|
textHeight = 80
|
||||||
itemWidth = (dimensions["width"] - border * 2) / m.top.rowSize
|
itemWidth = (dimensions["width"] - border) / 6
|
||||||
itemHeight = itemWidth * 1.5 + textHeight
|
itemHeight = itemWidth + (textHeight / 2.3)
|
||||||
|
|
||||||
m.top.itemSize = [dimensions["width"] - border * 2, itemHeight]
|
m.top.itemSize = [1350, itemHeight] ' this is used for setting the row size
|
||||||
m.top.itemSpacing = [0, 50]
|
m.top.itemSpacing = [0, 105]
|
||||||
|
|
||||||
m.top.rowItemSize = [itemWidth, itemHeight]
|
m.top.rowItemSize = [itemWidth, itemHeight]
|
||||||
m.top.rowItemSpacing = [0, 0]
|
m.top.rowItemSpacing = [0, 0]
|
||||||
|
m.top.numRows = 2
|
||||||
|
m.top.translation = "[12,18]"
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
function getData()
|
function getData()
|
||||||
|
@ -45,16 +46,17 @@ function getData()
|
||||||
' todo - Or get the old data? I can't remember...
|
' todo - Or get the old data? I can't remember...
|
||||||
data = CreateObject("roSGNode", "ContentNode")
|
data = CreateObject("roSGNode", "ContentNode")
|
||||||
' Do this to keep the ordering, AssociateArrays have no order
|
' Do this to keep the ordering, AssociateArrays have no order
|
||||||
type_array = ["Movie", "Series", "TvChannel", "Episode", "AlbumArtist", "Album", "Audio", "Person"]
|
type_array = ["Movie", "Series", "TvChannel", "Episode", "MusicArtist", "MusicAlbum", "Audio", "Person", "PlaylistsFolder"]
|
||||||
content_types = {
|
content_types = {
|
||||||
"TvChannel": { "label": "Channels", "count": 0 },
|
"TvChannel": { "label": "Channels", "count": 0 },
|
||||||
"Movie": { "label": "Movies", "count": 0 },
|
"Movie": { "label": "Movies", "count": 0 },
|
||||||
"Series": { "label": "Shows", "count": 0 },
|
"Series": { "label": "Shows", "count": 0 },
|
||||||
"Episode": { "label": "Episodes", "count": 0 },
|
"Episode": { "label": "Episodes", "count": 0 },
|
||||||
"AlbumArtist": { "label": "Artists", "count": 0 },
|
"MusicArtist": { "label": "Artists", "count": 0 },
|
||||||
"Album": { "label": "Albums", "count": 0 },
|
"MusicAlbum": { "label": "Albums", "count": 0 },
|
||||||
"Audio": { "label": "Songs", "count": 0 },
|
"Audio": { "label": "Songs", "count": 0 },
|
||||||
"Person": { "label": "People", "count": 0 }
|
"Person": { "label": "People", "count": 0 },
|
||||||
|
"PlaylistsFolder": { "label": "Playlist", "count": 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
for each item in itemData.searchHints
|
for each item in itemData.searchHints
|
||||||
|
@ -84,3 +86,4 @@ sub addRow(data, title, type_filter)
|
||||||
end if
|
end if
|
||||||
end for
|
end for
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
<field id="rowSize" type="int" />
|
<field id="rowSize" type="int" />
|
||||||
<field id="itemData" type="assocarray" onChange="getData" />
|
<field id="itemData" type="assocarray" onChange="getData" />
|
||||||
<field id="query" type="string" />
|
<field id="query" type="string" />
|
||||||
<field id="itemSelected" type="int" />
|
<field id="itemSelected" type="node" alwaysNotify="true" />
|
||||||
</interface>
|
</interface>
|
||||||
<script type="text/brightscript" uri="SearchRow.brs" />
|
<script type="text/brightscript" uri="SearchRow.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/Items.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/deviceCapabilities.brs" />
|
||||||
</component>
|
</component>
|
||||||
|
|
9
components/search/SearchTask.brs
Normal file
9
components/search/SearchTask.brs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
sub init()
|
||||||
|
m.top.functionName = "search"
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub search()
|
||||||
|
if m.top.query <> invalid and m.top.query <> ""
|
||||||
|
m.top.results = searchMedia(m.top.query)
|
||||||
|
end if
|
||||||
|
end sub
|
14
components/search/SearchTask.xml
Normal file
14
components/search/SearchTask.xml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
|
||||||
|
<component name="SearchTask" extends="Task">
|
||||||
|
<interface>
|
||||||
|
<field id="query" type="string" />
|
||||||
|
<field id="results" type="assocarray" />
|
||||||
|
</interface>
|
||||||
|
<script type="text/brightscript" uri="SearchTask.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/Items.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/baserequest.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/api/Image.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/deviceCapabilities.brs" />
|
||||||
|
</component>
|
|
@ -12,6 +12,9 @@ sub init()
|
||||||
m.path = m.top.findNode("path")
|
m.path = m.top.findNode("path")
|
||||||
|
|
||||||
m.boolSetting = m.top.findNode("boolSetting")
|
m.boolSetting = m.top.findNode("boolSetting")
|
||||||
|
m.integerSetting = m.top.findNode("integerSetting")
|
||||||
|
m.integerSetting.observeField("submit", "onKeyGridSubmit")
|
||||||
|
m.integerSetting.observeField("escape", "onKeyGridEscape")
|
||||||
|
|
||||||
m.settingsMenu.setFocus(true)
|
m.settingsMenu.setFocus(true)
|
||||||
m.settingsMenu.observeField("itemFocused", "settingFocused")
|
m.settingsMenu.observeField("itemFocused", "settingFocused")
|
||||||
|
@ -24,6 +27,17 @@ sub init()
|
||||||
LoadMenu({ children: m.configTree })
|
LoadMenu({ children: m.configTree })
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
sub onKeyGridSubmit()
|
||||||
|
selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]
|
||||||
|
set_user_setting(selectedSetting.settingName, m.integerSetting.text)
|
||||||
|
m.settingsMenu.setFocus(true)
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub onKeyGridEscape()
|
||||||
|
if m.integerSetting.escape = "left" or m.integerSetting.escape = "back"
|
||||||
|
m.settingsMenu.setFocus(true)
|
||||||
|
end if
|
||||||
|
end sub
|
||||||
|
|
||||||
sub LoadMenu(configSection)
|
sub LoadMenu(configSection)
|
||||||
|
|
||||||
|
@ -58,8 +72,6 @@ sub LoadMenu(configSection)
|
||||||
end for
|
end for
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sub settingFocused()
|
sub settingFocused()
|
||||||
|
|
||||||
selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]
|
selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]
|
||||||
|
@ -68,6 +80,7 @@ sub settingFocused()
|
||||||
|
|
||||||
' Hide Settings
|
' Hide Settings
|
||||||
m.boolSetting.visible = false
|
m.boolSetting.visible = false
|
||||||
|
m.integerSetting.visible = false
|
||||||
|
|
||||||
if selectedSetting.type = invalid
|
if selectedSetting.type = invalid
|
||||||
return
|
return
|
||||||
|
@ -80,6 +93,12 @@ sub settingFocused()
|
||||||
else
|
else
|
||||||
m.boolSetting.checkedItem = 0
|
m.boolSetting.checkedItem = 0
|
||||||
end if
|
end if
|
||||||
|
else if selectedSetting.type = "integer"
|
||||||
|
integerValue = get_user_setting(selectedSetting.settingName, selectedSetting.default)
|
||||||
|
if isValid(integerValue)
|
||||||
|
m.integerSetting.text = integerValue
|
||||||
|
end if
|
||||||
|
m.integerSetting.visible = true
|
||||||
else
|
else
|
||||||
print "Unknown setting type " + selectedSetting.type
|
print "Unknown setting type " + selectedSetting.type
|
||||||
end if
|
end if
|
||||||
|
@ -91,11 +110,13 @@ sub settingSelected()
|
||||||
|
|
||||||
selectedItem = m.userLocation.peek().children[m.settingsMenu.itemFocused]
|
selectedItem = m.userLocation.peek().children[m.settingsMenu.itemFocused]
|
||||||
|
|
||||||
|
|
||||||
if selectedItem.type <> invalid ' Show setting
|
if selectedItem.type <> invalid ' Show setting
|
||||||
if selectedItem.type = "bool"
|
if selectedItem.type = "bool"
|
||||||
m.boolSetting.setFocus(true)
|
m.boolSetting.setFocus(true)
|
||||||
end if
|
end if
|
||||||
|
if selectedItem.type = "integer"
|
||||||
|
m.integerSetting.setFocus(true)
|
||||||
|
end if
|
||||||
else if selectedItem.children <> invalid and selectedItem.children.Count() > 0 ' Show sub menu
|
else if selectedItem.children <> invalid and selectedItem.children.Count() > 0 ' Show sub menu
|
||||||
LoadMenu(selectedItem)
|
LoadMenu(selectedItem)
|
||||||
m.settingsMenu.setFocus(true)
|
m.settingsMenu.setFocus(true)
|
||||||
|
|
|
@ -2,50 +2,39 @@
|
||||||
<component name="Settings" extends="JFGroup">
|
<component name="Settings" extends="JFGroup">
|
||||||
<children>
|
<children>
|
||||||
|
|
||||||
<Label id="path" translation = "[95,175]" font="font:SmallestBoldSystemFont" />
|
<Label id="path" translation = "[95,175]" font="font:SmallestBoldSystemFont" />
|
||||||
|
|
||||||
<LabelList
|
<LabelList
|
||||||
translation = "[120,250]"
|
translation = "[120,250]"
|
||||||
id = "settingsMenu"
|
id = "settingsMenu"
|
||||||
itemSize = "[440,48]"
|
itemSize = "[440,48]"
|
||||||
vertFocusAnimationStyle = "floatingFocus"
|
vertFocusAnimationStyle = "floatingFocus"
|
||||||
focusBitmapBlendColor = "#006fab"
|
focusBitmapBlendColor = "#006fab"
|
||||||
focusedColor = "#ffffff"
|
focusedColor = "#ffffff"
|
||||||
itemSpacing = "[0,5]"
|
itemSpacing = "[0,5]" />
|
||||||
/>
|
|
||||||
|
|
||||||
<Poster
|
<Poster
|
||||||
translation = "[710,250]"
|
translation = "[710,250]" id="testRectangle" width="880" height="700" uri="pkg:/images/white.9.png"
|
||||||
id="testRectangle"
|
blendColor = "#3f3f3f" />
|
||||||
width="880"
|
|
||||||
height="700"
|
|
||||||
uri="pkg:/images/white.9.png"
|
|
||||||
blendColor = "#3f3f3f"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<LayoutGroup
|
<LayoutGroup translation = "[1150,275]" id="settingDetail" vertAlignment="top" horizAlignment="center" itemSpacings="[50]">
|
||||||
translation = "[1150,275]"
|
|
||||||
id="settingDetail"
|
|
||||||
vertAlignment="top"
|
|
||||||
horizAlignment="center"
|
|
||||||
itemSpacings="[50]"
|
|
||||||
>
|
|
||||||
|
|
||||||
<ScrollingLabel font="font:LargeSystemFont" id="settingTitle" maxWidth="750" />
|
<ScrollingLabel font="font:LargeSystemFont" id="settingTitle" maxWidth="750" />
|
||||||
|
|
||||||
<Label id="settingDesc" width="750" wrap = "true" />
|
<Label id="settingDesc" width="750" wrap = "true" />
|
||||||
|
|
||||||
<RadioButtonList id="boolSetting" vertFocusAnimationStyle="floatingFocus">
|
<RadioButtonList id="boolSetting" vertFocusAnimationStyle="floatingFocus">
|
||||||
<ContentNode role="content">
|
<ContentNode role="content">
|
||||||
<ContentNode title="Disabled" />
|
<ContentNode title="Disabled" />
|
||||||
<ContentNode title="Enabled" />
|
<ContentNode title="Enabled" />
|
||||||
</ContentNode>
|
</ContentNode>
|
||||||
</RadioButtonList>
|
</RadioButtonList>
|
||||||
|
</LayoutGroup>
|
||||||
</LayoutGroup>
|
|
||||||
|
|
||||||
|
<intkeyboard_integerKeyboard translation="[900, 520]" id="integerSetting" maxLength="3" domain="numeric" visible="false" />
|
||||||
|
|
||||||
</children>
|
</children>
|
||||||
<script type="text/brightscript" uri="settings.brs" />
|
<script type="text/brightscript" uri="settings.brs" />
|
||||||
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
<script type="text/brightscript" uri="pkg:/source/utils/config.brs" />
|
||||||
|
<script type="text/brightscript" uri="pkg:/source/utils/misc.brs" />
|
||||||
</component>
|
</component>
|
BIN
images/icons/mic_icon.png
Normal file
BIN
images/icons/mic_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
|
@ -3302,7 +3302,7 @@
|
||||||
<translation>Speciální funkce</translation>
|
<translation>Speciální funkce</translation>
|
||||||
<message>
|
<message>
|
||||||
<source>Press 'OK' to Close</source>
|
<source>Press 'OK' to Close</source>
|
||||||
<translation>Press 'OK' to Close</translation>
|
<translation>Pro zavření stiskni 'OK'</translation>
|
||||||
</message>
|
</message>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -3402,5 +3402,74 @@
|
||||||
<source>Save Credentials?</source>
|
<source>Save Credentials?</source>
|
||||||
<translation>Uložit přihlašovací údaje?</translation>
|
<translation>Uložit přihlašovací údaje?</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<comment>Title of Tab for options to filter library content</comment>
|
||||||
|
<source>TAB_FILTER</source>
|
||||||
|
<translation>Filtr</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<comment>Title of Tab for options to sort library content</comment>
|
||||||
|
<source>TAB_SORT</source>
|
||||||
|
<translation>Třídit</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<comment>Title of Tab for switching "views" when looking at a library</comment>
|
||||||
|
<source>TAB_VIEW</source>
|
||||||
|
<translation>Pohled</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>RUNTIME</source>
|
||||||
|
<translation>Délka</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>RELEASE_DATE</source>
|
||||||
|
<translation>Datum vydání</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>PLAY_COUNT</source>
|
||||||
|
<translation>Počet přehrání</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>OFFICIAL_RATING</source>
|
||||||
|
<translation>Rodičovské hodnocení</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>DATE_PLAYED</source>
|
||||||
|
<translation>Datum přehrání</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>DATE_ADDED</source>
|
||||||
|
<translation>Datum přidání</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>CRITIC_RATING</source>
|
||||||
|
<translation>Honocení kritiků</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>IMDB_RATING</source>
|
||||||
|
<translation>Hodnocení IMDb</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<comment>Name or Title field of media item</comment>
|
||||||
|
<source>TITLE</source>
|
||||||
|
<translation>Název</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<comment>Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)</comment>
|
||||||
|
<source>NO_ITEMS</source>
|
||||||
|
<translation>Tato %1 neobsahuje žádné položky</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>On Now</source>
|
||||||
|
<translation>Nyní</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Delete Saved</source>
|
||||||
|
<translation>Smazat uložené</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Save Credentials?</source>
|
||||||
|
<translation>Uložit přihlašovací údaje?</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
|
@ -476,13 +476,13 @@
|
||||||
<extracomment>Title for Playback section in user setting screen.</extracomment>
|
<extracomment>Title for Playback section in user setting screen.</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>MPEG 2 Support</source>
|
<source>MPEG-2 Support</source>
|
||||||
<translation>MPEG 2 Support</translation>
|
<translation>MPEG-2 Support</translation>
|
||||||
<extracomment>Settings Menu - Title for option</extracomment>
|
<extracomment>Settings Menu - Title for option</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Support direct play of MPEG 2 content (e.g. Live TV). This will prevent transcoding of MPEG 2 content, but uses significantly more bandwidth</source>
|
<source>Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.</source>
|
||||||
<translation>Support direct play of MPEG 2 content (e.g. Live TV). This will prevent transcoding of MPEG 2 content, but uses significantly more bandwidth</translation>
|
<translation>Support Direct Play of MPEG-2 content (e.g., Live TV). This will prevent transcoding of MPEG-2 content, but uses significantly more bandwidth.</translation>
|
||||||
<extracomment>Settings Menu - Description for option</extracomment>
|
<extracomment>Settings Menu - Description for option</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -504,8 +504,8 @@
|
||||||
<extracomment>UI -> Media Grid section in user setting screen.</extracomment>
|
<extracomment>UI -> Media Grid section in user setting screen.</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Media Grid Options</source>
|
<source>Media Grid options.</source>
|
||||||
<translation>Media Grid Options</translation>
|
<translation>Media Grid options.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Item Titles</source>
|
<source>Item Titles</source>
|
||||||
|
@ -513,8 +513,8 @@
|
||||||
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Always show the titles below the poster images. (If disabled, title will be shown under hilighted item only)</source>
|
<source>Always show the titles below the poster images. (If disabled, the title will be shown under the highlighted item only).</source>
|
||||||
<translation>Always show the titles below the poster images. (If disabled, title will be shown under hilighted item only)</translation>
|
<translation>Always show the titles below the poster images. (If disabled, the title will be shown under the highlighted item only).</translation>
|
||||||
<extracomment>Description for option in Setting Screen</extracomment>
|
<extracomment>Description for option in Setting Screen</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -523,8 +523,8 @@
|
||||||
<extracomment>UI -> Media Grid -> Item Count in user setting screen.</extracomment>
|
<extracomment>UI -> Media Grid -> Item Count in user setting screen.</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Show item count in the library, and index of selected item.</source>
|
<source>Show item count in the library and index of selected item.</source>
|
||||||
<translation>Show item count in the library, and index of selected item.</translation>
|
<translation>Show item count in the library and index of selected item.</translation>
|
||||||
<extracomment>Description for option in Setting Screen</extracomment>
|
<extracomment>Description for option in Setting Screen</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -552,6 +552,21 @@
|
||||||
<translation>Go to episode</translation>
|
<translation>Go to episode</translation>
|
||||||
<extracomment>Continue Watching Popup Menu - Navigate to the Episode Detail Page</extracomment>
|
<extracomment>Continue Watching Popup Menu - Navigate to the Episode Detail Page</extracomment>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Use voice remote to search</source>
|
||||||
|
<translation>Use voice remote to search</translation>
|
||||||
|
<extracomment>Help text in search voice text box</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Search now</source>
|
||||||
|
<translation>Search now</translation>
|
||||||
|
<extracomment>Help text in search Box</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>You can search for Titles, People, Live TV Channels and more</source>
|
||||||
|
<translation>You can search for Titles, People, Live TV Channels and more</translation>
|
||||||
|
<extracomment>Help text in search results</extracomment>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>%1 of %2</source>
|
<source>%1 of %2</source>
|
||||||
<translation>%1 of %2</translation>
|
<translation>%1 of %2</translation>
|
||||||
|
@ -591,18 +606,18 @@
|
||||||
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
<extracomment>UI -> Media Grid -> Item Title in user setting screen.</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Use the replay button to slowly animate to the first item in the folder. (If disabled, The folder will reset to the first item immediately)</source>
|
<source>Use the replay button to slowly animate to the first item in the folder. (If disabled, the folder will reset to the first item immediately).</source>
|
||||||
<translation>Use the replay button to slowly animate to the first item in the folder. (If disabled, The folder will reset to the first item immediately)</translation>
|
<translation>Use the replay button to slowly animate to the first item in the folder. (If disabled, the folder will reset to the first item immediately).</translation>
|
||||||
<extracomment>Description for option in Setting Screen</extracomment>
|
<extracomment>Description for option in Setting Screen</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Detail Page</source>
|
<source>Details Page</source>
|
||||||
<translation>Detail Page</translation>
|
<translation>Details Page</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Options for details pages.</source>
|
<source>Options for Details pages.</source>
|
||||||
<translation>Options for details pages.</translation>
|
<translation>Options for Details pages.</translation>
|
||||||
<extracomment>Description for Detail Page user settings.</extracomment>
|
<extracomment>Description for Details page user settings.</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Hide Taglines</source>
|
<source>Hide Taglines</source>
|
||||||
|
@ -624,8 +639,8 @@
|
||||||
<extracomment>Option Title in user setting screen</extracomment>
|
<extracomment>Option Title in user setting screen</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>If enabled, images for unwatched episodes will be blurred.</source>
|
<source>If enabled, images of unwatched episodes will be blurred.</source>
|
||||||
<translation>If enabled, images for unwatched episodes will be blurred.</translation>
|
<translation>If enabled, images of unwatched episodes will be blurred.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Screensaver</source>
|
<source>Screensaver</source>
|
||||||
|
@ -642,8 +657,8 @@
|
||||||
<extracomment>Option Title in user setting screen</extracomment>
|
<extracomment>Option Title in user setting screen</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Use generated splashscreen image as Jellyfin's screensaver background.</source>
|
<source>Use generated splashscreen image as Jellyfin's screensaver background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||||
<translation>Use generated splashscreen image as Jellyfin's screensaver background.</translation>
|
<translation>Use generated splashscreen image as Jellyfin's screensaver background. Jellyfin will need to be closed and reopened for change to take effect.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Design Elements</source>
|
<source>Design Elements</source>
|
||||||
|
@ -660,18 +675,18 @@
|
||||||
<extracomment>Option Title in user setting screen</extracomment>
|
<extracomment>Option Title in user setting screen</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Use generated splashscreen image as Jellyfin home background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
<source>Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.</source>
|
||||||
<translation>Use generated splashscreen image as Jellyfin home background. Jellyfin will need to be closed and reopened for change to take effect.</translation>
|
<translation>Use generated splashscreen image as Jellyfin's home background. Jellyfin will need to be closed and reopened for change to take effect.</translation>
|
||||||
<extracomment>Description for option in Setting Screen</extracomment>
|
<extracomment>Description for option in Setting Screen</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Cinema mode</source>
|
<source>Cinema Mode</source>
|
||||||
<translation>Cinema mode</translation>
|
<translation>Cinema Mode</translation>
|
||||||
<extracomment>Settings Menu - Title for option</extracomment>
|
<extracomment>Settings Menu - Title for option</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Cinema mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.</source>
|
<source>Cinema Mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.</source>
|
||||||
<translation>Cinema mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.</translation>
|
<translation>Cinema Mode brings the theater experience straight to your living room with the ability to play custom intros before the main feature.</translation>
|
||||||
<extracomment>Settings Menu - Description for option</extracomment>
|
<extracomment>Settings Menu - Description for option</extracomment>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -692,6 +707,33 @@
|
||||||
<source>Play Trailer</source>
|
<source>Play Trailer</source>
|
||||||
<translation>Play Trailer</translation>
|
<translation>Play Trailer</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Settings relating to playback and supported codec and media types.</source>
|
||||||
|
<translation>Settings relating to playback and supported codec and media types.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Settings relating to how the application looks.</source>
|
||||||
|
<translation>Settings relating to how the application looks.</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Home Page</source>
|
||||||
|
<translation>Home Page</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Options for Home Page.</source>
|
||||||
|
<translation>Options for Home Page.</translation>
|
||||||
|
<extracomment>Description for Home Page user settings.</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Max Days Next Up</source>
|
||||||
|
<translation>Max Days Next Up</translation>
|
||||||
|
<extracomment>Option Title in user setting screen</extracomment>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</source>
|
||||||
|
<translation>Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.</translation>
|
||||||
|
<extracomment>Settings Menu - Description for option</extracomment>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Playback Information</source>
|
<source>Playback Information</source>
|
||||||
<translation>Playback Information</translation>
|
<translation>Playback Information</translation>
|
||||||
|
|
|
@ -2692,5 +2692,13 @@
|
||||||
<source>IMDB_RATING</source>
|
<source>IMDB_RATING</source>
|
||||||
<translation>Classement IMDb</translation>
|
<translation>Classement IMDb</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Delete Saved</source>
|
||||||
|
<translation>Supprimer les informations enregistrées</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Save Credentials?</source>
|
||||||
|
<translation>Enregistrer les identifiants ?</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
|
@ -6325,5 +6325,13 @@ elemeket</translation>
|
||||||
<source>Save Credentials?</source>
|
<source>Save Credentials?</source>
|
||||||
<translation>Mented a hitelesítő adatokat?</translation>
|
<translation>Mented a hitelesítő adatokat?</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Delete Saved</source>
|
||||||
|
<translation>Mentettek Törlése</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Save Credentials?</source>
|
||||||
|
<translation>Mented a hitelesítő adatokat?</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -12,7 +12,8 @@
|
||||||
"api": "npm:jellyfin-api-bs-client@^1.0.5",
|
"api": "npm:jellyfin-api-bs-client@^1.0.5",
|
||||||
"bgv": "npm:button-group-vert@^1.0.1",
|
"bgv": "npm:button-group-vert@^1.0.1",
|
||||||
"brighterscript-formatter": "^1.6.8",
|
"brighterscript-formatter": "^1.6.8",
|
||||||
"sob": "npm:slide-out-button@^1.0.1"
|
"sob": "npm:slide-out-button@^1.0.1",
|
||||||
|
"intKeyboard": "npm:integer-keyboard@^1.0.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rokucommunity/bslint": "0.7.5",
|
"@rokucommunity/bslint": "0.7.5",
|
||||||
|
@ -3767,6 +3768,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/intKeyboard": {
|
||||||
|
"name": "integer-keyboard",
|
||||||
|
"version": "1.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/integer-keyboard/-/integer-keyboard-1.0.12.tgz",
|
||||||
|
"integrity": "sha512-DSLyd/PvtEBfc4grICTxSLu94Yo/Vm6rNerRZRbbzRrP0HQ9pYaquoY2RD9x6gAmica43gsFimScNpuRYVe54w=="
|
||||||
|
},
|
||||||
"node_modules/invariant": {
|
"node_modules/invariant": {
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
|
@ -9535,6 +9542,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
},
|
},
|
||||||
|
"intKeyboard": {
|
||||||
|
"version": "npm:integer-keyboard@1.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/integer-keyboard/-/integer-keyboard-1.0.12.tgz",
|
||||||
|
"integrity": "sha512-DSLyd/PvtEBfc4grICTxSLu94Yo/Vm6rNerRZRbbzRrP0HQ9pYaquoY2RD9x6gAmica43gsFimScNpuRYVe54w=="
|
||||||
|
},
|
||||||
"invariant": {
|
"invariant": {
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"ropm": "0.10.9"
|
"ropm": "0.10.9"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"postinstall": "npx ropm copy",
|
||||||
"validate": "npx bsc --copy-to-staging=false --create-package=false",
|
"validate": "npx bsc --copy-to-staging=false --create-package=false",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"lint": "bslint",
|
"lint": "bslint",
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
"api": "npm:jellyfin-api-bs-client@^1.0.5",
|
"api": "npm:jellyfin-api-bs-client@^1.0.5",
|
||||||
"bgv": "npm:button-group-vert@^1.0.1",
|
"bgv": "npm:button-group-vert@^1.0.1",
|
||||||
"brighterscript-formatter": "^1.6.8",
|
"brighterscript-formatter": "^1.6.8",
|
||||||
"sob": "npm:slide-out-button@^1.0.1"
|
"sob": "npm:slide-out-button@^1.0.1",
|
||||||
|
"intKeyboard": "npm:integer-keyboard@^1.0.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
"default": "true"
|
"default": "true"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Cinema mode",
|
"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.",
|
"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",
|
"settingName": "playback.cinemamode",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"default": "false"
|
"default": "false"
|
||||||
|
@ -30,9 +30,22 @@
|
||||||
"title": "User Interface",
|
"title": "User Interface",
|
||||||
"description": "Settings relating to how the application looks.",
|
"description": "Settings relating to how the application looks.",
|
||||||
"children": [
|
"children": [
|
||||||
|
{
|
||||||
|
"title": "Home Page",
|
||||||
|
"description": "Options for Home page.",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"title": "Max Days Next Up",
|
||||||
|
"description": "Set the maximum amount of days a show should stay in the 'Next Up' list without watching it.",
|
||||||
|
"settingName": "ui.details.maxdaysnextup",
|
||||||
|
"type": "integer",
|
||||||
|
"default": "365"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "Details Page",
|
"title": "Details Page",
|
||||||
"description": "Options for details pages.",
|
"description": "Options for Details pages.",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"title": "Hide Taglines",
|
"title": "Hide Taglines",
|
||||||
|
@ -42,8 +55,8 @@
|
||||||
"default": "false"
|
"default": "false"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "TV Shows",
|
"title": "TV Shows",
|
||||||
"description": "Options for TV Shows.",
|
"description": "Options for TV Shows.",
|
||||||
"children": [
|
"children": [
|
||||||
|
@ -55,8 +68,8 @@
|
||||||
"default": "false"
|
"default": "false"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Screensaver",
|
"title": "Screensaver",
|
||||||
"description": "Options for Jellyfin's screensaver.",
|
"description": "Options for Jellyfin's screensaver.",
|
||||||
"children": [
|
"children": [
|
||||||
|
@ -68,7 +81,7 @@
|
||||||
"default": "false"
|
"default": "false"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Design Elements",
|
"title": "Design Elements",
|
||||||
"description": "Options that alter the design of Jellyfin.",
|
"description": "Options that alter the design of Jellyfin.",
|
||||||
|
@ -91,7 +104,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Media Grid",
|
"title": "Media Grid",
|
||||||
"description": "Media Grid Options.",
|
"description": "Media Grid options.",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"title": "Item Count",
|
"title": "Item Count",
|
||||||
|
@ -118,4 +131,4 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -250,8 +250,29 @@ sub Main (args as dynamic) as void
|
||||||
' types: [ Series (Show), Episode, Movie, Audio, Person, Studio, MusicArtist ]
|
' types: [ Series (Show), Episode, Movie, Audio, Person, Studio, MusicArtist ]
|
||||||
if node.type = "Series"
|
if node.type = "Series"
|
||||||
group = CreateSeriesDetailsGroup(node)
|
group = CreateSeriesDetailsGroup(node)
|
||||||
else
|
else if node.type = "Movie"
|
||||||
group = CreateMovieDetailsGroup(node)
|
group = CreateMovieDetailsGroup(node)
|
||||||
|
else if node.type = "MusicArtist"
|
||||||
|
group = CreateArtistView(node.json)
|
||||||
|
else if node.type = "MusicAlbum"
|
||||||
|
group = CreateAlbumView(node.json)
|
||||||
|
else if node.type = "Audio"
|
||||||
|
group = CreateAudioPlayerGroup([node.json])
|
||||||
|
else if node.type = "Person"
|
||||||
|
group = CreatePersonView(node)
|
||||||
|
else if node.type = "TvChannel"
|
||||||
|
group = CreateVideoPlayerGroup(node.id)
|
||||||
|
sceneManager.callFunc("pushScene", group)
|
||||||
|
else if node.type = "Episode"
|
||||||
|
group = CreateVideoPlayerGroup(node.id)
|
||||||
|
sceneManager.callFunc("pushScene", group)
|
||||||
|
else if node.type = "Audio"
|
||||||
|
selectedIndex = msg.getData()
|
||||||
|
screenContent = msg.getRoSGNode()
|
||||||
|
group = CreateAudioPlayerGroup([screenContent.albumData.items[node.id]])
|
||||||
|
else
|
||||||
|
' TODO - switch on more node types
|
||||||
|
message_dialog("This type is not yet supported: " + node.type + ".")
|
||||||
end if
|
end if
|
||||||
else if isNodeEvent(msg, "buttonSelected")
|
else if isNodeEvent(msg, "buttonSelected")
|
||||||
' If a button is selected, we have some determining to do
|
' If a button is selected, we have some determining to do
|
||||||
|
@ -334,8 +355,8 @@ sub Main (args as dynamic) as void
|
||||||
end if
|
end if
|
||||||
group = CreateSearchPage()
|
group = CreateSearchPage()
|
||||||
sceneManager.callFunc("pushScene", group)
|
sceneManager.callFunc("pushScene", group)
|
||||||
group.findNode("SearchBox").findNode("search-input").setFocus(true)
|
group.findNode("SearchBox").findNode("search_Key").setFocus(true)
|
||||||
group.findNode("SearchBox").findNode("search-input").active = true
|
group.findNode("SearchBox").findNode("search_Key").active = true
|
||||||
else if button.id = "change_server"
|
else if button.id = "change_server"
|
||||||
unset_setting("server")
|
unset_setting("server")
|
||||||
unset_setting("port")
|
unset_setting("port")
|
||||||
|
|
|
@ -446,12 +446,8 @@ end function
|
||||||
|
|
||||||
function CreateSearchPage()
|
function CreateSearchPage()
|
||||||
' Search + Results Page
|
' Search + Results Page
|
||||||
group = CreateObject("roSGNode", "SearchResults")
|
group = CreateObject("roSGNode", "searchResults")
|
||||||
|
options = group.findNode("searchSelect")
|
||||||
search = group.findNode("SearchBox")
|
|
||||||
search.observeField("search_value", m.port)
|
|
||||||
|
|
||||||
options = group.findNode("SearchSelect")
|
|
||||||
options.observeField("itemSelected", m.port)
|
options.observeField("itemSelected", m.port)
|
||||||
|
|
||||||
return group
|
return group
|
||||||
|
|
|
@ -34,34 +34,40 @@ function ItemPostPlaybackInfo(id as string, mediaSourceId = "" as string, audioT
|
||||||
end function
|
end function
|
||||||
|
|
||||||
' Search across all libraries
|
' Search across all libraries
|
||||||
function SearchMedia(query as string)
|
function searchMedia(query as string)
|
||||||
' This appears to be done differently on the web now
|
' This appears to be done differently on the web now
|
||||||
' For each potential type, a separate query is done:
|
' For each potential type, a separate query is done:
|
||||||
' varying item types, and artists, and people
|
' varying item types, and artists, and people
|
||||||
resp = APIRequest(Substitute("Users/{0}/Items", get_setting("active_user")), {
|
|
||||||
"searchTerm": query,
|
|
||||||
"IncludePeople": true,
|
|
||||||
"IncludeMedia": true,
|
|
||||||
"IncludeShows": true,
|
|
||||||
"IncludeGenres": false,
|
|
||||||
"IncludeStudios": false,
|
|
||||||
"IncludeArtists": false,
|
|
||||||
"IncludeItemTypes": "TvChannel,Movie,BoxSet,Series,Episode,Video",
|
|
||||||
"EnableTotalRecordCount": false,
|
|
||||||
"ImageTypeLimit": 1,
|
|
||||||
"Recursive": true
|
|
||||||
})
|
|
||||||
|
|
||||||
data = getJson(resp)
|
if query <> ""
|
||||||
results = []
|
resp = APIRequest(Substitute("Search/Hints", get_setting("active_user")), {
|
||||||
for each item in data.Items
|
"searchTerm": query,
|
||||||
tmp = CreateObject("roSGNode", "SearchData")
|
"IncludePeople": true,
|
||||||
tmp.image = PosterImage(item.id)
|
"IncludeMedia": true,
|
||||||
tmp.json = item
|
"IncludeShows": true,
|
||||||
results.push(tmp)
|
"IncludeGenres": true,
|
||||||
end for
|
"IncludeStudios": true,
|
||||||
data.SearchHints = results
|
"IncludeArtists": true,
|
||||||
return data
|
"IncludeItemTypes": "LiveTvChannel,Movie,BoxSet,Series,Episode,Video,Person,Audio,MusicAlbum,MusicArtist,Playlist",
|
||||||
|
"EnableTotalRecordCount": false,
|
||||||
|
"ImageTypeLimit": 1,
|
||||||
|
"Recursive": true,
|
||||||
|
"limit": 100
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
data = getJson(resp)
|
||||||
|
results = []
|
||||||
|
for each item in data.SearchHints
|
||||||
|
tmp = CreateObject("roSGNode", "SearchData")
|
||||||
|
tmp.image = PosterImage(item.id)
|
||||||
|
tmp.json = item
|
||||||
|
results.push(tmp)
|
||||||
|
end for
|
||||||
|
data.SearchHints = results
|
||||||
|
return data
|
||||||
|
end if
|
||||||
|
return []
|
||||||
end function
|
end function
|
||||||
|
|
||||||
' MetaData about an item
|
' MetaData about an item
|
||||||
|
@ -94,7 +100,7 @@ function ItemMetaData(id as string)
|
||||||
tmp.image = PosterImage(data.id, imgParams)
|
tmp.image = PosterImage(data.id, imgParams)
|
||||||
tmp.json = data
|
tmp.json = data
|
||||||
return tmp
|
return tmp
|
||||||
else if data.type = "BoxSet"
|
else if data.type = "BoxSet" or data.type = "Playlist"
|
||||||
tmp = CreateObject("roSGNode", "CollectionData")
|
tmp = CreateObject("roSGNode", "CollectionData")
|
||||||
tmp.image = PosterImage(data.id, imgParams)
|
tmp.image = PosterImage(data.id, imgParams)
|
||||||
tmp.json = data
|
tmp.json = data
|
||||||
|
@ -268,6 +274,9 @@ function AudioStream(id as string)
|
||||||
content.title = songData.title
|
content.title = songData.title
|
||||||
content.streamformat = songData.mediaSources[0].container
|
content.streamformat = songData.mediaSources[0].container
|
||||||
|
|
||||||
|
playbackInfo = ItemPostPlaybackInfo(songData.id, params.MediaSourceId)
|
||||||
|
content.id = playbackInfo.PlaySessionId
|
||||||
|
|
||||||
return content
|
return content
|
||||||
end function
|
end function
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user