summaryrefslogtreecommitdiffstats
path: root/TOOLS
diff options
context:
space:
mode:
Diffstat (limited to 'TOOLS')
-rwxr-xr-xTOOLS/appveyor-build.sh3
-rwxr-xr-xTOOLS/appveyor-install.sh24
-rwxr-xr-xTOOLS/dylib-unhell.py82
-rwxr-xr-xTOOLS/file2string.py20
-rw-r--r--TOOLS/lua/autocrop.lua383
-rw-r--r--TOOLS/lua/autoload.lua54
-rw-r--r--TOOLS/lua/command-test.lua35
-rw-r--r--TOOLS/lua/nan-test.lua37
-rw-r--r--TOOLS/lua/osd-test.lua35
-rw-r--r--TOOLS/lua/skip-logo.lua265
-rw-r--r--TOOLS/lua/test-hooks.lua32
-rwxr-xr-xTOOLS/macos-sdk-version.py68
-rwxr-xr-xTOOLS/macos-swift-lib-directory.py42
-rwxr-xr-xTOOLS/matroska.py19
-rw-r--r--TOOLS/mpv-osd-symbols.sfdir/font.props2
-rw-r--r--TOOLS/mpv-osd-symbols.sfdir/uniE112.glyph15
-rw-r--r--TOOLS/mpv-osd-symbols.sfdir/uniE113.glyph20
-rw-r--r--TOOLS/mpv-osd-symbols.sfdir/uniE114.glyph31
-rw-r--r--TOOLS/mpv-osd-symbols.sfdir/uniE115.glyph27
-rwxr-xr-xTOOLS/osxbundle.py9
-rw-r--r--TOOLS/osxbundle/mpv.app/Contents/Info.plist6
-rw-r--r--TOOLS/osxbundle/mpv.app/Contents/Resources/mpv.conf1
-rwxr-xr-xTOOLS/stats-conv.py4
-rwxr-xr-xTOOLS/travis-rebuild-website2
-rwxr-xr-xTOOLS/umpv43
-rwxr-xr-xTOOLS/zsh.pl283
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