first attempt with promises
This commit is contained in:
parent
be9aa38134
commit
a11f786d99
|
@ -1,5 +1,6 @@
|
||||||
import "pkg:/source/roku_modules/log/LogMixin.brs"
|
import "pkg:/source/roku_modules/log/LogMixin.brs"
|
||||||
import "pkg:/source/utils/deviceCapabilities.brs"
|
import "pkg:/source/utils/deviceCapabilities.brs"
|
||||||
|
import "pkg:/source/roku_modules/promises/promises.brs"
|
||||||
|
|
||||||
sub init()
|
sub init()
|
||||||
m.log = log.Logger("SceneManager")
|
m.log = log.Logger("SceneManager")
|
||||||
|
@ -7,8 +8,6 @@ sub init()
|
||||||
m.scene = m.top.getScene()
|
m.scene = m.top.getScene()
|
||||||
m.content = m.scene.findNode("content")
|
m.content = m.scene.findNode("content")
|
||||||
m.overhang = m.scene.findNode("overhang")
|
m.overhang = m.scene.findNode("overhang")
|
||||||
m.postTask = CreateObject("roSGNode", "PostTask")
|
|
||||||
m.postTask.observeField("responseCode", "postFinished")
|
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
'
|
'
|
||||||
|
@ -89,7 +88,7 @@ sub popScene()
|
||||||
group.control = "stop"
|
group.control = "stop"
|
||||||
else if groupType = "Settings"
|
else if groupType = "Settings"
|
||||||
' update device profile after exiting the settings page - some settings affect the device profile
|
' update device profile after exiting the settings page - some settings affect the device profile
|
||||||
postProfile()
|
postDeviceProfile()
|
||||||
end if
|
end if
|
||||||
|
|
||||||
group.visible = false
|
group.visible = false
|
||||||
|
@ -363,49 +362,3 @@ end sub
|
||||||
function isDialogOpen() as boolean
|
function isDialogOpen() as boolean
|
||||||
return m.scene.dialog <> invalid
|
return m.scene.dialog <> invalid
|
||||||
end function
|
end function
|
||||||
|
|
||||||
' Send Device Profile information to server
|
|
||||||
function postProfile() as boolean
|
|
||||||
profile = getDeviceCapabilities()
|
|
||||||
print "profile =", profile
|
|
||||||
print "profile.DeviceProfile =", profile.DeviceProfile
|
|
||||||
print "profile.DeviceProfile.CodecProfiles ="
|
|
||||||
for each prof in profile.DeviceProfile.CodecProfiles
|
|
||||||
print prof
|
|
||||||
for each cond in prof.Conditions
|
|
||||||
print cond
|
|
||||||
end for
|
|
||||||
end for
|
|
||||||
print "profile.DeviceProfile.ContainerProfiles =", profile.DeviceProfile.ContainerProfiles
|
|
||||||
print "profile.DeviceProfile.DirectPlayProfiles ="
|
|
||||||
for each prof in profile.DeviceProfile.DirectPlayProfiles
|
|
||||||
print prof
|
|
||||||
end for
|
|
||||||
print "profile.DeviceProfile.SubtitleProfiles ="
|
|
||||||
for each prof in profile.DeviceProfile.SubtitleProfiles
|
|
||||||
print prof
|
|
||||||
end for
|
|
||||||
print "profile.DeviceProfile.TranscodingProfiles ="
|
|
||||||
for each prof in profile.DeviceProfile.TranscodingProfiles
|
|
||||||
print prof
|
|
||||||
if isValid(prof.Conditions)
|
|
||||||
for each condition in prof.Conditions
|
|
||||||
print condition
|
|
||||||
end for
|
|
||||||
end if
|
|
||||||
end for
|
|
||||||
print "profile.PlayableMediaTypes =", profile.PlayableMediaTypes
|
|
||||||
print "profile.SupportedCommands =", profile.SupportedCommands
|
|
||||||
|
|
||||||
m.postTask.arrayData = profile
|
|
||||||
m.postTask.apiUrl = "/Sessions/Capabilities/Full"
|
|
||||||
m.postTask.control = "RUN"
|
|
||||||
return true
|
|
||||||
end function
|
|
||||||
|
|
||||||
' Post Task is finished
|
|
||||||
sub postFinished()
|
|
||||||
m.postTask.unobserveField("responseCode")
|
|
||||||
m.postTask.callFunc("emptyPostTask")
|
|
||||||
m.postTask.observeField("responseCode", "postFinished")
|
|
||||||
end sub
|
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
<function name="dismissDialog" />
|
<function name="dismissDialog" />
|
||||||
<function name="isDialogOpen" />
|
<function name="isDialogOpen" />
|
||||||
<function name="optionDialog" />
|
<function name="optionDialog" />
|
||||||
<function name="postProfile" />
|
|
||||||
<field id="currentUser" type="string" onChange="updateUser" />
|
<field id="currentUser" type="string" onChange="updateUser" />
|
||||||
<field id="returnData" type="assocarray" />
|
<field id="returnData" type="assocarray" />
|
||||||
<field id="dataReturned" type="boolean" />
|
<field id="dataReturned" type="boolean" />
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
import "pkg:/source/api/baserequest.brs"
|
|
||||||
|
|
||||||
sub init()
|
|
||||||
m.top.functionName = "postItems"
|
|
||||||
end sub
|
|
||||||
|
|
||||||
sub postItems()
|
|
||||||
if m.top.apiUrl <> ""
|
|
||||||
if m.top.arrayData.count() > 0 and m.top.stringData = ""
|
|
||||||
print "PostTask Started - Posting array to " + m.top.apiUrl
|
|
||||||
req = APIRequest(m.top.apiUrl)
|
|
||||||
req.SetRequest("POST")
|
|
||||||
httpResponse = asyncPost(req, FormatJson(m.top.arrayData))
|
|
||||||
m.top.responseCode = httpResponse
|
|
||||||
print "PostTask Finished. " + m.top.apiUrl + " Response = " + httpResponse.toStr()
|
|
||||||
else if m.top.arrayData.count() = 0 and m.top.stringData <> ""
|
|
||||||
print "PostTask Started - Posting string(" + m.top.stringData + ") to " + m.top.apiUrl
|
|
||||||
req = APIRequest(m.top.apiUrl)
|
|
||||||
req.SetRequest("POST")
|
|
||||||
httpResponse = asyncPost(req, m.top.stringData)
|
|
||||||
m.top.responseCode = httpResponse
|
|
||||||
print "PostTask Finished. " + m.top.apiUrl + " Response = " + httpResponse.toStr()
|
|
||||||
else
|
|
||||||
print "ERROR processing data for PostTask"
|
|
||||||
end if
|
|
||||||
else
|
|
||||||
print "ERROR in PostTask. Invalid API URL provided"
|
|
||||||
end if
|
|
||||||
end sub
|
|
||||||
|
|
||||||
' Post data and wait for response code
|
|
||||||
function asyncPost(req, data = "" as string) as integer
|
|
||||||
' response code 0 means there was an error
|
|
||||||
respCode = 0
|
|
||||||
|
|
||||||
req.setMessagePort(CreateObject("roMessagePort"))
|
|
||||||
req.AddHeader("Content-Type", "application/json")
|
|
||||||
req.AsyncPostFromString(data)
|
|
||||||
' wait up to m.top.timeoutSeconds for a response
|
|
||||||
' NOTE: wait() uses milliseconds - multiply by 1000 to convert
|
|
||||||
resp = wait(m.top.timeoutSeconds * 1000, req.GetMessagePort())
|
|
||||||
|
|
||||||
respString = resp.GetString()
|
|
||||||
if respString <> invalid and respString <> ""
|
|
||||||
m.top.responseBody = ParseJson(respString)
|
|
||||||
print "m.top.responseBody=", m.top.responseBody
|
|
||||||
end if
|
|
||||||
|
|
||||||
respCode = resp.GetResponseCode()
|
|
||||||
if respCode < 0
|
|
||||||
' there was an unexpected error
|
|
||||||
m.top.failureReason = resp.GetFailureReason()
|
|
||||||
else if respCode >= 200 and respCode < 300
|
|
||||||
' save response headers if they're available
|
|
||||||
m.top.responseHeaders = resp.GetResponseHeaders()
|
|
||||||
end if
|
|
||||||
|
|
||||||
return respCode
|
|
||||||
end function
|
|
||||||
|
|
||||||
' Revert PostTask to default state
|
|
||||||
sub emptyPostTask()
|
|
||||||
' These should match the defaults set in PostTask.xml
|
|
||||||
m.top.apiUrl = ""
|
|
||||||
m.top.timeoutSeconds = 30
|
|
||||||
|
|
||||||
m.top.arrayData = {}
|
|
||||||
m.top.stringData = ""
|
|
||||||
|
|
||||||
m.top.responseCode = invalid
|
|
||||||
m.top.responseBody = {}
|
|
||||||
m.top.responseHeaders = {}
|
|
||||||
m.top.failureReason = ""
|
|
||||||
end sub
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<component name="PostTask" extends="Task">
|
|
||||||
<interface>
|
|
||||||
<field id="apiUrl" type="string" />
|
|
||||||
<field id="timeoutSeconds" type="integer" value="30" />
|
|
||||||
|
|
||||||
<field id="arrayData" type="assocarray" value="{}" />
|
|
||||||
<field id="stringData" type="string" value="" />
|
|
||||||
|
|
||||||
<field id="responseCode" type="integer" />
|
|
||||||
<field id="responseBody" type="assocarray" value="{}" />
|
|
||||||
<field id="responseHeaders" type="assocarray" value="{}" />
|
|
||||||
<field id="failureReason" type="string" value="" />
|
|
||||||
|
|
||||||
<function name="emptyPostTask" />
|
|
||||||
</interface>
|
|
||||||
</component>
|
|
27
components/tasks/PromiseTask.bs
Normal file
27
components/tasks/PromiseTask.bs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import "pkg:/source/roku_modules/promises/promises.brs"
|
||||||
|
|
||||||
|
sub init()
|
||||||
|
m.top.functionName = "resolve"
|
||||||
|
m.input = invalid
|
||||||
|
end sub
|
||||||
|
|
||||||
|
function getPromise(input = invalid as dynamic) as object
|
||||||
|
m.input = input
|
||||||
|
m.top.promise = promises.create()
|
||||||
|
m.top.control = "run"
|
||||||
|
return m.top.promise
|
||||||
|
end function
|
||||||
|
|
||||||
|
' Override me
|
||||||
|
function exec(input = invalid as dynamic) as dynamic
|
||||||
|
throw "Not implemented"
|
||||||
|
end function
|
||||||
|
|
||||||
|
sub resolve()
|
||||||
|
try
|
||||||
|
result = exec(m.input)
|
||||||
|
promises.resolve(result, m.top.promise)
|
||||||
|
catch e
|
||||||
|
promises.reject(e, m.top.promise)
|
||||||
|
end try
|
||||||
|
end sub
|
6
components/tasks/PromiseTask.xml
Normal file
6
components/tasks/PromiseTask.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<component name="PromiseTask" extends="Task">
|
||||||
|
<interface>
|
||||||
|
<field id="promise" type="node" />
|
||||||
|
<function name="getPromise" />
|
||||||
|
</interface>
|
||||||
|
</component>
|
6
components/tasks/RequestPromiseTask.bs
Normal file
6
components/tasks/RequestPromiseTask.bs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import "pkg:/source/roku_modules/rokurequests/Requests.brs"
|
||||||
|
|
||||||
|
function exec(input as object) as dynamic
|
||||||
|
print "input=", input
|
||||||
|
return Requests.request(input.method, input.url, input.params)
|
||||||
|
end function
|
2
components/tasks/RequestPromiseTask.xml
Normal file
2
components/tasks/RequestPromiseTask.xml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<component name="RequestPromiseTask" extends="PromiseTask">
|
||||||
|
</component>
|
13
package-lock.json
generated
13
package-lock.json
generated
|
@ -15,6 +15,8 @@
|
||||||
"brighterscript-formatter": "1.6.32",
|
"brighterscript-formatter": "1.6.32",
|
||||||
"intKeyboard": "npm:integer-keyboard@1.0.12",
|
"intKeyboard": "npm:integer-keyboard@1.0.12",
|
||||||
"log": "npm:roku-log@0.11.1",
|
"log": "npm:roku-log@0.11.1",
|
||||||
|
"promises": "npm:@rokucommunity/promises@0.1.0",
|
||||||
|
"roku-requests": "1.2.0",
|
||||||
"sob": "npm:slide-out-button@1.0.1"
|
"sob": "npm:slide-out-button@1.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -3688,6 +3690,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
},
|
},
|
||||||
|
"node_modules/promises": {
|
||||||
|
"name": "@rokucommunity/promises",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rokucommunity/promises/-/promises-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-FOPtEnHXfShwhrQiGSksTK0AQt5+rxcqpP6hg0U3Dx7WbMpL9PEd3udJhQteg3Iy2/GF858vYLcwdG8YdOloYw=="
|
||||||
|
},
|
||||||
"node_modules/psl": {
|
"node_modules/psl": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||||
|
@ -4369,6 +4377,11 @@
|
||||||
"integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==",
|
"integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/roku-requests": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/roku-requests/-/roku-requests-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-X6XakmJwxT8H+YNvjZOwH+k8rmYpD5o47k37WyZJ/brrSD6cw9xbNdxO203nz6jpso4maQJGwSJvLGZpzSQ0AA=="
|
||||||
|
},
|
||||||
"node_modules/rooibos-roku": {
|
"node_modules/rooibos-roku": {
|
||||||
"version": "5.7.0",
|
"version": "5.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/rooibos-roku/-/rooibos-roku-5.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/rooibos-roku/-/rooibos-roku-5.7.0.tgz",
|
||||||
|
|
|
@ -8,8 +8,15 @@
|
||||||
"brighterscript-formatter": "1.6.32",
|
"brighterscript-formatter": "1.6.32",
|
||||||
"intKeyboard": "npm:integer-keyboard@1.0.12",
|
"intKeyboard": "npm:integer-keyboard@1.0.12",
|
||||||
"log": "npm:roku-log@0.11.1",
|
"log": "npm:roku-log@0.11.1",
|
||||||
|
"promises": "npm:@rokucommunity/promises@0.1.0",
|
||||||
|
"roku-requests": "1.2.0",
|
||||||
"sob": "npm:slide-out-button@1.0.1"
|
"sob": "npm:slide-out-button@1.0.1"
|
||||||
},
|
},
|
||||||
|
"ropm": {
|
||||||
|
"noprefix": [
|
||||||
|
"roku-requests"
|
||||||
|
]
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rokucommunity/bslint": "0.8.10",
|
"@rokucommunity/bslint": "0.8.10",
|
||||||
"brighterscript": "0.65.5",
|
"brighterscript": "0.65.5",
|
||||||
|
@ -52,4 +59,4 @@
|
||||||
"url": "https://github.com/jellyfin/jellyfin-roku/issues"
|
"url": "https://github.com/jellyfin/jellyfin-roku/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/jellyfin/jellyfin-roku"
|
"homepage": "https://github.com/jellyfin/jellyfin-roku"
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,11 @@ sub Main (args as dynamic) as void
|
||||||
m.global.addFields({ audioPlayer: CreateObject("roSGNode", "AudioPlayer") })
|
m.global.addFields({ audioPlayer: CreateObject("roSGNode", "AudioPlayer") })
|
||||||
|
|
||||||
app_start:
|
app_start:
|
||||||
|
postDeviceProfile()
|
||||||
' First thing to do is validate the ability to use the API
|
' First thing to do is validate the ability to use the API
|
||||||
if not LoginFlow() then return
|
if not LoginFlow() then return
|
||||||
' tell jellyfin server about device capabilities
|
' tell jellyfin server about device capabilities
|
||||||
m.global.sceneManager.callFunc("postProfile")
|
|
||||||
' remove previous scenes from the stack
|
' remove previous scenes from the stack
|
||||||
sceneManager.callFunc("clearScenes")
|
sceneManager.callFunc("clearScenes")
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import "pkg:/source/utils/misc.brs"
|
import "pkg:/source/utils/misc.brs"
|
||||||
import "pkg:/source/api/baserequest.brs"
|
import "pkg:/source/api/baserequest.brs"
|
||||||
|
import "pkg:/source/roku_modules/promises/promises.brs"
|
||||||
|
|
||||||
'Device Capabilities for Roku.
|
'Device Capabilities for Roku.
|
||||||
'This will likely need further tweaking
|
'This will likely need further tweaking
|
||||||
|
@ -963,3 +964,53 @@ function removeDecimals(value as string) as string
|
||||||
value = r.ReplaceAll(value, "")
|
value = r.ReplaceAll(value, "")
|
||||||
return value
|
return value
|
||||||
end function
|
end function
|
||||||
|
|
||||||
|
' Post the deviceProfile to the server
|
||||||
|
sub postDeviceProfile()
|
||||||
|
profile = getDeviceCapabilities()
|
||||||
|
printDeviceProfile(profile)
|
||||||
|
|
||||||
|
request = CreateObject("roSGNode", "RequestPromiseTask")
|
||||||
|
promise = request@.getPromise({
|
||||||
|
method: "GET",
|
||||||
|
url: "https://api.github.com/events"
|
||||||
|
})
|
||||||
|
|
||||||
|
promises.onThen(promise, sub (response as object)
|
||||||
|
? "ok?", response.ok
|
||||||
|
? "status code:", response.statusCode
|
||||||
|
end sub)
|
||||||
|
end sub
|
||||||
|
|
||||||
|
' Print out the deviceProfile for debugging
|
||||||
|
sub printDeviceProfile(profile as object)
|
||||||
|
print "profile =", profile
|
||||||
|
print "profile.DeviceProfile =", profile.DeviceProfile
|
||||||
|
print "profile.DeviceProfile.CodecProfiles ="
|
||||||
|
for each prof in profile.DeviceProfile.CodecProfiles
|
||||||
|
print prof
|
||||||
|
for each cond in prof.Conditions
|
||||||
|
print cond
|
||||||
|
end for
|
||||||
|
end for
|
||||||
|
print "profile.DeviceProfile.ContainerProfiles =", profile.DeviceProfile.ContainerProfiles
|
||||||
|
print "profile.DeviceProfile.DirectPlayProfiles ="
|
||||||
|
for each prof in profile.DeviceProfile.DirectPlayProfiles
|
||||||
|
print prof
|
||||||
|
end for
|
||||||
|
print "profile.DeviceProfile.SubtitleProfiles ="
|
||||||
|
for each prof in profile.DeviceProfile.SubtitleProfiles
|
||||||
|
print prof
|
||||||
|
end for
|
||||||
|
print "profile.DeviceProfile.TranscodingProfiles ="
|
||||||
|
for each prof in profile.DeviceProfile.TranscodingProfiles
|
||||||
|
print prof
|
||||||
|
if isValid(prof.Conditions)
|
||||||
|
for each condition in prof.Conditions
|
||||||
|
print condition
|
||||||
|
end for
|
||||||
|
end if
|
||||||
|
end for
|
||||||
|
print "profile.PlayableMediaTypes =", profile.PlayableMediaTypes
|
||||||
|
print "profile.SupportedCommands =", profile.SupportedCommands
|
||||||
|
end sub
|
||||||
|
|
|
@ -149,6 +149,9 @@ namespace session
|
||||||
end for
|
end for
|
||||||
|
|
||||||
if m.global.app.isDev
|
if m.global.app.isDev
|
||||||
|
print "m.global.session.user = ", m.global.session.user
|
||||||
|
print "m.global.session.user.Configuration = ", m.global.session.user.Configuration
|
||||||
|
print "m.global.session.user.Policy = ", m.global.session.user.Policy
|
||||||
print "m.global.session.user.settings = ", m.global.session.user.settings
|
print "m.global.session.user.settings = ", m.global.session.user.settings
|
||||||
end if
|
end if
|
||||||
' ensure registry is updated
|
' ensure registry is updated
|
||||||
|
|
Loading…
Reference in New Issue
Block a user