diff options
| author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2025-05-16 14:50:50 -0700 | 
|---|---|---|
| committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2025-05-16 14:50:50 -0700 | 
| commit | eec40d039986119f4e39b2c6e43053da549edc8d (patch) | |
| tree | 3ae3e128d6a659f76c3c7690cc13eab7695f4d7c | |
| parent | 11924e092e6b7dce6ed40a31ca11ad55dfe0358a (diff) | |
| download | mpv-iptv-menu-eec40d039986119f4e39b2c6e43053da549edc8d.tar.gz mpv-iptv-menu-eec40d039986119f4e39b2c6e43053da549edc8d.tar.xz | |
add movie details menu
| -rw-r--r-- | main.lua | 145 | 
1 files changed, 129 insertions, 16 deletions
| @@ -86,7 +86,7 @@ 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) +local function wrap(str, width, cont_width)  	local t = {}  	local start, stop = 0, 0  	while stop < #str do @@ -94,6 +94,9 @@ local function wrap(str, width)  		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 @@ -614,6 +617,17 @@ local function get_series_info(series_id)  	return utils.parse_json(json)  end +local function get_vod_info(vod_id) +	local cmd = 'curl -sSfL \'' .. xc_server .. '/player_api.php' .. +		'?username=' .. xc_user .. '&password=' .. xc_pass .. '&' .. +		'action=get_vod_info&vod_id=' .. vod_id .. '\'' +	print('exec: ' .. cmd) +	local fd = io.popen(cmd) +	local json = fd:read('*all') +	fd:close() +	return utils.parse_json(json) +end +  local function series_group_menu_options(series)  	local info = get_series_info(series.series_id) @@ -769,7 +783,7 @@ local function goto_option()  end  local function open_epg_programme(prog) -	options = { +	local options = {  		{name='Title: ' .. prog.title},  		{name='Start: ' .. os.date('%a %d %b %H:%M', prog.start)},  		{name='Stop: ' .. os.date('%a %d %b %H:%M', prog.stop)}, @@ -790,19 +804,7 @@ local function open_epg_programme(prog)  	update_osd()  end -local function open_option_epg() -	local menu = menus[depth] -	local opt = menu.options[menu.cursor] -	if not opt then -		return -	end - -	if menu.type == 'epg' and opt.programme then -		return open_epg_programme(opt.programme) -	elseif not opt.epg_channel_id then -		return -	end - +local function open_option_epg(opt)  	local ch = opt.epg_channel_id:lower()  	if not epg[ch] then  		return @@ -835,6 +837,117 @@ local function open_option_epg()  	set_cursor(curr, {centre=true})  end +local function add_info_field(dst, k, v, fmt) +	if not v then +		return +	end + +	local str = strip(tostring(v)) +	if fmt then +		str = string.format(fmt, str) +	end +	if k then +		str = k .. ': ' .. str +	end + +	-- continuation lines are 4 chars shorter and indented with 2 em spaces +	for i, v in ipairs(wrap(str, 80, 76)) do +		if i > 1 then +			v = '\226\128\131\226\128\131' .. v +		end +		dst[#dst+1] = {name=v} +	end +end + +local function open_option_movie_info(opt) +	local info = get_vod_info(opt.stream_id) +	if not info or not info.info then +		return +	end + +	info = info.info + +	local options = {} +	add_info_field(options, nil, info.name) +	add_info_field(options, 'Directed by', info.director) +	add_info_field(options, 'Starring', info.cast) + +	if info.description then +		options[#options+1] = {name=' '} +		for _, v in ipairs(wrap(info.description, 80)) do +			options[#options+1] = {name=v} +		end +	end + +	local set = {{name=' '}} +	add_info_field(set, 'Genre', info.genre) +	if info.releasedate then +		local y, m, d = info.releasedate:match('(%d+)-(%d+)-(%d+)') +		if y then +			local dt = {year=y, month=m, day=d} +			add_info_field(set, 'Release date', +				os.date('%d %B %Y', os.time(dt))) +		end +	end +	add_info_field(set, 'Running time', info.duration) +	if #set > 1 then +		for _, v in ipairs(set) do +			options[#options+1] = v +		end +	end + +	set = {{name=' '}} +	if info.video then +		if info.video.width and info.video.height then +			local res = info.video.width .. 'x' .. +				info.video.height +			if info.video.display_aspect_ratio then +				res = res .. ' (' .. +					info.video.display_aspect_ratio .. ')' +			end +			add_info_field(set, 'Resolution', res) +		end +		add_info_field(set, 'Video codec', info.video.codec_long_name) +	end +	if info.audio then +		add_info_field(set, 'Audio codec', info.audio.codec_long_name) +	end +	if info.bitrate ~= 0 then +		add_info_field(set, 'Bitrate', info.bitrate, '%s Kbps') +	end +	if #set > 1 then +		for _, v in ipairs(set) do +			options[#options+1] = v +		end +	end + +	push_menu({ +		options=options, +		title='Movie Info: ' .. opt.name, +	}) +	update_osd() + +	if info.cover_big then +		mp.commandv('loadfile', info.cover_big) +	end +end + +local function open_option_info() +	local menu = menus[depth] +	local opt = menu.options[menu.cursor] +	if not opt then +		return +	end + +	if menu.type == 'epg' and opt.programme then +		open_epg_programme(opt.programme) +	elseif opt.epg_channel_id then +		open_option_epg(opt) +	elseif opt.stream_id and opt.stream_type == 'movie' then +		open_option_movie_info(opt) +	end +end +  local function search_menu_options_build(options, t, path)  	local menu = menus[depth]  	local path = path or {} @@ -1067,7 +1180,7 @@ function bind_menu_keys()  	bind_key('ENTER', select_option)  	bind_key('Ctrl+f', favourite_option)  	bind_key('g', goto_option) -	bind_key('?', open_option_epg) +	bind_key('?', open_option_info)  	bind_key('UP', cursor_up, {repeatable=true})  	bind_key('DOWN', cursor_down, {repeatable=true}) | 
