The intention is to provide a slightly nicer way to distribute scripts.
For example, you could put multiple source files into the directory, and
then import them from the actual script file (this is still
unimplemented).
At first I wanted to require a config file (because you need to know at
least which scripting backend it should use). This wouldn't have been
too hard (could have reused/abused the mpv config file parsing
mechanism, and I already had working code that was just 2 function
calls). But probably better to do this without new config files, because
it might become a pain in the distant future.
So this just probes for "main.lua", "main.js", etc., until an existing
file is found.
Another important change is that this skips all directory entries whose
name starts with ".". This automatically excludes the "." and ".."
special directories, and is probably useful to exclude random crap that
might be lying around in the directory (such as editor temporary files,
or OSX, in its usual hrmful, annoying, and idiotic modus operandi,
sharting all over any directories opened by "Finder").
Although the changelog mentions the docs, they're added only in a later
commit.
This code assumed that the function is only called from the playloop
itself (and since property notification is done at the end of it, i.e.
before sleeping, it obviously would not have needed to wake up the
core).
But this function is actually called from some comments (such as
playlist-move), so this assumption was incorrect. Use the same method as
the other function.
Untested.
Fixes: #7339 (probably)
check_obj_resize() in sub/osd.c calls mp_client_broadcast_event(), which
calls notify_property_events(). This is pretty unexpected, because
check_obj_resize() may be called from the VO thread. While that's sort
of awful, it seems to be OK locking-wise. But it breaks an assumption in
notify_property_events() that the core doesn't need to be woken up,
which could possibly lead to a missed/delayed property update (although
rather unlikely).
Fix this by explicitly waking up the core when it's called from the OSD
code.
Lua scripting has an undocumented mp.set_osd_ass() function, which is
used by osc.lua and console.lua. Apparently, 3rd party scripts also use
this. It's probably time to make this a public API.
The Lua implementation just bypassed the libmpv API. To make it usable
by any type of client, turn it into a command, "osd-overlay".
There's already a "overlay-add". Ignore it (although the manpage admits
guiltiness). I don't really want to deal with that old command. Its main
problem is that it uses global IDs, while I'd like to avoid that scripts
mess with each others overlays (whether that is accidentally or
intentionally). Maybe "overlay-add" can eventually be merged into
"osd-overlay", but I'm too lazy to do that now.
Scripting now uses the commands. There is a helper to manage OSD
overlays. The helper is very "thin"; I only want to force script authors
to use the ID allocation, which may help with putting multiple scripts
into a single .lua file without causing conflicts (basically, avoiding
singletons within a script's environment). The old set_osd_ass() is
emulated with the new API.
The JS scripting wrapper also provides a set_osd_ass() function, which
calls internal mpv API. Comment that part (to keep it compiling), but
I'm leaving it to @avih to finish the change.
I intend to rewrite this code approximately every 2 months.
Last time, I did this in commit d66eb93e5d (and 065c307e8e and
b2006eeb74). It was intended to remove the roundabout synchronous
thread "ping pong" when observing properties. At first, the original
async. code was replaced with some nice mostly synchronous code. But
then an async. code path had to be added for vo_libmpv, and finally the
sync. code was dropped because it broke in other obscure cases (like the
Objective-C Cocoa backend).
Try again. This time, update properties entirely on the main thread.
Updates get batched out on every playloop iteration. (At first I wanted
it to make it every time the player goes to sleep, but that might starve
API clients if the playloop get saturated.) One nice thing is that
clients only get woken up once all changed events have been sent, which
might reduce overhead.
While this sounds simple, it's not. The main problem is that reading
properties must not block the client API, i.e. no client API locks can
be held while reading the property. Maybe eventually we can avoid this
requirement, but currently it's just a fact. This means we have to
iterate over all clients and then over all properties (of each client),
all while releasing all locks when updating a property. Solve this by
rechecking on each iteration whether the list changed, and if so,
aborting the iteration and redo it "next time".
High risk change, expect bugs such as crashes and missing property
updates.
As preparation for making repl.lua part of the core (maybe), add some
mechanisms which are supposed to improve its behavior.
Add a silent mode. Calling mpv_request_log_messages() with the log level
name prefixed with "silent:" will disable logging from the API user's
perspective. But it will keep the log buffer, and record new messages,
without returning them to the user. If logging is enabled again by
requesting the same log level without "silent:" prefix, the buffered log
messages are returned to the user at once. This is not documented,
because it's far too messy and special as that I'd want anyone to rely
on this behavior, but it will be perfectly fine for an internal script.
Another thing is that we record early startup messages. The goal is to
make the repl.lua script show option and config parsing file errors.
This works only with the special "terminal-default" log level.
In addition, reduce the "terminal-default" capacity to only 100 log
messages. If this is going to be enabled by default, it shouldn't use
too much resources.
It's too easy to introduce unintended circular lock dependencies. Just
now we found that the (old) cocoa vo_gpu backend is also affected by
this, because it waits on the Cocoa main thread, which in turn uses
libmpv API for OSX... stuff.
Also fix a missing initial property update after observe.
This leaves me unhappy, because it just leads to a stupid thread ping
pong. Will probably rewrite this later.
Used to contain flags for "save" setting of options at runtime. Now
there is nothing special needed anymore and it's 0. So drop it
completely, and remove anything that distinguishes between runtime and
initialization time.
In theory, it's better to keep the old value, because that's more
consistent with the logic of using change timestamps. With the current
code, the old value will probably never be used (instead it will fetch a
new value on every change), so this shouldn't make a difference in
practice.
In commit 065c307e8e, I broke everything. It seemed like a nice idea,
but it explicitly broke an assumption vo_libmpv were explicitly allowed
to make: that observing properties does not lock the core. The commit
did just that and locked the core for property updates. This made for
example mpv's own OSX backend freeze (it uses vo_libmpv for convenience
to make up for Apple's incredibly broken OpenGL shit).
I don't want to revert that commit just because vo_libmpv's design is
horrible. So instead add an optional asynchronous path, that is only
used if vo_libmpv is in use (best idea ever?).
Interestingly, this isn't so hard. It adds about 90 lines of code, which
are only run on OSX and libmpv users, so I don't have to care about the
crashes and weird behavior this might cause. It even worked on the first
try except for a quickly fixed memory leak. The code path can be tested
anywhere by just turning the uses_vo_libmpv condition into always true.
The atomic is out of laziness. Saves some thinking how to get around the
locking order.
The commit linked below added temporary unlocking to update_prop(),
which is indirectly called by mpv_wait_event(). If an unlock happens,
and no property change event is returned, we must re-poll the event
queue. Rechecking the state on unlocks is basically a standard
requirement for code using condition variables.
Untested beyond a simple test.
Fixes: 065c307e8e
Property change notification works by having the mpv core wake up all
clients observing a property when the property potentially changes. The
clients then read the property's value, and determine if there was an
actual change. (The latter part depends what the property returned for
the previous change notification, so it depends on the client, and
cannot be generated by the core itself.)
Until now, reading the property value was done in a pseudo-async way by
queuing a callback back to the core, running it there, and then waking
up the client thread again. I cannot comprehend why this was done in
such a complicated, fragile way. Maybe it's a leftover from times when
client.c had to do this (in short, because properties could access
vo_opengl, which has thread-local state).
One past idea was to make the implementation of true async properties
easier (for which you would need such a state machine anyway). But they
don't exist yet, and I doubt the current mess would be really helpful
when actually implementing them.
Simplify this, and run the update in the client's thread directly. In
addition to the fundamental change, many roundabout things can be
removed as a consequence.
Unfortunately, I noticed that lock order issues force you to release
ctx->lock before doing so, which makes things more complex due to
possible concurrent mpv_unobserve_property() calls. Solve this by
removing properties lazily, which means you may have to do multiple
mpv_wait_event() calls before the property entry is actually destroyed.
This should not matter in practice, and does not affect the semantics.
It could also cause "leaks" by observing/unobserving properties in a
loop, without ever calling mpv_wait_event(). Just don't do this, duh.
(I considered making this dependent on whether the previous
mpv_wait_event() call returned the property being removed, but a
separate code path seemed too complicated. I also considered copying the
name and property data when returning a MPV_EVENT_PROPERTY_CHANGE, but
actually this doesn't solve the problem of update_prop() being
interrupted by mpv_unobserve_property(); there are ways around it, but I
just said no.)
This was made using the cowboy coding software engineering methodology.
If you find any bugs, keep them yourself.
Apparently this was only added and used for cache update stuff, which
was changed in commit 8dbc93a94c. Now it's unused, messy, ugly, and
is in the way, so get rid of it.
This change adds a version of `mpv_command` that also returns a result.
The main rationale behind this is `mpv_command_node` requires defining
multiple structs before you can even use it, which results in a pretty
painful to use interface just to get the result from a command.
There isn't really a good name for this function, so I'm open to
suggestions on a better name for it.
When update_prop() successfully fetched a changed property value, it
set prop->changed to true to indicate the success.
mark_property_changed() also always set
prop->changed to true and additionally prop->need_new_value to true
This is the case since 6ac0ef78
If the observed property changes every frame and then due to timing
the next mark_property_changed() is called before
gen_property_change_event() and therefore directly after update_prop(),
prop->need_new_value was again true and indicated that a new value
has to be retrieved with update_prop(). As a result the event for the
last successful update_prop() was never triggered. This meant that
a property change event were never generated for frame-based properties
only for properties that were observed with MPV_FORMAT_NONE or when the
timing was different and gen_property_change_event() was called after
update_prop().
To fix this, mark_property_change() and update_prop() should not use the
same flag to indicate different things and therefore a new flag for
successfully update a property is introduced. But with the now decoupled property
changed and updated the need_new_value flag is redundant and removed completely.
Fixes#4195
render api needs to wait for vo to be destroyed before frees the context.
The purpose of kill_cb is to wake up render api after vo is destroyed,
but uninit did that before kill_cb, so kill_cb tries using the freed
memory. Remove kill_cb to fix the issue as uninit is able to do the
work.
Until now, stopping playback aborted the demuxer and I/O layer violently
by signaling mp_cancel (bound to libavformat's AVIOInterruptCB
mechanism). Change it to try closing them gracefully.
The main purpose is to silence those libavformat errors that happen when
you request termination. Most of libavformat barely cares about the
termination mechanism (AVIOInterruptCB), and essentially it's like the
network connection is abruptly severed, or file I/O suddenly returns I/O
errors. There were issues with dumb TLS warnings, parsers complaining
about incomplete data, and some special protocols that require server
communication to gracefully disconnect.
We still want to abort it forcefully if it refuses to terminate on its
own, so a timeout is required. Users can set the timeout to 0, which
should give them the old behavior.
This also removes the old mechanism that treats certain commands (like
"quit") specially, and tries to terminate the demuxers even if the core
is currently frozen. This is for situations where the core synchronized
to the demuxer or stream layer while network is unresponsive. This in
turn can only happen due to the "program" or "cache-size" properties in
the current code (see one of the previous commits). Also, the old
mechanism doesn't fit particularly well with the new one. We wouldn't
want to abort playback immediately on a "quit" command - the new code is
all about giving it a chance to end it gracefully. We'd need some sort
of watchdog thread or something equally complicated to handle this. So
just remove it.
The change in osd.c is to prevent that it clears the status line while
waiting for termination. The normal status line code doesn't output
anything useful at this point, and the code path taken clears it, both
of which is an annoying behavior change, so just let it show the old
one.
This affects async commands started by client API, commands with async
capability run in a sync way by client API (think mpv_command_node()
with "subprocess"), and detached async work.
Since scripts might want to do some cleanup work (that might involve
launching processes, don't ask), we don't unconditionally kill
everything on exit, but apply an arbitrary timeout of 2 seconds until
async commands are aborted.
Many asynchronous commands are potentially long running operations, such
as loading something from network or running a foreign process.
Obviously it shouldn't just be possible for them to freeze the player if
they don't terminate as expected. Also, there will be situations where
you want to explicitly stop some of those operations explicitly. So add
an infrastructure for this.
Commands have to support this explicitly. The next commit uses this to
actually add support to a command.
This enables two types of command behavior:
1. Plain async behavior, like "loadfile" not completing until the file
is fully loaded.
2. Running parts of the command on worker threads, e.g. for I/O, such as
"sub-add" doing network accesses on a thread while the core
continues.
Both have no implementation yet, and most new code is actually inactive.
The plan is to implement a number of useful cases in the following
commits.
The most tricky part is handling internal keybindings (input.conf) and
the multi-command feature (concatenating commands with ";"). It requires
a bunch of roundabout code to make it do the expected thing in
combination with async commands.
There is the question how commands should be handled that come in at a
higher rate than what can be handled by the core. Currently, it will
simply queue up input.conf commands as long as memory lasts. The client
API is limited by the size of the reply queue per client. For commands
which require a worker thread, the thread pool is limited to 30 threads,
and then will queue up work in memory. The number is completely
arbitrary.
This has some tricky interactions. In particular, it requires the core
to be locked due to reading outstanding_async, which is documented on
the only caller only. It's probably better to merge it with its only
caller.
The new code should be strictly equivalent, other than the fact that it
doesn't temporarily unlock+lock when entering the loop for the first
time (which doesn't matter here).
DR (letting the decoder allocate texture memory) requires running the
allocation on the render thread. This is rather hard with the render
API, because the user controls this thread and when it's entered. It was
not possible until now.
This commit adds a bunch of infrastructure to make this possible. We add
a new optional mode (MPV_RENDER_PARAM_ADVANCED_CONTROL) which basically
lets the user's render thread and libmpv agree how this should be done.
Misuse would lead to deadlocks. To make this less likely, strictly
document thread safety/locking issues. In particular, document which
libmpv functions can be called without issues. (The rest has to be
assumed unsafe.)
The worst issue is destruction of the render context while video is
still active. To avoid certain unintended recursive locks (i.e.
deadlocks, unless we'd make the locks recursive), make the update
callback lock separate. Make "killing" the video chain asynchronous, so
we can do extra work while video is being destroyed.
Because losing wakeups is a big deal, setting the update callback now
triggers a wakeup. (It would have been better if the wakeup callback
were a parameter to mpv_render_context_create(), but too late.)
This commit does not add DR yet; the following commit does this.
This was slightly broken: since mp_initialize() did not necessarily
interrupt core_thread() (which is waiting for initialization), it did
not enter mp_play_files(), which would have sent an IDLE event.
I suppose that in some cases (like with mpv-android), the initial IDLE
event was never actually sent, because the first wakeup of the core
thread happens with the "loadfile" command, which will disallow the core
thread an IDLE event.
Although this was never observed to be happening, it seems definitely
possible: we first tell the main thread to exit, and then we ask the
main thread to do some work for us (with mp_dispatch_run()). Obviously
this is racy, and the main thread could exit without doing this, which
would block mp_dispatch_run() forever.
Fix this by changing the order of operation, so that it makes sense.
We could also just store the pthread_t of the main thread in some
variable, but the fact that pthread_create() might set the pthread_t
argument _after_ starting the thread makes this a bit messy (at least it
doesn't seem to be guaranteed on a superficial look at the manpage).
As it turns out, there are multiple libmpv users who saw a need to
use the hook API. The API is kind of shitty and was never meant to be
actually public (it was mostly a hack for the ytdl script).
Introduce a proper API and deprecate the old one. The old one will
probably continue to work for a few releases, but will be removed
eventually.
There are some slight changes to the old API, but if a user followed
the manual properly, it won't break.
Mostly untested. Appears to work with ytdl_hook.
Hardware decoding things often need access to additional handles from
the windowing system, such as the X11 or Wayland display when using
vaapi. The opengl-cb had nothing dedicated for this, and used the weird
GL_MP_MPGetNativeDisplay GL extension (which was mpv specific and not
officially registered with OpenGL).
This was awkward, and a pain due to having to emulate GL context
behavior (like needing a TLS variable to store context for the pseudo GL
extension function). In addition (and not inherently due to this), we
could pass only one resource from mpv builtin context backends to
hwdecs. It was also all GL specific.
Replace this with a newer mechanism. It works for all RA backends, not
just GL. the API user can explicitly pass the objects at init time via
mpv_render_context_create(). Multiple resources are naturally possible.
The API uses MPV_RENDER_PARAM_* defines, but internally we use strings.
This is done for 2 reasons: 1. trying to leave libmpv and internal
mechanisms decoupled, 2. not having to add public API for some of the
internal resource types (especially D3D/GL interop stuff).
To remain sane, drop support for obscure half-working opengl-cb things,
like the DRM interop (was missing necessary things), the RPI window
thing (nobody used it), and obscure D3D interop things (not needed with
ANGLE, others were undocumented). In order not to break ABI and the C
API, we don't remove the associated structs from opengl_cb.h.
The parts which are still needed (in particular DRM interop) needs to be
ported to the render API.
Before this change, mpv_wait_event() could inconsistently return
multiple MPV_EVENT_SHUTDOWN events to a single mpv_handle, up to the
point of spamming the event queue under certain circumstances. Change
this and just send it exactly once to each mpv_handle.
Some client API users might have weird requirements about destroying
their state asynchronously (and not reacting immediately to the SHUTDOWN
event). This change will help a bit to make this less weird and
surprising.
This changes how mpv_terminate_destroy() and mpv_detach_destroy()
behave. The doxygen in client.h tries to point out the differences. The
goal is to make this more useful to the API user (making it behave like
refcounting).
This will be refined in follow up commits.
Initialization is unfortunately closely tied to termination, so that
changes as well. This also removes earlier hacks that make sure that
some parts of FFmpeg initialization are run in the playback thread
(instead of the user's thread). This does not matter with standard
FFmpeg, and I have no reason to care about this anymore.
The intention is to reduce annoying differences between mpv CLI and
libmpv, and there's no reason to have the locale check only in libmpv
(although it doesn't help with any real issues either).
this API was introduced in c5e4538 solely for the use with cocoa-cb and
was not public. with the port to the new API in 760d471 it is now unused
and can safely be removed.
The purpose of the new API is to make it useable with other APIs than
OpenGL, especially D3D11 and vulkan. In theory it's now possible to
support other vo_gpu backends, as well as backends that don't use the
vo_gpu code at all.
This also aims to get rid of the dumb mpv_get_sub_api() function. The
life cycle of the new mpv_render_context is a bit different from
mpv_opengl_cb_context, and you explicitly create/destroy the new
context, instead of calling init/uninit on an object returned by
mpv_get_sub_api().
In other to make the render API generic, it's annoyingly EGL style, and
requires you to pass in API-specific objects to generic functions. This
is to avoid explicit objects like the internal ra API has, because that
sounds more complicated and annoying for an API that's supposed to never
change.
The opengl_cb API will continue to exist for a bit longer, but
internally there are already a few tradeoffs, like reduced
thread-safety.
Mostly untested. Seems to work fine with mpc-qt.
this is meant to replace the old and not properly working vo_gpu/opengl
cocoa backend in the future. the problems are various shortcomings of
Apple's opengl implementation and buggy behaviour in certain
circumstances that couldn't be properly worked around. there are also
certain regressions on newer macOS versions from 10.11 onwards.
- awful opengl performance with a none layer backed context
- huge amount of dropped frames with an early context flush
- flickering of system elements like the dock or volume indicator
- double buffering not properly working with a none layer backed context
- bad performance in fullscreen because of system optimisations
all the problems were caused by using a normal opengl context, that
seems somewhat abandoned by apple, and are fixed by using a layer backed
opengl context instead. problems that couldn't be fixed could be
properly worked around.
this has all features our old backend has sans the wid embedding,
the possibility to disable the automatic GPU switching and taking
screenshots of the window content. the first was deemed unnecessary by
me for now, since i just use the libmpv API that others can use anyway.
second is technically not possible atm because we have to pre-allocate
our opengl context at a time the config isn't read yet, so we can't get
the needed property. third one is a bit tricky because of deadlocking
and it needed to be in sync, hopefully i can work around that in the
future.
this also has at least one additional feature or eye-candy. a properly
working fullscreen animation with the native fs. also since this is a
direct port of the old backend of the parts that could be used, though
with adaptions and improvements, this looks a lot cleaner and easier to
understand.
some credit goes to @pigoz for the initial swift build support which
i could improve upon.
Fixes: #5478, #5393, #5152, #5151, #4615, #4476, #3978, #3746, #3739,
#2392, #2217
This takes car eof unsubtle bugs if something at init does not work
(specifically if mp_new_client() returns NULL). It also removes the need
for that PMP MF hack.
The license text refers a "above copyright notice", so I guess it'd be
good to actually provide such a notice.
Add the license to some files that were missing it (since in theory, our
Copyright file says that such files are LGPL by default).
Remove the questionable remarks about the license in the client API.
Fixes theoretical lock-order issues found by Coverity. Calling these
inside the log is unnecessary anyway, because they have their own
locking, and because mpv_detach_destroy() needs to be called by someone
who has exclusive access to the mpv_handle (it's basically a destructor
function). The lock order issues comes from the fact that they call back
into the client API implementation to broadcast events and such.
As preparation for file prefetching, we basically have to get rid of
using mpctx->playback_abort for the main demuxer (i.e. the thing that
can be prefetched). It can't be changed on a running demuxer, and always
using the same cancel handle would either mean aborting playback would
also abort prefetching, or that playback can't be aborted anymore.
Make this more flexible with some refactoring.
Thi is a quite shitty solution if you ask me, but YOLO.