On user request to quit, two kinds of blocking calls must be interrupted
on the server:
1. the reads from and writes to the socket;
2. the call to MediaCodec.dequeueOutputBuffer().
The former case was handled by calling shutdown() on the socket from the
client, but the latter was not managed.
There is no easy way to wake this call properly, so just terminate the
process from the client (i.e. send SIGTERM on Linux) instead.
The server is copied to /data/local/tmp/scrcpy-server.jar and executed
on the device.
As soon as we are connected, we can unlink (rm) it from /data/local/tmp,
to keep the device clean.
The server is currently a JAR, but it may ba an APK or a DEX, so the
variable name should not contain the type.
Rename the environment variable, the Meson options and the C
definitions.
No exception was thrown on EOF, so the event controller did not
terminate. This leaded to a further InvocationTargetException.
Instead, terminate the event controller on EOF, so that the process
terminates properly.
Expose net_recv_all() and net_send_all(), equivalent of net_recv() and
net_send(), but that waits/retries until the requested length has been
transferred.
Use these new functions where it was (wrongly) assumed that the
requested length had been transferred.
SDL_net is not very suitable for scrcpy.
For example, SDLNet_TCP_Accept() is non-blocking, so we have to wrap it
by calling many SDL_Net-specific functions to make it blocking.
But above all, SDLNet_TCP_Open() is a server socket only when no IP is
provided; otherwise, it's a client socket. Therefore, it is not possible
to create a server socket bound to localhost, so it accepts connections
from anywhere.
This is a problem for scrcpy, because on start, the application listens
for nearly 1 second until it accepts the first connection, supposedly
from the device. If someone on the local network manages to connect to
the server socket first, then they can stream arbitrary H.264 video.
This may be troublesome, for example during a public presentation ;-)
Provide our own simplified API (net.h) instead, implemented for the
different platforms.
The syntax was correct, but less readable, and it unnecessarily zeroed
the fields other than "type".
Create the event properly, from a separate method.
screen_render() should not be called on initialization:
1. it is useless, since the window is hidden until the first frame;
2. it writes an empty texture (probably green) to the renderer.
The "screen control" handled user input, which happened to be only
used to control the screen.
The controller and screen were passed to every function. Instead, group
them in a struct input_manager.
The purpose is to add a new shortcut to enable/disable FPS counter. This
feature is not related to "screen control", and will require access to
the "frames" instance.
The device serial was provided as a positional argument:
scrcpy 0123456789abcdef
Instead, expose it as an optional argument, -s or --serial:
scrcpy -s 0123456789abcdef
This avoids inconsistency between platforms when the positional
argument is passed before the options (which is undefined).
Add a script to simplify the execution of scrcpy generated in a specific
build directory.
To run scrcpy generated in builddir, with a video size of 1024:
./run builddir -m 1024
Expose a 'prebuilt_server' option to pass the path of the prebuilt
binary, so that the build does not require Android SDK.
Usage:
meson builddir -Dprebuilt_server=/tmp/my_prebuilt_server.jar
The custom target used to invoke Gradle from Meson should always
be built, otherwise, the server would not be rebuilt on source changes.
However, when enabling "build_always", gradle is invoked as root on
"sudo ninja install" after "ninja", so it downloads the whole Gradle
world into /root/.gradle.
To avoid the problem, just do not call gradle if the effective user id
is 0.
Since Meson 0.44, subproject_dir may not be '.' anymore. This implies we
must move app/ and server/ to a subprojects/ directory, which requires
to also change some gradle files.
Instead, just use subdir(), with options to disable building of the app
or the server.
The client was built with Meson, the server with Gradle, and were run by
a Makefile.
Add a Meson script for the server (which delegates to Gradle), and a
parent script to build and install both the client and the server to the
system, typically with:
meson --buildtype release build
cd build
ninja
sudo ninja install
In addition, use a separate Makefile to build a "portable" version of
the application (where the client expects the server to be in the
current directory). Typically:
make release-portable
cd dist/scrcpy
./scrcpy
This is especially useful for Windows builds, which are not "installed".
The current meson version is able to generate a config.h from a
configuration data object without any template.
However, older versions of meson require a template, so provide it for
compatibility.
Characters like 'é' or 'î' are not resolved by getEvents(). For example,
getEvents("é") returns null.
However, it is possible to decompose them. For example,
getEvents("\u0301e") returns the events generating "é".
Thank you Philippe! ;)
The SDL clean up does not crash anymore on exit, probably since the
memory corruption caused by calling SDLNet_TCP_Close() too early has
been resolved.