2020-03-21 21:22:26 +00:00
function CreateServerGroup()
2019-04-29 16:44:37 +00:00
' Get and Save Jellyfin Server Information
2019-10-13 19:33:14 +00:00
group = CreateObject("roSGNode", "ConfigScene")
m.scene.appendChild(group)
2020-03-21 21:22:26 +00:00
port = CreateObject("roMessagePort")
2020-05-05 21:09:18 +00:00
group.findNode("prompt").text = tr("Connect to Server")
2019-03-07 03:14:52 +00:00
2019-10-13 19:33:14 +00:00
config = group.findNode("configOptions")
2019-03-22 03:27:31 +00:00
server_field = CreateObject("roSGNode", "ConfigData")
2020-05-05 21:09:18 +00:00
server_field.label = tr("Server")
2019-03-22 03:27:31 +00:00
server_field.field = "server"
server_field.type = "string"
2019-07-25 01:35:52 +00:00
if get_setting("server") <> invalid
server_field.value = get_setting("server")
end if
2020-05-05 21:09:18 +00:00
group.findNode("example").text = tr("192.168.1.100:8096 or https://example.com/jellyfin")
2020-02-20 06:43:59 +00:00
items = [ server_field ]
2019-03-20 03:23:58 +00:00
config.configItems = items
2019-03-07 03:14:52 +00:00
2019-10-13 19:33:14 +00:00
button = group.findNode("submit")
2020-03-21 21:22:26 +00:00
button.observeField("buttonSelected", port)
2019-03-07 03:14:52 +00:00
server_hostname = config.content.getChild(0)
2020-03-21 21:22:26 +00:00
group.observeField("backPressed", port)
2019-03-07 03:14:52 +00:00
while(true)
2020-03-21 21:22:26 +00:00
msg = wait(0, port)
2019-03-07 03:14:52 +00:00
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
2020-03-21 21:22:26 +00:00
return "false"
else if isNodeEvent(msg, "backPressed")
return "backPressed"
2019-03-07 03:14:52 +00:00
else if type(msg) = "roSGNodeEvent"
node = msg.getNode()
if node = "submit"
2020-03-21 21:42:53 +00:00
'Append default ports
2020-03-22 22:40:47 +00:00
maxSlashes = 0
if left(server_hostname.value,8) = "https://" or left(server_hostname.value,7) = "http://" then maxSlashes = 2
'Check to make sure entry has no extra slashes before adding default ports.
2020-05-05 21:09:18 +00:00
if Instr(0, server_hostname.value, "/") = maxSlashes then
2020-03-21 21:42:53 +00:00
if server_hostname.value.len() > 5 and mid(server_hostname.value, server_hostname.value.len()-4,1) <> ":" and mid(server_hostname.value, server_hostname.value.len()-5,1) <> ":" then
if left(server_hostname.value ,5) = "https" then
server_hostname.value = server_hostname.value + ":8920"
else
server_hostname.value = server_hostname.value + ":8096"
end if
2020-03-21 21:22:26 +00:00
end if
end if
2020-03-21 21:42:53 +00:00
'Append http:// to server
2020-03-21 21:22:26 +00:00
if left(server_hostname.value,4) <> "http" then server_hostname.value = "http://" + server_hostname.value
2021-01-20 04:41:22 +00:00
'If this is a different server from what we know, reset username/password setting
if get_setting("server") <> server_hostname.value then
set_setting("username", "")
set_setting("password", "")
endif
2019-03-07 03:14:52 +00:00
set_setting("server", server_hostname.value)
2020-03-04 03:02:05 +00:00
if ServerInfo() = invalid then
2019-04-27 14:44:14 +00:00
' Maybe don't unset setting, but offer as a prompt
' Server not found, is it online? New values / Retry
print "Server not found, is it online? New values / Retry"
2020-05-05 21:09:18 +00:00
group.findNode("alert").text = tr("Server not found, is it online?")
2019-04-27 14:44:14 +00:00
SignOut()
2019-07-09 13:57:59 +00:00
else
2019-10-13 19:33:14 +00:00
group.visible = false
2020-03-21 21:22:26 +00:00
return "true"
2019-04-27 14:44:14 +00:00
endif
2019-03-07 03:14:52 +00:00
end if
end if
end while
2019-10-13 19:33:14 +00:00
' Just hide it when done, in case we need to come back
group.visible = false
2020-03-21 21:22:26 +00:00
end function
function CreateUserSelectGroup(users = [])
if users.count() = 0 then
return ""
end if
group = CreateObject("roSGNode", "UserSelect")
m.scene.appendChild(group)
port = CreateObject("roMessagePort")
2020-03-22 22:40:47 +00:00
group.itemContent = users
group.findNode("userRow").observeField("userSelected", port)
group.findNode("alternateOptions").observeField("itemSelected", port)
2020-03-21 21:22:26 +00:00
group.observeField("backPressed", port)
while(true)
msg = wait(0, port)
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
group.visible = false
return -1
else if isNodeEvent(msg, "backPressed")
return "backPressed"
2020-03-22 22:40:47 +00:00
else if type(msg) = "roSGNodeEvent" and msg.getField() = "userSelected"
2020-03-21 21:22:26 +00:00
return msg.GetData()
else if type(msg) = "roSGNodeEvent" and msg.getField() = "itemSelected"
if msg.getData() = 0 then
return ""
end if
end if
end while
' Just hide it when done, in case we need to come back
group.visible = false
end function
2019-03-07 03:14:52 +00:00
2020-03-21 21:22:26 +00:00
function CreateSigninGroup(user = "")
2019-04-29 16:44:37 +00:00
' Get and Save Jellyfin user login credentials
2019-10-13 19:33:14 +00:00
group = CreateObject("roSGNode", "ConfigScene")
m.scene.appendChild(group)
2020-03-21 21:22:26 +00:00
port = CreateObject("roMessagePort")
2019-03-07 03:14:52 +00:00
2020-05-05 21:09:18 +00:00
group.findNode("prompt").text = tr("Sign In")
2019-03-07 03:14:52 +00:00
2019-10-13 19:33:14 +00:00
config = group.findNode("configOptions")
2019-03-22 03:27:31 +00:00
username_field = CreateObject("roSGNode", "ConfigData")
2020-05-05 21:09:18 +00:00
username_field.label = tr("Username")
2019-03-22 03:27:31 +00:00
username_field.field = "username"
username_field.type = "string"
2021-01-18 04:19:52 +00:00
if user = "" and get_setting("username") <> invalid
username_field.value = get_setting("username")
else
username_field.value = user
end if
2019-03-22 03:27:31 +00:00
password_field = CreateObject("roSGNode", "ConfigData")
2020-05-05 21:09:18 +00:00
password_field.label = tr("Password")
2019-03-22 03:27:31 +00:00
password_field.field = "password"
password_field.type = "password"
2021-01-18 04:19:52 +00:00
if get_setting("password") <> invalid
password_field.value = get_setting("password")
end if
2019-03-22 03:27:31 +00:00
items = [ username_field, password_field ]
2019-03-20 03:23:58 +00:00
config.configItems = items
2019-03-07 03:14:52 +00:00
2019-10-13 19:33:14 +00:00
button = group.findNode("submit")
2020-03-21 21:22:26 +00:00
button.observeField("buttonSelected", port)
2019-03-07 03:14:52 +00:00
2019-10-13 19:33:14 +00:00
config = group.findNode("configOptions")
2019-03-07 03:14:52 +00:00
username = config.content.getChild(0)
password = config.content.getChild(1)
2020-03-21 21:22:26 +00:00
group.observeField("backPressed", port)
2019-03-07 03:14:52 +00:00
while(true)
2020-03-21 21:22:26 +00:00
msg = wait(0, port)
2019-03-07 03:14:52 +00:00
if type(msg) = "roSGScreenEvent" and msg.isScreenClosed()
2019-10-13 19:33:14 +00:00
group.visible = false
2020-03-21 21:22:26 +00:00
return "false"
else if isNodeEvent(msg, "backPressed")
group.unobserveField("backPressed")
group.backPressed = false
return "backPressed"
2019-03-07 03:14:52 +00:00
else if type(msg) = "roSGNodeEvent"
node = msg.getNode()
if node = "submit"
' Validate credentials
get_token(username.value, password.value)
2021-01-18 04:19:52 +00:00
if get_setting("active_user") <> invalid
set_setting("username", username.value)
set_setting("password", password.value)
return "true"
end if
2019-03-07 03:14:52 +00:00
print "Login attempt failed..."
2020-05-05 21:09:18 +00:00
group.findNode("alert").text = tr("Login attempt failed.")
2019-03-07 03:14:52 +00:00
end if
end if
end while
2019-10-13 19:33:14 +00:00
' Just hide it when done, in case we need to come back
group.visible = false
2020-03-21 21:22:26 +00:00
end function
2019-03-07 03:14:52 +00:00
2020-03-03 23:01:13 +00:00
function CreateHomeGroup()
2019-04-29 16:44:37 +00:00
' Main screen after logging in. Shows the user's libraries
2020-03-03 23:01:13 +00:00
group = CreateObject("roSGNode", "Home")
2019-03-10 05:28:28 +00:00
2020-03-12 18:33:45 +00:00
group.observeField("selectedItem", m.port)
2020-12-08 08:39:58 +00:00
group.observeField("quickPlayNode", m.port)
2019-04-15 00:16:47 +00:00
2019-10-12 21:23:44 +00:00
sidepanel = group.findNode("options")
2019-10-13 19:33:14 +00:00
sidepanel.observeField("closeSidePanel", m.port)
2019-03-19 04:17:50 +00:00
new_options = []
options_buttons = [
2019-10-13 19:33:14 +00:00
{"title": "Search", "id": "goto_search"},
2019-03-19 14:11:46 +00:00
{"title": "Change server", "id": "change_server"},
2020-10-24 08:17:43 +00:00
{"title": "Sign out", "id": "sign_out"}
2019-03-19 04:17:50 +00:00
]
for each opt in options_buttons
o = CreateObject("roSGNode", "OptionsButton")
2020-05-05 21:09:18 +00:00
o.title = tr(opt.title)
2019-03-19 04:17:50 +00:00
o.id = opt.id
2019-10-13 19:33:14 +00:00
o.observeField("optionSelected", m.port)
2019-04-22 20:07:34 +00:00
new_options.push(o)
2019-03-19 04:17:50 +00:00
end for
2019-04-22 20:07:34 +00:00
' And a profile button
user_node = CreateObject("roSGNode", "OptionsData")
user_node.id = "active_user"
2020-05-05 21:09:18 +00:00
user_node.title = tr("Profile")
user_node.base_title = tr("Profile")
2019-04-22 20:07:34 +00:00
user_options = []
for each user in AvailableUsers()
user_options.push({display: user.username + "@" + user.server, value: user.id})
end for
user_node.choices = user_options
user_node.value = get_setting("active_user")
new_options.push(user_node)
2019-03-19 04:17:50 +00:00
sidepanel.options = new_options
2019-10-12 21:23:44 +00:00
return group
2019-10-12 20:21:34 +00:00
end function
2019-03-07 03:14:52 +00:00
2020-06-15 16:05:48 +00:00
function CreateMovieListGroup(libraryItem)
2020-06-10 16:43:32 +00:00
group = CreateObject("roSGNode", "ItemGrid2")
2020-06-15 16:05:48 +00:00
group.parentItem = libraryItem
2020-05-05 21:09:18 +00:00
2020-06-10 16:43:32 +00:00
group.observeField("selectedItem", m.port)
2020-12-08 09:08:19 +00:00
group.observeField("quickPlayNode", m.port)
2019-03-13 01:16:12 +00:00
2019-10-13 19:33:14 +00:00
sidepanel = group.findNode("options")
movie_options = [
{"title": "Sort Field",
"base_title": "Sort Field",
"key": "movie_sort_field",
"default": "DateCreated",
"values": [
2020-05-05 21:09:18 +00:00
{display: tr("Date Added"), value: "DateCreated"},
{display: tr("Release Date"), value: "PremiereDate"},
{display: tr("Name"), value: "SortName"}
2019-10-13 19:33:14 +00:00
]},
{"title": "Sort Order",
"base_title": "Sort Order",
"key": "movie_sort_order",
"default": "Ascending",
"values": [
2020-05-05 21:09:18 +00:00
{display: tr("Descending"), value: "Descending"},
{display: tr("Ascending"), value: "Ascending"}
2019-10-13 19:33:14 +00:00
]}
]
new_options = []
for each opt in movie_options
o = CreateObject("roSGNode", "OptionsData")
2020-05-05 21:09:18 +00:00
o.title = tr(opt.title)
2019-10-13 19:33:14 +00:00
o.choices = opt.values
2020-05-05 21:09:18 +00:00
o.base_title = tr(opt.base_title)
2019-10-13 19:33:14 +00:00
o.config_key = opt.key
o.value = get_user_setting(opt.key, opt.default)
new_options.append([o])
end for
sidepanel.options = new_options
sidepanel.observeField("closeSidePanel", m.port)
2020-10-24 22:50:07 +00:00
return group
2019-10-12 20:21:34 +00:00
end function
2019-03-07 03:14:52 +00:00
2019-10-13 19:33:14 +00:00
function CreateMovieDetailsGroup(movie)
2019-10-12 20:21:34 +00:00
group = CreateObject("roSGNode", "MovieDetails")
2019-03-12 03:49:17 +00:00
2019-10-12 20:21:34 +00:00
movie = ItemMetaData(movie.id)
group.itemContent = movie
buttons = group.findNode("buttons")
for each b in buttons.getChildren(-1, 0)
b.observeField("buttonSelected", m.port)
2019-03-17 23:07:57 +00:00
end for
2019-10-12 20:21:34 +00:00
return group
end function
2019-03-08 03:47:10 +00:00
2020-06-15 16:05:48 +00:00
function CreateSeriesListGroup(libraryItem)
2019-04-23 03:28:25 +00:00
2020-06-15 16:05:48 +00:00
group = CreateObject("roSGNode", "ItemGrid2")
group.parentItem = libraryItem
2019-03-11 01:24:50 +00:00
2020-06-15 16:05:48 +00:00
group.observeField("selectedItem", m.port)
2019-03-11 01:24:50 +00:00
2020-06-15 16:05:48 +00:00
sidepanel = group.findNode("options")
2019-03-31 03:15:53 +00:00
2019-12-07 02:49:37 +00:00
return group
end function
2019-03-11 01:24:50 +00:00
2019-12-07 02:49:37 +00:00
function CreateSeriesDetailsGroup(series)
group = CreateObject("roSGNode", "TVShowDetails")
2019-03-11 01:24:50 +00:00
2019-12-07 02:49:37 +00:00
group.itemContent = ItemMetaData(series.id)
group.seasonData = TVSeasons(series.id)
2019-03-31 03:15:53 +00:00
2019-12-07 02:49:37 +00:00
group.observeField("seasonSelected", m.port)
2019-04-14 04:47:27 +00:00
2019-12-07 02:49:37 +00:00
return group
end function
2019-04-14 04:47:27 +00:00
2019-12-07 02:49:37 +00:00
function CreateSeasonDetailsGroup(series, season)
group = CreateObject("roSGNode", "TVEpisodes")
2019-04-14 04:47:27 +00:00
2020-02-23 15:45:31 +00:00
group.seasonData = ItemMetaData(season.id).json
2019-12-07 02:49:37 +00:00
group.objects = TVEpisodes(series.id, season.id)
2019-04-14 04:47:27 +00:00
2019-12-07 02:49:37 +00:00
group.observeField("episodeSelected", m.port)
2020-12-08 20:05:22 +00:00
group.observeField("quickPlayNode", m.port)
2019-04-14 04:47:27 +00:00
2019-12-07 02:49:37 +00:00
return group
end function
2019-03-11 01:24:50 +00:00
2020-06-23 16:12:47 +00:00
function CreateCollectionsList(libraryItem)
2019-03-20 02:30:08 +00:00
2020-06-23 16:12:47 +00:00
group = CreateObject("roSGNode", "ItemGrid2")
group.parentItem = libraryItem
2019-10-17 02:40:50 +00:00
2020-06-23 16:12:47 +00:00
group.observeField("selectedItem", m.port)
2020-12-08 09:08:19 +00:00
group.observeField("quickPlayNode", m.port)
2019-10-17 02:40:50 +00:00
2020-06-23 16:12:47 +00:00
sidepanel = group.findNode("options")
2019-10-17 02:40:50 +00:00
return group
end function
2019-03-20 02:30:08 +00:00
2020-05-13 19:36:38 +00:00
function CreateCollectionDetailList(collectionId)
sort_order = get_user_setting("movie_sort_order", "Ascending")
sort_field = get_user_setting("movie_sort_field", "SortName")
item_list = ItemList(collectionId, {
"SortBy": sort_field,
"SortOrder": sort_order
})
group = CreateObject("roSGNode", "CollectionDetail")
group.collectionId = collectionId
group.objects = item_list
group.observeField("selectedItem", m.port)
return group
end function
2020-10-17 19:07:32 +00:00
function CreateChannelList(libraryItem)
group = CreateObject("roSGNode", "ItemGrid2")
group.parentItem = libraryItem
2020-05-13 19:36:38 +00:00
2020-10-17 19:07:32 +00:00
group.observeField("selectedItem", m.port)
2020-05-31 13:46:33 +00:00
sidepanel = group.findNode("options")
return group
end function
2019-10-13 20:52:34 +00:00
function CreateSearchPage()
' Search + Results Page
group = CreateObject("roSGNode", "SearchResults")
2019-03-14 22:50:20 +00:00
2019-10-13 20:52:34 +00:00
search = group.findNode("SearchBox")
search.observeField("search_value", m.port)
2019-03-14 22:50:20 +00:00
2019-10-13 20:52:34 +00:00
options = group.findNode("SearchSelect")
options.observeField("itemSelected", m.port)
2019-03-14 22:50:20 +00:00
2019-10-13 20:52:34 +00:00
return group
end function
2019-03-14 22:50:20 +00:00
2019-10-13 19:33:14 +00:00
function CreateSidePanel(buttons, options)
group = CreateObject("roSGNode", "OptionsSlider")
group.buttons = buttons
group.options = options
end function
2019-10-13 22:10:23 +00:00
function CreatePaginator()
group = CreateObject("roSGNode", "Pager")
group.id = "paginator"
group.observeField("pageSelected", m.port)
return group
end function
2020-10-24 16:23:20 +00:00
function CreateVideoPlayerGroup(video_id, audio_stream_idx = 1)
2019-04-29 16:44:37 +00:00
' Video is Playing
2020-10-24 16:23:20 +00:00
video = VideoPlayer(video_id, audio_stream_idx)
2020-03-04 02:46:26 +00:00
if video = invalid return invalid
2020-02-17 19:30:04 +00:00
timer = video.findNode("playbackTimer")
2019-03-19 00:33:44 +00:00
2019-10-12 21:00:07 +00:00
video.observeField("backPressed", m.port)
2020-03-28 20:04:57 +00:00
video.observeField("selectSubtitlePressed", m.port)
2019-10-12 21:00:07 +00:00
video.observeField("state", m.port)
2020-02-17 19:30:04 +00:00
timer.control = "start"
timer.observeField("fire", m.port)
2019-03-07 03:14:52 +00:00
2019-10-12 21:00:07 +00:00
return video
end function
2019-10-17 02:40:50 +00:00
2019-12-07 02:49:37 +00:00
function SeriesLister(group, page_size)
sort_order = get_user_setting("series_sort_order", "Ascending")
sort_field = get_user_setting("series_sort_field", "SortName")
item_list = ItemList(group.id, {"limit": page_size,
"StartIndex": page_size * (group.pageNumber - 1),
"SortBy": sort_field,
"SortOrder": sort_order,
"IncludeItemTypes": "Series"
})
group.objects = item_list
p = group.findNode("paginator")
p.maxPages = div_ceiling(group.objects.TotalRecordCount, page_size)
end function
2019-10-17 02:40:50 +00:00
function CollectionLister(group, page_size)
sort_order = get_user_setting("boxsets_sort_order", "Ascending")
sort_field = get_user_setting("boxsets_sort_field", "SortName")
item_list = ItemList(group.id, {"limit": page_size,
"StartIndex": page_size * (group.pageNumber - 1),
"SortBy": sort_field,
"SortOrder": sort_order,
})
group.objects = item_list
p = group.findNode("paginator")
p.maxPages = div_ceiling(group.objects.TotalRecordCount, page_size)
2019-10-13 22:10:23 +00:00
end function
2020-05-31 13:46:33 +00:00
function ChannelLister(group, page_size)
sort_order = get_user_setting("channel_sort_order", "Ascending")
sort_field = get_user_setting("channel_sort_field", "SortName")
group.objects = Channels({"limit": page_size,
"StartIndex": page_size * (group.pageNumber - 1),
"SortBy": sort_field,
"SortOrder": sort_order,
})
p = group.findNode("paginator")
p.maxPages = div_ceiling(group.objects.TotalRecordCount, page_size)
end function