mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-04-21 03:55:05 +00:00
Working version
This commit is contained in:
parent
1f6f68dba4
commit
108f785c12
17 changed files with 97 additions and 123 deletions
|
@ -1,66 +0,0 @@
|
|||
# Generated from CLion C/C++ Code Style settings
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignOperands: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 0
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 4
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: All
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 0
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
|
@ -1,8 +1,19 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
project(scrcpy C)
|
||||
project(scrcpy LANGUAGES C VERSION 1.17)
|
||||
|
||||
set(SCRCPY_VERSION ${PROJECT_VERSION})
|
||||
|
||||
option(PORTABLE "Whether should search scrcpy-server in the same dir" ON)
|
||||
|
||||
configure_file(src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
set(SYSDIR ${CMAKE_CURRENT_LIST_DIR}/src/sys/win/)
|
||||
else ()
|
||||
set(SYSDIR ${CMAKE_CURRENT_LIST_DIR}/src/sys/unix/)
|
||||
endif ()
|
||||
|
||||
|
||||
add_executable(scrcpy
|
||||
src/main.c
|
||||
src/cli.c
|
||||
|
@ -27,16 +38,29 @@ add_executable(scrcpy
|
|||
src/video_buffer.c
|
||||
src/util/net.c
|
||||
src/util/str_util.c
|
||||
$<$<PLATFORM_ID:Windows>:
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/sys/win/getopt.c
|
||||
>)
|
||||
${SYSDIR}/command.c
|
||||
|
||||
find_package(SDL2 CONFIG REQUIRED)
|
||||
$<$<PLATFORM_ID:Windows>:
|
||||
${SYSDIR}/getopt.c
|
||||
>
|
||||
${CMAKE_CURRENT_BINARY_DIR}/config.h
|
||||
)
|
||||
|
||||
find_package(SDL2 REQUIRED)
|
||||
find_package(FFMPEG COMPONENTS avformat avcodec avutil REQUIRED)
|
||||
|
||||
target_include_directories(scrcpy
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${FFMPEG_INCLUDE_DIRS}
|
||||
$<$<PLATFORM_ID:Windows>:${CMAKE_CURRENT_LIST_DIR}/src/sys/win/>)
|
||||
target_link_libraries(scrcpy SDL2::SDL2 SDL2::SDL2main ${FFMPEG_LIBRARIES})
|
||||
${SYSDIR}
|
||||
)
|
||||
|
||||
target_link_libraries(scrcpy
|
||||
PRIVATE
|
||||
SDL2::SDL2
|
||||
SDL2::SDL2main
|
||||
${FFMPEG_LIBRARIES}
|
||||
$<$<PLATFORM_ID:Windows>:ws2_32>
|
||||
)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
// build a "portable" version (with scrcpy-server accessible from the same
|
||||
// directory as the executable)
|
||||
#cmakedefine01 PORTABLE
|
||||
#cmakedefine PORTABLE
|
||||
|
||||
// the default client TCP port range for the "adb reverse" tunnel
|
||||
// overridden by option --port
|
||||
|
@ -40,7 +40,7 @@
|
|||
// overridden by option --lock-video-orientation
|
||||
#cmakedefine DEFAULT_LOCK_VIDEO_ORIENTATION ${DEFAULT_LOCK_VIDEO_ORIENTATION}
|
||||
#ifndef DEFAULT_LOCK_VIDEO_ORIENTATION
|
||||
#define DEFAULT_LOCK_VIDEO_ORIENTATION -1 /* -1 - unlocked */
|
||||
#define DEFAULT_LOCK_VIDEO_ORIENTATION (-1) /* -1 - unlocked */
|
||||
#endif
|
||||
|
||||
// the default video bitrate, in bits/second
|
||||
|
@ -53,10 +53,10 @@
|
|||
#define HIDPI_SUPPORT ${HIDPI_SUPPORT}
|
||||
|
||||
// run a server debugger and wait for a client to be attached
|
||||
#define SERVER_DEBUGGER ${SERVER_DEBUGGER}
|
||||
#cmakedefine SERVER_DEBUGGER
|
||||
|
||||
// select the debugger method ('old' for Android < 9, 'new' for Android >= 9)
|
||||
#cmakedefine01 SERVER_DEBUGGER_METHOD_NEW
|
||||
#cmakedefine SERVER_DEBUGGER_METHOD_NEW
|
||||
|
||||
|
||||
#endif //SCRCPY_CONFIG_H_IN_H
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "util/buffer_util.h"
|
||||
#include "util/log.h"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ fps_counter_init(struct fps_counter *counter) {
|
|||
}
|
||||
|
||||
counter->thread = NULL;
|
||||
atomic_init(&counter->started, 0);
|
||||
SDL_AtomicSet(&counter->started, 0);
|
||||
// no need to initialize the other fields, they are unused until started
|
||||
|
||||
return true;
|
||||
|
@ -37,12 +37,12 @@ fps_counter_destroy(struct fps_counter *counter) {
|
|||
|
||||
static inline bool
|
||||
is_started(struct fps_counter *counter) {
|
||||
return atomic_load_explicit(&counter->started, memory_order_acquire);
|
||||
return SDL_AtomicGet(&counter->started);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_started(struct fps_counter *counter, bool started) {
|
||||
atomic_store_explicit(&counter->started, started, memory_order_release);
|
||||
SDL_AtomicSet(&counter->started, started);
|
||||
}
|
||||
|
||||
// must be called with mutex locked
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#include <stdint.h>
|
||||
#include <SDL2/SDL_mutex.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
/* todo: this */
|
||||
#define atomic_bool bool
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
@ -17,7 +15,7 @@ struct fps_counter {
|
|||
|
||||
// atomic so that we can check without locking the mutex
|
||||
// if the FPS counter is disabled, we don't want to lock unnecessarily
|
||||
atomic_bool started;
|
||||
SDL_atomic_t started;
|
||||
|
||||
// the following fields are protected by the mutex
|
||||
bool interrupted;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#define SDL_MAIN_HANDLED // avoid link error on Linux Windows Subsystem
|
||||
/*#define SDL_MAIN_HANDLED // avoid link error on Linux Windows Subsystem*/
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "config.h"
|
||||
|
|
|
@ -76,7 +76,7 @@ run_receiver(void *data) {
|
|||
assert(head < DEVICE_MSG_MAX_SIZE);
|
||||
size_t r = net_recv(receiver->control_socket, buf + head,
|
||||
DEVICE_MSG_MAX_SIZE - head);
|
||||
if (r <= 0) {
|
||||
if (!r || r == -1) {
|
||||
LOGD("Receiver stopped");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2,15 +2,13 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <sys/time.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
// not needed here, but winsock2.h must never be included AFTER windows.h
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
@ -74,7 +72,7 @@ BOOL WINAPI windows_ctrl_handler(DWORD ctrl_type) {
|
|||
static bool
|
||||
sdl_init_and_configure(bool display, const char *render_driver,
|
||||
bool disable_screensaver) {
|
||||
uint32_t flags = display ? SDL_INIT_VIDEO : SDL_INIT_EVENTS;
|
||||
uint32_t flags = SDL_INIT_EVENTS | (display ? SDL_INIT_VIDEO : 0);
|
||||
if (SDL_Init(flags)) {
|
||||
LOGC("Could not initialize SDL: %s", SDL_GetError());
|
||||
return false;
|
||||
|
@ -462,6 +460,7 @@ end:
|
|||
if (stream_started) {
|
||||
stream_stop(&stream);
|
||||
}
|
||||
|
||||
if (controller_started) {
|
||||
controller_stop(&controller);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
|
@ -22,6 +21,20 @@
|
|||
#define DEFAULT_SERVER_PATH PREFIX "/share/scrcpy/" SERVER_FILENAME
|
||||
#define DEVICE_SERVER_PATH "/data/local/tmp/scrcpy-server.jar"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <string.h>
|
||||
char *dirname(char *path){
|
||||
char *iter = path, *base = path;
|
||||
while ((iter = strpbrk(iter, "/\\"))){
|
||||
path = iter++;
|
||||
}
|
||||
*path = '\0';
|
||||
return base;
|
||||
}
|
||||
#else
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
static char *
|
||||
get_server_path(void) {
|
||||
#ifdef __WINDOWS__
|
||||
|
@ -359,8 +372,7 @@ server_init(struct server *server) {
|
|||
server->serial = NULL;
|
||||
server->process = PROCESS_NONE;
|
||||
server->wait_server_thread = NULL;
|
||||
atomic_flag_clear_explicit(&server->server_socket_closed,
|
||||
memory_order_relaxed);
|
||||
SDL_AtomicSet(&server->server_socket_closed, 0);
|
||||
|
||||
server->mutex = SDL_CreateMutex();
|
||||
if (!server->mutex) {
|
||||
|
@ -402,7 +414,7 @@ run_wait_server(void *data) {
|
|||
// no need for synchronization, server_socket is initialized before this
|
||||
// thread was created
|
||||
if (server->server_socket != INVALID_SOCKET
|
||||
&& !atomic_flag_test_and_set(&server->server_socket_closed)) {
|
||||
&& !SDL_AtomicSet(&server->server_socket_closed, 1)) {
|
||||
// On Linux, accept() is unblocked by shutdown(), but on Windows, it is
|
||||
// unblocked by closesocket(). Therefore, call both (close_socket()).
|
||||
close_socket(server->server_socket);
|
||||
|
@ -459,7 +471,7 @@ server_start(struct server *server, const char *serial,
|
|||
error2:
|
||||
if (!server->tunnel_forward) {
|
||||
bool was_closed =
|
||||
atomic_flag_test_and_set(&server->server_socket_closed);
|
||||
SDL_AtomicSet(&server->server_socket_closed, 1);
|
||||
// the thread is not started, the flag could not be already set
|
||||
assert(!was_closed);
|
||||
(void) was_closed;
|
||||
|
@ -486,7 +498,7 @@ server_connect_to(struct server *server) {
|
|||
}
|
||||
|
||||
// we don't need the server socket anymore
|
||||
if (!atomic_flag_test_and_set(&server->server_socket_closed)) {
|
||||
if (!SDL_AtomicSet(&server->server_socket_closed, 1)) {
|
||||
// close it from here
|
||||
close_socket(server->server_socket);
|
||||
// otherwise, it is closed by run_wait_server()
|
||||
|
@ -518,7 +530,7 @@ server_connect_to(struct server *server) {
|
|||
void
|
||||
server_stop(struct server *server) {
|
||||
if (server->server_socket != INVALID_SOCKET
|
||||
&& !atomic_flag_test_and_set(&server->server_socket_closed)) {
|
||||
&& !SDL_AtomicSet(&server->server_socket_closed, 1)) {
|
||||
close_socket(server->server_socket);
|
||||
}
|
||||
if (server->video_socket != INVALID_SOCKET) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef SERVER_H
|
||||
#define SERVER_H
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
|
@ -17,7 +16,7 @@ struct server {
|
|||
char *serial;
|
||||
process_t process;
|
||||
SDL_Thread *wait_server_thread;
|
||||
atomic_flag server_socket_closed;
|
||||
SDL_atomic_t server_socket_closed;
|
||||
|
||||
SDL_mutex *mutex;
|
||||
SDL_cond *process_terminated_cond;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL2/SDL_mutex.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "compat.h"
|
||||
|
@ -43,7 +42,7 @@ stream_recv_packet(struct stream *stream, AVPacket *packet) {
|
|||
|
||||
uint64_t pts = buffer_read64be(header);
|
||||
uint32_t len = buffer_read32be(&header[8]);
|
||||
assert(pts == NO_PTS || (pts & 0x8000000000000000) == 0);
|
||||
assert(pts == NO_PTS || (pts >> 63) == 0);
|
||||
assert(len);
|
||||
|
||||
if (av_new_packet(packet, len)) {
|
||||
|
@ -52,7 +51,7 @@ stream_recv_packet(struct stream *stream, AVPacket *packet) {
|
|||
}
|
||||
|
||||
r = net_recv_all(stream->socket, packet->data, len);
|
||||
if (r < 0 || ((uint32_t) r) < len) {
|
||||
if (r == -1 || ((uint32_t) r) < len) {
|
||||
av_packet_unref(packet);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
#include "util/log.h"
|
||||
#include "util/str_util.h"
|
||||
|
||||
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
build_cmd(char *cmd, size_t len, const char *const argv[]) {
|
||||
// Windows command-line parsing is WTF:
|
||||
|
@ -27,7 +32,7 @@ cmd_execute(const char *const argv[], HANDLE *handle) {
|
|||
memset(&si, 0, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
|
||||
char cmd[256];
|
||||
char cmd[512];
|
||||
if (build_cmd(cmd, sizeof(cmd), argv)) {
|
||||
*handle = NULL;
|
||||
return PROCESS_ERROR_GENERIC;
|
||||
|
|
|
@ -60,7 +60,7 @@ read_xpm(char *xpm[]) {
|
|||
(void) chars;
|
||||
|
||||
// init index
|
||||
struct index index[colors];
|
||||
struct index *index = SDL_malloc(sizeof(*index) * colors);
|
||||
for (int i = 0; i < colors; ++i) {
|
||||
const char *line = xpm[1+i];
|
||||
index[i].c = line[0];
|
||||
|
@ -116,5 +116,6 @@ read_xpm(char *xpm[]) {
|
|||
}
|
||||
// make the surface own the raw pixels
|
||||
surface->flags &= ~SDL_PREALLOC;
|
||||
SDL_free(index);
|
||||
return surface;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#define cbuf_take(PCBUF, PITEM) \
|
||||
( \
|
||||
cbuf_is_empty(PCBUF) \
|
||||
(!cbuf_is_empty(PCBUF)) \
|
||||
? ( \
|
||||
*(PITEM) = (PCBUF)->data[(PCBUF)->tail], \
|
||||
(PCBUF)->tail = ((PCBUF)->tail + 1) % cbuf_size_(PCBUF), \
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
(void) ((PQ)->first = (PQ)->last = NULL)
|
||||
|
||||
#define queue_is_empty(PQ) \
|
||||
!(PQ)->first
|
||||
(!(PQ)->first)
|
||||
|
||||
// NEXTFIELD is the field in the ITEM type used for intrusive linked-list
|
||||
//
|
||||
|
@ -50,28 +50,29 @@
|
|||
//
|
||||
|
||||
// push a new item into the queue
|
||||
#define queue_push(PQ, NEXTFIELD, ITEM) \
|
||||
(void) ({ \
|
||||
(ITEM)->NEXTFIELD = NULL; \
|
||||
if (queue_is_empty(PQ)) { \
|
||||
(PQ)->first = (PQ)->last = (ITEM); \
|
||||
} else { \
|
||||
(PQ)->last->NEXTFIELD = (ITEM); \
|
||||
(PQ)->last = (ITEM); \
|
||||
} \
|
||||
})
|
||||
#define queue_push(PQ, NEXTFIELD, ITEM) \
|
||||
(void) ( \
|
||||
(ITEM)->NEXTFIELD = NULL, \
|
||||
(queue_is_empty(PQ)) \
|
||||
? (PQ)->first = (PQ)->last = (ITEM) \
|
||||
: ( \
|
||||
(PQ)->last->NEXTFIELD = (ITEM), \
|
||||
(PQ)->last = (ITEM) \
|
||||
) \
|
||||
\
|
||||
)
|
||||
|
||||
// take the next item and remove it from the queue (the queue must not be empty)
|
||||
// the result is stored in *(PITEM)
|
||||
// (without typeof(), we could not store a local variable having the correct
|
||||
// type so that we can "return" it)
|
||||
#define queue_take(PQ, NEXTFIELD, PITEM) \
|
||||
(void) ({ \
|
||||
assert(!queue_is_empty(PQ)); \
|
||||
*(PITEM) = (PQ)->first; \
|
||||
(PQ)->first = (PQ)->first->NEXTFIELD; \
|
||||
})
|
||||
// no need to update (PQ)->last if the queue is left empty:
|
||||
// (PQ)->last is undefined if !(PQ)->first anyway
|
||||
#define queue_take(PQ, NEXTFIELD, PITEM) \
|
||||
(void) ( \
|
||||
assert(!queue_is_empty(PQ)), \
|
||||
*(PITEM) = (PQ)->first, \
|
||||
(PQ)->first = (PQ)->first->NEXTFIELD \
|
||||
)
|
||||
// no need to update (PQ)->last if the queue is left empty:
|
||||
// (PQ)->last is undefined if !(PQ)->first anyway
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue