Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
57687bdfcd |
@ -34,7 +34,7 @@ WIN32_TARGET := $(WIN32_TARGET_DIR)-$(VERSION).zip
|
||||
WIN64_TARGET := $(WIN64_TARGET_DIR)-$(VERSION).zip
|
||||
|
||||
release: clean zip-win32 zip-win64 sums
|
||||
@echo "Windows archives generated in $(DIST)/"
|
||||
@echo "Release created in $(DIST)/."
|
||||
|
||||
clean:
|
||||
$(GRADLE) clean
|
||||
|
@ -162,7 +162,7 @@ It is possible to record the screen while mirroring:
|
||||
|
||||
```bash
|
||||
scrcpy --record file.mp4
|
||||
scrcpy -r file.mkv
|
||||
scrcpy -r file.mp4
|
||||
```
|
||||
|
||||
"Skipped frames" are recorded, even if they are not displayed in real time (for
|
||||
|
@ -3,33 +3,33 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
#include <SDL2/SDL_platform.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
# include <winsock2.h> // not needed here, but must never be included AFTER windows.h
|
||||
# include <windows.h>
|
||||
# define PRIexitcode "lu"
|
||||
// <https://stackoverflow.com/a/44383330/1987178>
|
||||
#ifdef _WIN32
|
||||
# define PRIexitcode "lu"
|
||||
# ifdef _WIN64
|
||||
# define PRIsizet PRIu64
|
||||
# else
|
||||
# define PRIsizet PRIu32
|
||||
# endif
|
||||
#else
|
||||
# define PRIsizet "zu"
|
||||
# define PRIexitcode "d"
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
# include <winsock2.h> // not needed here, but must never be included AFTER windows.h
|
||||
# include <windows.h>
|
||||
# define PROCESS_NONE NULL
|
||||
typedef HANDLE process_t;
|
||||
typedef DWORD exit_code_t;
|
||||
|
||||
#else
|
||||
|
||||
# include <sys/types.h>
|
||||
# define PRIsizet "zu"
|
||||
# define PRIexitcode "d"
|
||||
# define PROCESS_NONE -1
|
||||
typedef pid_t process_t;
|
||||
typedef int exit_code_t;
|
||||
|
||||
#endif
|
||||
|
||||
# define NO_EXIT_CODE -1
|
||||
|
||||
enum process_result {
|
||||
|
@ -7,13 +7,11 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "recorder.h"
|
||||
|
||||
struct args {
|
||||
const char *serial;
|
||||
const char *crop;
|
||||
const char *record_filename;
|
||||
enum recorder_format record_format;
|
||||
SDL_bool fullscreen;
|
||||
SDL_bool help;
|
||||
SDL_bool version;
|
||||
@ -44,9 +42,6 @@ static void usage(const char *arg0) {
|
||||
" -f, --fullscreen\n"
|
||||
" Start in fullscreen.\n"
|
||||
"\n"
|
||||
" -F, --record-format\n"
|
||||
" Force recording format (either mp4 or mkv).\n"
|
||||
"\n"
|
||||
" -h, --help\n"
|
||||
" Print this help.\n"
|
||||
"\n"
|
||||
@ -62,8 +57,6 @@ static void usage(const char *arg0) {
|
||||
"\n"
|
||||
" -r, --record file.mp4\n"
|
||||
" Record screen to file.\n"
|
||||
" The format is determined by the -F/--record-format option if\n"
|
||||
" set, or by the file extension (.mp4 or .mkv).\n"
|
||||
"\n"
|
||||
" -s, --serial\n"
|
||||
" The device serial number. Mandatory only if several devices\n"
|
||||
@ -215,36 +208,6 @@ static SDL_bool parse_port(char *optarg, Uint16 *port) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
parse_record_format(const char *optarg, enum recorder_format *format) {
|
||||
if (!strcmp(optarg, "mp4")) {
|
||||
*format = RECORDER_FORMAT_MP4;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
if (!strcmp(optarg, "mkv")) {
|
||||
*format = RECORDER_FORMAT_MKV;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
LOGE("Unsupported format: %s (expected mp4 or mkv)", optarg);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static enum recorder_format
|
||||
guess_record_format(const char *filename) {
|
||||
size_t len = strlen(filename);
|
||||
if (len < 4) {
|
||||
return 0;
|
||||
}
|
||||
const char *ext = &filename[len - 4];
|
||||
if (!strcmp(ext, ".mp4")) {
|
||||
return RECORDER_FORMAT_MP4;
|
||||
}
|
||||
if (!strcmp(ext, ".mkv")) {
|
||||
return RECORDER_FORMAT_MKV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_bool parse_args(struct args *args, int argc, char *argv[]) {
|
||||
static const struct option long_options[] = {
|
||||
{"always-on-top", no_argument, NULL, 'T'},
|
||||
@ -255,14 +218,13 @@ static SDL_bool parse_args(struct args *args, int argc, char *argv[]) {
|
||||
{"max-size", required_argument, NULL, 'm'},
|
||||
{"port", required_argument, NULL, 'p'},
|
||||
{"record", required_argument, NULL, 'r'},
|
||||
{"record-format", required_argument, NULL, 'f'},
|
||||
{"serial", required_argument, NULL, 's'},
|
||||
{"show-touches", no_argument, NULL, 't'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{NULL, 0, NULL, 0 },
|
||||
};
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "b:c:fF:hm:p:r:s:tTv", long_options, NULL)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "b:c:fhm:p:r:s:tTv", long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
if (!parse_bit_rate(optarg, &args->bit_rate)) {
|
||||
@ -275,11 +237,6 @@ static SDL_bool parse_args(struct args *args, int argc, char *argv[]) {
|
||||
case 'f':
|
||||
args->fullscreen = SDL_TRUE;
|
||||
break;
|
||||
case 'F':
|
||||
if (!parse_record_format(optarg, &args->record_format)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
args->help = SDL_TRUE;
|
||||
break;
|
||||
@ -319,21 +276,6 @@ static SDL_bool parse_args(struct args *args, int argc, char *argv[]) {
|
||||
LOGE("Unexpected additional argument: %s", argv[index]);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (args->record_format && !args->record_filename) {
|
||||
LOGE("Record format specified without recording");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (args->record_filename && !args->record_format) {
|
||||
args->record_format = guess_record_format(args->record_filename);
|
||||
if (!args->record_format) {
|
||||
LOGE("No format specified for \"%s\" (try with -F mkv)",
|
||||
args->record_filename);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
@ -348,7 +290,6 @@ int main(int argc, char *argv[]) {
|
||||
.serial = NULL,
|
||||
.crop = NULL,
|
||||
.record_filename = NULL,
|
||||
.record_format = 0,
|
||||
.help = SDL_FALSE,
|
||||
.version = SDL_FALSE,
|
||||
.show_touches = SDL_FALSE,
|
||||
@ -388,7 +329,6 @@ int main(int argc, char *argv[]) {
|
||||
.crop = args.crop,
|
||||
.port = args.port,
|
||||
.record_filename = args.record_filename,
|
||||
.record_format = args.record_format,
|
||||
.max_size = args.max_size,
|
||||
.bit_rate = args.bit_rate,
|
||||
.show_touches = args.show_touches,
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "recorder.h"
|
||||
|
||||
#include <libavutil/time.h>
|
||||
#include <SDL2/SDL_assert.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
@ -16,9 +15,7 @@
|
||||
# define LAVF_NEW_CODEC_API
|
||||
#endif
|
||||
|
||||
static const AVRational SCRCPY_TIME_BASE = {1, 1000000}; // timestamps in us
|
||||
|
||||
static const AVOutputFormat *find_muxer(const char *name) {
|
||||
static const AVOutputFormat *find_mp4_muxer(void) {
|
||||
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 9, 100)
|
||||
void *opaque = NULL;
|
||||
#endif
|
||||
@ -30,13 +27,11 @@ static const AVOutputFormat *find_muxer(const char *name) {
|
||||
oformat = av_oformat_next(oformat);
|
||||
#endif
|
||||
// until null or with name "mp4"
|
||||
} while (oformat && strcmp(oformat->name, name));
|
||||
} while (oformat && strcmp(oformat->name, "mp4"));
|
||||
return oformat;
|
||||
}
|
||||
|
||||
SDL_bool recorder_init(struct recorder *recorder,
|
||||
const char *filename,
|
||||
enum recorder_format format,
|
||||
SDL_bool recorder_init(struct recorder *recorder, const char *filename,
|
||||
struct size declared_frame_size) {
|
||||
recorder->filename = SDL_strdup(filename);
|
||||
if (!recorder->filename) {
|
||||
@ -44,7 +39,6 @@ SDL_bool recorder_init(struct recorder *recorder,
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
recorder->format = format;
|
||||
recorder->declared_frame_size = declared_frame_size;
|
||||
recorder->header_written = SDL_FALSE;
|
||||
|
||||
@ -55,21 +49,10 @@ void recorder_destroy(struct recorder *recorder) {
|
||||
SDL_free(recorder->filename);
|
||||
}
|
||||
|
||||
static const char *
|
||||
recorder_get_format_name(enum recorder_format format) {
|
||||
switch (format) {
|
||||
case RECORDER_FORMAT_MP4: return "mp4";
|
||||
case RECORDER_FORMAT_MKV: return "matroska";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool recorder_open(struct recorder *recorder, AVCodec *input_codec) {
|
||||
const char *format_name = recorder_get_format_name(recorder->format);
|
||||
SDL_assert(format_name);
|
||||
const AVOutputFormat *format = find_muxer(format_name);
|
||||
if (!format) {
|
||||
LOGE("Could not find muxer");
|
||||
const AVOutputFormat *mp4 = find_mp4_muxer();
|
||||
if (!mp4) {
|
||||
LOGE("Could not find mp4 muxer");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
@ -83,7 +66,7 @@ SDL_bool recorder_open(struct recorder *recorder, AVCodec *input_codec) {
|
||||
// returns (on purpose) a pointer-to-const, but AVFormatContext.oformat
|
||||
// still expects a pointer-to-non-const (it has not be updated accordingly)
|
||||
// <https://github.com/FFmpeg/FFmpeg/commit/0694d8702421e7aff1340038559c438b61bb30dd>
|
||||
recorder->ctx->oformat = (AVOutputFormat *) format;
|
||||
recorder->ctx->oformat = (AVOutputFormat *) mp4;
|
||||
|
||||
AVStream *ostream = avformat_new_stream(recorder->ctx, input_codec);
|
||||
if (!ostream) {
|
||||
@ -104,6 +87,7 @@ SDL_bool recorder_open(struct recorder *recorder, AVCodec *input_codec) {
|
||||
ostream->codec->width = recorder->declared_frame_size.width;
|
||||
ostream->codec->height = recorder->declared_frame_size.height;
|
||||
#endif
|
||||
ostream->time_base = (AVRational) {1, 1000000}; // timestamps in us
|
||||
|
||||
int ret = avio_open(&recorder->ctx->pb, recorder->filename,
|
||||
AVIO_FLAG_WRITE);
|
||||
@ -114,8 +98,6 @@ SDL_bool recorder_open(struct recorder *recorder, AVCodec *input_codec) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
LOGI("Recording started to %s file: %s", format_name, recorder->filename);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
@ -126,16 +108,12 @@ void recorder_close(struct recorder *recorder) {
|
||||
}
|
||||
avio_close(recorder->ctx->pb);
|
||||
avformat_free_context(recorder->ctx);
|
||||
|
||||
const char *format_name = recorder_get_format_name(recorder->format);
|
||||
LOGI("Recording complete to %s file: %s", format_name, recorder->filename);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
recorder_write_header(struct recorder *recorder, AVPacket *packet) {
|
||||
SDL_bool recorder_write_header(struct recorder *recorder, AVPacket *packet) {
|
||||
AVStream *ostream = recorder->ctx->streams[0];
|
||||
|
||||
uint8_t *extradata = av_malloc(packet->size * sizeof(uint8_t));
|
||||
uint8_t *extradata = SDL_malloc(packet->size * sizeof(uint8_t));
|
||||
if (!extradata) {
|
||||
LOGC("Cannot allocate extradata");
|
||||
return SDL_FALSE;
|
||||
@ -164,12 +142,6 @@ recorder_write_header(struct recorder *recorder, AVPacket *packet) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
recorder_rescale_packet(struct recorder *recorder, AVPacket *packet) {
|
||||
AVStream *ostream = recorder->ctx->streams[0];
|
||||
av_packet_rescale_ts(packet, SCRCPY_TIME_BASE, ostream->time_base);
|
||||
}
|
||||
|
||||
SDL_bool recorder_write(struct recorder *recorder, AVPacket *packet) {
|
||||
if (!recorder->header_written) {
|
||||
SDL_bool ok = recorder_write_header(recorder, packet);
|
||||
@ -179,6 +151,5 @@ SDL_bool recorder_write(struct recorder *recorder, AVPacket *packet) {
|
||||
recorder->header_written = SDL_TRUE;
|
||||
}
|
||||
|
||||
recorder_rescale_packet(recorder, packet);
|
||||
return av_write_frame(recorder->ctx, packet) >= 0;
|
||||
}
|
||||
|
@ -6,24 +6,15 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
enum recorder_format {
|
||||
RECORDER_FORMAT_MP4 = 1,
|
||||
RECORDER_FORMAT_MKV,
|
||||
};
|
||||
|
||||
struct recorder {
|
||||
char *filename;
|
||||
enum recorder_format format;
|
||||
AVFormatContext *ctx;
|
||||
struct size declared_frame_size;
|
||||
SDL_bool header_written;
|
||||
};
|
||||
|
||||
SDL_bool recorder_init(struct recorder *recoder,
|
||||
const char *filename,
|
||||
enum recorder_format format,
|
||||
SDL_bool recorder_init(struct recorder *recoder, const char *filename,
|
||||
struct size declared_frame_size);
|
||||
|
||||
void recorder_destroy(struct recorder *recorder);
|
||||
|
||||
SDL_bool recorder_open(struct recorder *recorder, AVCodec *input_codec);
|
||||
|
@ -229,10 +229,7 @@ SDL_bool scrcpy(const struct scrcpy_options *options) {
|
||||
|
||||
struct recorder *rec = NULL;
|
||||
if (options->record_filename) {
|
||||
if (!recorder_init(&recorder,
|
||||
options->record_filename,
|
||||
options->record_format,
|
||||
frame_size)) {
|
||||
if (!recorder_init(&recorder, options->record_filename, frame_size)) {
|
||||
ret = SDL_FALSE;
|
||||
server_stop(&server);
|
||||
goto finally_destroy_file_handler;
|
||||
|
@ -2,13 +2,11 @@
|
||||
#define SCRCPY_H
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
#include <recorder.h>
|
||||
|
||||
struct scrcpy_options {
|
||||
const char *serial;
|
||||
const char *crop;
|
||||
const char *record_filename;
|
||||
enum recorder_format record_format;
|
||||
Uint16 port;
|
||||
Uint16 max_size;
|
||||
Uint32 bit_rate;
|
||||
|
@ -3,11 +3,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
# include <tchar.h>
|
||||
#endif
|
||||
|
||||
size_t xstrncpy(char *dest, const char *src, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n - 1 && src[i] != '\0'; ++i)
|
||||
@ -52,22 +47,3 @@ char *strquote(const char *src) {
|
||||
quoted[len + 2] = '\0';
|
||||
return quoted;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
wchar_t *utf8_to_wide_char(const char *utf8) {
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
|
||||
if (!len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t *wide = malloc(len * sizeof(wchar_t));
|
||||
if (!wide) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wide, len);
|
||||
return wide;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -20,10 +20,4 @@ size_t xstrjoin(char *dst, const char *const tokens[], char sep, size_t n);
|
||||
// returns the new allocated string, to be freed by the caller
|
||||
char *strquote(const char *src);
|
||||
|
||||
#ifdef _WIN32
|
||||
// convert a UTF-8 string to a wchar_t string
|
||||
// returns the new allocated string, to be freed by the caller
|
||||
wchar_t *utf8_to_wide_char(const char *utf8);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -18,7 +18,7 @@ static int build_cmd(char *cmd, size_t len, const char *const argv[]) {
|
||||
}
|
||||
|
||||
enum process_result cmd_execute(const char *path, const char *const argv[], HANDLE *handle) {
|
||||
STARTUPINFOW si;
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
@ -29,19 +29,12 @@ enum process_result cmd_execute(const char *path, const char *const argv[], HAND
|
||||
return PROCESS_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
wchar_t *wide = utf8_to_wide_char(cmd);
|
||||
if (!wide) {
|
||||
LOGC("Cannot allocate wide char string");
|
||||
return PROCESS_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
#ifdef WINDOWS_NOCONSOLE
|
||||
int flags = CREATE_NO_WINDOW;
|
||||
#else
|
||||
int flags = 0;
|
||||
#endif
|
||||
if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi)) {
|
||||
free(wide);
|
||||
if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi)) {
|
||||
*handle = NULL;
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||
return PROCESS_ERROR_MISSING_BINARY;
|
||||
@ -49,7 +42,6 @@ enum process_result cmd_execute(const char *path, const char *const argv[], HAND
|
||||
return PROCESS_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
free(wide);
|
||||
*handle = pi.hProcess;
|
||||
return PROCESS_SUCCESS;
|
||||
}
|
||||
|
@ -87,13 +87,13 @@ static void test_serialize_mouse_event(void) {
|
||||
|
||||
unsigned char buf[SERIALIZED_EVENT_MAX_SIZE];
|
||||
int size = control_event_serialize(&event, buf);
|
||||
assert(size == 18);
|
||||
assert(size == 14);
|
||||
|
||||
const unsigned char expected[] = {
|
||||
0x02, // CONTROL_EVENT_TYPE_MOUSE
|
||||
0x00, // AKEY_EVENT_ACTION_DOWN
|
||||
0x00, 0x00, 0x00, 0x01, // AMOTION_EVENT_BUTTON_PRIMARY
|
||||
0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x04, 0x02, // 260 1026
|
||||
0x01, 0x04, 0x04, 0x02, // 260 1026
|
||||
0x04, 0x38, 0x07, 0x80, // 1080 1920
|
||||
};
|
||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||
@ -120,11 +120,11 @@ static void test_serialize_scroll_event(void) {
|
||||
|
||||
unsigned char buf[SERIALIZED_EVENT_MAX_SIZE];
|
||||
int size = control_event_serialize(&event, buf);
|
||||
assert(size == 21);
|
||||
assert(size == 17);
|
||||
|
||||
const unsigned char expected[] = {
|
||||
0x03, // CONTROL_EVENT_TYPE_SCROLL
|
||||
0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x04, 0x02, // 260 1026
|
||||
0x01, 0x04, 0x04, 0x02, // 260 1026
|
||||
0x04, 0x38, 0x07, 0x80, // 1080 1920
|
||||
0x00, 0x00, 0x00, 0x01, // 1
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // -1
|
||||
|
@ -1,5 +1,5 @@
|
||||
project('scrcpy', 'c',
|
||||
version: '1.7',
|
||||
version: '1.6',
|
||||
meson_version: '>= 0.37',
|
||||
default_options: 'c_std=c11')
|
||||
|
||||
|
35
release.sh
35
release.sh
@ -1,35 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# build and test locally
|
||||
BUILDDIR=build_release
|
||||
rm -rf "$BUILDDIR"
|
||||
meson "$BUILDDIR" --buildtype release --strip -Db_lto=true
|
||||
cd "$BUILDDIR"
|
||||
ninja
|
||||
ninja test
|
||||
cd -
|
||||
|
||||
# build Windows releases
|
||||
make -f Makefile.CrossWindows
|
||||
|
||||
# the generated server must be the same everywhere
|
||||
cmp "$BUILDDIR/server/scrcpy-server.jar" dist/scrcpy-win32/scrcpy-server.jar
|
||||
cmp "$BUILDDIR/server/scrcpy-server.jar" dist/scrcpy-win64/scrcpy-server.jar
|
||||
|
||||
# get version name
|
||||
TAG=$(git describe --tags --always)
|
||||
|
||||
# create release directory
|
||||
mkdir -p "release-$TAG"
|
||||
cp "$BUILDDIR/server/scrcpy-server.jar" "release-$TAG/scrcpy-server-$TAG.jar"
|
||||
cp "dist/scrcpy-win32-$TAG.zip" "release-$TAG/"
|
||||
cp "dist/scrcpy-win64-$TAG.zip" "release-$TAG/"
|
||||
|
||||
# generate checksums
|
||||
cd "release-$TAG"
|
||||
sha256sum "scrcpy-server-$TAG.jar" \
|
||||
"scrcpy-win32-$TAG.zip" \
|
||||
"scrcpy-win64-$TAG.zip" > SHA256SUMS.txt
|
||||
|
||||
echo "Release generated in release-$TAG/"
|
@ -6,8 +6,8 @@ android {
|
||||
applicationId "com.genymobile.scrcpy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 27
|
||||
versionCode 8
|
||||
versionName "1.7"
|
||||
versionCode 7
|
||||
versionName "1.6"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
|
Reference in New Issue
Block a user