Trigger SDL_CONTROLLERDEVICEADDED for all gamepads already connected
when scrcpy starts. We want to handle both the gamepads initially
connected and the gamepads connected while scrcpy is running.
This is not racy, because this event may not trigged automatically until
SDL events are "pumped" (SDL_PumpEvents/SDL_WaitEvent).
Introduce a gamepad processor trait, similar to the keyboard processor
and mouse processor traits.
Handle gamepad events received from SDL, convert them to scrcpy-specific
gamepad events, and forward them to the gamepad processor.
Further commits will provide AOA and UHID implementations of the gamepad
processor trait.
Co-authored-by: Luiz Henrique Laurini <luizhenriquelaurini@gmail.com>
Now that the AOA open/close are asynchronous, an open error did not make
scrcpy exit anymore.
Add a mechanism to exit if the AOA device could not be opened
asynchronously.
Pushing a close event from the keyboard_aoa or mouse_aoa implementation
was racy, because the AOA thread might be stopped before these events
were processed.
Instead, keep the list of open AOA devices to close them automatically
from the AOA thread before exiting.
This allows to handle HID open/close at the same place as HID input
events (in the HID layer).
This will be especially useful to manage HID gamepads, to avoid
implementing one part in the HID layer and another part in the gamepad
processor implementation.
For AOA keyboard and mouse, only input events were asynchronous.
Register/unregister were called from the main thread.
This had the benefit to fail immediately if the AOA registration failed,
but to support gamepads we want to open/close AOA devices dynamically.
Also, it is better to avoid USB I/O from the main thread.
The HID ids (accessory ids or UHID ids) were defined by the keyboard and
mouse implementations.
Instead, define them in the common HID part, and make that id part of
the sc_hid_event.
This prepares the introduction of gamepad support, which will handle
several gamepads (and ids) in the common HID gamepad code.
Control messages are queued from the main thread and sent to the device
from a separate thread.
When the queue is full, messages are just dropped. This avoids to
accumulate too much delay between the client and the device in case of
network issue.
However, some messages should not be dropped: for example, dropping a
UHID_CREATE message would make invalid all further UHID_INPUT messages.
Therefore, mark these messages as non-droppable.
A non-droppable event is queued anyway (resizing the queue if
necessary, unless the allocation fails).
This allows to schedule a runnable to be executed on the main thread,
until the event loop is explicitly terminated.
It is guaranteed that all accepted runnables will be executed (this
avoids possible memory leaks if a runnable owns resources).
In Java, control messages were parsed using manual buffering, which was
convoluted and error-prone.
Instead, read the socket directly through a DataInputStream and a
BufferedInputStream. Symmetrically, use a DataOutputStream and a
BufferedOutputStream to write messages.
Even if the pointer is a mouse, inject it as a finger unless it is
required to be a mouse, that is:
- when it is a HOVER_MOUSE event, or
- when a secondary button is pressed.
Some apps/games only accept events from a finger/touchscreen, so using a
mouse by default does not work for them.
For simplicity, make this change on the server side just before
event injection (so that the client does not need to know about this
hacky behavior).
Refs 6808288823239b0f3a76f9be377e4de82e91b35a
Refs c7b1d0ea9af8bb9603ec8f713f1a5fbf3f628b6a
Fixes#5162 <https://github.com/Genymobile/scrcpy/issues/5162>
Fixes#5163 <https://github.com/Genymobile/scrcpy/issues/5163>
By default, the audio source is initialized to SC_AUDIO_SOURCE_AUTO, and
is "resolved" only if audio is enabled.
But the server arguments were built assuming that the audio source was
never SC_AUDIO_SOURCE_AUTO (even with audio disabled), causing a crash.
Regression introduced by a10f8cd798023f858796b023cb846fa2184ad2c7.
Automatically switch implicit audio source to "playback" if --audio-dup
is passed.
This allows to run:
scrcpy --audio-dup
without specifying explicitly:
scrcpy --audio-source=playback --audio-dup
PR #5102 <https://github.com/Genymobile/scrcpy/pull/5102>