Some heavy restructuring

This commit is contained in:
Nick Bisby 2019-03-04 22:59:31 -06:00
parent f350ec8cff
commit 0f15d6983f
No known key found for this signature in database
GPG Key ID: F6E0C4E6D0B5EB36
5 changed files with 136 additions and 172 deletions

View File

@ -15,6 +15,7 @@
end sub end sub
function itemContentChanged() as void function itemContentChanged() as void
m.itemText = m.top.findNode("itemText")
itemData = m.top.itemContent itemData = m.top.itemContent
m.itemText.text = itemData.labelText m.itemText.text = itemData.labelText
end function end function

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<component name="VideoScene" extends="Scene">
<children>
<Video id="VideoPlayer" />
</children>
<script type="text/brightscript">
<![CDATA[
function init()
m.top.setFocus(true)
end function
]]>
</script>
</component>

View File

@ -1,42 +1,42 @@
' Functions for making requests to the API ' Functions for making requests to the API
function APIRequest(url as String, params={} as Object) function APIRequest(url as String, params={} as Object)
req = createObject("roUrlTransfer") req = createObject("roUrlTransfer")
if server_is_https() then if server_is_https() then
req.setCertificatesFile("common:/certs/ca-bundle.crt") req.setCertificatesFile("common:/certs/ca-bundle.crt")
end if end if
full_url = get_base_url() + "/emby/" + url full_url = get_base_url() + "/emby/" + url
if params.count() > 0 if params.count() > 0
full_url = full_url + "?" full_url = full_url + "?"
param_array = [] param_array = []
for each field in params.items() for each field in params.items()
if type(field.value) = "String" then if type(field.value) = "String" then
item = field.key + "=" + req.escape(field.value.trim()) item = field.key + "=" + req.escape(field.value.trim())
else if type(field.value) = "roInteger" then else if type(field.value) = "roInteger" then
item = field.key + "=" + req.escape(str(field.value).trim()) item = field.key + "=" + req.escape(str(field.value).trim())
else else
item = field.key + "=" + req.escape(field.value) item = field.key + "=" + req.escape(field.value)
end if end if
param_array.push(item) param_array.push(item)
end for end for
full_url = full_url + param_array.join("&") full_url = full_url + param_array.join("&")
end if end if
req.setUrl(full_url) req.setUrl(full_url)
req = authorize_request(req) req = authorize_request(req)
return req return req
end function end function
function parseRequest(req) function parseRequest(req)
'req.retainBodyOnError(True) 'req.retainBodyOnError(True)
'print req.GetToString() 'print req.GetToString()
json = ParseJson(req.GetToString()) json = ParseJson(req.GetToString())
return json return json
end function end function
function get_base_url() function get_base_url()
@ -49,70 +49,76 @@ function get_base_url()
end function end function
function server_is_https() as Boolean function server_is_https() as Boolean
server = get_setting("server") server = get_setting("server")
i = server.Instr(":") i = server.Instr(":")
' No protocol found ' No protocol found
if i = 0 then if i = 0 then
return False
end if
protocol = Left(server, i)
if protocol = "https" then
return True
end if
return False return False
end if
protocol = Left(server, i)
if protocol = "https" then
return True
end if
return False
end function end function
function get_token(user as String, password as String) function get_token(user as String, password as String)
bytes = createObject("roByteArray") bytes = createObject("roByteArray")
bytes.FromAsciiString(password) bytes.FromAsciiString(password)
digest = createObject("roEVPDigest") digest = createObject("roEVPDigest")
digest.setup("sha1") digest.setup("sha1")
hashed_pass = digest.process(bytes) hashed_pass = digest.process(bytes)
url = "Users/AuthenticateByName?format=json" url = "Users/AuthenticateByName?format=json"
req = APIRequest(url) req = APIRequest(url)
' BrightScript will only return a POST body if you call post asynch ' BrightScript will only return a POST body if you call post asynch
' and then wait for the response ' and then wait for the response
req.setMessagePort(CreateObject("roMessagePort")) req.setMessagePort(CreateObject("roMessagePort"))
req.AsyncPostFromString("Username=" + user + "&Password=" + hashed_pass) req.AsyncPostFromString("Username=" + user + "&Password=" + hashed_pass)
resp = wait(5000, req.GetMessagePort()) resp = wait(5000, req.GetMessagePort())
if type(resp) <> "roUrlEvent" if type(resp) <> "roUrlEvent"
return invalid return invalid
end if end if
json = ParseJson(resp.GetString()) json = ParseJson(resp.GetString())
set_setting("active_user", json.User.id) set_setting("active_user", json.User.id)
set_user_setting("id", json.User.id) ' redundant, but could come in handy set_user_setting("id", json.User.id) ' redundant, but could come in handy
set_user_setting("token", json.AccessToken) set_user_setting("token", json.AccessToken)
set_user_setting("response", json) set_user_setting("response", json)
return json return json
end function end function
function authorize_request(request) function authorize_request(request)
auth = "MediaBrowser" auth = "MediaBrowser"
auth = auth + " Client=" + Chr(34) + "Jellyfin Roku" + Chr(34) auth = auth + " Client=" + Chr(34) + "Jellyfin Roku" + Chr(34)
auth = auth + ", Device=" + Chr(34) + "Roku Model" + Chr(34) auth = auth + ", Device=" + Chr(34) + "Roku Model" + Chr(34)
auth = auth + ", DeviceId=" + Chr(34) + "12345" + Chr(34) auth = auth + ", DeviceId=" + Chr(34) + "12345" + Chr(34)
auth = auth + ", Version=" + Chr(34) + "10.1.0" + Chr(34) auth = auth + ", Version=" + Chr(34) + "10.1.0" + Chr(34)
user = get_setting("active_user") user = get_setting("active_user")
if user <> invalid and user <> "" then if user <> invalid and user <> "" then
auth = auth + ", UserId=" + Chr(34) + user + Chr(34) auth = auth + ", UserId=" + Chr(34) + user + Chr(34)
end if end if
token = get_user_setting("token") token = get_user_setting("token")
if token <> invalid and token <> "" then if token <> invalid and token <> "" then
auth = auth + ", Token=" + Chr(34) + token + Chr(34) auth = auth + ", Token=" + Chr(34) + token + Chr(34)
end if end if
request.AddHeader("X-Emby-Authorization", auth) request.AddHeader("X-Emby-Authorization", auth)
return request return request
end function
function AboutMe()
url = Substitute("Users/{0}", get_setting("active_user"))
resp = APIRequest(url)
return parseRequest(resp)
end function end function
@ -122,45 +128,30 @@ end function
' Params: None ' Params: None
' Returns { Items, TotalRecordCount } ' Returns { Items, TotalRecordCount }
function LibraryList() function LibraryList()
url = Substitute("Users/{0}/Views/", get_setting("active_user")) url = Substitute("Users/{0}/Views/", get_setting("active_user"))
resp = APIRequest(url) resp = APIRequest(url)
return parseRequest(resp) return parseRequest(resp)
end function end function
' Search for a string ' Search for a string
' Params: Search Query ' Params: Search Query
' Returns: { SearchHints, TotalRecordCount } ' Returns: { SearchHints, TotalRecordCount }
function SearchMedia(query as String) function SearchMedia(query as String)
resp = APIRequest("Search/Hints", {"searchTerm": query}) resp = APIRequest("Search/Hints", {"searchTerm": query})
return parseRequest(resp) return parseRequest(resp)
end function end function
' List items from within a Library ' List items from within a Library
' Params: Library ID, Limit, Offset, SortBy, SortOrder, IncludeItemTypes, Fields, EnableImageTypes ' Params: Library ID, Limit, Offset, SortBy, SortOrder, IncludeItemTypes, Fields, EnableImageTypes
' Returns { Items, TotalRecordCount } ' Returns { Items, TotalRecordCount }
function ItemList(library_id=invalid as String) function ItemList(library_id=invalid as String)
url = Substitute("Users/{0}/Items/", get_setting("active_user")) url = Substitute("Users/{0}/Items/", get_setting("active_user"))
resp = APIRequest(url, {"parentid": library_id, "limit": 30}) resp = APIRequest(url, {"parentid": library_id, "limit": 30})
return parseRequest(resp) return parseRequest(resp)
end function end function
function ItemMetaData(id as String) function ItemMetaData(id as String)
url = Substitute("Users/{0}/Items/{1}", get_setting("active_user"), id) url = Substitute("Users/{0}/Items/{1}", get_setting("active_user"), id)
resp = APIRequest(url) resp = APIRequest(url)
return parseRequest(resp) return parseRequest(resp)
end function
' Video
function VideoStream(id as String)
player = createObject("roVideoPlayer")
content = VideoContent(id)
player.addContent(content)
player.play()
return player
end function end function

