Compare commits

...

5 commits

Author SHA1 Message Date
Romain Vimont 20e54a8403 Remove legacy scrcpy icon
Remove the old icon in XPM format and the code to load it.
2021-10-22 18:51:20 +02:00
Romain Vimont 4fc8bdb084 Use the new scrcpy icon
Use the new icon designed by @varlesh:
<https://github.com/Genymobile/scrcpy/pull/1987#issuecomment-949684080>

Attempt to use the SVG, and fallback to PNG.
2021-10-22 18:51:20 +02:00
Romain Vimont 13457884ba Add support for palette icon formats
To support more icon formats.
2021-10-22 18:51:20 +02:00
Romain Vimont c6c1554258 Add icon loader
Add helper to load icons from image files via FFmpeg.
2021-10-22 18:51:20 +02:00
Romain Vimont dffa4e5a24 Extract util function to build a local file path
Finding a local file in the scrcpy directory may be useful for files
other than scrcpy-server in the future.
2021-10-22 18:51:20 +02:00
15 changed files with 389 additions and 228 deletions

View file

@ -9,6 +9,7 @@ src = [
'src/decoder.c',
'src/device_msg.c',
'src/event_converter.c',
'src/icon.c',
'src/file_handler.c',
'src/fps_counter.c',
'src/frame_buffer.c',
@ -20,7 +21,6 @@ src = [
'src/screen.c',
'src/server.c',
'src/stream.c',
'src/tiny_xpm.c',
'src/video_buffer.c',
'src/util/log.c',
'src/util/net.c',
@ -150,6 +150,12 @@ executable('scrcpy', src,
c_args: [])
install_man('scrcpy.1')
install_data('../data/icon.svg',
rename: 'scrcpy.svg',
install_dir: 'share/icons/hicolor/scalable/apps')
install_data('../data/icon_256x256.png',
rename: 'scrcpy.png',
install_dir: 'share/icons/hicolor/256x256/apps')
### TESTS

291
app/src/icon.c Normal file
View file

@ -0,0 +1,291 @@
#include "icon.h"
#include <assert.h>
#include <stdbool.h>
#include <libavformat/avformat.h>
#include <libavutil/pixdesc.h>
#include <libavutil/pixfmt.h>
#include "config.h"
#include "compat.h"
#include "util/log.h"
#include "util/process.h"
#include "util/str_util.h"
static const char *const scrcpy_icons[] = {
#ifdef PORTABLE
"icon.svg",
"icon.png",
#else
PREFIX "/share/icons/hicolor/scalable/apps/scrcpy.svg"
PREFIX "/share/icons/hicolor/256x256/apps/scrcpy.png"
#endif
};
static char *
get_envvar_icon_path(void) {
#ifdef __WINDOWS__
const wchar_t *icon_path_env = _wgetenv(L"SCRCPY_ICON_PATH");
#else
const char *icon_path_env = getenv("SCRCPY_ICON_PATH");
#endif
if (!icon_path_env) {
return NULL;
}
#ifdef __WINDOWS__
char *icon_path = utf8_from_wide_char(icon_path_env);
#else
char *icon_path = strdup(icon_path_env);
#endif
if (!icon_path) {
LOGE("Could not allocate memory");
return NULL;
}
return icon_path;
}
static AVFrame *
decode_image(const char *path) {
// The non-allocation errors are logged in debug mode, because several
// paths might be tested sequentially. If the first fails but the second
// succeeds, then we don't want error messages in the console.
AVFrame *result = NULL;
AVFormatContext *ctx = avformat_alloc_context();
if (!ctx) {
LOGE("Could not allocate image decoder context");
return NULL;
}
if (avformat_open_input(&ctx, path, NULL, NULL) < 0) {
LOGD("Could not open image codec: %s", path);
goto free_ctx;
}
if (avformat_find_stream_info(ctx, NULL) < 0) {
LOGD("Could not find image stream info");
goto close_input;
}
int stream = av_find_best_stream(ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (stream < 0 ) {
LOGD("Could not find best image stream");
goto close_input;
}
AVCodecParameters *params = ctx->streams[stream]->codecpar;
AVCodec *codec = avcodec_find_decoder(params->codec_id);
if (!codec) {
LOGD("Could not find image decoder");
goto close_input;
}
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
if (avcodec_parameters_to_context(codec_ctx, params) < 0) {
LOGD("Could not fill codec context");
goto free_codec_ctx;
}
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
LOGD("Could not open image codec");
goto free_codec_ctx;
}
AVFrame *frame = av_frame_alloc();
if (!frame) {
LOGE("Could not allocate frame");
goto close_codec;
}
AVPacket *packet = av_packet_alloc();
if (!packet) {
LOGE("Could not allocate packet");
av_frame_free(&frame);
goto close_codec;
}
if (av_read_frame(ctx, packet) < 0) {
LOGD("Could not read frame");
av_packet_free(&packet);
av_frame_free(&frame);
goto close_codec;
}
int ret;
if ((ret = avcodec_send_packet(codec_ctx, packet)) < 0) {
LOGD("Could not send icon packet: %d", ret);
av_packet_free(&packet);
av_frame_free(&frame);
goto close_codec;
}
if ((ret = avcodec_receive_frame(codec_ctx, frame)) != 0) {
LOGD("Could not receive icon frame: %d", ret);
av_packet_free(&packet);
av_frame_free(&frame);
goto close_codec;
}
av_packet_free(&packet);
result = frame;
close_codec:
avcodec_close(codec_ctx);
free_codec_ctx:
avcodec_free_context(&codec_ctx);
close_input:
avformat_close_input(&ctx);
free_ctx:
avformat_free_context(ctx);
return result;
}
static SDL_PixelFormatEnum
to_sdl_pixel_format(enum AVPixelFormat fmt) {
switch (fmt) {
case AV_PIX_FMT_RGB24: return SDL_PIXELFORMAT_RGB24;
case AV_PIX_FMT_BGR24: return SDL_PIXELFORMAT_BGR24;
case AV_PIX_FMT_ARGB: return SDL_PIXELFORMAT_ARGB32;
case AV_PIX_FMT_RGBA: return SDL_PIXELFORMAT_RGBA32;
case AV_PIX_FMT_ABGR: return SDL_PIXELFORMAT_ABGR32;
case AV_PIX_FMT_BGRA: return SDL_PIXELFORMAT_BGRA32;
case AV_PIX_FMT_RGB565BE: return SDL_PIXELFORMAT_RGB565;
case AV_PIX_FMT_RGB555BE: return SDL_PIXELFORMAT_RGB555;
case AV_PIX_FMT_BGR565BE: return SDL_PIXELFORMAT_BGR565;
case AV_PIX_FMT_BGR555BE: return SDL_PIXELFORMAT_BGR555;
case AV_PIX_FMT_RGB444BE: return SDL_PIXELFORMAT_RGB444;
case AV_PIX_FMT_BGR444BE: return SDL_PIXELFORMAT_BGR444;
case AV_PIX_FMT_PAL8: return SDL_PIXELFORMAT_INDEX8;
default: return SDL_PIXELFORMAT_UNKNOWN;
}
}
static SDL_Surface *
load_from_path(const char *path) {
AVFrame *frame = decode_image(path);
if (!frame) {
return NULL;
}
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
if (!desc) {
LOGE("Could not get icon format descriptor");
goto error;
}
bool is_packed = !(desc->flags & AV_PIX_FMT_FLAG_PLANAR);
if (!is_packed) {
LOGE("Could not load non-packed icon");
goto error;
}
SDL_PixelFormatEnum format = to_sdl_pixel_format(frame->format);
if (format == SDL_PIXELFORMAT_UNKNOWN) {
LOGE("Unsupported icon pixel format: %s (%d)", desc->name,
frame->format);
goto error;
}
int bits_per_pixel = av_get_bits_per_pixel(desc);
SDL_Surface *surface =
SDL_CreateRGBSurfaceWithFormatFrom(frame->data[0],
frame->width, frame->height,
bits_per_pixel,
frame->linesize[0],
format);
if (!surface) {
LOGE("Could not create icon surface");
goto error;
}
if (frame->format == AV_PIX_FMT_PAL8) {
// Initialize the SDL palette
uint8_t *data = frame->data[1];
SDL_Color colors[256];
for (int i = 0; i < 256; ++i) {
SDL_Color *color = &colors[i];
// The palette is transported in AVFrame.data[1], is 1024 bytes
// long (256 4-byte entries) and is formatted the same as in
// AV_PIX_FMT_RGB32 described above (i.e., it is also
// endian-specific).
// <https://ffmpeg.org/doxygen/4.1/pixfmt_8h.html#a9a8e335cf3be472042bc9f0cf80cd4c5>
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
color->a = data[i * 4];
color->r = data[i * 4 + 1];
color->g = data[i * 4 + 2];
color->b = data[i * 4 + 3];
#else
color->a = data[i * 4 + 3];
color->r = data[i * 4 + 2];
color->g = data[i * 4 + 1];
color->b = data[i * 4];
#endif
}
SDL_Palette *palette = surface->format->palette;
assert(palette);
int ret = SDL_SetPaletteColors(palette, colors, 0, 256);
if (ret) {
LOGE("Could not set palette colors");
goto error;
}
}
surface->userdata = frame; // frame owns the data
return surface;
error:
av_frame_free(&frame);
return NULL;
}
SDL_Surface *
scrcpy_icon_load() {
SDL_Surface *icon = NULL;
char *icon_path = get_envvar_icon_path();
if (icon_path) {
LOGD("Using SCRCPY_ICON_PATH: %s", icon_path);
// An icon path is forced by environment variable
icon = load_from_path(icon_path);
free(icon_path);
// Do not fallback on default path even if icon is NULL
return icon;
}
for (size_t i = 0; i < ARRAY_LEN(scrcpy_icons); ++i) {
#ifndef PORTABLE
icon = load_from_path(scrcpy_icons[i]);
if (icon) {
LOGD("Using icon: %s", scrcpy_icons[i]);
}
#else
icon_path = get_local_file_path(scrcpy_icons[i]);
icon = load_from_path(icon_path);
if (icon) {
LOGD("Using icon (portable): %s", icon_path);
}
free(icon_path);
#endif
}
return icon;
}
void
scrcpy_icon_destroy(SDL_Surface *icon) {
AVFrame *frame = icon->userdata;
assert(frame);
av_frame_free(&frame);
SDL_FreeSurface(icon);
}

16
app/src/icon.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef ICON_H
#define ICON_H
#include "common.h"
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <libavformat/avformat.h>
SDL_Surface *
scrcpy_icon_load(void);
void
scrcpy_icon_destroy(SDL_Surface *icon);
#endif

View file

@ -1,53 +0,0 @@
/* XPM */
static char * icon_xpm[] = {
"48 48 2 1",
" c None",
". c #96C13E",
" .. .. ",
" ... ... ",
" ... ...... ... ",
" ................ ",
" .............. ",
" ................ ",
" .................. ",
" .................... ",
" ..... ........ ..... ",
" ..... ........ ..... ",
" ...................... ",
" ........................ ",
" ........................ ",
" ........................ ",
" ",
" ",
" .... ........................ .... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" ...... ........................ ...... ",
" .... ........................ .... ",
" ........................ ",
" ...................... ",
" ...... ...... ",
" ...... ...... ",
" ...... ...... ",
" ...... ...... ",
" ...... ...... ",
" ...... ...... ",
" ...... ...... ",
" ...... ...... ",
" ...... ...... ",
" .... .... "};

View file

@ -22,7 +22,6 @@
#include "screen.h"
#include "server.h"
#include "stream.h"
#include "tiny_xpm.h"
#include "util/log.h"
#include "util/net.h"
#ifdef HAVE_V4L2

View file

@ -5,9 +5,8 @@
#include <SDL2/SDL.h>
#include "events.h"
#include "icon.xpm"
#include "icon.h"
#include "scrcpy.h"
#include "tiny_xpm.h"
#include "video_buffer.h"
#include "util/log.h"
@ -405,10 +404,10 @@ screen_init(struct screen *screen, const struct screen_params *params) {
LOGD("Trilinear filtering disabled (not an OpenGL renderer)");
}
SDL_Surface *icon = read_xpm(icon_xpm);
SDL_Surface *icon = scrcpy_icon_load();
if (icon) {
SDL_SetWindowIcon(screen->window, icon);
SDL_FreeSurface(icon);
scrcpy_icon_destroy(icon);
} else {
LOGW("Could not load icon");
}

View file

@ -3,7 +3,6 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <libgen.h>
#include <stdio.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_platform.h>
@ -51,48 +50,13 @@ get_server_path(void) {
// the absolute path is hardcoded
return server_path;
#else
// use scrcpy-server in the same directory as the executable
char *executable_path = get_executable_path();
if (!executable_path) {
LOGE("Could not get executable path, "
"using " SERVER_FILENAME " from current directory");
// not found, use current directory
return strdup(SERVER_FILENAME);
}
// dirname() does not work correctly everywhere, so get the parent
// directory manually.
// See <https://github.com/Genymobile/scrcpy/issues/2619>
char *p = strrchr(executable_path, PATH_SEPARATOR);
if (!p) {
LOGE("Unexpected executable path: \"%s\" (it should contain a '%c')",
executable_path, PATH_SEPARATOR);
free(executable_path);
return strdup(SERVER_FILENAME);
}
*p = '\0'; // modify executable_path in place
char *dir = executable_path;
size_t dirlen = strlen(dir);
// sizeof(SERVER_FILENAME) gives statically the size including the null byte
size_t len = dirlen + 1 + sizeof(SERVER_FILENAME);
char *server_path = malloc(len);
char *server_path = get_local_file_path(SERVER_FILENAME);
if (!server_path) {
LOGE("Could not alloc server path string, "
LOGE("Could not get local file path, "
"using " SERVER_FILENAME " from current directory");
free(executable_path);
return strdup(SERVER_FILENAME);
}
memcpy(server_path, dir, dirlen);
server_path[dirlen] = PATH_SEPARATOR;
memcpy(&server_path[dirlen + 1], SERVER_FILENAME, sizeof(SERVER_FILENAME));
// the final null byte has been copied with SERVER_FILENAME
free(executable_path);
LOGD("Using server (portable): %s", server_path);
return server_path;
#endif

View file

@ -1,119 +0,0 @@
#include "tiny_xpm.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "util/log.h"
struct index {
char c;
uint32_t color;
};
static bool
find_color(struct index *index, int len, char c, uint32_t *color) {
// there are typically very few color, so it's ok to iterate over the array
for (int i = 0; i < len; ++i) {
if (index[i].c == c) {
*color = index[i].color;
return true;
}
}
*color = 0;
return false;
}
// We encounter some problems with SDL2_image on MSYS2 (Windows),
// so here is our own XPM parsing not to depend on SDL_image.
//
// We do not hardcode the binary image to keep some flexibility to replace the
// icon easily (just by replacing icon.xpm).
//
// Parameter is not "const char *" because XPM formats are generally stored in a
// (non-const) "char *"
SDL_Surface *
read_xpm(char *xpm[]) {
#ifndef NDEBUG
// patch the XPM to change the icon color in debug mode
xpm[2] = ". c #CC00CC";
#endif
char *endptr;
// *** No error handling, assume the XPM source is valid ***
// (it's in our source repo)
// Assertions are only checked in debug
int width = strtol(xpm[0], &endptr, 10);
int height = strtol(endptr + 1, &endptr, 10);
int colors = strtol(endptr + 1, &endptr, 10);
int chars = strtol(endptr + 1, &endptr, 10);
// sanity checks
assert(0 <= width && width < 256);
assert(0 <= height && height < 256);
assert(0 <= colors && colors < 256);
assert(chars == 1); // this implementation does not support more
(void) chars;
// init index
struct index index[colors];
for (int i = 0; i < colors; ++i) {
const char *line = xpm[1+i];
index[i].c = line[0];
assert(line[1] == '\t');
assert(line[2] == 'c');
assert(line[3] == ' ');
if (line[4] == '#') {
index[i].color = 0xff000000 | strtol(&line[5], &endptr, 0x10);
assert(*endptr == '\0');
} else {
assert(!strcmp("None", &line[4]));
index[i].color = 0;
}
}
// parse image
uint32_t *pixels = SDL_malloc(4 * width * height);
if (!pixels) {
LOGE("Could not allocate icon memory");
return NULL;
}
for (int y = 0; y < height; ++y) {
const char *line = xpm[1 + colors + y];
for (int x = 0; x < width; ++x) {
char c = line[x];
uint32_t color;
bool color_found = find_color(index, colors, c, &color);
assert(color_found);
(void) color_found;
pixels[y * width + x] = color;
}
}
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
uint32_t amask = 0x000000ff;
uint32_t rmask = 0x0000ff00;
uint32_t gmask = 0x00ff0000;
uint32_t bmask = 0xff000000;
#else // little endian, like x86
uint32_t amask = 0xff000000;
uint32_t rmask = 0x00ff0000;
uint32_t gmask = 0x0000ff00;
uint32_t bmask = 0x000000ff;
#endif
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(pixels,
width, height,
32, 4 * width,
rmask, gmask, bmask, amask);
if (!surface) {
LOGE("Could not create icon surface");
return NULL;
}
// make the surface own the raw pixels
surface->flags &= ~SDL_PREALLOC;
return surface;
}

View file

@ -1,11 +0,0 @@
#ifndef TINYXPM_H
#define TINYXPM_H
#include "common.h"
#include <SDL2/SDL.h>
SDL_Surface *
read_xpm(char *xpm[]);
#endif

View file

@ -1,5 +1,6 @@
#include "process.h"
#include <libgen.h>
#include "log.h"
bool
@ -19,3 +20,44 @@ process_check_success(process_t proc, const char *name, bool close) {
}
return true;
}
char *
get_local_file_path(const char *name) {
char *executable_path = get_executable_path();
if (!executable_path) {
return NULL;
}
// dirname() does not work correctly everywhere, so get the parent
// directory manually.
// See <https://github.com/Genymobile/scrcpy/issues/2619>
char *p = strrchr(executable_path, PATH_SEPARATOR);
if (!p) {
LOGE("Unexpected executable path: \"%s\" (it should contain a '%c')",
executable_path, PATH_SEPARATOR);
free(executable_path);
return NULL;
}
*p = '\0'; // modify executable_path in place
char *dir = executable_path;
size_t dirlen = strlen(dir);
size_t namelen = strlen(name);
size_t len = dirlen + namelen + 2; // +2: '/' and '\0'
char *file_path = malloc(len);
if (!file_path) {
LOGE("Could not alloc path");
free(executable_path);
return NULL;
}
memcpy(file_path, dir, dirlen);
file_path[dirlen] = PATH_SEPARATOR;
// namelen + 1 to copy the final '\0'
memcpy(&file_path[dirlen + 1], name, namelen + 1);
free(executable_path);
return file_path;
}

View file

@ -74,6 +74,11 @@ search_executable(const char *file);
char *
get_executable_path(void);
// Return the absolute path of a file in the same directory as he executable.
// May be NULL on error. To be freed by free().
char *
get_local_file_path(const char *name);
// returns true if the file exists and is not a directory
bool
is_regular_file(const char *path);

16
data/icon.svg Normal file
View file

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" version="1.1">
<path style="opacity:0.2" d="m 16.846877,12 c -1.116351,0 -2.227419,0.912229 -2.015075,2 l 3.122973,16 -5.596557,11.109375 C 11.959876,41.871734 11.885244,42.336988 12.177176,43 c 0.278672,0.632897 0.998812,1 1.747448,1 H 24 34.075375 c 0.748637,0 1.468777,-0.367103 1.747448,-1 0.291932,-0.663012 0.217302,-1.128266 -0.181041,-1.890625 L 30.045225,30 33.168198,14 c 0.212344,-1.087771 -0.898724,-2 -2.015075,-2 H 24 Z"/>
<path style="fill:#cccccc" d="m 16.846877,11 c -1.116351,0 -2.227419,0.912229 -2.015075,2 l 3.122973,16 -5.596557,11.109375 C 11.959876,40.871734 11.885244,41.336988 12.177176,42 c 0.278672,0.632897 0.998812,1 1.747448,1 H 24 34.075375 c 0.748637,0 1.468777,-0.367103 1.747448,-1 0.291932,-0.663012 0.217302,-1.128266 -0.181041,-1.890625 L 30.045225,29 33.168198,13 c 0.212344,-1.087771 -0.898724,-2 -2.015075,-2 H 24 Z"/>
<rect style="opacity:0.2" width="40" height="32" x="4" y="6" rx="2" ry="2"/>
<path style="fill:#e4e4e4" d="m 4,33 v 2 c 0,1.108 0.892,2 2,2 h 36 c 1.108,0 2,-0.892 2,-2 v -2 z"/>
<path style="opacity:0.1" d="m 11.494141,15 a 1.5,1.5 0 0 0 -0.832032,0.255859 1.5,1.5 0 0 0 -0.40625,2.082032 l 3.13086,4.654297 C 10.404945,24.606192 8.4012371,28.299159 8.0019531,32.460938 7.9284599,34.000879 9.5546875,34 9.5546875,34 H 38.40625 c 0,0 1.672856,-3.38e-4 1.591797,-1.617188 -0.416529,-4.131451 -2.415618,-7.796833 -5.380859,-10.394531 l 3.126953,-4.65039 a 1.5,1.5 0 0 0 -0.40625,-2.082032 1.5,1.5 0 0 0 -1.125,-0.228515 1.5,1.5 0 0 0 -0.957032,0.634765 l -3.072265,4.566407 C 29.78649,18.814887 26.990024,18 24.001953,18 c -2.989385,0 -5.786177,0.815488 -8.183594,2.230469 l -3.074218,-4.56836 A 1.5,1.5 0 0 0 11.787109,15.027344 1.5,1.5 0 0 0 11.494141,15 Z"/>
<path style="fill:#077063" d="M 6,5 C 4.892,5 4,5.892 4,7 V 33 H 44 V 7 C 44,5.892 43.108,5 42,5 Z"/>
<path style="opacity:0.1;fill:#ffffff" d="M 6,5 C 4.892,5 4,5.892 4,7 V 8 C 4,6.892 4.892,6 6,6 h 36 c 1.108,0 2,0.892 2,2 V 7 C 44,5.892 43.108,5 42,5 Z"/>
<path style="fill:none;stroke:#30dd81;stroke-width:3;stroke-linecap:round" d="M 15.1998,21.000026 11.5,15.5"/>
<path style="fill:none;stroke:#30dd81;stroke-width:3;stroke-linecap:round" d="M 32.799764,21.000026 36.5,15.5"/>
<path style="fill:#30dd81" d="m 24.002386,17.000034 c -8.355868,0 -15.2214979,6.346843 -15.9999669,14.460906 C 7.9289259,33.000882 9.5544999,33 9.5544999,33 H 38.406003 c 0,0 1.672201,-3.35e-4 1.591142,-1.617185 C 39.182807,23.305596 32.331836,17.000034 24.002386,17.000034 Z"/>
<path style="opacity:0.2" d="m 16,25 a 1.9999959,1.9999959 0 0 0 -2,2 1.9999959,1.9999959 0 0 0 2,2 1.9999959,1.9999959 0 0 0 2,-2 1.9999959,1.9999959 0 0 0 -2,-2 z m 16,0 a 1.9999959,1.9999959 0 0 0 -2,2 1.9999959,1.9999959 0 0 0 2,2 1.9999959,1.9999959 0 0 0 2,-2 1.9999959,1.9999959 0 0 0 -2,-2 z"/>
<path style="fill:#ffffff" d="M 15.999996,24.000008 A 1.9999959,1.9999959 0 0 1 17.999992,26.000004 1.9999959,1.9999959 0 0 1 15.999996,28 1.9999959,1.9999959 0 0 1 14,26.000004 1.9999959,1.9999959 0 0 1 15.999996,24.000008 Z"/>
<path style="fill:#ffffff" d="M 31.999996,24.000008 A 1.9999959,1.9999959 0 0 1 33.999991,26.000004 1.9999959,1.9999959 0 0 1 31.999996,28 1.9999959,1.9999959 0 0 1 30,26.000004 1.9999959,1.9999959 0 0 1 31.999996,24.000008 Z"/>
<path style="fill:#ffffff;opacity:0.2" d="M 11.494141 14 A 1.5 1.5 0 0 0 10.662109 14.255859 A 1.5 1.5 0 0 0 10.115234 16.001953 A 1.5 1.5 0 0 1 10.662109 15.255859 A 1.5 1.5 0 0 1 11.494141 15 A 1.5 1.5 0 0 1 11.787109 15.027344 A 1.5 1.5 0 0 1 12.744141 15.662109 L 15.818359 20.230469 C 18.215776 18.815488 21.012568 18 24.001953 18 C 26.990024 18 29.78649 18.814887 32.183594 20.228516 L 35.255859 15.662109 A 1.5 1.5 0 0 1 36.212891 15.027344 A 1.5 1.5 0 0 1 37.337891 15.255859 A 1.5 1.5 0 0 1 37.910156 16.001953 A 1.5 1.5 0 0 0 37.337891 14.255859 A 1.5 1.5 0 0 0 36.212891 14.027344 A 1.5 1.5 0 0 0 35.255859 14.662109 L 32.183594 19.228516 C 29.78649 17.814887 26.990024 17 24.001953 17 C 21.012568 17 18.215776 17.815488 15.818359 19.230469 L 12.744141 14.662109 A 1.5 1.5 0 0 0 11.787109 14.027344 A 1.5 1.5 0 0 0 11.494141 14 z M 35.033203 21.369141 L 34.617188 21.988281 C 37.477056 24.493668 39.433905 27.993356 39.943359 31.945312 C 39.986866 31.783283 40.008864 31.598575 39.998047 31.382812 C 39.601372 27.448291 37.768055 23.938648 35.033203 21.369141 z M 12.970703 21.373047 C 10.220358 23.959215 8.3822757 27.496796 8.0019531 31.460938 C 7.9920657 31.668114 8.0150508 31.844846 8.0585938 32 C 8.5570234 28.027243 10.515755 24.509049 13.386719 21.992188 L 12.970703 21.373047 z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
data/icon_256x256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View file

@ -94,6 +94,8 @@ dist-win32: build-server build-win32
cp "$(WIN32_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp data/scrcpy-console.bat "$(DIST)/$(WIN32_TARGET_DIR)"
cp data/scrcpy-noconsole.vbs "$(DIST)/$(WIN32_TARGET_DIR)"
cp data/icon_256x256.png "$(DIST)/$(WIN32_TARGET_DIR)/icon.png"
cp data/icon.svg "$(DIST)/$(WIN32_TARGET_DIR)"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win32-shared/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
@ -110,6 +112,8 @@ dist-win64: build-server build-win64
cp "$(WIN64_BUILD_DIR)"/app/scrcpy.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp data/scrcpy-console.bat "$(DIST)/$(WIN64_TARGET_DIR)"
cp data/scrcpy-noconsole.vbs "$(DIST)/$(WIN64_TARGET_DIR)"
cp data/icon_256x256.png "$(DIST)/$(WIN64_TARGET_DIR)/icon.png"
cp data/icon.svg "$(DIST)/$(WIN64_TARGET_DIR)"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avutil-56.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avcodec-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/ffmpeg-4.3.1-win64-shared/bin/avformat-58.dll "$(DIST)/$(WIN64_TARGET_DIR)/"

4
run
View file

@ -20,4 +20,6 @@ then
exit 1
fi
SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" "$BUILDDIR/app/scrcpy" "$@"
SCRCPY_ICON_PATH="data/icon.svg" \
SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" \
"$BUILDDIR/app/scrcpy" "$@"