diff options
Diffstat (limited to 'mpv/lua-modules')
| -rw-r--r-- | mpv/lua-modules/auto-profiles-functions.lua | 122 | ||||
| -rw-r--r-- | mpv/lua-modules/scroll-list.lua | 236 | ||||
| -rw-r--r-- | mpv/lua-modules/user-input-module.lua | 49 |
3 files changed, 407 insertions, 0 deletions
diff --git a/mpv/lua-modules/auto-profiles-functions.lua b/mpv/lua-modules/auto-profiles-functions.lua new file mode 100644 index 0000000..539a84d --- /dev/null +++ b/mpv/lua-modules/auto-profiles-functions.lua @@ -0,0 +1,122 @@ +local utils = require 'mp.utils' +local msg = require 'mp.msg' + +-- Quality levels +local HIGH = "High Quality" +local MID = "Mid Quality" +local LOW = "Low Quality" +-- Platform +local is_linux, is_osx, is_windows = false, false, false +local exec_cache = {} + + +local function exec(process, force_exec) + local key = table.concat(process, " ") + if force_exec or exec_cache[key] == nil or exec_cache[key].error then + local p_ret = utils.subprocess({args = process, playback_only = false}) + exec_cache[key] = p_ret + if p_ret.error and p_ret.error == "init" then + msg.error("executable not found: " .. key) + end + return p_ret + else + return exec_cache[key] + end +end + + +local function get_platform() + local is_linux = false + local is_osx = false + local is_windows = type(package) == 'table' and type(package.config) == 'string' and string.sub(package.config, 1, 1) == '\\' + if not is_windows then + uname = exec({"uname"}) + is_linux = uname.stdout == "Linux\n" + is_osx = uname.stdout == "Darwin\n" + end + return is_linux, is_osx, is_windows +end + + +function on_battery() + if is_osx then + local bat = exec({"/usr/bin/pmset", "-g", "batt"}, true) + return string.match(bat.stdout, "Now drawing from 'Battery Power'") + elseif is_linux then + local res = exec({"/bin/cat", "/sys/class/power_supply/AC0/online"}, true) + return res.stdout == "0\n" + elseif is_windows then + msg.warn("on_battery() not implemented on windows. PRs welcome") + end + msg.warn("assuming AC power") + return false +end + + +-- This is a crude attempt to figure out if a (beefy) dedicated GPU is present. +-- Can't identify the actually used GPU but works when we assume that an existing +-- dedicated GPU can/will be used in case we are drawing power from AC. + -- local r = exec({"lshw", "-C", 'display'}) + -- local r = exec({"nvidia-smi"}) + -- r.stdout = string.lower(r.stdout) + -- return string.find(r.stdout, "amd") ~= nil or string.find(r.stdout, "nvidia") ~= nil + -- return string.find(r.stdout, "mpv") ~= nil +function dedicated_gpu() + if is_osx then + local r = exec({"system_profiler", "SPDisplaysDataType"}) + return string.find(r.stdout, "Chipset Model: Radeon") ~= nil or string.find(r.stdout, "Chipset Model: NVIDIA GeForce") ~= nil + -- Untested + elseif is_linux then + local nv = os.getenv("__NV_PRIME_RENDER_OFFLOAD") + return nv ~= nil + elseif is_windows then + msg.warn("dedicated_gpu() not implemented on windows. PRs welcome") + end + msg.warn("assuming dedicated GPU") + return true +end + + +local function determine_level(width, height, fps) + + if on_battery() then + return LOW + end + + if dedicated_gpu() then + if width > 4096 then + return MID + end + if width > 1920 and fps > 61 then + return MID + end + return HIGH + else + if width > 1919 then + return LOW + end + if fps > 58 then + return LOW + end + return MID + end + + msg.error("could not determine profile") + msg.warn("assuming HIGH") + return HIGH +end + + +local function is_level(level) + return function(width, height, fps) + local l = determine_level(width, height, fps) + return l == level + end +end + + +is_high = is_level(HIGH) +is_mid = is_level(MID) +is_low = is_level(LOW) + +is_linux, is_osx, is_windows = get_platform() diff --git a/mpv/lua-modules/scroll-list.lua b/mpv/lua-modules/scroll-list.lua new file mode 100644 index 0000000..0666f5a --- /dev/null +++ b/mpv/lua-modules/scroll-list.lua @@ -0,0 +1,236 @@ +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 taken from https://github.com/mpv-player/mpv/blob/master/player/lua/console.lua#L110 +function scroll_list.ass_escape(str) + str = str:gsub('\\', '\\\239\187\191') + str = str:gsub('{', '\\{') + str = str:gsub('}', '\\}') + -- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of + -- consecutive newlines + str = str:gsub('\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') + 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.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 + +--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() + self:open_list() + self:add_keybinds() +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}}, + {'ESC', 'close_browser', function() vars:close() end, {}} + } + } + return setmetatable(vars, metatable) +end + +return scroll_list:new() diff --git a/mpv/lua-modules/user-input-module.lua b/mpv/lua-modules/user-input-module.lua new file mode 100644 index 0000000..2c25d42 --- /dev/null +++ b/mpv/lua-modules/user-input-module.lua @@ -0,0 +1,49 @@ +--[[ + This is a module designed to interface with mpv-user-input + https://github.com/CogentRedTester/mpv-user-input + + Loading this script as a module will return a table with two functions to format + requests to get and cancel user-input requests. See the README for details. + + Alternatively, developers can just paste these functions directly into their script, + however this is not recommended as there is no guarantee that the formatting of + these requests will remain the same for future versions of user-input. +]] + +local mp = require 'mp' +local mod = {} + +local name = mp.get_script_name() +local counter = 1 + +-- sends a request to ask the user for input using formatted options provided +-- creates a script message to recieve the response and call fn +function mod.get_user_input(fn, options) + options = options or {} + local response_string = name.."/__user_input_request/"..counter + counter = counter + 1 + + -- create a callback for user-input to respond to + mp.register_script_message(response_string, function(input, err) + mp.unregister_script_message(response_string) + fn(err == "" and input or nil, err) + end) + + -- send the input command + mp.commandv("script-message-to", "user_input", "request-user-input", + response_string, + name .. '/' .. (options.id or ""), -- id code for the request + options.request_text or options.text or (name.." is requesting user input:"), + options.default_input or "", + options.queueable and "1" or "", + options.replace and "1" or "" + ) +end + +-- sends a request to cancel all input requests with the given id +function mod.cancel_user_input(id) + id = name .. '/' .. (id or "") + mp.commandv("script-message-to", "user_input", "cancel-user-input", id) +end + +return mod |
