mirror of
https://github.com/gaitas13/dotfiles.git
synced 2025-12-06 07:15:37 +01:00
changed mpv settings and added ivtc on D key
This commit is contained in:
parent
a1849bbeb4
commit
9b3cc564d2
5 changed files with 844 additions and 37 deletions
|
|
@ -1 +1,2 @@
|
|||
#d script-message cycle-profiles "bwdifdeint;deinterlace-no"
|
||||
#d script-message cycle-profiles "bwdifdeint;deinterlace-no" #only needed if using hwdec that has its own deinterlacer and is not bwdif
|
||||
D vf toggle "pullup,dejudder"
|
||||
|
|
|
|||
421
.config/mpv/scripts/dvd-browser.lua
Normal file
421
.config/mpv/scripts/dvd-browser.lua
Normal file
|
|
@ -0,0 +1,421 @@
|
|||
--[[
|
||||
mpv-dvd-browser
|
||||
|
||||
This script uses the `lsdvd` commandline utility to allow users to view and select titles
|
||||
for DVDs from directly within mpv. The browser is interractive and allows for both playing
|
||||
the selected title, or appending it to the playlist.
|
||||
|
||||
For full documentation see: https://github.com/CogentRedTester/mpv-dvd-browser
|
||||
]]--
|
||||
|
||||
local mp = require 'mp'
|
||||
local msg = require 'mp.msg'
|
||||
local opt = require 'mp.options'
|
||||
local utils = require 'mp.utils'
|
||||
|
||||
local o = {
|
||||
lsdvd = 'lsdvd',
|
||||
|
||||
--path to the dvd device to send to lsdvd, leaving this blank will set the script to
|
||||
--use the --dvd-device option.
|
||||
--It is recommended that this be left blank unless using wsl
|
||||
dvd_device = "",
|
||||
|
||||
--number of titles to display on the screen at once
|
||||
num_entries = 20,
|
||||
|
||||
--by default the player enters an infinite loop, usually of the DVD menu screen, after moving
|
||||
--past the last second of the file. If this option is enabled, then the script will
|
||||
--automatically configure mpv to end playback before entering the loop
|
||||
escape_loop = true,
|
||||
|
||||
--changes default mpv behaviour and loads the first title instead of the longest when
|
||||
--the title isn't specified
|
||||
start_from_first_title = true,
|
||||
|
||||
---------------------
|
||||
--playlist options:
|
||||
---------------------
|
||||
|
||||
--adds the previous and subsequent titles to the playlist when playing a dvd
|
||||
--only does this when there is only one item in the playlist
|
||||
create_playlist = true,
|
||||
|
||||
--when dvd:// (no specified title) is loaded the script will always insert all of the
|
||||
--titles into the playlist, regardless of the playlist length
|
||||
--similar to loading a directory or playlist file
|
||||
treat_root_as_playlist = true,
|
||||
|
||||
------------------------------------------
|
||||
--wsl options for limitted windows support
|
||||
------------------------------------------
|
||||
wsl = false,
|
||||
wsl_password = "",
|
||||
|
||||
--------------
|
||||
--ass options
|
||||
---------------
|
||||
ass_header = "{\\q2\\fs35\\c&00ccff&}",
|
||||
ass_body = "{\\q2\\fs25\\c&Hffffff&}",
|
||||
ass_selected = "{\\c&Hfce788&}",
|
||||
ass_playing = "{\\c&H33ff66&}",
|
||||
ass_footerheader = "{\\c&00ccff&\\fs16}",
|
||||
ass_cursor = "{\\c&00ccff&}",
|
||||
ass_length = "{\\fs20\\c&aaaaaa&}"
|
||||
}
|
||||
|
||||
opt.read_options(o, 'dvd_browser')
|
||||
|
||||
--[[
|
||||
lsdvd returns a JSON object with a number of details about the dvd
|
||||
some notable values are:
|
||||
title = title of the dvd
|
||||
longest_track = longest track on the dvd
|
||||
device = path to the dvd mount point
|
||||
track = array of 'titles'/tracks on the disc
|
||||
length = length of each title
|
||||
ix = numerical id of the title starting from 1
|
||||
chapter = array of chapters in the title
|
||||
num_chapters = length of chapters array (added by me)
|
||||
]]--
|
||||
|
||||
--if the script name includes file_browser, then the script is being loaded
|
||||
--as an addon, and hence we can skip loading several things
|
||||
local STANDALONE = not mp.get_script_name():find("file_browser")
|
||||
|
||||
local list = {}
|
||||
if STANDALONE then
|
||||
package.path = mp.command_native( {"expand-path", "~~/script-modules/?.lua;" } ) .. package.path
|
||||
list = require "scroll-list"
|
||||
|
||||
list.header_style = o.ass_header
|
||||
list.list_style = o.ass_body
|
||||
list.wrapper_style = o.ass_footerheader
|
||||
list.empty_text = "insert DVD"
|
||||
end
|
||||
|
||||
local dvd = {}
|
||||
local state = {
|
||||
playing_disc = false,
|
||||
selected = 1,
|
||||
flag_update = false
|
||||
}
|
||||
|
||||
--automatically match to the current dvd device
|
||||
if (o.dvd_device == "") then
|
||||
mp.observe_property('dvd-device', 'string', function(_, device)
|
||||
if device == "" then device = "/dev/dvd" end
|
||||
o.dvd_device = device
|
||||
|
||||
--we set this to false to force a dvd rescan
|
||||
state.playing_disc = false
|
||||
end)
|
||||
end
|
||||
|
||||
local function get_header_str()
|
||||
local title
|
||||
if dvd == nil then title = ""
|
||||
else title = dvd.title end
|
||||
return '📀 dvd://'..title
|
||||
end
|
||||
|
||||
local function get_line_str(v)
|
||||
return "Title "..(v.ix-1)..o.ass_length.." ["..v.length.."] "..v.num_chapters.." chapters"
|
||||
end
|
||||
|
||||
function list:format_header()
|
||||
self.ass.data = o.ass_header..get_header_str().."\\N ---------------------------------------------------- \\N"
|
||||
end
|
||||
|
||||
--simple function to append to the ass string
|
||||
function list:format_line(i, v)
|
||||
self:append(o.ass_body)
|
||||
|
||||
--the below text contains unicode whitespace characters
|
||||
if i == list.selected then self:append(o.ass_cursor..[[➤\h]]..o.ass_selected)
|
||||
else self:append([[\h\h\h\h]]) end
|
||||
|
||||
--prints the currently-playing icon and style
|
||||
if mp.get_property('filename', "0") == tostring(i-1) then
|
||||
self:append(o.ass_playing)
|
||||
end
|
||||
|
||||
self:append(get_line_str(v))
|
||||
self:newline()
|
||||
end
|
||||
|
||||
--sends a call to lsdvd to read the contents of the disc
|
||||
local function read_disc()
|
||||
msg.verbose('reading contents of ' .. o.dvd_device)
|
||||
|
||||
local args
|
||||
if o.wsl then
|
||||
msg.verbose('wsl compatibility mode enabled')
|
||||
|
||||
--if wsl password is not set then we'll assume the user has mounted manually
|
||||
if o.wsl_password ~= "" then
|
||||
local dvd_device = mp.get_property('dvd-device', ''):gsub([[\]], [[/]])
|
||||
msg.verbose('mounting '..dvd_device..' at '..o.dvd_device)
|
||||
|
||||
mp.command_native({
|
||||
name = 'subprocess',
|
||||
playback_only = false,
|
||||
args = {'wsl', 'echo', o.wsl_password, '|', 'sudo', '-S', 'mount', '-t', 'drvfs', dvd_device, o.dvd_device}
|
||||
})
|
||||
end
|
||||
|
||||
--setting wsl arguments
|
||||
args = {'wsl', o.lsdvd, o.dvd_device, '-Oy', '-c'}
|
||||
else
|
||||
args = {o.lsdvd, o.dvd_device, '-Oy', '-c'}
|
||||
end
|
||||
|
||||
local cmd = mp.command_native({
|
||||
name = 'subprocess',
|
||||
playback_only = false,
|
||||
capture_stdout = true,
|
||||
capture_stderr = true,
|
||||
args = args
|
||||
})
|
||||
|
||||
--making the python string JSON compatible
|
||||
local result = cmd.stdout:gsub("'", '"')
|
||||
result = result:gsub('lsdvd = ', '')
|
||||
dvd = utils.parse_json(result)
|
||||
|
||||
if (not dvd) then
|
||||
msg.error(cmd.stderr)
|
||||
state.playing_disc = false
|
||||
return
|
||||
end
|
||||
msg.trace(utils.to_string(dvd))
|
||||
|
||||
--creating a fallback for the title
|
||||
-- if dvd.title == "unknown" then dvd.title = "dvd://" end
|
||||
|
||||
--making modifications to all the entries
|
||||
for i = 1, #dvd.track do
|
||||
local v = dvd.track[i]
|
||||
|
||||
--saving the chapter count
|
||||
v.num_chapters = #v.chapter
|
||||
|
||||
--modifying the length
|
||||
local l = v.length
|
||||
local lstr = tostring(l)
|
||||
|
||||
--adding the microseconds as is
|
||||
local index = tostring(l):find([[.[^.]*$]])
|
||||
local str
|
||||
if index == 1 then str = "00"
|
||||
else
|
||||
str = tostring(lstr:sub(index+1))
|
||||
str = string.format('%02d', str)
|
||||
end
|
||||
l = math.floor(l)
|
||||
|
||||
local seconds = l%60
|
||||
str = string.format('%02d', seconds) .. '.' .. str
|
||||
l = (l - seconds)/60
|
||||
|
||||
local mins = l%60
|
||||
str = string.format('%02d', mins) .. ':' .. str
|
||||
l = (l-mins)/60
|
||||
|
||||
local hours = l%24
|
||||
str = string.format('%02d', hours) .. ':' .. str
|
||||
|
||||
msg.debug('changing length string for title '..(i-1)..' to '..str)
|
||||
v.length = str
|
||||
end
|
||||
|
||||
state.playing_disc = true
|
||||
list.list = dvd.track
|
||||
end
|
||||
|
||||
--this function updates dvd information and updates the browser
|
||||
local function update()
|
||||
read_disc()
|
||||
list:update()
|
||||
end
|
||||
|
||||
--appends the specified playlist item along with the desired options
|
||||
local function load_dvd_title(title, flag)
|
||||
local i = title.ix-1
|
||||
mp.commandv("loadfile", "dvd://"..i, flag)
|
||||
end
|
||||
|
||||
--handles actions when dvd:// paths are played directly
|
||||
--updates dvd information and inserts disc titles into the playlist
|
||||
local function load_disc()
|
||||
local path = mp.get_property('stream-open-filename', '')
|
||||
|
||||
if path:find('dvd://') ~= 1 then
|
||||
state.playing_disc = false
|
||||
return
|
||||
end
|
||||
msg.verbose('playing dvd')
|
||||
|
||||
--if we have not stopped playing a disc then there's no need to parse the disc again
|
||||
if not state.playing_disc then read_disc() end
|
||||
|
||||
--if we still can't detect a disc then return
|
||||
if (not state.playing_disc) then return end
|
||||
|
||||
--if we successfully loaded info about the disc it's time to do some other stuff:
|
||||
--this code block finds the default title of the disc
|
||||
local curr_title
|
||||
|
||||
--if the user specified a title number we use that
|
||||
if path ~= "dvd://" then
|
||||
--treating whatever comes after "dvd://" as the title number
|
||||
curr_title = tonumber(path:sub(7))
|
||||
|
||||
--if dvd:// was sent and this option is set we set the default ourselves
|
||||
elseif o.start_from_first_title then
|
||||
mp.set_property('stream-open-filename', "dvd://0")
|
||||
curr_title = 0
|
||||
|
||||
--otherwise if just dvd:// was sent we need to find the longest title
|
||||
else
|
||||
curr_title = dvd.longest_track
|
||||
end
|
||||
|
||||
mp.set_property('file-local-options/title', dvd.title.." - Title "..curr_title)
|
||||
|
||||
--if o.create_playlist is false then the function can end here
|
||||
if not o.create_playlist then return end
|
||||
|
||||
--offsetting curr_title by one to account for lua arrays being 1-based
|
||||
curr_title = curr_title+1
|
||||
local length = mp.get_property_number('playlist-count', 1)
|
||||
|
||||
--load files in the playlist under the specified conditions
|
||||
if (path == "dvd://" and o.treat_root_as_playlist) or length == 1 then
|
||||
local pos = mp.get_property_number('playlist-pos', 1)
|
||||
|
||||
--add all of the files to the playlist
|
||||
for i = 1, #dvd.track do
|
||||
if i ~= curr_title then
|
||||
load_dvd_title(dvd.track[i], "append")
|
||||
length = length + 1
|
||||
|
||||
--we need slightly different behaviour when prepending vs appending a playlist entry
|
||||
if (i < curr_title) then
|
||||
mp.commandv("playlist-move", length-1, pos)
|
||||
pos = pos+1
|
||||
elseif (i > curr_title) then
|
||||
mp.commandv("playlist-move", length-1, pos+(i-curr_title))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--if the path is dvd, then we actually need to fully replace this entry in the playlist,
|
||||
--otherwise the whole disc will be added to the playlist again if moving back to this entry
|
||||
if (path == "dvd://") then
|
||||
msg.verbose('replacing dvd:// with playlist')
|
||||
|
||||
load_dvd_title(dvd.track[curr_title], "append")
|
||||
length = length+1
|
||||
mp.commandv('playlist-move', length-1, pos+1)
|
||||
mp.commandv('playlist-remove', 'current')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--opens the currently selected file
|
||||
local function open_file(flag)
|
||||
load_dvd_title(dvd.track[list.selected], flag)
|
||||
|
||||
if flag == 'replace' then
|
||||
list:close()
|
||||
end
|
||||
end
|
||||
|
||||
--opens the browser and declares dynamic keybinds
|
||||
function list:open()
|
||||
self.hidden = false
|
||||
if not state.playing_disc then
|
||||
update()
|
||||
else
|
||||
self:open_list()
|
||||
end
|
||||
self:add_keybinds()
|
||||
end
|
||||
|
||||
list.keybinds = {
|
||||
{"ESC", "exit", function() list:close() end, {}},
|
||||
{"ENTER", "open", function() open_file('replace') end, {}},
|
||||
{"Shift+ENTER", "append_playlist", function() open_file('append') end, {}},
|
||||
{'DOWN', 'scroll_down', function() list:scroll_down() end, {repeatable = true}},
|
||||
{'UP', 'scroll_up', function() list:scroll_up() end, {repeatable = true}},
|
||||
{'Ctrl+r', 'reload', function() read_disc() ; list:update() end, {}}
|
||||
}
|
||||
|
||||
--modifies track length to escape infinite loop
|
||||
if o.escape_loop then
|
||||
mp.add_hook('on_preloaded', 50, function()
|
||||
if mp.get_property("path", ""):find("dvd://") ~= 1 then return end
|
||||
if mp.get_property('end', 'none') ~= 'none' then return end
|
||||
|
||||
local chapters = mp.get_property_native('chapter-list')
|
||||
if not chapters then return end
|
||||
|
||||
local num_chapters = #chapters
|
||||
|
||||
-- occurs if there are no chapters
|
||||
if not chapters[num_chapters] then return end
|
||||
if (mp.get_property_number('duration', 0) - (chapters[num_chapters].time or 0)) > 1 then return end
|
||||
|
||||
msg.verbose('modifying end of the title to escape infinite loop')
|
||||
mp.set_property('file-local-options/end', "#"..num_chapters)
|
||||
end)
|
||||
end
|
||||
|
||||
--if we're playing a disc then read it and modify playlist appropriately
|
||||
mp.add_hook('on_load', 50, load_disc)
|
||||
|
||||
--if these events are disabled then the list gui functions are never called
|
||||
if STANDALONE then
|
||||
mp.observe_property('path', 'string', function(_,path)
|
||||
if state.playing_disc then list:update() end
|
||||
end)
|
||||
|
||||
mp.register_script_message('browse-dvd', function() list:open() end)
|
||||
|
||||
mp.add_key_binding('MENU', 'dvd-browser', function() list:toggle() end)
|
||||
end
|
||||
|
||||
--module functions when loading as file_browser addon
|
||||
local dvd_module = {
|
||||
priority = 50
|
||||
}
|
||||
|
||||
function dvd_module:can_parse(directory)
|
||||
return directory:sub(1,6) == "dvd://" or directory == self.get_dvd_device()
|
||||
end
|
||||
|
||||
function dvd_module:parse()
|
||||
read_disc()
|
||||
local list = {}
|
||||
|
||||
if dvd then
|
||||
for i = 1, #dvd.track do
|
||||
list[i] = {
|
||||
ass = get_line_str(dvd.track[i]),
|
||||
name = tostring(dvd.track[i].ix-1),
|
||||
path = "dvd://"..(dvd.track[i].ix-1),
|
||||
type = "file"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return list, {
|
||||
empty_text = "insert DVD",
|
||||
directory_label = get_header_str(),
|
||||
filtered = true,
|
||||
sorted = true
|
||||
}
|
||||
end
|
||||
|
||||
return dvd_module
|
||||
65
.config/mpv/scripts/dvd_browser.conf
Normal file
65
.config/mpv/scripts/dvd_browser.conf
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#################################################################
|
||||
######### Default configuration file for mpv-dvd-browser ########
|
||||
####### https://github.com/CogentRedTester/mpv-dvd-browser ######
|
||||
#################################################################
|
||||
|
||||
#path to the lsdvd executable
|
||||
#searches the system path by default
|
||||
lsdvd=lsdvd
|
||||
|
||||
#path to the dvd device to send to lsdvd, leaving this blank will set the script to
|
||||
#use the --dvd-device option.
|
||||
#It is recommended that this be left blank unless using wsl
|
||||
dvd_device=
|
||||
|
||||
#number of titles to display on the screen at once
|
||||
num_entries=20
|
||||
|
||||
#by default the player enters an infinite loop, usually of the DVD menu screen, after moving
|
||||
#past the last second of the file. If this option is enabled, then the script will
|
||||
#automatically configure mpv to end playback before entering the loop
|
||||
escape_loop=yes
|
||||
|
||||
#changes default mpv behaviour and loads the first title instead of the longest when
|
||||
#the title isn't specified
|
||||
start_from_first_title=yes
|
||||
|
||||
########################
|
||||
### playlist options ###
|
||||
########################
|
||||
|
||||
#adds the previous and subsequent titles to the playlist when playing a dvd
|
||||
#only does this when there is only one item in the playlist
|
||||
create_playlist=yes
|
||||
|
||||
#when dvd:// (no specified title) is loaded the script will always insert all of the
|
||||
#titles into the playlist, regardless of the playlist length
|
||||
#similar to loading a directory or playlist file
|
||||
treat_root_as_playlist=yes
|
||||
|
||||
##################################################
|
||||
#### wsl options for limitted windows support ####
|
||||
##################################################
|
||||
|
||||
#enable wsl compatibility mode
|
||||
wsl=no
|
||||
|
||||
#your WSL user password for running the `sudo mount` command
|
||||
#leaving this blank will disable the auto-mounting command
|
||||
wsl_password=
|
||||
|
||||
|
||||
###########################################################################################
|
||||
# ass tags to change the look of the menu
|
||||
# For information see: http://docs.aegisub.org/3.2/ASS_Tags/
|
||||
#
|
||||
# It's recommended not to put these in your config file unless you know what you're doing,
|
||||
# otherwise any improvements I make to the default theme will be overwritten
|
||||
###########################################################################################
|
||||
ass_header={\q2\fs35\c&00ccff&}
|
||||
ass_body={\q2\fs25\c&Hffffff&}
|
||||
ass_selected={\c&Hfce788&}
|
||||
ass_playing={\c&H33ff66&}
|
||||
ass_footerheader={\c&00ccff&\fs16}
|
||||
ass_cursor={\c&00ccff&}
|
||||
ass_length={\fs20\c&aaaaaa&}
|
||||
|
|
@ -19,6 +19,7 @@ local ext = {
|
|||
local double_page_check = false
|
||||
local first_start = true
|
||||
local filedims = {}
|
||||
local format = {}
|
||||
local initiated = false
|
||||
local input = ""
|
||||
local jump = false
|
||||
|
|
@ -34,11 +35,11 @@ local opts = {
|
|||
double = false,
|
||||
manga = true,
|
||||
pan_size = 0.05,
|
||||
similar_height_threshold = 50,
|
||||
similar_height_threshold = 200,
|
||||
skip_size = 10,
|
||||
trigger_zone = 0.05,
|
||||
zoom_multiplier = 1,
|
||||
}
|
||||
local lavfi_format = {}
|
||||
local lavfi_scale = {}
|
||||
local similar_height = {}
|
||||
local valid_width = {}
|
||||
|
|
@ -50,25 +51,6 @@ function add_tracks(start, finish)
|
|||
end
|
||||
end
|
||||
|
||||
function calculate_zoom_level(dims, pages)
|
||||
local display_width = mp.get_property_number("display-width")
|
||||
local display_height = mp.get_property_number("display-height")
|
||||
local display_dpi = mp.get_property_number("display-hidpi-scale")
|
||||
|
||||
display_width = display_width / display_dpi
|
||||
display_height = display_height / display_dpi
|
||||
|
||||
dims[0] = tonumber(dims[0])
|
||||
dims[1] = tonumber(dims[1]) * opts.continuous_size
|
||||
|
||||
local scaled_width = display_height/dims[1] * dims[0]
|
||||
if display_width >= opts.continuous_size*scaled_width then
|
||||
return pages
|
||||
else
|
||||
return display_width / scaled_width
|
||||
end
|
||||
end
|
||||
|
||||
function check_aspect_ratio(index)
|
||||
local a = filedims[index]
|
||||
local b = filedims[index+1]
|
||||
|
|
@ -106,6 +88,14 @@ function check_double_page_dims(index)
|
|||
double_page_check = false
|
||||
end
|
||||
|
||||
function check_gray_format(name)
|
||||
if name and string.sub(name, 1, 4) == "gray" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function check_images()
|
||||
local audio = mp.get_property("audio-params")
|
||||
local image = mp.get_property_bool("current-tracks/video/image")
|
||||
|
|
@ -128,6 +118,9 @@ function set_custom_title(last_index)
|
|||
end
|
||||
|
||||
function create_modes()
|
||||
if first_start and not opts.auto_start then
|
||||
return
|
||||
end
|
||||
local index = mp.get_property_number("playlist-pos")
|
||||
local len = mp.get_property_number("playlist-count")
|
||||
local pages
|
||||
|
|
@ -143,7 +136,7 @@ function create_modes()
|
|||
finish = len - 1
|
||||
end
|
||||
add_tracks(index, finish)
|
||||
store_file_dims(index, finish)
|
||||
store_file_props(index, finish)
|
||||
if opts.double then
|
||||
check_double_page_dims(index)
|
||||
set_lavfi_complex_double()
|
||||
|
|
@ -160,7 +153,7 @@ function create_modes()
|
|||
end
|
||||
end
|
||||
|
||||
function store_file_dims(start, finish)
|
||||
function store_file_props(start, finish)
|
||||
local len = mp.get_property_number("playlist-count")
|
||||
local needs_dims = false
|
||||
for i=start, finish do
|
||||
|
|
@ -191,12 +184,21 @@ function store_file_dims(start, finish)
|
|||
dims[0] = width
|
||||
dims[1] = height
|
||||
filedims[i+start] = dims
|
||||
format[i+start] = mp.get_property("track-list/"..tostring(i).."/format-name")
|
||||
-- special case any yuvj formats to avoid ffmpeg deprecation warning spam
|
||||
if format[i+start] and string.sub(format[i+start], 1, 4) == "yuvj" then
|
||||
format[i+start] = string.gsub(format[i+start], "j", "")
|
||||
end
|
||||
end
|
||||
for i=start, finish - 1 do
|
||||
valid_width[i] = check_aspect_ratio(i)
|
||||
if filedims[i][1] ~= filedims[i+1][1] then
|
||||
lavfi_scale[i] = true
|
||||
end
|
||||
if format[i] ~= format[i+1] and check_gray_format(format[i]) or check_gray_format(format[i+1]) then
|
||||
-- if one page is gray, we need to forcibly convert it
|
||||
lavfi_format[i] = check_gray_format(format[i]) and format[i+1] or format[i]
|
||||
end
|
||||
if math.abs(filedims[i][1] - filedims[i+1][1]) < opts.similar_height_threshold then
|
||||
similar_height[i] = true
|
||||
else
|
||||
|
|
@ -232,6 +234,27 @@ function set_lavfi_complex_continuous(arg, finish)
|
|||
local index = mp.get_property_number("playlist-pos")
|
||||
local pages = finish - index
|
||||
local max_width = find_max_width(pages)
|
||||
local has_gray = false
|
||||
local has_color = false
|
||||
local color_format = ""
|
||||
for i=0, pages do
|
||||
if check_gray_format(format[index+i]) then
|
||||
has_gray = true
|
||||
else
|
||||
has_color = true
|
||||
color_format = format[index+i]
|
||||
end
|
||||
end
|
||||
-- if at least one page is color, any gray pages must be converted
|
||||
if has_gray and has_color then
|
||||
for i=0, pages do
|
||||
if check_gray_format(format[index+i]) then
|
||||
local split_format = string.gsub(split[i], "]", "_format]")
|
||||
vstack = vstack..split[i].." format="..color_format.. " "..split_format.."; "
|
||||
split[i] = split_format
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=0, pages do
|
||||
if filedims[index+i][0] ~= max_width then
|
||||
local split_pad = string.gsub(split[i], "]", "_pad]")
|
||||
|
|
@ -245,8 +268,6 @@ function set_lavfi_complex_continuous(arg, finish)
|
|||
vstack = vstack.."vstack=inputs="..tostring(pages + 1).." [vo]"
|
||||
mp.set_property("lavfi-complex", vstack)
|
||||
local index = mp.get_property_number("playlist-pos")
|
||||
local zoom_level = calculate_zoom_level(filedims[index], pages+1)
|
||||
mp.set_property_number("video-zoom", opts.zoom_multiplier * log2(zoom_level))
|
||||
mp.set_property_number("video-pan-y", 0)
|
||||
if upwards then
|
||||
mp.set_property_number("video-align-y", 1)
|
||||
|
|
@ -265,18 +286,26 @@ function set_lavfi_complex_double()
|
|||
end
|
||||
return
|
||||
end
|
||||
local hstack
|
||||
local external_vid = "[vid2]"
|
||||
local hstack = ""
|
||||
local vid1 = "[vid1]"
|
||||
local vid2 = "[vid2]"
|
||||
if lavfi_format[index] then
|
||||
if check_gray_format(format[index]) then
|
||||
hstack = vid1.." format="..lavfi_format[index].." [vid1_format]; "
|
||||
vid1 = "[vid1_format]"
|
||||
else
|
||||
hstack = vid2.." format="..lavfi_format[index].." [vid2_format]; "
|
||||
vid2 = "[vid2_format]"
|
||||
end
|
||||
end
|
||||
if lavfi_scale[index] then
|
||||
external_vid = string.sub(external_vid, 0, 5).."_scale]"
|
||||
hstack = hstack..vid2.." scale="..filedims[index][0].."x"..filedims[index][1]..":flags=lanczos [vid2_scale]; "
|
||||
vid2 = "[vid2_scale]"
|
||||
end
|
||||
if opts.manga then
|
||||
hstack = external_vid.." [vid1] hstack [vo]"
|
||||
hstack = hstack..vid2.." "..vid1.. " hstack [vo]"
|
||||
else
|
||||
hstack = "[vid1] "..external_vid.." hstack [vo]"
|
||||
end
|
||||
if lavfi_scale[index] then
|
||||
hstack = "[vid2] scale="..filedims[index][0].."x"..filedims[index][1]..":flags=lanczos [vid2_scale]; "..hstack
|
||||
hstack = hstack..vid1.." "..vid2.. " hstack [vo]"
|
||||
end
|
||||
mp.set_property("lavfi-complex", hstack)
|
||||
end
|
||||
|
|
@ -631,6 +660,7 @@ function toggle_reader()
|
|||
set_properties()
|
||||
mp.observe_property("playlist-count", number, remove_non_images)
|
||||
mp.osd_message("Manga Reader Started")
|
||||
mp.add_hook("on_preloaded", 50, create_modes)
|
||||
mp.add_key_binding("c", "toggle-continuous-mode", toggle_continuous_mode)
|
||||
mp.add_key_binding("d", "toggle-double-page", toggle_double_page)
|
||||
mp.add_key_binding("m", "toggle-manga-mode", toggle_manga_mode)
|
||||
|
|
@ -642,7 +672,6 @@ function toggle_reader()
|
|||
restore_properties()
|
||||
mp.unobserve_property(check_y_pos)
|
||||
mp.unobserve_property(remove_non_images)
|
||||
mp.set_property_number("video-zoom", 0)
|
||||
mp.set_property_number("video-align-y", 0)
|
||||
mp.set_property_number("video-pan-y", 0)
|
||||
mp.set_property("lavfi-complex", "")
|
||||
|
|
@ -723,7 +752,6 @@ function toggle_continuous_mode()
|
|||
opts.continuous = false
|
||||
mp.unobserve_property(check_y_pos)
|
||||
mp.set_property("lavfi-complex", "")
|
||||
mp.set_property_number("video-zoom", 0)
|
||||
mp.set_property_number("video-align-y", 0)
|
||||
mp.set_property_number("video-pan-y", 0)
|
||||
else
|
||||
|
|
@ -764,7 +792,6 @@ function toggle_manga_mode()
|
|||
mp.commandv("playlist-play-index", index)
|
||||
end
|
||||
|
||||
mp.add_hook("on_preloaded", 50, create_modes)
|
||||
mp.register_event("file-loaded", init)
|
||||
mp.add_key_binding("y", "toggle-reader", toggle_reader)
|
||||
require "mp.options".read_options(opts, "manga-reader")
|
||||
|
|
|
|||
293
.config/mpv/scripts/scroll-list.lua
Normal file
293
.config/mpv/scripts/scroll-list.lua
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
local mp = require 'mp'
|
||||
local scroll_list = {
|
||||
global_style = [[]],
|
||||
header_style = [[{\q2\fs35\c&00ccff&}]],
|
||||
list_style = [[{\q2\fs25\c&Hffffff&}]],
|
||||
wrapper_style = [[{\c&00ccff&\fs16}]],
|
||||
cursor_style = [[{\c&00ccff&}]],
|
||||
selected_style = [[{\c&Hfce788&}]],
|
||||
|
||||
cursor = [[➤\h]],
|
||||
indent = [[\h\h\h\h]],
|
||||
|
||||
num_entries = 16,
|
||||
wrap = false,
|
||||
empty_text = "no entries"
|
||||
}
|
||||
|
||||
--formats strings for ass handling
|
||||
--this function is based on a similar function from https://github.com/mpv-player/mpv/blob/master/player/lua/console.lua#L110
|
||||
function scroll_list.ass_escape(str, replace_newline)
|
||||
if replace_newline == true then replace_newline = "\\\239\187\191n" end
|
||||
|
||||
--escape the invalid single characters
|
||||
str = str:gsub('[\\{}\n]', {
|
||||
-- There is no escape for '\' in ASS (I think?) but '\' is used verbatim if
|
||||
-- it isn't followed by a recognised character, so add a zero-width
|
||||
-- non-breaking space
|
||||
['\\'] = '\\\239\187\191',
|
||||
['{'] = '\\{',
|
||||
['}'] = '\\}',
|
||||
-- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of
|
||||
-- consecutive newlines
|
||||
['\n'] = '\239\187\191\\N',
|
||||
})
|
||||
|
||||
-- Turn leading spaces into hard spaces to prevent ASS from stripping them
|
||||
str = str:gsub('\\N ', '\\N\\h')
|
||||
str = str:gsub('^ ', '\\h')
|
||||
|
||||
if replace_newline then
|
||||
str = str:gsub("\\N", replace_newline)
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
--format and return the header string
|
||||
function scroll_list:format_header_string(str)
|
||||
return str
|
||||
end
|
||||
|
||||
--appends the entered text to the overlay
|
||||
function scroll_list:append(text)
|
||||
if text == nil then return end
|
||||
self.ass.data = self.ass.data .. text
|
||||
end
|
||||
|
||||
--appends a newline character to the osd
|
||||
function scroll_list:newline()
|
||||
self.ass.data = self.ass.data .. '\\N'
|
||||
end
|
||||
|
||||
--re-parses the list into an ass string
|
||||
--if the list is closed then it flags an update on the next open
|
||||
function scroll_list:update()
|
||||
if self.hidden then self.flag_update = true
|
||||
else self:update_ass() end
|
||||
end
|
||||
|
||||
--prints the header to the overlay
|
||||
function scroll_list:format_header()
|
||||
self:append(self.header_style)
|
||||
self:append(self:format_header_string(self.header))
|
||||
self:newline()
|
||||
end
|
||||
|
||||
--formats each line of the list and prints it to the overlay
|
||||
function scroll_list:format_line(index, item)
|
||||
self:append(self.list_style)
|
||||
|
||||
if index == self.selected then self:append(self.cursor_style..self.cursor..self.selected_style)
|
||||
else self:append(self.indent) end
|
||||
|
||||
self:append(item.style)
|
||||
self:append(item.ass)
|
||||
self:newline()
|
||||
end
|
||||
|
||||
--refreshes the ass text using the contents of the list
|
||||
function scroll_list:update_ass()
|
||||
self.ass.data = self.global_style
|
||||
self:format_header()
|
||||
|
||||
if #self.list < 1 then
|
||||
self:append(self.empty_text)
|
||||
self.ass:update()
|
||||
return
|
||||
end
|
||||
|
||||
local start = 1
|
||||
local finish = start+self.num_entries-1
|
||||
|
||||
--handling cursor positioning
|
||||
local mid = math.ceil(self.num_entries/2)+1
|
||||
if self.selected+mid > finish then
|
||||
local offset = self.selected - finish + mid
|
||||
|
||||
--if we've overshot the end of the list then undo some of the offset
|
||||
if finish + offset > #self.list then
|
||||
offset = offset - ((finish+offset) - #self.list)
|
||||
end
|
||||
|
||||
start = start + offset
|
||||
finish = finish + offset
|
||||
end
|
||||
|
||||
--making sure that we don't overstep the boundaries
|
||||
if start < 1 then start = 1 end
|
||||
local overflow = finish < #self.list
|
||||
--this is necessary when the number of items in the dir is less than the max
|
||||
if not overflow then finish = #self.list end
|
||||
|
||||
--adding a header to show there are items above in the list
|
||||
if start > 1 then self:append(self.wrapper_style..(start-1)..' item(s) above\\N\\N') end
|
||||
|
||||
for i=start, finish do
|
||||
self:format_line(i, self.list[i])
|
||||
end
|
||||
|
||||
if overflow then self:append('\\N'..self.wrapper_style..#self.list-finish..' item(s) remaining') end
|
||||
self.ass:update()
|
||||
end
|
||||
|
||||
--moves the selector down the list
|
||||
function scroll_list:scroll_down()
|
||||
if self.selected < #self.list then
|
||||
self.selected = self.selected + 1
|
||||
self:update_ass()
|
||||
elseif self.wrap then
|
||||
self.selected = 1
|
||||
self:update_ass()
|
||||
end
|
||||
end
|
||||
|
||||
--moves the selector up the list
|
||||
function scroll_list:scroll_up()
|
||||
if self.selected > 1 then
|
||||
self.selected = self.selected - 1
|
||||
self:update_ass()
|
||||
elseif self.wrap then
|
||||
self.selected = #self.list
|
||||
self:update_ass()
|
||||
end
|
||||
end
|
||||
|
||||
--moves the selector to the list next page
|
||||
function scroll_list:move_pagedown()
|
||||
if #self.list > self.num_entries then
|
||||
self.selected = self.selected + self.num_entries
|
||||
if self.selected > #self.list then self.selected = #self.list end
|
||||
self:update_ass()
|
||||
end
|
||||
end
|
||||
|
||||
--moves the selector to the list previous page
|
||||
function scroll_list:move_pageup()
|
||||
if #self.list > self.num_entries then
|
||||
self.selected = self.selected - self.num_entries
|
||||
if self.selected < 1 then self.selected = 1 end
|
||||
self:update_ass()
|
||||
end
|
||||
end
|
||||
|
||||
--moves the selector to the list begin
|
||||
function scroll_list:move_begin()
|
||||
if #self.list > 1 then
|
||||
self.selected = 1
|
||||
self:update_ass()
|
||||
end
|
||||
end
|
||||
|
||||
--moves the selector to the list end
|
||||
function scroll_list:move_end()
|
||||
if #self.list > 1 then
|
||||
self.selected = #self.list
|
||||
self:update_ass()
|
||||
end
|
||||
end
|
||||
|
||||
--adds the forced keybinds
|
||||
function scroll_list:add_keybinds()
|
||||
for _,v in ipairs(self.keybinds) do
|
||||
mp.add_forced_key_binding(v[1], 'dynamic/'..self.ass.id..'/'..v[2], v[3], v[4])
|
||||
end
|
||||
end
|
||||
|
||||
--removes the forced keybinds
|
||||
function scroll_list:remove_keybinds()
|
||||
for _,v in ipairs(self.keybinds) do
|
||||
mp.remove_key_binding('dynamic/'..self.ass.id..'/'..v[2])
|
||||
end
|
||||
end
|
||||
|
||||
--opens the list and sets the hidden flag
|
||||
function scroll_list:open_list()
|
||||
self.hidden = false
|
||||
if not self.flag_update then self.ass:update()
|
||||
else self.flag_update = false ; self:update_ass() end
|
||||
end
|
||||
|
||||
--closes the list and sets the hidden flag
|
||||
function scroll_list:close_list()
|
||||
self.hidden = true
|
||||
self.ass:remove()
|
||||
end
|
||||
|
||||
--modifiable function that opens the list
|
||||
function scroll_list:open()
|
||||
if self.hidden then self:add_keybinds() end
|
||||
self:open_list()
|
||||
end
|
||||
|
||||
--modifiable function that closes the list
|
||||
function scroll_list:close()
|
||||
self:remove_keybinds()
|
||||
self:close_list()
|
||||
end
|
||||
|
||||
--toggles the list
|
||||
function scroll_list:toggle()
|
||||
if self.hidden then self:open()
|
||||
else self:close() end
|
||||
end
|
||||
|
||||
--clears the list in-place
|
||||
function scroll_list:clear()
|
||||
local i = 1
|
||||
while self.list[i] do
|
||||
self.list[i] = nil
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
--added alias for ipairs(list.list) for lua 5.1
|
||||
function scroll_list:ipairs()
|
||||
return ipairs(self.list)
|
||||
end
|
||||
|
||||
--append item to the end of the list
|
||||
function scroll_list:insert(item)
|
||||
self.list[#self.list + 1] = item
|
||||
end
|
||||
|
||||
local metatable = {
|
||||
__index = function(t, key)
|
||||
if scroll_list[key] ~= nil then return scroll_list[key]
|
||||
elseif key == "__current" then return t.list[t.selected]
|
||||
elseif type(key) == "number" then return t.list[key] end
|
||||
end,
|
||||
__newindex = function(t, key, value)
|
||||
if type(key) == "number" then rawset(t.list, key, value)
|
||||
else rawset(t, key, value) end
|
||||
end,
|
||||
__scroll_list = scroll_list,
|
||||
__len = function(t) return #t.list end,
|
||||
__ipairs = function(t) return ipairs(t.list) end
|
||||
}
|
||||
|
||||
--creates a new list object
|
||||
function scroll_list:new()
|
||||
local vars
|
||||
vars = {
|
||||
ass = mp.create_osd_overlay('ass-events'),
|
||||
hidden = true,
|
||||
flag_update = true,
|
||||
|
||||
header = "header \\N ----------------------------------------------",
|
||||
list = {},
|
||||
selected = 1,
|
||||
|
||||
keybinds = {
|
||||
{'DOWN', 'scroll_down', function() vars:scroll_down() end, {repeatable = true}},
|
||||
{'UP', 'scroll_up', function() vars:scroll_up() end, {repeatable = true}},
|
||||
{'PGDWN', 'move_pagedown', function() vars:move_pagedown() end, {}},
|
||||
{'PGUP', 'move_pageup', function() vars:move_pageup() end, {}},
|
||||
{'HOME', 'move_begin', function() vars:move_begin() end, {}},
|
||||
{'END', 'move_end', function() vars:move_end() end, {}},
|
||||
{'ESC', 'close_browser', function() vars:close() end, {}}
|
||||
}
|
||||
}
|
||||
return setmetatable(vars, metatable)
|
||||
end
|
||||
|
||||
return scroll_list:new()
|
||||
Loading…
Add table
Reference in a new issue