At the issue templates "tested with the latest version" checkbox, make
that a link to the latest version, revise the text slightly, and add
"or newer".
At the linux issue template, also note that if the distro does not
provide the latest version, then the issue should be reported to them.
Previously stats_time_start first sampled cpu-time and then real-time,
while stats_time_end sampled them in reverse order.
This resulted in real-time delta values being possibly a bit smaller
than the respective cpu-time deltas, which could become meaningful if
the start/end durations are consistently very short and very frequent.
In one test case (measuging the time spent at the event loop of
a script which spins on zero timeouts), this resulted in accumulated
real-time value of ~230ms per second, with a respective cpu-time
values of ~500ms. This should not be possible with single thread load.
Now start and end sample the values at the same order, so that it
balances on average. Each start/end delta now includes overhead of one
of each sample type, and excludes one of each sample type on average.
With the test case above, it's now 490 +-1 ms for both.
(the other 510ms real-time are at the excluded mpv_wait_event calls
and the unmeasured-overhead-parts of stats_time_start/end).
This fixes a bug where if stats reset happened after stats_time_start
and before stats_time_end, then the next reported cpu-time value of
that measurement was from the thread startup.
The long version:
stats resets the time-accumulated values if more than two seconds
ellapsed since last poll.
The reset keeps the elements, but makes them as if no measurement was
yet taken, so that they don't show up at new reports until a new
measurement is taken.
While the events and (untimed) cpu are reset, the timed-cpu value
was only partially reset - the values are reset but the indication
that the element is empty was not enough for stats_time_end.
So when reset happened between start/end calls, stats_time_end was
entered eventhough it shouldn't have, but with reset cpu-time value
it calculated the time since the thread's startup, hence this bug.
Further polls were ok, because they are of the delta since the
previous poll. But at the next reset it happened again.
Now the cpu-value is reset correctly, which fixes this bug.
stats_time_start and stats_time_end accumulate real-time and cpu-time
between these calls, but the total was only updated on stats_time_end.
This resulted in two issues:
- Inaccurate measured value if a report (read the perf-info property)
happened between start/end. No biggie because it's OK on average and
typically each start/end duration is quite smaller than the interval.
- If the start/end duration is bigger than the interval, then one or
more intervals had a report value (delta) of 0, and then one report
with a value bigger than the interval - which shouldn't be possible.
This commit effectively does end+start at the report time for ongoing
timed measurements, so that the report accounts for them too.
Doing end+start at the report required two more changes:
Store the element type (VAL_TIME) at stats_time_start rather than at
the end. Otherwise if the report happens after the first start but
before the first end, then the type is not yet set and the element
is skipped at the report (bypassing the end+start).
Store the thread id at the element. start/end measure the cpu-time at
the current thread so they used pthread_self(), but with the report
usually running on a different thread, it needs the thread id for the
measurement. Measuring cpu-time from a different thread is OK, and
already happens with VAL_THREAD_CPU_TIME elements during the report.
While at it, stats_time_end now uses the thread id which was stored on
start instead of using pthread_self(). This also serves as a general
protection against measuring start/end from different threads, which
would yield generally meaningless results anyway. In mpv all the
start/end calls for the same element are at the same thread.
On Windows and any other platform where cpu-time is unsuported,
previously the cpu-time was reported as 0, and now it's omitted
(at the perf-info property native value).
Code which process this report, like stats.lua, could not distinguish
between 0 which was due to unsupported platform, and "real" 0 which
indicates zero cpu activity in this poll-period.
In stats.lua this resulted in a whole lot of empty cpu graphs,
including one for every loaded script.
Now cpu-time is excluded from the report on unsupported platforms.
Real-time is obviously still being reported where requested.
Implementation wise, this is slightly hacky, by literally only
excluding the cpu-time nodes from the report itself, while keeping
all the other cpu-tinme code intact.
A more correct solution might be to identify support at compile
(configure) time, and no-op the relevant code if needed.
However, stats.c is already hacky in parts, and there's no real cost
to keeping the code active even if the result is excluded at the
report, and it's also way simpler and less bug prone. So be it.
This reverts:
3fb4140c lua/defaults: add user_data helpers
68a20e7a javascript/defaults: add user_data helpers
00510379 lua/js: fix user_data_del util function
As well as the lua/js parts of:
3ec2a098 docs: document new user-data property
user-data and its sub-properties can be set/get/observed/deleted
via the standard properties interface, so there's no need for
additional helpers specific to user-data, which only added maintenance
burden.
Previously, if log-file was set not via a CLI option (e.g. set via
mpv.conf or other config file, or set from a script init phase),
then meaningful early log messages were thrown away because the log
file name was unknown initially.
Such early log messages include the command line arguments, any
options set from mpv.conf, and possibly more.
Now we store up to 5000 early messages before the log file name is
known, and flush them once/if it becomes known, or destroy this
buffer once mpv init is complete.
The implementation is similar and adjacent, but not identical, to an
existing early log system for mpv clients which request a log buffer.
Commit 7f4841ff sorted the bindings so that if the same key was bound
more than once, then the newest binding takes priority (sorted last).
However, it got the comparison function wrong, which means the result
of the sort depended on the algorithm and not on the actual data, so
the priority for keys with more than one binding was still arbitraty.
Fix the sort function, and finally ensure that later binding acutally
override earlier bindings of the same key.
TL;DR: previously a JavaScript VM was created + destroyed whenever
a sub track was initialized, even if no jsre filter was set.
Now a JS VM is created only if jsre filters were set.
Sub filters are initialized once when a subtitle track is chosen, and
then whenever the sub track changes or when some sub options change.
Sub filters init is synchronous - playback is suspended till it ends.
A filter can abort init early (get disabled) depending on conditions
specific to each filter. The regex and jsre filters aborted early
if the filter is disabled (default is enabled) or if the track is not
ass (relativey rare, e.g. bitmap subs).
The init then iterates over the filter strings, and if the result is
empty (common - no filter was added, but also if all strings failed
regex init) then it's also aborted during init.
While this iteration step is cheap with filter regex, with jsre it
requires instanciating the JS VM (mujs) in advance in order to parse
the filter strings at the list, and the VM is then destroyed if the
list ends up empty.
This VM create+destroy is fast but measurable (0.2 - 0.7 ms, slowest
measured on 2010 MacBook Air), but can be avoided altogether if we
check that the filter list is not empty before we create the VM.
So now we do just that.
Previously, when mpv was invoked with unsupported hwdec value, such
as --hwdec=foobar, there was no indication that it doesn't exist.
The reason it's not validated during options parsing is that the name
is only evaluated when selecting hwdec for actual decoding, by
matching it against runtime list of names from ffmpeg.
Additionally, when selecting hwdec for decoding, matching the name
came after filtering by codec, hence overall never-matched-name did
not necessarily indicate it's unsupported (doesn't exist at all).
Now we check the name before filtering by codec, and when done,
warn if no hwdec with that name exists at all.
This means that an unsupported name will now generate such warning
whenever we try to choose a hwdec, i.e. possibly more than once.
It's much better than no notification at all, and arguably adequate
for a sort of configuration error (linked ffmpeg has no such hwdec
name) which we don't validate during option parsing.
Previously only status<0 was considered as error, but status>0 is
also an error (the process exit code). Change to status != 0.
This likely makes little to no difference in practice, because if
stdout is empty or can't be parsed as JSON then it's considered
an error anyway, but still, this is more correct.
Also, on error, add the complete subprocess result to the verbose log.
Page 2 displays the frame timing info for each type (currently "Fresh"
and "Redraw"), but since they're unordered keys of a map, their
iteration order and hence their order on screen could (and did) change
depending on $things, which was annoying.
haasn thinks none of them should be considered more important (and
therefore maybe worthy of being displayed on top), so we go with
lexicographic order, which currently means that "Fresh" is first.
Fixes#9901
This fixes two potential divisions by 0 at generate_graph(...):
- If v_avg is (given and) 0.
- if v_max is 0.
The former doesn't seem to happen in practice because v_avg is only
used at one generate_gpah call, where it's apparently not 0.
The latter triggers if all the graph values are 0 (hence v_max is
also 0).
The implication of these divisions by 0 is an invalid y-value which
ends up at the ASS coordinates string for the graph inner content.
On linux the value ends as "nan" (luajit) or "-nan" (lua 5.1/5.2), and
on Windows it's "nan" (luajit) or "-1.#IND00" (lua 5.1/5.2), maybe due
to msvcrt's snprintf.
All these strings are wrong as ASS numbers, but due to luck in how
libass parses the coordinates, "nan" and "-nan" result in empty graph
(which looks OK for "all values are 0"), while "-1.#IND00" is parsed
as -1, which breaks the graph rendering (affects other graphs too).
One example of "all values are 0" is at page 0 (internal performance
graphs) on Windows - because the cpu metrics don't work.
So this fixes at least page 0 on Windows with lua 5.1/5.2.
While at it, move the scale calculations to one place, which now
avoids division by 0, instead of duplicating this calculation.
In the future, we can consider improving the generate_graph API:
- It needs one peak value, but takes 3 (v_max, v_avg, scale) which
are meshed into one final value.
- v_avg is only used in 1 of 6 call sites, but at the middle of the
arguments, so all other call sites need to pass explicit "nil".
- "scale" is arbitrary and used to leave some space at the top of the
graph. 5 places use 0.8, one uses 0.9. Could probably be unified.
This speeds up chapter name access while hovering the seekbar:
- Fetch the chapter-list property using observation rather than on
every render while hovering the bar. Property access, especially
with potentially lots of values (chapters), can be expensive-ish,
and can involve locking, so the less per-render the better.
- Sort the list once (on change) to simplify the iteration logic when
searching the chapter which matches the mouse position. It's still
O(N) (no binary search currently), but with less work.
The cached sorted list is stored at the state. While there are other
places which access this property and could use this cache, for now we
don't touch them, because they're not performance-critical (on init
for the chapter markers, on ch_{prev,next} button click for OSD).
Caching properties using observation instead of using mp.get_property
can indeed speedup other places too, but it should be part of a system
rather than implemented per-property. Maybe some day.
When utils.get_user_path was added, the expand-path command didn't
exist. Now it does, so remove the C code, make it a trivial wrapper.
Keep this function for backward compat to not break scripts, but
technically it's not required anymore.
The docs specify that the +-X+-Y geometry values position the content.
This used to work correctly but got broken at 8fb4fd9a .
Geometry size is unaffected - this only concerns position.
Commit 8fb4fd9a made it center the window rather than the content by
taking the borders into account during positioning, but forgot to make
an exception when a position is specified explicitly.
This commit adds this exception, and now if a specific position is
requested then the borders are ignored, and the content is positioned
correctly.
Currently the profile-restore field is intentionally omitted if it
holds the default value (i.e. no values are stored for the profile,
and trying to restore would only warn).
See m_config_get_profiles at command.c .
This reverts commit 04f0b0abe4.
It's not a good idea to unify the names only for visibility, while
keeping secondary-* for everything else.
This needs a bit more thought before we allow secondary sub to be
visible on its own.
This commit is mainly for correcting the previous commit message.
The previous commit fixed an issue where [un]registering events above
the first event ID "hole" is not requested from libmpv, and that's
indeed true.
However, this had nearly zero impact in practice, because libmpv
enables all events by default anyway (except TICK).
Therefore, above the first ID "hole" [un]register requests are not
sent to libmpv, and the events just keep arriving.
But the callback functions are still added/removed correctly (at
defaults.js), and so the script is not called back even if unregister
did not actually happen with libmpv.
The only event which was affected is TICK - which is not enabled by
default as it's deprecated, and before the previous commit could not
be enabled.
So the fix is more a general correctness fix now that the IDs array
can have "holes", but with effctively no impact in practice.
Commit 63205981 removed some events but left all other event IDs at
their original values, which created "holes" at the events IDs array.
The JS backend for mp.register_event maps a name to an ID by scanning
all IDs and stopping when the name was found or a NULL name was
returned. Lua does the same except that it doesn't stop on NULL name.
Previously it was not possible to have a NULL name before the end of
the array, but now it is possible due to the enumeration holes.
Fix by skipping missing names, like lua does.
Previously OSD was always displayed on {ch,pl}_{next,prev} left-click,
and seekbar-hover-chapter was always enabled and with fixed format.
Now it can be controlled with:
- chapters_osd, playlist_osd: yes/no (only affects left-click).
- chapter_fmt: lua string.format template, or "no" to disable.
Fixes#4675
The problem with the previous code - which used mp.get_user_path, is
that it returns a path even with --no-config, and even if the file
doesn't exist.
This is why we tested the "config" property, and also used
mp.utils.file_info to check that the file exists.
mp.find_config_file doesn't return a path with no-cofig and doesn't
return a path if the file doesn't exists. It's simpler and better.
Normally there was no issue, but when the code converted a deeply
nested table into an mpv node - it didn't ensure the stack has room.
Lua doesn't check stack overflow when invoking lua_push* functions,
and leaves this responsibility to the (c) user via lua_checkstack.
Normally that's not an issue because when a lua (or autofree) function
is called, it's guaranteed at least LUA_MINSTACK (20) pushes.
However, pushnode and makenode are recursive, and each iteration can
add few values at the stack (which are popped when the recursion
unwinds), so checkstack must be used on (recursive) entry.
pushnode already checked the stack, makenode did not.
This commit checks the stack at makenode as well. The value of 6
(stack places to reserve) is with some room to spare, and in pratice
each iteration needs 2-3 at most (pushnode also leaves room).
Example which could previously corrupt the stack:
utils.format_json({d1={d2={<8 more times>}}}
This uses makenode to convert the lua table into an mpv node which
the json writer uses as input, and if the depth is 10 or more then
corruption could occur. mp.command_native is also affected, as well as
any other mp/utils command which takes a lua table as input.
While at it, fix the error string which pushnode used (luaL_checkstack
uses the provided string with "Stack overflow (%s)", so the user
message only needs to be additional info).
The speedup is due to moving big part of the autofree runtime overhead
(new lua c closure) to happen once on init at af_pushcclosure, instead
of on every call. This also allows supporting upvalues trivially, even
if mpv doesn't use it currently, and is more consistent with lua APIs.
While x2 infrastructure speedup is meaningful - and similar between
lua 5.1/5.2/jit, in practice it's a much smaller improvement because
the autofree overhead is typically small compared to the "real" work
(the actual functionality, and talloc+free which is needed anyway).
So with this commit, fast functions improve more in percentage.
E.g. utils.parse_json("0") is relatively fast and is now about 25%
faster, while a slower call like mp.command_native("ignore") is now
about 10% faster than before. If we had mp.noop() which does nothing
(but still "needs" alloc/free) - it would now be about 50% faster.
Overall, it's a mild performance improvements, the API is now more
consistent with lua, and without increasing code size or complexity.
mpv doesn't have other dot files in its config dir, and it also
shouldn't be "invisible".
The new name ~~/init.js now replaces ~~/.init.js
While mpv usually deprecates things before outright removing them,
in this case the old (dot) name is replaced without deprecation:
- It's a bad idea to execute hidden scripts, even if at a config dir,
and we don't want to do that for the next release cycle too.
- We warn if the old (dot) name exists and the new name doesn't,
which should be reasonably visible for affected users.
- It's likely niche enough to not cause too much pain.
If for some reason both names are needed, e.g. when using also an old
mpv versions, then the old name could be symlinked to the new one, or
simply have one line: `require("~~/init")` to load the new name, while
a new mpv version will load (only) the new name without warning.
The custom init script should be considered a configuration file, and
as such it should be ignored when the user wants vanilla mpv - and now
it is ignored with --no-config.
This is similar to [no-]input-default-bindings, but affects only
builtin bindings (while input-default-bindings affects anything which
config files can override, like scripting mp.add_key_binding).
Arguably, this is what input-default-binding should have always done,
however, it does not.
The reason we add a new option rather than repurpose/modify the
existing option is that it behaves differently enough to raise
concerns that it will break some use cases for existing users:
- The new option is only applied once on startup, while
input-default-bindings can be modified effectively at runtime.
- They affects different sets of bindings, and it's possible that
the set of input-default-bindings is useful enough to keep.
Implementation-wise, both options are trivial, so keeping one or the
other or both doesn't affect code complexity.
It could be argued that it would be useful to make the new option
also effective for runtime changes, however, this opens a can of
worms of how the bindings are stored beyond the initial setup.
TL;DR: it's impossible to differentiate correctly at runtime between
builtin bindings, and those added with mp.add_key_bindings.
The gist is that technically mpv needs/uses two binding "classes":
- weak/builtin bindings - lower priority than config files.
- "user" bindings - config files and "forced" runtime bindings.
input-default-bindings affects the first class trivially, but
input-builtin-bindings would not be able split this class further
at runtime without meaningful changes to a lot of delicate code.
So a new option it is. It should be useful to some libmpv clients
(players) which want to disable mpv's builtin bindings without
breaking mp.add_key_bindings for scripts.
Fixes#8809
(again. the previous fix 8edfe70b only improved the docs, while
now we're actually making the requested behavior possible)
Before this commit, animation-end was handled at render(), however,
it's not called on idle, which resulted in state.anitype ~= nil, with
nothing to reset it during idle, which caused in an infinite tick()
loop (starts on first mouse move).
Now tick resets the animation on idle, and also, as a safety measure,
if we're past 1s after the animation deadline.
The safety measure is because the osc states are complex, and it's
easier to detect a "we really shouldn't be animating now" at tick()
itself rather than detecting the exact states where animation should
be reset. Generally, the safety mmeasure is not needed.
TL;DR: use --lua=XXX for pkg-config name XXX, e.g. --lua=lua-5.1 .
For unversioned 'lua.pc', use the name luadef51/luadef52 .
Autodetection remains the same (5.2 names, luajit, 5.1 names).
The old names are still supported, but not auto-detected.
Before this patch, if one wanted to choose a specific lua version when
more than one is installed, then the names were a mess, e.g. 51obsd is
also the name detected on Arch linux, and other (distro) names are
also not unique to a specific distro/platform.
So to ask mpv to choose the package name (specifically, the pkg-config
file name), one needs to look at the mpv sources and find the
(arbitrary) distro name which has the same lua version naming as they
do on their own system, e.g. --lua=51obsd on Arch. This is a pain.
Now we add generic names:
- luadef51/luadef52 - generic pkg-config lua.pc (version is inside).
- lua* - exactly the pkg-config name, e.g. --lua=lua-51 for lua-51.pc
(the names are curated, e.g. --lua=foo won't detect foo.pc).
- The legacy names (e.g. 51deb) are still supported, but undocumented,
and the new generic names take precedence during auto-detection.
The fact that the generic names all start with "lua" has an additional
benefit that it shows right after "lua" at the output of mpv -v,
while the old names start with numbers, so they're first at the list,
making it hard to understand that e.g. "51obsd" is the lua version.
None of these names are actually used at the mpv code. The C code
checks the version using the lua headers (LUA_VERSION_NUM).
The lua version names which are autodetected/chosen (such as "51deb")
are used for two things:
- as key for storing the pkg-config compile/link flags.
- as ID for config.h and elsewhere - they're sanitized to use "_".
Due to some inconsistensies, if the sanitized ID is different than
the original name, then the compile/link flags are stored with the
original name as key, while the retrieval happens with the sanitized
ID - and therefore fails to find the correct flags.
The solution is to use the original name only for display purpose at
the output of configure, while using the sanitized version for
everything else, so that storage and retrieval use the same key.
Currently there's no issue and the patch has no effect, because the
sanitizer considers all the current names as valid IDs.
However, the next commit will add names which the sanitizer modifies,
such as "lua-5.1", so this commit makes such names work too.
Previously, loading ~~/.init.js was inside a try block, in order to
quietly ignore errors if the file doesn't exist.
However, that also prevented any real errors from showing up even when
the file does exist, and the script continued as if everything is OK,
while in fact the custom init script didn't complete correctly.
Now we first check if the file exists, and then load it without
try/catch, so that any error shows up normally (and abort the script).
Before this commit, timeBeginPeriod(1) was set once when mpv starts,
and the timers remained hi-res till mpv exits.
Now we do the same as before on Windows version < 10.
On Windows 10+ we now use timeBeginPeriod if needed, per timeout.
To force a mode regardless of Windows version, set env MPV_HRT:
- "always": the old behavior - hires timers as long as mpv runs.
- "perwait": sets 1ms timer resolution if timeout <= 50ms.
- "never": don't use timeBeginPeriod at all.
It was observed that on Windows 10 we lose about 0.5ms accuracy of
timeouts with "perwait" mode (acceptable), but otherwise it works
well for continuous timeouts (one after the other) and random ones.
On Windows 7 with "perwait": continous timeouts are accurate, but
random timeouts (after some time without timeouts) have bad
accuracy - roughly 16ms resolution instead of the requested 1ms.
Windows 8 was not tested, so to err on the side of caution, we keep
the legacy behavior "always" by default.
Last time it was extended was de3ecc60 from 8K to 512K two years ago.
The issue currently is that youtube EDL files can get very big.
Size of about 520K (one line), was observed, at the time of writing:
mpv https://youtube.com/watch?v=DBzFQgSMHdQ --ytdl-format=299
ytdl_hook.lua is unaffected by this because EDL lists don't go through
the file reader at demux_playlist.c (where each line was limited to
512K before this commit), however, EDL files on disk which are
loaded with --playlist=file.edl do.
Increase the limit to 2M so that such EDL files can also be loaded
from disk.
Fixes#9186
Previously, the initial positioning and fit ignored the borders, and
centered the content (the video itself) at the working area.
Now, the initial positioning centers the window, by subtracting the
borders (if needed) from the target area for the initial fit/position.
While this does mean that the initial maximum content area is now
smaller than before, ultimately this has no impact on the window size,
because fit_on_screen is called later and, if needed, further shrinks
the window to fit the borders too - but without centering the window.
So the net impact of this commit is only the initial positioning (same
size as before), which now centers the window instead of the content.
Note that on Windows 10 the borders include invisible areas at the
sides and bottom of the window (for mouse edge-drag), so visibly the
window is nearer to the top than to the bottom, but these are the
metrics we have (fit_on_screen uses the same border size values).
On Windows 7 it looks perfectly centered.
The --monitoraspect value is calculated at vo_calc_window_geometry2
(VCWG2) or VCWG3, and applied via vo_apply_window_geometry.
Before this commit, the screen size which the win32 VO used with
VCWG2 was the working area (screen minus taskbar). This allows better
fitting, but breaks the pixelaspect calculation which is derived from
the --monitoraspect value and this rectangle.
VCWG3 allows an independent size for the aspect calculations, and now
we use it independently of the fit size.
vo_calc_window_geometry2 (VCWG2) calculates both the pixelaspect and
the autofit sizes based on one "screen" rectangle.
However, these two calculations might need two different "screen"
rects if the fit should take into account decorations and/or taskbar
etc, while pixelaspect should be based on the full (monitor) rect.
VCWG3 does just that. It's the same as VCWG2, but with an additional
monitor rect which is used exclussively to calculate pixelaspect,
while the "screen" argument is used for fitting (like before).
VCWG2 now uses/calls VCWG3 with the same screen and monitor rects.
Currently yet unused.
If an unknown ESC sequence is detected where an ASCII char <X> follows
the ESC, mpv interprets it as ALT+<X>, which is the traditional
terminal encoding of ALT+letter.
However, if <X> is '[' then it's a CSI sequence which continues after
the '[', and has its own termination rules (can be many chars).
Previously, mpv interpreted unknown CSI sequences as (incorrect) ALT+[
followed by (incorrect) "keys" from the rest of the sequence.
In this commit, if a unknown CSI sequence is detected, mpv ignores
exactly the complete sequence.
The "cycle" command _declaration_ enables repeatability by default,
however, the command handler applies additional logic to augment it,
based on the property which is being cycled - using some guesswork.
Specifically, properties with discrete values are not repeatable
(like sub or osd-level), while continuous properties are repeatable
(like volume).
Previously, the "repeatable" prefix could not override this additional
logic.
This commit changes the behavior so that the logic affects only the
default repeatability (still based on the property like before),
however, the "repeatable" prefix is now allowed to override it.
This is an artificial background box with the original colors,
rendered as a plain rectangle instead of libass's opaque-box.
Fixes#9134 (together with the previous commit)
This breaks the rendering in various ways, so first workaround is to
simply disable the opaque box for the bar.
Next commit will add an artificial background box.
This read-only property reflects the VO's dpi-scale value, and wasn't
supported on win32 until now (it is supported on wayland/x11/osx).
Currently in mpv it's only used by the builtin script console.lua,
and assumed 1 if unavailable.
When --window-scale=NUM is set from CLI, the dpi_scale value was/is
taken into account when the win32 VO calls vo_calc_window_geometry2.
However, when [current]-window-scale is read or set at runtime, it uses
the VOCTRL_{GET,SET}_UNFS_WINDOW_SIZE interface, where other VOs apply
the dpi_scale value internally (wayland, x11, osx), but the win32 VO
didn't before this commit.
Fixes two issues when --hidpi-window-scale=yes and dpi_scale != 1 :
- Incorrect window-size when setting [current-]window-scale at runtime.
- Incorrect current-window-scale value when reading it.
vo_calc_window_geometry2(...) is called to initialize the window
size with the dpi_scale value as one of the arguments.
dpi_scale is 0 initially, and set to a valid value at update_dpi(),
which is called from [force_]update_display_info().
However, no measures were taken to ensure that dpi_scale is set
correctly before vo_calc_window_geometry2() is called, which could
result in incorrect window size if it's not initialized.
It did happen to get initialized on time, by luck, because
VOCTRL_GET_DISPLAY_FPS is used early, which happens to call
update_display_info to read the fps value (other update_display_info()
calls are after the first vo_calc_window_geometry2() call).
This commit ensures that dpi_scale is initialized on time if needed.
Also, update_dpi() now ensures that dpi_scale is never 0.
Previously, a list of commands was always considered repeatable.
This behavior was added at 6710527a (and moved around since then),
in order to fix#807 (impossible to make a repeatable list).
The problem was that a list doesn't have the normal repeatability
flags and so it was never repeatable, so it was hardcoded to be
repeatable instead. Presumably it was deemed good enough.
However, this made it impossible to have a non-repeatable list.
This commit changes the behavior so that a list repeatability is
that of the first command at the list.
This way, any list can be made either repeatable or non-repeatable
using the following idiom (e.g. at input.conf), based on the fact
that the "ignore" command is not repeatable by default:
x ignore; cmd1...; cmd2... # non-repeatable
y repeatable ignore; cmd1...; cmd2... # repeatable
Fixes#7841
This is a regression from cbbd81bb (the previous commit):
print_seq1 (which prints a sequence with 1 parametric byte value) is
used with 256 colors output, and apparently was never tested.
Two issues were introduced at the offending commit:
1. The ";5" part was incorrectly removed from the strings
ESC_COLOR256_{BG,FG} (affects both *nix and Windows).
2. On windows only - a semicolon was not used after the prefix.
Both issues resulted in an invalid 256 colors sequences and output.
On windows the UTF-8 strings are translated to wchar_t when printed to
the console, and some escape sequences are also translated, however,
this only works when printf is mapped to mp_printf, and for that to
happen we need to include osdep/io.h .
This reverts commit 873ae0de2a.
The next commit will restore this functionality, with the
following differences from the reverted commit:
- Smaller and simpler code change.
- On bad scale: use "Invalid value" (compared to "no such property").
- Doesn't combine the docs for window-scale and current-window-scale.
- Doesn't remove the docs for window-scale behavior prior to 0.31.0.
Using --sub-filter-regex-plain (default:no)
The ass-to-plaintext functionality already existed at sd_ass.c, but
it's internal and uses a private buffer type, so a trivial utility
wrapper was added with standard char*/bstr interface.
The plaintext can be multi-line, and the multi-line regexp flag is now
always set, but only affects plaintext (the ASS source is one line).
Pretty much identical to filter-regex but with JS expressions and
requires only JS support. Shares the filter-regex-* control options.
The target audience is Windows users - where filter-regex doesn't
work due to missing APIs, but mujs builds cleanly on Windows, and JS
is usually enabled in 3rd party Windows mpv builds.
Lua could have been used with similar effort, however, the JS regex
syntax is more extensive and also much more similar to POSIX.
1. On a pathological case where event_format is NULL, previously the
filter was trying to use it with each new sub - and re-failed. Now
the filter gets disabled on init (event_format doesn't change).
2. Previously, if the filter didn't modify the text or if the text
could not be extracted - it still allocated a new packet with same
content. Now it returns the original, saving a whole lot of no-ops
(there are still few allocations in this case though).
1 above is preparation for the next commit, and 2 was trivial, but
there's more to do if anyone cares (NIH string functions instead of
bstr, unused arguments, messages could be improved, and more).
Add two stand-alone function to help with the text-extraction task
which ass filters need. Makes it easier to add new filters without
cargo-culting this functionality.
Currently, on malformed event (which shouldn't happen), a warning is
printed when a filter tries to extract the text, so if few filters
are enabled, we'll get multiple warnings (like before) - not critical.
The regex filter now uses these utils, the SDH filter not yet.
Previously we assumed the key-name string occupies strlen(name) cells,
now we count codepoints instead.
This improves alignment of non-english key names. Still not perfect
because we don't know if the key name is single or double width, but
wcwidth not available to scripts, notoriously unreliable (depends on
locale, correct and updated tables, etc), and also not always
available (Windows).
Still, better than nothing, and we err by at most one cell - vs up to
three before this commit (4 bytes keyname codepoint).
In the future we could do the alignment using libass tags, however,
this both complicates the ass-output generation, and also not available
when we output for the terminal, so for now only count codepoints.
Also, if the key name was in a right-to-left language, then previously
the name/command were swapped visually. Now we inject a left-to-right
marker before the name to ensure direction. This works also when
harfbuzz is disabled for libass (--sub-ass-shaper=simple).
Users expect single quotes to work when the value includes literal
backslashes or double-quotes (or as general quoting like in shell).
The updated docs also include some previously-missing notes:
- newline is only supported in double quotes.
- adjacent (quoted) arguments don't join into one.
Supporting mixed quoting (adjacent quoted strings) would make
mpv's parsing more complete, but would require delicate effort of
larger scope, for two reasons:
- We'd need to also support escaping outside of quotes and do our
best about backward compatibility.
- The parsed value can either be a substring of the input or
a newly-allocated string, which would be delicate when joining.
Not critical to add right now.
Custom quotes were added in 4f129a3e and began with !, however, this
required quoting "!reverse" (used for the cycle-values command), which
is inconvenient, and was not taken into account when ! was chosen for
custom quotes. Also, ` is more natural for quoting than !.
This does break backward compatibility with the earlier form of custom
quotes, but at least we didn't make a release yet since custom quotes
were added (the last release - 0.33[.1] doesn't support it).
In rst, double-backtick starts a code string only if it's followed by
a non-space char, otherwise it's taken literally, hence, `` x2.0``
was taken literally rather than code string.
mpv has two methods to display output from text input:
- show-text (scripting: mp.osd_message) has ass disabled by default
(escaped), and the property osd-ass-cc can control escaping.
- osd-overlay (scripting: mp.set_osd_ass or mp.create_osd_overlay)
has ass enabled (unescaped), and osd-ass-cc is NOT supported.
By default, stats.lua uses mp.osd_message which does support escaping.
That's persistent_overlay=no.
When using persistent_overlay=yes then mp.set_osd_ass is used.
Due to this, the no_ASS(..) function - which is supposed to escape
ass, simply returned its input unmodified when persistent_overlay
is enabled.
This is not a new issue, and the filters on page 1 use no_ASS() to no
avail in persistent mode, however, this content (filter name and value
strings) rarely actually needs escaping, and users didn't notice.
However, the new page 4 (keys) does break visibly when no_ASS doesn't
work, because it tries to escape arbitrary key-names and command
strings, and at the very least the key '{' is bound by default, which
is displayed incorrectly if escaping doesn't work.
Fix this by rolling our own escaping when using mp.set_osd_ass,
similar to how the mpv code does it for mp.osd_message (substrings
replacements).
However, this means that the set_ASS(..) function can no longer
behave correctly because escaping requires going through the whole
content string rather than only inserting a marker.
Luckily, other than at no_ASS, set_ASS was only used at one place
(text_style), which is only called from two places:
- generate_graph() only needs to restore styles - not to enable ass.
- add_header() is only used at the begining of page output, and
uses set_ASS to enable ass initially when using mp.osd_message.
So remove the set_ASS function, and instead enable ass directly at
print_page using osd-ass-cc when mp.osd_message is used.
Fixes#9022
As it turns out, js_try can throw if it runs out of try-stack
(without/before entering either the try part or the catch part).
If it happens, then C code which does allocation -> try will leak.
In mpv there were two places which do alloc and then try, one of
them as part of the autofree system. On both cases the leak is the
smallest possible (zero allocation) - talloc_new(NULL);
It's very unlikely to trigger - an autofree mpv API should be called
when the try-stack is exactly full, and our next try will throw
(and guaranteed to get caught at an outer level, but with a leak).
Fix that by doing the allocation inside the try block, so that if
try throws before it's entered then nothing got allocated/leaked.
Mujs internal code also has/had similar leaks, which are getting
fixed around this time (July 2021, post mujs 1.1.3).
[1] exhaust the try-stack or call-stack, whichever comes first:
function kaboom() { try { kaboom() } catch(e) {} }
Previously, if a script bound the same key more than once to different
functions (without removing the older bindings first), then pressing
the key triggered any of the bound functions arbitrarily[1].
Now the newest binding for the same key is always the active one.
If the newest binding is then removed - the second-newest will become
active, etc. (same mechanism as before, except that the active key
was not always the newest).
[1] The order was implementation-defined, however `for (name in obj)'
happens to iterate. With mujs that's currently alhabetic order,
and name is from mp.add_[forced_]key_binding(key, name...)
or generated internally if name is not provided. So a binding with
higher alphabetic `name' value had priority over lower name value.
Page 4 bindings listing wants to exclude the interactive keys of the
stats script itself - so that they don't hide the normal keys which
are bound when stats is not interactive.
It did so by testing that the bound command includes stats/__key
which is how it usually looks when a script binds keys.
However, if a script uses a name for the binding - like stats.lua does
for the interative keys (because it later removes them by name when
interactive mode ends), then the command has stats/name rather than
stats/__key...
To fix this, we change the names of the forced interactive bindings
to start with __forced_, and that's now also what the page-4 listing
excludes.
This reverts commit 0f1654811bda0dfdd337734ec33c59b67522234a.
It was an incorrect fix, because the key names do get used - to remove
the forced bindings once stats exits the interactive mode.
And without names - the interactive keys remained active even after
stats exited interactive mode.
The page 4 keybinding list tries to skip the interactive bindings of
stats itself (because they would hide the normal bindings of these
keys when stats is not visible), and to do that it excludes commands
containing "script-binding stats/__key" - which is how script-added
bindings usually look like.
However, keys which are added with a "name" bind stats/name rather
than stats/__key... - and that's what stats.lua did till now with its
interactive force-bindings.
Now the interactive forced bindings are added without a name, and so
they do end up using the automatic stats/__key... and get excluded.
While --input-test is useful, and so is page 4 of stats, until now
there was no way to simply print the list in a help-like fashion.
This commit adds such printout, invoked by the script opt
stats-bindlist=yes, which uses the existing page 4 code. This prints
the list on startup and quits immediately - like any help page.
It's awkward to invoke compared to other help pages, and it does
require the stats page to be enabled (it is by default), however
it is a script-generated output, and currently there's no other
method to print a help page generated by a script.
The printout itself is performed using lua's io.write. While reliable,
it's not the standard way for mpv to print to the terminal.
Other possible printout methods are mp.msg.info - which also prints
"[stats]" prefix on each line (ugly), or forcing term-osd and setting
an osd-message which mpv will then print at the terminal - however
that's printed to stderr, and could also be subject to timing concerns
since we quit right afterwards.
In the future we can consider changing/integrating the invocation so
that mpv itself could print a help page generated by a script, thus
solving both the awkward invocation and printout-method issues.
This is a scrollable page which also works nicely with the terminal
OSD. Typically there are more than 100 bound keys.
It groups the binding using fuzzy property/command/script name after
simple analysis of the command string, and then further sorts the
binding in each group according to the "complexity" of the key itself
(plain keys -> keys with modifiers, alphabetically, etc).
The alignment/grouping style is heavily inspired by @medhefgo's #8924
but otherwise it's an independent implementation.
Typically the current page is rebuilt and rendered once per second,
howeve, scrolling can invoke the rebuild function very frequently,
even at a rate which is too fast for the rebuild function to keep
up. This can result in high CPU usage and input lag.
This commit adds an argument to the page-rebuild function, letting it
know whether or not it's called following a scroll keypress, thus
allowing it to cache intermediate data so that it doesn't have to
re-calculate the whole page from scratch.
This additional argument is unused currently, but it could be useful
for the internal performance page - which can be relatively heavy.
osc-visibility can already be changed at runtime via script-message
or other means, but until now there was no way to tell what the
current state is.
Now shared-script-properties/osc-visibility reflects this state.
It's output-only by the osc - changing it does not affect the osc.
Useful if a script wants to change osc-visibility temporarily, and
later restore to its original state.
There's no way to coordinate if more than one script wants to change
it, but that would be a hard problem to solve anyway, even if the
osc itself tried to coordinate such requests from different sources.
This fixes two issues, both of which resulted from the timers-wait
period not being re-calculated after idle-observers were executed:
- If timers were added from an idle observer then they could fire long
after they were due (only when/if the next mpv event arrives).
- Idle observers don't execute in zero time, and the wait period for
the next timer was implicitly extended by the idle observers
execution time (because it was calculated before the idle observers).
This commit ensures that if idle-observers were executed, then the
timers wait period is re-calculated, which solves both issues.
Previously, process_timers() kept going as long as there were due
timers, which could be for extended periods of time or even forever
if there were slow timer callbacks with either periodic timers or if
timers were added repeatedly.
This prevented dequeuing mpv events, and subsequently, among others,
prevented mpv from quitting until process_timers() completed.
For instance, this caused process_timers() to never return:
function render() <longer than 1/60 s on a slow system> end
mp.add_periodic_timer(1/60, render)
Similarly, it never returned if a timer callback always added a new
one-shot which was already due by the time the callback completed.
This commit ensures that process_timers() only executes callbacks which
were due when it started, so that timers which are added (or repeated)
during process_timers() will wait for the next iteration - after mpv
events are dequeued.
This has no performance impact under normal conditions (when callbacks
complete before the next timer is due).
Additionally, previously idle-observers were executed unconditionally
after the timers because indeed there was nothing due when (if...)
process_timers() completed. However, now process_timers() can return
even if there are due timers, so skip idle-observers on such case.
The idle-observers block has at least 3 function calls, and it was
entered every time the script went into idle, however, we can save these
calls by checking first that there are indeed such observers.
Previously tick() was ensured unconditionally only after mouse-move,
but there are other mouse-events which need re-rendering (tick), like
mouse-down (icons may get grayed-out) or mouse-up (icons may change).
For instance: mpv --pause --myclip.mkv
then move the mouse over the volume/mute OSC button, then - without
moving the mouse - press and release the left mouse button.
The osc was not re-rendered because it's paused and the mouse didn't
move, so the volume icon didn't get grayed-out when held down, and the
icon doesn't change on mouse-up (to reflect the new mute state).
Now both these changes are rendered correctly.
This is not a new issue, however, until the last commit - 96b246d
init probably didn't happen much (or at all) between mouse-down and
mouse-up, but after this commit, if there are chapters in a live-stream
then osc_init() is used to re-render the markers at the adjusted
position - which breaks the OSC buttons functionality if init happened
between mouse-down and mouse-up.
And also change the existing WM_KILLFOCUS handler to return 0 instead
of 'break' (which later calls DefWindowProcW), as MSDN says we should
do for WM_{KILL,SET}FOCUS.
It seems that the 'focused' property is now supported by all main VOs:
x11, macOS, wayland, Windows.
TCT/sixel/caca probably don't support it, and unknown with SDL.
Fixes#8868
This commit describes more accurately what currently gets disabled
by this option - specifically also keys from mp.add_key_binding.
It's not necessarily the best behavior because libmpv clients might
want to disable mpv's own builtin keybindings while still allowing
scripts to define keys which `input.conf' can override.
In the future we might exclude mp.add_key_binding from this option,
but for now at least document this option accurately.
Fixes#8809
The ctime member on Windows uses FILE_BASIC_INFO.ChangeTime, which is
pretty much the same as st_ctime on POSIX.
See https://devblogs.microsoft.com/oldnewthing/20100709-00/?p=13463 :
... The LastWriteTime covers writes to the file’s data stream
(which you accomplish via the WriteFile function). On the other
hand, the ChangeTime also includes changes to the file metadata,
such as changing its file attributes ...
Fixes#8801
We now have at least 3 scripting APIs which are trivial wrappers
around properties: mp.get_mouse_pos, utils.getcwd, utils.getpid.
After some discussion on IRC it was decided that it's easier for us to
maintain them as trivial wrappers than to deprecate them and inflict
pain on users and script authors, so currently no plan to deprecate.
The fit_on_screen logic was a bit twisted. Simplify it a bit
and update few comments to explain better what it's used for.
Note that the new logic is not identical to before, but its intent
should now be clearer. This means there might be regressions or
improvements at edge cases. If followup fixes are needed, then we
should keep the intent clear. Most likely though that it's fine.
fit_on_screen is called only from reinit_window_state.
Move the yes/no logic unmodified from fit_on_screen to
reinit_window_state, and remove the w32->parent condition because it's
already checked earlier at reinit_window_state.
Previously, because the video (client area) was centered but the top
and bottom borders are uneven (title is taller), then if the window
is shrunk vertically to just-fit the desktop - the top edge of the
title bar ended above the top edge of the display.
This is a state which Windows prevents during manual move, but
apparently it's not rejected at the Windows API.
Now we ensure it doesn't happen, and nudge the window down to align
the top edges if necessary.
This is a commulative regression of commits 981048e0 and 364af7c6.
To clarify functionality, this includes a no-op change: fit_rect was
renamed to fit_rect_size and it now takes explicit width and height,
because it only used the width/height of rc2 anyway.
Fixes#6695
The accurate description of this option was:
- fit-border is enabled by default. When disabled, it adds a bug where
if the window has borders and mpv shrinks it to fit the desktop, then
the calculation ignores the borders and adds incorrect video crop.
The option was added at commits 70f64f3c and 949247d6, in order to
solve an issue (#2935) where if mpv wanted to display a video with
size WxH, then w32_common.c incorrectly set the window to WxH, while
down-scaling the video slightly to fit (even with small sizes).
It was addressed with a new option which is enabled by default, but
does the right thing (sets the client area to WxH) only when disabled,
so that everyone who prefers their video slightly downscaled could
keep their default behavior.
(#2935 also addressed an off-by-one issue, fixed before fit-border)
While disabling the option did avoid unnecessary downscaling, it also
added a bug when disabled: the borders are no longer taken into
account when the size is too big for the desktop. Most users don't
notice and are unaffected as it's enabled by default.
Shortly later (981048e0) the core issue is fixed, and now the client
area is correctly set to WxH instead of the window (and together with
the three following commits which center the video, adds a new bug
where the window title can be outside the display - addressed next).
However, fit-border remained, now without any effect, except that it
still has the same bug when disabled and the window is too big.
Later code changes and refactoring preserved this issue with great
attention to details, and it remained in identical form until now.
Simply rip out fit-border.
Before this commit, the user could specify a printf format string
which wasn't verified, and could result in:
- Undefined behavior due to missing or non-matching arguments.
- Buffer overflow due to untested result length.
The offending code was added at commit 103a9609 (2002, mplayer svn):
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@4566 b3059339-0415-0410-9bf9-f77b7e298cf2
It moved around but was not modified meaningfully until now.
Now we reject all conversion specifiers at the format except %%
and a simple subset of the valid specifiers. Also, we now use
snprintf to avoid buffer overflow.
The format string is provided by the user as part of mf:// URI.
Report and initial patch by Stefan Schiller.
Patch reviewed by @jeeb, @sfan5, Stefan Schiller.
Where X is any ASCII char chosen by the user. An argument is only
interpreted as custom-quoted if it starts with '!' and the line doesn't
end right after it. Custom quotes don't interpret backslash-escape.
This change only affects command arguments which mpv parses (not array
commands), and not tokens before the arguments (where applicable - key
name, input section, command prefixes, command name).