Compare commits
10 Commits
install.2
...
printf_flo
Author | SHA1 | Date | |
---|---|---|---|
d23b3e88a4 | |||
a47848f304 | |||
db8c1ce8e1 | |||
4aeb78ece2 | |||
396e4bd925 | |||
7f2f5950f2 | |||
af4b7855e1 | |||
b1d8c72780 | |||
55e65fa270 | |||
69fb5f6ee1 |
@ -401,6 +401,7 @@ sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
|
|||||||
#define BUFSIZE 65536
|
#define BUFSIZE 65536
|
||||||
char *buf = malloc(BUFSIZE);
|
char *buf = malloc(BUFSIZE);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
|
LOG_OOM();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,48 +713,3 @@ sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags) {
|
|||||||
|
|
||||||
return sc_adb_parse_device_ip(buf);
|
return sc_adb_parse_device_ip(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
sc_adb_get_installed_apk_path(struct sc_intr *intr, const char *serial,
|
|
||||||
unsigned flags) {
|
|
||||||
assert(serial);
|
|
||||||
const char *const argv[] =
|
|
||||||
SC_ADB_COMMAND("-s", serial, "shell", "pm", "list", "package", "-f",
|
|
||||||
SC_ANDROID_PACKAGE);
|
|
||||||
|
|
||||||
sc_pipe pout;
|
|
||||||
sc_pid pid = sc_adb_execute_p(argv, flags, &pout);
|
|
||||||
if (pid == SC_PROCESS_NONE) {
|
|
||||||
LOGD("Could not execute \"pm list packages\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "pm list packages -f <package>" output should contain only one line, so
|
|
||||||
// the output should be short
|
|
||||||
char buf[1024];
|
|
||||||
ssize_t r = sc_pipe_read_all_intr(intr, pid, pout, buf, sizeof(buf) - 1);
|
|
||||||
sc_pipe_close(pout);
|
|
||||||
|
|
||||||
bool ok = process_check_success_intr(intr, pid, "pm list packages", flags);
|
|
||||||
if (!ok) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r == -1) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert((size_t) r < sizeof(buf));
|
|
||||||
if (r == sizeof(buf) - 1) {
|
|
||||||
// The implementation assumes that the output of "ip route" fits in the
|
|
||||||
// buffer in a single pass
|
|
||||||
LOGW("Result of \"pm list package\" does not fit in 1Kb. "
|
|
||||||
"Please report an issue.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// It is parsed as a NUL-terminated string
|
|
||||||
buf[r] = '\0';
|
|
||||||
|
|
||||||
return sc_adb_parse_installed_apk_path(buf);
|
|
||||||
}
|
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
#define SC_ADB_SILENT (SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR)
|
#define SC_ADB_SILENT (SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR)
|
||||||
|
|
||||||
#define SC_ANDROID_PACKAGE "com.genymobile.scrcpy"
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
sc_adb_get_executable(void);
|
sc_adb_get_executable(void);
|
||||||
|
|
||||||
@ -116,11 +114,4 @@ sc_adb_getprop(struct sc_intr *intr, const char *serial, const char *prop,
|
|||||||
char *
|
char *
|
||||||
sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags);
|
sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags);
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the path of the installed APK for com.genymobile.scrcpy (if any)
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
sc_adb_get_installed_apk_path(struct sc_intr *intr, const char *serial,
|
|
||||||
unsigned flags);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -225,31 +225,3 @@ sc_adb_parse_device_ip(char *str) {
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
sc_adb_parse_installed_apk_path(char *str) {
|
|
||||||
// str is expected to look like:
|
|
||||||
// "package:/data/app/.../base.apk=com.genymobile.scrcpy"
|
|
||||||
// ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
// We want to extract the path (which may contain '=', even in practice)
|
|
||||||
|
|
||||||
if (strncmp(str, "package:", 8)) {
|
|
||||||
// Does not start with "package:"
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *s = str + 8;
|
|
||||||
size_t len = strcspn(s, " \r\n");
|
|
||||||
s[len] = '\0';
|
|
||||||
|
|
||||||
char *p = strrchr(s, '=');
|
|
||||||
if (!p) {
|
|
||||||
// No '=' found
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Truncate at the last '='
|
|
||||||
*p = '\0';
|
|
||||||
|
|
||||||
return strdup(s);
|
|
||||||
}
|
|
||||||
|
@ -27,15 +27,4 @@ sc_adb_parse_devices(char *str, struct sc_vec_adb_devices *out_vec);
|
|||||||
char *
|
char *
|
||||||
sc_adb_parse_device_ip(char *str);
|
sc_adb_parse_device_ip(char *str);
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the package path from the output of
|
|
||||||
* `adb shell pm list packages -f <package>`
|
|
||||||
*
|
|
||||||
* The parameter must be a NUL-terminated string.
|
|
||||||
*
|
|
||||||
* Warning: this function modifies the buffer for optimization purposes.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
sc_adb_parse_installed_apk_path(char *str);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -98,7 +98,7 @@ sc_clock_update(struct sc_clock *clock, sc_tick system, sc_tick stream) {
|
|||||||
sc_clock_estimate(clock, &clock->slope, &clock->offset);
|
sc_clock_estimate(clock, &clock->slope, &clock->offset);
|
||||||
|
|
||||||
#ifndef SC_CLOCK_NDEBUG
|
#ifndef SC_CLOCK_NDEBUG
|
||||||
LOGD("Clock estimation: %g * pts + %" PRItick,
|
LOGD("Clock estimation: %f * pts + %" PRItick,
|
||||||
clock->slope, clock->offset);
|
clock->slope, clock->offset);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
|
|||||||
if (id == POINTER_ID_MOUSE || id == POINTER_ID_VIRTUAL_FINGER) {
|
if (id == POINTER_ID_MOUSE || id == POINTER_ID_VIRTUAL_FINGER) {
|
||||||
// string pointer id
|
// string pointer id
|
||||||
LOG_CMSG("touch [id=%s] %-4s position=%" PRIi32 ",%" PRIi32
|
LOG_CMSG("touch [id=%s] %-4s position=%" PRIi32 ",%" PRIi32
|
||||||
" pressure=%g buttons=%06lx",
|
" pressure=%f buttons=%06lx",
|
||||||
id == POINTER_ID_MOUSE ? "mouse" : "vfinger",
|
id == POINTER_ID_MOUSE ? "mouse" : "vfinger",
|
||||||
MOTIONEVENT_ACTION_LABEL(action),
|
MOTIONEVENT_ACTION_LABEL(action),
|
||||||
msg->inject_touch_event.position.point.x,
|
msg->inject_touch_event.position.point.x,
|
||||||
@ -180,7 +180,7 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
|
|||||||
} else {
|
} else {
|
||||||
// numeric pointer id
|
// numeric pointer id
|
||||||
LOG_CMSG("touch [id=%" PRIu64_ "] %-4s position=%" PRIi32 ",%"
|
LOG_CMSG("touch [id=%" PRIu64_ "] %-4s position=%" PRIi32 ",%"
|
||||||
PRIi32 " pressure=%g buttons=%06lx",
|
PRIi32 " pressure=%f buttons=%06lx",
|
||||||
id,
|
id,
|
||||||
MOTIONEVENT_ACTION_LABEL(action),
|
MOTIONEVENT_ACTION_LABEL(action),
|
||||||
msg->inject_touch_event.position.point.x,
|
msg->inject_touch_event.position.point.x,
|
||||||
|
@ -37,8 +37,8 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
|
|||||||
// CK...... ........ ........ ........ ........ ........ ........ ........
|
// CK...... ........ ........ ........ ........ ........ ........ ........
|
||||||
// ^^<------------------------------------------------------------------->
|
// ^^<------------------------------------------------------------------->
|
||||||
// || PTS
|
// || PTS
|
||||||
// | `- config packet
|
// | `- key frame
|
||||||
// `-- key frame
|
// `-- config packet
|
||||||
|
|
||||||
uint8_t header[SC_PACKET_HEADER_SIZE];
|
uint8_t header[SC_PACKET_HEADER_SIZE];
|
||||||
ssize_t r = net_recv_all(demuxer->socket, header, SC_PACKET_HEADER_SIZE);
|
ssize_t r = net_recv_all(demuxer->socket, header, SC_PACKET_HEADER_SIZE);
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
#ifndef STREAM_H
|
|
||||||
#define STREAM_H
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
|
|
||||||
#include "trait/packet_sink.h"
|
|
||||||
#include "util/net.h"
|
|
||||||
#include "util/thread.h"
|
|
||||||
|
|
||||||
#define STREAM_MAX_SINKS 2
|
|
||||||
|
|
||||||
struct stream {
|
|
||||||
sc_socket socket;
|
|
||||||
sc_thread thread;
|
|
||||||
|
|
||||||
struct sc_packet_sink *sinks[STREAM_MAX_SINKS];
|
|
||||||
unsigned sink_count;
|
|
||||||
|
|
||||||
AVCodecContext *codec_ctx;
|
|
||||||
AVCodecParserContext *parser;
|
|
||||||
// successive packets may need to be concatenated, until a non-config
|
|
||||||
// packet is available
|
|
||||||
AVPacket *pending;
|
|
||||||
|
|
||||||
const struct stream_callbacks *cbs;
|
|
||||||
void *cbs_userdata;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stream_callbacks {
|
|
||||||
void (*on_eos)(struct stream *stream, void *userdata);
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
stream_init(struct stream *stream, sc_socket socket,
|
|
||||||
const struct stream_callbacks *cbs, void *cbs_userdata);
|
|
||||||
|
|
||||||
void
|
|
||||||
stream_add_sink(struct stream *stream, struct sc_packet_sink *sink);
|
|
||||||
|
|
||||||
bool
|
|
||||||
stream_start(struct stream *stream);
|
|
||||||
|
|
||||||
void
|
|
||||||
stream_join(struct stream *stream);
|
|
||||||
|
|
||||||
#endif
|
|
@ -23,6 +23,11 @@ read_string(libusb_device_handle *handle, uint8_t desc_index) {
|
|||||||
|
|
||||||
// When non-negative, 'result' contains the number of bytes written
|
// When non-negative, 'result' contains the number of bytes written
|
||||||
char *s = malloc(result + 1);
|
char *s = malloc(result + 1);
|
||||||
|
if (!s) {
|
||||||
|
LOG_OOM();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(s, buffer, result);
|
memcpy(s, buffer, result);
|
||||||
s[result] = '\0';
|
s[result] = '\0';
|
||||||
return s;
|
return s;
|
||||||
|
@ -3,11 +3,10 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL2/SDL_platform.h>
|
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef _WIN32
|
||||||
# include <ws2tcpip.h>
|
# include <ws2tcpip.h>
|
||||||
typedef int socklen_t;
|
typedef int socklen_t;
|
||||||
typedef SOCKET sc_raw_socket;
|
typedef SOCKET sc_raw_socket;
|
||||||
@ -29,7 +28,7 @@
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
net_init(void) {
|
net_init(void) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef _WIN32
|
||||||
WSADATA wsa;
|
WSADATA wsa;
|
||||||
int res = WSAStartup(MAKEWORD(2, 2), &wsa) < 0;
|
int res = WSAStartup(MAKEWORD(2, 2), &wsa) < 0;
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
@ -42,14 +41,14 @@ net_init(void) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
net_cleanup(void) {
|
net_cleanup(void) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef _WIN32
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline sc_socket
|
static inline sc_socket
|
||||||
wrap(sc_raw_socket sock) {
|
wrap(sc_raw_socket sock) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef _WIN32
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
return SC_SOCKET_NONE;
|
return SC_SOCKET_NONE;
|
||||||
}
|
}
|
||||||
@ -72,7 +71,7 @@ wrap(sc_raw_socket sock) {
|
|||||||
|
|
||||||
static inline sc_raw_socket
|
static inline sc_raw_socket
|
||||||
unwrap(sc_socket socket) {
|
unwrap(sc_socket socket) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef _WIN32
|
||||||
if (socket == SC_SOCKET_NONE) {
|
if (socket == SC_SOCKET_NONE) {
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
@ -248,7 +247,7 @@ net_interrupt(sc_socket socket) {
|
|||||||
|
|
||||||
sc_raw_socket raw_sock = unwrap(socket);
|
sc_raw_socket raw_sock = unwrap(socket);
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef _WIN32
|
||||||
if (!atomic_flag_test_and_set(&socket->closed)) {
|
if (!atomic_flag_test_and_set(&socket->closed)) {
|
||||||
return !closesocket(raw_sock);
|
return !closesocket(raw_sock);
|
||||||
}
|
}
|
||||||
@ -262,7 +261,7 @@ bool
|
|||||||
net_close(sc_socket socket) {
|
net_close(sc_socket socket) {
|
||||||
sc_raw_socket raw_sock = unwrap(socket);
|
sc_raw_socket raw_sock = unwrap(socket);
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef _WIN32
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
if (!atomic_flag_test_and_set(&socket->closed)) {
|
if (!atomic_flag_test_and_set(&socket->closed)) {
|
||||||
ret = !closesocket(raw_sock);
|
ret = !closesocket(raw_sock);
|
||||||
|
@ -5,9 +5,8 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <SDL2/SDL_platform.h>
|
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef _WIN32
|
||||||
|
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
# include <stdatomic.h>
|
# include <stdatomic.h>
|
||||||
@ -17,7 +16,7 @@
|
|||||||
atomic_flag closed;
|
atomic_flag closed;
|
||||||
} *sc_socket;
|
} *sc_socket;
|
||||||
|
|
||||||
#else // not __WINDOWS__
|
#else // not _WIN32
|
||||||
|
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
# define SC_SOCKET_NONE -1
|
# define SC_SOCKET_NONE -1
|
||||||
|
@ -241,28 +241,6 @@ static void test_get_ip_truncated(void) {
|
|||||||
assert(!ip);
|
assert(!ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_apk_path(void) {
|
|
||||||
char str[] = "package:/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile."
|
|
||||||
"scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk=com.genymobile."
|
|
||||||
"scrcpy\n";
|
|
||||||
|
|
||||||
const char *expected = "/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile"
|
|
||||||
".scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk";
|
|
||||||
char *path = sc_adb_parse_installed_apk_path(str);
|
|
||||||
assert(!strcmp(path, expected));
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_apk_path_invalid(void) {
|
|
||||||
// Does not start with "package:"
|
|
||||||
char str[] = "garbage:/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile."
|
|
||||||
"scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk=com.genymobile."
|
|
||||||
"scrcpy\n";
|
|
||||||
|
|
||||||
char *path = sc_adb_parse_installed_apk_path(str);
|
|
||||||
assert(!path);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
(void) argc;
|
(void) argc;
|
||||||
(void) argv;
|
(void) argv;
|
||||||
@ -285,8 +263,5 @@ int main(int argc, char *argv[]) {
|
|||||||
test_get_ip_no_wlan_without_eol();
|
test_get_ip_no_wlan_without_eol();
|
||||||
test_get_ip_truncated();
|
test_get_ip_truncated();
|
||||||
|
|
||||||
test_apk_path();
|
|
||||||
test_apk_path_invalid();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
||||||
testImplementation 'junit:junit:4.13.1'
|
testImplementation 'junit:junit:4.13.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user