This commit is contained in:
Ren Tatsumoto 2023-06-25 22:23:02 +03:00
parent cc4b51b241
commit 1b816e916e
3 changed files with 186 additions and 149 deletions

53
helpers.lua Normal file
View file

@ -0,0 +1,53 @@
--[[
Copyright: Ren Tatsumoto and contributors
License: GNU GPL, version 3 or later; http://www.gnu.org/licenses/gpl.html
Various helper functions.
]]
local mp = require('mp')
local this = {}
this.is_wayland = function()
return os.getenv('WAYLAND_DISPLAY') ~= nil
end
this.is_win = function()
return mp.get_property('options/vo-mmcss-profile') ~= nil
end
this.is_mac = function()
return mp.get_property('options/macos-force-dedicated-gpu') ~= nil
end
this.notify = function(message, level, duration)
level = level or 'info'
duration = duration or 1
mp.msg[level](message)
mp.osd_message(message, duration)
end
this.subprocess = function(args, stdin)
local command_table = {
name = "subprocess",
playback_only = false,
capture_stdout = true,
capture_stderr = true,
args = args,
stdin_data = (stdin or ""),
}
return mp.command_native(command_table)
end
this.subprocess_async = function(args, on_complete)
local command_table = {
name = "subprocess",
playback_only = false,
capture_stdout = true,
capture_stderr = true,
args = args
}
return mp.command_native_async(command_table, on_complete)
end
return this

83
platform.lua Normal file
View file

@ -0,0 +1,83 @@
--[[
Copyright: Ren Tatsumoto and contributors
License: GNU GPL, version 3 or later; http://www.gnu.org/licenses/gpl.html
OS-related constants and functions.
]]
local h = require('helpers')
local mp = require('mp')
local utils = require('mp.utils')
local this = {}
this.Platform = {
gnu_linux = "gnu_linux",
macos = "macos",
windows = "windows",
}
this.platform = (
h.is_win() and this.Platform.windows
or h.is_mac() and this.Platform.macos
or this.Platform.gnu_linux
)
this.default_video_folder = utils.join_path(
(os.getenv("HOME") or os.getenv("USERPROFILE")),
(this.platform == this.Platform.macos and "Movies" or "Videos")
)
this.default_audio_folder = utils.join_path(
(os.getenv("HOME") or os.getenv('USERPROFILE')),
"Music"
)
this.curl_exe = (this.platform == this.Platform.windows and 'curl.exe' or 'curl')
this.open_utility = (
this.platform == this.Platform.windows and 'explorer.exe'
or this.platform == this.Platform.macos and 'open'
or this.platform == this.Platform.gnu_linux and 'xdg-open'
)
this.open = function(file_or_url)
return mp.commandv('run', this.open_utility, file_or_url)
end
this.clipboard = (function()
local self = {}
if this.platform == this.Platform.windows then
self.clip_exe = "powershell.exe"
self.copy = function(text)
return h.subprocess({ self.clip_exe, '-command', 'Set-Clipboard -Value ' .. text })
end
elseif this.platform == this.Platform.macos then
self.clip_exe = "pbcopy"
self.copy = function(text)
return h.subprocess({ self.clip_exe, }, text)
end
else
self.clip_exe = h.is_wayland() and "wl-copy" or "xclip"
self.copy = function(text)
local handle = io.popen(h.is_wayland() and "wl-copy" or "xclip -i -selection clipboard", 'w')
if handle then
handle:write(text)
handle:close()
return { status = 0 }
else
return { status = 1 }
end
end
end
return self
end)()
this.copy_or_open_url = function(url)
local cb = this.clipboard.copy(url)
if cb.status ~= 0 then
local msg = string.format(
"Failed to copy URL to clipboard, trying to open in browser instead. Make sure %s is installed.",
this.clipboard.clip_exe
)
h.notify(msg, "warn", 4)
this.open(url)
else
h.notify("Done! Copied URL to clipboard.", "info", 2)
end
return cb
end
return this

View file

@ -22,39 +22,19 @@ local mp = require('mp')
local mpopt = require('mp.options') local mpopt = require('mp.options')
local utils = require('mp.utils') local utils = require('mp.utils')
local OSD = require('osd_styler') local OSD = require('osd_styler')
local p = require('platform')
local h = require('helpers')
------------------------------------------------------------ ------------------------------------------------------------
-- System-dependent variables -- System-dependent variables
local os_type
local uname = mp.command_native({
name = "subprocess",
playback_only = false,
capture_stdout = true,
capture_stderr = true,
args = "uname",
}).stdout
if string.find(uname, "MSYS_NT") then
os_type = 'windows'
elseif string.find(uname, "Darwin") then
os_type = 'macos'
else
os_type = 'linux'
end
local open_utility =
os_type == 'windows' and 'explorer.exe' or
os_type == 'macos' and 'open' or
os_type == 'linux' and 'xdg-open'
-- Options can be changed here or in a separate config file. -- Options can be changed here or in a separate config file.
-- Config path: ~/.config/mpv/script-opts/videoclip.conf -- Config path: ~/.config/mpv/script-opts/videoclip.conf
local config = { local config = {
-- absolute paths -- absolute paths
-- relative paths (e.g. ~ for home dir) do NOT work. -- relative paths (e.g. ~ for home dir) do NOT work.
video_folder_path = string.format(os_type == 'macos' and '%s/Movies/' or '%s/Videos/', os.getenv("HOME") or os.getenv('USERPROFILE')), video_folder_path = p.default_video_folder,
audio_folder_path = string.format('%s/Music/', os.getenv("HOME") or os.getenv('USERPROFILE')), audio_folder_path = p.default_audio_folder,
-- The range of the CRF scale is 051, where 0 is lossless, -- The range of the CRF scale is 051, where 0 is lossless,
-- 23 is the default, and 51 is worst quality possible. -- 23 is the default, and 51 is worst quality possible.
-- Insane values like 9999 still work but produce the worst quality. -- Insane values like 9999 still work but produce the worst quality.
@ -151,28 +131,6 @@ local function construct_filename()
return filename return filename
end end
local function subprocess(args, stdin)
local command_table = {
name = "subprocess",
playback_only = false,
capture_stdout = true,
capture_stderr = true,
args = args,
stdin_data = stdin or "",
}
return mp.command_native(command_table)
end
local function subprocess_async(args, on_complete)
local command_table = {
name = "subprocess",
playback_only = false,
capture_stdout = true,
capture_stderr = true,
args = args
}
return mp.command_native_async(command_table, on_complete)
end
local function force_resolution(width, height, clip_fn, ...) local function force_resolution(width, height, clip_fn, ...)
local cached_prefs = { local cached_prefs = {
video_width = config.video_width, video_width = config.video_width,
@ -222,11 +180,34 @@ local function validate_config()
set_encoding_settings() set_encoding_settings()
end end
local function notify(message, level, duration) local function upload_to_catbox(outfile)
level = level or 'info' local endpoint = config.litterbox and 'https://litterbox.catbox.moe/resources/internals/api.php' or 'https://catbox.moe/user/api.php'
duration = duration or 1 h.notify("Uploading to " .. (config.litterbox and "litterbox.catbox.moe..." or "catbox.moe..."), "info", 9999)
mp.msg[level](message)
mp.osd_message(message, duration) -- This uses cURL to send a request to the cat-/litterbox API.
-- cURL is included on Windows 10 and up, most Linux distributions and macOS.
local r = h.subprocess({ -- This is technically blocking, but I don't think it has any real consequences ..?
p.curl_exe, '-s',
'-F', 'reqtype=fileupload',
'-F', 'time=' .. config['litterbox_expire'],
'-F', 'fileToUpload=@"' .. outfile .. '"',
endpoint
})
-- Exit codes in the range [0, 99] are returned by cURL itself.
-- Any other exit code means the shell failed to execute cURL.
if r.status < 0 or r.status > 99 then
h.notify("Error: Failed to upload. Make sure cURL is installed and in your PATH.", "error", 3)
return
elseif r.status ~= 0 then
h.notify("Error: Failed to upload to " .. (config.litterbox and "litterbox.catbox.moe" or "catbox.moe"), "error", 2)
return
end
mp.msg.info("Catbox URL: " .. r.stdout)
-- Copy to clipboard
p.copy_or_open_url(r.stdout)
end end
------------------------------------------------------------ ------------------------------------------------------------
@ -325,12 +306,12 @@ encoder.create_clip = function(clip_type, on_complete)
end end
if not main_menu.timings:validate() then if not main_menu.timings:validate() then
notify("Wrong timings. Aborting.", "warn", 2) h.notify("Wrong timings. Aborting.", "warn", 2)
return return
end end
local clip_filename = construct_filename() local clip_filename = construct_filename()
notify("Please wait...", "info", 9999) h.notify("Please wait...", "info", 9999)
local args local args
local location local location
@ -345,16 +326,16 @@ encoder.create_clip = function(clip_type, on_complete)
local process_result = function(_, ret, _) local process_result = function(_, ret, _)
if ret.status ~= 0 or string.match(ret.stdout, "could not open") then if ret.status ~= 0 or string.match(ret.stdout, "could not open") then
notify(string.format("Error: couldn't create the clip.\nDoes %s exist?", location), "error", 5) h.notify(string.format("Error: couldn't create the clip.\nDoes %s exist?", location), "error", 5)
else else
notify(string.format("Clip saved to %s.", location), "info", 2) h.notify(string.format("Clip saved to %s.", location), "info", 2)
if on_complete then if on_complete then
on_complete(utils.join_path(config.video_folder_path, clip_filename .. config.video_extension)) on_complete(utils.join_path(config.video_folder_path, clip_filename .. config.video_extension))
end end
end end
end end
local result = subprocess_async(args, process_result) h.subprocess_async(args, process_result)
main_menu.timings:reset() main_menu.timings:reset()
end end
@ -419,10 +400,10 @@ main_menu.keybindings = {
{ key = 'c', fn = function() encoder.create_clip('video') end }, { key = 'c', fn = function() encoder.create_clip('video') end },
{ key = 'C', fn = function() force_resolution(1920, -2, encoder.create_clip, 'video') end }, { key = 'C', fn = function() force_resolution(1920, -2, encoder.create_clip, 'video') end },
{ key = 'a', fn = function() encoder.create_clip('audio') end }, { key = 'a', fn = function() encoder.create_clip('audio') end },
{ key = 'x', fn = function() main_menu:upload_catbox() end }, { key = 'x', fn = function() main_menu:create_clip_and_upload_to_catbox() end },
{ key = 'X', fn = function() force_resolution(1920, -2, main_menu.upload_catbox) end }, { key = 'X', fn = function() force_resolution(1920, -2, main_menu.create_clip_and_upload_to_catbox) end },
{ key = 'p', fn = function() pref_menu:open() end }, { key = 'p', fn = function() pref_menu:open() end },
{ key = 'o', fn = function() mp.commandv('run', open_utility, 'https://streamable.com/') end }, { key = 'o', fn = function() p.open('https://streamable.com/') end },
{ key = 'ESC', fn = function() main_menu:close() end }, { key = 'ESC', fn = function() main_menu:close() end },
} }
@ -436,7 +417,7 @@ function main_menu:set_time_sub(property)
local time_pos = mp.get_property_number(string.format("sub-%s", property)) local time_pos = mp.get_property_number(string.format("sub-%s", property))
if time_pos == nil then if time_pos == nil then
notify("Warning: No subtitles visible.", "warn", 2) h.notify("Warning: No subtitles visible.", "warn", 2)
return return
end end
@ -475,88 +456,8 @@ function main_menu:update()
self:overlay_draw(osd:get_text()) self:overlay_draw(osd:get_text())
end end
function main_menu:upload_catbox() function main_menu:create_clip_and_upload_to_catbox()
local endpoint = config.litterbox and 'https://litterbox.catbox.moe/resources/internals/api.php' or 'https://catbox.moe/user/api.php' encoder.create_clip('video', upload_to_catbox)
encoder.create_clip('video',
function(outfile)
notify("Uploading to " .. (config.litterbox and "litterbox.catbox.moe..." or "catbox.moe..."), "info", 9999)
-- This uses cURL to send a request to the cat-/litterbox API.
-- cURL is included on Windows 10 and up, most Linux distributions and macOS.
local r = subprocess({ -- This is technically blocking, but I don't think it has any real consequences ..?
os_type == 'windows' and 'curl.exe' or 'curl', '-s',
'-F', 'reqtype=fileupload',
'-F', 'time=' .. config['litterbox_expire'],
'-F', 'fileToUpload=@"' .. outfile .. '"',
endpoint
})
-- Exit codes in the range [0, 99] are returned by cURL itself.
-- Any other exit code means the shell failed to execute cURL.
if r.status < 0 or r.status > 99 then
notify("Error: Failed to upload. Make sure cURL is installed and in your PATH.", "error", 3)
return
end
if r.status ~= 0 then
notify("Error: Failed to upload to " .. config.litterbox and "litterbox.catbox.moe" or "catbox.moe", "error", 2)
return
end
-- Copy to clipboard
if os_type == 'windows' then
local clipboard_command = {
'powershell.exe', '-command',
'Set-Clipboard -Value ' .. r.stdout
}
local cb = subprocess(clipboard_command)
-- local status = mp.command('run ' .. clipboard_command)
if cb.status ~= 0 then
notify("Failed to copy URL to clipboard, trying to open in browser instead. (Make sure PowerShell is installed)", "warn", 4)
mp.commandv('run', open_utility, r.stdout)
return
end
end
if os_type == 'macos' then
local clipboard_command = {
"pbcopy"
}
local cb = subprocess(clipboard_command, r.stdout)
if cb.status ~= 0 then
notify("Failed to copy URL to clipboard, trying to open in browser instead. (Make sure pbcopy is installed)", "warn", 4)
mp.commandv('run', open_utility, r.stdout)
return
end
end
if os_type == "linux" then
local cb_x11 = string.find(subprocess({
"whereis", "xclip"
}).stdout, "/")
local cb_wayland = string.find(subprocess({
"whereis", "wl-copy"
}).stdout, "/")
if cb_x11 == nil and cb_wayland == nil then
notify("Failed to copy URL to clipboard, trying to open in browser instead.\n(Make sure xclip or wl-clipboard is installed)", "warn", 6)
mp.commandv('run', open_utility, r.stdout)
return
end
if cb_x11 ~= nil then
mp.command("run /bin/sh -c \"echo " .. r.stdout .. " | xclip -sel clip\"")
elseif cb_wayland ~= nil then
mp.command("run wl-copy " .. r.stdout)
end
end
notify("Done! Copied URL to clipboard.", "info", 2)
end
)
end end
------------------------------------------------------------ ------------------------------------------------------------
@ -606,11 +507,11 @@ pref_menu.aud_formats = { 'aac', 'opus', }
pref_menu.litterbox_expirations = { '1h', '12h', '24h', '72h', } pref_menu.litterbox_expirations = { '1h', '12h', '24h', '72h', }
function pref_menu:get_selected_resolution() function pref_menu:get_selected_resolution()
local w = config.video_width return string.format(
local h = config.video_height '%s x %s',
w = w == -2 and 'auto' or w config.video_width == -2 and 'auto' or config.video_width,
h = h == -2 and 'auto' or h config.video_height == -2 and 'auto' or config.video_height
return string.format('%s x %s', w, h) )
end end
function pref_menu:cycle_resolutions() function pref_menu:cycle_resolutions()
@ -733,9 +634,9 @@ function pref_menu:save()
end end
end end
handle:close() handle:close()
notify("Settings saved.", "info", 2) h.notify("Settings saved.", "info", 2)
else else
notify(string.format("Couldn't open %s.", config_filepath), "error", 4) h.notify(string.format("Couldn't open %s.", config_filepath), "error", 4)
end end
end end