summaryrefslogtreecommitdiffstats
path: root/TOOLS/lua
diff options
context:
space:
mode:
Diffstat (limited to 'TOOLS/lua')
-rw-r--r--TOOLS/lua/acompressor.lua2
-rw-r--r--TOOLS/lua/autocrop.lua246
-rw-r--r--TOOLS/lua/autodeint.lua2
-rw-r--r--TOOLS/lua/autoload.lua298
-rw-r--r--TOOLS/lua/skip-logo.lua2
5 files changed, 326 insertions, 224 deletions
diff --git a/TOOLS/lua/acompressor.lua b/TOOLS/lua/acompressor.lua
index 5fc5063e8d..6a6914076a 100644
--- a/TOOLS/lua/acompressor.lua
+++ b/TOOLS/lua/acompressor.lua
@@ -2,7 +2,7 @@
-- filter including key bindings for adjusting parameters.
--
-- See https://ffmpeg.org/ffmpeg-filters.html#acompressor for explanation
--- of the parameteres.
+-- of the parameters.
local mp = require 'mp'
local options = require 'mp.options'
diff --git a/TOOLS/lua/autocrop.lua b/TOOLS/lua/autocrop.lua
index af6021b75a..ea57d15658 100644
--- a/TOOLS/lua/autocrop.lua
+++ b/TOOLS/lua/autocrop.lua
@@ -1,96 +1,69 @@
--[[
-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.
---]]
+This script uses the lavfi cropdetect filter and the video-crop property to
+automatically crop the currently playing video with appropriate parameters.
+
+It automatically crops the video when playback starts.
+
+You can also manually crop the video by pressing the "C" (shift+c) key.
+Pressing it again undoes the crop.
-require "mp.msg"
-require 'mp.options'
+The workflow is as follows: First, it inserts the cropdetect filter. After
+<detect_seconds> (default is 1) seconds, it then sets video-crop based on the
+vf-metadata values gathered by cropdetect. The cropdetect filter is removed
+after video-crop is set as it is no longer needed.
+Since the crop parameters are determined from the 1 second of video between
+inserting the cropdetect filter and setting video-crop, 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).
+
+If non-copy-back hardware decoding is in use, hwdec is temporarily disabled for
+the duration of cropdetect as the filter would fail otherwise.
+
+These are the default options. They can be overridden by adding
+script-opts-append=autocrop-<parameter>=<value> to mpv.conf.
+--]]
local options = {
+ -- Whether to automatically apply crop at the start of playback. If you
+ -- don't want to crop automatically, add
+ -- script-opts-append=autocrop-auto=no to mpv.conf.
auto = true,
+ -- Delay before starting crop in auto mode. You can try to increase this
+ -- value to avoid dark scenes or fade ins at beginning. Automatic cropping
+ -- will not occur if the value is larger than the remaining playback time.
auto_delay = 4,
+ -- Black threshold for cropdetect. Smaller values will generally result in
+ -- less cropping. See limit of
+ -- https://ffmpeg.org/ffmpeg-filters.html#cropdetect
detect_limit = "24/255",
+ -- 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_round = 2,
+ -- The ratio of the minimum clip size to the original. A number from 0 to
+ -- 1. If the picture is over cropped, try adjusting this value.
detect_min_ratio = 0.5,
- detect_seconds = 1
+ -- How long to gather cropdetect data. Increasing this may be desirable to
+ -- allow cropdetect more time to collect data.
+ detect_seconds = 1,
+ -- Whether the OSD shouldn't be used when cropdetect and video-crop are
+ -- applied and removed.
+ suppress_osd = false,
}
-read_options(options)
-local label_prefix = mp.get_script_name()
-local labels = {
- crop = string.format("%s-crop", label_prefix),
- cropdetect = string.format("%s-cropdetect", label_prefix)
-}
+require "mp.options".read_options(options)
+
+local cropdetect_label = mp.get_script_name() .. "-cropdetect"
timers = {
auto_delay = nil,
detect_crop = nil
}
-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
+local hwdec_backup
+
+local command_prefix = options.suppress_osd and 'no-osd' or ''
function is_enough_time(seconds)
@@ -101,53 +74,64 @@ function is_enough_time(seconds)
return playtime_remaining and time_needed < playtime_remaining
end
-function is_cropable()
- local vid = mp.get_property_native("vid")
- local is_album = vid and mp.get_property_native(
- string.format("track-list/%d/albumart", vid)
- ) or false
+function is_cropable(time_needed)
+ if mp.get_property_native('current-tracks/video/image') ~= false then
+ mp.msg.warn("autocrop only works for videos.")
+ return false
+ end
+
+ if not is_enough_time(time_needed) then
+ mp.msg.warn("Not enough time to detect crop.")
+ return false
+ end
- return vid and not is_album
+ return true
end
-function remove_filter(label)
- if is_filter_present(label) then
- mp.command(string.format('vf remove @%s', label))
- return true
+function remove_cropdetect()
+ for _, filter in pairs(mp.get_property_native("vf")) do
+ if filter.label == cropdetect_label then
+ mp.command(
+ string.format("%s vf remove @%s", command_prefix, filter.label))
+
+ return
+ end
end
- return false
end
-function cleanup()
-
- -- Remove all existing filters.
- for key, value in pairs(labels) do
- remove_filter(value)
+function restore_hwdec()
+ if hwdec_backup then
+ mp.set_property("hwdec", hwdec_backup)
+ hwdec_backup = nil
end
+end
+
+function cleanup()
+ remove_cropdetect()
-- Kill all timers.
for index, timer in pairs(timers) do
if timer then
timer:kill()
- timer = nil
+ timers[index] = nil
end
end
+
+ restore_hwdec()
end
function detect_crop()
+ local time_needed = options.detect_seconds
- -- If it's not cropable, exit.
- if not is_cropable() then
- mp.msg.warn("autocrop only works for videos.")
+ if not is_cropable(time_needed) then
return
end
- -- 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
+ local hwdec_current = mp.get_property("hwdec-current")
+ if hwdec_current:find("-copy$") == nil and hwdec_current ~= "no" and
+ hwdec_current ~= "crystalhd" and hwdec_current ~= "rkmpp" then
+ hwdec_backup = mp.get_property("hwdec")
+ mp.set_property("hwdec", "no")
end
-- Insert the cropdetect filter.
@@ -156,8 +140,8 @@ function detect_crop()
mp.command(
string.format(
- 'vf pre @%s:cropdetect=limit=%s:round=%d:reset=0',
- labels.cropdetect, limit, round
+ '%s vf pre @%s:cropdetect=limit=%s:round=%d:reset=0',
+ command_prefix, cropdetect_label, limit, round
)
)
@@ -168,13 +152,9 @@ end
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)
+ local cropdetect_metadata = mp.get_property_native(
+ "vf-metadata/" .. cropdetect_label)
+ remove_cropdetect()
-- Remove the timer of detect crop.
if timers.detect_crop then
@@ -182,6 +162,8 @@ function detect_end()
timers.detect_crop = nil
end
+ restore_hwdec()
+
local meta = {}
-- Verify the existence of metadata.
@@ -195,7 +177,7 @@ function detect_end()
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?")
+ mp.msg.info("Does your version of FFmpeg support AVFrame metadata?")
return
end
@@ -217,7 +199,6 @@ function detect_end()
else
mp.msg.error("Got empty crop data.")
mp.msg.info("You might need to increase detect_seconds.")
- return
end
apply_crop(meta)
@@ -226,32 +207,27 @@ 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
+ local is_effective = meta.w and meta.h and meta.x and meta.y and
+ (meta.x > 0 or meta.y > 0
+ or meta.w < meta.max_w or meta.h < meta.max_h)
-- Verify it is not over cropped.
- local is_excessive = meta.w < meta.min_w and meta.h < meta.min_h
-
- if is_excessive then
+ local is_excessive = false
+ if is_effective and (meta.w < meta.min_w or meta.h < meta.min_h) then
mp.msg.info("The area to be cropped is too large.")
mp.msg.info("You might need to decrease detect_min_ratio.")
- return
+ is_excessive = true
end
- -- Remove existing crop.
- remove_filter(labels.crop)
+ if not is_effective or is_excessive then
+ -- Clear any existing crop.
+ mp.command(string.format("%s set file-local-options/video-crop ''", command_prefix))
+ return
+ end
-- Apply crop.
- mp.command(
- string.format("vf pre @%s:lavfi-crop=w=%s:h=%s:x=%s:y=%s",
- labels.crop, meta.w, meta.h, meta.x, meta.y
- )
- )
+ mp.command(string.format("%s set file-local-options/video-crop %sx%s+%s+%s",
+ command_prefix, meta.w, meta.h, meta.x, meta.y))
end
function on_start()
@@ -275,8 +251,7 @@ function on_start()
-- 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.")
+ if not is_cropable(time_needed) then
return
end
@@ -303,7 +278,8 @@ function on_toggle()
end
-- Cropped => Remove it.
- if remove_filter(labels.crop) then
+ if mp.get_property("video-crop") ~= "" then
+ mp.command(string.format("%s set file-local-options/video-crop ''", command_prefix))
return
end
@@ -313,7 +289,7 @@ function on_toggle()
return
end
- -- Neither => Do delectcrop.
+ -- Neither => Detect crop.
detect_crop()
end
diff --git a/TOOLS/lua/autodeint.lua b/TOOLS/lua/autodeint.lua
index b891c9a838..4e929607a0 100644
--- a/TOOLS/lua/autodeint.lua
+++ b/TOOLS/lua/autodeint.lua
@@ -8,7 +8,7 @@
-- telecined and the interlacing field dominance.
--
-- Based on this information, it may set mpv's ``deinterlace`` property (which
--- usually inserts the yadif filter), or insert the ``pullup`` filter if the
+-- usually inserts the bwdif filter), or insert the ``pullup`` filter if the
-- content is telecined. It also sets field dominance with lavfi setfield.
--
-- OPTIONS:
diff --git a/TOOLS/lua/autoload.lua b/TOOLS/lua/autoload.lua
index 7150abb95e..e0cfeb2997 100644
--- a/TOOLS/lua/autoload.lua
+++ b/TOOLS/lua/autoload.lua
@@ -16,10 +16,17 @@ disabled=no
images=no
videos=yes
audio=yes
+additional_image_exts=list,of,ext
+additional_video_exts=list,of,ext
+additional_audio_exts=list,of,ext
+ignore_hidden=yes
+same_type=yes
+directory_mode=recursive
--]]
MAXENTRIES = 5000
+MAXDIRSTACK = 20
local msg = require 'mp.msg'
local options = require 'mp.options'
@@ -29,9 +36,25 @@ o = {
disabled = false,
images = true,
videos = true,
- audio = true
+ audio = true,
+ additional_image_exts = "",
+ additional_video_exts = "",
+ additional_audio_exts = "",
+ ignore_hidden = true,
+ same_type = false,
+ directory_mode = "auto"
}
-options.read_options(o)
+options.read_options(o, nil, function(list)
+ split_option_exts(list.additional_video_exts, list.additional_audio_exts, list.additional_image_exts)
+ if list.videos or list.additional_video_exts or
+ list.audio or list.additional_audio_exts or
+ list.images or list.additional_image_exts then
+ create_extensions()
+ end
+ if list.directory_mode then
+ validate_directory_mode()
+ end
+end)
function Set (t)
local set = {}
@@ -40,35 +63,70 @@ function Set (t)
end
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
+ for k in pairs(b) do a[k] = true end
+ return a
+end
+
+function Split (s)
+ local set = {}
+ for v in string.gmatch(s, '([^,]+)') do set[v] = true end
+ return set
end
-EXTENSIONS_VIDEO = Set {
- 'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp'
+EXTENSIONS_VIDEO_DEFAULT = Set {
+ '3g2', '3gp', 'avi', 'flv', 'm2ts', 'm4v', 'mj2', 'mkv', 'mov',
+ 'mp4', 'mpeg', 'mpg', 'ogv', 'rmvb', 'webm', 'wmv', 'y4m'
}
-EXTENSIONS_AUDIO = Set {
- 'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus'
+EXTENSIONS_AUDIO_DEFAULT = Set {
+ 'aiff', 'ape', 'au', 'flac', 'm4a', 'mka', 'mp3', 'oga', 'ogg',
+ 'ogm', 'opus', 'wav', 'wma'
}
-EXTENSIONS_IMAGES = Set {
- 'jpg', 'jpeg', 'png', 'tif', 'tiff', 'gif', 'webp', 'svg', 'bmp'
+EXTENSIONS_IMAGES_DEFAULT = Set {
+ 'avif', 'bmp', 'gif', 'j2k', 'jp2', 'jpeg', 'jpg', 'jxl', 'png',
+ 'svg', 'tga', 'tif', 'tiff', 'webp'
}
-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 split_option_exts(video, audio, image)
+ if video then o.additional_video_exts = Split(o.additional_video_exts) end
+ if audio then o.additional_audio_exts = Split(o.additional_audio_exts) end
+ if image then o.additional_image_exts = Split(o.additional_image_exts) end
+end
+split_option_exts(true, true, true)
+
+function create_extensions()
+ EXTENSIONS = {}
+ EXTENSIONS_VIDEO = {}
+ EXTENSIONS_AUDIO = {}
+ EXTENSIONS_IMAGES = {}
+ if o.videos then
+ SetUnion(SetUnion(EXTENSIONS_VIDEO, EXTENSIONS_VIDEO_DEFAULT), o.additional_video_exts)
+ SetUnion(EXTENSIONS, EXTENSIONS_VIDEO)
+ end
+ if o.audio then
+ SetUnion(SetUnion(EXTENSIONS_AUDIO, EXTENSIONS_AUDIO_DEFAULT), o.additional_audio_exts)
+ SetUnion(EXTENSIONS, EXTENSIONS_AUDIO)
+ end
+ if o.images then
+ SetUnion(SetUnion(EXTENSIONS_IMAGES, EXTENSIONS_IMAGES_DEFAULT), o.additional_image_exts)
+ SetUnion(EXTENSIONS, EXTENSIONS_IMAGES)
+ end
+end
+create_extensions()
+
+function validate_directory_mode()
+ if o.directory_mode ~= "recursive" and o.directory_mode ~= "lazy" and o.directory_mode ~= "ignore" then
+ o.directory_mode = nil
+ end
+end
+validate_directory_mode()
-function add_files_at(index, files)
- index = index - 1
+function add_files(files)
local oldcount = mp.get_property_number("playlist-count", 1)
for i = 1, #files do
- mp.commandv("loadfile", files[i], "append")
- mp.commandv("playlist-move", oldcount + i - 1, index + i - 1)
+ mp.commandv("loadfile", files[i][1], "append")
+ mp.commandv("playlist-move", oldcount + i - 1, files[i][2])
end
end
@@ -89,59 +147,125 @@ table.filter = function(t, iter)
end
end
--- splitbynum and alnumcomp from alphanum.lua (C) Andre Bogus
--- Released under the MIT License
--- http://www.davekoelle.com/files/alphanum.lua
-
--- split a string into a table of number and string values
-function splitbynum(s)
- local result = {}
- for x, y in (s or ""):gmatch("(%d*)(%D*)") do
- if x ~= "" then table.insert(result, tonumber(x)) end
- if y ~= "" then table.insert(result, y) end
+table.append = function(t1, t2)
+ local t1_size = #t1
+ for i = 1, #t2 do
+ t1[t1_size + i] = t2[i]
end
- return result
end
-function clean_key(k)
- k = (' '..k..' '):gsub("%s+", " "):sub(2, -2):lower()
- return splitbynum(k)
-end
+-- alphanum sorting for humans in Lua
+-- http://notebook.kulchenko.com/algorithms/alphanumeric-natural-sorting-for-humans-in-lua
--- compare two strings
-function alnumcomp(x, y)
- local xt, yt = clean_key(x), clean_key(y)
- for i = 1, math.min(#xt, #yt) do
- local xe, ye = xt[i], yt[i]
- if type(xe) == "string" then ye = tostring(ye)
- elseif type(ye) == "string" then xe = tostring(xe) end
- if xe ~= ye then return xe < ye end
+function alphanumsort(filenames)
+ local function padnum(n, d)
+ return #d > 0 and ("%03d%s%.12f"):format(#n, n, tonumber(d) / (10 ^ #d))
+ or ("%03d%s"):format(#n, n)
end
- return #xt < #yt
+
+ local tuples = {}
+ for i, f in ipairs(filenames) do
+ tuples[i] = {f:lower():gsub("0*(%d+)%.?(%d*)", padnum), f}
+ end
+ table.sort(tuples, function(a, b)
+ return a[1] == b[1] and #b[2] < #a[2] or a[1] < b[1]
+ end)
+ for i, tuple in ipairs(tuples) do filenames[i] = tuple[2] end
+ return filenames
end
local autoloaded = nil
+local added_entries = {}
+local autoloaded_dir = nil
+
+function scan_dir(path, current_file, dir_mode, separator, dir_depth, total_files, extensions)
+ if dir_depth == MAXDIRSTACK then
+ return
+ end
+ msg.trace("scanning: " .. path)
+ local files = utils.readdir(path, "files") or {}
+ local dirs = dir_mode ~= "ignore" and utils.readdir(path, "dirs") or {}
+ local prefix = path == "." and "" or path
+ table.filter(files, function (v)
+ -- 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 (prefix .. v == current_file) and string.match(v, "^%.")) then
+ return false
+ end
+ local ext = get_extension(v)
+ if ext == nil then
+ return false
+ end
+ return extensions[string.lower(ext)]
+ end)
+ table.filter(dirs, function(d)
+ return not ((o.ignore_hidden and string.match(d, "^%.")))
+ end)
+ alphanumsort(files)
+ alphanumsort(dirs)
+
+ for i, file in ipairs(files) do
+ files[i] = prefix .. file
+ end
+
+ table.append(total_files, files)
+ if dir_mode == "recursive" then
+ for _, dir in ipairs(dirs) do
+ scan_dir(prefix .. dir .. separator, current_file, dir_mode,
+ separator, dir_depth + 1, total_files, extensions)
+ end
+ else
+ for i, dir in ipairs(dirs) do
+ dirs[i] = prefix .. dir
+ end
+ table.append(total_files, dirs)
+ end
+end
function find_and_add_entries()
+ local aborted = mp.get_property_native("playback-abort")
+ if aborted then
+ msg.debug("stopping: playback aborted")
+ return
+ end
+
local path = mp.get_property("path", "")
local dir, filename = utils.split_path(path)
msg.trace(("dir: %s, filename: %s"):format(dir, filename))
if o.disabled then
- msg.verbose("stopping: autoload disabled")
+ msg.debug("stopping: autoload disabled")
return
elseif #dir == 0 then
- msg.verbose("stopping: not a local path")
+ msg.debug("stopping: not a local path")
return
end
local pl_count = mp.get_property_number("playlist-count", 1)
+ this_ext = get_extension(filename)
-- 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")
+ (pl_count == 1 and EXTENSIONS[string.lower(this_ext)] == nil) then
+ msg.debug("stopping: manually made playlist")
return
else
- autoloaded = true
+ if pl_count == 1 then
+ autoloaded = true
+ autoloaded_dir = dir
+ added_entries = {}
+ end
+ end
+
+ local extensions = {}
+ if o.same_type then
+ if EXTENSIONS_VIDEO[string.lower(this_ext)] ~= nil then
+ extensions = EXTENSIONS_VIDEO
+ elseif EXTENSIONS_AUDIO[string.lower(this_ext)] ~= nil then
+ extensions = EXTENSIONS_AUDIO
+ else
+ extensions = EXTENSIONS_IMAGES
+ end
+ else
+ extensions = EXTENSIONS
end
local pl = mp.get_property_native("playlist", {})
@@ -149,31 +273,22 @@ function find_and_add_entries()
msg.trace(("playlist-pos-1: %s, playlist: %s"):format(pl_current,
utils.to_string(pl)))
- local files = utils.readdir(dir, "files")
- if files == nil then
- msg.verbose("no other files in directory")
- return
+ local files = {}
+ do
+ local dir_mode = o.directory_mode or mp.get_property("directory-mode", "lazy")
+ local separator = mp.get_property_native("platform") == "windows" and "\\" or "/"
+ scan_dir(autoloaded_dir, path, dir_mode, separator, 0, files, extensions)
end
- table.filter(files, function (v, k)
- if string.match(v, "^%.") then
- return false
- end
- local ext = get_extension(v)
- if ext == nil then
- return false
- end
- return EXTENSIONS[string.lower(ext)]
- end)
- table.sort(files, alnumcomp)
- if dir == "." then
- dir = ""
+ if next(files) == nil then
+ msg.debug("no other files or directories in directory")
+ return
end
-- Find the current pl entry (dir+"/"+filename) in the sorted dir list
local current
for i = 1, #files do
- if files[i] == filename then
+ if files[i] == path then
current = i
break
end
@@ -183,38 +298,49 @@ function find_and_add_entries()
end
msg.trace("current file position in files: "..current)
+ -- treat already existing playlist entries, independent of how they got added
+ -- as if they got added by autoload
+ for _, entry in ipairs(pl) do
+ added_entries[entry.filename] = true
+ end
+
local append = {[-1] = {}, [1] = {}}
for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1
for i = 1, MAXENTRIES do
- local file = files[current + i * direction]
- local pl_e = pl[pl_current + i * direction]
+ local pos = current + i * direction
+ local file = files[pos]
if file == nil or file[1] == "." then
break
end
- local filepath = dir .. file
- if pl_e then
- -- If there's a playlist entry, and it's the same file, stop.
- msg.trace(pl_e.filename.." == "..filepath.." ?")
- if pl_e.filename == filepath then
- break
+ -- skip files that are/were already in the playlist
+ if not added_entries[file] then
+ if direction == -1 then
+ msg.verbose("Prepending " .. file)
+ table.insert(append[-1], 1, {file, pl_current + i * direction + 1})
+ else
+ msg.verbose("Adding " .. file)
+ if pl_count > 1 then
+ table.insert(append[1], {file, pl_current + i * direction - 1})
+ else
+ mp.commandv("loadfile", file, "append")
+ end
end
end
-
- if direction == -1 then
- if pl_current == 1 then -- never add additional entries in the middle
- msg.info("Prepending " .. file)
- table.insert(append[-1], 1, filepath)
- end
- else
- msg.info("Adding " .. file)
- table.insert(append[1], filepath)
+ added_entries[file] = true
+ end
+ if pl_count == 1 and direction == -1 and #append[-1] > 0 then
+ for i = 1, #append[-1] do
+ mp.commandv("loadfile", append[-1][i][1], "append")
end
+ mp.commandv("playlist-move", 0, current)
end
end
- add_files_at(pl_current + 1, append[1])
- add_files_at(pl_current, append[-1])
+ if pl_count > 1 then
+ add_files(append[1])
+ add_files(append[-1])
+ end
end
mp.register_event("start-file", find_and_add_entries)
diff --git a/TOOLS/lua/skip-logo.lua b/TOOLS/lua/skip-logo.lua
index 8e1f9da489..ae66b22250 100644
--- a/TOOLS/lua/skip-logo.lua
+++ b/TOOLS/lua/skip-logo.lua
@@ -232,7 +232,7 @@ local function read_frames()
end
end
-mp.observe_property(meta_property, "none", function()
+mp.observe_property(meta_property, "native", function()
-- Ignore frames that are decoded/filtered during seeking.
if seeking then
return