From 8d1b98871485609fcca3d398f2681a2d43cf426f Mon Sep 17 00:00:00 2001 From: Brian <18603393+brian6932@users.noreply.github.com> Date: Tue, 8 Apr 2025 04:06:01 -0400 Subject: [PATCH] SmartCopyPaste(_II): Use native `clipboard/text` As of https://github.com/mpv-player/mpv/releases/tag/v0.40.0, there's no need for this hacky and slow design anymore. --- script-opts/SmartCopyPaste.conf | 25 +- script-opts/SmartCopyPaste_II.conf | 35 +- scripts/SmartCopyPaste.lua | 224 ++++-------- scripts/SmartCopyPaste_II.lua | 537 ++++++++++++----------------- 4 files changed, 299 insertions(+), 522 deletions(-) diff --git a/script-opts/SmartCopyPaste.conf b/script-opts/SmartCopyPaste.conf index 1a1eb30..9dd3d44 100644 --- a/script-opts/SmartCopyPaste.conf +++ b/script-opts/SmartCopyPaste.conf @@ -1,27 +1,6 @@ ######----Settings For SmartCopyPaste 3.1----###### ####------Script Settings-----#### -#--auto is for automatic device detection, or manually change to: windows or mac or linux -device=auto - -#--copy command that will be used in Linux. OR write a different command -linux_copy=xclip -silent -selection clipboard -in - -#--paste command that will be used in Linux. OR write a different command -linux_paste=xclip -selection clipboard -o - -#--copy command that will be used in MAC. OR write a different command -mac_copy=pbcopy - -#--paste command that will be used in MAC. OR write a different command -mac_paste=pbpaste - -#--powershell is for using windows powershell to copy. OR write the copy command, e.g:clip -windows_copy=powershell - -#--powershell is for using windows powershell to paste. OR write the paste command -windows_paste=powershell - #--change to 0 so item resumes from the exact position, or decrease the value so that it gives you a little preview before loading the resume point resume_offset=-0.65 @@ -29,7 +8,7 @@ resume_offset=-0.65 osd_messages=yes #--Time seperator that will be shown before the saved time in osd messages -time_seperator= 🕒 +time_seperator= 🕒 #--Prefers to copy filename over filetitle. Select between: local, protocols, all, none. 'local' prefer filenames for videos that are not protocols. 'protocols' will prefer filenames for protocols only. 'all' will prefer filename over filetitle for both protocols and not protocols videos. 'none' will always use filetitle instead of filename prefer_filename_over_title=local @@ -40,7 +19,7 @@ copy_time_method=all #--The time attributes which will be added when copying protocols of specific websites from this list. Additional attributes can be added following the same format. specific_time_attributes=[ ["twitter", "?t=", ""], ["twitch", "?t=", "s"], ["youtube", "&t=", "s"] ] -#--The text that will be copied before the seek time when copying a protocol video from mpv +#--The text that will be copied before the seek time when copying a protocol video from mpv protocols_time_attribute=&t= #--The text that will be copied before the seek time when copying a local video from mpv diff --git a/script-opts/SmartCopyPaste_II.conf b/script-opts/SmartCopyPaste_II.conf index 29303af..d330175 100644 --- a/script-opts/SmartCopyPaste_II.conf +++ b/script-opts/SmartCopyPaste_II.conf @@ -1,27 +1,6 @@ ######----Settings For SmartCopyPaste_II 3.1----###### ####------Script Settings-----#### -#--auto is for automatic device detection, or manually change to: windows or mac or linux -device=auto - -#--copy command that will be used in Linux. OR write a different command -linux_copy=xclip -silent -selection clipboard -in - -#--paste command that will be used in Linux. OR write a different command -linux_paste=xclip -selection clipboard -o - -#--copy command that will be used in MAC. OR write a different command -mac_copy=pbcopy - -#--paste command that will be used in MAC. OR write a different command -mac_paste=pbpaste - -#--powershell is for using windows powershell to copy. OR write the copy command, e.g:clip -windows_copy=powershell - -#--powershell is for using windows powershell to paste. OR write the paste command -windows_paste=powershell - #--Auto run the list when opening mpv and there is no video / file loaded. 'none' for disabled. Or choose between: all, copy, paste, recents, distinct, protocols, fileonly, titleonly, timeonly, keywords. auto_run_list_idle=none @@ -49,7 +28,7 @@ log_paste_running_behavior=timestamp>playlist #--The time attributes which will be added when copying protocols of specific websites from this list. Additional attributes can be added following the same format. specific_time_attributes=[ ["twitter", "?t=", ""], ["twitch", "?t=", "s"], ["youtube", "&t=", "s"] ] -#--The text that will be copied before the seek time when copying a protocol video from mpv +#--The text that will be copied before the seek time when copying a protocol video from mpv protocols_time_attribute=&t= #--The text that will be copied before the seek time when copying a local video from mpv @@ -191,7 +170,7 @@ list_alignment=7 text_time_type=duration #--Time seperator that will be used before the saved time -time_seperator= 🕒 +time_seperator= 🕒 #--The text that indicates there are more items above. \N is for new line. \h is for hard space. list_sliced_prefix=...\h\N\N @@ -221,7 +200,7 @@ text_cursor_scale=50 text_cursor_border=0.7 #--Pre text for highlighted multi-select item -text_highlight_pre_text=✅ +text_highlight_pre_text=✅ #--Search color when in typing mode search_color_typing=ffffaa @@ -251,17 +230,17 @@ header_sort_hide_text=added-asc #--Text to be shown before or after triggered variable in the header header_sort_pre_text= \{ header_sort_after_text=} -header_filter_pre_text= [Filter: +header_filter_pre_text= [Filter: header_filter_after_text=] header_search_pre_text=\h\N\N[Search= header_search_after_text=..] header_highlight_pre_text=✅ header_highlight_after_text= -header_list_duration_pre_text= 🕒 +header_list_duration_pre_text= 🕒 header_list_duration_after_text= -header_list_length_pre_text= 🕒 +header_list_length_pre_text= 🕒 header_list_length_after_text= -header_list_remaining_pre_text= 🕒 +header_list_remaining_pre_text= 🕒 header_list_remaining_after_text= #--Copy seperator that will be shown for copied items in the list diff --git a/scripts/SmartCopyPaste.lua b/scripts/SmartCopyPaste.lua index 41af740..4f403ca 100644 --- a/scripts/SmartCopyPaste.lua +++ b/scripts/SmartCopyPaste.lua @@ -10,13 +10,6 @@ local o = { --Changes are recommended to be made in the script-opts directory. -----Script Settings---- - device = 'auto', --'auto' is for automatic device detection, or manually change to: 'windows' or 'mac' or 'linux' - linux_copy = 'xclip -silent -selection clipboard -in', --copy command that will be used in Linux. OR write a different command - linux_paste = 'xclip -selection clipboard -o', --paste command that will be used in Linux. OR write a different command - mac_copy = 'pbcopy', --copy command that will be used in MAC. OR write a different command - mac_paste = 'pbpaste', --paste command that will be used in MAC. OR write a different command - windows_copy = 'powershell', --'powershell' is for using windows powershell to copy. OR write the copy command, e.g: ' clip' - windows_paste = 'powershell', --'powershell' is for using windows powershell to paste. OR write the paste command resume_offset = -0.65, --change to 0 so item resumes from the exact position, or decrease the value so that it gives you a little preview before loading the resume point osd_messages = true, --true is for displaying osd messages when actions occur. Change to false will disable all osd messages generated from this script time_seperator = ' 🕒 ', --Time seperator that will be shown before the saved time in osd messages @@ -25,7 +18,7 @@ local o = { specific_time_attributes=[[ [ ["twitter", "?t=", ""], ["twitch", "?t=", "s"], ["youtube", "&t=", "s"] ] ]], --The time attributes which will be added when copying protocols of specific websites from this list. Additional attributes can be added following the same format. - protocols_time_attribute = '&t=', --The text that will be copied before the seek time when copying a protocol video from mpv + protocols_time_attribute = '&t=', --The text that will be copied before the seek time when copying a protocol video from mpv local_time_attribute = '&time=', --The text that will be copied before the seek time when copying a local video from mpv pastable_time_attributes=[[ [" | time="] @@ -56,7 +49,7 @@ local o = { paste_subtitles=[[ ["aqt", "gsub", "jss", "sub", "ttxt", "pjs", "psb", "rt", "smi", "slt", "ssf", "srt", "ssa", "ass", "usf", "idx", "vtt"] ]], --add above (after a comma) any extension you want paste to attempt to add as a subtitle file, e.g.:'txt'. Or set it as "" by deleting all defined extension to make paste attempt to add any subtitle. - + -----Time Format Settings----- --in the first parameter, you can define from the available styles: default, hms, hms-full, timestamp, timestamp-concise "default" to show in HH:MM:SS.sss format. "hms" to show in 1h 2m 3.4s format. "hms-full" is the same as hms but keeps the hours and minutes persistent when they are 0. "timestamp" to show the total time as timestamp 123456.700 format. "timestamp-concise" shows the total time in 123456.7 format (shows and hides decimals depending on availability). --in the second parameter, you can define whether to show milliseconds, round them or truncate them. Available options: 'truncate' to remove the milliseconds and keep the seconds. 0 to remove the milliseconds and round the seconds. 1 or above is the amount of milliseconds to display. The default value is 3 milliseconds. @@ -98,7 +91,7 @@ function has_value(tab, val) return true end end - + return false end @@ -110,16 +103,6 @@ for i = 1, #o.specific_time_attributes do end end -if not o.device or o.device == 'auto' then - if os.getenv('windir') ~= nil then - o.device = 'windows' - elseif os.execute '[ -d "/Applications" ]' == 0 and os.execute '[ -d "/Library" ]' == 0 or os.execute '[ -d "/Applications" ]' == true and os.execute '[ -d "/Library" ]' == true then - o.device = 'mac' - else - o.device = 'linux' - end -end - function starts_protocol(tab, val) for index, value in ipairs(tab) do if (val:find(value) == 1) then @@ -138,7 +121,7 @@ function contain_value(tab, val) return true end end - + return false end @@ -152,7 +135,7 @@ function format_time(seconds, sep, decimals, style) return math.floor(a / b), a % b end decimals = decimals == nil and 3 or decimals - + local s = seconds local h, s = divmod(s, 60*60) local m, s = divmod(s, 60) @@ -164,7 +147,7 @@ function format_time(seconds, sep, decimals, style) seconds = math.floor(seconds) end end - + if not style or style == '' or style == 'default' then local second_format = string.format("%%0%d.%df", 2+(decimals > 0 and decimals+1 or 0), decimals) sep = sep and sep or ":" @@ -188,9 +171,9 @@ end function get_path() local path = mp.get_property('path') if not path then return end - + local title = mp.get_property('media-title'):gsub("\"", "") - + if starts_protocol(protocols, path) and o.prefer_filename_over_title == 'protocols' then title = mp.get_property('filename'):gsub("\"", "") elseif not starts_protocol(protocols, path) and o.prefer_filename_over_title == 'local' then @@ -198,7 +181,7 @@ function get_path() elseif o.prefer_filename_over_title == 'all' then title = mp.get_property('filename'):gsub("\"", "") end - + return path, title end @@ -207,9 +190,9 @@ function bind_keys(keys, name, func, opts) mp.add_forced_key_binding(keys, name, func, opts) return end - + for i = 1, #keys do - if i == 1 then + if i == 1 then mp.add_forced_key_binding(keys[i], name, func, opts) else mp.add_forced_key_binding(keys[i], name .. i, func, opts) @@ -217,19 +200,6 @@ function bind_keys(keys, name, func, opts) end end -function handleres(res, args) - if not res.error and res.status == 0 then - return res.stdout - else - msg.error("There was an error getting "..o.device.." clipboard: ") - msg.error(" Status: "..(res.status or "")) - msg.error(" Error: "..(res.error or "")) - msg.error(" stdout: "..(res.stdout or "")) - msg.error("args: "..utils.to_string(args)) - return '' - end -end - function os.capture(cmd) local f = assert(io.popen(cmd, 'r')) local s = assert(f:read('*a')) @@ -286,75 +256,9 @@ function get_time_attribute(target_path) return pre_attribute end - -function get_clipboard() - local clipboard - if o.device == 'linux' then - clipboard = os.capture(o.linux_paste) - return clipboard - elseif o.device == 'windows' then - if o.windows_paste == 'powershell' then - local 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) - }]] - } - return handleres(utils.subprocess({ args = args, cancellable = false }), args) - else - clipboard = os.capture(o.windows_paste) - return clipboard - end - elseif o.device == 'mac' then - clipboard = os.capture(o.mac_paste) - return clipboard - end - return '' -end - - -function set_clipboard(text) - local pipe - if o.device == 'linux' then - pipe = io.popen(o.linux_copy, 'w') - pipe:write(text) - pipe:close() - elseif o.device == 'windows' then - if o.windows_copy == 'powershell' then - local res = utils.subprocess({ args = { - 'powershell', '-NoProfile', '-Command', string.format([[& { - Trap { - Write-Error -ErrorRecord $_ - Exit 1 - } - Add-Type -AssemblyName PresentationCore - [System.Windows.Clipboard]::SetText('%s') - }]], text) - } }) - else - pipe = io.popen(o.windows_copy,'w') - pipe:write(text) - pipe:close() - end - elseif o.device == 'mac' then - pipe = io.popen(o.mac_copy,'w') - pipe:write(text) - pipe:close() - end - return '' -end - function parse_clipboard(text) if not text then return end - + local clip, clip_file, clip_time, pre_attribute local clip_table = {} clip = text @@ -363,7 +267,7 @@ function parse_clipboard(text) for c in clip:gmatch("[^\n\r]+") do --3.2.1# fix for #80 , accidentally additional "+" was added to the gmatch local c_pre_attribute, c_clip_file, c_clip_time, c_clip_extension c = make_raw(c) - + if starts_protocol(protocols, c) then --3.2# handle protocols to allow for space as a seperator for c_protocols in c:gmatch("[^%s]+") do --3.2# loop iterator using space if starts_protocol(protocols, c_protocols) then --3.2# check if it starts with protocols again after a space @@ -375,7 +279,7 @@ function parse_clipboard(text) c_clip_file = string.match(c, '^\"(.*)\"$') else c_clip_file = c_protocols - end + end c_clip_extension = get_extension(c_clip_file) table.insert(clip_table, {c_clip_file, c_clip_time, c_clip_extension}) end @@ -390,7 +294,7 @@ function parse_clipboard(text) else c_clip_file = c end - + c_clip_extension = get_extension(c_clip_file) table.insert(clip_table, {c_clip_file, c_clip_time, c_clip_extension}) end @@ -463,14 +367,14 @@ function copy_specific(action) if o.osd_messages == true then mp.osd_message("Copied:\n"..fileTitle) end - set_clipboard(fileTitle) + mp.set_property_native('clipboard/text', fileTitle) msg.info("Copied the below into clipboard:\n"..fileTitle) end if action == 'path' then if o.osd_messages == true then mp.osd_message("Copied:\n"..filePath) end - set_clipboard(filePath) + mp.set_property_native('clipboard/text', filePath) msg.info("Copied the below into clipboard:\n"..filePath) end if action == 'timestamp' then @@ -479,7 +383,7 @@ function copy_specific(action) if o.osd_messages == true then mp.osd_message("Copied"..o.time_seperator..format_time(video_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end - set_clipboard(pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) + mp.set_property_native('clipboard/text', pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) msg.info('Copied the below into clipboard:\n'..pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) end if action == 'path×tamp' then @@ -488,7 +392,7 @@ function copy_specific(action) if o.osd_messages == true then mp.osd_message("Copied:\n" .. fileTitle .. o.time_seperator .. format_time(video_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end - set_clipboard(filePath..pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) + mp.set_property_native('clipboard/text', filePath..pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) msg.info('Copied the below into clipboard:\n'..filePath..pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) end end @@ -496,7 +400,7 @@ end function trigger_paste_action(action) if not action then return end - + if action == 'load-file' then filePath = clip_file if o.osd_messages == true then @@ -508,14 +412,14 @@ function trigger_paste_action(action) end mp.commandv('loadfile', clip_file) clipboard_pasted = true - + if clip_time ~= nil then msg.info("Pasted the below file into mpv:\n"..clip_file .. format_time(clip_time)) else msg.info("Pasted the below file into mpv:\n"..clip_file) end end - + if action == 'load-subtitle' then if o.osd_messages == true then mp.osd_message("Pasted Subtitle:\n"..clip_file) @@ -523,30 +427,30 @@ function trigger_paste_action(action) mp.commandv('sub-add', clip_file, 'select') msg.info("Pasted the below subtitle into mpv:\n"..clip_file) end - + if action == 'file-seek' then local video_duration = mp.get_property_number('duration') seekTime = clip_time + o.resume_offset - - if seekTime > video_duration then + + if seekTime > video_duration then if o.osd_messages == true then mp.osd_message('Time Paste Exceeds Video Length' .. o.time_seperator .. format_time(clip_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end msg.info("The time pasted exceeds the video length:\n"..format_time(clip_time)) return - end - + end + if (seekTime < 0) then seekTime = 0 end - + if o.osd_messages == true then mp.osd_message('Resumed to Pasted Time' .. o.time_seperator .. format_time(clip_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end mp.commandv('seek', seekTime, 'absolute', 'exact') msg.info("Resumed to the pasted time" .. o.time_seperator .. format_time(clip_time)) end - + if action == 'add-playlist' then if o.osd_messages == true then mp.osd_message('Pasted Into Playlist:\n'..clip_file) @@ -554,28 +458,28 @@ function trigger_paste_action(action) mp.commandv('loadfile', clip_file, 'append-play') msg.info("Pasted the below into playlist:\n"..clip_file) end - + if action == 'error-subtitle' then if o.osd_messages == true then mp.osd_message('Subtitle Paste Requires Running Video:\n'..clip_file) end msg.info('Subtitles can only be pasted if a video is running:\n'..clip_file) end - + if action == 'error-unsupported' then if o.osd_messages == true then mp.osd_message('Paste of this item is unsupported possibly due to configuration:\n'..clip) end msg.info('Failed to paste into mpv, pasted item shown below is unsupported possibly due to configuration:\n'..clip) end - + if action == 'error-missing' then if o.osd_messages == true then mp.osd_message('File Doesn\'t Exist:\n' .. clip_file) end msg.info('The file below doesn\'t seem to exist:\n' .. clip_file) end - + if action == 'error-time' then if o.osd_messages == true then if clip_time ~= nil then @@ -584,28 +488,28 @@ function trigger_paste_action(action) mp.osd_message('Time Paste Requires Running Video') end end - + if clip_time ~= nil then msg.info('Time can only be pasted if a video is running:\n'.. format_time(clip_time)) else msg.info('Time can only be pasted if a video is running') end end - + if action == 'error-missingtime' then if o.osd_messages == true then mp.osd_message('Clipboard does not contain time for seeking:\n'..clip) end msg.info("Clipboard does not contain the time attribute and time for seeking:\n"..clip) end - + if action == 'error-samefile' then if o.osd_messages == true then mp.osd_message('Pasted file is already running:\n'..clip) end msg.info("Pasted file shown below is already running:\n"..clip) end - + if action == 'error-unknown' then if o.osd_messages == true then mp.osd_message('Paste was ignored due to an error:\n'..clip) @@ -623,7 +527,7 @@ function multipaste() if filePath == nil then for i=1, #clip_table do - if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) + if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) or starts_protocol(o.paste_protocols, clip_table[i][1]) then filePath = clip_table[i][1] mp.commandv('loadfile', clip_table[i][1]) @@ -634,7 +538,7 @@ function multipaste() end end end - + if filePath ~= nil then for i=1, #clip_table do if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) @@ -656,7 +560,7 @@ function multipaste() end end end - + local osd_msg = '' if triggered_multipaste[1] == true then if osd_msg ~= '' then osd_msg = osd_msg..'\n' end @@ -669,16 +573,16 @@ function multipaste() if triggered_multipaste[2] == true then if osd_msg ~= '' then osd_msg = osd_msg..'\n' end osd_msg = osd_msg..'Added Into Playlist '..#clip_table - file_ignored_total - file_subtitle_total..' item/s' - end + end if file_ignored_total > 0 then if osd_msg ~= '' then osd_msg = osd_msg..'\n' end osd_msg = osd_msg..'Ignored '..file_ignored_total.. ' Item/s' end - + if osd_msg == '' then osd_msg = 'Pasted Items Ignored or Unable To Append Into Video:\n'..clip end - + if o.osd_messages == true then mp.osd_message(osd_msg) end @@ -692,16 +596,16 @@ function paste() end msg.info("Pasting...") - clip = get_clipboard(clip) + clip = mp.get_property('clipboard/text') if not clip then msg.error('Error: clip is null' .. clip) return end clip, clip_file, clip_time, clip_table = parse_clipboard(clip) - + if #clip_table > 1 then multipaste() else local currentVideoExtension = string.lower(get_extension(clip_file)) if filePath == nil then - if file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) + if file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) or starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('load-file') elseif file_exists(clip_file) and has_value(o.paste_subtitles, currentVideoExtension) then @@ -711,7 +615,7 @@ function paste() elseif not file_exists(clip_file) then trigger_paste_action('error-missing') else - trigger_paste_action('error-unknown') + trigger_paste_action('error-unknown') end else if file_exists(clip_file) and has_value(o.paste_subtitles, currentVideoExtension) then @@ -734,7 +638,7 @@ function paste() elseif o.running_paste_behavior == 'timestamp' then if clip_time ~= nil then trigger_paste_action('file-seek') - elseif file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) + elseif file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) or starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('add-playlist') elseif not has_value(o.paste_extensions, currentVideoExtension) and not has_value(o.paste_subtitles, currentVideoExtension) then @@ -745,12 +649,12 @@ function paste() trigger_paste_action('error-unknown') end elseif o.running_paste_behavior == 'force' then - if filePath ~= clip_file and file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) + if filePath ~= clip_file and file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) or filePath ~= clip_file and starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('load-file') elseif clip_time ~= nil then trigger_paste_action('file-seek') - elseif file_exists(clip_file) and filePath == clip_file + elseif file_exists(clip_file) and filePath == clip_file or filePath == clip_file and starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('add-playlist') elseif not has_value(o.paste_extensions, currentVideoExtension) and not has_value(o.paste_subtitles, currentVideoExtension) then @@ -768,16 +672,16 @@ end function paste_specific(action) if not action then return end - + if o.osd_messages == true then mp.osd_message("Pasting...") end msg.info("Pasting...") - - clip = get_clipboard(clip) + + clip = mp.get_property('clipboard/text') if not clip then msg.error('Error: clip is null' .. clip) return end clip, clip_file, clip_time, clip_table = parse_clipboard(clip) - + if #clip_table > 1 then multipaste() else @@ -794,7 +698,7 @@ function paste_specific(action) trigger_paste_action('error-unknown') end end - + if action == 'timestamp' then if filePath == nil then trigger_paste_action('error-time') @@ -810,12 +714,12 @@ function paste_specific(action) trigger_paste_action('error-unknown') end end - + if action == 'force' then - if filePath ~= clip_file and file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) + if filePath ~= clip_file and file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) or filePath ~= clip_file and starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('load-file') - elseif file_exists(clip_file) and filePath == clip_file + elseif file_exists(clip_file) and filePath == clip_file or filePath == clip_file and starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('error-samefile') elseif not has_value(o.paste_extensions, currentVideoExtension) and not has_value(o.paste_subtitles, currentVideoExtension) then @@ -832,13 +736,13 @@ end mp.register_event('file-loaded', function() filePath, fileTitle = get_path() if clipboard_pasted == true then - clip = get_clipboard(clip) + clip = mp.get_property('clipboard/text') if not clip then msg.error('Error: clip is null' .. clip) return end clip, clip_file, clip_time, clip_table = parse_clipboard(clip) - + if #clip_table > 1 then for i=1, #clip_table do - if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) + if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) or starts_protocol(o.paste_protocols, clip_table[i][1]) then clip_file = clip_table[i][1] clip_time = clip_table[i][2] @@ -846,18 +750,18 @@ mp.register_event('file-loaded', function() end end end - + if filePath == clip_file and clip_time ~= nil then local video_duration = mp.get_property_number('duration') seekTime = clip_time + o.resume_offset - if seekTime > video_duration then + if seekTime > video_duration then if o.osd_messages == true then mp.osd_message('Time Paste Exceeds Video Length' .. o.time_seperator .. format_time(clip_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end msg.info("The time pasted exceeds the video length:\n"..format_time(clip_time)) return - end + end if seekTime < 0 then seekTime = 0 diff --git a/scripts/SmartCopyPaste_II.lua b/scripts/SmartCopyPaste_II.lua index 16bbda0..9d7acec 100644 --- a/scripts/SmartCopyPaste_II.lua +++ b/scripts/SmartCopyPaste_II.lua @@ -10,14 +10,7 @@ local o = { --Changes are recommended to be made in the script-opts directory. -----Script Settings---- - device = 'auto', --'auto' is for automatic device detection, or manually change to: 'windows' or 'mac' or 'linux' - linux_copy = 'xclip -silent -selection clipboard -in', --copy command that will be used in Linux. OR write a different command - linux_paste = 'xclip -selection clipboard -o', --paste command that will be used in Linux. OR write a different command - mac_copy = 'pbcopy', --copy command that will be used in MAC. OR write a different command - mac_paste = 'pbpaste', --paste command that will be used in MAC. OR write a different command - windows_copy = 'powershell', --'powershell' is for using windows powershell to copy. OR write the copy command, e.g: ' clip' - windows_paste = 'powershell', --'powershell' is for using windows powershell to paste. OR write the paste command - auto_run_list_idle = 'none', --Auto run the list when opening mpv and there is no video / file loaded. 'none' for disabled. Or choose between: 'all', 'copy', 'paste', 'recents', 'distinct', 'protocols', 'fileonly', 'titleonly', 'timeonly', 'keywords'. + auto_run_list_idle = 'none', --Auto run the list when opening mpv and there is no video / file loaded. 'none' for disabled. Or choose between: 'all', 'copy', 'paste', 'recents', 'distinct', 'protocols', 'fileonly', 'titleonly', 'timeonly', 'keywords'. toggle_idlescreen = false, --hides OSC idle screen message when opening and closing menu (could cause unexpected behavior if multiple scripts are triggering osc-idlescreen off) resume_offset = -0.65, --change to 0 so item resumes from the exact position, or decrease the value so that it gives you a little preview before loading the resume point osd_messages = true, --true is for displaying osd messages when actions occur. Change to false will disable all osd messages generated from this script @@ -65,7 +58,7 @@ local o = { list_filter_jump_keybind=[[ [ ["c", "all"], ["C", "all"], ["r", "recents"], ["R", "recents"], ["d", "distinct"], ["D", "distinct"], ["f", "fileonly"], ["F", "fileonly"] ] ]], --Keybind that is used while the list is open to jump to the specific filter (it also enables pressing a filter keybind twice to close list). Available fitlers: 'all', 'copy', 'paste', 'recents', 'distinct', 'protocols', 'fileonly', 'titleonly', 'timeonly', 'keywords'. - + -----Logging Settings----- log_path = '/:dir%mpvconf%', --Change to '/:dir%script%' for placing it in the same directory of script, OR change to '/:dir%mpvconf%' for mpv portable_config directory. OR write any variable using '/:var' then the variable '/:var%APPDATA%' you can use path also, such as: '/:var%APPDATA%\\mpv' OR '/:var%HOME%/mpv' OR specify the absolute path , e.g.: 'C:\\Users\\Eisa01\\Desktop\\' log_file = 'mpvClipboard.log', --name+extension of the file that will be used to store the log data @@ -115,7 +108,7 @@ local o = { list_cycle_sort_keybind=[[ ["alt+s", "alt+S"] ]], --Keybind to cycle through the different available sorts when list is open - + -----List Design Settings----- list_alignment = 7, --The alignment for the list, uses numpad positions choose from 1-9 or 0 to disable. e,g.:7 top left alignment, 8 top middle alignment, 9 top right alignment. text_time_type = 'duration', --The time type for items on the list. Select between 'duration', 'length', 'remaining'. @@ -131,7 +124,7 @@ local o = { text_cursor_border = 0.7, --Black border size for highlighted text in list text_highlight_pre_text = '✅ ', --Pre text for highlighted multi-select item search_color_typing = 'ffffaa', --Search color when in typing mode - search_color_not_typing = '56ffaa', --Search color when not in typing mode and it is active + search_color_not_typing = '56ffaa', --Search color when not in typing mode and it is active header_color = '56ffaa', --Header color in BGR hexadecimal header_scale = 55, --Header text size for the list header_border = 0.8, --Black border size for the Header of list @@ -179,7 +172,7 @@ local o = { header_remaining_time_format=[[ ["hms", "truncate", ":"] ]], - + -----List Keybind Settings----- --Add below (after a comma) any additional keybind you want to bind. Or change the letter inside the quotes to change the keybind --Example of changing and adding keybinds: --From ["b", "B"] To ["b"]. --From [""] to ["alt+b"]. --From [""] to ["a" "ctrl+a", "alt+a"] @@ -337,13 +330,13 @@ end function contain_value(tab, val) if not tab then return msg.error('check value passed') end if not val then return msg.error('check value passed') end - + for index, value in ipairs(tab) do if value.match(string.lower(val), string.lower(value)) then return true end end - + return false end @@ -364,7 +357,7 @@ function has_value(tab, val, array2d) end end end - + return false end @@ -378,7 +371,7 @@ function format_time(seconds, sep, decimals, style) return math.floor(a / b), a % b end decimals = decimals == nil and 3 or decimals - + local s = seconds local h, s = divmod(s, 60*60) local m, s = divmod(s, 60) @@ -390,7 +383,7 @@ function format_time(seconds, sep, decimals, style) seconds = math.floor(seconds) end end - + if not style or style == '' or style == 'default' then local second_format = string.format("%%0%d.%df", 2+(decimals > 0 and decimals+1 or 0), decimals) sep = sep and sep or ":" @@ -414,12 +407,12 @@ end function get_file() local path = mp.get_property('path') if not path then return end - + local length = (mp.get_property_number('duration') or 0) - + local title = mp.get_property('media-title'):gsub("\"", "") - - + + if starts_protocol(o.logging_protocols, path) and o.prefer_filename_over_title == 'protocols' then title = mp.get_property('filename'):gsub("\"", "") elseif not starts_protocol(o.logging_protocols, path) and o.prefer_filename_over_title == 'local' then @@ -427,7 +420,7 @@ function get_file() elseif o.prefer_filename_over_title == 'all' then title = mp.get_property('filename'):gsub("\"", "") end - + return path, title, length end @@ -436,9 +429,9 @@ function bind_keys(keys, name, func, opts) mp.add_forced_key_binding(keys, name, func, opts) return end - + for i = 1, #keys do - if i == 1 then + if i == 1 then mp.add_forced_key_binding(keys[i], name, func, opts) else mp.add_forced_key_binding(keys[i], name .. i, func, opts) @@ -451,7 +444,7 @@ function unbind_keys(keys, name) mp.remove_key_binding(name) return end - + for i = 1, #keys do if i == 1 then mp.remove_key_binding(name) @@ -519,7 +512,7 @@ function list_sort(tab, sort) table.sort(tab, function(a, b) return tostring(a['found_path']):gsub("%.?%d+", padnum) .. ("%3d"):format(#b) < tostring(b['found_path']):gsub("%.?%d+", padnum) .. ("%3d"):format(#a) end) end end - + return tab end @@ -532,7 +525,7 @@ function parse_header(string) osd_search_color = string.format("{\\1c&H%s}", o.search_color_not_typing) end local osd_msg_end = "{\\1c&HFFFFFF}" - + string = string:gsub("%%total%%", #list_contents) :gsub("%%cursor%%", list_cursor) @@ -545,7 +538,7 @@ function parse_header(string) :gsub("%%prefilter%%", '') :gsub("%%afterfilter%%", '') end - + local list_total_duration = 0 if string:match('%listduration%%') then list_total_duration = get_total_duration('found_time') @@ -554,7 +547,7 @@ function parse_header(string) else string = string:gsub("%%listduration%%", '') end - end + end if list_total_duration > 0 then string = string:gsub("%%prelistduration%%", o.header_list_duration_pre_text) :gsub("%%afterlistduration%%", o.header_list_duration_after_text) @@ -562,7 +555,7 @@ function parse_header(string) string = string:gsub("%%prelistduration%%", '') :gsub("%%afterlistduration%%", '') end - + local list_total_length = 0 if string:match('%listlength%%') then list_total_length = get_total_duration('found_length') @@ -571,7 +564,7 @@ function parse_header(string) else string = string:gsub("%%listlength%%", '') end - end + end if list_total_length > 0 then string = string:gsub("%%prelistlength%%", o.header_list_length_pre_text) :gsub("%%afterlistlength%%", o.header_list_length_after_text) @@ -579,7 +572,7 @@ function parse_header(string) string = string:gsub("%%prelistlength%%", '') :gsub("%%afterlistlength%%", '') end - + local list_total_remaining = 0 if string:match('%listremaining%%') then list_total_remaining = get_total_duration('found_remaining') @@ -588,7 +581,7 @@ function parse_header(string) else string = string:gsub("%%listremaining%%", '') end - end + end if list_total_remaining > 0 then string = string:gsub("%%prelistremaining%%", o.header_list_remaining_pre_text) :gsub("%%afterlistremaining%%", o.header_list_remaining_after_text) @@ -596,7 +589,7 @@ function parse_header(string) string = string:gsub("%%prelistremaining%%", '') :gsub("%%afterlistremaining%%", '') end - + if #list_highlight_cursor > 0 then string = string:gsub("%%highlight%%", #list_highlight_cursor) :gsub("%%prehighlight%%", o.header_highlight_pre_text) @@ -606,7 +599,7 @@ function parse_header(string) :gsub("%%prehighlight%%", '') :gsub("%%afterhighlight%%", '') end - + if sortName and sortName ~= o.header_sort_hide_text then string = string:gsub("%%sort%%", sortName) :gsub("%%presort%%", o.header_sort_pre_text) @@ -616,15 +609,15 @@ function parse_header(string) :gsub("%%presort%%", '') :gsub("%%aftersort%%", '') end - + if search_active then local search_string_osd = search_string if search_string_osd ~= '' then search_string_osd = search_string:gsub('%%', '%%%%%%%%'):gsub('\\', '\\​'):gsub('{', '\\{') end - + string = string:gsub("%%search%%", osd_search_color..search_string_osd..osd_header_color) - :gsub("%%presearch%%", o.header_search_pre_text) + :gsub("%%presearch%%", o.header_search_pre_text) :gsub("%%aftersearch%%", o.header_search_after_text) else string = string:gsub("%%search%%", '') @@ -638,61 +631,61 @@ end function get_list_contents(filter, sort) if not filter then filter = filterName end if not sort then sort = get_list_sort(filter) end - + local current_sort local filtered_table = {} local prev_list_contents - if list_contents ~= nil and list_contents[1] then + if list_contents ~= nil and list_contents[1] then prev_list_contents = list_contents else prev_list_contents = read_log_table() end - + list_contents = read_log_table() if not list_contents and not search_active or not list_contents[1] and not search_active then return end current_sort = 'added-asc' - + if filter == 'copy' then for i = 1, #list_contents do if list_contents[i].found_copy then table.insert(filtered_table, list_contents[i]) end end - + if not sort then active_sort = o.sort_copy_filter end if active_sort ~= 'none' or active_sort ~= '' then list_sort(filtered_table, active_sort) end - + list_contents = filtered_table end - + if filter == 'paste' then for i = 1, #list_contents do if list_contents[i].found_paste then table.insert(filtered_table, list_contents[i]) end end - + if not sort then active_sort = o.sort_paste_filter end if active_sort ~= 'none' or active_sort ~= '' then list_sort(filtered_table, active_sort) end - + list_contents = filtered_table end - + if filter == 'recents' then table.sort(list_contents, function(a, b) return a['found_sequence'] < b['found_sequence'] end) local unique_values = {} local list_total = #list_contents - + if filePath == list_contents[#list_contents].found_path and tonumber(list_contents[#list_contents].found_time) == 0 then list_total = list_total -1 end - + for i = list_total, 1, -1 do if not has_value(unique_values, list_contents[i].found_path) then table.insert(unique_values, list_contents[i].found_path) @@ -700,20 +693,20 @@ function get_list_contents(filter, sort) end end table.sort(filtered_table, function(a, b) return a['found_sequence'] < b['found_sequence'] end) - + list_contents = filtered_table - + end - + if filter == 'distinct' then table.sort(list_contents, function(a, b) return a['found_sequence'] < b['found_sequence'] end) local unique_values = {} local list_total = #list_contents - + if filePath == list_contents[#list_contents].found_path and tonumber(list_contents[#list_contents].found_time) == 0 then list_total = list_total -1 end - + for i = list_total, 1, -1 do if list_contents[i].found_directory and not has_value(unique_values, list_contents[i].found_directory) and not starts_protocol(protocols, list_contents[i].found_path) then table.insert(unique_values, list_contents[i].found_directory) @@ -721,81 +714,81 @@ function get_list_contents(filter, sort) end end table.sort(filtered_table, function(a, b) return a['found_sequence'] < b['found_sequence'] end) - + list_contents = filtered_table end - + if filter == 'fileonly' then for i = 1, #list_contents do if tonumber(list_contents[i].found_time) == 0 then table.insert(filtered_table, list_contents[i]) end end - + list_contents = filtered_table end - + if filter == 'timeonly' then for i = 1, #list_contents do if tonumber(list_contents[i].found_time) > 0 then table.insert(filtered_table, list_contents[i]) end end - + list_contents = filtered_table end - + if filter == 'titleonly' then for i = 1, #list_contents do if list_contents[i].found_title then table.insert(filtered_table, list_contents[i]) end end - + list_contents = filtered_table end - + if filter == 'protocols' then for i = 1, #list_contents do if starts_protocol(o.logging_protocols, list_contents[i].found_path) then table.insert(filtered_table, list_contents[i]) end end - + list_contents = filtered_table end - + if filter == 'keywords' then for i = 1, #list_contents do if contain_value(o.keywords_filter_list, list_contents[i].found_line) then table.insert(filtered_table, list_contents[i]) end end - + list_contents = filtered_table end - + if filter == 'playing' then for i = 1, #list_contents do if list_contents[i].found_path == filePath then table.insert(filtered_table, list_contents[i]) end end - + list_contents = filtered_table end - + if search_active and search_string ~= '' then local filtered_table = {} - + local search_query = '' for search in search_string:gmatch("[^%s]+") do search_query = search_query..'.-'..esc_string(search) end - + local contents_string = '' for i = 1, #list_contents do - + if o.search_behavior == 'specific' then if string.lower(list_contents[i].found_path):match(string.lower(search_query)) then table.insert(filtered_table, list_contents[i]) @@ -808,32 +801,32 @@ function get_list_contents(filter, sort) end elseif o.search_behavior == 'any' then contents_string = list_contents[i].found_datetime..(list_contents[i].found_title or '')..list_contents[i].found_path - if tonumber(list_contents[i].found_time) > 0 then + if tonumber(list_contents[i].found_time) > 0 then contents_string = contents_string..format_time(list_contents[i].found_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1]) end elseif o.search_behavior == 'any-notime' then contents_string = list_contents[i].found_datetime..(list_contents[i].found_title or '')..list_contents[i].found_path end - + if string.lower(contents_string):match(string.lower(search_query)) then table.insert(filtered_table, list_contents[i]) end end - + list_contents = filtered_table - + end - + if sort ~= current_sort then list_sort(list_contents, sort) end - + if not list_contents and not search_active or not list_contents[1] and not search_active then return end end function get_list_sort(filter) if not filter then filter = filterName end - + local sort for i=1, #o.list_filters_sort do if o.list_filters_sort[i][1] == filter then @@ -841,11 +834,11 @@ function get_list_sort(filter) break end end - + if not sort and has_value(available_sorts, o.list_default_sort) then sort = o.list_default_sort end - + if not sort then sort = 'added-asc' end - + return sort end @@ -860,28 +853,28 @@ function draw_list() local osd_header = string.format("{\\an%f}{\\fscx%f}{\\fscy%f}{\\bord%f}{\\1c&H%s}", o.list_alignment, o.header_scale, o.header_scale, o.header_border, o.header_color) local osd_msg_end = "{\\1c&HFFFFFF}" local osd_time_type = 'found_time' - + if o.text_time_type == 'length' then osd_time_type = 'found_length' elseif o.text_time_type == 'remaining' then osd_time_type = 'found_remaining' end - + if o.header_text ~= '' then osd_msg = osd_msg .. osd_header .. parse_header(o.header_text) osd_msg = osd_msg .. "\\h\\N\\N" .. osd_msg_end end - + if search_active and not list_contents[1] then osd_msg = osd_msg .. 'No search results found' .. osd_msg_end end - + if o.list_middle_loader then list_start = list_cursor - math.floor(o.list_show_amount / 2) else list_start = list_cursor - o.list_show_amount end - + local showall = false local showrest = false if list_start < 0 then list_start = 0 end @@ -898,59 +891,59 @@ function draw_list() end for i = list_start, list_start + o.list_show_amount - 1, 1 do if i == #list_contents then break end - + if o.show_paths then p = list_contents[#list_contents - i].found_path or list_contents[#list_contents - i].found_name or "" else p = list_contents[#list_contents - i].found_name or list_contents[#list_contents - i].found_path or "" end - + if o.slice_longfilenames and p:len() > o.slice_longfilenames_amount then p = p:sub(1, o.slice_longfilenames_amount) .. "..." end - + if o.quickselect_0to9_keybind and o.list_show_amount <= 10 and o.quickselect_0to9_pre_text then key = 1 + key if key == 10 then key = 0 end osd_key = '(' .. key .. ') ' end - + if o.show_item_number then osd_index = (i + 1) .. '. ' end - + if i + 1 == list_cursor then osd_color = osd_cursor else osd_color = osd_text end - + for j = 1, #list_highlight_cursor do if list_highlight_cursor[j] and list_highlight_cursor[j][1] == i+1 then osd_msg = osd_msg..osd_color..esc_string(o.text_highlight_pre_text) end end - + osd_msg = osd_msg .. osd_color .. osd_key .. osd_index .. p - + if list_contents[#list_contents - i][osd_time_type] and tonumber(list_contents[#list_contents - i][osd_time_type]) > 0 then osd_msg = osd_msg .. o.time_seperator .. format_time(list_contents[#list_contents - i][osd_time_type], o.list_time_format[3], o.list_time_format[2], o.list_time_format[1]) end - + if list_contents[#list_contents - i].found_copy then osd_msg = osd_msg .. o.copy_seperator end - + if list_contents[#list_contents - i].found_paste then osd_msg = osd_msg .. o.paste_seperator end - + osd_msg = osd_msg .. '\\h\\N\\N' .. osd_msg_end - + if i == list_start + o.list_show_amount - 1 and not showall and not showrest then osd_msg = osd_msg .. o.list_sliced_suffix end - + end mp.set_osd_ass(0, 0, osd_msg) end @@ -972,7 +965,7 @@ end function display_list(filter, sort, action) if not filter or not has_value(available_filters, filter) then filter = 'all' end if not sortName then sortName = get_list_sort(filter) end - + local prev_sort = sortName if not has_value(available_sorts, prev_sort) then prev_sort = get_list_sort() end @@ -981,9 +974,9 @@ function display_list(filter, sort, action) local prev_filter = filterName filterName = filter - + get_list_contents(filter, sort) - + if action ~= 'hide-osd' then if not list_contents or not list_contents[1] then list_empty_error_msg() @@ -993,17 +986,17 @@ function display_list(filter, sort, action) end end if not list_contents and not search_active or not list_contents[1] and not search_active then return end - + if not has_value(o.filters_and_sequence, filter) then table.insert(o.filters_and_sequence, filter) end - + local insert_new = false - + local trigger_close_list = false local trigger_initial_list = false - - + + if not list_pages or not list_pages[1] then table.insert(list_pages, {filter, 1, 1, {}, sort}) else @@ -1017,9 +1010,9 @@ function display_list(filter, sort, action) end end end - + if insert_new then table.insert(list_pages, {filter, 1, 1, {}, sort}) end - + for i = 1, #list_pages do if not search_active and list_pages[i][1] == prev_filter then list_pages[i][2] = list_cursor @@ -1032,22 +1025,22 @@ function display_list(filter, sort, action) if list_pages[i][3] == 2 and filter == 'all' and o.main_list_keybind_twice_exits then trigger_close_list = true elseif list_pages[i][3] == 2 and list_pages[1][1] == filter then - trigger_close_list = true + trigger_close_list = true elseif list_pages[i][3] == 2 then trigger_initial_list = true end end - + if trigger_initial_list then display_list(list_pages[1][1], nil, 'hide-osd') return end - + if trigger_close_list then list_close_and_trash_collection() return end - + if not search_active then get_page_properties(filter) else update_search_results('','') end draw_list() if utils.shared_script_property_set then @@ -1069,24 +1062,24 @@ function select(pos, action) return end end - + local list_cursor_temp = list_cursor + pos if list_cursor_temp > 0 and list_cursor_temp <= #list_contents then list_cursor = list_cursor_temp - + if action == 'highlight' then if not has_value(list_highlight_cursor, list_cursor, 1) then if pos > -1 then for i = pos, 1, -1 do if not has_value(list_highlight_cursor, list_cursor-i, 1) then table.insert(list_highlight_cursor, {list_cursor-i, list_contents[#list_contents+1+i - list_cursor]}) - end + end end else for i = pos, -1, 1 do if not has_value(list_highlight_cursor, list_cursor-i, 1) then table.insert(list_highlight_cursor, {list_cursor-i, list_contents[#list_contents+1+i - list_cursor]}) - end + end end end table.insert(list_highlight_cursor, {list_cursor, list_contents[#list_contents+1 - list_cursor]}) @@ -1116,7 +1109,7 @@ function select(pos, action) end end end - + if o.loop_through_list then if list_cursor_temp > #list_contents then list_cursor = 1 @@ -1124,7 +1117,7 @@ function select(pos, action) list_cursor = #list_contents end end - + draw_list() end @@ -1165,7 +1158,7 @@ function list_page_up(action) if search_active and o.search_not_typing_smartly then list_search_not_typing_mode(true) - end + end end function list_page_down(action) @@ -1187,18 +1180,18 @@ function list_page_down(action) if search_active and o.search_not_typing_smartly then list_search_not_typing_mode(true) - end + end end function list_highlight_all() get_list_contents(filterName) if not list_contents or not list_contents[1] then return end - + if #list_highlight_cursor < #list_contents then for i=1, #list_contents do if not has_value(list_highlight_cursor, i, 1) then table.insert(list_highlight_cursor, {i, list_contents[#list_contents+1-i]}) - end + end end select(0) else @@ -1263,7 +1256,7 @@ function list_add_playlist(action) elseif action == 'highlight' then if not list_highlight_cursor or not list_highlight_cursor[1] then return end local file_ignored_total = 0 - + for i=1, #list_highlight_cursor do if file_exists(list_highlight_cursor[i][2].found_path) or starts_protocol(protocols, list_highlight_cursor[i][2].found_path) then mp.commandv("loadfile", list_highlight_cursor[i][2].found_path, "append-play") @@ -1292,7 +1285,7 @@ function delete_log_entry_specific(target_index, target_path, target_time) if not list_contents or not list_contents[1] then return end if target_index == 'last' then target_index = #list_contents end if not target_index then return end - + if target_index and target_path and target_time then if list_contents[target_index].found_path == target_path and tonumber(list_contents[target_index].found_time) == target_time then table.remove(list_contents, target_index) @@ -1312,7 +1305,7 @@ function delete_log_entry_specific(target_index, target_path, target_time) table.remove(list_contents, target_index) trigger_delete = true end - + if not trigger_delete then return end local f = io.open(log_fullpath, "w+") if list_contents ~= nil and list_contents[1] then @@ -1329,7 +1322,7 @@ function delete_log_entry(multiple, round, target_path, target_time, entry_limit list_contents = read_log_table() if not list_contents or not list_contents[1] then return end local trigger_delete = false - + if not multiple then for i = #list_contents, 1, -1 do if not round then @@ -1361,7 +1354,7 @@ function delete_log_entry(multiple, round, target_path, target_time, entry_limit end end end - + if entry_limit and entry_limit > -1 then local entries_found = 0 for i = #list_contents, 1, -1 do @@ -1373,7 +1366,7 @@ function delete_log_entry(multiple, round, target_path, target_time, entry_limit end end end - + if not trigger_delete then return end local f = io.open(log_fullpath, "w+") if list_contents ~= nil and list_contents[1] then @@ -1388,9 +1381,9 @@ function delete_log_entry_highlighted() if not list_highlight_cursor or not list_highlight_cursor[1] then return end list_contents = read_log_table() if not list_contents or not list_contents[1] then return end - + local list_contents_length = #list_contents - + for i = 1, list_contents_length do for j=1, #list_highlight_cursor do if list_contents[list_contents_length+1-i] then @@ -1400,11 +1393,11 @@ function delete_log_entry_highlighted() end end end - + msg.info("Deleted "..#list_highlight_cursor.." Item/s") - + list_unhighlight_all() - + local f = io.open(log_fullpath, "w+") if list_contents ~= nil and list_contents[1] then for i = 1, #list_contents do @@ -1412,7 +1405,7 @@ function delete_log_entry_highlighted() end end f:close() - + end function delete_selected() @@ -1515,13 +1508,13 @@ function select_filter_sequence(pos) if not list_drawn then return end local curr_pos local target_pos - + for i = 1, #o.filters_and_sequence do if filterName == o.filters_and_sequence[i] then curr_pos = i end end - + if curr_pos and pos > -1 then for i = curr_pos, #o.filters_and_sequence do if o.filters_and_sequence[i + pos] then @@ -1543,7 +1536,7 @@ function select_filter_sequence(pos) end end end - + if o.loop_through_filters then if not target_pos and pos > -1 or target_pos and target_pos > #o.filters_and_sequence then for i = 1, #o.filters_and_sequence do @@ -1619,11 +1612,11 @@ function get_list_keybinds() mp.add_forced_key_binding(o.list_highlight_move_keybind[i]..'+'..o.list_page_down_keybind[j], 'highlight-page-down'..j, function()list_page_down('highlight') end, 'repeatable') end end - + if not search_active then bind_keys(o.list_close_keybind, 'list-close', list_close_and_trash_collection) end - + for i = 1, #o.list_filter_jump_keybind do mp.add_forced_key_binding(o.list_filter_jump_keybind[i][1], 'list-filter-jump'..i, function()display_list(o.list_filter_jump_keybind[i][2]) end) end @@ -1634,8 +1627,8 @@ function get_list_keybinds() else mp.remove_key_binding('open-list'..i) end - end - + end + if o.quickselect_0to9_keybind and o.list_show_amount <= 10 then mp.add_forced_key_binding("1", "recent-1", function()load(list_start + 1) end) mp.add_forced_key_binding("2", "recent-2", function()load(list_start + 2) end) @@ -1669,7 +1662,7 @@ function unbind_list_keys() unbind_keys(o.list_highlight_all_keybind, 'list-highlight-all') unbind_keys(o.list_highlight_all_keybind, 'list-unhighlight-all') unbind_keys(o.list_cycle_sort_keybind, 'list-cycle-sort') - + for i = 1, #o.list_move_up_keybind do mp.remove_key_binding('highlight-move-up'..i) end @@ -1688,7 +1681,7 @@ function unbind_list_keys() for i = 1, #o.list_page_down_keybind do mp.remove_key_binding('highlight-page-down'..i) end - + for i = 1, #o.list_filter_jump_keybind do mp.remove_key_binding('list-filter-jump'..i) end @@ -1700,7 +1693,7 @@ function unbind_list_keys() mp.add_forced_key_binding(o.open_list_keybind[i][1], 'open-list'..i, function()display_list(o.open_list_keybind[i][2]) end) end end - + if o.quickselect_0to9_keybind and o.list_show_amount <= 10 then mp.remove_key_binding("recent-1") mp.remove_key_binding("recent-2") @@ -1748,7 +1741,7 @@ end function list_search_not_typing_mode(auto_triggered) if auto_triggered then - if search_string ~= '' and list_contents[1] then + if search_string ~= '' and list_contents[1] then search_active = 'not_typing' elseif not list_contents[1] then return @@ -1757,8 +1750,8 @@ function list_search_not_typing_mode(auto_triggered) end else if search_string ~= '' then - search_active = 'not_typing' - else + search_active = 'not_typing' + else search_active = false end end @@ -1771,7 +1764,7 @@ function list_search_activate() if not list_drawn then return end if search_active == 'typing' then list_search_exit() return end search_active = 'typing' - + for i = 1, #list_pages do if list_pages[i][1] == filterName then list_pages[i][2] = list_cursor @@ -1779,7 +1772,7 @@ function list_search_activate() list_pages[i][5] = sortName end end - + update_search_results('','') bind_search_keys() end @@ -1787,16 +1780,16 @@ end function update_search_results(character, action) if not character then character = '' end if action == 'string_del' then - search_string = search_string:sub(1, -2) + search_string = search_string:sub(1, -2) end search_string = search_string..character local prev_contents_length = #list_contents get_list_contents(filterName) - + if prev_contents_length ~= #list_contents then list_highlight_cursor = {} end - + if character ~= '' and #list_contents > 0 or action ~= nil and #list_contents > 0 then select(1-list_cursor) elseif #list_contents == 0 then @@ -1946,7 +1939,7 @@ function unbind_search_keys() mp.remove_key_binding('search_string_x') mp.remove_key_binding('search_string_y') mp.remove_key_binding('search_string_z') - + mp.remove_key_binding('search_string_A') mp.remove_key_binding('search_string_B') mp.remove_key_binding('search_string_C') @@ -1973,7 +1966,7 @@ function unbind_search_keys() mp.remove_key_binding('search_string_X') mp.remove_key_binding('search_string_Y') mp.remove_key_binding('search_string_Z') - + mp.remove_key_binding('search_string_1') mp.remove_key_binding('search_string_2') mp.remove_key_binding('search_string_3') @@ -1984,7 +1977,7 @@ function unbind_search_keys() mp.remove_key_binding('search_string_8') mp.remove_key_binding('search_string_9') mp.remove_key_binding('search_string_0') - + mp.remove_key_binding('search_string_space') mp.remove_key_binding('search_string_`') mp.remove_key_binding('search_string_~') @@ -2018,7 +2011,7 @@ function unbind_search_keys() mp.remove_key_binding('search_string_>') mp.remove_key_binding('search_string_,') mp.remove_key_binding('search_string_<') - + mp.remove_key_binding('search_string_del') if not search_active then unbind_keys(o.list_close_keybind, 'search_exit') @@ -2029,11 +2022,11 @@ end function mark_chapter() if not o.mark_clipboard_as_chapter then return end - + local all_chapters = mp.get_property_native("chapter-list") local chapter_index = 0 local chapters_time = {} - + get_list_contents() if not list_contents or not list_contents[1] then return end for i = 1, #list_contents do @@ -2042,20 +2035,20 @@ function mark_chapter() end end if not chapters_time[1] then return end - + table.sort(chapters_time, function(a, b) return a < b end) - + for i = 1, #chapters_time do chapter_index = chapter_index + 1 - + all_chapters[chapter_index] = { title = 'SmartCopyPaste-II ' .. chapter_index, time = chapters_time[i] } end - + table.sort(all_chapters, function(a, b) return a['time'] < b['time'] end) - + mp.set_property_native("chapter-list", all_chapters) end @@ -2067,7 +2060,7 @@ function write_log(target_time, update_seekTime, entry_limit, action) seekTime = target_time end if seekTime < 0 then seekTime = 0 end - + delete_log_entry(false, true, filePath, math.floor(seekTime), entry_limit) local f = io.open(log_fullpath, "a+") @@ -2080,7 +2073,7 @@ function write_log(target_time, update_seekTime, entry_limit, action) else f:write(("[%s] %s | %s | %s"):format(os.date(o.date_format), filePath, log_length_text .. tostring(fileLength), log_time_text .. tostring(seekTime))) end - + if action == 'copy' then f:write(' | ' .. log_clipboard_text .. action) end @@ -2090,7 +2083,7 @@ function write_log(target_time, update_seekTime, entry_limit, action) f:write('\n') f:close() - + if not update_seekTime then seekTime = prev_seekTime end @@ -2120,19 +2113,6 @@ if not o.device or o.device == 'auto' then end end -function handleres(res, args) - if not res.error and res.status == 0 then - return res.stdout - else - msg.error("There was an error getting "..o.device.." clipboard: ") - msg.error(" Status: "..(res.status or "")) - msg.error(" Error: "..(res.error or "")) - msg.error(" stdout: "..(res.stdout or "")) - msg.error("args: "..utils.to_string(args)) - return '' - end -end - function os.capture(cmd) local f = assert(io.popen(cmd, 'r')) local s = assert(f:read('*a')) @@ -2150,7 +2130,7 @@ end function get_extension(path) if not path then return end - + match = string.match(path, '%.([^%.]+)$' ) if match == nil then return 'nomatch' @@ -2188,74 +2168,9 @@ function get_time_attribute(target_path) return pre_attribute end -function get_clipboard() - local clipboard - if o.device == 'linux' then - clipboard = os.capture(o.linux_paste) - return clipboard - elseif o.device == 'windows' then - if o.windows_paste == 'powershell' then - local 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) - }]] - } - return handleres(utils.subprocess({ args = args, cancellable = false }), args) - else - clipboard = os.capture(o.windows_paste) - return clipboard - end - elseif o.device == 'mac' then - clipboard = os.capture(o.mac_paste) - return clipboard - end - return '' -end - - -function set_clipboard(text) - local pipe - if o.device == 'linux' then - pipe = io.popen(o.linux_copy, 'w') - pipe:write(text) - pipe:close() - elseif o.device == 'windows' then - if o.windows_copy == 'powershell' then - local res = utils.subprocess({ args = { - 'powershell', '-NoProfile', '-Command', string.format([[& { - Trap { - Write-Error -ErrorRecord $_ - Exit 1 - } - Add-Type -AssemblyName PresentationCore - [System.Windows.Clipboard]::SetText('%s') - }]], text) - } }) - else - pipe = io.popen(o.windows_copy,'w') - pipe:write(text) - pipe:close() - end - elseif o.device == 'mac' then - pipe = io.popen(o.mac_copy,'w') - pipe:write(text) - pipe:close() - end - return '' -end - function parse_clipboard(text) if not text then return end - + local clip, clip_file, clip_time, pre_attribute local clip_table = {} clip = text @@ -2264,7 +2179,7 @@ function parse_clipboard(text) for c in clip:gmatch("[^\n\r]+") do --3.2.1# fix for #80 , accidentally additional "+" was added to the gmatch local c_pre_attribute, c_clip_file, c_clip_time, c_clip_extension c = make_raw(c) - + if starts_protocol(protocols, c) then --3.2# handle protocols to allow for space as a seperator for c_protocols in c:gmatch("[^%s]+") do --3.2# loop iterator using space if starts_protocol(protocols, c_protocols) then --3.2# check if it starts with protocols again after a space @@ -2276,7 +2191,7 @@ function parse_clipboard(text) c_clip_file = string.match(c, '^\"(.*)\"$') else c_clip_file = c_protocols - end + end c_clip_extension = get_extension(c_clip_file) table.insert(clip_table, {c_clip_file, c_clip_time, c_clip_extension}) end @@ -2291,7 +2206,7 @@ function parse_clipboard(text) else c_clip_file = c end - + c_clip_extension = get_extension(c_clip_file) table.insert(clip_table, {c_clip_file, c_clip_time, c_clip_extension}) end @@ -2363,14 +2278,14 @@ function copy_specific(action) if o.osd_messages == true then mp.osd_message("Copied:\n"..fileTitle) end - set_clipboard(fileTitle) + mp.set_property_native('clipboard/text', fileTitle) msg.info("Copied the below into clipboard:\n"..fileTitle) end if action == 'path' then if o.osd_messages == true then mp.osd_message("Copied:\n"..filePath) end - set_clipboard(filePath) + mp.set_property_native('clipboard/text', filePath) msg.info("Copied and logged the below into clipboard:\n"..filePath) write_log(0, false, o.same_entry_limit, 'copy') end @@ -2380,7 +2295,7 @@ function copy_specific(action) if o.osd_messages == true then mp.osd_message("Copied"..o.time_seperator..format_time(video_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end - set_clipboard(pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) + mp.set_property_native('clipboard/text', pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) msg.info('Copied the below into clipboard:\n'..pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) end if action == 'path×tamp' then @@ -2389,7 +2304,7 @@ function copy_specific(action) if o.osd_messages == true then mp.osd_message("Copied:\n" .. fileTitle .. o.time_seperator .. format_time(video_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end - set_clipboard(filePath..pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) + mp.set_property_native('clipboard/text', filePath..pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) msg.info('Copied and logged the below into clipboard:\n'..filePath..pre_attribute..format_time(video_time, o.copy_time_format[3], o.copy_time_format[2], o.copy_time_format[1])..after_attribute) write_log(false, false, o.same_entry_limit, 'copy') end @@ -2398,7 +2313,7 @@ end function trigger_paste_action(action) if not action then return end - + if action == 'load-file' then filePath = clip_file if o.osd_messages == true then @@ -2410,14 +2325,14 @@ function trigger_paste_action(action) end mp.commandv('loadfile', clip_file) clipboard_pasted = true - + if clip_time ~= nil then msg.info("Pasted the below file into mpv:\n"..clip_file .. format_time(clip_time)) else msg.info("Pasted the below file into mpv:\n"..clip_file) end end - + if action == 'load-subtitle' then if o.osd_messages == true then mp.osd_message("Pasted Subtitle:\n"..clip_file) @@ -2425,47 +2340,47 @@ function trigger_paste_action(action) mp.commandv('sub-add', clip_file, 'select') msg.info("Pasted the below subtitle into mpv:\n"..clip_file) end - + if action == 'file-seek' then local video_duration = mp.get_property_number('duration') seekTime = clip_time + o.resume_offset - - if seekTime > video_duration then + + if seekTime > video_duration then if o.osd_messages == true then mp.osd_message('Time Paste Exceeds Video Length' .. o.time_seperator .. format_time(clip_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end msg.info("The time pasted exceeds the video length:\n"..format_time(clip_time)) return - end - + end + if (seekTime < 0) then seekTime = 0 end - + if o.osd_messages == true then mp.osd_message('Resumed to Pasted Time' .. o.time_seperator .. format_time(clip_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end mp.commandv('seek', seekTime, 'absolute', 'exact') msg.info("Resumed to the pasted time" .. o.time_seperator .. format_time(clip_time)) end - + if action == 'add-playlist' then if o.osd_messages == true then mp.osd_message('Pasted Into Playlist:\n'..clip_file) end mp.commandv('loadfile', clip_file, 'append-play') msg.info("Pasted the below into playlist and added it to the log file:\n"..clip_file) - + local temp_filePath = filePath local temp_title_logging = o.file_title_logging - + filePath = clip_file o.file_title_logging = 'none' write_log(0, false, o.same_entry_limit, 'paste') filePath = temp_filePath o.file_title_logging = temp_title_logging end - + if action == 'log-force' then get_list_contents('all', 'added-asc') load(1) @@ -2481,7 +2396,7 @@ function trigger_paste_action(action) msg.info("Pasted the below from log file into mpv:\n"..list_contents[#list_contents - 1 + 1].found_path) end end - + if action == 'log-force-noresume' then get_list_contents('all', 'added-asc') if not list_contents or not list_contents[1] then return end @@ -2491,7 +2406,7 @@ function trigger_paste_action(action) end msg.info("Pasted the below from log file into mpv:\n"..list_contents[#list_contents - 1 + 1].found_path) end - + if action == 'log-playlist' then get_list_contents('all', 'added-asc') if not list_contents or not list_contents[1] then return end @@ -2501,7 +2416,7 @@ function trigger_paste_action(action) end msg.info("Pasted the below from log file into mpv playlist:\n"..list_contents[#list_contents - 1 + 1].found_path) end - + if action == 'log-timestamp' then get_list_contents('all', 'added-asc') if not list_contents or not list_contents[1] then return end @@ -2522,7 +2437,7 @@ function trigger_paste_action(action) list_contents = nil end end - + if action == 'log-timestamp>playlist' then get_list_contents('all', 'added-asc') if not list_contents or not list_contents[1] then return end @@ -2545,7 +2460,7 @@ function trigger_paste_action(action) msg.info("Pasted the below from log file into mpv playlist:\n"..list_contents[#list_contents - 1 + 1].found_path) end end - + if action == 'log-timestamp>force' then get_list_contents('all', 'added-asc') if not list_contents or not list_contents[1] then return end @@ -2577,28 +2492,28 @@ function trigger_paste_action(action) end end end - + if action == 'error-subtitle' then if o.osd_messages == true then mp.osd_message('Subtitle Paste Requires Running Video:\n'..clip_file) end msg.info('Subtitles can only be pasted if a video is running:\n'..clip_file) end - + if action == 'error-unsupported' then if o.osd_messages == true then mp.osd_message('Paste of this item is unsupported possibly due to configuration:\n'..clip) end msg.info('Failed to paste into mpv, pasted item shown below is unsupported possibly due to configuration:\n'..clip) end - + if action == 'error-missing' then if o.osd_messages == true then mp.osd_message('File Doesn\'t Exist:\n' .. clip_file) end msg.info('The file below doesn\'t seem to exist:\n' .. clip_file) end - + if action == 'error-time' then if o.osd_messages == true then if clip_time ~= nil then @@ -2607,28 +2522,28 @@ function trigger_paste_action(action) mp.osd_message('Time Paste Requires Running Video') end end - + if clip_time ~= nil then msg.info('Time can only be pasted if a video is running:\n'.. format_time(clip_time)) else msg.info('Time can only be pasted if a video is running') end end - + if action == 'error-missingtime' then if o.osd_messages == true then mp.osd_message('Clipboard does not contain time for seeking:\n'..clip) end msg.info("Clipboard does not contain the time attribute and time for seeking:\n"..clip) end - + if action == 'error-samefile' then if o.osd_messages == true then mp.osd_message('Pasted file is already running:\n'..clip) end msg.info("Pasted file shown below is already running:\n"..clip) end - + if action == 'error-unknown' then if o.osd_messages == true then mp.osd_message('Paste was ignored due to an error:\n'..clip) @@ -2646,7 +2561,7 @@ function multipaste() if filePath == nil then for i=1, #clip_table do - if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) + if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) or starts_protocol(o.paste_protocols, clip_table[i][1]) then filePath = clip_table[i][1] mp.commandv('loadfile', clip_table[i][1]) @@ -2657,14 +2572,14 @@ function multipaste() end end end - + if filePath ~= nil then for i=1, #clip_table do if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) or starts_protocol(o.paste_protocols, clip_table[i][1]) then mp.commandv('loadfile', clip_table[i][1], 'append-play') triggered_multipaste[2] = true - + local temp_filePath = filePath local temp_title_logging = o.file_title_logging filePath = clip_table[i][1] @@ -2687,7 +2602,7 @@ function multipaste() end end end - + local osd_msg = '' if triggered_multipaste[1] == true then if osd_msg ~= '' then osd_msg = osd_msg..'\n' end @@ -2700,16 +2615,16 @@ function multipaste() if triggered_multipaste[2] == true then if osd_msg ~= '' then osd_msg = osd_msg..'\n' end osd_msg = osd_msg..'Added Into Playlist '..#clip_table - file_ignored_total - file_subtitle_total..' item/s' - end + end if file_ignored_total > 0 then if osd_msg ~= '' then osd_msg = osd_msg..'\n' end osd_msg = osd_msg..'Ignored '..file_ignored_total.. ' Item/s' end - + if osd_msg == '' then osd_msg = 'Pasted Items Ignored or Unable To Append Into Video:\n'..clip end - + if o.osd_messages == true then mp.osd_message(osd_msg) end @@ -2722,16 +2637,16 @@ function paste() end msg.info("Pasting...") - clip = get_clipboard(clip) + clip = mp.get_property('clipboard/text') if not clip then msg.error('Error: clip is null' .. clip) return end clip, clip_file, clip_time, clip_table = parse_clipboard(clip) - + if #clip_table > 1 then multipaste() else local currentVideoExtension = string.lower(get_extension(clip_file)) if filePath == nil then - if file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) + if file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) or starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('load-file') elseif file_exists(clip_file) and has_value(o.paste_subtitles, currentVideoExtension) then @@ -2782,7 +2697,7 @@ function paste() elseif o.running_paste_behavior == 'timestamp' then if clip_time ~= nil then trigger_paste_action('file-seek') - elseif file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) + elseif file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) or starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('add-playlist') elseif not has_value(o.paste_extensions, currentVideoExtension) then @@ -2802,12 +2717,12 @@ function paste() end end elseif o.running_paste_behavior == 'force' then - if filePath ~= clip_file and file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) + if filePath ~= clip_file and file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) or filePath ~= clip_file and starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('load-file') elseif clip_time ~= nil then trigger_paste_action('file-seek') - elseif file_exists(clip_file) and filePath == clip_file + elseif file_exists(clip_file) and filePath == clip_file or filePath == clip_file and starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('add-playlist') elseif not has_value(o.paste_extensions, currentVideoExtension) then @@ -2828,22 +2743,22 @@ function paste() end end end - end + end end function paste_specific(action) if not action then return end - + if o.osd_messages == true then mp.osd_message("Pasting...") end msg.info("Pasting...") - - clip = get_clipboard(clip) + + clip = mp.get_property('clipboard/text') if not clip then msg.error('Error: clip is null' .. clip) return end clip, clip_file, clip_time, clip_table = parse_clipboard(clip) - + if #clip_table > 1 then multipaste() else @@ -2860,7 +2775,7 @@ function paste_specific(action) trigger_paste_action('error-unknown') end end - + if action == 'timestamp' then if filePath == nil then trigger_paste_action('error-time') @@ -2876,12 +2791,12 @@ function paste_specific(action) trigger_paste_action('error-unknown') end end - + if action == 'force' then - if filePath ~= clip_file and file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) + if filePath ~= clip_file and file_exists(clip_file) and has_value(o.paste_extensions, currentVideoExtension) or filePath ~= clip_file and starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('load-file') - elseif file_exists(clip_file) and filePath == clip_file + elseif file_exists(clip_file) and filePath == clip_file or filePath == clip_file and starts_protocol(o.paste_protocols, clip_file) then trigger_paste_action('error-samefile') elseif not has_value(o.paste_extensions, currentVideoExtension) and not has_value(o.paste_subtitles, currentVideoExtension) then @@ -2899,13 +2814,13 @@ mp.register_event('file-loaded', function() list_close_and_trash_collection() filePath, fileTitle, fileLength = get_file() if clipboard_pasted == true then - clip = get_clipboard(clip) + clip = mp.get_property('clipboard/text') if not clip then msg.error('Error: clip is null' .. clip) return end clip, clip_file, clip_time, clip_table = parse_clipboard(clip) - + if #clip_table > 1 then for i=1, #clip_table do - if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) + if file_exists(clip_table[i][1]) and has_value(o.paste_extensions, clip_table[i][3]) or starts_protocol(o.paste_protocols, clip_table[i][1]) then clip_file = clip_table[i][1] clip_time = clip_table[i][2] @@ -2913,7 +2828,7 @@ mp.register_event('file-loaded', function() end end end - + local video_duration = mp.get_property_number('duration') if not clip_time or clip_time > video_duration or clip_time <= 0 then write_log(0, false, o.same_entry_limit, 'paste') @@ -2922,8 +2837,8 @@ mp.register_event('file-loaded', function() end if filePath == clip_file and clip_time ~= nil then seekTime = clip_time + o.resume_offset - - if seekTime > video_duration then + + if seekTime > video_duration then if o.osd_messages == true then mp.osd_message('Time Paste Exceeds Video Length' .. o.time_seperator .. format_time(clip_time, o.osd_time_format[3], o.osd_time_format[2], o.osd_time_format[1])) end @@ -2934,12 +2849,12 @@ mp.register_event('file-loaded', function() if seekTime < 0 then seekTime = 0 end - + mp.commandv('seek', seekTime, 'absolute', 'exact') clipboard_pasted = false end end - + if resume_selected == true and seekTime ~= nil then mp.commandv('seek', seekTime, 'absolute', 'exact') resume_selected = false