This also means that the printed size is always rounded to KBs, because
the cache properties are returned in KB. I think this doesn't matter
much. But if it does, the cache properties should probably changed to
return bytes in the first place.
Something like "char *s = ...; isdigit(s[0]);" triggers undefined
behavior, because char can be signed, and thus s[0] can be a negative
value. The is*() functions require unsigned char _or_ EOF. EOF is a
special value outside of unsigned char range, thus the argument to the
is*() functions can't be a char.
This undefined behavior can actually trigger crashes if the
implementation of these functions e.g. uses lookup tables, which are
then indexed with out-of-range values.
Replace all <ctype.h> uses with our own custom mp_is*() functions added
with misc/ctype.h. As a bonus, these functions are locale-independent.
(Although currently, we _require_ C locale for other reasons.)
Also allows it to deal with NULL return values, which currently is not
needed, but may or may not be required at some point in the future (what
if malloc fails).
It's better to keep the logic in one place.
Also drop that a broken config file aborts loading of the player. I
don't see much reason for this, and it inflates the code slightly.
Search $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS for config files.
This also negates the need to have separate user and global variants of
mp_find_config_file()
Closes#864, #109.
Signed-off-by: wm4 <wm4@nowhere>
The main issue was actually that the OSD callback locked the subtitle
decoder, which does not necessarily work, because the OSD code is
already allowed to lock it. The state was already protected by
unsetting the callback (which involes the OSD lock). So, in summary,
this is probably just a cleanup.
Let the VOs draw the OSD on their own, instead of making OSD drawing a
separate VO driver call. Further, let it be the VOs responsibility to
request subtitles with the correct PTS. We also basically allow the VO
to request OSD/subtitles at any time.
OSX changes untested.
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.
Does anyone actually use this?
For now, update it, because it's the only case left where an option
points to a global variable (and not a struct offset).
While I'm not very fond of "const", it's important for declarations
(it decides whether a symbol is emitted in a read-only or read/write
section). Fix all these cases, so we have writeable global data only
when we really need.
Convert all these commands to properties. (Except tv_last_channel, not
sure what to do with this.) Also, internally, don't access stream
details directly, but dispatch commands with stream ctrls.
Many of the new properties are a bit strange, because they're write-
only. Also remove some OSD output these commands produced, because I
couldn't be bothered to port these.
In general, this makes everything much cleaner, and will also make it
easier to e.g. move the demuxer to its own thread.
Don't bother updating input.conf, but changes.rst documents how old
commands map to the new ones.
Mostly untested, due to lack of hardware.
Basically, this allows gapless playback with similar files (including
the ordered chapter case), while still being robust in general.
The implementation is quite simplistic on purpose, in order to avoid
all the weird corner cases that can occur when creating the filter
chain. The consequence is that it might do not-gapless playback in
more cases when needed, but if that bothers you, you still can use
the normal gapless mode.
Just using "--gapless-audio" or "--gapless-audio=yes" selects the old
mode.
Since redundant wakeups are avoided now, it's easy to miss a wakeup when
creating/setting the pipe/callback after the client API was signalled.
If the client API is signalled, need_wakeup is set to true, and
wakeup_client skips writing to the pipe or calling the client API. That
this can happen is not very obvious to the client API, so trigger a
wakeup right on start in order to remove this special case.
Until now, availability of new log messages (through the mechanism
associated with mpv_request_log_messages()) did not wakeup the client
API properly. Commit 3b7402b5 was basically a hack to improve that
somewhat, but it wasn't a solution.
The main problem is that the client API itself is producing messages, so
the message callback would attempt to lock the client API lock,
resulting in a deadlock. Even if the lock was recursive, we'd run into
lock-order issues.
Solve this by using a separate lock for waiting and wakeup. Also, since
it's a natural addition, avoid redundant wakeups. This means the wakeup
callback as well as the wakeup pipe will be triggered only once until
the next mpv_wait_event() call happens.
This might make the wakeup callback be invoked in a reentrant way for
the first time, for example if a mpv_* function prints to a log. Adjust
the docs accordingly. (Note that non-reentrant beheavior was never
guaranteed - basically the wakeup callback is somewhat dangerous and
inconvenient.)
Also remove some traces of unneeded code. ctx->shutdown for one was
never set, and probably a leftover of an abandoned idea.
A bit verbose, but less misleading. In most cases, the API user probably
actually wants mpv_terminate_destroy() instead, so the less-useful
function shouldn't have a simnpler name anyway.
mpv_destroy() should perhaps better be called mpv_detach(), because it
destroys only the handle, not necessarily the player. The player is only
terminated if a quit command is sent.
This function quits automatically, and additionally waits until the
player is completely destroyed. It removes the possibility that the
player core is still uninitializing, while all client handles are
already destroyed. (Although in practice, the difference is usually not
important.)
Now a negative timeout mean an infinite timeout. This is similar to the
poll() system call. Apparently this is more intuitive and less confusing
than specifying a "very high" value as timeout if you want to wait
forever.
For callers that never pass negative timeouts, nothing changes.
Listening on messages currently uses polling (every time
mpv_wait_event() has no new events, the message buffer is polled and a
message event is possibly created). Improve this situation a bit, and
call the user-supplied wakeup callback.
This will increase the frequency with which the wakeup callback is
called, but the client is already supposed to be able to deal with this
situation. Also, as before, calling mpv_wait_event() from the wakeup
callback is forbidden, so the client can't read new messages from the
callback directly.
The wakeup pipe is written either. Since the wakeup pipe is created
lazily, we can't access the pipe handle without creating a race
condition or a deadlock. (This is actually very silly, since in practice
the race condition won't matter, but for now let's keep it clean.)
If an API user calls mpv_wait_event() and mpv_observe_property() before
mpv_initialize(), it could happen that a property was accessed before
initialization, which is not ok.
This was always intended this way, and even documented in client.h. Due
to an oversight it was never actually implemented.
The intention is that mpv embedded in applications and "real mpv" don't
conflict. An API user can undo this by setting the "config" option to
"yes", if using the user's mpv config is desired.