Instead of making m_config a special-case, it more or less uses the
underlying m_config_cache/m_config_shadow APIs properly. This makes the
player core a (relatively) equivalent user of the core option API. In
particular, this means that other threads can change core options with
m_config_cache_write_opt() calls (before this commit, this merely led to
diverging option values).
An important change is that before this commit, mpctx->opts contained
the "master copy" of all option data. Now it's just another copy of the
option data, and the shadow copy is considered the master. This is why
whenever mpctx->opts is written, the change needs to be copied to the
master (thus why this commits add a bunch of m_config_notify... calls).
If another thread (e.g. a VO) changes an option, async_change_cb is now
invoked, which funnels the change notification through the player's
layers.
The new self_notification parameter on mp_option_change_callback is so
that m_config_notify... doesn't trigger recursion, and it's used in
cases where the change was already "processed". It's still needed to
trigger libmpv property updates. (I considered using an extra
m_config_cache for that, but it'd only cause problems with no
advantages.)
I think the recent changes actually forgot to send libmpv property
updates in some cases. This should fix this anyway. In some cases,
property updates are reworked, and the potential for bugs should be
lower (probably).
The primary point of this change is to allow external updates, for
example by a VO writing the fullscreen option if the window state is
changed by the window manager (rather than mpv changing it). This is not
used yet, but the following commits will.
The previous bunch of commits made this unnecessary, so this should be
a purely internal change with no user impact.
This may or may not open the way to future improvements. Even if not,
at least the property/option interaction should now be much less buggy.
That's right, and it's probably not the end of it. I'll just claim that
I have no idea how to create a proper user interface for this, so I'm
creating multiple partially-orthogonal, of which some may work better in
each of its special use cases.
Until now, there was --record-file. You get relatively good control
about what is muxed, and it can use the cache. But it sucks that it's
bound to playback. If you pause while it's set, muxing stops. If you
seek while it's set, the output will be sort-of trashed, and that's by
design.
Then --stream-record was added. This is a bit better (especially for
live streams), but you can't really control well when muxing stops or
ends. In particular, it can't use the cache (it just dumps whatever the
underlying demuxer returns).
Today, the idea is that the user should just be able to select a time
range to dump to a file, and it should not affected by the user seeking
around in the cache. In addition, the stream may still be running, so
there's some need to continue dumping, even if it's redundant to
--stream-record.
One notable thing is that it uses the async command shit. Not sure
whether this is a good idea. Maybe not, but whatever. Also, a user can
always use the "async" prefix to pretend it doesn't.
Much of this was barely tested (especially the reinterleaving crap),
let's just hope it mostly works. I'm sure you can tolerate the one or
other crash?
The screenshot command has this weird behavior that it shows messages
both on terminal and OSD by default, but that a command prefix can be
used to disable the OSD message.
Move this mechanism to common code, and make this available to other
commands too (although as of this commit only the screenshot commands
use it).
This gets rid of the weird screenshot_ctx.osd field too, which was sort
of set on a command, and sometimes inconsistently restored after the
command.
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 gets rid of run_command() and its big switch statement, which was
an idiotically big function of almost 1000 lines.
The switch is replaced with a callback per command, and each command is
now implemented in its own function. Command IDs are not needed anymore,
so the mp_command_type enum disappears.
There should be no functional changes, but since this refactors 64
commands, regressions are possible.
The handler() parameter is void*, because in theory the input code is
supposed to be independent of the player core code. For example, you
should be able to reuse the command parser code for some other part of
mpv. In practice, the variable containing command list is defined in the
player core anyway, so you could say this doesn't work. But I'm still
trying to hold onto this idea, so I went with void*.
There was a "generic" function to run a hook and to wait for its
completion, yet there were two duplicated functions doing the same
anyway. Replace them with a single function.
They differed in how stop_play was handled, but it was broken anyway.
stop_play is set when playback is stopped due to quitting or changing
the playlist entry - but we still can't stop hook processing, because
that would mean asynchronously doing something else while the user hook
code is still busy and might still have the expectation that running the
hook stops everything else. So not waiting until the hook ends properly
is against the whole hook idea. That this was done inconsistently is
even worse. (Though it could be argued that when quitting the player,
everything should just be stopped violently. But I still think that's
up to the hook handler.)
process_hooks() does not return anything, since hook processing doesn't
really have a result (it's all about blocking and letting some other
code synchronously do something). Just let the caller check whether
loading was aborted in the meantime.
Also change the potentially misleading name of mp_hook_run().
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.
This will help with things like livestreams.
As a minor detail, subtitles are excluded, because they sometimes have
"unused" events after video and audio ends. To avoid this annoying
corner case, just ignore them.
See "Copyright" file for caveats.
This changes the remaining "almost LGPL" files to LGPL, because we think
that the conditions the author set for these was finally fulfilled.
These files have all in common that they were fully or mostly taken from
mplayer.c. (mplayer.c was a huge file that contains almost all of the
playback core, until it was split into multiple parts.) This was
probably the hardest part to relicense, because so much code was moved
around all the time.
player/audio.c still does not compile. We'll have to redo audio
filtering. Once that is done, we can probably actually provide an
actual LGPL configure switch.
Here is a relatively detailed list of potential issues:
8d190244: author did not reply, parts were made GPL-only in a previous
commit.
7882ea9b: author could not be reached, but the code is gone. wscript
still has --datadir switch, but I don't think this is relevant to
copyright.
f197efd5: unclear origin, but I consider the code gone anyway (replaced
with generic OSD mechanisms).
8337d9c2: author did not reply, but only the option still exists (under
a different name), other code was removed.
d8fd7131: did not reply. Disabled in a previous commit.
05258251: same author as above. Both fields actually seem to have
vanished (even when tracking renames), so no action taken.
d459e644, 268b2c1a: author did not reply, but we reuse only the options
(with different names and slightly or fully different semantics, and
completely different implementations), so I don't think this is relevant
for copyright.
09e742fe, 17c39c4e: same as above.
e8a173de, bff4b3ee: author could not be reached. The commands were
reworked to properties, and the code outside of the TV code were moved
back to the TV code. So I don't think copyright applies to the current
command.c parts (mp_property_tv_color, mp_property_tv_freq,
mp_property_tv_scan). The TV parts remain GPL.
0810e427: could not be reached. Disabled in a previous commit.
43744a2d: unknown author, but this was replaced by dynamic alloc (if the
change is even copyrightable).
116ca0c7: unknown author; reasoning see input.c relicensing commit.
e7e4d1d8: these semantics still exist, but as generic code, and this
code was fully removed.
f1175cd9: the author of the cited patch is unknown, and upon inspection
it turns out that I was only using the idea to pause the player on EOF,
so I claim it's not copyright relevant.
25affdcc: author could not be reached (yet) - but it's only a function
rename, not copyrightable.
5728504c was committed by Arpi (who agreed), but hints that it might be
by a different author. In fact it seems to be mostly this patch:
http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2001-November/002041.html
The author did not respond, but it all seems to have been removed later.
It's a terrible mess though. Arpi reverted the A-V sync code at first,
but left the RTC code for a while. The following commits remove these
changes 100%: 14b35442, 7181a091, 31482783, 614f8475, df58e822.
cehoyos did explicitly not agree to LGPL, but was involved in the
following changes:
c99d8fc8: applied a patch and didn't modify it, the original author
agreed.
40ac0d31: author could not be reached, but all code is gone anyway. The
"af" command has a similar function, but works completely different and
actually reuses a mechanism older than this patch.
54350436: applied a patch, but didn't modify it, except for adding a
German translation, which was removed later.
a2dda036: same situation as above
240b743e: this was made GPL-only in a previous commit
7b25afd7: same as above (for now)
kirijua could not be reached, but was a regular patch contributor:
c2c997fd: video equalizer code move; probably not copyrightable. Is GPL
due to Nick anyway.
be54f481: technically, this became the audio track property later. But
all what is left is the fact that you pass a track ID to it, so consider
the original coypright non-relevant.
2f376d1b: this was rewritten in b7052b43, but for now we can afford to
be careful, so this was marked as GPL only in a previous commit.
43844d09: remaining parts in main.c were reverted in a previous commit.
anders has mostly disagreed with the LGPL relicensing. Does not want
libaf to become LGPL, but made some concessions. In particular, he
granted us permission to relicense 4943e9c52c and 242aa6ebd4. We also
consider some of his changes remaining in mpv not relevant for copyright
(such as 735de602 - we won't remove the this option completely). We will
completely remove his other contributions, including the entire audio
filter chain. For now, this stuff is marked as GPL only. The remaining
question is how much code in player/audio.c (based on the former
mplayer.c and dec_audio.c) is under his copyright. I made claims about
this in a previous commit.
Nick(ols) Kurshev, svn username "nick" and "nickols_k", could not be
reached. He had a lot of changes in early MPlayer. It seems all of that
was removed, at least in mpv. His main work, like VIDIX or libswscale
work, does not exist in mpv anymore, but the changes to mplayer.c and
other core parts still deserve attention:
a4119f6b, fb927549, ad3529b8, e11b23dc, 5f2178be, 93c371d5: removed in
b43d67e0, d1628d12, 24ed01fe, df58e822.
0a83c6ec, 104c125e, 4e067f62, aec5dcc8, b587a3d6, f3de6e6b: DR, VAA, and
"tune" stuff was fully removed later on or replaced with other
mechanisms.
340183b0: screenshots were redone later (the VOCTRL was even removed,
with an independent implementation using the same VOCTRL a few years
later), so not relevant anymore. Basically only the 's' shortcut remains
(but not its implementation).
92c5c274, bffd4007, 555c6766: for now marked as GPL only in a previous
commit.
Might contain some trace amounts of "michael"'s copyright, who agreed to
LGPL only once the core is relicensed. This will still be respected, but
I don't think it matters at this in this case. (Some code touched by him
was merged into mplayer.c, and then disappeared after heavy
refactoring.)
I tried to be as careful and as complete as possible. It can't be
excluded that amends to this will be made later.
This does not make the player LGPL yet.
Make mpv_observe_property() work correctly on them even with
--keep-open-pause=no.
This also changes the situations in which the screensaver is
enabled/disabled subtly.
Extend the flag-based notification mechanism that was used via
M_OPT_TERM. Make the vo_opengl update mechanism use this (which, btw.,
also fixes compilation with OpenGL renderers forcibly disabled).
While this adds a 3rd mechanism and just seems to further the chaos, I'd
rather have a very simple mechanism now, than actually furthering the
mess by mixing old and new update mechanisms. In particular, we'll be
able to remove quite some property implementations, and replace them
with much simpler update handling. The new update mechanism can also
more easily refactored once we have a final mechanism that handles
everything in an uniform way.
All option write accesses are now put through the property interface,
which means runtime option value verification and runtime updates are
applied. This is done even for command line arguments and config files.
This has many subtle and not-so-subtle consequences. The potential for
unintended and intended subtle or not-subtle behavior changes is very
large.
Architecturally, this is us literally jumping through hoops. It really
should work the other way around, with options being able to have
callbacks for value verification and applying runtime updates. But this
would require rewriting the entirety of command.c. This change is more
practical, and if anything will at least allow incremental changes.
Some options are too incompatible for this to work - these are excluded
with an explicit blacklist.
This change fixes many issues caused by the mismatch between properties
and options. For example, this fixes#3281.
Now options are accessible through the property list as well, which
unifies them to a degree.
Not all options support runtime changes (meaning affected components
need to be restarted for the options to take effects). Remove from the
manpage those properties which are cleanly mapped to options anyway.
From the user-perspective they're just options available through the
property interface.
This affects A-B loops and --loop-file, and audio. Instead of dropping
audio by resetting the AO, try to make it seamless by not sending data
after the loop point, and after the seek send new data without a reset.
Instead of using the "vf" command code (which changes filters at runtime
on user input), use the general filter-insertion code. The latter was
added later, and is more suitable for automatically inserted filters.
The old code failed in particular when using watch-later saving, which
stored the filter list in the resume config file. If a user changed the
hardware decoding mode via command line, the stored filter chain was out
of date and could cause failure due to not working with hardware or
software decoding mode. Storing the deinterlace filter in the filter
list was unavoidable, because it was part of the user state. (The new
code only edits the actually instantiated filters.)
If filters are disabled or reconfigured, attempt to remove and probe the
deinterlace filter again. This fixes behavior if e.g. a software deint
filter was automatically inserted, and then hardware decoding is enabled
during playback. Without this commit, initializing hw decoding would
fail because of the software filter; with this commit, it'll replace it
with the hw deinterlacer instead.
The previous behavior is confusing if the B point is near EOF (consider
B being the duration of the file, which is strictly speaking past the
last video timestamp). The new behavior is fine as well for B being far
past EOF.
Achieve this by checking the EOF state in addition to whether playback
has reached the B point. Also, move the A-B loop code out of
command_event(). It just isn't useful anymore, and obfuscates the code
more than it makes it loop simple.
Fixes#2046.
The way the AO wakes up the playloop has nothing to do with events;
instead we must query the events on the AO once the playloop was woken
up. Querying the events in every playloop iteration is thus the correct
way to do this.
This commit adds notifications for hot plugging of devices. It also extends
the old behaviour of the `audio-out-detected-device` property which is now
backed by the hotplugging code. This allows clients to be notified when the
actual audio output device changes.
Maybe hotplugging should be supported for ao_coreaudio_exclusive too, but it's
device selection code is a bit fragile.
Not very important for the command line player; but GUI applications
will want to know about this.
This only adds the internal API; support for specific audio outputs
comes later.
This reuses the ao struct as context for the hotplug event listener,
similar to how the "old" device listing API did. This is probably a bit
unclean and confusing. One argument got reusing it is that otherwise
rewriting parts of ao_pulse would be required (because the PulseAudio
API requires so damn much boilerplate). Another is that --ao-defaults is
applied to the hotplug dummy ao struct, which automatically applies such
defaults even to the hotplug context.
Notification works through the property observation mechanism in the
client API. The notification chain is a bit complicated: the AO notifies
the player, which in turn notifies the clients, which in turn will
actually retrieve the device list. (It still has the advantage that it's
slightly cleaner, since the AO stuff doesn't need to know about client
API issues.)
The weird handling of atomic flags in ao.c is because we still don't
require real atomics from the compiler. Otherwise we'd just use atomic
bitwise operations.
Opening the stream and opening the demuxer are both done asynchronously,
meaning the player reacts to client API requests. They also can
potentially take a while. Thus it's better to process outstanding
property changes, so that change events are sent for properties that
were changed during opening.
Before this, we merely printed a message to the terminal. Now the API
user can determine this properly. This might be important for API users
which somehow maintain complex state, which all has to be invalidated if
(state-changing) events are missing due to an overflow.
This also forces the client API user to empty the event queue, which is
good, because otherwise the event queue would reach the "filled up"
state immediately again due to further asynchronous events being added
to the queue.
Also add some minor improvements to mpv_wait_event() documentation, and
some other minor cosmetic changes.
Add a generic mechanism to the VO to relay "extra" events from VO to
player. Use it to notify the core of window resizes, which in turn will
be used to mark all affected properties ("window-scale" in this case) as
changed.
(I refrained from hacking this as internal command into input_ctx, or to
poll the state change, etc. - but in the end, maybe it would be best to
actually pass the client API context directly to the places where events
can happen.)
A vague idea to get something similar what libquvi did.
Undocumented because it might change a lot, or even be removed. To give
an idea what it does, a Lua script could do the following:
-- type ID priority
mp.commandv("hook_add", "on_load", 0, 0)
mp.register_script_message("hook_run", function(param, param2)
-- param is "0", the user-chosen ID from the hook_add command
-- param2 is the magic value that has to be passed to finish
-- the hook
mp.resume_all()
-- do something, maybe set options that are reset on end:
mp.set_property("file-local-options/name", "value")
-- or change the URL that's being opened:
local url = mp.get_property("stream-open-filename")
mp.set_property("stream-open-filename", url .. ".png")
-- let the player (or the next script) continue
mp.commandv("hook_ack", param2)
end)
Internally, there are two mechanisms which can trigger property
notification as used with "observed" properties in the client API.
The first mechanism associates events with a group of properties that
are potentially changed by a certain event. mp_event_property_change[]
declares these associations, and maps each event to a set of strings.
When an event happens, the set of strings is matched against the list of
observed properties of each client. Make this more efficient by
comparing bitsets of events instead. This way, only a bit-wise "and" is
needed for each observed property. Even better, we can completely skip
clients which have no observed properties that match.
The second mechanism just updates individual properties explicitly by
name. Optimize this by using the property index instead. It would be
nice if we could reuse the first mechanism for the second one, but
there are too many properties to fit into a 64 bit mask.
(Though the limit on 64 events might get us into trouble later...)
Achieve this by polling. Will be used by the OSC. Basically a bad hack -
but the point is that the mpv core itself is in the best position to
improve this later.
Instead of absuing m_option to store the property list, introduce a
separate type for properties. m_option is still used to handle data
types. The property declaration itself now never contains the option
type, and instead it's always queried with M_PROPERTY_GET_TYPE. (This
was already done with some properties, now all properties use it.)
This also fixes that the function signatures did not match the function
type with which these functions were called. They were called as:
int (*)(const m_option_t*, int, void*, void*)
but the actual function signatures were:
int (*)(m_option_t*, int, void*, MPContext *)
Two arguments were mismatched.
This adds one line per property implementation. With additional the
reordering of the parameters, this makes most of the changes in this
commit.
Until now, an error was reported only if the command couldn't be parsed.
Attempt to do more fine-grained reporting. This is not necessarily
perfect, but it's an improvement.
This turned out ridiculously complex. I think it will have to be
simplified some day. Main reason for the complexity are:
- filtering properties by forcing clients to observe individual
properties explicitly
(to avoid spamming clients with changes they don't want)
- optional retrieval of property value with the notification
(the basic idea was that this is more user friendly)
- allowing to the client to specify a format in which the value
should be retrieved
(because if a property changes its type, the client API couldn't
convert it properly, and compatibility would break)
I don't know yet which of these are important, and everything could
change. In particular, the interface and semantics should be adjusted
to reduce the implementation complexity.
While I consider the API complete, there could (and probably will) be
bugs left. Also while the implementation is complete, it's inefficient.
The complexity of the property matching is O(a*b*c) with a clients,
b observed properties, and c properties changing at once. I threw away
an earlier implementation using bitmasks, because it was too unwieldy.
M_OPT_PARSE_ESCAPES was pretty stupid, and broke the (useful) assumption
that string variables contain exactly the same value as set by the
option. Simplify it, and move escape handling to the place where it's
used.
Escape handling itself is not terribly useful, but still allows useful
things like multiline custom OSD with "\n".
This is partial only, and it still accesses some MPContext internals.
Specifically, chapter and track lists are still read directly, and OSD
access is special-cased too.
The OSC seems to work fine, except using the fast-forward/backward
buttons. These buttons behave differently, because the OSC code had
certain assumptions how often its update code is called.
The Lua interface changes slightly.
Note that this has the odd property that Lua script and video start
at the same time, asynchronously. If this becomes an issue, explicit
synchronization could be added.
Add a client API, which is intended to be a stable API to get some rough
control over the player. Basically, it reflects what can be done with
input.conf commands or the old slavemode. It will replace the old
slavemode (and enable the implementation of a new slave protocol).