diff options
author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2025-05-21 04:49:30 -0700 |
---|---|---|
committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2025-05-21 04:49:30 -0700 |
commit | 48fcfe19baae31c2e1635c911f7383d6d58d2aa1 (patch) | |
tree | 34d88c77352c151378fd47234d25aa59df2e9dbf /main.lua | |
parent | 29e4c12898b232ec7c3af563f27aa1f5638fe0da (diff) | |
download | mpv-iptv-menu-48fcfe19baae31c2e1635c911f7383d6d58d2aa1.tar.gz mpv-iptv-menu-48fcfe19baae31c2e1635c911f7383d6d58d2aa1.tar.xz |
Diffstat (limited to 'main.lua')
-rw-r--r-- | main.lua | 143 |
1 files changed, 38 insertions, 105 deletions
@@ -1,9 +1,10 @@ -- Copyright 2025 David Vazgenovich Shakaryan +local util = require('util') local _downloader = require('downloader') local _xc = require('xc') -local utils = require('mp.utils') +local mp_utils = require('mp.utils') -- font size is in units of osd height, which is scaled to 720 local font_size = 20 @@ -27,6 +28,7 @@ local colours = { local script_name = mp.get_script_name() local script_dir = mp.get_script_directory() + local downloader = _downloader.new() local xc = _xc.new({ server = mp.get_opt('iptv_menu.xc_server'), @@ -59,88 +61,12 @@ local depth = 0 local menus = {} local key_bindings = {} -local function copy_table(t) - local u = {} - for k, v in pairs(t) do - u[k] = v - end - return u -end - -local function reverse(t) - for i = 1, #t/2 do - t[i], t[#t-i+1] = t[#t-i+1], t[i] - end -end - -local function strip(str) - return (str:gsub('^%s*(.-)%s*$', '%1')) -end - -local function utf8_seek(str, pos, n) - local step = n > 0 and 1 or -1 - local test = n > 0 - and function() return pos > #str end - or function() return pos <= 1 end - - while n ~= 0 and not test() do - repeat - pos = pos + step - until test() or bit.band(str:byte(pos), 0xc0) ~= 0x80 - - n = n - step - end - - return pos -end - --- returns table of strings wrapped at width. spaces are not removed, resulting --- in width-1 visible chars; newlines and end of string are handled similarly --- for consistency. words longer than width are not broken. -local function wrap(str, width, cont_width) - local t = {} - local start, stop = 0, 0 - while stop < #str do - local i = str:find('[ \n]', stop + 1) or #str + 1 - if i - start >= width then - t[#t+1] = str:sub(start, stop) - start = stop + 1 - if cont_width then - width = cont_width - end - end - stop = i - if str:byte(stop) == 10 or stop >= #str then - t[#t+1] = str:sub(start, stop - 1) .. ' ' - start = stop + 1 - end - end - - return t -end - -local function read_json_file(fn) - local f = io.open(script_dir .. '/' .. fn, 'r') - if not f then - return {} - end - local json = f:read('*all') - f:close() - return utils.parse_json(json) -end - -local function write_json_file(fn, data) - local f = io.open(script_dir .. '/' .. fn, 'w') - f:write(utils.format_json(data), '\n') - f:close() -end - local update_osd local function get_image_path(url, dl) local path = 'img/' .. url:gsub('%W', '_') - local f = utils.file_info(path) + local f = mp_utils.file_info(path) if f then return path end @@ -198,18 +124,20 @@ local function load_section(section, name) name=name, }) - local tmp = read_json_file(section .. '_categories.json') + local tmp = util.read_json_file( + mp_utils.join_path(script_dir, section .. '_categories.json')) for _, v in ipairs(tmp) do v.section = section v.type = 'group' v.group_type = 'category' v.id = section .. ':category:' .. v.category_id v.parent_id = section .. ':category:' .. v.parent_id - v.name = strip(v.category_name) + v.name = util.strip(v.category_name) add_object(v) end - tmp = read_json_file(section .. '_streams.json') + local tmp = util.read_json_file( + mp_utils.join_path(script_dir, section .. '_streams.json')) for _, v in ipairs(tmp) do v.section = section if v.series_id then @@ -222,7 +150,7 @@ local function load_section(section, name) v.id = section .. ':stream:' .. v.stream_id end v.parent_id = section .. ':category:' .. v.category_id - v.name = strip(v.name) + v.name = util.strip(v.name) add_object(v) end end @@ -243,7 +171,8 @@ local function epg_parse_time(str) end local function load_epg() - local tmp = read_json_file('epg.json') + local tmp = util.read_json_file( + mp_utils.join_path(script_dir, 'epg.json')) for _, v in ipairs(tmp) do local ch = v.channel:lower() local prog = { @@ -285,7 +214,8 @@ local function load_data() load_section('series', 'Series') load_epg() - favourites = read_json_file('favourites.json') + favourites = util.read_json_file( + mp_utils.join_path(script_dir, 'favourites.json')) -- json loading/dumping breaks when the table is empty, so we need a -- dummy value to prevent that if next(favourites) == nil then @@ -440,7 +370,7 @@ local function update_osd_image(path, menu_res) disp = true else - local f = utils.file_info(path) + local f = mp_utils.file_info(path) if f then local cmd = 'magick \'' .. path .. '\'' .. ' -background none' .. @@ -638,12 +568,12 @@ local function toggle_menu_sort() if not menu.sorted_options then menu.orig_options = menu.options - menu.sorted_options = copy_table(menu.options) + menu.sorted_options = util.copy_table(menu.options) sort_options(menu.sorted_options) if menu.search_options then menu.orig_search_options = menu.search_options - menu.sorted_search_options = copy_table( + menu.sorted_search_options = util.copy_table( menu.search_options) sort_options(menu.sorted_search_options) end @@ -718,14 +648,14 @@ local function favourites_group_menu_options(group) path[#path+1] = curr end - obj = copy_table(obj) + obj = util.copy_table(obj) add_programme(obj, time) local c = group_count(obj) if c then obj.info = tostring(c) end if #path > 0 and curr.parent_id == 'root' then - reverse(path) + util.reverse(path) obj.path = path end options[#options+1] = obj @@ -755,7 +685,7 @@ local function series_group_menu_options(series) if info.episodes and info.episodes[season_num] then for i, episode in pairs(info.episodes[season_num]) do episodes[#episodes+1] = { - name=strip(episode.title), + name=util.strip(episode.title), type='stream', stream_type='series', id=series.section .. ':stream:' .. @@ -774,7 +704,7 @@ local function series_group_menu_options(series) group_type='season', id=series.section .. 'series:season:' .. season.id, children=episodes, - name=strip(season.name), + name=util.strip(season.name), info=count, } end @@ -794,7 +724,7 @@ local function group_menu_options(group) local options = {} local time = os.time() for i, v in ipairs(group.children) do - v = copy_table(v) + v = util.copy_table(v) add_programme(v, time) local c = group_count(v) if c then @@ -865,7 +795,8 @@ local function favourite_option() favourites[id] = true end - write_json_file('favourites.json', favourites) + util.write_json_file(mp_utils.join_path(script_dir, 'favourites.json'), + favourites) update_osd() end @@ -930,7 +861,7 @@ local function open_epg_programme(prog) if prog.desc then options[#options+1] = {name=' '} - for _, v in ipairs(wrap(prog.desc, 80)) do + for _, v in ipairs(util.wrap(prog.desc, 80)) do options[#options+1] = {name=v} end end @@ -981,7 +912,7 @@ local function add_info_field(dst, k, v, fmt) return end - local str = strip(tostring(v)) + local str = util.strip(tostring(v)) if fmt then str = string.format(fmt, str) end @@ -990,7 +921,7 @@ local function add_info_field(dst, k, v, fmt) end -- continuation lines are 4 chars shorter and indented with 2 em spaces - for i, v in ipairs(wrap(str, 80, 76)) do + for i, v in ipairs(util.wrap(str, 80, 76)) do if i > 1 then v = '\226\128\131\226\128\131' .. v end @@ -1013,7 +944,7 @@ local function open_option_movie_info(opt) if info.description then options[#options+1] = {name=' '} - for _, v in ipairs(wrap(info.description, 80)) do + for _, v in ipairs(util.wrap(info.description, 80)) do options[#options+1] = {name=v} end end @@ -1112,13 +1043,13 @@ local function search_menu_options_build(options, t, path) t[v.type] = {} end - local v = copy_table(v) + local v = util.copy_table(v) v.path = path t[v.type][#t[v.type]+1] = v -- contents of lazy-loaded groups should not be searchable if v.type == 'group' and not v.lazy then - local path = copy_table(path) + local path = util.copy_table(path) path[#path+1] = v search_menu_options_build( group_menu_options(v), t, path) @@ -1173,7 +1104,7 @@ local function update_search_matches() end if #matches > 0 then - local t = copy_table(v) + local t = util.copy_table(v) t.matches = matches options[#options+1] = t end @@ -1201,7 +1132,7 @@ local function search_input_bs() return end - local pos = utf8_seek(menu.search_text, menu.search_cursor, -1) + local pos = util.utf8_seek(menu.search_text, menu.search_cursor, -1) menu.search_text = menu.search_text:sub(1, pos - 1) .. menu.search_text:sub(menu.search_cursor) menu.search_cursor = pos @@ -1215,8 +1146,8 @@ local function search_input_del() end menu.search_text = menu.search_text:sub(1, menu.search_cursor - 1) .. - menu.search_text:sub( - utf8_seek(menu.search_text, menu.search_cursor, 1)) + menu.search_text:sub(util.utf8_seek( + menu.search_text, menu.search_cursor, 1)) update_search_matches() end @@ -1233,12 +1164,14 @@ end local function search_cursor_left() local menu = menus[depth] - set_search_cursor(utf8_seek(menu.search_text, menu.search_cursor, -1)) + set_search_cursor(util.utf8_seek( + menu.search_text, menu.search_cursor, -1)) end local function search_cursor_right() local menu = menus[depth] - set_search_cursor(utf8_seek(menu.search_text, menu.search_cursor, 1)) + set_search_cursor(util.utf8_seek( + menu.search_text, menu.search_cursor, 1)) end local function search_cursor_start() |