diff options
Diffstat (limited to 'rt.lua')
| -rw-r--r-- | rt.lua | 349 |
1 files changed, 211 insertions, 138 deletions
@@ -29,7 +29,148 @@ local function cache_miss_status_msg(str) } end +local function series_children(series) + local info = ctx.xc:with_opts('get_series_info', series.series_id, + cache_miss_status_msg('Loading series info...')) + if not info or not info.seasons then + return {} + end + + local seasons = {} + for _, season in pairs(info.seasons) do + local episodes = {} + local season_num = tostring(season.season_number) + if info.episodes and info.episodes[season_num] then + for i, episode in pairs(info.episodes[season_num]) do + local epinfo = episode.info or {} + local t = { + name = util.strip(episode.title), + type = 'stream', + stream_type = 'series', + id = series.section .. ':stream:' .. + episode.id, + stream_id = episode.id, + img_url = util.strip_ne( + epinfo.movie_image), + } + t.info_data = { + name = t.name, + cover = t.img_url, + description = epinfo.plot, + releasedate = epinfo.releasedate, + duration = epinfo.duration, + video = epinfo.video, + audio = epinfo.audio, + } + episodes[#episodes+1] = t + end + end + + local count = tostring(#episodes) + local tmp = util.strip_ne(season.episode_count) + if tmp then + count = count .. '/' .. tmp + end + local t = { + type = 'group', + group_type = 'season', + id = series.id .. ':season:' .. season.id, + children = episodes, + name = util.strip(season.name), + info = count, + img_url = util.strip_ne(season.cover_big) or + util.strip_ne(season.cover), + } + t.info_data = { + name = t.name, + cover = t.img_url, + description = season.overview, + releasedate = season.air_date, + num_episodes = count, + } + seasons[#seasons+1] = t + end + + return seasons +end + +local function catalogue_add_section(sect, cats, elems) + ctx.catalogue:add({ + section = sect.id, + type = 'group', + group_type = 'category', + id = sect.id .. ':category:0', + parent_id = 'root', + name = sect.name, + }) + + -- currently, this will not correctly handle subcategories which come + -- before their parent category + for _, v in ipairs(cats) do + ctx.catalogue:add({ + section = sect.id, + type = 'group', + group_type = 'category', + id = sect.id .. ':category:' .. v.category_id, + parent_id = sect.id .. ':category:' .. v.parent_id, + name = util.strip(v.category_name), + }) + end + + for _, v in ipairs(elems) do + local vv = { + section = sect.id, + parent_id = sect.id .. ':category:' .. v.category_id, + name = util.strip(v.name), + } + + if sect.type == 'series' then + vv.type = 'group' + vv.group_type = 'series' + vv.id = sect.id .. ':series:' .. v.series_id + vv.series_id = v.series_id + vv.img_url = util.strip_ne(v.cover) + vv.count = 1 + vv.hide_count = true + vv.children_f = series_children + else + vv.type = 'stream' + vv.id = sect.id .. ':stream:' .. v.stream_id + vv.stream_type = v.stream_type + vv.stream_id = v.stream_id + vv.img_url = util.strip_ne(v.stream_icon) + vv.epg_channel_id = util.strip_ne(v.epg_channel_id) + end + + ctx.catalogue:add(vv) + end +end + function rt.load_data(force) + ctx.catalogue:add({ + type = 'group', + id = 'favourites', + parent_id = 'root', + name = 'Favourites', + count_f = function() + return #state.favourites + end, + children_f = function() + local options = {} + for i, id in ipairs(state.favourites) do + -- missing favourites are displayed so that + -- they can be removed + options[i] = ctx.catalogue:get(id) or + { + id = id, + name = id, + missing = true, + } + end + return options + end, + }) + local arr = { {id = 'live', name = 'Live TV', type = 'live'}, {id = 'movie', name = 'Movies', type = 'vod'}, @@ -56,15 +197,15 @@ function rt.load_data(force) end end, } - for _, v in ipairs(arr) do - sect_str = base_str .. ' » ' .. v.name - v.categories = ctx.xc:with_opts( - 'get_' .. v.type .. '_categories', call_opts) - v.elements = ctx.xc:with_opts( - v.type == 'series' and 'get_series' or - ('get_' .. v.type .. '_streams'), + for _, sect in ipairs(arr) do + sect_str = base_str .. ' » ' .. sect.name + local cats = ctx.xc:with_opts( + 'get_' .. sect.type .. '_categories', call_opts) + local elems = ctx.xc:with_opts( + sect.type == 'series' and 'get_series' or + ('get_' .. sect.type .. '_streams'), call_opts) - ctx.catalogue:load_xc_section(v) + catalogue_add_section(sect, cats, elems) end osd:set_status('Loading EPG...') @@ -257,140 +398,65 @@ local function add_programme(opt, time) end end -local function group_count(group) - if group.children and not group.lazy then - local count = 0 - for _, v in ipairs(group.children) do - if v.type == 'stream' or v.group_type == 'series' then - count = count + 1 - elseif v.type == 'group' then - local c = group_count(v) - if c then - count = count + c - end - end - end - return count - elseif group.id == 'favourites' then - -- not recursive - return #state.favourites - end -end +local menu_option_mt_count = 0 +local menu_option_mt = { + __index = function(t, k) + local v = t._v -local function favourites_group_menu_options(group) - local options = {} - local time = os.time() - for _, id in ipairs(state.favourites) do - local obj = ctx.catalogue:get(id) - if obj then - obj = util.copy_table(obj) - add_programme(obj, time) - local c = group_count(obj) - if c then - obj.info = tostring(c) - end - local path = ctx.catalogue:path_from_root(obj) - if path then - obj.path = path - end - options[#options+1] = obj - else - -- display missing favourites so that they can be - -- removed - options[#options+1] = { - id = id, - name = id, - missing = true, - } - end - end - return options -end + if k == 'info' then + if v.type == 'group' and not v.hide_count then + local c = ctx.catalogue:group_count(v) + local ret = c and tostring(c) or '' + rawset(t, 'info', ret) + return ret + elseif v.epg_channel_id then + if t._info_exp and + osd.redraw_time < + t._info_exp then + return t._info + end -local function series_group_menu_options(series) - local info = ctx.xc:with_opts('get_series_info', series.series_id, - cache_miss_status_msg('Loading series info...')) - if not info or not info.seasons then - return {} - end + local prog = ctx.epg:scheduled_programme( + v.epg_channel_id, + osd.redraw_time) + local ret = prog and prog.title or '' + local exp = prog and prog.stop + + if not prog then + prog = ctx.epg:next_programme( + v.epg_channel_id, + osd.redraw_time) + exp = prog and prog.start + + if not prog then + rawset(t, 'info', ret) + return ret + end + end - local seasons = {} - for _, season in pairs(info.seasons) do - local episodes = {} - local season_num = tostring(season.season_number) - if info.episodes and info.episodes[season_num] then - for i, episode in pairs(info.episodes[season_num]) do - local epinfo = episode.info or {} - local t = { - name = util.strip(episode.title), - type = 'stream', - stream_type = 'series', - id = series.section .. ':stream:' .. - episode.id, - stream_id = episode.id, - img_url = util.strip_ne( - epinfo.movie_image), - } - t.info_data = { - name = t.name, - cover = t.img_url, - description = epinfo.plot, - releasedate = epinfo.releasedate, - duration = epinfo.duration, - video = epinfo.video, - audio = epinfo.audio, - } - episodes[#episodes+1] = t + rawset(t, '_info_exp', exp) + rawset(t, '_info', ret) + return ret end end - local count = tostring(#episodes) - local tmp = util.strip_ne(season.episode_count) - if tmp then - count = count .. '/' .. tmp - end - local t = { - type = 'group', - group_type = 'season', - id = series.id .. ':season:' .. season.id, - children = episodes, - name = util.strip(season.name), - info = count, - img_url = util.strip_ne(season.cover_big) or - util.strip_ne(season.cover), - } - t.info_data = { - name = t.name, - cover = t.img_url, - description = season.overview, - releasedate = season.air_date, - num_episodes = count, - } - seasons[#seasons+1] = t - end - - return seasons -end + return v[k] + end, +} local function group_menu_options(group) - if group.id == 'favourites' then - return favourites_group_menu_options(group) - end - - if group.group_type == 'series' then - return series_group_menu_options(group) - end - local options = {} - local time = os.time() - for i, v in ipairs(group.children) do - v = util.copy_table(v) - add_programme(v, time) - local c = group_count(v) - if c then - v.info = tostring(c) + for i, v in ipairs(ctx.catalogue:group_children(group)) do + local t = setmetatable({_v = v}, menu_option_mt) + + if group.id == 'favourites' then + local path = ctx.catalogue:path_from_root(v) + if path then + t.path = path + end end - options[i] = v + + options[i] = t end return options end @@ -784,12 +850,9 @@ function rt.open_option_info(opt) end local function search_menu_options_build(options, t, path) - local menu = state:menu() - local path = path or {} - for _, v in ipairs(options) do - local v = util.copy_table(v) v.path = path + if v.type == 'group' and v.group_type ~= 'series' then t.categories[#t.categories+1] = v else @@ -797,7 +860,7 @@ local function search_menu_options_build(options, t, path) end -- contents of lazy-loaded groups should not be searchable - if v.type == 'group' and not v.lazy then + if v.type == 'group' and v.children then local path = util.copy_table(path) path[#path+1] = v search_menu_options_build( @@ -808,7 +871,17 @@ end local function search_menu_options(options) local t = {categories = {}, elements = {}} - search_menu_options_build(options, t) + + local opts = {} + for i, v in ipairs(options) do + -- menu options may contain dynamic data that is updated on + -- redraw. using a proxy table instead of copying allows a + -- single update to target both the source and search menus. + opts[i] = setmetatable({}, {__index = v}) + end + + -- empty table is needed to shadow existing path from proxied table + search_menu_options_build(opts, t, {}) -- display categories first local ret = t.categories |
