diff options
Diffstat (limited to 'TOOLS')
26 files changed, 1063 insertions, 479 deletions
diff --git a/TOOLS/appveyor-build.sh b/TOOLS/appveyor-build.sh index 0c3aaacedd..a6a7b724a3 100755 --- a/TOOLS/appveyor-build.sh +++ b/TOOLS/appveyor-build.sh @@ -10,15 +10,12 @@ export PYTHON=/usr/bin/python3 "$PYTHON" bootstrap.py "$PYTHON" waf configure \ --check-c-compiler=gcc \ - --disable-egl-angle-lib \ --enable-spirv-cross \ --enable-d3d-hwaccel \ --enable-d3d11 \ - --enable-egl-angle \ --enable-jpeg \ --enable-lcms2 \ --enable-libarchive \ - --enable-libass \ --enable-lua \ --enable-rubberband \ --enable-shaderc \ diff --git a/TOOLS/appveyor-install.sh b/TOOLS/appveyor-install.sh index 15595facf0..95e4f7b4ed 100755 --- a/TOOLS/appveyor-install.sh +++ b/TOOLS/appveyor-install.sh @@ -14,15 +14,17 @@ EOF # Install build dependencies for mpv pacman -S --noconfirm --needed \ $MINGW_PACKAGE_PREFIX-toolchain \ - $MINGW_PACKAGE_PREFIX-angleproject-git \ $MINGW_PACKAGE_PREFIX-cmake \ $MINGW_PACKAGE_PREFIX-lcms2 \ $MINGW_PACKAGE_PREFIX-libarchive \ $MINGW_PACKAGE_PREFIX-libass \ $MINGW_PACKAGE_PREFIX-libjpeg-turbo \ + $MINGW_PACKAGE_PREFIX-libplacebo \ $MINGW_PACKAGE_PREFIX-lua51 \ $MINGW_PACKAGE_PREFIX-ninja \ $MINGW_PACKAGE_PREFIX-rubberband \ + $MINGW_PACKAGE_PREFIX-shaderc \ + $MINGW_PACKAGE_PREFIX-spirv-cross \ $MINGW_PACKAGE_PREFIX-uchardet \ $MINGW_PACKAGE_PREFIX-vulkan @@ -50,23 +52,3 @@ pacman -Sc --noconfirm --enable-schannel make -j4 install ) - -# Compile shaderc -( - git clone --depth=1 https://github.com/google/shaderc && cd shaderc - "$PYTHON" utils/git-sync-deps - - mkdir build && cd build - cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DSHADERC_SKIP_TESTS=ON \ - -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX .. - ninja install -) - -# Compile SPIRV-Cross -( - git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Cross && cd SPIRV-Cross - - mkdir build && cd build - cmake -GNinja -DSPIRV_CROSS_SHARED=ON -DCMAKE_INSTALL_PREFIX=$MINGW_PREFIX .. - ninja install -) diff --git a/TOOLS/dylib-unhell.py b/TOOLS/dylib-unhell.py index 427f00530f..6752e7341c 100755 --- a/TOOLS/dylib-unhell.py +++ b/TOOLS/dylib-unhell.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import re import os @@ -20,19 +20,37 @@ def is_user_lib(objfile, libname): not "libc." in libname and \ not "libgcc." in libname and \ not os.path.basename(libname) == 'Python' and \ - not os.path.basename(objfile) in libname + not os.path.basename(objfile) in libname and \ + not "libswift" in libname def otool(objfile): - command = "otool -L %s | grep -e '\t' | awk '{ print $1 }'" % objfile + command = "otool -L '%s' | grep -e '\t' | awk '{ print $1 }'" % objfile output = subprocess.check_output(command, shell = True, universal_newlines=True) return set(filter(partial(is_user_lib, objfile), output.split())) +def get_rpaths_dev_tools(binary): + command = "otool -l '%s' | grep -A2 LC_RPATH | grep path | grep \"Xcode\|CommandLineTools\"" % binary + result = subprocess.check_output(command, shell = True, universal_newlines=True) + pathRe = re.compile("^\s*path (.*) \(offset \d*\)$") + output = [] + + for line in result.splitlines(): + output.append(pathRe.search(line).group(1).strip()) + + return output + def install_name_tool_change(old, new, objfile): subprocess.call(["install_name_tool", "-change", old, new, objfile]) def install_name_tool_id(name, objfile): subprocess.call(["install_name_tool", "-id", name, objfile]) +def install_name_tool_add_rpath(rpath, binary): + subprocess.call(["install_name_tool", "-add_rpath", rpath, binary]) + +def install_name_tool_delete_rpath(rpath, binary): + subprocess.call(["install_name_tool", "-delete_rpath", rpath, binary]) + def libraries(objfile, result = dict()): libs_list = otool(objfile) result[objfile] = libs_list @@ -43,29 +61,19 @@ def libraries(objfile, result = dict()): return result -def leafs(libs_dict, processed = []): - result = [] - processed = set(processed) - - for objfile, libs in libs_dict.items(): - if libs <= processed: - result.append(objfile) - - return result - def lib_path(binary): return os.path.join(os.path.dirname(binary), 'lib') def lib_name(lib): return os.path.join("@executable_path", "lib", os.path.basename(lib)) -def process_libraries(libs_dict, binary, processed = []): - ls = leafs(libs_dict, processed) - diff = set(ls) - set(processed) - if diff == set([binary]): - return +def process_libraries(libs_dict, binary): + libs_set = set(libs_dict) + # Remove binary from libs_set to prevent a duplicate of the binary being + # added to the libs directory. + libs_set.remove(binary) - for src in diff: + for src in libs_set: name = lib_name(src) dst = os.path.join(lib_path(binary), os.path.basename(src)) @@ -76,21 +84,47 @@ def process_libraries(libs_dict, binary, processed = []): if src in libs_dict[binary]: install_name_tool_change(src, name, binary) - for p in processed: + for p in libs_set: if p in libs_dict[src]: install_name_tool_change(p, lib_name(p), dst) - return ls +def process_swift_libraries(binary): + command = ['xcrun', '--find', 'swift-stdlib-tool'] + swiftStdlibTool = subprocess.check_output(command, universal_newlines=True).strip() + # from xcode11 on the dynamic swift libs reside in a separate directory from + # the std one, might need versioned paths for future swift versions + swiftLibPath = os.path.join(swiftStdlibTool, '../../lib/swift-5.0/macosx') + swiftLibPath = os.path.abspath(swiftLibPath) + + command = [swiftStdlibTool, '--copy', '--platform', 'macosx', '--scan-executable', binary, '--destination', lib_path(binary)] + + if os.path.exists(swiftLibPath): + command.extend(['--source-libraries', swiftLibPath]) + + subprocess.check_output(command, universal_newlines=True) + + print(">> setting additional rpath for swift libraries") + install_name_tool_add_rpath("@executable_path/lib", binary) + +def remove_dev_tools_rapths(binary): + for path in get_rpaths_dev_tools(binary): + install_name_tool_delete_rpath(path, binary) def main(): binary = os.path.abspath(sys.argv[1]) if not os.path.exists(lib_path(binary)): os.makedirs(lib_path(binary)) + print(">> gathering all linked libraries") libs = libraries(binary) - libs_processed = process_libraries(libs, binary) - while libs_processed is not None: - libs_processed = process_libraries(libs, binary, libs_processed) + print(">> copying and processing all linked libraries") + process_libraries(libs, binary) + + print(">> removing rpath definitions towards dev tools") + remove_dev_tools_rapths(binary) + + print(">> copying and processing swift libraries") + process_swift_libraries(binary) if __name__ == "__main__": main() diff --git a/TOOLS/file2string.py b/TOOLS/file2string.py index b40317218c..1f2cd64fdf 100755 --- a/TOOLS/file2string.py +++ b/TOOLS/file2string.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Convert the contents of a file into a C string constant. # Note that the compiler will implicitly add an extra 0 byte at the end @@ -22,27 +22,27 @@ # License along with mpv. If not, see <http://www.gnu.org/licenses/>. # -from __future__ import unicode_literals import sys -# Indexing a byte string yields int on Python 3.x, and a str on Python 2.x -def pord(c): - return ord(c) if type(c) == str else c - def file2string(infilename, infile, outfile): outfile.write("// Generated from %s\n\n" % infilename) - conv = ['\\' + ("%03o" % c) for c in range(256)] + conv = ["\\%03o" % c for c in range(256)] safe_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" \ - "0123456789!#%&'()*+,-./:;<=>?[]^_{|}~ " + "0123456789!#%&'()*+,-./:;<=>[]^_{|}~ " for c in safe_chars: conv[ord(c)] = c for c, esc in ("\nn", "\tt", r"\\", '""'): conv[ord(c)] = '\\' + esc for line in infile: - outfile.write('"' + ''.join(conv[pord(c)] for c in line) + '"\n') + outfile.write('"' + ''.join(conv[c] for c in line) + '"\n') if __name__ == "__main__": + if len(sys.argv) < 2: + outfile = sys.stdout + else: + outfile = open(sys.argv[2], "w") + with open(sys.argv[1], 'rb') as infile: - file2string(sys.argv[1], infile, sys.stdout) + file2string(sys.argv[1], infile, outfile) diff --git a/TOOLS/lua/autocrop.lua b/TOOLS/lua/autocrop.lua index 2316a46d00..3683b9f02a 100644 --- a/TOOLS/lua/autocrop.lua +++ b/TOOLS/lua/autocrop.lua @@ -1,114 +1,329 @@ --- This script uses the lavfi cropdetect filter to automatically --- insert a crop filter with appropriate parameters for the currently --- playing video. --- --- It registers the key-binding "C" (shift+c), which when pressed, --- inserts the filter vf=lavfi=cropdetect. After 1 second, it then --- inserts the filter vf=crop=w:h:x:y, where w,h,x,y are determined --- from the vf-metadata gathered by cropdetect. The cropdetect filter --- is removed immediately after the crop filter is inserted as it is --- no longer needed. --- --- If the "C" key is pressed again, the crop filter is removed --- restoring playback to its original state. --- --- Since the crop parameters are determined from the 1 second of video --- between inserting the cropdetect and crop filters, the "C" key --- should be pressed at a position in the video where the crop region --- is unambiguous (i.e., not a black frame, black background title --- card, or dark scene). --- --- The default delay between insertion of the cropdetect and --- crop filters may be overridden by adding --- --- --script-opts=autocrop.detect_seconds=<number of seconds> --- --- to mpv's arguments. This may be desirable to allow cropdetect more --- time to collect data. +--[[ +This script uses the lavfi cropdetect filter to automatically +insert a crop filter with appropriate parameters for the +currently playing video. + +It will automatically crop the video, when playback starts. + +Also It registers the key-binding "C" (shift+c). You can manually +crop the video by pressing the "C" (shift+c) key. + +If the "C" key is pressed again, the crop filter is removed +restoring playback to its original state. + +The workflow is as follows: First, it inserts the filter +vf=lavfi=cropdetect. After <detect_seconds> (default is 1) +seconds, it then inserts the filter vf=crop=w:h:x:y, where +w,h,x,y are determined from the vf-metadata gathered by +cropdetect. The cropdetect filter is removed immediately after +the crop filter is inserted as it is no longer needed. + +Since the crop parameters are determined from the 1 second of +video between inserting the cropdetect and crop filters, the "C" +key should be pressed at a position in the video where the crop +region is unambiguous (i.e., not a black frame, black background +title card, or dark scene). + +The default options can be overridden by adding +script-opts-append=autocrop-<parameter>=<value> into mpv.conf + +List of available parameters (For default values, see <options>): + +auto: bool - Whether to automatically apply crop at the start of + playback. If you don't want to crop automatically, set it to + false or add "script-opts-append=autocrop-auto=no" into + mpv.conf. + +auto_delay: seconds - Delay before starting crop in auto mode. + You can try to increase this value to avoid dark scene or + fade in at beginning. Automatic cropping will not occur if + the value is larger than the remaining playback time. + +detect_limit: number[0-255] - Black threshold for cropdetect. + Smaller values will generally result in less cropping. + See limit of https://ffmpeg.org/ffmpeg-filters.html#cropdetect + +detect_round: number[2^n] - The value which the width/height + should be divisible by. Smaller values have better detection + accuracy. If you have problems with other filters, + you can try to set it to 4 or 16. + See round of https://ffmpeg.org/ffmpeg-filters.html#cropdetect + +detect_min_ratio: number[0.0-1.0] - The ratio of the minimum clip + size to the original. If the picture is over cropped or under + cropped, try adjusting this value. + +detect_seconds: seconds - How long to gather cropdetect data. + Increasing this may be desirable to allow cropdetect more + time to collect data. + +suppress_osd: bool - Whether the OSD shouldn't be used when filters + are applied and removed. +--]] + require "mp.msg" +require 'mp.options' -script_name = mp.get_script_name() -cropdetect_label = string.format("%s-cropdetect", script_name) -crop_label = string.format("%s-crop", script_name) +local options = { + auto = true, + auto_delay = 4, + detect_limit = "24/255", + detect_round = 2, + detect_min_ratio = 0.5, + detect_seconds = 1, + suppress_osd = false, +} +read_options(options) --- number of seconds to gather cropdetect data -detect_seconds = tonumber(mp.get_opt(string.format("%s.detect_seconds", script_name))) -if not detect_seconds then - detect_seconds = 1 -end +local label_prefix = mp.get_script_name() +local labels = { + crop = string.format("%s-crop", label_prefix), + cropdetect = string.format("%s-cropdetect", label_prefix) +} + +timers = { + auto_delay = nil, + detect_crop = nil +} + +local command_prefix = options.suppress_osd and 'no-osd' or '' -function del_filter_if_present(label) - -- necessary because mp.command('vf del @label:filter') raises an - -- error if the filter doesn't exist - local vfs = mp.get_property_native("vf") - for i,vf in pairs(vfs) do - if vf["label"] == label then - table.remove(vfs, i) - mp.set_property_native("vf", vfs) +function is_filter_present(label) + local filters = mp.get_property_native("vf") + for index, filter in pairs(filters) do + if filter["label"] == label then return true end end return false end -function autocrop_start() - -- exit if cropdetection is already in progress - if timer then - mp.msg.warn("already cropdetecting!") +function is_enough_time(seconds) + + -- Plus 1 second for deviation. + local time_needed = seconds + 1 + local playtime_remaining = mp.get_property_native("playtime-remaining") + + return playtime_remaining and time_needed < playtime_remaining +end + +function is_cropable() + for _, track in pairs(mp.get_property_native('track-list')) do + if track.type == 'video' and track.selected then + return not track.albumart + end + end + + return false +end + +function remove_filter(label) + if is_filter_present(label) then + mp.command(string.format('%s vf remove @%s', command_prefix, label)) + return true + end + return false +end + +function cleanup() + + -- Remove all existing filters. + for key, value in pairs(labels) do + remove_filter(value) + end + + -- Kill all timers. + for index, timer in pairs(timers) do + if timer then + timer:kill() + timer = nil + end + end +end + +function detect_crop() + + -- If it's not cropable, exit. + if not is_cropable() then + mp.msg.warn("autocrop only works for videos.") return end - -- if there's a crop filter, remove it and exit - if del_filter_if_present(crop_label) then + -- Verify if there is enough time to detect crop. + local time_needed = options.detect_seconds + + if not is_enough_time(time_needed) then + mp.msg.warn("Not enough time to detect crop.") return end - -- insert the cropdetect filter - ret=mp.command( + -- Insert the cropdetect filter. + local limit = options.detect_limit + local round = options.detect_round + + mp.command( string.format( - 'vf add @%s:cropdetect=limit=%f:round=2:reset=0', - cropdetect_label, 24/255 + '%s vf pre @%s:cropdetect=limit=%s:round=%d:reset=0', + command_prefix, labels.cropdetect, limit, round ) ) - -- wait to gather data - timer=mp.add_timeout(detect_seconds, do_crop) + + -- Wait to gather data. + timers.detect_crop = mp.add_timeout(time_needed, detect_end) end -function do_crop() - -- get the metadata - local cropdetect_metadata = mp.get_property_native( - string.format("vf-metadata/%s", cropdetect_label) +function detect_end() + + -- Get the metadata and remove the cropdetect filter. + local cropdetect_metadata = + mp.get_property_native( + string.format("vf-metadata/%s", + labels.cropdetect + ) ) + remove_filter(labels.cropdetect) + + -- Remove the timer of detect crop. + if timers.detect_crop then + timers.detect_crop:kill() + timers.detect_crop = nil + end + + local meta = {} - -- use it to crop if its valid + -- Verify the existence of metadata. if cropdetect_metadata then - if cropdetect_metadata["lavfi.cropdetect.w"] - and cropdetect_metadata["lavfi.cropdetect.h"] - and cropdetect_metadata["lavfi.cropdetect.x"] - and cropdetect_metadata["lavfi.cropdetect.y"] - then - mp.command(string.format("vf add @%s:lavfi-crop=w=%s:h=%s:x=%s:y=%s", - crop_label, - cropdetect_metadata["lavfi.cropdetect.w"], - cropdetect_metadata["lavfi.cropdetect.h"], - cropdetect_metadata["lavfi.cropdetect.x"], - cropdetect_metadata["lavfi.cropdetect.y"])) - else - mp.msg.error( - "Got empty crop data. You might need to increase detect_seconds." - ) - end + meta = { + w = cropdetect_metadata["lavfi.cropdetect.w"], + h = cropdetect_metadata["lavfi.cropdetect.h"], + x = cropdetect_metadata["lavfi.cropdetect.x"], + y = cropdetect_metadata["lavfi.cropdetect.y"], + } + else + mp.msg.error("No crop data.") + mp.msg.info("Was the cropdetect filter successfully inserted?") + mp.msg.info("Does your version of ffmpeg/libav support AVFrame metadata?") + return + end + + -- Verify that the metadata meets the requirements and convert it. + if meta.w and meta.h and meta.x and meta.y then + local width = mp.get_property_native("width") + local height = mp.get_property_native("height") + + meta = { + w = tonumber(meta.w), + h = tonumber(meta.h), + x = tonumber(meta.x), + y = tonumber(meta.y), + min_w = width * options.detect_min_ratio, + min_h = height * options.detect_min_ratio, + max_w = width, + max_h = height + } else - mp.msg.error( - "No crop data. Was the cropdetect filter successfully inserted?" + mp.msg.error("Got empty crop data.") + mp.msg.info("You might need to increase detect_seconds.") + return + end + + apply_crop(meta) +end + +function apply_crop(meta) + + -- Verify if it is necessary to crop. + local is_effective = meta.x > 0 or meta.y > 0 + or meta.w < meta.max_w or meta.h < meta.max_h + + if not is_effective then + mp.msg.info("No area detected for cropping.") + return + end + + -- Verify it is not over cropped. + local is_excessive = meta.w < meta.min_w and meta.h < meta.min_h + + if is_excessive then + mp.msg.info("The area to be cropped is too large.") + mp.msg.info("You might need to decrease detect_min_ratio.") + return + end + + -- Remove existing crop. + remove_filter(labels.crop) + + -- Apply crop. + mp.command( + string.format("%s vf pre @%s:lavfi-crop=w=%s:h=%s:x=%s:y=%s", + command_prefix, labels.crop, meta.w, meta.h, meta.x, meta.y ) - mp.msg.error( - "Does your version of ffmpeg/libav support AVFrame metadata?" + ) +end + +function on_start() + + -- Clean up at the beginning. + cleanup() + + -- If auto is not true, exit. + if not options.auto then + return + end + + -- If it is the beginning, wait for detect_crop + -- after auto_delay seconds, otherwise immediately. + local playback_time = mp.get_property_native("playback-time") + local is_delay_needed = playback_time + and options.auto_delay > playback_time + + if is_delay_needed then + + -- Verify if there is enough time for autocrop. + local time_needed = options.auto_delay + options.detect_seconds + + if not is_enough_time(time_needed) then + mp.msg.warn("Not enough time for autocrop.") + return + end + + timers.auto_delay = mp.add_timeout(time_needed, + function() + detect_crop() + + -- Remove the timer of auto delay. + timers.auto_delay:kill() + timers.auto_delay = nil + end ) + else + detect_crop() end - -- remove the cropdetect filter - del_filter_if_present(cropdetect_label) - timer=nil end -mp.add_key_binding("C", "auto_crop", autocrop_start) +function on_toggle() + + -- If it is during auto_delay, kill the timer. + if timers.auto_delay then + timers.auto_delay:kill() + timers.auto_delay = nil + end + + -- Cropped => Remove it. + if remove_filter(labels.crop) then + return + end + + -- Detecting => Leave it. + if timers.detect_crop then + mp.msg.warn("Already cropdetecting!") + return + end + + -- Neither => Do delectcrop. + detect_crop() +end + +mp.add_key_binding("C", "toggle_crop", on_toggle) +mp.register_event("end-file", cleanup) +mp.register_event("file-loaded", on_start) diff --git a/TOOLS/lua/autoload.lua b/TOOLS/lua/autoload.lua index 351b87bbbf..aa7e46d060 100644 --- a/TOOLS/lua/autoload.lua +++ b/TOOLS/lua/autoload.lua @@ -2,9 +2,24 @@ -- the currently played file. It does so by scanning the directory a file is -- located in when starting playback. It sorts the directory entries -- alphabetically, and adds entries before and after the current file to --- the internal playlist. (It stops if the it would add an already existing +-- the internal playlist. (It stops if it would add an already existing -- playlist entry at the same position - this makes it "stable".) -- Add at most 5000 * 2 files when starting a file (before + after). + +--[[ +To configure this script use file autoload.conf in directory script-opts (the "script-opts" +directory must be in the mpv configuration directory, typically ~/.config/mpv/). + +Example configuration would be: + +disabled=no +images=no +videos=yes +audio=yes +ignore_hidden=yes + +--]] + MAXENTRIES = 5000 local msg = require 'mp.msg' @@ -12,7 +27,11 @@ local options = require 'mp.options' local utils = require 'mp.utils' o = { - disabled = false + disabled = false, + images = true, + videos = true, + audio = true, + ignore_hidden = true } options.read_options(o) @@ -22,11 +41,30 @@ function Set (t) return set end -EXTENSIONS = Set { - 'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp', - 'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus', +function SetUnion (a,b) + local res = {} + for k in pairs(a) do res[k] = true end + for k in pairs(b) do res[k] = true end + return res +end + +EXTENSIONS_VIDEO = Set { + 'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp' +} + +EXTENSIONS_AUDIO = Set { + 'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus' } +EXTENSIONS_IMAGES = Set { + 'jpg', 'jpeg', 'png', 'tif', 'tiff', 'gif', 'webp', 'svg', 'bmp' +} + +EXTENSIONS = Set {} +if o.videos then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_VIDEO) end +if o.audio then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_AUDIO) end +if o.images then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_IMAGES) end + function add_files_at(index, files) index = index - 1 local oldcount = mp.get_property_number("playlist-count", 1) @@ -102,6 +140,7 @@ function find_and_add_entries() -- check if this is a manually made playlist if (pl_count > 1 and autoloaded == nil) or (pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then + msg.verbose("stopping: manually made playlist") return else autoloaded = true @@ -114,10 +153,13 @@ function find_and_add_entries() local files = utils.readdir(dir, "files") if files == nil then + msg.verbose("no other files in directory") return end table.filter(files, function (v, k) - if string.match(v, "^%.") then + -- The current file could be a hidden file, ignoring it doesn't load other + -- files from the current directory. + if (o.ignore_hidden and not (v == filename) and string.match(v, "^%.")) then return false end local ext = get_extension(v) diff --git a/TOOLS/lua/command-test.lua b/TOOLS/lua/command-test.lua index dd384818cc..877cacdeb6 100644 --- a/TOOLS/lua/command-test.lua +++ b/TOOLS/lua/command-test.lua @@ -76,6 +76,25 @@ mp.observe_property("vo-configured", "bool", function(_, v) end) + mp.command_native_async({name = "subprocess", args = {"wc", "-c"}, + stdin_data = "hello", capture_stdout = true}, + function(res, val, err) + print("Should be '5': " .. val.stdout) + end) + -- blocking stdin by default + mp.command_native_async({name = "subprocess", args = {"cat"}, + capture_stdout = true}, + function(res, val, err) + print("Should be 0: " .. #val.stdout) + end) + -- stdin + detached + mp.command_native_async({name = "subprocess", + args = {"bash", "-c", "(sleep 5s ; cat)"}, + stdin_data = "this should appear after 5s.\n", + detach = true}, + function(res, val, err) + print("5s test: " .. val.status) + end) -- This should get killed on script exit. mp.command_native_async({name = "subprocess", playback_only = false, @@ -86,10 +105,20 @@ mp.observe_property("vo-configured", "bool", function(_, v) playback_only = false, args = {"sleep", "inf"}}) end) -mp.register_event("shutdown", function() +function freeze_test(playback_only) -- This "freezes" the script, should be killed via timeout. - print("freeze!") - local x = mp.command_native({name = "subprocess", playback_only = false, + counter = counter and counter + 1 or 0 + print("freeze! " .. counter) + local x = mp.command_native({name = "subprocess", + playback_only = playback_only, args = {"sleep", "inf"}}) print("done, killed=" .. utils.to_string(x.killed_by_us)) +end + +mp.register_event("shutdown", function() + freeze_test(false) +end) + +mp.register_event("idle", function() + freeze_test(true) end) diff --git a/TOOLS/lua/nan-test.lua b/TOOLS/lua/nan-test.lua new file mode 100644 index 0000000000..d3f1c8cc8f --- /dev/null +++ b/TOOLS/lua/nan-test.lua @@ -0,0 +1,37 @@ +-- Test a float property which internally uses NaN. +-- Run with --no-config (or just scale-param1 not set). + +local utils = require 'mp.utils' + +prop_name = "scale-param1" + +-- internal NaN, return string "default" instead of NaN +v = mp.get_propert |