diff --git a/BUILD.md b/BUILD.md index 90a7d18ef5..1d5d970b7c 100644 --- a/BUILD.md +++ b/BUILD.md @@ -46,7 +46,7 @@ sudo ninja -Cbuild-auto uninstall ### `master` The `master` branch concerns the latest release, and is the home page of the -project on Github. +project on GitHub. ### `dev` @@ -272,10 +272,10 @@ install` must be run as root)._ #### Option 2: Use prebuilt server - - [`scrcpy-server-v1.23`][direct-scrcpy-server] - _(SHA-256: 2a913fd47478c0b306fca507cb0beb625e49a19ff9fc7ab904e36ef5b9fe7e68)_ + - [`scrcpy-server-v1.24`][direct-scrcpy-server] + SHA-256: `ae74a81ea79c0dc7250e586627c278c0a9a8c5de46c9fb5c38c167fb1a36f056` -[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v1.23/scrcpy-server-v1.23 +[direct-scrcpy-server]: https://github.com/Genymobile/scrcpy/releases/download/v1.24/scrcpy-server-v1.24 Download the prebuilt server somewhere, and specify its path during the Meson configuration: @@ -305,13 +305,16 @@ After a successful build, you can install _scrcpy_ on the system: sudo ninja -Cx install # without sudo on Windows ``` -This installs three files: +This installs several files: - - `/usr/local/bin/scrcpy` - - `/usr/local/share/scrcpy/scrcpy-server` - - `/usr/local/share/man/man1/scrcpy.1` + - `/usr/local/bin/scrcpy` (main app) + - `/usr/local/share/scrcpy/scrcpy-server` (server to push to the device) + - `/usr/local/share/man/man1/scrcpy.1` (manpage) + - `/usr/local/share/icons/hicolor/256x256/apps/icon.png` (app icon) + - `/usr/local/share/zsh/site-functions/_scrcpy` (zsh completion) + - `/usr/local/share/bash-completion/completions/scrcpy` (bash completion) -You can then [run](README.md#run) _scrcpy_. +You can then [run](README.md#run) `scrcpy`. ### Uninstall diff --git a/README.de.md b/README.de.md index 92d00df2f8..1299ae0e00 100644 --- a/README.de.md +++ b/README.de.md @@ -375,7 +375,7 @@ Dies finden automatisch das Gerät und aktiviert den TCP/IP-Modus. Anschließend Alternativ kann die TCP/IP-Verbindung auch manuell per `adb` aktiviert werden: -1. Gerät mit demselben Wifi wie den Computer verbinden. +1. Gerät mit demselben Wi-Fi wie den Computer verbinden. 2. IP-Adresse des Gerätes herausfinden, entweder über Einstellungen → Über das Telefon → Status, oder indem dieser Befehl ausgeführt wird: ```bash diff --git a/README.id.md b/README.id.md index 9657b95a06..1230f0cc65 100644 --- a/README.id.md +++ b/README.id.md @@ -218,7 +218,7 @@ variation] does not impact the recorded file. #### Wireless -_Scrcpy_ menggunakan `adb` untuk berkomunikasi dengan perangkat, dan` adb` dapat [terhubung] ke perangkat melalui TCP / IP: +_Scrcpy_ menggunakan `adb` untuk berkomunikasi dengan perangkat, dan `adb` dapat [terhubung] ke perangkat melalui TCP / IP: 1. Hubungkan perangkat ke Wi-Fi yang sama dengan komputer Anda. 2. Dapatkan alamat IP perangkat Anda (dalam Pengaturan → Tentang ponsel → Status). @@ -281,7 +281,7 @@ Dari terminal lain: scrcpy ``` -Untuk menghindari mengaktifkan penerusan port jarak jauh, Anda dapat memaksa sambungan maju sebagai gantinya (perhatikan `-L`, bukan` -R`): +Untuk menghindari mengaktifkan penerusan port jarak jauh, Anda dapat memaksa sambungan maju sebagai gantinya (perhatikan `-L`, bukan `-R`): ```bash adb kill-server # matikan server adb lokal di 5037 @@ -579,7 +579,7 @@ Lihat juga [Masalah #14]. Dalam daftar berikut, MOD adalah pengubah pintasan. Secara default, ini (kiri) Alt atau (kiri) Super. -Ini dapat diubah menggunakan `--shortcut-mod`. Kunci yang memungkinkan adalah `lctrl`,`rctrl`, `lalt`,` ralt`, `lsuper` dan` rsuper`. Sebagai contoh: +Ini dapat diubah menggunakan `--shortcut-mod`. Kunci yang memungkinkan adalah `lctrl`, `rctrl`, `lalt`, `ralt`, `lsuper` dan `rsuper`. Sebagai contoh: ```bash # gunakan RCtrl untuk jalan pintas diff --git a/README.it.md b/README.it.md index 52e68ba327..a35c7bbb26 100644 --- a/README.it.md +++ b/README.it.md @@ -1,23 +1,42 @@ -_Apri il [README](README.md) originale e sempre aggiornato._ +_Apri il [README](README.md) originale (in inglese) e sempre aggiornato._ -# scrcpy (v1.19) +scrcpy -Questa applicazione fornisce la visualizzazione e il controllo dei dispositivi Android collegati via USB (o [via TCP/IP][article-tcpip]). Non richiede alcun accesso _root_. +# scrcpy (v1.23) + +_si pronuncia "**scr**een **c**o**py**"_ + +[Leggi in altre lingue](#traduzioni) + +Questa applicazione fornisce la visualizzazione e il controllo di dispositivi Android collegati via USB (o [via TCP/IP](#tcpip-wireless)). Non richiede alcun accesso _root_. Funziona su _GNU/Linux_, _Windows_ e _macOS_. ![screenshot](assets/screenshot-debian-600.jpg) Si concentra su: - - **leggerezza** (nativo, mostra solo lo schermo del dispositivo) - - **prestazioni** (30~60fps) - - **qualità** (1920×1080 o superiore) - - **bassa latenza** ([35~70ms][lowlatency]) - - **tempo di avvio basso** (~ 1secondo per visualizzare la prima immagine) - - **non invadenza** (nulla viene lasciato installato sul dispositivo) + - **leggerezza**: nativo, mostra solo lo schermo del dispositivo + - **prestazioni**: 30~120fps, in funzione del dispositivo + - **qualità**: 1920×1080 o superiore + - **bassa latenza**: [35~70ms][lowlatency] + - **tempo di avvio basso**: ~ 1secondo per visualizzare la prima immagine + - **non invadenza**: nulla rimane installato sul dispositivo + - **vantaggi per l'utente**: nessun account, nessuna pubblicità, non è richiesta alcuna connessione a internet + - **libertà**: software libero e a codice aperto (_free and open source_) [lowlatency]: https://github.com/Genymobile/scrcpy/pull/646 +Le sue caratteristiche includono: + - [registrazione](#registrazione) + - mirroring con [schermo del dispositivo spento](#spegnere-lo-schermo) + - [copia-incolla](#copia-incolla) in entrambe le direzioni + - [qualità configurabile](#configurazione-di-acquisizione) + - schermo del dispositivo [come webcam (V4L2)](#v4l2loopback) (solo per Linux) + - [simulazione della tastiera fisica (HID)](#simulazione-della-tastiera-fisica-HID) + - [simulazione mouse fisico (HID)](#simulazione-del-mouse-fisico-HID) + - [modalità OTG](#otg) + - e altro ancora... + ## Requisiti @@ -49,12 +68,18 @@ Compila dai sorgenti: [BUILD] (in inglese) ([procedimento semplificato][BUILD_si ### Linux -Su Debian (_testing_ e _sid_ per ora) e Ubuntu (20.04): +Su Debian e Ubuntu: ``` apt install scrcpy ``` +Su Arch Linux: + +``` +pacman -S scrcpy +``` + È disponibile anche un pacchetto [Snap]: [`scrcpy`][snap-link]. [snap-link]: https://snapstats.org/snaps/scrcpy @@ -66,10 +91,6 @@ Per Fedora, è disponibile un pacchetto [COPR]: [`scrcpy`][copr-link]. [COPR]: https://fedoraproject.org/wiki/Category:Copr [copr-link]: https://copr.fedorainfracloud.org/coprs/zeno/scrcpy/ -Per Arch Linux, è disponibile un pacchetto [AUR]: [`scrcpy`][aur-link]. - -[AUR]: https://wiki.archlinux.org/index.php/Arch_User_Repository -[aur-link]: https://aur.archlinux.org/packages/scrcpy/ Per Gentoo, è disponibile una [Ebuild]: [`scrcpy/`][ebuild-link]. @@ -142,7 +163,7 @@ Collega un dispositivo Android ed esegui: scrcpy ``` -Scrcpy accetta argomenti da riga di comando, essi sono listati con: +Scrcpy accetta argomenti da riga di comando, elencati con: ```bash scrcpy --help @@ -186,6 +207,14 @@ scrcpy --max-fps 15 Questo è supportato ufficialmente a partire da Android 10, ma potrebbe funzionare in versioni precedenti. +L'attuale frame rate di acquisizione può essere stampato sulla console: + +``` +scrcpy --print-fps +``` + +Può anche essere abilitato o disabilitato in qualsiasi momento con MOD+i. + #### Ritaglio Lo schermo del dispositivo può essere ritagliato per visualizzare solo parte di esso. @@ -258,7 +287,7 @@ I "fotogrammi saltati" sono registrati nonostante non siano mostrati in tempo re #### v4l2loopback -Su Linux è possibile inviare il flusso video ad un dispositivo v4l2 loopback, cosicchè un dispositivo Android possa essere aperto come una webcam da qualsiasi strumento compatibile con v4l2. +Su Linux è possibile inviare il flusso video ad un dispositivo v4l2 loopback, cosicché un dispositivo Android possa essere aperto come una webcam da qualsiasi strumento compatibile con v4l2. Il modulo `v4l2loopback` deve essere installato: @@ -321,42 +350,72 @@ scrcpy --display-buffer=50 # aggiungi 50 ms di buffer per la visualizzazione e per il V4L2 sink: ```bash -scrcpy --v4l2-buffer=500 # aggiungi 50 ms di buffer per il v4l2 sink +scrcpy --v4l2-buffer=500 # aggiungi 500 ms di buffer per il v4l2 sink ``` ### Connessione -#### Wireless +#### TCP/IP (wireless) + +_Scrcpy_ usa `adb` per comunicare col dispositivo e `adb` può [connettersi][connect] a un dispositivo mediante TCP/IP. Il dispositivo deve essere collegato alla stessa rete del computer. +##### Automatico -_Scrcpy_ usa `adb` per comunicare col dispositivo e `adb` può [connettersi][connect] al dispositivo mediante TCP/IP: +Un'opzione `--tcpip` permette di configurare automaticamente la connessione. Ci sono due varianti. -1. Connetti il dispositivo alla stessa rete Wi-Fi del tuo computer. -2. Trova l'indirizzo IP del tuo dispositivo in Impostazioni → Informazioni sul telefono → Stato, oppure eseguendo questo comando: +Se il dispositivo (accessibile a 192.168.1.1 in questo esempio) ascolta già su una porta (tipicamente 5555) per le connessioni adb in entrata, allora esegui: + +```bash +scrcpy --tcpip=192.168.1.1 # la porta predefinita è 5555 +scrcpy --tcpip=192.168.1.1:5555 +``` + +Se la modalità TCP/IP di adb è disabilitata sul dispositivo (o se non si conosce l'indirizzo IP indirizzo), collegare il dispositivo tramite USB, quindi eseguire: + +```bash +scrcpy --tcpip # senza argomenti +``` + +Il comando troverà automaticamente l'indirizzo IP del dispositivo, abiliterà la modalità TCP/IP, quindi connettersi al dispositivo prima di iniziare. + +##### Manuale + +In alternativa, è possibile abilitare la connessione TCP/IP manualmente usando `adb`: + +1. Inserisci il dispositivo in una porta USB del tuo computer. +2. Connetti il dispositivo alla stessa rete Wi-Fi del tuo computer. +3. Ottieni l'indirizzo IP del tuo dispositivo, in Impostazioni → Informazioni sul telefono → Stato, o + eseguendo questo comando: ```bash adb shell ip route | awk '{print $9}' ``` -3. Abilita adb via TCP/IP sul tuo dispositivo: `adb tcpip 5555`. -4. Scollega il tuo dispositivo. -5. Connetti il tuo dispositivo: `adb connect IP_DISPOSITVO:5555` _(rimpiazza `IP_DISPOSITIVO`)_. -6. Esegui `scrcpy` come al solito. +4. Abilita adb via TCP/IP sul tuo dispositivo: `adb tcpip 5555`. +5. Scollega il tuo dispositivo. +6. Connettiti al tuo dispositivo: `adb connect DEVICE_IP:5555` _(sostituisci `DEVICE_IP` +con l'indirizzo IP del dispositivo che hai trovato)_. +7. Esegui `scrcpy` come al solito. + +Da Android 11, una [opzione di debug wireless][adb-wireless] permette di evitare di dover collegare fisicamente il dispositivo direttamente al computer. -Potrebbe essere utile diminuire il bit-rate e la definizione +[adb-wireless]: https://developer.android.com/studio/command-line/adb#connect-to-a-device-over-wi-fi-android-11+ + +Se la connessione cade casualmente, esegui il comando `scrcpy` per riconnetterti. Se il comando dice che non ci sono dispositivi/emulatori trovati, prova ad eseguire `adb connect DEVICE_IP:5555` di nuovo, e poi `scrcpy` come al solito. Se dice ancora che non ne ha trovato nessuno, prova ad eseguire `adb disconnect` e poi esegui di nuovo questi due comandi. + +Potrebbe essere utile diminuire il bit-rate e la definizione: ```bash scrcpy --bit-rate 2M --max-size 800 -scrcpy -b2M -m800 # versione breve +scrcpy -b2M -m800 # versione breve ``` [connect]: https://developer.android.com/studio/command-line/adb.html#wireless - #### Multi dispositivo -Se in `adb devices` sono listati più dispositivi, è necessario specificare il _seriale_: +Se in `adb devices` sono elencati più dispositivi, è necessario specificare il _seriale_: ```bash scrcpy --serial 0123456789abcdef @@ -370,6 +429,18 @@ scrcpy --serial 192.168.0.1:5555 scrcpy -s 192.168.0.1:5555 # versione breve ``` +Se solo un dispositivo è collegato via USB o TCP/IP, è possibile selezionarlo automaticamente: + +```bash +# Select the only device connected via USB +scrcpy -d # like adb -d +scrcpy --select-usb # long version + +# Select the only device connected via TCP/IP +scrcpy -e # like adb -e +scrcpy --select-tcpip # long version +``` + Puoi avviare più istanze di _scrcpy_ per diversi dispositivi. @@ -383,37 +454,77 @@ autoadb scrcpy -s '{}' [AutoAdb]: https://github.com/rom1v/autoadb -#### Tunnel SSH +#### Tunnels + +Per connettersi a un dispositivo remoto, è possibile collegare un client `adb` locale a un server remoto `adb` (purché usino la stessa versione del protocollo _adb_). ). -Per connettersi a un dispositivo remoto è possibile collegare un client `adb` locale ad un server `adb` remoto (assunto che entrambi stiano usando la stessa versione del protocollo _adb_): +##### Server ADB remoto + +Per connettersi a un server ADB remoto, fate ascoltare il server su tutte le interfacce: ```bash -adb kill-server # termina il server adb locale su 5037 -ssh -CN -L5037:localhost:5037 -R27183:localhost:27183 your_remote_computer -# tieni questo aperto +adb kill-server +adb -a nodaemon server start +# tienilo aperto +``` + +**Attenzione: tutte le comunicazioni tra i client e il server ADB non sono criptate.** + +Supponi che questo server sia accessibile a 192.168.1.2. Poi, da un altro terminale, esegui scrcpy: + +```bash +export ADB_SERVER_SOCKET=tcp:192.168.1.2:5037 +scrcpy --tunnel-host=192.168.1.2 +``` + +Per impostazione predefinita, scrcpy utilizza la porta locale utilizzata per il tunnel `adb forward` (tipicamente `27183`, vedi `--port`). È anche possibile forzare una diversa porta del tunnel (può essere utile in situazioni più complesse, quando sono coinvolti più reindirizzamenti): + +``` +scrcpy --tunnel-port=1234 +``` + +##### SSH tunnel + +Per comunicare con un server ADB remoto in modo sicuro, è preferibile utilizzare un tunnel SSH. + +Per prima cosa, assicurati che il server ADB sia in esecuzione sul computer remoto: + +```bash +adb start-server ``` -Da un altro terminale: +Poi, crea un tunnel SSH: ```bash +# local 5038 --> remote 5037 +# local 27183 <-- remote 27183 +ssh -CN -L5038:localhost:5037 -R27183:localhost:27183 your_remote_computer +# keep this open +``` + +Da un altro terminale, esegui scrcpy: + +```bash +export ADB_SERVER_SOCKET=tcp:localhost:5038 scrcpy ``` Per evitare l'abilitazione dell'apertura porte remota potresti invece forzare una "forward connection" (notare il `-L` invece di `-R`) ```bash -adb kill-server # termina il server adb locale su 5037 -ssh -CN -L5037:localhost:5037 -L27183:localhost:27183 your_remote_computer +# local 5038 --> remote 5037 +# local 27183 --> remote 27183 +ssh -CN -L5038:localhost:5037 -L27183:localhost:27183 your_remote_computer # tieni questo aperto ``` -Da un altro terminale: +Da un altro terminale, esegui scrcpy: ```bash +export ADB_SERVER_SOCKET=tcp:localhost:5038 scrcpy --force-adb-forward ``` - Come per le connessioni wireless potrebbe essere utile ridurre la qualità: ``` @@ -551,6 +662,14 @@ scrcpy --turn-screen-off --stay-awake scrcpy -Sw ``` +#### Spegnimento alla chiusura + +Per spegnere lo schermo del dispositivo quando si chiude scrcpy: + +```bash +scrcpy --power-off-on-close +``` + #### Mostrare i tocchi @@ -596,20 +715,22 @@ Qualsiasi scorciatoia Ctrl viene inoltrata al dispositivo. In partico - Ctrl+x taglia - Ctrl+v incolla (dopo la sincronizzazione degli appunti da computer a dispositivo) -Questo solitamente funziona nella maniera più comune. +Questo solitamente funziona come ci si aspetta. Il comportamento reale, però, dipende dall'applicazione attiva. Per esempio _Termux_ invia SIGINT con Ctrl+c, e _K-9 Mail_ compone un nuovo messaggio. Per copiare, tagliare e incollare in questi casi (ma è solo supportato in Android >= 7): - - MOD+c inietta `COPY` - - MOD+x inietta `CUT` - - MOD+v inietta `PASTE` (dopo la sincronizzazione degli appunti da computer a dispositivo) + - MOD+c invia `COPY` + - MOD+x invia `CUT` + - MOD+v invia `PASTE` (dopo la sincronizzazione degli appunti da computer a dispositivo) -In aggiunta, MOD+Shift+v permette l'iniezione del testo degli appunti del computer come una sequenza di eventi pressione dei tasti. Questo è utile quando il componente non accetta l'incollaggio di testo (per esempio in _Termux_), ma questo può rompere il contenuto non ASCII. +In aggiunta, MOD+Shift+v permette l'invio del testo degli appunti del computer come una sequenza di eventi pressione dei tasti. Questo è utile quando il componente non accetta l'incollaggio di testo (per esempio in _Termux_), ma questo può compromettere il contenuto non ASCII. **AVVISO:** Incollare gli appunti del computer nel dispositivo (sia con Ctrl+v che con MOD+v) copia il contenuto negli appunti del dispositivo. Come conseguenza, qualsiasi applicazione Android potrebbe leggere il suo contenuto. Dovresti evitare di incollare contenuti sensibili (come password) in questa maniera. -Alcuni dispositivi non si comportano come aspettato quando si modificano gli appunti del dispositivo a livello di codice. L'opzione `--legacy-paste` è fornita per cambiare il comportamento di Ctrl+v and MOD+v in modo tale che anch'essi iniettino il testo gli appunti del computer come una sequenza di eventi pressione dei tasti (nella stessa maniera di MOD+Shift+v). +Alcuni dispositivi non si comportano come aspettato quando si modificano gli appunti del dispositivo a livello di codice. L'opzione `--legacy-paste` è fornita per cambiare il comportamento di Ctrl+v and MOD+v in modo tale che anch'essi inviino il testo degli appunti del computer come una sequenza di eventi di pressione dei tasti (nella stessa maniera di MOD+Shift+v). + +Per disabilitare la sincronizzazione automatica degli appunti, usa `--no-clipboard-autosync`. #### Pizzica per zoomare (pinch-to-zoom) @@ -617,16 +738,98 @@ Per simulare il "pizzica per zoomare": Ctrl+_click e trascina_. Più precisamente, tieni premuto Ctrl mentre premi il pulsante sinistro. Finchè il pulsante non sarà rilasciato, tutti i movimenti del mouse ridimensioneranno e ruoteranno il contenuto (se supportato dall'applicazione) relativamente al centro dello schermo. -Concretamente scrcpy genera degli eventi di tocco addizionali di un "dito virtuale" nella posizione simmetricamente opposta rispetto al centro dello schermo. +Concretamente, scrcpy genera degli eventi di tocco addizionali di un "dito virtuale" nella posizione simmetricamente opposta rispetto al centro dello schermo. + +#### Simulazione della tastiera fisica (HID) + +Per impostazione predefinita, scrcpy utilizza l'invio dei tasti o del testo di Android: funziona ovunque, ma è limitato all'ASCII. + +In alternativa scrcpy può simulare una tastiera fisica USB su Android per fornire una migliore esperienza di input (utilizzando [USB HID over AOAv2][hid-aoav2]): la tastiera virtuale è disabilitata e funziona per tutti i caratteri e IME. + +[hid-aoav2]: https://source.android.com/devices/accessories/aoa2#hid-support + +Tuttavia, funziona solo se il dispositivo è collegato via USB. + +Nota: su Windows, può funzionare solo in [odalità OTG](#otg), non durante il mirroring (non è possibile aprire un dispositivo USB se è già aperto da un altro processo come il daemon adb). + +Per abilitare questa modalità: + +```bash +scrcpy --hid-keyboard +scrcpy -K # versione breve +``` + +Se fallisce per qualche motivo (per esempio perché il dispositivo non è connesso via USB), ritorna automaticamente alla modalità predefinita (con un log nella console). Questo permette di usare le stesse opzioni della linea di comando quando si è connessi via USB e TCP/IP. + +In questa modalità, gli eventi i pressione originali (scancodes) sono inviati al dispositivo, indipendentemente dalla mappatura dei tasti dell'host. Pertanto, se il layout della tua tastiera non corrisponde, deve essere configurato sul dispositivo Android, in Impostazioni → Sistema → Lingue e input → [Tastiera fisica] (in inglese). + +Questa pagina di impostazioni può essere avviata direttamente: + +```bash +adb shell am start -a android.settings.HARD_KEYBOARD_SETTINGS +``` + +Tuttavia, l'opzione è disponibile solo quando la tastiera HID è abilitata (o quando una tastiera fisica è collegata). + +[Tastiera fisica]: https://github.com/Genymobile/scrcpy/pull/2632#issuecomment-923756915 + +#### Simulazione del mouse fisico (HID) + +In modo simile alla simulazione della tastiera fisica, è possibile simulare un mouse fisico. Allo stesso modo funziona solo se il dispositivo è connesso via USB. + +Per impostazione predefinita, scrcpy utilizza l'invio degli eventi del mouse di Android, utilizzando coordinate assolute. Simulando un mouse fisico, un puntatore del mouse appare sul dispositivo Android e vengono inviati i movimenti relativi del mouse, i click e gli scorrimenti. + +Per abilitare questa modalità: + +```bash +scrcpy --hid-mouse +scrcpy -M # versione breve +``` + +Si potrebbe anche aggiungere `--forward-all-clicks` a [inoltra tutti i pulsanti del mouse][forward_all_clicks]. +[forward_all_clicks]: #click-destro-e-click-centrale -#### Preferenze di iniezione del testo + +Quando questa modalità è attivata, il mouse del computer viene "catturato" (il puntatore del mouse scompare dal computer e appare invece sul dispositivo Android). + +I tasti speciali di cattura, Alt o Super, commutano (disabilitano o abilitano) la cattura del mouse. Usa uno di essi per ridare il controllo del mouse al computer. + + +#### OTG + +È possibile eseguire _scrcpy_ con la sola simulazione della tastiera fisica e del mouse (HID), come se la tastiera e il mouse del computer fossero collegati direttamente al dispositivo tramite un cavo OTG. + +In questa modalità, _adb_ (debug USB) non è necessario e il mirroring è disabilitato. + +Per attivare la modallità OTG: + +```bash +scrcpy --otg +# Passa la seriale se sono disponibili diversi dispositivi USB +scrcpy --otg -s 0123456789abcdef +``` + +È possibile abilitare solo la tastiera HID o il mouse HID: + +```bash +scrcpy --otg --hid-keyboard # solo la tastiera +scrcpy --otg --hid-mouse # solo mouse +scrcpy --otg --hid-keyboard --hid-mouse # tastiera e mouse +# per comodità, abilita entrambi per default +scrcpy --otg # tastiera e mouse +``` + +Come `--hid-keyboard` e `--hid-mouse`, funziona solo se il dispositivo è collegato via USB. + + +#### Preferenze di invio del testo Ci sono due tipi di [eventi][textevents] generati quando si scrive testo: - _eventi di pressione_, segnalano che tasto è stato premuto o rilasciato; - _eventi di testo_, segnalano che del testo è stato inserito. -In maniera predefinita le lettere sono "iniettate" usando gli eventi di pressione, in maniera tale che la tastiera si comporti come aspettato nei giochi (come accade solitamente per i tasti WASD). +In maniera predefinita le lettere sono inviate usando gli eventi di pressione, in maniera tale che la tastiera si comporti come aspettato nei giochi (come accade solitamente per i tasti WASD). Questo, però, può [causare problemi][prefertext]. Se incontri un problema del genere, puoi evitarlo con: @@ -636,13 +839,21 @@ scrcpy --prefer-text (ma questo romperà il normale funzionamento della tastiera nei giochi) +Al contrario, si potrebbe forzare per inviare sempre eventi di pressione grezzi: + +```bash +scrcpy --raw-key-events +``` + +Queste opzioni non hanno effetto sulla tastiera HID (tutti gli eventi di pressione sono inviati come scancodes in questa modalità). + [textevents]: https://blog.rom1v.com/2018/03/introducing-scrcpy/#handle-text-input [prefertext]: https://github.com/Genymobile/scrcpy/issues/650#issuecomment-512945343 #### Ripetizione di tasti -In maniera predefinita tenere premuto un tasto genera una ripetizione degli eventi di pressione di tale tasto. Questo può creare problemi di performance in alcuni giochi, dove questi eventi sono inutilizzati. +In maniera predefinita, tenere premuto un tasto genera una ripetizione degli eventi di pressione di tale tasto. Questo può creare problemi di performance in alcuni giochi, dove questi eventi sono inutilizzati. Per prevenire l'inoltro ripetuto degli eventi di pressione: @@ -650,9 +861,12 @@ Per prevenire l'inoltro ripetuto degli eventi di pressione: scrcpy --no-key-repeat ``` +Questa opzione non ha effetto sulla tastiera HID (la ripetizione dei tasti è gestita da Android direttamente in questa modalità). + + #### Click destro e click centrale -In maniera predefinita, click destro aziona BACK (indietro) e il click centrale aziona HOME. Per disabilitare queste scorciatoie e, invece, inviare i click al dispositivo: +In maniera predefinita, click destro aziona BACK (indietro) o POWER on (accensione) e il click centrale aziona HOME. Per disabilitare queste scorciatoie e, invece, inviare i click al dispositivo: ```bash scrcpy --forward-all-clicks @@ -705,7 +919,7 @@ scrcpy --shortcut-mod=rctrl scrcpy --shortcut-mod=lctrl+lalt,lsuper ``` -_[Super] è il pulsante Windows o Cmd._ +_[Super] è solitamente il pulsante Windows o Cmd._ [Super]: https://it.wikipedia.org/wiki/Tasto_Windows @@ -720,7 +934,7 @@ _[Super] è il pulsante Windows o Cmd._ | Premi il tasto `HOME` | MOD+h \| _Click centrale_ | Premi il tasto `BACK` | MOD+b \| _Click destro²_ | Premi il tasto `APP_SWITCH` | MOD+s \| _4° click³_ - | Premi il tasto `MENU` (sblocca lo schermo) | MOD+m + | Premi il tasto `MENU` (sblocca lo schermo)⁴ | MOD+m | Premi il tasto `VOLUME_UP` | MOD+ _(su)_ | Premi il tasto `VOLUME_DOWN` | MOD+ _(giù)_ | Premi il tasto `POWER` | MOD+p @@ -731,17 +945,20 @@ _[Super] è il pulsante Windows o Cmd._ | Espandi il pannello delle notifiche | MOD+n \| _5° click³_ | Espandi il pannello delle impostazioni | MOD+n+n \| _Doppio 5° click³_ | Chiudi pannelli | MOD+Shift+n - | Copia negli appunti⁴ | MOD+c - | Taglia negli appunti⁴ | MOD+x - | Sincronizza gli appunti e incolla⁴ | MOD+v - | Inietta il testo degli appunti del computer | MOD+Shift+v + | Copia negli appunti⁵ | MOD+c + | Taglia negli appunti⁵ | MOD+x + | Sincronizza gli appunti e incolla⁵ | MOD+v + | Invia il testo degli appunti del computer | MOD+Shift+v | Abilita/Disabilita il contatore FPS (su stdout) | MOD+i | Pizzica per zoomare | Ctrl+_click e trascina_ + | Trascina file APK | Installa APK dal computer + | Trascina file non-APK | [Trasferisci file verso il dispositivo](#push-file-to-device) _¹Doppio click sui bordi neri per rimuoverli._ _²Il tasto destro accende lo schermo se era spento, preme BACK in caso contrario._ _³4° e 5° pulsante del mouse, se il tuo mouse ne dispone._ -_⁴Solo in Android >= 7._ +_⁴Per le app native react in sviluppo, `MENU` attiva il menu di sviluppo._ +_⁵Solo in Android >= 7._ Le scorciatoie con pulsanti ripetuti sono eseguite rilasciando e premendo il pulsante una seconda volta. Per esempio, per eseguire "Espandi il pannello delle impostazioni": @@ -811,3 +1028,14 @@ Leggi la [pagina per sviluppatori]. [article-intro]: https://blog.rom1v.com/2018/03/introducing-scrcpy/ [article-tcpip]: https://www.genymotion.com/blog/open-source-project-scrcpy-now-works-wirelessly/ + +## Contatti + +Se incontri un bug, per favore leggi prima le [FAQ](FAQ.it.md), poi apri una [issue]. + +[issue]: https://github.com/Genymobile/scrcpy/issues + +Per domande generali o discussioni, puoi anche usare: + + - Reddit: [`r/scrcpy`](https://www.reddit.com/r/scrcpy) + - Twitter: [`@scrcpy_app`](https://twitter.com/scrcpy_app) diff --git a/README.md b/README.md index c89b0c8d29..20ad0f9c46 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# scrcpy (v1.23) +# scrcpy (v1.24) scrcpy @@ -7,7 +7,7 @@ _pronounced "**scr**een **c**o**py**"_ [Read in another language](#translations) This application provides display and control of Android devices connected via -USB (or [over TCP/IP](#tcpip-wireless)). It does not require any _root_ access. +USB or [over TCP/IP](#tcpip-wireless). It does not require any _root_ access. It works on _GNU/Linux_, _Windows_ and _macOS_. ![screenshot](assets/screenshot-debian-600.jpg) @@ -19,7 +19,7 @@ It focuses on: - **quality**: 1920×1080 or above - **low latency**: [35~70ms][lowlatency] - **low startup time**: ~1 second to display the first image - - **non-intrusiveness**: nothing is left installed on the device + - **non-intrusiveness**: nothing is left installed on the Android device - **user benefits**: no account, no ads, no internet required - **freedom**: free and open source software @@ -27,10 +27,10 @@ It focuses on: Its features include: - [recording](#recording) - - mirroring with [device screen off](#turn-screen-off) + - mirroring with [Android device screen off](#turn-screen-off) - [copy-paste](#copy-paste) in both directions - [configurable quality](#capture-configuration) - - device screen [as a webcam (V4L2)](#v4l2loopback) (Linux-only) + - Android device [as a webcam (V4L2)](#v4l2loopback) (Linux-only) - [physical keyboard simulation (HID)](#physical-keyboard-simulation-hid) - [physical mouse simulation (HID)](#physical-mouse-simulation-hid) - [OTG mode](#otg) @@ -40,12 +40,12 @@ Its features include: The Android device requires at least API 21 (Android 5.0). -Make sure you [enabled adb debugging][enable-adb] on your device(s). +Make sure you [enable adb debugging][enable-adb] on your device(s). [enable-adb]: https://developer.android.com/studio/command-line/adb.html#Enabling On some devices, you also need to enable [an additional option][control] to -control it using keyboard and mouse. +control it using a keyboard and mouse. [control]: https://github.com/Genymobile/scrcpy/issues/70#issuecomment-373286323 @@ -97,19 +97,19 @@ For Gentoo, an [Ebuild] is available: [`scrcpy/`][ebuild-link]. [Ebuild]: https://wiki.gentoo.org/wiki/Ebuild [ebuild-link]: https://github.com/maggu2810/maggu2810-overlay/tree/master/app-mobilephone/scrcpy -You could also [build the app manually][BUILD] ([simplified +You can also [build the app manually][BUILD] ([simplified process][BUILD_simple]). ### Windows -For Windows, for simplicity, a prebuilt archive with all the dependencies -(including `adb`) is available: +For Windows, a prebuilt archive with all the dependencies (including `adb`) is +available: - - [`scrcpy-win64-v1.23.zip`][direct-win64] - _(SHA-256: d2f601b1d0157faf65153d8a093d827fd65aec5d5842d677ac86fb2b5b7704cc)_ + - [`scrcpy-win64-v1.24.zip`][direct-win64] + SHA-256: `6ccb64cba0a3e75715e85a188daeb4f306a1985f8ce123eba92ba74fc9b27367` -[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v1.23/scrcpy-win64-v1.23.zip +[direct-win64]: https://github.com/Genymobile/scrcpy/releases/download/v1.24/scrcpy-win64-v1.24.zip It is also available in [Chocolatey]: @@ -148,7 +148,7 @@ You need `adb`, accessible from your `PATH`. If you don't have it yet: brew install android-platform-tools ``` -It's also available in [MacPorts], which sets up adb for you: +It's also available in [MacPorts], which sets up `adb` for you: ```bash sudo port install scrcpy @@ -162,7 +162,7 @@ You can also [build the app manually][BUILD]. ## Run -Plug an Android device, and execute: +Plug an Android device into your computer, and execute: ```bash scrcpy @@ -180,7 +180,7 @@ scrcpy --help #### Reduce size -Sometimes, it is useful to mirror an Android device at a lower definition to +Sometimes, it is useful to mirror an Android device at a lower resolution to increase performance. To limit both the width and height to some value (e.g. 1024): @@ -190,8 +190,8 @@ scrcpy --max-size 1024 scrcpy -m 1024 # short version ``` -The other dimension is computed to that the device aspect ratio is preserved. -That way, a device in 1920×1080 will be mirrored at 1024×576. +The other dimension is computed so that the Android device aspect ratio is +preserved. That way, a device in 1920×1080 will be mirrored at 1024×576. #### Change bit-rate @@ -226,7 +226,7 @@ It may also be enabled or disabled at any time with MOD+i. The device screen may be cropped to mirror only part of the screen. -This is useful for example to mirror only one eye of the Oculus Go: +This is useful, for example, to mirror only one eye of the Oculus Go: ```bash scrcpy --crop 1224:1440:0:0 # 1224x1440 at offset (0,0) @@ -237,7 +237,6 @@ If `--max-size` is also specified, resizing is applied after cropping. #### Lock video orientation - To lock the orientation of the mirroring: ```bash @@ -262,7 +261,7 @@ crash. It is possible to select a different encoder: scrcpy --encoder OMX.qcom.video.encoder.avc ``` -To list the available encoders, you could pass an invalid encoder name, the +To list the available encoders, you can pass an invalid encoder name; the error will give the available encoders: ```bash @@ -326,7 +325,7 @@ v4l2-ctl --list-devices ls /dev/video* ``` -To start scrcpy using a v4l2 sink: +To start `scrcpy` using a v4l2 sink: ```bash scrcpy --v4l2-sink=/dev/videoN @@ -334,7 +333,7 @@ scrcpy --v4l2-sink=/dev/videoN --no-display # disable mirroring window scrcpy --v4l2-sink=/dev/videoN -N # short version ``` -(replace `N` by the device ID, check with `ls /dev/video*`) +(replace `N` with the device ID, check with `ls /dev/video*`) Once enabled, you can open your video stream with a v4l2-capable tool: @@ -350,7 +349,7 @@ For example, you could capture the video within [OBS]. #### Buffering -It is possible to add buffering. This increases latency but reduces jitter (see +It is possible to add buffering. This increases latency, but reduces jitter (see [#2464]). [#2464]: https://github.com/Genymobile/scrcpy/issues/2464 @@ -382,14 +381,14 @@ An option `--tcpip` allows to configure the connection automatically. There are two variants. If the device (accessible at 192.168.1.1 in this example) already listens on a -port (typically 5555) for incoming adb connections, then run: +port (typically 5555) for incoming _adb_ connections, then run: ```bash scrcpy --tcpip=192.168.1.1 # default port is 5555 scrcpy --tcpip=192.168.1.1:5555 ``` -If adb TCP/IP mode is disabled on the device (or if you don't know the IP +If _adb_ TCP/IP mode is disabled on the device (or if you don't know the IP address), connect the device over USB, then run: ```bash @@ -413,7 +412,7 @@ Alternatively, it is possible to enable the TCP/IP connection manually using adb shell ip route | awk '{print $9}' ``` -4. Enable adb over TCP/IP on your device: `adb tcpip 5555`. +4. Enable `adb` over TCP/IP on your device: `adb tcpip 5555`. 5. Unplug your device. 6. Connect to your device: `adb connect DEVICE_IP:5555` _(replace `DEVICE_IP` with the device IP address you found)_. @@ -427,9 +426,9 @@ having to physically connect your device directly to your computer. If the connection randomly drops, run your `scrcpy` command to reconnect. If it says there are no devices/emulators found, try running `adb connect DEVICE_IP:5555` again, and then `scrcpy` as usual. If it still says there are -none found, try running `adb disconnect` and then run those two commands again. +none found, try running `adb disconnect`, and then run those two commands again. -It may be useful to decrease the bit-rate and the definition: +It may be useful to decrease the bit-rate and the resolution: ```bash scrcpy --bit-rate 2M --max-size 800 @@ -448,6 +447,9 @@ scrcpy --serial 0123456789abcdef scrcpy -s 0123456789abcdef # short version ``` +The serial may also be provided via the environment variable `ANDROID_SERIAL` +(also used by `adb`). + If the device is connected over TCP/IP: ```bash @@ -488,7 +490,7 @@ protocol). ##### Remote ADB server -To connect to a remote ADB server, make the server listen on all interfaces: +To connect to a remote _adb server_, make the server listen on all interfaces: ```bash adb kill-server @@ -496,17 +498,18 @@ adb -a nodaemon server start # keep this open ``` -**Warning: all communications between clients and ADB server are unencrypted.** +**Warning: all communications between clients and the _adb server_ are +unencrypted.** Suppose that this server is accessible at 192.168.1.2. Then, from another -terminal, run scrcpy: +terminal, run `scrcpy`: ```bash export ADB_SERVER_SOCKET=tcp:192.168.1.2:5037 scrcpy --tunnel-host=192.168.1.2 ``` -By default, scrcpy uses the local port used for `adb forward` tunnel +By default, `scrcpy` uses the local port used for `adb forward` tunnel establishment (typically `27183`, see `--port`). It is also possible to force a different tunnel port (it may be useful in more complex situations, when more redirections are involved): @@ -518,16 +521,16 @@ scrcpy --tunnel-port=1234 ##### SSH tunnel -To communicate with a remote ADB server securely, it is preferable to use a SSH -tunnel. +To communicate with a remote _adb server_ securely, it is preferable to use an +SSH tunnel. -First, make sure the ADB server is running on the remote computer: +First, make sure the _adb server_ is running on the remote computer: ```bash adb start-server ``` -Then, establish a SSH tunnel: +Then, establish an SSH tunnel: ```bash # local 5038 --> remote 5037 @@ -536,7 +539,7 @@ ssh -CN -L5038:localhost:5037 -R27183:localhost:27183 your_remote_computer # keep this open ``` -From another terminal, run scrcpy: +From another terminal, run `scrcpy`: ```bash export ADB_SERVER_SOCKET=tcp:localhost:5038 @@ -553,7 +556,7 @@ ssh -CN -L5038:localhost:5037 -L27183:localhost:27183 your_remote_computer # keep this open ``` -From another terminal, run scrcpy: +From another terminal, run `scrcpy`: ```bash export ADB_SERVER_SOCKET=tcp:localhost:5038 @@ -595,7 +598,7 @@ scrcpy --window-borderless #### Always on top -To keep the scrcpy window always on top: +To keep the _scrcpy_ window always on top: ```bash scrcpy --always-on-top @@ -620,7 +623,7 @@ The window may be rotated: scrcpy --rotation 1 ``` -Possibles values are: +Possible values: - `0`: no rotation - `1`: 90 degrees counterclockwise - `2`: 180 degrees @@ -669,19 +672,19 @@ adb shell dumpsys display # search "mDisplayId=" in the output ``` The secondary display may only be controlled if the device runs at least Android -10 (otherwise it is mirrored in read-only). +10 (otherwise it is mirrored as read-only). #### Stay awake -To prevent the device to sleep after some delay when the device is plugged in: +To prevent the device from sleeping after a delay when the device is plugged in: ```bash scrcpy --stay-awake scrcpy -w ``` -The initial state is restored when scrcpy is closed. +The initial state is restored when _scrcpy_ is closed. #### Turn screen off @@ -699,9 +702,10 @@ Or by pressing MOD+o at any time. To turn it back on, press MOD+Shift+o. On Android, the `POWER` button always turns the screen on. For convenience, if -`POWER` is sent via scrcpy (via right-click or MOD+p), it -will force to turn the screen off after a small delay (on a best effort basis). -The physical `POWER` button will still cause the screen to be turned on. +`POWER` is sent via _scrcpy_ (via right-click or MOD+p), +it will force to turn the screen off after a small delay (on a best effort +basis). The physical `POWER` button will still cause the screen to be turned +on. It can also be useful to prevent the device from sleeping: @@ -712,12 +716,22 @@ scrcpy -Sw #### Power off on close -To turn the device screen off when closing scrcpy: +To turn the device screen off when closing _scrcpy_: ```bash scrcpy --power-off-on-close ``` +#### Power on on start + +By default, on start, the device is powered on. + +To prevent this behavior: + +```bash +scrcpy --no-power-on +``` + #### Show touches @@ -734,12 +748,13 @@ scrcpy --show-touches scrcpy -t ``` -Note that it only shows _physical_ touches (with the finger on the device). +Note that it only shows _physical_ touches (by a finger on the device). #### Disable screensaver -By default, scrcpy does not prevent the screensaver to run on the computer. +By default, _scrcpy_ does not prevent the screensaver from running on the +computer. To disable it: @@ -781,18 +796,18 @@ To copy, cut and paste in such cases (but only supported on Android >= 7): - MOD+v injects `PASTE` (after computer-to-device clipboard synchronization) -In addition, MOD+Shift+v allows to inject the -computer clipboard text as a sequence of key events. This is useful when the -component does not accept text pasting (for example in _Termux_), but it can -break non-ASCII content. +In addition, MOD+Shift+v injects the computer +clipboard text as a sequence of key events. This is useful when the component +does not accept text pasting (for example in _Termux_), but it can break +non-ASCII content. **WARNING:** Pasting the computer clipboard to the device (either via Ctrl+v or MOD+v) copies the content -into the device clipboard. As a consequence, any Android application could read -its content. You should avoid to paste sensitive content (like passwords) that +into the Android clipboard. As a consequence, any Android application could read +its content. You should avoid pasting sensitive content (like passwords) that way. -Some devices do not behave as expected when setting the device clipboard +Some Android devices do not behave as expected when setting the device clipboard programmatically. An option `--legacy-paste` is provided to change the behavior of Ctrl+v and MOD+v so that they also inject the computer clipboard text as a sequence of key events (the same @@ -805,29 +820,29 @@ To disable automatic clipboard synchronization, use To simulate "pinch-to-zoom": Ctrl+_click-and-move_. -More precisely, hold Ctrl while pressing the left-click button. Until -the left-click button is released, all mouse movements scale and rotate the -content (if supported by the app) relative to the center of the screen. +More precisely, hold down Ctrl while pressing the left-click button. +Until the left-click button is released, all mouse movements scale and rotate +the content (if supported by the app) relative to the center of the screen. -Concretely, scrcpy generates additional touch events from a "virtual finger" at -a location inverted through the center of the screen. +Technically, _scrcpy_ generates additional touch events from a "virtual finger" +at a location inverted through the center of the screen. #### Physical keyboard simulation (HID) -By default, scrcpy uses Android key or text injection: it works everywhere, but -is limited to ASCII. +By default, _scrcpy_ uses Android key or text injection: it works everywhere, +but is limited to ASCII. -Alternatively, scrcpy can simulate a physical USB keyboard on Android to provide -a better input experience (using [USB HID over AOAv2][hid-aoav2]): the virtual -keyboard is disabled and it works for all characters and IME. +Alternatively, `scrcpy` can simulate a physical USB keyboard on Android to +provide a better input experience (using [USB HID over AOAv2][hid-aoav2]): the +virtual keyboard is disabled and it works for all characters and IME. [hid-aoav2]: https://source.android.com/devices/accessories/aoa2#hid-support -However, it only works if the device is connected by USB. +However, it only works if the device is connected via USB. Note: On Windows, it may only work in [OTG mode](#otg), not while mirroring (it is not possible to open a USB device if it is already open by another process -like the adb daemon). +like the _adb daemon_). To enable this mode: @@ -838,7 +853,7 @@ scrcpy -K # short version If it fails for some reason (for example because the device is not connected via USB), it automatically fallbacks to the default mode (with a log in the -console). This allows to use the same command line options when connected over +console). This allows using the same command line options when connected over USB and TCP/IP. In this mode, raw key events (scancodes) are sent to the device, independently @@ -862,7 +877,7 @@ a physical keyboard is connected). Similarly to the physical keyboard simulation, it is possible to simulate a physical mouse. Likewise, it only works if the device is connected by USB. -By default, scrcpy uses Android mouse events injection, using absolute +By default, _scrcpy_ uses Android mouse events injection with absolute coordinates. By simulating a physical mouse, a mouse pointer appears on the Android device, and relative mouse motion, clicks and scrolls are injected. @@ -873,7 +888,7 @@ scrcpy --hid-mouse scrcpy -M # short version ``` -You could also add `--forward-all-clicks` to [forward all mouse +You can also add `--forward-all-clicks` to [forward all mouse buttons][forward_all_clicks]. [forward_all_clicks]: #right-click-and-middle-click @@ -892,7 +907,7 @@ It is possible to run _scrcpy_ with only physical keyboard and mouse simulation (HID), as if the computer keyboard and mouse were plugged directly to the device via an OTG cable. -In this mode, _adb_ (USB debugging) is not necessary, and mirroring is disabled. +In this mode, `adb` (USB debugging) is not necessary, and mirroring is disabled. To enable OTG mode: @@ -918,7 +933,7 @@ connected by USB. #### Text injection preference -There are two kinds of [events][textevents] generated when typing text: +Two kinds of [events][textevents] are generated when typing text: - _key events_, signaling that a key is pressed or released; - _text events_, signaling that a text has been entered. @@ -1062,7 +1077,7 @@ _³4th and 5th mouse buttons, if your mouse has them._ _⁴For react-native apps in development, `MENU` triggers development menu._ _⁵Only on Android >= 7._ -Shortcuts with repeated keys are executted by releasing and pressing the key a +Shortcuts with repeated keys are executed by releasing and pressing the key a second time. For example, to execute "Expand settings panel": 1. Press and keep pressing MOD. @@ -1075,7 +1090,7 @@ handled by the active application. ## Custom paths -To use a specific _adb_ binary, configure its path in the environment variable +To use a specific `adb` binary, configure its path in the environment variable `ADB`: ```bash @@ -1088,7 +1103,7 @@ To override the path of the `scrcpy-server` file, configure its path in To override the icon, configure its path in `SCRCPY_ICON_PATH`. -## Why _scrcpy_? +## Why the name _scrcpy_? A colleague challenged me to find a name as unpronounceable as [gnirehtet]. @@ -1105,7 +1120,7 @@ See [BUILD]. ## Common issues -See the [FAQ].md). +See the [FAQ]. [FAQ]: FAQ.md @@ -1148,7 +1163,7 @@ If you encounter a bug, please read the [FAQ] first, then open an [issue]. [issue]: https://github.com/Genymobile/scrcpy/issues -For general questions or discussions, you could also use: +For general questions or discussions, you can also use: - Reddit: [`r/scrcpy`](https://www.reddit.com/r/scrcpy) - Twitter: [`@scrcpy_app`](https://twitter.com/scrcpy_app) @@ -1159,7 +1174,7 @@ This README is available in other languages: - [Deutsch (German, `de`) - v1.22](README.de.md) - [Indonesian (Indonesia, `id`) - v1.16](README.id.md) -- [Italiano (Italiano, `it`) - v1.19](README.it.md) +- [Italiano (Italiano, `it`) - v1.23](README.it.md) - [日本語 (Japanese, `jp`) - v1.19](README.jp.md) - [한국어 (Korean, `ko`) - v1.11](README.ko.md) - [Português Brasileiro (Brazilian Portuguese, `pt-BR`) - v1.19](README.pt-br.md) diff --git a/README.zh-Hans.md b/README.zh-Hans.md index caf964b3b3..ac0713a69d 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -704,11 +704,11 @@ scrcpy --disable-screensaver #### 双指缩放 -模拟“双指缩放”:Ctrl+_按住并移动鼠标_。 +模拟“双指缩放”:Ctrl+_按下并拖动鼠标_。 -更准确的说,在按住鼠标左键时按住 Ctrl。直到松开鼠标左键,所有鼠标移动将以屏幕中心为原点,缩放或旋转内容 (如果应用支持)。 +在按住 Ctrl 时按下鼠标左键,直到松开鼠标左键前,移动鼠标会使屏幕内容相对于屏幕中心进行缩放或旋转 (如果应用支持)。 -实际上,_scrcpy_ 会在关于屏幕中心对称的位置上用“虚拟手指”发出触摸事件。 +具体来说,_scrcpy_ 会在鼠标位置,以及鼠标以屏幕中心镜像的位置分别生成触摸事件。 #### 物理键盘模拟 (HID) diff --git a/app/data/bash-completion/scrcpy b/app/data/bash-completion/scrcpy index 464bc532f4..3e75cbb018 100644 --- a/app/data/bash-completion/scrcpy +++ b/app/data/bash-completion/scrcpy @@ -29,6 +29,7 @@ _scrcpy() { -N --no-display --no-key-repeat --no-mipmaps + --no-power-on --otg -p --port= --power-off-on-close diff --git a/app/data/zsh-completion/_scrcpy b/app/data/zsh-completion/_scrcpy index 77e6027a40..097c80d68b 100644 --- a/app/data/zsh-completion/_scrcpy +++ b/app/data/zsh-completion/_scrcpy @@ -35,6 +35,7 @@ arguments=( {-N,--no-display}'[Do not display device \(during screen recording or when V4L2 sink is enabled\)]' '--no-key-repeat[Do not forward repeated key events when a key is held down]' '--no-mipmaps[Disable the generation of mipmaps]' + '--no-power-on[Do not power on the device on start]' '--otg[Run in OTG mode \(simulating physical keyboard and mouse\)]' {-p,--port=}'[\[port\[\:port\]\] Set the TCP port \(range\) used by the client to listen]' '--power-off-on-close[Turn the device screen off when closing scrcpy]' diff --git a/app/meson.build b/app/meson.build index e34b189354..f5d76c61dd 100644 --- a/app/meson.build +++ b/app/meson.build @@ -143,12 +143,12 @@ else prebuilt_libusb = meson.get_cross_property('prebuilt_libusb') prebuilt_libusb_root = meson.get_cross_property('prebuilt_libusb_root') - libusb_bin_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_libusb + '/dll' + libusb_bin_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_libusb libusb_include_dir = 'prebuilt-deps/data/' + prebuilt_libusb_root + '/include' libusb = declare_dependency( dependencies: [ - cc.find_library('libusb-1.0', dirs: libusb_bin_dir), + cc.find_library('msys-usb-1.0', dirs: libusb_bin_dir), ], include_directories: include_directories(libusb_include_dir) ) diff --git a/app/prebuilt-deps/prepare-adb.sh b/app/prebuilt-deps/prepare-adb.sh index 2e7997e138..6a1f489612 100755 --- a/app/prebuilt-deps/prepare-adb.sh +++ b/app/prebuilt-deps/prepare-adb.sh @@ -6,10 +6,10 @@ cd "$DIR" mkdir -p "$PREBUILT_DATA_DIR" cd "$PREBUILT_DATA_DIR" -DEP_DIR=platform-tools-31.0.3 +DEP_DIR=platform-tools-33.0.1 -FILENAME=platform-tools_r31.0.3-windows.zip -SHA256SUM=0f4b8fdd26af2c3733539d6eebb3c2ed499ea1d4bb1f4e0ecc2d6016961a6e24 +FILENAME=platform-tools_r33.0.1-windows.zip +SHA256SUM=c1f02d42ea24ef4ff2a405ae7370e764ef4546f9b3e4520f5571a00ed5012c42 if [[ -d "$DEP_DIR" ]] then diff --git a/app/prebuilt-deps/prepare-ffmpeg-win64.sh b/app/prebuilt-deps/prepare-ffmpeg-win64.sh index a62eb26165..8e6c2440e1 100755 --- a/app/prebuilt-deps/prepare-ffmpeg-win64.sh +++ b/app/prebuilt-deps/prepare-ffmpeg-win64.sh @@ -6,10 +6,11 @@ cd "$DIR" mkdir -p "$PREBUILT_DATA_DIR" cd "$PREBUILT_DATA_DIR" -DEP_DIR=ffmpeg-win64-5.0 +VERSION=5.0.1 +DEP_DIR=ffmpeg-win64-$VERSION -FILENAME=ffmpeg-5.0-full_build-shared.7z -SHA256SUM=e5900f6cecd4c438d398bd2fc308736c10b857cd8dd61c11bcfb05bff5d1211a +FILENAME=ffmpeg-$VERSION-full_build-shared.7z +SHA256SUM=ded28435b6f04b74f5ef5a6a13761233bce9e8e9f8ecb0eabe936fd36a778b0c if [[ -d "$DEP_DIR" ]] then @@ -17,13 +18,13 @@ then exit 0 fi -get_file "https://github.com/GyanD/codexffmpeg/releases/download/5.0/$FILENAME" \ +get_file "https://github.com/GyanD/codexffmpeg/releases/download/$VERSION/$FILENAME" \ "$FILENAME" "$SHA256SUM" mkdir "$DEP_DIR" cd "$DEP_DIR" -ZIP_PREFIX=ffmpeg-5.0-full_build-shared +ZIP_PREFIX=ffmpeg-$VERSION-full_build-shared 7z x "../$FILENAME" \ "$ZIP_PREFIX"/bin/avutil-57.dll \ "$ZIP_PREFIX"/bin/avcodec-59.dll \ diff --git a/app/prebuilt-deps/prepare-libusb.sh b/app/prebuilt-deps/prepare-libusb.sh index 54ead536ef..a0c3721d84 100755 --- a/app/prebuilt-deps/prepare-libusb.sh +++ b/app/prebuilt-deps/prepare-libusb.sh @@ -6,10 +6,10 @@ cd "$DIR" mkdir -p "$PREBUILT_DATA_DIR" cd "$PREBUILT_DATA_DIR" -DEP_DIR=libusb-1.0.25 +DEP_DIR=libusb-1.0.26 -FILENAME=libusb-1.0.25.7z -SHA256SUM=3d1c98416f454026034b2b5d67f8a294053898cb70a8b489874e75b136c6674d +FILENAME=libusb-1.0.26-binaries.7z +SHA256SUM=9c242696342dbde9cdc47239391f71833939bf9f7aa2bbb28cdaabe890465ec5 if [[ -d "$DEP_DIR" ]] then @@ -17,12 +17,18 @@ then exit 0 fi -get_file "https://github.com/libusb/libusb/releases/download/v1.0.25/$FILENAME" "$FILENAME" "$SHA256SUM" +get_file "https://github.com/libusb/libusb/releases/download/v1.0.26/$FILENAME" "$FILENAME" "$SHA256SUM" mkdir "$DEP_DIR" cd "$DEP_DIR" +# include/ is the same in all folders of the archive 7z x "../$FILENAME" \ - MinGW32/dll/libusb-1.0.dll \ - MinGW64/dll/libusb-1.0.dll \ - include / + libusb-1.0.26-binaries/libusb-MinGW-Win32/bin/msys-usb-1.0.dll \ + libusb-1.0.26-binaries/libusb-MinGW-x64/bin/msys-usb-1.0.dll \ + libusb-1.0.26-binaries/libusb-MinGW-x64/include/ + +mv libusb-1.0.26-binaries/libusb-MinGW-Win32/bin MinGW-Win32 +mv libusb-1.0.26-binaries/libusb-MinGW-x64/bin MinGW-x64 +mv libusb-1.0.26-binaries/libusb-MinGW-x64/include . +rm -rf libusb-1.0.26-binaries diff --git a/app/prebuilt-deps/prepare-sdl.sh b/app/prebuilt-deps/prepare-sdl.sh index c414c85433..0b41fe5c61 100755 --- a/app/prebuilt-deps/prepare-sdl.sh +++ b/app/prebuilt-deps/prepare-sdl.sh @@ -6,10 +6,10 @@ cd "$DIR" mkdir -p "$PREBUILT_DATA_DIR" cd "$PREBUILT_DATA_DIR" -DEP_DIR=SDL2-2.0.20 +DEP_DIR=SDL2-2.0.22 -FILENAME=SDL2-devel-2.0.20-mingw.tar.gz -SHA256SUM=38094d82a857d6c62352e5c5cdec74948c5b4d25c59cbd298d6d233568976bd1 +FILENAME=SDL2-devel-2.0.22-mingw.tar.gz +SHA256SUM=0e91e35973366aa1e6f81ee368924d9b4f93f9da4d2f2a89ec80b06eadcf23d1 if [[ -d "$DEP_DIR" ]] then diff --git a/app/scrcpy-windows.rc b/app/scrcpy-windows.rc index 41101e705d..6c731003b4 100644 --- a/app/scrcpy-windows.rc +++ b/app/scrcpy-windows.rc @@ -13,7 +13,7 @@ BEGIN VALUE "LegalCopyright", "Romain Vimont, Genymobile" VALUE "OriginalFilename", "scrcpy.exe" VALUE "ProductName", "scrcpy" - VALUE "ProductVersion", "1.23" + VALUE "ProductVersion", "1.24" END END BLOCK "VarFileInfo" diff --git a/app/scrcpy.1 b/app/scrcpy.1 index f9d4ba2471..7cb893b7f0 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -180,6 +180,10 @@ Do not forward repeated key events when a key is held down. .B \-\-no\-mipmaps If the renderer is OpenGL 3.0+ or OpenGL ES 2.0+, then mipmaps are automatically generated to improve downscaling quality. This option disables the generation of mipmaps. +.TP +.B \-\-no\-power\-on +Do not power on the device on start. + .TP .B \-\-otg Run in OTG mode: simulate physical keyboard and mouse, as if the computer keyboard and mouse were plugged directly to the device via an OTG cable. @@ -355,6 +359,12 @@ Set the initial window height. Default is 0 (automatic). +.SH EXIT STATUS +.B scrcpy +will exit with code 0 on normal program termination. If an initial +connection cannot be established, the exit code 1 will be returned. If the +device disconnects while a session is active, exit code 2 will be returned. + .SH SHORTCUTS In the following list, MOD is the shortcut modifier. By default, it's (left) @@ -471,6 +481,10 @@ Push file to device (see \fB\-\-push\-target\fR) .B ADB Path to adb. +.TP +.B ANDROID_SERIAL +Device serial to use if no selector (-s, -d, -e or --tcpip=) is specified. + .TP .B SCRCPY_ICON_PATH Path to the program icon. diff --git a/app/src/adb/adb.c b/app/src/adb/adb.c index 06090b46b2..344f7fcc27 100644 --- a/app/src/adb/adb.c +++ b/app/src/adb/adb.c @@ -473,9 +473,12 @@ sc_adb_accept_device(const struct sc_adb_device *device, } return !strcmp(selector->serial, device->serial); case SC_ADB_DEVICE_SELECT_USB: - return !sc_adb_is_serial_tcpip(device->serial); + return sc_adb_device_get_type(device->serial) == + SC_ADB_DEVICE_TYPE_USB; case SC_ADB_DEVICE_SELECT_TCPIP: - return sc_adb_is_serial_tcpip(device->serial); + // Both emulators and TCP/IP devices are selected via -e + return sc_adb_device_get_type(device->serial) != + SC_ADB_DEVICE_TYPE_USB; default: assert(!"Missing SC_ADB_DEVICE_SELECT_* handling"); break; @@ -509,8 +512,10 @@ sc_adb_devices_log(enum sc_log_level level, struct sc_adb_device *devices, for (size_t i = 0; i < count; ++i) { struct sc_adb_device *d = &devices[i]; const char *selection = d->selected ? "-->" : " "; - const char *type = sc_adb_is_serial_tcpip(d->serial) ? "(tcpip)" - : " (usb)"; + bool is_usb = + sc_adb_device_get_type(d->serial) == SC_ADB_DEVICE_TYPE_USB; + const char *type = is_usb ? " (usb)" + : "(tcpip)"; LOG(level, " %s %s %-20s %16s %s", selection, type, d->serial, d->state, d->model ? d->model : ""); } @@ -531,6 +536,8 @@ sc_adb_device_check_state(struct sc_adb_device *device, LOGE("A popup should open on the device to request authorization."); LOGE("Check the FAQ: " ""); + } else { + LOGE("Device could not be connected (state=%s)", state); } return false; @@ -705,8 +712,3 @@ sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags) { return sc_adb_parse_device_ip_from_output(buf); } - -bool -sc_adb_is_serial_tcpip(const char *serial) { - return strchr(serial, ':'); -} diff --git a/app/src/adb/adb.h b/app/src/adb/adb.h index 10e8f293b1..ffd532eac6 100644 --- a/app/src/adb/adb.h +++ b/app/src/adb/adb.h @@ -114,13 +114,4 @@ sc_adb_getprop(struct sc_intr *intr, const char *serial, const char *prop, char * sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags); -/** - * Indicate if the serial represents an IP address - * - * In practice, it just returns true if and only if it contains a ':', which is - * sufficient to distinguish an ip:port from a real USB serial. - */ -bool -sc_adb_is_serial_tcpip(const char *serial); - #endif diff --git a/app/src/adb/adb_device.c b/app/src/adb/adb_device.c index cfd5dc3027..5ea8eb44a6 100644 --- a/app/src/adb/adb_device.c +++ b/app/src/adb/adb_device.c @@ -1,6 +1,7 @@ #include "adb_device.h" #include +#include void sc_adb_device_destroy(struct sc_adb_device *device) { @@ -25,3 +26,18 @@ sc_adb_devices_destroy(struct sc_vec_adb_devices *devices) { sc_vector_destroy(devices); } +enum sc_adb_device_type +sc_adb_device_get_type(const char *serial) { + // Starts with "emulator-" + if (!strncmp(serial, "emulator-", sizeof("emulator-") - 1)) { + return SC_ADB_DEVICE_TYPE_EMULATOR; + } + + // If the serial contains a ':', then it is a TCP/IP device (it is + // sufficient to distinguish an ip:port from a real USB serial) + if (strchr(serial, ':')) { + return SC_ADB_DEVICE_TYPE_TCPIP; + } + + return SC_ADB_DEVICE_TYPE_USB; +} diff --git a/app/src/adb/adb_device.h b/app/src/adb/adb_device.h index 14d0408cc1..56393bcfe7 100644 --- a/app/src/adb/adb_device.h +++ b/app/src/adb/adb_device.h @@ -15,6 +15,12 @@ struct sc_adb_device { bool selected; }; +enum sc_adb_device_type { + SC_ADB_DEVICE_TYPE_USB, + SC_ADB_DEVICE_TYPE_TCPIP, + SC_ADB_DEVICE_TYPE_EMULATOR, +}; + struct sc_vec_adb_devices SC_VECTOR(struct sc_adb_device); void @@ -35,4 +41,10 @@ sc_adb_device_move(struct sc_adb_device *dst, struct sc_adb_device *src); void sc_adb_devices_destroy(struct sc_vec_adb_devices *devices); +/** + * Deduce the device type from the serial + */ +enum sc_adb_device_type +sc_adb_device_get_type(const char *serial); + #endif diff --git a/app/src/cli.c b/app/src/cli.c index a4f79840af..538dd3e7ab 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -56,6 +56,7 @@ #define OPT_OTG 1036 #define OPT_NO_CLEANUP 1037 #define OPT_PRINT_FPS 1038 +#define OPT_NO_POWER_ON 1039 struct sc_option { char shortopt; @@ -80,6 +81,11 @@ struct sc_envvar { const char *text; }; +struct sc_exit_status { + unsigned value; + const char *text; +}; + struct sc_getopt_adapter { char *optstring; struct option *longopts; @@ -297,6 +303,11 @@ static const struct sc_option options[] = { "mipmaps are automatically generated to improve downscaling " "quality. This option disables the generation of mipmaps.", }, + { + .longopt_id = OPT_NO_POWER_ON, + .longopt = "no-power-on", + .text = "Do not power on the device on start.", + }, { .longopt_id = OPT_OTG, .longopt = "otg", @@ -572,7 +583,7 @@ static const struct sc_shortcut shortcuts[] = { .text = "Click on BACK", }, { - .shortcuts = { "MOD+s" }, + .shortcuts = { "MOD+s", "4th-click" }, .text = "Click on APP_SWITCH", }, { @@ -608,7 +619,7 @@ static const struct sc_shortcut shortcuts[] = { .text = "Rotate device screen", }, { - .shortcuts = { "MOD+n" }, + .shortcuts = { "MOD+n", "5th-click" }, .text = "Expand notification panel", }, { @@ -655,6 +666,11 @@ static const struct sc_envvar envvars[] = { .name = "ADB", .text = "Path to adb executable", }, + { + .name = "ANDROID_SERIAL", + .text = "Device serial to use if no selector (-s, -d, -e or " + "--tcpip=) is specified", + }, { .name = "SCRCPY_ICON_PATH", .text = "Path to the program icon", @@ -662,7 +678,22 @@ static const struct sc_envvar envvars[] = { { .name = "SCRCPY_SERVER_PATH", .text = "Path to the server binary", - } + }, +}; + +static const struct sc_exit_status exit_statuses[] = { + { + .value = 0, + .text = "Normal program termination", + }, + { + .value = 1, + .text = "Start failure", + }, + { + .value = 2, + .text = "Device disconnected while running", + }, }; static char * @@ -901,6 +932,25 @@ print_envvar(const struct sc_envvar *envvar, unsigned cols) { free(text); } +static void +print_exit_status(const struct sc_exit_status *status, unsigned cols) { + assert(cols > 8); // sc_str_wrap_lines() requires indent < columns + assert(status->text); + + // The text starts at 9: 4 ident spaces, 3 chars for numeric value, 2 spaces + char *text = sc_str_wrap_lines(status->text, cols, 9); + if (!text) { + printf("\n"); + return; + } + + assert(strlen(text) >= 9); // Contains at least the initial identation + + // text + 9 to remove the initial indentation + printf(" %3d %s\n", status->value, text + 9); + free(text); +} + void scrcpy_print_usage(const char *arg0) { #define SC_TERM_COLS_DEFAULT 80 @@ -939,6 +989,11 @@ scrcpy_print_usage(const char *arg0) { for (size_t i = 0; i < ARRAY_LEN(envvars); ++i) { print_envvar(&envvars[i], cols); } + + printf("\nExit status:\n\n"); + for (size_t i = 0; i < ARRAY_LEN(exit_statuses); ++i) { + print_exit_status(&exit_statuses[i], cols); + } } static bool @@ -1549,6 +1604,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], case OPT_NO_CLEANUP: opts->cleanup = false; break; + case OPT_NO_POWER_ON: + opts->power_on = false; + break; case OPT_PRINT_FPS: opts->start_fps_counter = true; break; diff --git a/app/src/common.h b/app/src/common.h index ce9ccad4e8..dccc8316d9 100644 --- a/app/src/common.h +++ b/app/src/common.h @@ -1,5 +1,5 @@ -#ifndef COMMON_H -#define COMMON_H +#ifndef SC_COMMON_H +#define SC_COMMON_H #include "config.h" #include "compat.h" diff --git a/app/src/compat.h b/app/src/compat.h index 6243571869..8265dbc85e 100644 --- a/app/src/compat.h +++ b/app/src/compat.h @@ -1,5 +1,5 @@ -#ifndef COMPAT_H -#define COMPAT_H +#ifndef SC_COMPAT_H +#define SC_COMPAT_H #include "config.h" diff --git a/app/src/control_msg.h b/app/src/control_msg.h index fbe203d440..1463fddc24 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -1,5 +1,5 @@ -#ifndef CONTROLMSG_H -#define CONTROLMSG_H +#ifndef SC_CONTROLMSG_H +#define SC_CONTROLMSG_H #include "common.h" diff --git a/app/src/controller.h b/app/src/controller.h index f8bc7c02c0..f866235340 100644 --- a/app/src/controller.h +++ b/app/src/controller.h @@ -1,5 +1,5 @@ -#ifndef CONTROLLER_H -#define CONTROLLER_H +#ifndef SC_CONTROLLER_H +#define SC_CONTROLLER_H #include "common.h" diff --git a/app/src/device_msg.h b/app/src/device_msg.h index a0c989e3f8..e8d9fed428 100644 --- a/app/src/device_msg.h +++ b/app/src/device_msg.h @@ -1,5 +1,5 @@ -#ifndef DEVICEMSG_H -#define DEVICEMSG_H +#ifndef SC_DEVICEMSG_H +#define SC_DEVICEMSG_H #include "common.h" diff --git a/app/src/fps_counter.h b/app/src/fps_counter.h index e21c49c45d..e761927195 100644 --- a/app/src/fps_counter.h +++ b/app/src/fps_counter.h @@ -1,5 +1,5 @@ -#ifndef FPSCOUNTER_H -#define FPSCOUNTER_H +#ifndef SC_FPSCOUNTER_H +#define SC_FPSCOUNTER_H #include "common.h" diff --git a/app/src/icon.h b/app/src/icon.h index 8df5367186..3251e48f35 100644 --- a/app/src/icon.h +++ b/app/src/icon.h @@ -1,5 +1,5 @@ -#ifndef ICON_H -#define ICON_H +#ifndef SC_ICON_H +#define SC_ICON_H #include "common.h" diff --git a/app/src/input_manager.h b/app/src/input_manager.h index f6c210e349..46b1160e83 100644 --- a/app/src/input_manager.h +++ b/app/src/input_manager.h @@ -1,5 +1,5 @@ -#ifndef INPUTMANAGER_H -#define INPUTMANAGER_H +#ifndef SC_INPUTMANAGER_H +#define SC_INPUTMANAGER_H #include "common.h" diff --git a/app/src/main.c b/app/src/main.c index 2d1575f8e4..3334cbf9dd 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -40,19 +40,19 @@ main(int argc, char *argv[]) { #endif if (!scrcpy_parse_args(&args, argc, argv)) { - return 1; + return SCRCPY_EXIT_FAILURE; } sc_set_log_level(args.opts.log_level); if (args.help) { scrcpy_print_usage(argv[0]); - return 0; + return SCRCPY_EXIT_SUCCESS; } if (args.version) { scrcpy_print_version(); - return 0; + return SCRCPY_EXIT_SUCCESS; } #ifdef SCRCPY_LAVF_REQUIRES_REGISTER_ALL @@ -66,17 +66,17 @@ main(int argc, char *argv[]) { #endif if (avformat_network_init()) { - return 1; + return SCRCPY_EXIT_FAILURE; } #ifdef HAVE_USB - bool ok = args.opts.otg ? scrcpy_otg(&args.opts) - : scrcpy(&args.opts); + enum scrcpy_exit_code ret = args.opts.otg ? scrcpy_otg(&args.opts) + : scrcpy(&args.opts); #else - bool ok = scrcpy(&args.opts); + enum scrcpy_exit_code ret = scrcpy(&args.opts); #endif avformat_network_deinit(); // ignore failure - return ok ? 0 : 1; + return ret; } diff --git a/app/src/opengl.c b/app/src/opengl.c index da05c0821a..376690af3a 100644 --- a/app/src/opengl.c +++ b/app/src/opengl.c @@ -28,7 +28,7 @@ sc_opengl_init(struct sc_opengl *gl) { sizeof(OPENGL_ES_PREFIX) - 1); if (gl->is_opengles) { /* skip the prefix */ - version += sizeof(PREFIX) - 1; + version += sizeof(OPENGL_ES_PREFIX) - 1; } int r = sscanf(version, "%d.%d", &gl->version_major, &gl->version_minor); diff --git a/app/src/options.c b/app/src/options.c index 6651020f3e..8b2624d992 100644 --- a/app/src/options.c +++ b/app/src/options.c @@ -64,4 +64,5 @@ const struct scrcpy_options scrcpy_options_default = { .select_usb = false, .cleanup = true, .start_fps_counter = false, + .power_on = true, }; diff --git a/app/src/options.h b/app/src/options.h index f63e5c429c..7e542c06a8 100644 --- a/app/src/options.h +++ b/app/src/options.h @@ -139,6 +139,7 @@ struct scrcpy_options { bool select_tcpip; bool cleanup; bool start_fps_counter; + bool power_on; }; extern const struct scrcpy_options scrcpy_options_default; diff --git a/app/src/receiver.h b/app/src/receiver.h index 3c4e8c645a..f5808e4b1b 100644 --- a/app/src/receiver.h +++ b/app/src/receiver.h @@ -1,5 +1,5 @@ -#ifndef RECEIVER_H -#define RECEIVER_H +#ifndef SC_RECEIVER_H +#define SC_RECEIVER_H #include "common.h" diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 3ed1d24910..3588e9aef0 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -149,38 +149,41 @@ sdl_configure(bool display, bool disable_screensaver) { } } -static bool +static enum scrcpy_exit_code event_loop(struct scrcpy *s) { SDL_Event event; while (SDL_WaitEvent(&event)) { switch (event.type) { case EVENT_STREAM_STOPPED: LOGW("Device disconnected"); - return false; + return SCRCPY_EXIT_DISCONNECTED; case SDL_QUIT: LOGD("User requested to quit"); - return true; + return SCRCPY_EXIT_SUCCESS; default: sc_screen_handle_event(&s->screen, &event); break; } } - return false; + return SCRCPY_EXIT_FAILURE; } +// Return true on success, false on error static bool -await_for_server(void) { +await_for_server(bool *connected) { SDL_Event event; while (SDL_WaitEvent(&event)) { switch (event.type) { case SDL_QUIT: LOGD("User requested to quit"); - return false; + *connected = false; + return true; case EVENT_SERVER_CONNECTION_FAILED: LOGE("Server connection failed"); return false; case EVENT_SERVER_CONNECTED: LOGD("Server connected"); + *connected = true; return true; default: break; @@ -262,7 +265,7 @@ sc_server_on_disconnected(struct sc_server *server, void *userdata) { // event } -bool +enum scrcpy_exit_code scrcpy(struct scrcpy_options *options) { static struct scrcpy scrcpy; struct scrcpy *s = &scrcpy; @@ -270,12 +273,12 @@ scrcpy(struct scrcpy_options *options) { // Minimal SDL initialization if (SDL_Init(SDL_INIT_EVENTS)) { LOGE("Could not initialize SDL: %s", SDL_GetError()); - return false; + return SCRCPY_EXIT_FAILURE; } atexit(SDL_Quit); - bool ret = false; + enum scrcpy_exit_code ret = SCRCPY_EXIT_FAILURE; bool server_started = false; bool file_pusher_initialized = false; @@ -321,6 +324,7 @@ scrcpy(struct scrcpy_options *options) { .tcpip = options->tcpip, .tcpip_dst = options->tcpip_dst, .cleanup = options->cleanup, + .power_on = options->power_on, }; static const struct sc_server_callbacks cbs = { @@ -329,7 +333,7 @@ scrcpy(struct scrcpy_options *options) { .on_disconnected = sc_server_on_disconnected, }; if (!sc_server_init(&s->server, ¶ms, &cbs, NULL)) { - return false; + return SCRCPY_EXIT_FAILURE; } if (!sc_server_start(&s->server)) { @@ -351,7 +355,14 @@ scrcpy(struct scrcpy_options *options) { sdl_configure(options->display, options->disable_screensaver); // Await for server without blocking Ctrl+C handling - if (!await_for_server()) { + bool connected; + if (!await_for_server(&connected)) { + goto end; + } + + if (!connected) { + // This is not an error, user requested to quit + ret = SCRCPY_EXIT_SUCCESS; goto end; } diff --git a/app/src/scrcpy.h b/app/src/scrcpy.h index cdcecda7cd..d4d494a3ab 100644 --- a/app/src/scrcpy.h +++ b/app/src/scrcpy.h @@ -6,7 +6,18 @@ #include #include "options.h" -bool +enum scrcpy_exit_code { + // Normal program termination + SCRCPY_EXIT_SUCCESS, + + // No connection could be established + SCRCPY_EXIT_FAILURE, + + // Device was disconnected while running + SCRCPY_EXIT_DISCONNECTED, +}; + +enum scrcpy_exit_code scrcpy(struct scrcpy_options *options); #endif diff --git a/app/src/server.c b/app/src/server.c index c12b03d46e..663ef18bb4 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -248,6 +248,10 @@ execute_server(struct sc_server *server, // By default, cleanup is true ADD_PARAM("cleanup=false"); } + if (!params->power_on) { + // By default, power_on is true + ADD_PARAM("power_on=false"); + } #undef ADD_PARAM @@ -649,7 +653,8 @@ sc_server_configure_tcpip_known_address(struct sc_server *server, static bool sc_server_configure_tcpip_unknown_address(struct sc_server *server, const char *serial) { - bool is_already_tcpip = sc_adb_is_serial_tcpip(serial); + bool is_already_tcpip = + sc_adb_device_get_type(serial) == SC_ADB_DEVICE_TYPE_TCPIP; if (is_already_tcpip) { // Nothing to do LOGI("Device already connected via TCP/IP: %s", serial); @@ -707,7 +712,15 @@ run_server(void *data) { } else if (params->select_tcpip) { selector.type = SC_ADB_DEVICE_SELECT_TCPIP; } else { - selector.type = SC_ADB_DEVICE_SELECT_ALL; + // No explicit selection, check $ANDROID_SERIAL + const char *env_serial = getenv("ANDROID_SERIAL"); + if (env_serial) { + LOGI("Using ANDROID_SERIAL: %s", env_serial); + selector.type = SC_ADB_DEVICE_SELECT_SERIAL; + selector.serial = env_serial; + } else { + selector.type = SC_ADB_DEVICE_SELECT_ALL; + } } struct sc_adb_device device; ok = sc_adb_select_device(&server->intr, &selector, 0, &device); diff --git a/app/src/server.h b/app/src/server.h index 5f630ca8f1..49ba83c1f8 100644 --- a/app/src/server.h +++ b/app/src/server.h @@ -47,6 +47,7 @@ struct sc_server_params { bool select_usb; bool select_tcpip; bool cleanup; + bool power_on; }; struct sc_server { diff --git a/app/src/usb/hid_keyboard.c b/app/src/usb/hid_keyboard.c index 4a0e64baf8..a12fbf3b92 100644 --- a/app/src/usb/hid_keyboard.c +++ b/app/src/usb/hid_keyboard.c @@ -340,7 +340,7 @@ push_mod_lock_state(struct sc_hid_keyboard *kb, uint16_t mods_state) { if (!sc_aoa_push_hid_event(kb->aoa, &hid_event)) { sc_hid_event_destroy(&hid_event); - LOGW("Could request HID event"); + LOGW("Could not request HID event (mod lock state)"); return false; } @@ -382,7 +382,7 @@ sc_key_processor_process_key(struct sc_key_processor *kp, if (!sc_aoa_push_hid_event(kb->aoa, &hid_event)) { sc_hid_event_destroy(&hid_event); - LOGW("Could request HID event"); + LOGW("Could not request HID event (key)"); } } } diff --git a/app/src/usb/hid_mouse.c b/app/src/usb/hid_mouse.c index c24b4a4a32..bab8994000 100644 --- a/app/src/usb/hid_mouse.c +++ b/app/src/usb/hid_mouse.c @@ -181,7 +181,7 @@ sc_mouse_processor_process_mouse_motion(struct sc_mouse_processor *mp, if (!sc_aoa_push_hid_event(mouse->aoa, &hid_event)) { sc_hid_event_destroy(&hid_event); - LOGW("Could request HID event"); + LOGW("Could not request HID event (mouse motion)"); } } @@ -203,7 +203,7 @@ sc_mouse_processor_process_mouse_click(struct sc_mouse_processor *mp, if (!sc_aoa_push_hid_event(mouse->aoa, &hid_event)) { sc_hid_event_destroy(&hid_event); - LOGW("Could request HID event"); + LOGW("Could not request HID event (mouse click)"); } } @@ -228,7 +228,7 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp, if (!sc_aoa_push_hid_event(mouse->aoa, &hid_event)) { sc_hid_event_destroy(&hid_event); - LOGW("Could request HID event"); + LOGW("Could not request HID event (mouse scroll)"); } } diff --git a/app/src/usb/scrcpy_otg.c b/app/src/usb/scrcpy_otg.c index 1c53410eeb..ebcfa36fb6 100644 --- a/app/src/usb/scrcpy_otg.c +++ b/app/src/usb/scrcpy_otg.c @@ -29,32 +29,36 @@ sc_usb_on_disconnected(struct sc_usb *usb, void *userdata) { } } -static bool +static enum scrcpy_exit_code event_loop(struct scrcpy_otg *s) { SDL_Event event; while (SDL_WaitEvent(&event)) { switch (event.type) { case EVENT_USB_DEVICE_DISCONNECTED: LOGW("Device disconnected"); - return false; + return SCRCPY_EXIT_DISCONNECTED; case SDL_QUIT: LOGD("User requested to quit"); - return true; + return SCRCPY_EXIT_SUCCESS; default: sc_screen_otg_handle_event(&s->screen_otg, &event); break; } } - return false; + return SCRCPY_EXIT_FAILURE; } -bool +enum scrcpy_exit_code scrcpy_otg(struct scrcpy_options *options) { static struct scrcpy_otg scrcpy_otg; struct scrcpy_otg *s = &scrcpy_otg; const char *serial = options->serial; + if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) { + LOGW("Could not enable linear filtering"); + } + // Minimal SDL initialization if (SDL_Init(SDL_INIT_EVENTS)) { LOGE("Could not initialize SDL: %s", SDL_GetError()); @@ -67,7 +71,7 @@ scrcpy_otg(struct scrcpy_options *options) { LOGW("Could not enable mouse focus clickthrough"); } - bool ret = false; + enum scrcpy_exit_code ret = SCRCPY_EXIT_FAILURE; struct sc_hid_keyboard *keyboard = NULL; struct sc_hid_mouse *mouse = NULL; @@ -90,7 +94,7 @@ scrcpy_otg(struct scrcpy_options *options) { }; bool ok = sc_usb_init(&s->usb); if (!ok) { - return false; + return SCRCPY_EXIT_FAILURE; } struct sc_usb_device usb_device; @@ -162,6 +166,8 @@ scrcpy_otg(struct scrcpy_options *options) { .always_on_top = options->always_on_top, .window_x = options->window_x, .window_y = options->window_y, + .window_width = options->window_width, + .window_height = options->window_height, .window_borderless = options->window_borderless, }; diff --git a/app/src/usb/scrcpy_otg.h b/app/src/usb/scrcpy_otg.h index 24b9cde87c..e477660b7c 100644 --- a/app/src/usb/scrcpy_otg.h +++ b/app/src/usb/scrcpy_otg.h @@ -3,10 +3,10 @@ #include "common.h" -#include #include "options.h" +#include "scrcpy.h" -bool +enum scrcpy_exit_code scrcpy_otg(struct scrcpy_options *options); #endif diff --git a/app/src/usb/screen_otg.c b/app/src/usb/screen_otg.c index 561a84ca41..e1d5cb014a 100644 --- a/app/src/usb/screen_otg.c +++ b/app/src/usb/screen_otg.c @@ -69,10 +69,10 @@ sc_screen_otg_init(struct sc_screen_otg *screen, ? params->window_x : (int) SDL_WINDOWPOS_UNDEFINED; int y = params->window_y != SC_WINDOW_POSITION_UNDEFINED ? params->window_y : (int) SDL_WINDOWPOS_UNDEFINED; - int width = 256; - int height = 256; + int width = params->window_width ? params->window_width : 256; + int height = params->window_height ? params->window_height : 256; - uint32_t window_flags = 0; + uint32_t window_flags = SDL_WINDOW_ALLOW_HIGHDPI; if (params->always_on_top) { window_flags |= SDL_WINDOW_ALWAYS_ON_TOP; } @@ -97,6 +97,11 @@ sc_screen_otg_init(struct sc_screen_otg *screen, if (icon) { SDL_SetWindowIcon(screen->window, icon); + if (SDL_RenderSetLogicalSize(screen->renderer, icon->w, icon->h)) { + LOGW("Could not set renderer logical size: %s", SDL_GetError()); + // don't fail + } + screen->texture = SDL_CreateTextureFromSurface(screen->renderer, icon); scrcpy_icon_destroy(icon); if (!screen->texture) { diff --git a/app/src/usb/screen_otg.h b/app/src/usb/screen_otg.h index 0973ce59e1..a0acf40bda 100644 --- a/app/src/usb/screen_otg.h +++ b/app/src/usb/screen_otg.h @@ -29,6 +29,8 @@ struct sc_screen_otg_params { bool always_on_top; int16_t window_x; // accepts SC_WINDOW_POSITION_UNDEFINED int16_t window_y; // accepts SC_WINDOW_POSITION_UNDEFINED + uint16_t window_width; + uint16_t window_height; bool window_borderless; }; diff --git a/app/src/usb/usb.c b/app/src/usb/usb.c index 32a66f987a..97aa9a3350 100644 --- a/app/src/usb/usb.c +++ b/app/src/usb/usb.c @@ -15,6 +15,7 @@ read_string(libusb_device_handle *handle, uint8_t desc_index) { (unsigned char *) buffer, sizeof(buffer)); if (result < 0) { + LOGD("Read string: libusb error: %s", libusb_strerror(result)); return NULL; } diff --git a/app/src/util/cbuf.h b/app/src/util/cbuf.h index 01e4104442..2a75617143 100644 --- a/app/src/util/cbuf.h +++ b/app/src/util/cbuf.h @@ -1,6 +1,6 @@ // generic circular buffer (bounded queue) implementation -#ifndef CBUF_H -#define CBUF_H +#ifndef SC_CBUF_H +#define SC_CBUF_H #include "common.h" diff --git a/app/src/util/net.h b/app/src/util/net.h index 15979cf934..d92899819d 100644 --- a/app/src/util/net.h +++ b/app/src/util/net.h @@ -1,5 +1,5 @@ -#ifndef NET_H -#define NET_H +#ifndef SC_NET_H +#define SC_NET_H #include "common.h" diff --git a/cross_win32.txt b/cross_win32.txt index 750dbd78c7..d1d5d11b1d 100644 --- a/cross_win32.txt +++ b/cross_win32.txt @@ -20,6 +20,6 @@ ffmpeg_avcodec = 'avcodec-58' ffmpeg_avformat = 'avformat-58' ffmpeg_avutil = 'avutil-56' prebuilt_ffmpeg = 'ffmpeg-win32-4.3.1' -prebuilt_sdl2 = 'SDL2-2.0.20/i686-w64-mingw32' -prebuilt_libusb_root = 'libusb-1.0.25' -prebuilt_libusb = prebuilt_libusb_root + '/MinGW32' +prebuilt_sdl2 = 'SDL2-2.0.22/i686-w64-mingw32' +prebuilt_libusb_root = 'libusb-1.0.26' +prebuilt_libusb = prebuilt_libusb_root + '/MinGW-Win32' diff --git a/cross_win64.txt b/cross_win64.txt index 114b0c2217..cc9e4a0bbf 100644 --- a/cross_win64.txt +++ b/cross_win64.txt @@ -19,7 +19,7 @@ endian = 'little' ffmpeg_avcodec = 'avcodec-59' ffmpeg_avformat = 'avformat-59' ffmpeg_avutil = 'avutil-57' -prebuilt_ffmpeg = 'ffmpeg-win64-5.0' -prebuilt_sdl2 = 'SDL2-2.0.20/x86_64-w64-mingw32' -prebuilt_libusb_root = 'libusb-1.0.25' -prebuilt_libusb = prebuilt_libusb_root + '/MinGW64' +prebuilt_ffmpeg = 'ffmpeg-win64-5.0.1' +prebuilt_sdl2 = 'SDL2-2.0.22/x86_64-w64-mingw32' +prebuilt_libusb_root = 'libusb-1.0.26' +prebuilt_libusb = prebuilt_libusb_root + '/MinGW-x64' diff --git a/install_release.sh b/install_release.sh index 9b1ed8e7fb..88262f8ee9 100755 --- a/install_release.sh +++ b/install_release.sh @@ -2,8 +2,8 @@ set -e BUILDDIR=build-auto -PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v1.23/scrcpy-server-v1.23 -PREBUILT_SERVER_SHA256=2a913fd47478c0b306fca507cb0beb625e49a19ff9fc7ab904e36ef5b9fe7e68 +PREBUILT_SERVER_URL=https://github.com/Genymobile/scrcpy/releases/download/v1.24/scrcpy-server-v1.24 +PREBUILT_SERVER_SHA256=ae74a81ea79c0dc7250e586627c278c0a9a8c5de46c9fb5c38c167fb1a36f056 echo "[scrcpy] Downloading prebuilt server..." wget "$PREBUILT_SERVER_URL" -O scrcpy-server diff --git a/meson.build b/meson.build index e7270b5aa4..bfca61344f 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('scrcpy', 'c', - version: '1.23', + version: '1.24', meson_version: '>= 0.48', default_options: [ 'c_std=c11', diff --git a/release.mk b/release.mk index caf6ab1aba..94a9680e93 100644 --- a/release.mk +++ b/release.mk @@ -75,12 +75,10 @@ prepare-deps-win64: @app/prebuilt-deps/prepare-libusb.sh build-win32: prepare-deps-win32 - # -Dusb=false because of libusb-win32 build issue, cf #3011 [ -d "$(WIN32_BUILD_DIR)" ] || ( mkdir "$(WIN32_BUILD_DIR)" && \ meson "$(WIN32_BUILD_DIR)" \ --cross-file cross_win32.txt \ --buildtype release --strip -Db_lto=true \ - -Dusb=false \ -Dcompile_server=false \ -Dportable=true ) ninja -C "$(WIN32_BUILD_DIR)" @@ -107,11 +105,11 @@ dist-win32: build-server build-win32 cp app/prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/" cp app/prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/swscale-5.dll "$(DIST)/$(WIN32_TARGET_DIR)/" - cp app/prebuilt-deps/data/platform-tools-31.0.3/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/" - cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" - cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" - cp app/prebuilt-deps/data/SDL2-2.0.20/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/" - #cp app/prebuilt-deps/data/libusb-1.0.25/MinGW32/dll/libusb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/" + cp app/prebuilt-deps/data/platform-tools-33.0.1/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/" + cp app/prebuilt-deps/data/platform-tools-33.0.1/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" + cp app/prebuilt-deps/data/platform-tools-33.0.1/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/" + cp app/prebuilt-deps/data/SDL2-2.0.22/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/" + cp app/prebuilt-deps/data/libusb-1.0.26/MinGW-Win32/msys-usb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/" dist-win64: build-server build-win64 mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)" @@ -121,16 +119,16 @@ dist-win64: build-server build-win64 cp app/data/scrcpy-noconsole.vbs "$(DIST)/$(WIN64_TARGET_DIR)" cp app/data/icon.png "$(DIST)/$(WIN64_TARGET_DIR)" cp app/data/open_a_terminal_here.bat "$(DIST)/$(WIN64_TARGET_DIR)" - cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/avutil-57.dll "$(DIST)/$(WIN64_TARGET_DIR)/" - cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/avcodec-59.dll "$(DIST)/$(WIN64_TARGET_DIR)/" - cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/avformat-59.dll "$(DIST)/$(WIN64_TARGET_DIR)/" - cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/swresample-4.dll "$(DIST)/$(WIN64_TARGET_DIR)/" - cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/swscale-6.dll "$(DIST)/$(WIN64_TARGET_DIR)/" - cp app/prebuilt-deps/data/platform-tools-31.0.3/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/" - cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" - cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" - cp app/prebuilt-deps/data/SDL2-2.0.20/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/" - cp app/prebuilt-deps/data/libusb-1.0.25/MinGW64/dll/libusb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/ffmpeg-win64-5.0.1/bin/avutil-57.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/ffmpeg-win64-5.0.1/bin/avcodec-59.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/ffmpeg-win64-5.0.1/bin/avformat-59.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/ffmpeg-win64-5.0.1/bin/swresample-4.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/ffmpeg-win64-5.0.1/bin/swscale-6.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/platform-tools-33.0.1/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/platform-tools-33.0.1/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/platform-tools-33.0.1/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/SDL2-2.0.22/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/" + cp app/prebuilt-deps/data/libusb-1.0.26/MinGW-x64/msys-usb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/" zip-win32: dist-win32 cd "$(DIST)/$(WIN32_TARGET_DIR)"; \ diff --git a/run b/run index fda3ea57a1..56f0a4e1c0 100755 --- a/run +++ b/run @@ -20,6 +20,6 @@ then exit 1 fi -SCRCPY_ICON_PATH="data/icon.png" \ +SCRCPY_ICON_PATH="app/data/icon.png" \ SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" \ "$BUILDDIR/app/scrcpy" "$@" diff --git a/server/build.gradle b/server/build.gradle index f3eb6d64f3..dbc8261f68 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -6,8 +6,8 @@ android { applicationId "com.genymobile.scrcpy" minSdkVersion 21 targetSdkVersion 31 - versionCode 12300 - versionName "1.23" + versionCode 12400 + versionName "1.24" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/server/build_without_gradle.sh b/server/build_without_gradle.sh index b2bafa3f05..c881e38a8b 100755 --- a/server/build_without_gradle.sh +++ b/server/build_without_gradle.sh @@ -12,7 +12,7 @@ set -e SCRCPY_DEBUG=false -SCRCPY_VERSION_NAME=1.23 +SCRCPY_VERSION_NAME=1.24 PLATFORM=${ANDROID_PLATFORM:-31} BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-31.0.0} diff --git a/server/src/main/java/com/genymobile/scrcpy/Controller.java b/server/src/main/java/com/genymobile/scrcpy/Controller.java index 614f7de6a6..322959911f 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/Controller.java @@ -22,6 +22,7 @@ public class Controller { private final DesktopConnection connection; private final DeviceMessageSender sender; private final boolean clipboardAutosync; + private final boolean powerOn; private final KeyCharacterMap charMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); @@ -32,10 +33,11 @@ public class Controller { private boolean keepPowerModeOff; - public Controller(Device device, DesktopConnection connection, boolean clipboardAutosync) { + public Controller(Device device, DesktopConnection connection, boolean clipboardAutosync, boolean powerOn) { this.device = device; this.connection = connection; this.clipboardAutosync = clipboardAutosync; + this.powerOn = powerOn; initPointers(); sender = new DeviceMessageSender(connection); } @@ -56,7 +58,7 @@ private void initPointers() { public void control() throws IOException { // on start, power on the device - if (!Device.isScreenOn()) { + if (powerOn && !Device.isScreenOn()) { device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER, Device.INJECT_MODE_ASYNC); // dirty hack diff --git a/server/src/main/java/com/genymobile/scrcpy/Options.java b/server/src/main/java/com/genymobile/scrcpy/Options.java index 4842b63557..d1607c200c 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Options.java +++ b/server/src/main/java/com/genymobile/scrcpy/Options.java @@ -22,6 +22,7 @@ public class Options { private boolean clipboardAutosync = true; private boolean downsizeOnError = true; private boolean cleanup = true; + private boolean powerOn = true; // Options not used by the scrcpy client, but useful to use scrcpy-server directly private boolean sendDeviceMeta = true; // send device name and size @@ -164,6 +165,14 @@ public void setCleanup(boolean cleanup) { this.cleanup = cleanup; } + public boolean getPowerOn() { + return powerOn; + } + + public void setPowerOn(boolean powerOn) { + this.powerOn = powerOn; + } + public boolean getSendDeviceMeta() { return sendDeviceMeta; } diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java index 60f485d81a..1df9155207 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Server.java +++ b/server/src/main/java/com/genymobile/scrcpy/Server.java @@ -82,7 +82,7 @@ private static void scrcpy(Options options) throws IOException { Thread controllerThread = null; Thread deviceMessageSenderThread = null; if (control) { - final Controller controller = new Controller(device, connection, options.getClipboardAutosync()); + final Controller controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn()); // asynchronous controllerThread = startController(controller); @@ -248,6 +248,10 @@ private static Options createOptions(String... args) { boolean cleanup = Boolean.parseBoolean(value); options.setCleanup(cleanup); break; + case "power_on": + boolean powerOn = Boolean.parseBoolean(value); + options.setPowerOn(powerOn); + break; case "send_device_meta": boolean sendDeviceMeta = Boolean.parseBoolean(value); options.setSendDeviceMeta(sendDeviceMeta); diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java index 6116899351..38e96d4550 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/InputManager.java @@ -2,7 +2,6 @@ import com.genymobile.scrcpy.Ln; -import android.os.IInterface; import android.view.InputEvent; import java.lang.reflect.InvocationTargetException; @@ -14,24 +13,18 @@ public final class InputManager { public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1; public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; - private final IInterface manager; + private final android.hardware.input.InputManager manager; private Method injectInputEventMethod; - private boolean alternativeInjectInputEventMethod; private static Method setDisplayIdMethod; - public InputManager(IInterface manager) { + public InputManager(android.hardware.input.InputManager manager) { this.manager = manager; } private Method getInjectInputEventMethod() throws NoSuchMethodException { if (injectInputEventMethod == null) { - try { - injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class); - } catch (NoSuchMethodException e) { - injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class, int.class); - alternativeInjectInputEventMethod = true; - } + injectInputEventMethod = manager.getClass().getMethod("injectInputEvent", InputEvent.class, int.class); } return injectInputEventMethod; } @@ -39,10 +32,6 @@ private Method getInjectInputEventMethod() throws NoSuchMethodException { public boolean injectInputEvent(InputEvent inputEvent, int mode) { try { Method method = getInjectInputEventMethod(); - if (alternativeInjectInputEventMethod) { - // See - return (boolean) method.invoke(manager, inputEvent, mode, 0); - } return (boolean) method.invoke(manager, inputEvent, mode); } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { Ln.e("Could not invoke method", e); diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ServiceManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ServiceManager.java index 6f4b9c042c..ea2a078470 100644 --- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ServiceManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ServiceManager.java @@ -4,6 +4,7 @@ import android.os.IBinder; import android.os.IInterface; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @SuppressLint("PrivateApi,DiscouragedPrivateApi") @@ -56,7 +57,13 @@ public DisplayManager getDisplayManager() { public InputManager getInputManager() { if (inputManager == null) { - inputManager = new InputManager(getService("input", "android.hardware.input.IInputManager")); + try { + Method getInstanceMethod = android.hardware.input.InputManager.class.getDeclaredMethod("getInstance"); + android.hardware.input.InputManager im = (android.hardware.input.InputManager) getInstanceMethod.invoke(null); + inputManager = new InputManager(im); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new AssertionError(e); + } } return inputManager; }