View File

@ -1,49 +1,50 @@
sub Main() sub Main()
m.port = CreateObject("roMessagePort") ' First thing to do is validate the ability to use the API
' This facade keeps the app open when maybe other screens close
facade = CreateObject("roSGScreen")
facade.show()
if get_setting("server") = invalid then if get_setting("server") = invalid then
print "Get server details" print "Get server details"
' TODO - make this into a dialog
' TODO - be able to submit server info ' TODO - be able to submit server info
ShowServerSelect() ShowServerSelect()
end if end if
if get_setting("active_user") = invalid then if get_setting("active_user") = invalid then
print "Get user login" print "Get user login"
' TODO - make this into a dialog ' TODO - be able to submit user info
' screen.CreateScene("UserSignIn") ' ShowSigninSelect()
' TODO - sign in here
end if end if
' TODO - something here to validate that the active_user is still ' Confirm the configured server and user work
' valid. m.user = AboutMe()
if m.user.id <> get_setting("active_user")
' TODO - proper handling of the scenario where things have gone wrong
print "OH NO!"
end if
selected = ShowLibrarySelect() ShowLibrarySelect()
await_response()
end sub end sub
sub ShowServerSelect() sub ShowServerSelect()
port = CreateObject("roMessagePort") port = CreateObject("roMessagePort")
screen = CreateObject("roSGScreen") screen = CreateObject("roSGScreen")
screen.setMessagePort(port) screen.setMessagePort(port)
scene = screen.CreateScene("ServerSelection") scene = screen.CreateScene("ServerSelection")
screen.show() screen.show()
await_response() while(true)
msg = wait(0, port)
if msg.isScreenClosed() then
return
else
print(msgType)
end if
end while
end sub end sub
sub ShowLibrarySelect() sub ShowLibrarySelect()
port = CreateObject("roMessagePort") port = CreateObject("roMessagePort")
screen = CreateObject("roSGScreen") screen = CreateObject("roSGScreen")
screen.setMessagePort(port) screen.setMessagePort(port)
scene = screen.CreateScene("Library") scene = screen.CreateScene("Library")
screen.show() screen.show()
@ -56,32 +57,23 @@ sub ShowLibrarySelect()
while(true) while(true)
msg = wait(0, port) msg = wait(0, port)
print msg
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed() then if type(msg) = "roSGScreenEvent" and msg.isScreenClosed() then
exit while exit while
else if itemSelectedQ(msg) else if itemSelectedQ(msg)
target = getRowTarget(msg) target = getMsgRowTarget(msg)
ShowLibraryOptions(target.libraryID) if target.libraryType = "movies"
ShowMovieOptions(target.libraryID)
else
print "NOT YET IMPLEMENTED"
end if
end if end if
end while end while
end sub end sub
sub itemSelectedQ(msg) as boolean sub ShowMovieOptions(library_id)
return type(msg) = "roSGNodeEvent" and msg.getField() = "itemSelected"
end sub
sub getRowTarget(msg) as object
node = msg.getRoSGNode()
coords = node.rowItemSelected
target = node.content.getChild(coords[0]).getChild(coords[1])
return target
end sub
sub ShowLibraryOptions(library_id)
port = CreateObject("roMessagePort") port = CreateObject("roMessagePort")
screen = CreateObject("roSGScreen") screen = CreateObject("roSGScreen")
screen.setMessagePort(port) screen.setMessagePort(port)
scene = screen.CreateScene("Movies") scene = screen.CreateScene("Movies")
screen.show() screen.show()
@ -97,9 +89,8 @@ sub ShowLibraryOptions(library_id)
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed() then if type(msg) = "roSGScreenEvent" and msg.isScreenClosed() then
return return
else if itemSelectedQ(msg) else if itemSelectedQ(msg)
target = getRowTarget(msg) target = getMsgRowTarget(msg)
showVideoPlayer(target.movieID) showVideoPlayer(target.movieID)
print msg
end if end if
end while end while
end sub end sub
@ -108,8 +99,7 @@ sub showVideoPlayer(id)
port = CreateObject("roMessagePort") port = CreateObject("roMessagePort")
screen = CreateObject("roSGScreen") screen = CreateObject("roSGScreen")
screen.setMessagePort(port) screen.setMessagePort(port)
scene = screen.CreateScene("Scene")
scene = screen.CreateScene("VideoScene")
screen.show() screen.show()
@ -124,16 +114,15 @@ sub showVideoPlayer(id)
end sub end sub
sub await_response(port=invalid) sub itemSelectedQ(msg) as boolean
if port = invalid then ' "Q" stands for "Question mark" since itemSelected? wasn't acceptable
port = m.port ' Probably needs a better name, but unique for now
end if return type(msg) = "roSGNodeEvent" and msg.getField() = "itemSelected"
while(true) end sub
msg = wait(0, port)
if msg.isScreenClosed() then sub getMsgRowTarget(msg) as object
return node = msg.getRoSGNode()
else coords = node.rowItemSelected
print(msgType) target = node.content.getChild(coords[0]).getChild(coords[1])
end if return target
end while
end sub end sub

View File

@ -1,19 +1,15 @@
function VideoPlayer(scene, id) function VideoPlayer(scene, id)
video = scene.createChild("Video")
content = VideoContent(id)
content = VideoContent(id) video.content = content
video = scene.findNode("VideoPlayer") video.setFocus(true)
video.control = "play"
video.content = content
video.setFocus(true)
video.control = "play"
return video
return video
end function end function
function VideoContent(id) as object function VideoContent(id) as object
content = createObject("RoSGNode", "ContentNode") content = createObject("RoSGNode", "ContentNode")