-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathopen_dialog.lua
359 lines (334 loc) · 14.6 KB
/
open_dialog.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
-- Copyright (c) 2022-2024 dyphire <[email protected]>
-- License: MIT
-- link: https://github.com/dyphire/mpv-scripts
--[[
The script calls up a window in mpv to quickly load the folder/files/iso/clipboard (support url)/other subtitles/other audio tracks/other video tracks.
Usage, add bindings to input.conf:
key script-message-to open_dialog import_folder
key script-message-to open_dialog import_files
key script-message-to open_dialog import_files <type> # vid, aid, sid (video/audio/subtitle track)
key script-message-to open_dialog import_clipboard
key script-message-to open_dialog import_clipboard <type> # vid, aid, sid (video/audio/subtitle track)
key script-message-to open_dialog set_clipboard <text> # text can be mpv properties as ${path}
Also supports open dialog to select folder/files for other scripts.
Scripting Example:
-- open a folder select dialog
mp.commandv('script-message-to', 'open_dialog', 'select_folder', mp.get_script_name())
-- receive the selected folder reply
mp.register_script_message('select_folder_reply', function(folder_path)
if folder_path and folder_path ~= '' then
-- do something with folder_path
end
end)
-- open a xml file select dialog
mp.commandv('script-message-to', 'open_dialog', 'select_files', mp.get_script_name(), 'XML File|*.xml')
-- receive the selected files reply
mp.register_script_message('select_files_reply', function(file_paths)
for i, file_path in ipairs(utils.parse_json(file_paths)) do
-- do something with file_path
end
end)
]]--
local msg = require 'mp.msg'
local utils = require 'mp.utils'
local options = require 'mp.options'
o = {
video_types = '3g2,3gp,asf,avi,f4v,flv,h264,h265,m2ts,m4v,mkv,mov,mp4,mp4v,mpeg,mpg,ogm,ogv,rm,rmvb,ts,vob,webm,wmv,y4m',
audio_types = 'aac,ac3,aiff,ape,au,cue,dsf,dts,flac,m4a,mid,midi,mka,mp3,mp4a,oga,ogg,opus,spx,tak,tta,wav,weba,wma,wv',
image_types = 'apng,avif,bmp,gif,j2k,jp2,jfif,jpeg,jpg,jxl,mj2,png,svg,tga,tif,tiff,webp',
subtitle_types = 'aqt,ass,gsub,idx,jss,lrc,mks,pgs,pjs,psb,rt,sbv,slt,smi,sub,sup,srt,ssa,ssf,ttxt,txt,usf,vt,vtt',
playlist_types = 'm3u,m3u8,pls,cue',
iso_types = 'iso',
}
options.read_options(o)
local function split(input)
local ret = {}
for str in string.gmatch(input, "([^,]+)") do
ret[#ret + 1] = string.format("*.%s", str)
end
return ret
end
-- pre-defined file types
local file_types = {
video = table.concat(split(o.video_types), ';'),
audio = table.concat(split(o.audio_types), ';'),
image = table.concat(split(o.image_types), ';'),
iso = table.concat(split(o.iso_types), ';'),
subtitle = table.concat(split(o.subtitle_types), ';'),
playlist = table.concat(split(o.playlist_types), ';'),
}
local powershell = nil
local function pwsh_check()
local arg = {"cmd", "/c", "pwsh", "--version"}
local res = mp.command_native({name = "subprocess", capture_stdout = true, playback_only = false, args = arg})
if res.status ~= 0 or res.stdout:match("^PowerShell") == nil then
powershell = "powershell"
else
powershell = "pwsh"
end
end
-- https://github.com/mpv-player/mpv/blob/master/etc/mpv-icon-8bit-16x16.png
local mpv_icon_base64 = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACvklEQVQ4y3WTSWhUWRSGv/MmU1UpwYSoFbs0VXFo7IhTowgaJGrEhbYLFw44LNqFjWD3Og3dLsSFLlwILgRbXShuXPRCEcUhEUQRIyZROnGImipRkjhVXr2q9+69LrpSiMOBs7nn8t9z7v8d4esQwKqkVM4MoCtpvrz8edhL61obG+KTf3fEaReRZkFcbfRAaKKLw/6bI7dHO/OA+paAuza1YWvcTRwVpPYbnWEwBT8c23vp1b9ngBDArtSc9tT67bVu8h9BPICmWRl+Xr2YzNwMumx4P/oOQTzP9jam401PnxT6ewEtgCyZtHz2tGT6niDxmpoYew79yoK2FrTWKKXQWtN9tZcTf56mFAQYjJ/7+HLRnbc3+y3ArY817BMkDrDn8G4WtLVw8q+zvBkaRmuN1pp5rT+y8++tlbklXh9r2Ae4FjDBs712gMzsLPNXzkUpxcDdJxz57RgXTl4h8EsopfhpxRx+yKQB8GxvDeBZgGuJ1QQwc1G2+mIYhRT9IhdPXWL/joN0dz1AKcWMef8LWGJlAM+p+B0CtjGmKhCUivgln6BcxC5bRGGE1hqjqxiEgOUARhmVd8TJPu5+Wv20QlBAmYg1m1exdlsbtmujtWaw9wUAyqg8YBwgKoZ+V9KbmB3sf8b9a320rJjDzIXNbNr7C/VTJ1W76rnxiPxgDoBi6HcBkQ1YEsnrKYnUFkGcns4+UtkU63atJpaoqVrZd/M/zh08j1IKgwkejfT+8TYaGZIKTHXL6lfuTiUaD4wPmG6ezoyWNNponve8JPdsqErkq7F8x62R68eB0XGUJwBTlta17misndYhSM13UA7yhdyB26Odp4HXQGkcZQ2Uc8XnA37gX4u5cXEsJ2mJFQNUpKOhD+X3F/pGHnQ8LNy/DAwDpS+XSQAPSAITgQTgfmbZGPAB+AiUx9f6E25gOc5E3m0HAAAAAElFTkSuQmCC"
local function end_file(event)
mp.unregister_event(end_file)
if event["reason"] == "eof" or event["reason"] == "stop" or event["reason"] == "error" then
local bd_device = mp.get_property_native("bluray-device")
local dvd_device = mp.get_property_native("dvd-device")
if event["reason"] == "error" and bd_device and bd_device ~= "" then
loaded_fail = true
else
loaded_fail = false
end
if bd_device then mp.set_property("bluray-device", "") end
if dvd_device then mp.set_property("dvd-device", "") end
end
end
-- open bluray iso or dir
local function open_bluray(path)
mp.set_property('bluray-device', path)
mp.commandv('loadfile', 'bd://')
end
-- open dvd iso or dir
local function open_dvd(path)
mp.set_property('dvd-device', path)
mp.commandv('loadfile', 'dvd://')
end
-- open folder
local function open_folder(path, i)
local fpath, dir = utils.split_path(path)
if utils.file_info(utils.join_path(path, "BDMV")) then
open_bluray(path)
elseif utils.file_info(utils.join_path(path, "VIDEO_TS")) then
open_dvd(path)
elseif dir:upper() == "BDMV" then
open_bluray(fpath)
elseif dir:upper() == "VIDEO_TS" then
open_dvd(fpath)
else
mp.commandv('loadfile', path, i == 1 and 'replace' or 'append')
end
end
-- open files
local function open_files(path, type, i, is_clip)
local ext = string.match(path, "%.([^%.]+)$"):lower()
if file_types['subtitle']:match(ext) then
mp.commandv('sub-add', path, 'cached')
elseif type == 'vid' and (not is_clip or (file_types['video']:match(ext) or file_types['image']:match(ext))) then
mp.commandv('video-add', path, 'cached')
elseif type == 'aid' and (not is_clip or file_types['audio']:match(ext)) then
mp.commandv('audio-add', path, 'cached')
elseif file_types['iso']:match(ext) then
local idle = mp.get_property('idle')
if idle ~= 'yes' then mp.set_property('idle', 'yes') end
mp.register_event("end-file", end_file)
open_bluray(path)
mp.add_timeout(1.0, function()
if idle ~= 'yes' then mp.set_property('idle', idle) end
if loaded_fail then
loaded_fail = false
open_dvd(path)
end
end)
else
mp.commandv('loadfile', path, i == 1 and 'replace' or 'append')
end
end
local function select_folder()
if not powershell then pwsh_check() end
local was_ontop = mp.get_property_native("ontop")
if was_ontop then mp.set_property_native("ontop", false) end
local powershell_script = string.format([[
Add-Type -AssemblyName System.Windows.Forms
$u8 = [System.Text.Encoding]::UTF8
$out = [Console]::OpenStandardOutput()
$TopForm = New-Object System.Windows.Forms.Form
$TopForm.TopMost = $true
$TopForm.ShowInTaskbar = $false
$TopForm.Visible = $false
$IconBytes = [Convert]::FromBase64String("%s")
$IconStream = New-Object IO.MemoryStream($IconBytes, 0, $IconBytes.Length)
$IconStream.Write($IconBytes, 0, $IconBytes.Length)
$TopForm.Icon = [System.Drawing.Icon]::FromHandle((New-Object System.Drawing.Bitmap -Argument $IconStream).GetHIcon())
$folderBrowser = New-Object -TypeName System.Windows.Forms.FolderBrowserDialog
$folderBrowser.RootFolder = "Desktop"
$folderBrowser.ShowNewFolderButton = $true
$result = $folderBrowser.ShowDialog($TopForm)
if ($result -eq "OK") {
$selectedFolder = $folderBrowser.SelectedPath
$u8selectedFolder = $u8.GetBytes("$selectedFolder`n")
$out.Write($u8selectedFolder, 0, $u8selectedFolder.Length)
}
$TopForm.Dispose()
]], mpv_icon_base64)
local res = mp.command_native({
name = 'subprocess',
playback_only = false,
capture_stdout = true,
args = { powershell, '-NoProfile', '-Command', powershell_script },
})
if was_ontop then mp.set_property_native("ontop", true) end
if res.status ~= 0 then
mp.osd_message("Failed to open folder dialog.")
return nil
end
local folder_path = res.stdout:match("(.-)[\r\n]?$") -- Trim any trailing newline
return folder_path
end
local function select_files(filter)
if not powershell then pwsh_check() end
local was_ontop = mp.get_property_native("ontop")
if was_ontop then mp.set_property_native("ontop", false) end
local powershell_script = string.format([[& {
Trap {
Write-Error -ErrorRecord $_
Exit 1
}
Add-Type -AssemblyName System.Windows.Forms
$u8 = [System.Text.Encoding]::UTF8
$out = [Console]::OpenStandardOutput()
$TopForm = New-Object System.Windows.Forms.Form
$TopForm.TopMost = $true
$TopForm.ShowInTaskbar = $false
$TopForm.Visible = $false
$IconBytes = [Convert]::FromBase64String("%s")
$IconStream = New-Object IO.MemoryStream($IconBytes, 0, $IconBytes.Length)
$IconStream.Write($IconBytes, 0, $IconBytes.Length)
$TopForm.Icon = [System.Drawing.Icon]::FromHandle((New-Object System.Drawing.Bitmap -Argument $IconStream).GetHIcon())
$ofd = New-Object System.Windows.Forms.OpenFileDialog
$ofd.Multiselect = $true
$ofd.Filter = "%s"
If ($ofd.ShowDialog($TopForm) -eq $true) {
ForEach ($filename in $ofd.FileNames) {
$u8filename = $u8.GetBytes("$filename`n")
$out.Write($u8filename, 0, $u8filename.Length)
}
}
$TopForm.Dispose()
}]], mpv_icon_base64, filter)
local res = mp.command_native({
name = 'subprocess',
playback_only = false,
capture_stdout = true,
args = { powershell, '-NoProfile', '-Command', powershell_script },
})
if was_ontop then mp.set_property_native("ontop", true) end
local file_paths = {}
if res.status ~= 0 then
mp.osd_message("Failed to open files dialog.")
return file_paths
end
for file_path in string.gmatch(res.stdout, '[^\r\n]+') do
table.insert(file_paths, file_path)
end
return file_paths
end
-- import folder
local function import_folder()
local folder_path = select_folder()
if folder_path and folder_path ~= '' then open_folder(folder_path, 1) end
end
-- import files
local function import_files(type)
local filter = ''
if type == 'vid' then
filter = string.format("Video Files|%s|Image Files|%s", file_types['video'], file_types['image'])
elseif type == 'aid' then
filter = string.format("Audio Files|%s", file_types['audio'])
elseif type == 'sid' then
filter = string.format("Subtitle Files|%s", file_types['subtitle'])
else
filter = string.format("All Files (*.*)|*.*|Video Files|%s|Audio Files|%s|Image Files|%s|ISO Files|%s|Subtitle Files|%s|Playlist Files|%s",
file_types['video'], file_types['audio'], file_types['image'], file_types['iso'], file_types['subtitle'], file_types['playlist'])
end
for i, file_path in ipairs(select_files(filter)) do
open_files(file_path, type, i, false)
end
end
-- Returns a string of UTF-8 text from the clipboard
local function get_clipboard()
if mp.get_property_bool('clipboard-enable', false) then
return mp.get_property('clipboard/text', '')
end
local res = mp.command_native({
name = 'subprocess',
playback_only = false,
capture_stdout = true,
args = { 'powershell', '-NoProfile', '-Command', [[& {
Trap {
Write-Error -ErrorRecord $_
Exit 1
}
$clip = Get-Clipboard -Raw -Format Text -TextFormatType UnicodeText
if (-not $clip) {
$clip = Get-Clipboard -Raw -Format FileDropList
}
$u8clip = [System.Text.Encoding]::UTF8.GetBytes($clip)
[Console]::OpenStandardOutput().Write($u8clip, 0, $u8clip.Length)
}]] }
})
if not res.error then
return res.stdout
end
return ''
end
-- open files from clipboard
local function open_clipboard(path, type, i)
local path = path:gsub("^[\'\"]", ""):gsub("[\'\"]$", ""):gsub('^%s+', ''):gsub('%s+$', '')
if path:find('^%a[%w.+-]-://') then
mp.commandv('loadfile', path, i == 1 and 'replace' or 'append')
else
local meta = utils.file_info(path)
if not meta then
mp.osd_message('Clipboard path is invalid')
msg.warn('Clipboard path is invalid')
elseif meta.is_dir then
open_folder(path, i)
elseif meta.is_file then
open_files(path, type, i, true)
else
mp.osd_message('Clipboard path is invalid')
msg.warn('Clipboard path is invalid')
end
end
end
-- import clipboard
local function import_clipboard(type)
local clip = get_clipboard()
if clip ~= '' then
local i = 0
for path in string.gmatch(clip, '[^\r\n]+') do
i = i + 1
open_clipboard(path, type, i)
end
else
mp.osd_message('Clipboard is empty')
msg.warn('Clipboard is empty')
end
end
-- escapes a string so that it can be inserted into powershell as a string literal
local function escape_powershell(str)
if not str then return '""' end
str = str:gsub('[$"`]', '`%1'):gsub('“', '`%1'):gsub('”', '`%1')
return '"'..str..'"'
end
-- sets the contents of the clipboard to the given string
local function set_clipboard(text)
msg.verbose('setting clipboard text:', text)
if mp.get_property_bool('clipboard-enable', false) then
mp.commandv('set', 'clipboard/text', text)
else
mp.commandv('run', 'powershell', '-NoProfile', '-command', 'set-clipboard', escape_powershell(text))
end
end
mp.register_script_message('import_folder', import_folder)
mp.register_script_message('import_files', import_files)
mp.register_script_message('import_clipboard', import_clipboard)
mp.register_script_message('set_clipboard', set_clipboard)
mp.register_script_message('select_folder', function(script_name)
local folder_path = select_folder()
mp.commandv('script-message-to', script_name, 'select_folder_reply', folder_path)
end)
mp.register_script_message('select_files', function(script_name, filter)
local file_paths = select_files(filter)
mp.commandv('script-message-to', script_name, 'select_files_reply', utils.format_json(file_paths))
end)