local tid = -1; local data = libs.data; ------------------------------------------------------------------------ -- Events ------------------------------------------------------------------------ events.focus = function () host = settings.host; port = settings.port; password = settings.password; if (test()) then update_status(); update_library(); end end events.blur = function () libs.timer.cancel(tid); end function test() -- Verify that Kodi is accessible otherwise show some nice help information local resp = send("JSONRPC.Version"); if (resp == nil) then libs.server.update({ type = "dialog", title = "Kodi Connection", text = "A connection to Kodi could not be established." .. "We recommend using the latest version of Kodi.\n\n" .. "1. Make sure Kodi is running on your computer.\n\n" .. "2. Enable the Webserver in System > Settings > Services > Allow control of Kodi via HTTP\n\n" .. "3. Unified Remote is pre-configured to use port 8080 and no password.\n\n" .. "You may have to restart Kodi after enabling the web interface for the changes to take effect.", children = {{ type = "button", text = "OK" }} }); return false; else return true; end end ------------------------------------------------------------------------ -- Web Request ------------------------------------------------------------------------ function send(method, params) local req = {}; req.jsonrpc = "2.0"; req.id = 1; if (method ~= nil) then req.method = method; end if (params ~= nil) then req.params = params; end -- Send a JSON-RPC request local host = settings.host; local port = settings.port; local url = "http://" .. host .. ":" .. port .. "/jsonrpc"; -- local ok = true; local json = libs.data.tojson(req); local headers = {Authorization = "Basic " .. data.tobase64(settings.username .. ":" .. settings.password)} local ok, resp = pcall(libs.http.request,{ method = "post", url = url, mime = "application/json", headers = headers, content = json }); if (ok and resp ~= nil and resp.status == 200) then return libs.data.fromjson(resp.content); else libs.server.update({ id = "title", text = "[Not Connected]" }); return nil; end end ------------------------------------------------------------------------ -- Status ------------------------------------------------------------------------ function update_status() local pid = player(); if(pid == nil) then layout.title.text = "[Not Playing]"; else local resp = send("Player.GetItem", { playerid = pid }); layout.title.text = resp.result.item.label; end tid = libs.timer.timeout(update_status, 1000); end local stack = {}; local items = {}; local show = 0; local season = 0; local artist = ""; local album = "" function movies(items) local resp = send("VideoLibrary.GetMovies"); if (resp.result.movies ~= nil) then for k,v in pairs(resp.result.movies) do table.insert(items, { text = v.label .. " (" .. v.movieid .. ")", id = v.movieid }); end else empty(items); end end function tvshows(items) local resp = send("VideoLibrary.GetTvShows"); if (resp.result.tvshows ~= nil) then for k,v in pairs(resp.result.tvshows) do table.insert(items, { text = v.label .. " (" .. v.tvshowid .. ")", id = v.tvshowid }); end else empty(items); end end function tvseasons(items) local resp = send("VideoLibrary.GetSeasons", { tvshowid = show }); if (resp.result.seasons ~= nil) then for k,v in pairs(resp.result.seasons) do table.insert(items, { text = v.label, id = k }); end else empty(items); end end function tvepisodes(items) local resp = send("VideoLibrary.GetEpisodes", { tvshowid = show, season = season }); if (resp.result.episodes ~= nil) then for k,v in pairs(resp.result.episodes) do table.insert(items, { text = v.label, id = v.episodeid }); end else empty(items); end end function artists(items) local resp = send("AudioLibrary.GetArtists"); if (resp.result.artists ~= nil) then for k,v in pairs(resp.result.artists) do table.insert(items, { text = v.label, id = v.artistid }); end else empty(items); end end function albums(items) local resp = send("AudioLibrary.GetAlbums"); if (resp.result.albums ~= nil) then for k,v in pairs(resp.result.albums) do table.insert(items, { text = v.label, id = v.albumid }); end else empty(items); end end function songs(items) local resp = send("AudioLibrary.GetSongs", {asdf =asdf}); if (resp.result.songs ~= nil) then for k,v in pairs(resp.result.songs) do table.insert(items, { text = v.label, id = v.songid }); end else empty(items); end end function empty(items) table.insert(items, { text = "Empty" }); end function loading(items) local items = {}; table.insert(items, { type = "item", text = "Loading..." }); libs.server.update({ id = "list", children = items }); end function update_library() loading(items); items = {} local state = ""; if (#stack > 0) then state = stack[#stack]; end if (state == "") then table.insert(items, { text = "Music" }); table.insert(items, { text = "Movies" }); table.insert(items, { text = "TV Shows" }); elseif (state == "Music") then table.insert(items, { text = "Artists" }); table.insert(items, { text = "Albums" }); table.insert(items, { text = "Songs" }); elseif (state == "Artists") then artists(items); elseif (state == "Albums") then albums(items); elseif (state == "Songs") then songs(items); elseif (state == "AlbumSongs") then empty(items); elseif (state == "ArtistSongs") then empty(items); elseif (state == "Movies") then movies(items); elseif (state == "TV Shows") then tvshows(items); elseif (state == "Seasons") then tvseasons(items); elseif (state == "Episodes") then tvepisodes(items); end for k,v in pairs(items) do v.type = "item"; end libs.server.update({ id = "list", children = items }); end actions.library_select = function (i) local state = ""; if (#stack > 0) then state = stack[#stack]; end local text = items[i+1].text; local id = items[i+1].id; if (state == "") then table.insert(stack, text); elseif (state == "Music") then table.insert(stack, text); elseif (state == "Movies") then if (id ~= nil) then print("movie: " .. id); send("Player.Open", { item = { movieid = id } }); end elseif (state == "TV Shows") then if (id ~= nil) then show = id; table.insert(stack, "Seasons"); end elseif (state == "Seasons") then if (id ~= nil) then season = id; table.insert(stack, "Episodes"); end elseif (state == "Episodes") then if (id ~= nil) then send("Player.Open", { item = { episodeid = id } }); end elseif (state == "Artists") then if (id ~= nil) then artist = id; table.insert(stack, "ArtistSongs"); end elseif (state == "Albums") then if (id ~= nil) then album = id; table.insert(stack, "AlbumSongs"); end end update_library(); end actions.library_back = function () if (#stack > 0) then table.remove(stack); update_library(); end end ------------------------------------------------------------------------ -- Actions ------------------------------------------------------------------------ --@help Launch Kodi application actions.launch = function() if OS_WINDOWS then os.start("%programfiles(x86)%\\Kodi\\Kodi.exe"); elseif OS_OSX then os.script("tell application \"Kodi\" to activate"); end end function player () local resp = send("Player.GetActivePlayers"); if(resp == nil) then print("Check your settings for Kodi. Possibly wrong port or password, username"); else if(resp.result[1] == nil) then return nil; else return resp.result[1].playerid; end end end function volume () local resp = send("Application.GetProperties", { properties = { "volume" } }); return resp.result.volume; end function input(key) send("Input." .. key); end --@help Toggle play/pause actions.play_pause = function () send("Player.PlayPause", { playerid = player() }); end --@help Stop playback actions.stop = function () send("Player.Stop", { playerid = player() }); end --@help Play next item actions.next = function () send("Player.GoNext", { playerid = player() }); end --@help Play previous item actions.previous = function () send("Player.GoPrevious", { playerid = player() }); end --@help Rewind actions.rewind = function () send("Player.SetSpeed", { playerid = player(), speed = "decrement" }); end --@help Fast forward actions.forward = function () send("Player.SetSpeed", { playerid = player(), speed = "increment" }); end --@help Set volume level --@param vol:number Volume level (0-100) actions.set_volume = function (vol) if (vol > 100) then vol = 100; end if (vol < 0) then vol = 0; end send("Application.SetVolume", { volume = vol }); end --@help Raise volume actions.volume_up = function () actions.set_volume(volume() + 10); end --@help Lower volume actions.volume_down = function () actions.set_volume(volume() - 10); end --@help Toggle mute volume actions.volume_mute = function () send("Application.SetMute", { mute = "toggle" }); end --@help Navigate left actions.left = function () input("Left"); end --@help Navigate right actions.right = function () input("Right"); end --@help Navigate up actions.up = function () input("Up"); end --@help Navigate down actions.down = function () input("Down"); end --@help Select current item actions.select = function () input("Select"); end --@help Navigate back actions.back = function () input("Back"); end --@help Toggle context menu actions.menu = function () input("ContextMenu"); end --@help Toggle OSD actions.osd = function () input("ShowOSD"); end --@help Navigate home actions.home = function () input("Home"); end --@help Toggle information actions.info = function () input("Info"); end --@help Toggle fullscreen actions.fullscreen = function () send("GUI.SetFullscreen", { fullscreen = "toggle" }); end