summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--catalogue.lua13
-rw-r--r--config.lua22
-rw-r--r--main.lua66
-rw-r--r--rt.lua115
-rw-r--r--rx.lua16
-rw-r--r--xc.lua8
6 files changed, 145 insertions, 95 deletions
diff --git a/catalogue.lua b/catalogue.lua
index 7f83e82..425dc17 100644
--- a/catalogue.lua
+++ b/catalogue.lua
@@ -22,19 +22,20 @@ function mt:get(id)
return self.data[id]
end
-function mt:_ensure_catchall(section_id)
- local id = section_id .. ':category:catchall'
+function mt:_ensure_catchall(src_id, section)
+ local id = src_id .. ':' .. section .. ':cat:catchall'
local entry = self.data[id]
if entry then
return entry
end
return self:add({
- section = section_id,
+ src_id = src_id,
+ section = section,
type = 'group',
- group_type = 'category',
+ group_type = 'cat',
id = id,
- parent_id = section_id .. ':category:0',
+ parent_id = src_id .. ':' .. section .. ':cat:0',
-- non-ascii symbol to sort near end
name = '∗CATCHALL∗',
})
@@ -56,7 +57,7 @@ function mt:add(entry)
-- dump any entries referencing nonexistent categories into a single
-- catchall category
if not parent then
- parent = self:_ensure_catchall(entry.section)
+ parent = self:_ensure_catchall(entry.src_id, entry.section)
entry.parent_id = parent.id
end
diff --git a/config.lua b/config.lua
index 805a47d..c044d57 100644
--- a/config.lua
+++ b/config.lua
@@ -81,22 +81,40 @@ local f = io.open(
mp.command_native(
{'expand-path', '~~/script-opts/' .. script_name .. '.conf'}),
'r')
+config.src_order = {}
+local conf_srcs = {}
if f then
for line in f:lines() do
if #line > 0 then
local k = line:match('^([^=]*)=')
opts[k] = opts[k] or ''
+
+ local src = k:match('^src%.([^.]*)%.')
+ if src and not conf_srcs[src] then
+ config.src_order[#config.src_order+1] = src
+ conf_srcs[src] = true
+ end
end
end
f:close()
end
for k, v in pairs(mp.get_property_native('script-opts')) do
if k:find(script_name .. '-', 1, true) == 1 then
- local pk = k:sub(#script_name + 2)
- opts[pk] = opts[pk] or ''
+ local k = k:sub(#script_name + 2)
+ opts[k] = opts[k] or ''
end
end
mp_options.read_options(opts)
util.unflatten_table(opts, config)
+local cli_srcs = {}
+for src in pairs(config.src or {}) do
+ if not conf_srcs[src] then
+ cli_srcs[#cli_srcs+1] = src
+ end
+end
+table.sort(cli_srcs)
+for _, src in ipairs(cli_srcs) do
+ config.src_order[#config.src_order+1] = src
+end
return config
diff --git a/main.lua b/main.lua
index 090395d..e9010c5 100644
--- a/main.lua
+++ b/main.lua
@@ -16,32 +16,7 @@ local _xc = require('xc')
local mp_utils = require('mp.utils')
local state = _state.new()
-
local downloader = _downloader.new({limit = 5})
-local xc = _xc.new({
- server = config.xc_server,
- user = config.xc_user,
- pass = config.xc_pass,
-})
-xc = cacher.wrap(xc, {
- directory = config.cache_dir,
- prefix = (xc.server:gsub('%W', '_')),
- time = 24*60*60,
- functions = {
- get_live_categories = true,
- get_live_streams = true,
- get_vod_categories = true,
- get_vod_streams = true,
- get_vod_info = true,
- get_series_categories = true,
- get_series = true,
- get_series_info = true,
- get_epg = true,
- },
-})
-
-local catalogue = _catalogue.new()
-local epg = _epg.new()
local osd
local function dl_img(url, path, cb)
@@ -71,10 +46,43 @@ osd = _osd.new({
})
local ctx = {
- catalogue = catalogue,
- epg = epg,
- xc = xc,
+ catalogue = _catalogue.new(),
+ src = {},
+ src_order = {},
}
+for _, v in ipairs(config.src_order) do
+ local src = config.src[v]
+ local xc = _xc.new({
+ url = src.url,
+ user = src.user,
+ pass = src.pass,
+ })
+ xc = cacher.wrap(xc, {
+ directory = config.cache_dir,
+ prefix = (xc.url:gsub('%W', '_')),
+ time = 24*60*60,
+ functions = {
+ get_live_categories = true,
+ get_live_streams = true,
+ get_vod_categories = true,
+ get_vod_streams = true,
+ get_vod_info = true,
+ get_series_categories = true,
+ get_series = true,
+ get_series_info = true,
+ get_epg = true,
+ },
+ })
+
+ ctx.src[v] = {
+ id = v,
+ name = src.name,
+ xc = xc,
+ epg = _epg.new(),
+ }
+ ctx.src_order[#ctx.src_order+1] = v
+end
+
rt.init(state, osd, ctx)
rx.init(state, osd, ctx)
@@ -216,6 +224,6 @@ input.activate(true)
mp.add_timeout(0, function()
rt.load_data()
state.depth = 0
- rt.push_group_menu(catalogue:get('root'))
+ rt.push_group_menu(ctx.catalogue:get('root'))
osd:redraw(state)
end)
diff --git a/rt.lua b/rt.lua
index 6b2c09d..c234415 100644
--- a/rt.lua
+++ b/rt.lua
@@ -4,6 +4,7 @@ local config = require('config')
local input = require('input')
local rx = require('rx')
local util = require('util')
+local _catalogue = require('catalogue')
local rt = {}
@@ -33,16 +34,18 @@ end
local function series_children(series)
return rx.series_children(
series,
- ctx.xc:with_opts('get_series_info', series.series_id,
+ ctx.src[series.src_id].xc:with_opts(
+ 'get_series_info', series.series_id,
cache_miss_status_msg('Loading series info...')))
end
-local function catalogue_add_section(sect, cats, elems)
+local function catalogue_add_section(src_id, sect, cats, elems)
ctx.catalogue:add({
+ src_id = src_id,
section = sect.id,
type = 'group',
- group_type = 'category',
- id = sect.id .. ':category:0',
+ group_type = 'cat',
+ id = src_id .. ':' .. sect.id .. ':cat:0',
parent_id = 'root',
name = sect.name,
})
@@ -51,26 +54,32 @@ local function catalogue_add_section(sect, cats, elems)
-- before their parent category
for _, v in ipairs(cats) do
ctx.catalogue:add({
+ src_id = src_id,
section = sect.id,
type = 'group',
- group_type = 'category',
- id = sect.id .. ':category:' .. v.category_id,
- parent_id = sect.id .. ':category:' .. v.parent_id,
+ group_type = 'cat',
+ id = src_id .. ':' .. sect.id .. ':cat:' ..
+ v.category_id,
+ parent_id = src_id .. ':' .. sect.id .. ':cat:' ..
+ v.parent_id,
name = util.strip(v.category_name),
})
end
for _, v in ipairs(elems) do
local vv = {
+ src_id = src_id,
section = sect.id,
- parent_id = sect.id .. ':category:' .. v.category_id,
+ parent_id = src_id .. ':' .. sect.id .. ':cat:' ..
+ 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.id = src_id .. ':' .. sect.id .. ':series:' ..
+ v.series_id
vv.series_id = v.series_id
vv.img_url = util.strip_ne(v.cover)
vv.count = 1
@@ -78,7 +87,8 @@ local function catalogue_add_section(sect, cats, elems)
vv.children_f = series_children
else
vv.type = 'stream'
- vv.id = sect.id .. ':stream:' .. v.stream_id
+ vv.id = src_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)
@@ -89,35 +99,12 @@ local function catalogue_add_section(sect, cats, elems)
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,
- })
-
+function rt.load_data_src(src, force)
+ local pre = src.name and src.name .. ' | ' or ''
local arr = {
- {id = 'live', name = 'Live TV', type = 'live'},
- {id = 'movie', name = 'Movies', type = 'vod'},
- {id = 'series', name = 'Series', type = 'series'},
+ {id = 'live', name = pre .. 'Channels', type = 'live'},
+ {id = 'movie', name = pre .. 'Movies', type = 'vod'},
+ {id = 'series', name = pre .. 'Series', type = 'series'},
}
local base_str = 'Loading catalogue'
@@ -142,20 +129,50 @@ function rt.load_data(force)
}
for _, sect in ipairs(arr) do
sect_str = base_str .. ' » ' .. sect.name
- local cats = ctx.xc:with_opts(
+ local cats = src.xc:with_opts(
'get_' .. sect.type .. '_categories', call_opts)
- local elems = ctx.xc:with_opts(
+ local elems = src.xc:with_opts(
sect.type == 'series' and 'get_series' or
('get_' .. sect.type .. '_streams'),
call_opts)
- catalogue_add_section(sect, cats, elems)
+ catalogue_add_section(src.id, sect, cats, elems)
end
osd:set_status('Loading EPG...')
osd:redraw(state)
- ctx.epg:load_xc_data(
- ctx.xc:with_opts('get_epg', {force = not not force}))
+ src.epg:load_xc_data(
+ src.xc:with_opts('get_epg', {force = not not force}))
osd:set_status()
+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,
+ })
+
+ for _, v in ipairs(ctx.src_order) do
+ rt.load_data_src(ctx.src[v], force)
+ end
local t = util.read_json_file(config.favourites_file)
state.favourites = t.favourites or {}
@@ -352,7 +369,8 @@ end
local function play_stream(stream)
local url = stream.stream_url or
- ctx.xc:stream_url(stream.stream_type, stream.stream_id)
+ ctx.src[stream.src_id].xc:stream_url(
+ stream.stream_type, stream.stream_id)
if not url then
return
end
@@ -459,7 +477,7 @@ end
local function open_option_channel_epg(opt)
local ch = opt.epg_channel_id:lower()
- local options, idx = rx.menu_options_channel_epg(ch)
+ local options, idx = rx.menu_options_channel_epg(opt.src_id, ch)
if not options then
return
end
@@ -490,13 +508,15 @@ local function open_option_entry_info(title, info)
end
local function open_option_movie_info(opt)
- local info = ctx.xc:with_opts('get_vod_info', opt.stream_id,
+ local info = ctx.src[opt.src_id].xc:with_opts(
+ 'get_vod_info', opt.stream_id,
cache_miss_status_msg('Loading movie info...'))
open_option_entry_info('Movie Info: ' .. opt.name, info)
end
local function open_option_series_info(opt)
- local info = ctx.xc:with_opts('get_series_info', opt.series_id,
+ local info = ctx.src[opt.src_id].xc:with_opts(
+ 'get_series_info', opt.series_id,
cache_miss_status_msg('Loading series info...'))
open_option_entry_info('Series Info: ' .. opt.name, info)
end
@@ -661,7 +681,6 @@ function rt.cancel_search()
return
end
- menu.search_active = false
state.depth = state.depth - 1
osd:dirty()
input.set_mapping('MENU')
diff --git a/rx.lua b/rx.lua
index c509559..d96420f 100644
--- a/rx.lua
+++ b/rx.lua
@@ -30,7 +30,8 @@ function rx.series_children(series, info)
name = util.strip(episode.title),
type = 'stream',
stream_type = 'series',
- id = series.section .. ':stream:' ..
+ id = series.src_id .. ':' ..
+ series.section .. ':stream:' ..
episode.id,
stream_id = episode.id,
img_url = util.strip_ne(
@@ -57,7 +58,9 @@ function rx.series_children(series, info)
local t = {
type = 'group',
group_type = 'season',
- id = series.id .. ':season:' .. season.id,
+ id = series.src_id .. ':' .. series.section ..
+ ':season:' .. series.series_id .. '-' ..
+ season.id,
children = episodes,
name = util.strip(season.name),
info = count,
@@ -95,14 +98,15 @@ local entry_mt = {
return t._info
end
- local prog = ctx.epg:scheduled_programme(
+ local epg = ctx.src[v.src_id].epg
+ local prog = epg:scheduled_programme(
v.epg_channel_id, time)
local ret = prog and prog.title or ''
local exp = prog and prog.stop
rawset(t, 'active_programme', prog)
if not prog then
- prog = ctx.epg:next_programme(
+ prog = epg:next_programme(
v.epg_channel_id, time)
exp = prog and prog.start
end
@@ -266,8 +270,8 @@ local programme_mt = {
end,
}
-function rx.menu_options_channel_epg(ch)
- local progs = ctx.epg:channel_programmes(ch)
+function rx.menu_options_channel_epg(src_id, ch)
+ local progs = ctx.src[src_id].epg:channel_programmes(ch)
if not progs then
return
end
diff --git a/xc.lua b/xc.lua
index e1f37d7..bfac020 100644
--- a/xc.lua
+++ b/xc.lua
@@ -7,7 +7,7 @@ local mt = {}
mt.__index = mt
function xc.new(t)
- assert(t.server)
+ assert(t.url)
assert(t.user)
assert(t.pass)
@@ -16,7 +16,7 @@ end
function mt:get(path, params)
local url =
- self.server .. path ..
+ self.url .. path ..
'?username=' .. self.user ..
'&password=' .. self.pass
for k, v in pairs(params or {}) do
@@ -110,12 +110,12 @@ end
function mt:stream_url(stream_type, stream_id)
if stream_type == 'series' then
- return self.server .. '/series/' ..
+ return self.url .. '/series/' ..
self.user .. '/' ..
self.pass .. '/' ..
stream_id .. '.vod'
else
- return self.server .. '/' ..
+ return self.url .. '/' ..
self.user .. '/' ..
self.pass .. '/' ..
stream_id