Some window managers can prevent mapping of a window as a feature. i3
can put new windows on a certain workspace (with "assign"), so if mpv is
started on a different workspace, the window will never be mapped.
mpv currently waits until the window is mapped (blocking almost all of
the player), in order to avoid race conditions regarding the window
size. We don't want to remove this, but on the other hand we also don't
want to block the player forever in these situations.
So what we need is a way to know when the window manager is "done" with
processing the map request. Unfortunately, there doesn't seem to be a
standard way for this. So, instead we could do some arbitrary
communication with the WM, that may act as "barrier" after map request
and the "immediate" mapping of the window. If the window is not mapped
after this barrier, it means the window manager decided to delay the
mapping indefinitely. Use the _NET_REQUEST_FRAME_EXTENTS message as such
a barrier. WMs supporting this message must set the _NET_FRAME_EXTENTS
property on the mpv window, and we receive a PropertyNotify event. If
that happens, we always continue and cancel waiting for the MapNotify
event.
I don't know if this is sane or if there's a better mechanism. Also,
this works only for WMs which support this message, which are not many.
But at least it appears to work on i3. It may reintroduce flickering on
fullscreen with other WMs, though.
This is pretty imperfect, but it's just a demo.
The main purpose is clarifying how and when to get the video size.
In theory, retrieving the properties this way has a race condition:
after reading dwidth, the video could resize again. But the worst that
can happen are mismatching dwidth/dheight values, and the
MPV_EVENT_VIDEO_RECONFIG event would be immediately received again,
which would fix the mismatch. You could read the full video-out-params
property to absolutely avoid it, but it's not worth the trouble.
Merges pull request #1094, with some minor changes. mpv expects IEEE,
and IEEE allows divisions by 0 for floats, so these shouldn't actually
be a problem, but do it anyway for the sake of clang.
Signed-off-by: wm4 <wm4@nowhere>
Use libwaio to read from pipes (stdin or named pipes) on Windows. This
liberates us from nasty issues, such as pipes (as created by most
programs) not being possible to read in a non-blocking or event-driven
way. Although it would be possible to do that in a somewhat sane way
on Vista+, it's still not easy, and on XP it's especially hard. libwaio
handles these things for us.
Move pipe.c to pipe-unix.c, and remove Windows specific things. Also
adjust the input.c code to make this work cleanly.
If you send the "quit" or "stop" command with the client API, it will
now attempt to kill network I/O immediately (same as normal input in the
previous commits).
Refine the ugly hack from the previous commit, and let the "quit"
command and some others abort playback immediately. For
playlist_next/playlist_prev, still use the old hack, because we can't
know if they would stop playback or not.
This mechanism originates from MPlayer's way of dealing with blocking
network, but it's still useful. On opening and closing, mpv waits for
network synchronously, and also some obscure commands and use-cases can
lead to such blocking. In these situations, the stream is asynchronously
forced to stop by "interrupting" it.
The old design interrupting I/O was a bit broken: polling with a
callback, instead of actively interrupting it. Change the direction of
this. There is no callback anymore, and the player calls
mp_cancel_trigger() to force the stream to return.
libavformat (via stream_lavf.c) has the old broken design, and fixing it
would require fixing libavformat, which won't happen so quickly. So we
have to keep that part. But everything above the stream layer is
prepared for a better design, and more sophisticated methods than
mp_cancel_test() could be easily introduced.
There's still one problem: commands are still run in the central
playback loop, which we assume can block on I/O in the worst case.
That's not a problem yet, because we simply mark some commands as being
able to stop playback of the current file ("quit" etc.), so input.c
could abort playback as soon as such a command is queued. But there are
also commands abort playback only conditionally, and the logic for that
is in the playback core and thus "unreachable". For example,
"playlist_next" aborts playback only if there's a next file. We don't
want it to always abort playback.
As a quite ugly hack, abort playback only if at least 2 abort commands
are queued - this pretty much happens only if the core is frozen and
doesn't react to input.
This means they get special handling for asynchronously aborting
playback, even if the player is "stuck".
Also document "stop". It seems somewhat useful for client API users
(although that will be implemented properly only in the following
commits.)
The memcpy() is actually not enough: the types are incompatible, and no
memcpy, union, etc. will change that. (Although no real compiler will
ever break this.) Attempt to make this theoretically correct by actually
using a struct pointer. It's not the same struct type, but supposedly
it's ok, because all struct pointers always have the same size and
representation in standard C.
Idle mode went to sleep too early, e.g. just pressing "ESC" did nothing,
until the next event happened. This was because it directly went to
sleep after processing commands. What we should do instead is rechecking
all state after processing commands, redraw OSD, and then go to sleep.
This also fixes some strange OSD-related behavior.
Also move some other code around to separate idle mode initialization
from the normal run loop.
Not sure why this was originally added as autorepeated. It makes no
sense, because switching between choices should never autorepeat. (For
the normal "add"/"cycle" commands, autorepeat is usually enabled, but
command.c tries to disable it specifically for choice properties.)
Mismatching units in timeout calculation.
Also, as a near-cosmetic change, explicitly wake up the core on the
right time. Currently this does nothing, because the core is woken up
anyway - but it will matter with the next commit.
Replace select() usage with poll() (and reduce code duplication).
Also, while we're at it, drop --disable-audio-select, since it has the
wrong name anyway. And I have doubts that this is needed anywhere. If
it is, it should probably fallback to doing the right thing by default,
instead of requiring the user to do it manually. Since nobody has done
that yet, and since this configure option has been part of MPlayer ever
since ao_oss was added, it's probably safe to say it's not needed.
The '#ifdef SNDCTL_DSP_GETOSPACE' was pointless, since it's already used
unconditionally in another place.
1. Separate buffer and temporary file handling from the vo to make maintenance
and reading code easier
2. Skip resizing as much as possible if back buffer is still busy.
3. Detach and mark osd buffers for deletion if we want to redraw them and they
are still busy. This could be a possible case for the video buffers as
well. Maybe better than double buffering.
All the above steps made it possible to have resizing without any artifacts
even for subtitles. Also fixes dozen of bugs only I knew, like broken subtitles
for rgb565 buffers. I can now sleep at night again.
OSX is POSIX conformant, but it's a sad joke: it provides the
<semaphore.h> prototype as the standard demands, but they're empty
wrappers, and all functions just return ENOSYS.
Emulate them similar to how osdep/io.h emulate filesystem functions on
Windows. By including the header, working sem_* functions become
available.
To make it async-signal safe, use a pipe for wakeup (write() is AS-safe,
but mutexes can't be). Actually I'm not sure anymore if we really need
AS-safety, but for now the emulation can do it.
On Linux, the system provides a far more efficient and robust
implementation. We definitely want to avoid using the emulation if
possible, so this code is active on OSX only. For convenience we always
build the source file though, even if the implementation is disabled and
no actual code is generated.
(Linux provides working semaphores, but is formally not POSIX
conformant. On OSX it's the opposite. Is POSIX a complete joke?)
I'm not quite sure what we should actually do (maybe read input
commands?), but interpreting input as terminal key sequences is
definitely weird. So just do nothing.
Do terminal input with a thread, instead of using the central select()
loop. This also changes some details how SIGTERM is handled.
Part of my crusade against mp_input_add_fd().
An attempt at fixing #1070. Apparently something goes wrong if the
video size is equal to the screen size. Since the window decorations
add to the window size, it must actually be larger than the screen.
Actually I don't know what exactly is going wrong, but since this
commit also slightly improves the behavior otherwise, it's a win
anyway.
Try to keep the window size strictly below screen size, even accounting
for window decorations. Size it down and center the window so that it
fits (by either touching the left/right or top/bottom screen borders).
I haven't found any information on what is the maximum allowed size and
position of a window so that it doesn't collide with the task bar, so
assume that we can use the entire screen, minus 1 pixel to avoid
triggering fullscreen semantics (if that is even possible).
The purpose is making accessing the current playlist entry saner when
commands are executed during initialization, termination, or after
playlist navigation commands.
For example, the "playlist_remove current" command will invalidate
playlist->current - but some things still access the playlist entry even
on uninit. Until now, checking stop_play implicitly took care of it, so
it worked, but it was still messy.
Introduce the mpctx->playing field, which points to the current playlist
entry, even if the entry was removed and/or the playlist's current entry
was moved (e.g. due to playlist navigation).
To handle legacy commands, string replacement is used; the modified
string is returned by parse_cmd_str(), but it also frees all temporary
memory, which includes the replaced string.
Closes#1075.