Working version

This commit is contained in:
Wirtos_new 2021-06-17 09:13:02 +03:00
parent 1f6f68dba4
commit 108f785c12
17 changed files with 97 additions and 123 deletions

View file

@ -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

View file

@ -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>
)

View file

@ -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

View file

@ -2,6 +2,7 @@
#include <string.h>
#include "config.h"
#include "util/buffer_util.h"
#include "util/log.h"

View file

@ -3,6 +3,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "config.h"

View file

@ -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

View file

@ -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;

View file

@ -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"

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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) {

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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), \

View file

@ -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