The current process could be waited both by run_file_handler() and
file_handler_stop().
To avoid the race condition, wait the process without closing, then
close with mutex locked.
There were two versions: process_wait() and process_wait_noclose().
Expose a single version with a flag (it was already implemented that way
internally).
The function process_wait() returned a bool (true if the process
terminated successfully) and provided the exit code via an output
parameter exit_code.
But the returned value was always equivalent to exit_code == 0, so just
return the exit code instead.
The size, point and position structs were defined in common.h. Move them
to coords.h so that common.h could be used for generic code to be
included in all source files.
The header libavformat/version.h was included, but not
libavcodec/version.h.
As a consequence, the LIBAVCODEC_VERSION_INT definition depended on the
caller includes.
On Linux, waitpid() both waits for the process to terminate and reaps it
(closes its handle). On Windows, these actions are separated into
WaitForSingleObject() and CloseHandle().
Expose these actions separately, so that it is possible to send a signal
to a process while waiting for its termination without race condition.
This allows to wait for server termination normally, but kill the
process without race condition if it is not terminated after some delay.
Let the server terminate properly once all the sockets are closed.
If it does not terminate (this can happen if the device is asleep), then
kill it.
Note: since the server process termination is detected by a flag set
after waitpid() returns, there is a small chance that the process
terminates (and the PID assigned to a new process) before the flag is
set but before the kill() call. This race condition already existed
before this commit.
Fixes#1992 <https://github.com/Genymobile/scrcpy/issues/1992>
TerminateProcess() is "equivalent" to kill(), while
WaitForSingleObject() is "equivalent" to waitpid(), so the handle must
be closed after WaitForSingleObject().
On Windows, scrcpy paused on error before exiting to give the user a
chance to see the user message.
This was a hack and causes issues when using scrcpy from batch scripts.
Disable this pause from the scrcpy binary, and provide a batch wrapper
(scrcpy-console.bat) to pause on error.
Fixes#1875 <https://github.com/Genymobile/scrcpy/issues/1875>
Use "%Iu" on Windows. This fixes the following warning:
../app/src/sys/win/command.c:17:14: warning: unknown conversion type character ‘l’ in format [-Wformat=]
17 | LOGE("Command too long (%" PRIsizet " chars)", len - 1);
A new "repeat" field has been added by
3c1ed5d86c, but it was not initialized in
every code path.
As a consequence, keycodes generated by shortcuts were sent with an
undetermined value, breaking some shortcuts (especially HOME) randomly.
Fixes#1643 <https://github.com/Genymobile/scrcpy/issues/1643>
This avoids to pass specific options values individually. Since these
function are static (internal to the file), this is not a problem to
make them depend on scrcpy_options.
Refs #1623 <https://github.com/Genymobile/scrcpy/pull/1623>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Send COPY and CUT on MOD+c and MOD+x (only supported for Android >= 7).
The shortcuts Ctrl+c and Ctrl+x should generally also work (even before
Android 7), but the active Android app may use them for other actions
instead.
Do not explicitly set the clipboard text if it already contains the
expected content.
Even if copy-paste loops are avoided by the previous commit, this avoids
to trigger a clipboard change on the computer-side.
Refs #1580 <https://github.com/Genymobile/scrcpy/issues/1580>
Pressing Ctrl+v on the device will typically paste the clipboard
content.
Before sending the key event, synchronize the computer clipboard to the
device clipboard to allow seamless copy-paste.
Now that the scrcpy shortcut modifier is Alt by default (and can be
configured), forward Ctrl to the device.
This allows to trigger Android shortcuts.
Fixes#555 <https://github.com/Genymobile/scrcpy/issues/555>
Pressing Alt+c generates a text event containing "c", so "c" was sent to
the device when --prefer-text was enabled.
Ignore text events when the mod state matches a shortcut modifier.
Remove the Cmd modifier on macOS, which was possible only for some
shortcuts but not all.
This paves the way to make the shortcut modifier customizable.
Touch events were HiDPI-scaled twice:
- once because the position (provided as floats between 0 and 1) were
converted in pixels using the drawable size (not the window size)
- once due to screen_convert_to_frame_coords()
One possible fix could be to compute the position in pixels from the
window size instead, but this would unnecessarily round the event
position to the nearest window coordinates (instead of drawable
coordinates).
Instead, expose two separate functions to convert to frame coordinates
from either window or drawable coordinates.
Fixes#1536 <https://github.com/Genymobile/scrcpy/issues/1536>
Refs #15 <https://github.com/Genymobile/scrcpy/issues/15>
Refs e40532a376
The header scrcpy.h is intended to be the "public" API. It should not
depend on other internal headers.
Therefore, declare all required structs in this header and adapt
internal code.
The function must return a SDL_LogPriority, but returned an enum
sc_log_level.
(It was harmless because this specific return should never happen, as
asserted.)
This reverts commit 8c8649cfcd.
I cannot reproduce the issue with Ctrl+Shift+o on any device, so in
practice it works, it's too bad to remove the feature for a random bug
on some Android versions on some devices.
Add a command-line option to force "adb forward", without attempting
"adb reverse" first.
This is especially useful for using SSH tunnels without enabling remote
port forwarding.
The verbosity was set either to info (in release mode) or debug (in
debug mode).
Add a command-line argument to change it, so that users can enable debug
logs using the release:
scrcpy -Vdebug
The field lock_video_orientation may only take values between -1 and 3
(included). But the compiler may trigger a warning on the sprintf()
call, because its type could represent values which could overflow the
string (like "-128"):
> warning: ‘%i’ directive writing between 1 and 4 bytes into a region of
> size 3 [-Wformat-overflow=]
Increase the buffer size to remove the warning.
Trilinear filtering can currently only be enabled for OpenGL renderers.
Do not print a warning if the renderer is not OpenGL, as it can confuses
users, while nothing is wrong.
On macOS with renderer "metal", HiDPI scaling may be incorrect on
initialization when several displays are connected.
Resetting the window size fixes the problem.
Refs #15 <https://github.com/Genymobile/scrcpy/issues/15>
Position and scale the content "manually" instead of relying on the
renderer "logical size".
This avoids possible rounding differences between the computed window
size and the content size, causing one row or column of black pixels on
the bottom or on the right.
This also avoids HiDPI scale issues, by computing the scaling manually.
This will also enable to draw items at their expected size on the screen
(unscaled).
Fixes#15 <https://github.com/Genymobile/scrcpy/issues/15>
In maximized state (but not fullscreen), it was possible to resize to
fit the device screen (with Ctrl+x or double-clicking on black borders).
This caused problems on macOS with the "expand to fullscreen" feature,
which behaves like a fullscreen mode but is seen as maximized by SDL.
In that state, resizing to fit causes unexpected results.
To keep the behavior consistent on all platforms, just disable "resize
to fit" when the window is maximized.
On Windows, in maximized+fullscreen state, disabling fullscreen mode
unexpectedly triggers the "restored" then "maximized" events, leaving
the window in a weird state (maximized according to the events, but not
maximized visually).
Moreover, apply_pending_resize() asserts that fullscreen is disabled.
To avoid the issue, if fullscreen is set, just ignore the "restored"
event.
If the content size changes (due to rotation for example) while the
window is maximized or fullscreen, the resize must be applied once
fullscreen and maximized are disabled.
The previous strategy consisted in storing the windowed size, computing
the target size on rotation, and applying it on window restoration. But
tracking the windowed size (while ignoring the non-windowed size) was
tricky, due to unspecified order of SDL events (e.g. size changes can be
notified before "maximized" events), race conditions when reading window
flags, different behaviors on different platforms...
To simplify the whole resize management, store the old content size (the
frame size, possibly rotated) when it changes while the window is
maximized or fullscreen, so that the new optimal size can be computed on
window restoration.
By default, Ctrl+C just kills the process on Windows. This caused
corrupted video files on recording.
Handle Ctrl+C properly to clean up properly.
Fixes#818 <https://github.com/Genymobile/scrcpy/issues/818>
Now that the server can access the Android settings and clean up
properly, handle the "show touches" option from the server.
The initial state is now correctly restored, even on device
disconnection.
The window dimensions are integers, so resizing to fit the content may
not be exact.
When computing the optimal size, it could cause to reduce alternatively
the width and height by few pixels, making the "optimal size" unstable.
To avoid this problem, check if the optimal size is already correct
either by keeping the width or the height.
Move the window-to-frame coordinates conversion from the input manager
to the screen.
This will allow to apply more screen-related transformations without
impacting the input manager.
Some compilers warns on uninitialized value in impossible case:
warning: variable 'result' is used uninitialized whenever switch
default is taken [-Wsometimes-uninitialized]
A double-click outside the device content (in the black borders) resizes
so that black borders are removed. But the display rotation was not
taken into account to detect the content.
Use the content size instead of the frame size to fix the issue.
Ref: <https://github.com/Genymobile/scrcpy/issues/898#issuecomment-610993695>
Add Ctrl+Left and Ctrl+Right shortcuts to rotate the display (the
content of the scrcpy window).
Contrary to --lock-video-orientation, the rotation has no impact on
recording, and can be changed dynamically (and immediately).
Fixes#218 <https://github.com/Genymobile/scrcpy/issues/218>
The server may die before connecting to the client. In that case, the
client was blocked indefinitely (until Ctrl+C) on accept().
To avoid the problem, close the server socket once the server process is
dead.
Accept a range of ports to listen to, so that it does not fail if
another instance of scrcpy is currently starting.
The range can be passed via the command line:
scrcpy -p 27183:27186
scrcpy -p 27183 # implicitly 27183:27183, as before
The default is 27183:27199.
Closes#951 <https://github.com/Genymobile/scrcpy/issues/951>
Start the server socket in enable_tunnel() directly.
For the caller point of view, enabling the tunnel opens a port (either
the server socket locally or the "adb forward" process).
The platform-specific code for net.c was implemented in sys/*/net.c.
But the differences are quite limited, so use ifdef-blocks in the single
net.c instead.
The file 'E:\安安\scrcpy-win64-v1.12.1-1-g31bd950\scrcpy-server'
exists, however, it will show msg as follow:
INFO: scrcpy 1.12.1 <https://github.com/Genymobile/scrcpy>
stat: No such file or directory
ERROR: 'E:\安安\scrcpy-win64-v1.12.1-1-g31bd950\scrcpy-server' does
not exist or is not a regular file
Press any key to continue...
This patch fixes it.
Signed-off-by: Yu-Chen Lin <npes87184@gmail.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
The function get_server_path() sometimes returned an owned string,
sometimes a non-owned string.
Always return an allocated (owned) string, and free it after usage.
A proper solution could be to use "long long" instead (guaranteed to be
at least 64 bits), but it adds its own problems (e.g. "%lld" is not
supported as a printf format on all platforms).
In practice, we don't need such high values, so keep it simple.
Fixes#995 <https://github.com/Genymobile/scrcpy/issues/995>
If SCRCPY_SERVER_PATH points to a directory, then a directory will be
pushed to /data/local/tmp/scrcpy-server.jar.
When executing it, app_process will just abort and leave the directory
on the device, causing scrcpy to always fail.
To avoid the problem, check that the server is a regular file before
pushing it.
Closes#956 <https://github.com/Genymobile/scrcpy/issues/956>
> Movements down (scroll backward) generate negative y values and up
> (scroll forward) generate positive y values.
> If direction is SDL_MOUSEWHEEL_FLIPPED the values in x and y will be
> opposite. Multiply by -1 to change them back.
<https://wiki.libsdl.org/SDL_MouseWheelEvent#Remarks>
The x and y values already take the scrolling configuration into
account. Reversing the values when the direction is flipped cancels the
scrolling configuration.
Therefore, just ignore the direction field.
Fixes <https://github.com/Genymobile/scrcpy/issues/966>
Commit 3da95b52bd renamed
'scrcpy-server.jar' to 'scrcpy-server' to avoid issues on the client
side.
However, removing the extension may cause issues with app_process, so
restore the extension only on the device side.
Fixes <https://github.com/Genymobile/scrcpy/issues/944>
Send client version as first parameter and check it at server start.
Signed-off-by: Yu-Chen Lin <npes87184@gmail.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Expose an option to configure how key/text events are forwarded to the
Android device.
Enabling the option avoids issues when combining multiple keys to enter
special characters, but breaks the expected behavior of alpha keys in
games (typically WASD).
Fixes <https://github.com/Genymobile/scrcpy/issues/650>
Mouse events coordinates depend on the screen size and location, so the
converter need to access the screen.
The fact that it needs the position or the size is an internal detail,
so pass a pointer to the whole screen structure.
Now, get_window_size() returns the current window size (fullscreen or
not), while get_windowed_window_size() always returned the windowed size
(the size when fullscreen is disabled).
Headers seem to be a bit different in Apple land and you need to include
stddef.h explicitly to the NULL declaration.
This also makes the code a bit more correct, as stddef.h is the header
in the C standard that defines NULL
(https://en.cppreference.com/w/cpp/header/cstddef).
We need several FIFO queues (a queue of packets, a queue of messages,
etc.).
Some of them are implemented using cbuf, a generic circular buffer. But
for recording, we need to store the packets in an unbounded queue until
they are written, so the queue was implemented manually.
Create a generic implementation (using macros) to avoid reimplementing
it every time.
The record file was written from the stream thread. As a consequence,
any blocking I/O to write the file delayed the decoder.
For maximum performance even when recording is enabled, send
(refcounted) packets to a separate recording thread.
To packetize the H.264 raw stream, av_parser_parse2() (called by
av_read_frame()) knows that it has received a full frame only after it
has received some data for the next frame. As a consequence, the client
always waited until the next frame before sending the current frame to
the decoder!
On the device side, we know packets boundaries. To reduce latency,
make the device always transmit the "frame meta" to packetize the stream
manually (it was already implemented to send PTS, but only enabled on
recording).
On the client side, replace av_read_frame() by manual packetizing and
parsing.
<https://stackoverflow.com/questions/50682518/replacing-av-read-frame-to-reduce-delay>
<https://trac.ffmpeg.org/ticket/3354>
If --no-control is set, then the controller is not initialized (both in
the client and the server), so it is not possible to control the device
to turn its screen off.
See <https://github.com/Genymobile/scrcpy/issues/608>.
In portable builds, scrcpy-server.jar was supposed to be present in the
current directory, so in practice it worked only if scrcpy was launched
from its own directory.
Instead, find the absolute path of the executable and build a suitable
path to use scrcpy-server.jar from the same directory.