mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-02-18 14:39:08 +08:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9c5e0d26b | ||
|
|
03999d900e | ||
|
|
b24551da7b | ||
|
|
bc461fe99b | ||
|
|
25e438a663 | ||
|
|
1f5aeda41d | ||
|
|
9114743577 | ||
|
|
7830a9e9f3 | ||
|
|
5fa8485130 | ||
|
|
ed9cb37283 | ||
|
|
e4b270a581 | ||
|
|
9dd9c45afc | ||
|
|
e163b75407 | ||
|
|
10ff3e6937 | ||
|
|
acae6d6558 | ||
|
|
d025ca1d81 | ||
|
|
e5aa31eb4c | ||
|
|
771cc565ab | ||
|
|
db3bdb16a1 | ||
|
|
c06e1d74b4 | ||
|
|
b544a2889b | ||
|
|
9c45636875 | ||
|
|
827b5f6a4c | ||
|
|
b0791ba183 | ||
|
|
b24b381575 | ||
|
|
0751005073 | ||
|
|
fe06cf77da | ||
|
|
d57cf204c8 | ||
|
|
63e22b7685 | ||
|
|
a02d2bb4ac | ||
|
|
0f7d78c263 | ||
|
|
0e321bd845 | ||
|
|
875b738222 | ||
|
|
b39e851262 | ||
|
|
ec466d459f | ||
|
|
d4a712bb32 | ||
|
|
1c17fddf51 | ||
|
|
3c838e7a92 | ||
|
|
8f44787ba3 | ||
|
|
12e15b5a37 |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -4,9 +4,9 @@ env:
|
||||
# MIN_SUPPORTED_RUST_VERSION: "1.46.0"
|
||||
# CICD_INTERMEDIATES_DIR: "_cicd-intermediates"
|
||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||
# vcpkg version: 2024.06.15
|
||||
# vcpkg version: 2024.11.16
|
||||
# for multiarch gcc compatibility
|
||||
VCPKG_COMMIT_ID: "f7423ee180c4b7f40d43402c2feb3859161ef625"
|
||||
VCPKG_COMMIT_ID: "b2cb0da531c2f1f740045bfe7c4dac59f0b2b69c"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
35
.github/workflows/flutter-build.yml
vendored
35
.github/workflows/flutter-build.yml
vendored
@@ -31,9 +31,9 @@ env:
|
||||
FLUTTER_ELINUX_VERSION: "3.16.9"
|
||||
TAG_NAME: "${{ inputs.upload-tag }}"
|
||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||
# vcpkg version: 2024.07.12
|
||||
VCPKG_COMMIT_ID: "1de2026f28ead93ff1773e6e680387643e914ea1"
|
||||
VERSION: "1.3.5"
|
||||
# vcpkg version: 2024.11.16
|
||||
VCPKG_COMMIT_ID: "b2cb0da531c2f1f740045bfe7c4dac59f0b2b69c"
|
||||
VERSION: "1.3.6"
|
||||
NDK_VERSION: "r27c"
|
||||
#signing keys env variable checks
|
||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||
@@ -719,7 +719,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
cd "$(dirname "$(which flutter)")"
|
||||
# https://github.com/flutter/flutter/issues/1.3.53
|
||||
# https://github.com/flutter/flutter/issues/133533
|
||||
sed -i -e 's/_setFramesEnabledState(false);/\/\/_setFramesEnabledState(false);/g' ../packages/flutter/lib/src/scheduler/binding.dart
|
||||
grep -n '_setFramesEnabledState(false);' ../packages/flutter/lib/src/scheduler/binding.dart
|
||||
|
||||
@@ -1852,6 +1852,8 @@ jobs:
|
||||
cat ~/.cargo/config
|
||||
# install dependencies from vcpkg
|
||||
export VCPKG_ROOT=/opt/artifacts/vcpkg
|
||||
# remove this when support higher version
|
||||
export USE_AOM_391=1
|
||||
if ! $VCPKG_ROOT/vcpkg install --triplet ${{ matrix.job.vcpkg-triplet }} --x-install-root="$VCPKG_ROOT/installed"; then
|
||||
find "${VCPKG_ROOT}/" -name "*.log" | while read -r _1; do
|
||||
echo "$_1:"
|
||||
@@ -2009,36 +2011,17 @@ jobs:
|
||||
shell: /bin/bash
|
||||
install: |
|
||||
apt-get update -y
|
||||
apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
rpm \
|
||||
wget
|
||||
apt-get install -y git flatpak flatpak-builder
|
||||
run: |
|
||||
# disable git safe.directory
|
||||
git config --global --add safe.directory "*"
|
||||
pushd /workspace
|
||||
# install
|
||||
apt-get update -y
|
||||
apt-get install -y \
|
||||
cmake \
|
||||
curl \
|
||||
flatpak \
|
||||
flatpak-builder \
|
||||
gcc \
|
||||
git \
|
||||
g++ \
|
||||
libgtk-3-dev \
|
||||
nasm \
|
||||
wget
|
||||
# flatpak deps
|
||||
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak --user install -y flathub org.freedesktop.Platform/${{ matrix.job.arch }}/23.08
|
||||
flatpak --user install -y flathub org.freedesktop.Sdk/${{ matrix.job.arch }}/23.08
|
||||
flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
# package
|
||||
pushd flatpak
|
||||
git clone https://github.com/flathub/shared-modules.git --depth=1
|
||||
flatpak-builder --user --force-clean --repo=repo ./build ./rustdesk.json
|
||||
flatpak-builder --user --install-deps-from=flathub -y --force-clean --repo=repo ./build ./rustdesk.json
|
||||
flatpak build-bundle ./repo rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}${{ matrix.job.suffix }}.flatpak com.rustdesk.RustDesk
|
||||
|
||||
- name: Publish flatpak package
|
||||
|
||||
6
.github/workflows/playground.yml
vendored
6
.github/workflows/playground.yml
vendored
@@ -16,9 +16,9 @@ env:
|
||||
FLUTTER_ELINUX_VERSION: "3.16.9"
|
||||
TAG_NAME: "nightly"
|
||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||
# vcpkg version: 2024.06.15
|
||||
VCPKG_COMMIT_ID: "f7423ee180c4b7f40d43402c2feb3859161ef625"
|
||||
VERSION: "1.3.5"
|
||||
# vcpkg version: 2024.11.16
|
||||
VCPKG_COMMIT_ID: "b2cb0da531c2f1f740045bfe7c4dac59f0b2b69c"
|
||||
VERSION: "1.3.6"
|
||||
NDK_VERSION: "r26d"
|
||||
#signing keys env variable checks
|
||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||
|
||||
14
Cargo.lock
generated
14
Cargo.lock
generated
@@ -1290,7 +1290,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cpal"
|
||||
version = "0.15.3"
|
||||
source = "git+https://github.com/rustdesk-org/cpal?branch=osx-screencapturekit#7cb4ed0bd5546bf209edde0d0e9da5194753f2c0"
|
||||
source = "git+https://github.com/rustdesk-org/cpal?branch=osx-screencapturekit#6b374bcaed076750ca8fce6da518ab39b882e14a"
|
||||
dependencies = [
|
||||
"alsa",
|
||||
"cidre",
|
||||
@@ -3065,7 +3065,7 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
[[package]]
|
||||
name = "hwcodec"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/rustdesk-org/hwcodec#835e599ed229e4e01b6fa3566e02ea45c73e2e9c"
|
||||
source = "git+https://github.com/rustdesk-org/hwcodec#3e7c0dc755f8a77bbed3b2a9921553a511fd7bb5"
|
||||
dependencies = [
|
||||
"bindgen 0.59.2",
|
||||
"cc",
|
||||
@@ -5219,7 +5219,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rdev"
|
||||
version = "0.5.0-2"
|
||||
source = "git+https://github.com/rustdesk-org/rdev#01ac3ec8009f04f7615842b9152338844b806184"
|
||||
source = "git+https://github.com/rustdesk-org/rdev#f9b60b1dd0f3300a1b797d7a74c116683cd232c8"
|
||||
dependencies = [
|
||||
"cocoa 0.24.1",
|
||||
"core-foundation 0.9.4",
|
||||
@@ -5466,7 +5466,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rust-pulsectl"
|
||||
version = "0.2.12"
|
||||
source = "git+https://github.com/open-trade/pulsectl#5e68f4c2b7c644fa321984688602d71e8ad0bba3"
|
||||
source = "git+https://github.com/rustdesk-org/pulsectl#aa34dde499aa912a3abc5289cc0b547bd07dd6e2"
|
||||
dependencies = [
|
||||
"libpulse-binding",
|
||||
]
|
||||
@@ -5494,7 +5494,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustdesk"
|
||||
version = "1.3.5"
|
||||
version = "1.3.6"
|
||||
dependencies = [
|
||||
"android-wakelock",
|
||||
"android_logger",
|
||||
@@ -5594,7 +5594,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustdesk-portable-packer"
|
||||
version = "1.3.5"
|
||||
version = "1.3.6"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"dirs 5.0.1",
|
||||
@@ -5813,7 +5813,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sciter-rs"
|
||||
version = "0.5.57"
|
||||
source = "git+https://github.com/open-trade/rust-sciter?branch=dyn#5322f3a755a0e6bf999fbc60d1efc35246c0f821"
|
||||
source = "git+https://github.com/rustdesk-org/rust-sciter?branch=dyn#5322f3a755a0e6bf999fbc60d1efc35246c0f821"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rustdesk"
|
||||
version = "1.3.5"
|
||||
version = "1.3.6"
|
||||
authors = ["rustdesk <info@rustdesk.com>"]
|
||||
edition = "2021"
|
||||
build= "build.rs"
|
||||
@@ -78,12 +78,15 @@ fon = "0.6"
|
||||
zip = "0.6"
|
||||
shutdown_hooks = "0.1"
|
||||
totp-rs = { version = "5.4", default-features = false, features = ["gen_secret", "otpauth"] }
|
||||
|
||||
[target.'cfg(not(target_os = "linux"))'.dependencies]
|
||||
# https://github.com/rustdesk/rustdesk/discussions/10197, not use cpal on linux
|
||||
cpal = { git = "https://github.com/rustdesk-org/cpal", branch = "osx-screencapturekit" }
|
||||
ringbuf = "0.3"
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
mac_address = "1.1"
|
||||
sciter-rs = { git = "https://github.com/open-trade/rust-sciter", branch = "dyn" }
|
||||
sciter-rs = { git = "https://github.com/rustdesk-org/rust-sciter", branch = "dyn" }
|
||||
sys-locale = "0.3"
|
||||
enigo = { path = "libs/enigo", features = [ "with_serde" ] }
|
||||
clipboard = { path = "libs/clipboard" }
|
||||
@@ -149,7 +152,7 @@ reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocki
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
psimple = { package = "libpulse-simple-binding", version = "2.27" }
|
||||
pulse = { package = "libpulse-binding", version = "2.27" }
|
||||
rust-pulsectl = { git = "https://github.com/open-trade/pulsectl" }
|
||||
rust-pulsectl = { git = "https://github.com/rustdesk-org/pulsectl" }
|
||||
async-process = "1.7"
|
||||
evdev = { git="https://github.com/rustdesk-org/evdev" }
|
||||
dbus = "0.9"
|
||||
|
||||
11
Dockerfile
11
Dockerfile
@@ -2,6 +2,7 @@ FROM debian:bullseye-slim
|
||||
|
||||
WORKDIR /
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV VCPKG_FORCE_SYSTEM_BINARIES=1
|
||||
RUN apt update -y && \
|
||||
apt install --yes --no-install-recommends \
|
||||
g++ \
|
||||
@@ -21,7 +22,8 @@ RUN apt update -y && \
|
||||
libpam0g-dev \
|
||||
libpulse-dev \
|
||||
make \
|
||||
cmake \
|
||||
wget \
|
||||
libssl-dev \
|
||||
unzip \
|
||||
zip \
|
||||
sudo \
|
||||
@@ -31,6 +33,13 @@ RUN apt update -y && \
|
||||
ninja-build && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN wget https://github.com/Kitware/CMake/releases/download/v3.30.6/cmake-3.30.6.tar.gz --no-check-certificate && \
|
||||
tar xzf cmake-3.30.6.tar.gz && \
|
||||
cd cmake-3.30.6 && \
|
||||
./configure --prefix=/usr/local && \
|
||||
make && \
|
||||
make install
|
||||
|
||||
RUN git clone --branch 2023.04.15 --depth=1 https://github.com/microsoft/vcpkg && \
|
||||
/vcpkg/bootstrap-vcpkg.sh -disableMetrics && \
|
||||
/vcpkg/vcpkg --disable-metrics install libvpx libyuv opus aom
|
||||
|
||||
@@ -25,9 +25,12 @@ RustDesk welcomes contribution from everyone. See [CONTRIBUTING.md](docs/CONTRIB
|
||||
|
||||
[**NIGHTLY BUILD**](https://github.com/rustdesk/rustdesk/releases/tag/nightly)
|
||||
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||
[<img src="https://f-droid.org/badge/get-it-on.png"
|
||||
alt="Get it on F-Droid"
|
||||
height="80">](https://f-droid.org/en/packages/com.carriez.flutter_hbb)
|
||||
[<img src="https://flathub.org/api/badge?svg&locale=en"
|
||||
alt="Get it on Flathub"
|
||||
height="80">](https://flathub.org/apps/com.rustdesk.RustDesk)
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ AppDir:
|
||||
id: rustdesk
|
||||
name: rustdesk
|
||||
icon: rustdesk
|
||||
version: 1.3.5
|
||||
exec: usr/lib/rustdesk/rustdesk
|
||||
version: 1.3.6
|
||||
exec: usr/share/rustdesk/rustdesk
|
||||
exec_args: $@
|
||||
apt:
|
||||
arch:
|
||||
@@ -77,7 +77,7 @@ AppDir:
|
||||
env:
|
||||
GIO_MODULE_DIR: /lib64/gio/modules:/usr/lib/aarch64-linux-gnu/gio/modules:$APPDIR/usr/lib/aarch64-linux-gnu/gio/modules
|
||||
GDK_BACKEND: x11
|
||||
APPDIR_LIBRARY_PATH: /lib64:/usr/lib/aarch64-linux-gnu:$APPDIR/lib/aarch64-linux-gnu:$APPDIR/lib/aarch64-linux-gnu/security:$APPDIR/lib/systemd:$APPDIR/usr/lib/aarch64-linux-gnu:$APPDIR/usr/lib/aarch64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders:$APPDIR/usr/lib/aarch64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/aarch64-linux-gnu/gtk-3.0/3.0.0/immodules:$APPDIR/usr/lib/aarch64-linux-gnu/gtk-3.0/3.0.0/printbackends:$APPDIR/usr/lib/aarch64-linux-gnu/krb5/plugins/preauth:$APPDIR/usr/lib/aarch64-linux-gnu/libcanberra-0.30:$APPDIR/usr/lib/aarch64-linux-gnu/pulseaudio:$APPDIR/usr/lib/aarch64-linux-gnu/sasl2:$APPDIR/usr/lib/aarch64-linux-gnu/vdpau:$APPDIR/usr/lib/rustdesk/lib:$APPDIR/lib/aarch64
|
||||
APPDIR_LIBRARY_PATH: /lib64:/usr/lib/aarch64-linux-gnu:$APPDIR/lib/aarch64-linux-gnu:$APPDIR/lib/aarch64-linux-gnu/security:$APPDIR/lib/systemd:$APPDIR/usr/lib/aarch64-linux-gnu:$APPDIR/usr/lib/aarch64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders:$APPDIR/usr/lib/aarch64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/aarch64-linux-gnu/gtk-3.0/3.0.0/immodules:$APPDIR/usr/lib/aarch64-linux-gnu/gtk-3.0/3.0.0/printbackends:$APPDIR/usr/lib/aarch64-linux-gnu/krb5/plugins/preauth:$APPDIR/usr/lib/aarch64-linux-gnu/libcanberra-0.30:$APPDIR/usr/lib/aarch64-linux-gnu/pulseaudio:$APPDIR/usr/lib/aarch64-linux-gnu/sasl2:$APPDIR/usr/lib/aarch64-linux-gnu/vdpau:$APPDIR/usr/share/rustdesk/lib:$APPDIR/lib/aarch64
|
||||
GST_PLUGIN_PATH: /lib64/gstreamer-1.0:/usr/lib/aarch64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/aarch64-linux-gnu/gstreamer-1.0
|
||||
GST_PLUGIN_SYSTEM_PATH: /lib64/gstreamer-1.0:/usr/lib/aarch64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/aarch64-linux-gnu/gstreamer-1.0
|
||||
test:
|
||||
|
||||
@@ -18,8 +18,8 @@ AppDir:
|
||||
id: rustdesk
|
||||
name: rustdesk
|
||||
icon: rustdesk
|
||||
version: 1.3.5
|
||||
exec: usr/lib/rustdesk/rustdesk
|
||||
version: 1.3.6
|
||||
exec: usr/share/rustdesk/rustdesk
|
||||
exec_args: $@
|
||||
apt:
|
||||
arch:
|
||||
@@ -80,7 +80,7 @@ AppDir:
|
||||
env:
|
||||
GIO_MODULE_DIR: /lib64/gio/modules:/usr/lib/x86_64-linux-gnu/gio/modules:$APPDIR/usr/lib/x86_64-linux-gnu/gio/modules
|
||||
GDK_BACKEND: x11
|
||||
APPDIR_LIBRARY_PATH: /lib64:/usr/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu/security:$APPDIR/lib/systemd:$APPDIR/usr/lib/x86_64-linux-gnu:$APPDIR/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders:$APPDIR/usr/lib/x86_64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules:$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/printbackends:$APPDIR/usr/lib/x86_64-linux-gnu/krb5/plugins/preauth:$APPDIR/usr/lib/x86_64-linux-gnu/libcanberra-0.30:$APPDIR/usr/lib/x86_64-linux-gnu/pulseaudio:$APPDIR/usr/lib/x86_64-linux-gnu/sasl2:$APPDIR/usr/lib/x86_64-linux-gnu/vdpau:$APPDIR/usr/lib/rustdesk/lib:$APPDIR/lib/x86_64
|
||||
APPDIR_LIBRARY_PATH: /lib64:/usr/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu:$APPDIR/lib/x86_64-linux-gnu/security:$APPDIR/lib/systemd:$APPDIR/usr/lib/x86_64-linux-gnu:$APPDIR/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders:$APPDIR/usr/lib/x86_64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules:$APPDIR/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/printbackends:$APPDIR/usr/lib/x86_64-linux-gnu/krb5/plugins/preauth:$APPDIR/usr/lib/x86_64-linux-gnu/libcanberra-0.30:$APPDIR/usr/lib/x86_64-linux-gnu/pulseaudio:$APPDIR/usr/lib/x86_64-linux-gnu/sasl2:$APPDIR/usr/lib/x86_64-linux-gnu/vdpau:$APPDIR/usr/share/rustdesk/lib:$APPDIR/lib/x86_64
|
||||
GST_PLUGIN_PATH: /lib64/gstreamer-1.0:/usr/lib/x86_64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/x86_64-linux-gnu/gstreamer-1.0
|
||||
GST_PLUGIN_SYSTEM_PATH: /lib64/gstreamer-1.0:/usr/lib/x86_64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/x86_64-linux-gnu/gstreamer-1.0
|
||||
test:
|
||||
|
||||
16
build.py
16
build.py
@@ -321,7 +321,7 @@ def build_flutter_deb(version, features):
|
||||
os.chdir('flutter')
|
||||
system2('flutter build linux --release')
|
||||
system2('mkdir -p tmpdeb/usr/bin/')
|
||||
system2('mkdir -p tmpdeb/usr/lib/rustdesk')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk')
|
||||
system2('mkdir -p tmpdeb/etc/rustdesk/')
|
||||
system2('mkdir -p tmpdeb/etc/pam.d/')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/')
|
||||
@@ -331,7 +331,7 @@ def build_flutter_deb(version, features):
|
||||
system2('mkdir -p tmpdeb/usr/share/polkit-1/actions')
|
||||
system2('rm tmpdeb/usr/bin/rustdesk || true')
|
||||
system2(
|
||||
f'cp -r {flutter_build_dir}/* tmpdeb/usr/lib/rustdesk/')
|
||||
f'cp -r {flutter_build_dir}/* tmpdeb/usr/share/rustdesk/')
|
||||
system2(
|
||||
'cp ../res/rustdesk.service tmpdeb/usr/share/rustdesk/files/systemd/')
|
||||
system2(
|
||||
@@ -366,7 +366,7 @@ def build_flutter_deb(version, features):
|
||||
def build_deb_from_folder(version, binary_folder):
|
||||
os.chdir('flutter')
|
||||
system2('mkdir -p tmpdeb/usr/bin/')
|
||||
system2('mkdir -p tmpdeb/usr/lib/rustdesk')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk/files/systemd/')
|
||||
system2('mkdir -p tmpdeb/usr/share/icons/hicolor/256x256/apps/')
|
||||
system2('mkdir -p tmpdeb/usr/share/icons/hicolor/scalable/apps/')
|
||||
@@ -374,7 +374,7 @@ def build_deb_from_folder(version, binary_folder):
|
||||
system2('mkdir -p tmpdeb/usr/share/polkit-1/actions')
|
||||
system2('rm tmpdeb/usr/bin/rustdesk || true')
|
||||
system2(
|
||||
f'cp -r ../{binary_folder}/* tmpdeb/usr/lib/rustdesk/')
|
||||
f'cp -r ../{binary_folder}/* tmpdeb/usr/share/rustdesk/')
|
||||
system2(
|
||||
'cp ../res/rustdesk.service tmpdeb/usr/share/rustdesk/files/systemd/')
|
||||
system2(
|
||||
@@ -621,14 +621,14 @@ def main():
|
||||
os.system('mkdir -p tmpdeb/etc/pam.d/')
|
||||
os.system('cp pam.d/rustdesk.debian tmpdeb/etc/pam.d/rustdesk')
|
||||
system2('strip tmpdeb/usr/bin/rustdesk')
|
||||
system2('mkdir -p tmpdeb/usr/lib/rustdesk')
|
||||
system2('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/lib/rustdesk/')
|
||||
system2('cp libsciter-gtk.so tmpdeb/usr/lib/rustdesk/')
|
||||
system2('mkdir -p tmpdeb/usr/share/rustdesk')
|
||||
system2('mv tmpdeb/usr/bin/rustdesk tmpdeb/usr/share/rustdesk/')
|
||||
system2('cp libsciter-gtk.so tmpdeb/usr/share/rustdesk/')
|
||||
md5_file('usr/share/rustdesk/files/systemd/rustdesk.service')
|
||||
md5_file('etc/rustdesk/startwm.sh')
|
||||
md5_file('etc/X11/rustdesk/xorg.conf')
|
||||
md5_file('etc/pam.d/rustdesk')
|
||||
md5_file('usr/lib/rustdesk/libsciter-gtk.so')
|
||||
md5_file('usr/share/rustdesk/libsciter-gtk.so')
|
||||
system2('dpkg-deb -b tmpdeb rustdesk.deb; /bin/rm -rf tmpdeb/')
|
||||
os.rename('rustdesk.deb', 'rustdesk-%s.deb' % version)
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
<b>README를 모국어로 번역하기 위한 당신의 도움의 필요합니다.</b>
|
||||
</p>
|
||||
|
||||
Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk)
|
||||
채팅하기: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk)
|
||||
|
||||
|
||||
[](https://ko-fi.com/I2I04VU09)
|
||||
|
||||
Rust로 작성되었고, 설정없이 바로 사용할 수 있는 원격 데스트탑 소프트웨어입니다. 자신의 데이터를 완전히 컨트롤할 수 있고, 보안의 염려도 없습니다. 우리의 rendezvous/relay 서버를 사용해도, [스스로 설정](https://rustdesk.com/server)하는 것도, [스스로 rendezvous/relay 서버를 작성할 수도 있습니다](https://github.com/rustdesk/rustdesk-server-demo).
|
||||
Rust로 작성되었고, 설정없이 바로 사용할 수 있는 원격 데스트탑 소프트웨어입니다. 자신의 데이터를 완전히 컨트롤할 수 있고, 보안의 염려도 없습니다. 우리의 rendezvous/relay 서버를 사용해도, [직접 설정](https://rustdesk.com/server)하거나 [직접 rendezvous/relay 서버를 작성할 수도 있습니다](https://github.com/rustdesk/rustdesk-server-demo).
|
||||
|
||||

|
||||
|
||||
@@ -43,9 +43,9 @@ RustDesk는 모든 기여를 환영합니다. 기여하고자 한다면 [`docs/C
|
||||
- Windows: vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static aom:x64-windows-static
|
||||
- Linux/MacOS: vcpkg install libvpx libyuv opus aom
|
||||
|
||||
- run `cargo run`
|
||||
- 실행 `cargo run`
|
||||
|
||||
## [Build](https://rustdesk.com/docs/en/dev/build/)
|
||||
## [빌드](https://rustdesk.com/docs/en/dev/build/)
|
||||
|
||||
## Linux에서 빌드 순서
|
||||
|
||||
@@ -67,7 +67,7 @@ sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-
|
||||
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pipewire
|
||||
```
|
||||
|
||||
### Install vcpkg
|
||||
### vcpkg 설치
|
||||
|
||||
```sh
|
||||
git clone https://github.com/microsoft/vcpkg
|
||||
@@ -79,7 +79,7 @@ export VCPKG_ROOT=$HOME/vcpkg
|
||||
vcpkg/vcpkg install libvpx libyuv opus aom
|
||||
```
|
||||
|
||||
### Fix libvpx (For Fedora)
|
||||
### libvpx 수정 (For Fedora용)
|
||||
|
||||
```sh
|
||||
cd vcpkg/buildtrees/libvpx/src
|
||||
@@ -92,7 +92,7 @@ cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
|
||||
cd
|
||||
```
|
||||
|
||||
### Build
|
||||
### 빌드
|
||||
|
||||
```sh
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
@@ -107,7 +107,7 @@ VCPKG_ROOT=$HOME/vcpkg cargo run
|
||||
|
||||
## Docker에 빌드하는 방법
|
||||
|
||||
레포지토리를 클론하고, Docker 컨테이너 구성하는 것으로 시작합니다.
|
||||
리포지토리를 클론하고, Docker 컨테이너 구성하는 것으로 시작합니다.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/rustdesk/rustdesk
|
||||
@@ -115,13 +115,13 @@ cd rustdesk
|
||||
docker build -t "rustdesk-builder" .
|
||||
```
|
||||
|
||||
이후, 애플리케이션을 빌드할 필요가 있을 때마다, 이하의 커맨드를 실행합니다.
|
||||
이후, 애플리케이션을 빌드할 필요가 있을 때마다, 아래의의 명령을 실행합니다.
|
||||
|
||||
```sh
|
||||
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
|
||||
```
|
||||
|
||||
첫 빌드에서는 의존관계가 캐시될 때까지 시간이 걸릴 수 있습니다만, 이후의 빌드때는 빨라집니다. 더불어 빌드 커맨드에 다른 인수를 지정할 필요가 있다면, 커맨드 끝에 있는 `<OPTIONAL-ARGS>` 에 지정할 수 있습니다. 예를 들어 최적화된 출시 버전을 빌드하고 싶다면 이렇게 상기한 커맨드 뒤에 `--release` 를 붙여 실행합니다. 성공했다면 실행파일은 시스템 타겟 폴더에 담겨지고, 다음 커맨드로 실행할 수 있습니다.
|
||||
첫 빌드에서는 의존관계가 캐시될 때까지 시간이 걸릴 수 있습니다만, 이후의 빌드때는 빨라집니다. 더불어 빌드 명령에 다른 인수를 지정할 필요가 있다면, 명령 끝에 있는 `<OPTIONAL-ARGS>` 에 지정할 수 있습니다. 예를 들어 최적화된 출시 버전을 빌드하고 싶다면 이렇게 상기한 명령 뒤에 `--release` 를 붙여 실행합니다. 성공했다면 실행파일은 시스템 타겟 폴더에 담겨지고, 다음 명령으로 실행할 수 있습니다.
|
||||
|
||||
```sh
|
||||
target/debug/rustdesk
|
||||
@@ -133,9 +133,9 @@ target/debug/rustdesk
|
||||
target/release/rustdesk
|
||||
```
|
||||
|
||||
커맨드를 RustDesk 리포지토리 루트에서 실행한다는 것을 확인해주세요. 그렇게 하지 않으면 애플리케이션이 필요한 리소스를 발견하지 못 할 가능성이 있습니다. 또한 `install`, `run` 같은 cargo 서브커맨드는 호스트가 아니라 컨테이너 프로그램을 설치, 실행을 위함이므로 현재 이 방법은 지원하지 않다는 점을 유념해주시길 바랍니다.
|
||||
명령을 RustDesk 리포지토리 루트에서 실행한다는 것을 확인해주세요. 그렇게 하지 않으면 애플리케이션이 필요한 리소스를 발견하지 못 할 가능성이 있습니다. 또한 `install`, `run` 같은 cargo 하위 명령은 호스트가 아니라 컨테이너 프로그램을 설치, 실행을 위함이므로 현재 이 방법은 지원하지 않다는 점을 유념해주시길 바랍니다.
|
||||
|
||||
## File Structure
|
||||
## 파일 구조
|
||||
|
||||
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: 비디오 코덱, 설정, tcp/udp 랩퍼, protobuf, 파일 전송을 위한 fs 함수, 그 외 유틸리티 함수
|
||||
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: 화면 캡처
|
||||
@@ -143,12 +143,12 @@ target/release/rustdesk
|
||||
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: GUI
|
||||
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: 오디오, 클립보드, 입력, 비디오 서비스 그리고 네트워크 연결
|
||||
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: 피어 접속 시작
|
||||
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: [rustdesk-server](https://github.com/rustdesk/rustdesk-server)와 통신해서 리모트 다이렉트(TCP hole punching) 혹은 relayed 접속
|
||||
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: [rustdesk-server](https://github.com/rustdesk/rustdesk-server)와 통신해서 리모트 다이렉트 (TCP hole punching) 혹은 relayed 접속
|
||||
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: 플랫폼 고유의 코드
|
||||
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: Flutter code for mobile
|
||||
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: Javascript for Flutter web client
|
||||
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: 모바일용 Flutter 코드
|
||||
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: Flutter 웹 클라이언트용 자바스크립트
|
||||
|
||||
## Snapshot
|
||||
## 스냅샷
|
||||
|
||||

|
||||
|
||||
|
||||
59
flatpak/com.rustdesk.RustDesk.metainfo.xml
Normal file
59
flatpak/com.rustdesk.RustDesk.metainfo.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>com.rustdesk.RustDesk</id>
|
||||
<developer id="com.rustdesk">
|
||||
<name>RustDesk</name>
|
||||
</developer>
|
||||
<launchable type="desktop-id">com.rustdesk.RustDesk.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>AGPL-3.0-only</project_license>
|
||||
<name>RustDesk</name>
|
||||
<summary>Secure remote desktop access</summary>
|
||||
<description>
|
||||
<p>
|
||||
RustDesk is a full-featured open source remote control alternative for self-hosting and security with minimal configuration.
|
||||
</p>
|
||||
<ul>
|
||||
<li> Works on Windows, macOS, Linux, iOS, Android, Web. </li>
|
||||
<li> Supports VP8 / VP9 / AV1 software codecs, and H264 / H265 hardware codecs. </li>
|
||||
<li> Own your data, easily set up self-hosting solution on your infrastructure. </li>
|
||||
<li> P2P connection with end-to-end encryption based on NaCl. </li>
|
||||
<li> No administrative privileges or installation needed for Windows, elevate priviledge locally or from remote on demand. </li>
|
||||
<li> We like to keep things simple and will strive to make simpler where possible. </li>
|
||||
</ul>
|
||||
<p>
|
||||
For self-hosting setup instructions please go to our home page.
|
||||
</p>
|
||||
</description>
|
||||
<categories>
|
||||
<category>Utility</category>
|
||||
</categories>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>Remote desktop session</caption>
|
||||
<image>https://user-images.githubusercontent.com/71636191/171661982-430285f0-2e12-4b1d-9957-4a58e375304d.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<branding>
|
||||
<color type="primary" scheme_preference="light">#d9eaf8</color>
|
||||
<color type="primary" scheme_preference="dark">#0160ee</color>
|
||||
</branding>
|
||||
<url type="homepage">https://rustdesk.com</url>
|
||||
<url type="bugtracker">https://github.com/rustdesk/rustdesk/issues</url>
|
||||
<url type="faq">https://github.com/rustdesk/rustdesk/wiki/FAQ</url>
|
||||
<url type="help">https://rustdesk.com/docs</url>
|
||||
<url type="donation">https://ko-fi.com/rustdesk</url>
|
||||
<url type="vcs-browser">https://github.com/rustdesk/rustdesk</url>
|
||||
<url type="translate">https://github.com/rustdesk/rustdesk/tree/master/src/lang</url>
|
||||
<url type="contribute">https://github.com/rustdesk/rustdesk/blob/master/docs/CONTRIBUTING.md</url>
|
||||
<url type="contact">https://rustdesk.com/docs/en/technical-support</url>
|
||||
<requires>
|
||||
<display_length compare="ge">600</display_length>
|
||||
<internet>always</internet>
|
||||
</requires>
|
||||
<supports>
|
||||
<control>keyboard</control>
|
||||
<control>pointing</control>
|
||||
</supports>
|
||||
<content_rating type="oars-1.1"/>
|
||||
</component>
|
||||
@@ -1,19 +1,30 @@
|
||||
{
|
||||
"id": "com.rustdesk.RustDesk",
|
||||
"runtime": "org.freedesktop.Platform",
|
||||
"runtime-version": "23.08",
|
||||
"runtime-version": "24.08",
|
||||
"sdk": "org.freedesktop.Sdk",
|
||||
"command": "rustdesk",
|
||||
"icon": "share/icons/hicolor/scalable/apps/rustdesk.svg",
|
||||
"cleanup": ["/include", "/lib/pkgconfig", "/share/gtk-doc"],
|
||||
"rename-desktop-file": "rustdesk.desktop",
|
||||
"rename-icon": "rustdesk",
|
||||
"modules": [
|
||||
"shared-modules/libappindicator/libappindicator-gtk3-12.10.json",
|
||||
"xdotool.json",
|
||||
{
|
||||
"name": "pam",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"./configure --disable-selinux --prefix=/app && make -j4 install"
|
||||
],
|
||||
"name": "xdotool",
|
||||
"no-autogen": true,
|
||||
"make-install-args": ["PREFIX=${FLATPAK_DEST}"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/jordansissel/xdotool/releases/download/v3.20211022.1/xdotool-3.20211022.1.tar.gz",
|
||||
"sha256": "96f0facfde6d78eacad35b91b0f46fecd0b35e474c03e00e30da3fdd345f9ada"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pam",
|
||||
"buildsystem": "autotools",
|
||||
"config-opts": ["--disable-selinux"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
@@ -26,32 +37,24 @@
|
||||
"name": "rustdesk",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"bsdtar -zxvf rustdesk.deb",
|
||||
"tar -xvf ./data.tar.xz",
|
||||
"cp -r ./usr/* /app/",
|
||||
"mkdir -p /app/bin && ln -s /app/lib/rustdesk/rustdesk /app/bin/rustdesk",
|
||||
"mv /app/share/applications/rustdesk.desktop /app/share/applications/com.rustdesk.RustDesk.desktop",
|
||||
"mv /app/share/applications/rustdesk-link.desktop /app/share/applications/com.rustdesk.RustDesk-link.desktop",
|
||||
"sed -i '/^Icon=/ c\\Icon=com.rustdesk.RustDesk' /app/share/applications/*.desktop",
|
||||
"mv /app/share/icons/hicolor/scalable/apps/rustdesk.svg /app/share/icons/hicolor/scalable/apps/com.rustdesk.RustDesk.svg",
|
||||
"for size in 16 24 32 48 64 128 256 512; do\n rsvg-convert -w $size -h $size -f png -o $size.png scalable.svg\n install -Dm644 $size.png /app/share/icons/hicolor/${size}x${size}/apps/com.rustdesk.RustDesk.png\n done"
|
||||
"bsdtar -Oxf rustdesk.deb data.tar.xz | bsdtar -xf -",
|
||||
"cp -r usr/* /app/",
|
||||
"mkdir -p /app/bin && ln -s /app/share/rustdesk/rustdesk /app/bin/rustdesk"
|
||||
],
|
||||
"cleanup": ["/include", "/lib/pkgconfig", "/share/gtk-doc"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"path": "./rustdesk.deb"
|
||||
"path": "rustdesk.deb"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"path": "../res/scalable.svg"
|
||||
"path": "com.rustdesk.RustDesk.metainfo.xml"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"finish-args": [
|
||||
"--share=ipc",
|
||||
"--socket=x11",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland",
|
||||
"--share=network",
|
||||
@@ -60,4 +63,4 @@
|
||||
"--socket=pulseaudio",
|
||||
"--talk-name=org.freedesktop.Flatpak"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "xdotool",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"make -j4 && PREFIX=./build make install",
|
||||
"cp -r ./build/* /app/"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/jordansissel/xdotool/releases/download/v3.20211022.1/xdotool-3.20211022.1.tar.gz",
|
||||
"sha256": "96f0facfde6d78eacad35b91b0f46fecd0b35e474c03e00e30da3fdd345f9ada"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -306,8 +306,8 @@ class FloatingWindowService : Service(), View.OnTouchListener {
|
||||
popupMenu.menu.add(0, idShowRustDesk, 0, translate("Show RustDesk"))
|
||||
// For host side, clipboard sync
|
||||
val idSyncClipboard = 1
|
||||
val isClipboardListenerEnabled = MainActivity.rdClipboardManager?.isListening ?: false
|
||||
if (isClipboardListenerEnabled) {
|
||||
val isServiceSyncEnabled = (MainActivity.rdClipboardManager?.isCaptureStarted ?: false) && FFI.isServiceClipboardEnabled()
|
||||
if (isServiceSyncEnabled) {
|
||||
popupMenu.menu.add(0, idSyncClipboard, 0, translate("Update client clipboard"))
|
||||
}
|
||||
val idStopService = 2
|
||||
|
||||
@@ -103,7 +103,6 @@ class MainActivity : FlutterActivity() {
|
||||
mainService?.let {
|
||||
unbindService(serviceConnection)
|
||||
}
|
||||
rdClipboardManager?.rustEnableServiceClipboard(false)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
@@ -221,6 +220,10 @@ class MainActivity : FlutterActivity() {
|
||||
result.success(true)
|
||||
|
||||
}
|
||||
"try_sync_clipboard" -> {
|
||||
rdClipboardManager?.syncClipboard(true)
|
||||
result.success(true)
|
||||
}
|
||||
GET_START_ON_BOOT_OPT -> {
|
||||
val prefs = getSharedPreferences(KEY_SHARED_PREFERENCES, MODE_PRIVATE)
|
||||
result.success(prefs.getBoolean(KEY_START_ON_BOOT_OPT, false))
|
||||
@@ -402,13 +405,4 @@ class MainActivity : FlutterActivity() {
|
||||
super.onStart()
|
||||
stopService(Intent(this, FloatingWindowService::class.java))
|
||||
}
|
||||
|
||||
// For client side
|
||||
// When swithing from other app to this app, try to sync clipboard.
|
||||
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||
super.onWindowFocusChanged(hasFocus)
|
||||
if (hasFocus) {
|
||||
rdClipboardManager?.syncClipboard(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,6 +433,7 @@ class MainService : Service() {
|
||||
checkMediaPermission()
|
||||
_isStart = true
|
||||
FFI.setFrameRawEnable("video",true)
|
||||
MainActivity.rdClipboardManager?.setCaptureStarted(_isStart)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -441,6 +442,7 @@ class MainService : Service() {
|
||||
Log.d(logTag, "Stop Capture")
|
||||
FFI.setFrameRawEnable("video",false)
|
||||
_isStart = false
|
||||
MainActivity.rdClipboardManager?.setCaptureStarted(_isStart)
|
||||
// release video
|
||||
if (reuseVirtualDisplay) {
|
||||
// The virtual display video projection can be paused by calling `setSurface(null)`.
|
||||
|
||||
@@ -36,19 +36,19 @@ class RdClipboardManager(private val clipboardManager: ClipboardManager) {
|
||||
// though the `lastUpdatedClipData` will be set to null once.
|
||||
private var lastUpdatedClipData: ClipData? = null
|
||||
private var isClientEnabled = true;
|
||||
private var _isListening = false;
|
||||
val isListening: Boolean
|
||||
get() = _isListening
|
||||
private var _isCaptureStarted = false;
|
||||
|
||||
fun checkPrimaryClip(isClient: Boolean, isSync: Boolean) {
|
||||
val isCaptureStarted: Boolean
|
||||
get() = _isCaptureStarted
|
||||
|
||||
fun checkPrimaryClip(isClient: Boolean) {
|
||||
val clipData = clipboardManager.primaryClip
|
||||
if (clipData != null && clipData.itemCount > 0) {
|
||||
// Only handle the first item in the clipboard for now.
|
||||
val clip = clipData.getItemAt(0)
|
||||
val isHostSync = !isClient && isSync
|
||||
// Ignore the `isClipboardDataEqual()` check if it's a host sync operation.
|
||||
// Because it's a action manually triggered by the user.
|
||||
if (!isHostSync) {
|
||||
// Ignore the `isClipboardDataEqual()` check if it's a host operation.
|
||||
// Because it's an action manually triggered by the user.
|
||||
if (isClient) {
|
||||
if (lastUpdatedClipData != null && isClipboardDataEqual(clipData, lastUpdatedClipData!!)) {
|
||||
Log.d(logTag, "Clipboard data is the same as last update, ignore")
|
||||
return
|
||||
@@ -95,13 +95,6 @@ class RdClipboardManager(private val clipboardManager: ClipboardManager) {
|
||||
}
|
||||
}
|
||||
|
||||
private val clipboardListener = object : ClipboardManager.OnPrimaryClipChangedListener {
|
||||
override fun onPrimaryClipChanged() {
|
||||
Log.d(logTag, "onPrimaryClipChanged")
|
||||
checkPrimaryClip(true, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSupportedMimeType(mimeType: String): Boolean {
|
||||
return supportedMimeTypes.contains(mimeType)
|
||||
}
|
||||
@@ -136,43 +129,23 @@ class RdClipboardManager(private val clipboardManager: ClipboardManager) {
|
||||
return true
|
||||
}
|
||||
|
||||
@Keep
|
||||
fun rustEnableServiceClipboard(enable: Boolean) {
|
||||
Log.d(logTag, "rustEnableServiceClipboard: enable: $enable, _isListening: $_isListening")
|
||||
if (enable) {
|
||||
if (!_isListening) {
|
||||
clipboardManager.addPrimaryClipChangedListener(clipboardListener)
|
||||
_isListening = true
|
||||
}
|
||||
} else {
|
||||
if (_isListening) {
|
||||
clipboardManager.removePrimaryClipChangedListener(clipboardListener)
|
||||
_isListening = false
|
||||
lastUpdatedClipData = null
|
||||
}
|
||||
}
|
||||
fun setCaptureStarted(started: Boolean) {
|
||||
_isCaptureStarted = started
|
||||
}
|
||||
|
||||
@Keep
|
||||
fun rustEnableClientClipboard(enable: Boolean) {
|
||||
Log.d(logTag, "rustEnableClientClipboard: enable: $enable")
|
||||
isClientEnabled = enable
|
||||
if (enable) {
|
||||
lastUpdatedClipData = clipboardManager.primaryClip
|
||||
} else {
|
||||
lastUpdatedClipData = null
|
||||
}
|
||||
lastUpdatedClipData = null
|
||||
}
|
||||
|
||||
fun syncClipboard(isClient: Boolean) {
|
||||
Log.d(logTag, "syncClipboard: isClient: $isClient, isClientEnabled: $isClientEnabled, _isListening: $_isListening")
|
||||
Log.d(logTag, "syncClipboard: isClient: $isClient, isClientEnabled: $isClientEnabled")
|
||||
if (isClient && !isClientEnabled) {
|
||||
return
|
||||
}
|
||||
if (!isClient && !_isListening) {
|
||||
return
|
||||
}
|
||||
checkPrimaryClip(isClient, true)
|
||||
checkPrimaryClip(isClient)
|
||||
}
|
||||
|
||||
@Keep
|
||||
|
||||
@@ -24,4 +24,5 @@ object FFI {
|
||||
external fun setCodecInfo(info: String)
|
||||
external fun getLocalOption(key: String): String
|
||||
external fun onClipboardUpdate(clips: ByteBuffer)
|
||||
external fun isServiceClipboardEnabled(): Boolean
|
||||
}
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
# https://docs.flutter.dev/deployment/ios
|
||||
# flutter build ipa --release --obfuscate --split-debug-info=./split-debug-info
|
||||
# no obfuscate, because no easy to check errors
|
||||
cd $(dirname $(dirname $(which flutter)))
|
||||
git apply ~/rustdesk/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff
|
||||
flutter build ipa --release
|
||||
|
||||
@@ -133,7 +133,7 @@ SPEC CHECKSUMS:
|
||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
|
||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
|
||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||
video_player_avfoundation: 02011213dab73ae3687df27ce441fbbcc82b5579
|
||||
wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import UIKit
|
||||
import Flutter
|
||||
|
||||
@UIApplicationMain
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
cd $(dirname $(dirname $(which flutter)))
|
||||
git apply ~/rustdesk/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff
|
||||
cargo build --features flutter,hwcodec --release --target aarch64-apple-ios --lib
|
||||
|
||||
@@ -2809,7 +2809,7 @@ Widget buildRemoteBlock(
|
||||
onExit: (event) => block.value = false,
|
||||
child: Stack(children: [
|
||||
// scope block tab
|
||||
FocusScope(child: child, canRequestFocus: !block.value),
|
||||
preventMouseKeyBuilder(child: child, block: block.value),
|
||||
// mask block click, cm not block click and still use check_click_time to avoid block local click
|
||||
if (mask)
|
||||
Offstage(
|
||||
@@ -2821,6 +2821,11 @@ Widget buildRemoteBlock(
|
||||
));
|
||||
}
|
||||
|
||||
Widget preventMouseKeyBuilder({required Widget child, required bool block}) {
|
||||
return ExcludeFocus(
|
||||
excluding: block, child: AbsorbPointer(child: child, absorbing: block));
|
||||
}
|
||||
|
||||
Widget unreadMessageCountBuilder(RxInt? count,
|
||||
{double? size, double? fontSize}) {
|
||||
return Obx(() => Offstage(
|
||||
@@ -3620,3 +3625,16 @@ void checkUpdate() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/flutter/flutter/issues/153560#issuecomment-2497160535
|
||||
// For TextField, TextFormField
|
||||
extension WorkaroundFreezeLinuxMint on Widget {
|
||||
Widget workaroundFreezeLinuxMint() {
|
||||
// No need to check if is Linux Mint, because this workaround is harmless on other platforms.
|
||||
if (isLinux) {
|
||||
return ExcludeSemantics(child: this);
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
searchMatchFn: (item, searchValue) {
|
||||
return item.value
|
||||
@@ -556,7 +556,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
: translate('ID'),
|
||||
errorText: errorMsg,
|
||||
errorMaxLines: 5),
|
||||
))),
|
||||
).workaroundFreezeLinuxMint())),
|
||||
row(
|
||||
lable: Text(
|
||||
translate('Alias'),
|
||||
@@ -569,7 +569,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
? null
|
||||
: translate('Alias'),
|
||||
),
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
),
|
||||
if (isCurrentAbShared)
|
||||
row(
|
||||
@@ -598,7 +598,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
)),
|
||||
if (gFFI.abModel.currentAbTags.isNotEmpty)
|
||||
Align(
|
||||
@@ -704,7 +704,7 @@ class _AddressBookState extends State<AddressBook> {
|
||||
),
|
||||
controller: controller,
|
||||
autofocus: true,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -167,7 +167,7 @@ class ChatPage extends StatelessWidget implements PageShape {
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
).workaroundFreezeLinuxMint();
|
||||
return SelectionArea(child: chat);
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -140,7 +140,7 @@ void changeIdDialog() {
|
||||
msg = '';
|
||||
});
|
||||
},
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
const SizedBox(
|
||||
height: 8.0,
|
||||
),
|
||||
@@ -201,13 +201,14 @@ void changeWhiteList({Function()? callback}) async {
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLines: null,
|
||||
decoration: InputDecoration(
|
||||
errorText: msg.isEmpty ? null : translate(msg),
|
||||
),
|
||||
controller: controller,
|
||||
enabled: !isOptFixed,
|
||||
autofocus: true),
|
||||
maxLines: null,
|
||||
decoration: InputDecoration(
|
||||
errorText: msg.isEmpty ? null : translate(msg),
|
||||
),
|
||||
controller: controller,
|
||||
enabled: !isOptFixed,
|
||||
autofocus: true)
|
||||
.workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -287,22 +288,23 @@ Future<String> changeDirectAccessPort(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: '21118',
|
||||
isCollapsed: true,
|
||||
prefix: Text('$currentIP : '),
|
||||
suffix: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Icons.clear, size: 16),
|
||||
onPressed: () => controller.clear())),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')),
|
||||
],
|
||||
controller: controller,
|
||||
autofocus: true),
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: '21118',
|
||||
isCollapsed: true,
|
||||
prefix: Text('$currentIP : '),
|
||||
suffix: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Icons.clear, size: 16),
|
||||
onPressed: () => controller.clear())),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')),
|
||||
],
|
||||
controller: controller,
|
||||
autofocus: true)
|
||||
.workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -335,21 +337,22 @@ Future<String> changeAutoDisconnectTimeout(String old) async {
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: '10',
|
||||
isCollapsed: true,
|
||||
suffix: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Icons.clear, size: 16),
|
||||
onPressed: () => controller.clear())),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')),
|
||||
],
|
||||
controller: controller,
|
||||
autofocus: true),
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: '10',
|
||||
isCollapsed: true,
|
||||
suffix: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Icons.clear, size: 16),
|
||||
onPressed: () => controller.clear())),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
r'^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')),
|
||||
],
|
||||
controller: controller,
|
||||
autofocus: true)
|
||||
.workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -427,7 +430,7 @@ class DialogTextField extends StatelessWidget {
|
||||
keyboardType: keyboardType,
|
||||
inputFormatters: inputFormatters,
|
||||
maxLength: maxLength,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).paddingSymmetric(vertical: 4.0);
|
||||
@@ -1501,7 +1504,7 @@ showAuditDialog(FFI ffi) async {
|
||||
maxLength: 256,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
actions: [
|
||||
dialogButton('Cancel', onPressed: close, isOutline: true),
|
||||
dialogButton('OK', onPressed: submit)
|
||||
@@ -1748,7 +1751,7 @@ void renameDialog(
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(labelText: translate('Name')),
|
||||
validator: validator,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
),
|
||||
// NOT use Offstage to wrap LinearProgressIndicator
|
||||
@@ -1808,7 +1811,7 @@ void changeBot({Function()? callback}) async {
|
||||
decoration: InputDecoration(
|
||||
hintText: translate('Token'),
|
||||
),
|
||||
);
|
||||
).workaroundFreezeLinuxMint();
|
||||
|
||||
return CustomAlertDialog(
|
||||
title: Text(translate("Telegram bot")),
|
||||
@@ -2178,7 +2181,7 @@ void setSharedAbPasswordDialog(String abName, Peer peer) {
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
if (!gFFI.abModel.current.isPersonal())
|
||||
Row(children: [
|
||||
Icon(Icons.info, color: Colors.amber).marginOnly(right: 4),
|
||||
|
||||
@@ -678,7 +678,7 @@ Future<bool?> verificationCodeDialog(
|
||||
labelText: "Email", prefixIcon: Icon(Icons.email)),
|
||||
readOnly: true,
|
||||
controller: TextEditingController(text: user?.email),
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
isEmailVerification ? const SizedBox(height: 8) : const Offstage(),
|
||||
codeField,
|
||||
/*
|
||||
|
||||
@@ -145,7 +145,7 @@ class _MyGroupState extends State<MyGroup> {
|
||||
border: InputBorder.none,
|
||||
isDense: true,
|
||||
),
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1257,7 +1257,7 @@ void _rdpDialog(String id) async {
|
||||
hintText: '3389'),
|
||||
controller: portController,
|
||||
autofocus: true,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).marginOnly(bottom: isDesktop ? 8 : 0),
|
||||
@@ -1277,7 +1277,7 @@ void _rdpDialog(String id) async {
|
||||
labelText:
|
||||
isDesktop ? null : translate('Username')),
|
||||
controller: userController,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).marginOnly(bottom: stateGlobal.isPortrait.isFalse ? 8 : 0)),
|
||||
@@ -1305,7 +1305,7 @@ void _rdpDialog(String id) async {
|
||||
? Icons.visibility_off
|
||||
: Icons.visibility))),
|
||||
controller: passwordController,
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
),
|
||||
],
|
||||
))
|
||||
|
||||
@@ -743,7 +743,7 @@ class _PeerSearchBarState extends State<PeerSearchBar> {
|
||||
border: InputBorder.none,
|
||||
isDense: true,
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
// Icon(Icons.close),
|
||||
IconButton(
|
||||
|
||||
@@ -339,7 +339,9 @@ class _RawTouchGestureDetectorRegionState
|
||||
if (isDesktop || isWebDesktop) {
|
||||
ffi.cursorModel.clearRemoteWindowCoords();
|
||||
}
|
||||
await inputModel.sendMouse('up', MouseButtons.left);
|
||||
if (handleTouch) {
|
||||
await inputModel.sendMouse('up', MouseButtons.left);
|
||||
}
|
||||
}
|
||||
|
||||
// scale + pan event
|
||||
|
||||
@@ -575,4 +575,4 @@ extension WindowsTargetExt on int {
|
||||
WindowsTarget get windowsVersion => getWindowsTarget(this);
|
||||
}
|
||||
|
||||
const kCheckSoftwareUpdateFinish = 'check_software_update_finish';
|
||||
const kCheckSoftwareUpdateFinish = 'check_software_update_finish';
|
||||
|
||||
@@ -179,6 +179,9 @@ class _OnlineStatusWidgetState extends State<OnlineStatusWidget> {
|
||||
stateGlobal.svcStatus.value = SvcStatus.notReady;
|
||||
}
|
||||
_svcIsUsingPublicServer.value = await bind.mainIsUsingPublicServer();
|
||||
try {
|
||||
stateGlobal.videoConnCount.value = status['video_conn_count'] as int;
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +362,7 @@ class _ConnectionPageState extends State<ConnectionPage>
|
||||
);
|
||||
}
|
||||
String textToFind = textEditingValue.text.toLowerCase();
|
||||
_autocompleteOpts = peers
|
||||
_autocompleteOpts = peers
|
||||
.where((peer) =>
|
||||
peer.id.toLowerCase().contains(textToFind) ||
|
||||
peer.username
|
||||
@@ -421,7 +424,7 @@ class _ConnectionPageState extends State<ConnectionPage>
|
||||
onSubmitted: (_) {
|
||||
onConnect();
|
||||
},
|
||||
));
|
||||
).workaroundFreezeLinuxMint());
|
||||
},
|
||||
onSelected: (option) {
|
||||
setState(() {
|
||||
|
||||
@@ -35,7 +35,7 @@ class DesktopHomePage extends StatefulWidget {
|
||||
const borderColor = Color(0xFF2F65BA);
|
||||
|
||||
class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
with AutomaticKeepAliveClientMixin {
|
||||
with AutomaticKeepAliveClientMixin, WidgetsBindingObserver {
|
||||
final _leftPaneScrollController = ScrollController();
|
||||
|
||||
@override
|
||||
@@ -51,6 +51,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
bool isCardClosed = false;
|
||||
|
||||
final RxBool _editHover = false.obs;
|
||||
final RxBool _block = false.obs;
|
||||
|
||||
final GlobalKey _childKey = GlobalKey();
|
||||
|
||||
@@ -58,14 +59,20 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final isIncomingOnly = bind.isIncomingOnly();
|
||||
return Row(
|
||||
return _buildBlock(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildLeftPane(context),
|
||||
if (!isIncomingOnly) const VerticalDivider(width: 1),
|
||||
if (!isIncomingOnly) Expanded(child: buildRightPane(context)),
|
||||
],
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
Widget _buildBlock({required Widget child}) {
|
||||
return buildRemoteBlock(
|
||||
block: _block, mask: true, use: canBeBlocked, child: child);
|
||||
}
|
||||
|
||||
Widget buildLeftPane(BuildContext context) {
|
||||
@@ -230,7 +237,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
style: TextStyle(
|
||||
fontSize: 22,
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
)
|
||||
],
|
||||
@@ -326,7 +333,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
EdgeInsets.only(top: 14, bottom: 10),
|
||||
),
|
||||
style: TextStyle(fontSize: 15),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
),
|
||||
if (showOneTime)
|
||||
@@ -423,7 +430,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
bind.mainUriPrefixSync().contains('rustdesk')) {
|
||||
return buildInstallCard(
|
||||
"Status",
|
||||
"There is a newer version of ${bind.mainGetAppNameSync()} ${bind.mainGetNewVersion()} available.",
|
||||
"${translate("new-version-of-{${bind.mainGetAppNameSync()}}-tip")} (${bind.mainGetNewVersion()}).",
|
||||
"Click to download", () async {
|
||||
final Uri url = Uri.parse('https://rustdesk.com/download');
|
||||
await launchUrl(url);
|
||||
@@ -805,6 +812,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
_updateWindowSize();
|
||||
});
|
||||
}
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
_updateWindowSize() {
|
||||
@@ -830,9 +838,18 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
platformFFI.unregisterEventHandler(
|
||||
kCheckSoftwareUpdateFinish, kCheckSoftwareUpdateFinish);
|
||||
}
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
super.didChangeAppLifecycleState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
shouldBeBlocked(_block, canBeBlocked);
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildPluginEntry() {
|
||||
final entries = PluginUiManager.instance.entries.entries;
|
||||
return Offstage(
|
||||
@@ -923,7 +940,7 @@ void setPasswordDialog({VoidCallback? notEmptyCallback}) async {
|
||||
});
|
||||
},
|
||||
maxLength: maxLength,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -950,7 +967,7 @@ void setPasswordDialog({VoidCallback? notEmptyCallback}) async {
|
||||
});
|
||||
},
|
||||
maxLength: maxLength,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -107,13 +107,20 @@ class DesktopSettingPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _DesktopSettingPageState extends State<DesktopSettingPage>
|
||||
with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
|
||||
with
|
||||
TickerProviderStateMixin,
|
||||
AutomaticKeepAliveClientMixin,
|
||||
WidgetsBindingObserver {
|
||||
late PageController controller;
|
||||
late Rx<SettingsTabKey> selectedTab;
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
final RxBool _block = false.obs;
|
||||
final RxBool _canBeBlocked = false.obs;
|
||||
Timer? _videoConnTimer;
|
||||
|
||||
_DesktopSettingPageState(SettingsTabKey initialTabkey) {
|
||||
var initialIndex = DesktopSettingPage.tabKeys.indexOf(initialTabkey);
|
||||
if (initialIndex == -1) {
|
||||
@@ -133,11 +140,34 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
super.didChangeAppLifecycleState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
shouldBeBlocked(_block, canBeBlocked);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_videoConnTimer =
|
||||
periodic_immediate(Duration(milliseconds: 1000), () async {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
_canBeBlocked.value = await canBeBlocked();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
Get.delete<PageController>(tag: _kSettingPageControllerTag);
|
||||
Get.delete<RxInt>(tag: _kSettingPageTabKeyTag);
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
_videoConnTimer?.cancel();
|
||||
}
|
||||
|
||||
List<_TabInfo> _settingTabs() {
|
||||
@@ -207,12 +237,35 @@ class _DesktopSettingPageState extends State<DesktopSettingPage>
|
||||
return children;
|
||||
}
|
||||
|
||||
Widget _buildBlock({required List<Widget> children}) {
|
||||
// check both mouseMoveTime and videoConnCount
|
||||
return Obx(() {
|
||||
final videoConnBlock =
|
||||
_canBeBlocked.value && stateGlobal.videoConnCount > 0;
|
||||
return Stack(children: [
|
||||
buildRemoteBlock(
|
||||
block: _block,
|
||||
mask: false,
|
||||
use: canBeBlocked,
|
||||
child: preventMouseKeyBuilder(
|
||||
child: Row(children: children),
|
||||
block: videoConnBlock,
|
||||
),
|
||||
),
|
||||
if (videoConnBlock)
|
||||
Container(
|
||||
color: Colors.black.withOpacity(0.5),
|
||||
)
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
body: Row(
|
||||
body: _buildBlock(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: _kTabWidth,
|
||||
@@ -706,8 +759,8 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
locked = false;
|
||||
setState(() => {});
|
||||
}),
|
||||
AbsorbPointer(
|
||||
absorbing: locked,
|
||||
preventMouseKeyBuilder(
|
||||
block: locked,
|
||||
child: Column(children: [
|
||||
permissions(context),
|
||||
password(context),
|
||||
@@ -1136,7 +1189,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(vertical: 12, horizontal: 12),
|
||||
),
|
||||
).marginOnly(right: 15),
|
||||
).workaroundFreezeLinuxMint().marginOnly(right: 15),
|
||||
),
|
||||
Obx(() => ElevatedButton(
|
||||
onPressed: applyEnabled.value &&
|
||||
@@ -1293,7 +1346,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(vertical: 12, horizontal: 12),
|
||||
),
|
||||
).marginOnly(right: 15),
|
||||
).workaroundFreezeLinuxMint().marginOnly(right: 15),
|
||||
),
|
||||
Obx(() => ElevatedButton(
|
||||
onPressed:
|
||||
@@ -1374,8 +1427,8 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
|
||||
locked = false;
|
||||
setState(() => {});
|
||||
}),
|
||||
AbsorbPointer(
|
||||
absorbing: locked,
|
||||
preventMouseKeyBuilder(
|
||||
block: locked,
|
||||
child: Column(children: [
|
||||
network(context),
|
||||
]),
|
||||
@@ -2259,7 +2312,7 @@ _LabeledTextField(
|
||||
style: TextStyle(
|
||||
color: disabledTextColor(context, enabled),
|
||||
),
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -2438,7 +2491,7 @@ void changeSocks5Proxy() async {
|
||||
controller: proxyController,
|
||||
autofocus: true,
|
||||
enabled: !isOptFixed,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).marginOnly(bottom: 8),
|
||||
@@ -2458,7 +2511,7 @@ void changeSocks5Proxy() async {
|
||||
labelText: isMobile ? translate('Username') : null,
|
||||
),
|
||||
enabled: !isOptFixed,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
).marginOnly(bottom: 8),
|
||||
@@ -2484,7 +2537,7 @@ void changeSocks5Proxy() async {
|
||||
controller: pwdController,
|
||||
enabled: !isOptFixed,
|
||||
maxLength: bind.mainMaxEncryptLen(),
|
||||
)),
|
||||
).workaroundFreezeLinuxMint()),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -37,13 +37,9 @@ class DesktopTabPage extends StatefulWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _DesktopTabPageState extends State<DesktopTabPage>
|
||||
with WidgetsBindingObserver {
|
||||
class _DesktopTabPageState extends State<DesktopTabPage> {
|
||||
final tabController = DesktopTabController(tabType: DesktopTabType.main);
|
||||
|
||||
final RxBool _block = false.obs;
|
||||
// bool mouseIn = false;
|
||||
|
||||
_DesktopTabPageState() {
|
||||
RemoteCountState.init();
|
||||
Get.put<DesktopTabController>(tabController);
|
||||
@@ -69,19 +65,10 @@ class _DesktopTabPageState extends State<DesktopTabPage>
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
super.didChangeAppLifecycleState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
shouldBeBlocked(_block, canBeBlocked);
|
||||
} else if (state == AppLifecycleState.inactive) {}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// HardwareKeyboard.instance.addHandler(_handleKeyEvent);
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -97,7 +84,6 @@ class _DesktopTabPageState extends State<DesktopTabPage>
|
||||
@override
|
||||
void dispose() {
|
||||
// HardwareKeyboard.instance.removeHandler(_handleKeyEvent);
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
Get.delete<DesktopTabController>();
|
||||
|
||||
super.dispose();
|
||||
@@ -119,7 +105,6 @@ class _DesktopTabPageState extends State<DesktopTabPage>
|
||||
isClose: false,
|
||||
),
|
||||
),
|
||||
blockTab: _block,
|
||||
)));
|
||||
return isMacOS || kUseCompatibleUiMode
|
||||
? tabWidget
|
||||
|
||||
@@ -768,7 +768,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
||||
),
|
||||
controller: name,
|
||||
autofocus: true,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
@@ -1657,7 +1657,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
||||
onChanged: _locationStatus.value == LocationStatus.fileSearchBar
|
||||
? (searchText) => onSearchText(searchText, isLocal)
|
||||
: null,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
@@ -147,7 +147,7 @@ class _InstallPageBodyState extends State<_InstallPageBody>
|
||||
decoration: InputDecoration(
|
||||
contentPadding: EdgeInsets.all(0.75 * em),
|
||||
),
|
||||
).marginOnly(right: 10),
|
||||
).workaroundFreezeLinuxMint().marginOnly(right: 10),
|
||||
),
|
||||
Obx(
|
||||
() => OutlinedButton.icon(
|
||||
|
||||
@@ -238,7 +238,7 @@ class _PortForwardPageState extends State<PortForwardPage>
|
||||
inputFormatters: inputFormatters,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
))),
|
||||
)).workaroundFreezeLinuxMint()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,8 @@ class ConnectionManager extends StatefulWidget {
|
||||
|
||||
class ConnectionManagerState extends State<ConnectionManager>
|
||||
with WidgetsBindingObserver {
|
||||
final RxBool _block = false.obs;
|
||||
final RxBool _controlPageBlock = false.obs;
|
||||
final RxBool _sidePageBlock = false.obs;
|
||||
|
||||
ConnectionManagerState() {
|
||||
gFFI.serverModel.tabController.onSelected = (client_id_str) {
|
||||
@@ -139,7 +140,8 @@ class ConnectionManagerState extends State<ConnectionManager>
|
||||
super.didChangeAppLifecycleState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
if (!allowRemoteCMModification()) {
|
||||
shouldBeBlocked(_block, null);
|
||||
shouldBeBlocked(_controlPageBlock, null);
|
||||
shouldBeBlocked(_sidePageBlock, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,7 +194,6 @@ class ConnectionManagerState extends State<ConnectionManager>
|
||||
selectedBorderColor: MyTheme.accent,
|
||||
maxLabelWidth: 100,
|
||||
tail: null, //buildScrollJumper(),
|
||||
blockTab: allowRemoteCMModification() ? null : _block,
|
||||
tabBuilder: (key, icon, label, themeConf) {
|
||||
final client = serverModel.clients
|
||||
.firstWhereOrNull((client) => client.id.toString() == key);
|
||||
@@ -237,13 +238,20 @@ class ConnectionManagerState extends State<ConnectionManager>
|
||||
? buildSidePage()
|
||||
: buildRemoteBlock(
|
||||
child: buildSidePage(),
|
||||
block: _block,
|
||||
block: _sidePageBlock,
|
||||
mask: true),
|
||||
)),
|
||||
SizedBox(
|
||||
width: realClosedWidth,
|
||||
child:
|
||||
SizedBox(width: realClosedWidth, child: pageView)),
|
||||
child: SizedBox(
|
||||
width: realClosedWidth,
|
||||
child: allowRemoteCMModification()
|
||||
? pageView
|
||||
: buildRemoteBlock(
|
||||
child: _buildKeyEventBlock(pageView),
|
||||
block: _controlPageBlock,
|
||||
mask: false,
|
||||
))),
|
||||
]);
|
||||
return Container(
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
@@ -268,6 +276,10 @@ class ConnectionManagerState extends State<ConnectionManager>
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildKeyEventBlock(Widget child) {
|
||||
return ExcludeFocus(child: child, excluding: true);
|
||||
}
|
||||
|
||||
Widget buildTitleBar() {
|
||||
return SizedBox(
|
||||
height: kDesktopRemoteTabBarHeight,
|
||||
|
||||
@@ -1495,7 +1495,7 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> {
|
||||
);
|
||||
}
|
||||
|
||||
TextField _resolutionInput(TextEditingController controller) {
|
||||
Widget _resolutionInput(TextEditingController controller) {
|
||||
return TextField(
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
@@ -1509,7 +1509,7 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> {
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
||||
],
|
||||
controller: controller,
|
||||
);
|
||||
).workaroundFreezeLinuxMint();
|
||||
}
|
||||
|
||||
List<Widget> _supportedResolutionMenuButtons() => resolutions
|
||||
|
||||
@@ -246,7 +246,6 @@ class DesktopTab extends StatefulWidget {
|
||||
final Color? selectedTabBackgroundColor;
|
||||
final Color? unSelectedTabBackgroundColor;
|
||||
final Color? selectedBorderColor;
|
||||
final RxBool? blockTab;
|
||||
|
||||
final DesktopTabController controller;
|
||||
|
||||
@@ -272,7 +271,6 @@ class DesktopTab extends StatefulWidget {
|
||||
this.selectedTabBackgroundColor,
|
||||
this.unSelectedTabBackgroundColor,
|
||||
this.selectedBorderColor,
|
||||
this.blockTab,
|
||||
}) : super(key: key);
|
||||
|
||||
static RxString tablabelGetter(String peerId) {
|
||||
@@ -311,7 +309,6 @@ class _DesktopTabState extends State<DesktopTab>
|
||||
Color? get unSelectedTabBackgroundColor =>
|
||||
widget.unSelectedTabBackgroundColor;
|
||||
Color? get selectedBorderColor => widget.selectedBorderColor;
|
||||
RxBool? get blockTab => widget.blockTab;
|
||||
DesktopTabController get controller => widget.controller;
|
||||
RxList<String> get invisibleTabKeys => widget.invisibleTabKeys;
|
||||
Debouncer get _scrollDebounce => widget._scrollDebounce;
|
||||
@@ -533,21 +530,9 @@ class _DesktopTabState extends State<DesktopTab>
|
||||
]);
|
||||
}
|
||||
|
||||
Widget _buildBlock({required Widget child}) {
|
||||
if (blockTab != null) {
|
||||
return buildRemoteBlock(
|
||||
child: child,
|
||||
block: blockTab!,
|
||||
use: canBeBlocked,
|
||||
mask: tabType == DesktopTabType.main);
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> _tabWidgets = [];
|
||||
Widget _buildPageView() {
|
||||
final child = _buildBlock(
|
||||
final child = Container(
|
||||
child: Obx(() => PageView(
|
||||
controller: state.value.pageController,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
|
||||
@@ -225,7 +225,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
||||
errorText: errorText,
|
||||
),
|
||||
controller: name,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
|
||||
@@ -147,6 +147,19 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
|
||||
gFFI.chatModel.onVoiceCallClosed("End connetion");
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
trySyncClipboard();
|
||||
}
|
||||
}
|
||||
|
||||
// For client side
|
||||
// When swithing from other app to this app, try to sync clipboard.
|
||||
void trySyncClipboard() {
|
||||
gFFI.invokeMethod("try_sync_clipboard");
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeMetrics() {
|
||||
// If the soft keyboard is visible and the canvas has been changed(panned or scaled)
|
||||
@@ -591,7 +604,7 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
|
||||
// ko/zh/ja input method: the button will trigger `onKeyEvent`
|
||||
// and the event will not popup if `KeyEventResult.handled` is returned.
|
||||
onChanged: handleSoftKeyboardInput,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
];
|
||||
if (showCursorPaint) {
|
||||
|
||||
@@ -66,7 +66,7 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async {
|
||||
? null
|
||||
: translate('Too short, at least 6 characters.');
|
||||
},
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
TextFormField(
|
||||
obscureText: true,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
@@ -85,7 +85,7 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async {
|
||||
? null
|
||||
: translate('The confirmation is not identical.');
|
||||
},
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
])),
|
||||
onCancel: close,
|
||||
onSubmit: (validateLength && validateSame) ? submit : null,
|
||||
@@ -216,7 +216,7 @@ void showServerSettingsWithValue(
|
||||
),
|
||||
validator: validator,
|
||||
autofocus: autofocus,
|
||||
),
|
||||
).workaroundFreezeLinuxMint(),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -229,7 +229,7 @@ void showServerSettingsWithValue(
|
||||
errorText: errorMsg.isEmpty ? null : errorMsg,
|
||||
),
|
||||
validator: validator,
|
||||
);
|
||||
).workaroundFreezeLinuxMint();
|
||||
}
|
||||
|
||||
return CustomAlertDialog(
|
||||
|
||||
@@ -323,10 +323,10 @@ class ServerModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
toggleClipboard() async {
|
||||
_clipboardOk = !_clipboardOk;
|
||||
_clipboardOk = !clipboardOk;
|
||||
bind.mainSetOption(
|
||||
key: kOptionEnableClipboard,
|
||||
value: _clipboardOk ? defaultOptionYes : 'N');
|
||||
value: clipboardOk ? defaultOptionYes : 'N');
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class StateGlobal {
|
||||
final RxDouble _windowBorderWidth = RxDouble(kWindowBorderWidth);
|
||||
final RxBool showRemoteToolBar = false.obs;
|
||||
final svcStatus = SvcStatus.notReady.obs;
|
||||
final RxInt videoConnCount = 0.obs;
|
||||
final RxBool isFocused = false.obs;
|
||||
// for mobile and web
|
||||
bool isInMainPage = true;
|
||||
|
||||
@@ -1364,13 +1364,13 @@ packages:
|
||||
source: hosted
|
||||
version: "6.2.2"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03"
|
||||
sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.4"
|
||||
version: "6.3.2"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# 1.1.9-1 works for android, but for ios it becomes 1.1.91, need to set it to 1.1.9-a.1 for iOS, will get 1.1.9.1, but iOS store not allow 4 numbers
|
||||
version: 1.3.5+54
|
||||
version: 1.3.6+55
|
||||
|
||||
environment:
|
||||
sdk: '^3.1.0'
|
||||
@@ -36,6 +36,7 @@ dependencies:
|
||||
#firebase_analytics: ^9.1.5
|
||||
package_info_plus: ^4.2.0
|
||||
url_launcher: ^6.2.1
|
||||
url_launcher_ios: ^6.3.2
|
||||
toggle_switch: ^2.1.0
|
||||
dash_chat_2:
|
||||
git:
|
||||
|
||||
@@ -211,6 +211,11 @@ struct wf_clipboard
|
||||
BOOL sync;
|
||||
UINT32 capabilities;
|
||||
|
||||
// This flag is not really needed,
|
||||
// but we can use it to double confirm that files can only be pasted after `Ctrl+C`.
|
||||
// Not sure `is_file_descriptor_from_remote()` is engough to check all cases on all Windows.
|
||||
BOOL copied;
|
||||
|
||||
size_t map_size;
|
||||
size_t map_capacity;
|
||||
formatMapping *format_mappings;
|
||||
@@ -263,6 +268,8 @@ static UINT cliprdr_send_request_filecontents(wfClipboard *clipboard, UINT32 con
|
||||
ULONG index, UINT32 flag, DWORD positionhigh,
|
||||
DWORD positionlow, ULONG request);
|
||||
|
||||
static BOOL is_file_descriptor_from_remote();
|
||||
|
||||
static void CliprdrDataObject_Delete(CliprdrDataObject *instance);
|
||||
|
||||
static CliprdrEnumFORMATETC *CliprdrEnumFORMATETC_New(ULONG nFormats, FORMATETC *pFormatEtc);
|
||||
@@ -712,6 +719,15 @@ static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject *This, FO
|
||||
if (!clipboard)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// If `Ctrl+C` is not pressed yet, do not handle the file paste, and empty the clipboard.
|
||||
if (!clipboard->copied) {
|
||||
if (try_open_clipboard(clipboard->hwnd)) {
|
||||
EmptyClipboard();
|
||||
CloseClipboard();
|
||||
}
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if ((idx = cliprdr_lookup_format(instance, pFormatEtc)) == -1)
|
||||
{
|
||||
// empty clipboard here?
|
||||
@@ -1479,6 +1495,8 @@ static UINT cliprdr_send_format_list(wfClipboard *clipboard, UINT32 connID)
|
||||
|
||||
// send
|
||||
rc = clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
||||
// No need to check `rc`, `copied` is only used to indicate `Ctrl+C` is pressed.
|
||||
clipboard->copied = TRUE;
|
||||
|
||||
for (index = 0; index < numFormats; index++)
|
||||
{
|
||||
@@ -2274,7 +2292,9 @@ static UINT wf_cliprdr_monitor_ready(CliprdrClientContext *context,
|
||||
if (rc != CHANNEL_RC_OK)
|
||||
return rc;
|
||||
|
||||
return cliprdr_send_format_list(clipboard, monitorReady->connID);
|
||||
return rc;
|
||||
// Don't send format list here, because we don't want to paste files copied before the connection.
|
||||
// return cliprdr_send_format_list(clipboard, monitorReady->connID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2321,11 +2341,20 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext *context,
|
||||
UINT32 i;
|
||||
formatMapping *mapping;
|
||||
CLIPRDR_FORMAT *format;
|
||||
wfClipboard *clipboard = (wfClipboard *)context->Custom;
|
||||
wfClipboard *clipboard = NULL;
|
||||
|
||||
if (!context || !formatList)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
clipboard = (wfClipboard *)context->Custom;
|
||||
if (!clipboard)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
if (!clear_format_map(clipboard))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
clipboard->copied = TRUE;
|
||||
|
||||
for (i = 0; i < formatList->numFormats; i++)
|
||||
{
|
||||
format = &(formatList->formats[i]);
|
||||
@@ -3060,6 +3089,19 @@ wf_cliprdr_server_file_contents_response(CliprdrClientContext *context,
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL is_file_descriptor_from_remote()
|
||||
{
|
||||
UINT fsid = 0;
|
||||
if (IsClipboardFormatAvailable(CF_HDROP)) {
|
||||
return FALSE;
|
||||
}
|
||||
fsid = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
|
||||
if (IsClipboardFormatAvailable(fsid)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||
{
|
||||
if (!clipboard || !cliprdr)
|
||||
@@ -3071,6 +3113,7 @@ BOOL wf_cliprdr_init(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||
clipboard->map_size = 0;
|
||||
clipboard->hUser32 = LoadLibraryA("user32.dll");
|
||||
clipboard->data_obj = NULL;
|
||||
clipboard->copied = FALSE;
|
||||
|
||||
if (clipboard->hUser32)
|
||||
{
|
||||
@@ -3126,14 +3169,18 @@ BOOL wf_cliprdr_uninit(wfClipboard *clipboard, CliprdrClientContext *cliprdr)
|
||||
if (!clipboard || !cliprdr)
|
||||
return FALSE;
|
||||
|
||||
clipboard->copied = FALSE;
|
||||
cliprdr->Custom = NULL;
|
||||
|
||||
/* discard all contexts in clipboard */
|
||||
if (try_open_clipboard(clipboard->hwnd))
|
||||
{
|
||||
if (!EmptyClipboard())
|
||||
if (is_file_descriptor_from_remote())
|
||||
{
|
||||
DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError());
|
||||
if (!EmptyClipboard())
|
||||
{
|
||||
DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError());
|
||||
}
|
||||
}
|
||||
if (!CloseClipboard())
|
||||
{
|
||||
@@ -3227,6 +3274,8 @@ BOOL wf_do_empty_cliprdr(wfClipboard *clipboard)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
clipboard->copied = FALSE;
|
||||
|
||||
if (WaitForSingleObject(clipboard->data_obj_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||
{
|
||||
return FALSE;
|
||||
@@ -3248,10 +3297,14 @@ BOOL wf_do_empty_cliprdr(wfClipboard *clipboard)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!EmptyClipboard())
|
||||
if (is_file_descriptor_from_remote())
|
||||
{
|
||||
rc = FALSE;
|
||||
if (!EmptyClipboard())
|
||||
{
|
||||
rc = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CloseClipboard())
|
||||
{
|
||||
// critical error!!!
|
||||
|
||||
@@ -284,7 +284,9 @@ enum ControlKey {
|
||||
}
|
||||
|
||||
message KeyEvent {
|
||||
// `down` indicates the key's state(down or up).
|
||||
bool down = 1;
|
||||
// `press` indicates a click event(down and up).
|
||||
bool press = 2;
|
||||
oneof union {
|
||||
ControlKey control_key = 3;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rustdesk-portable-packer"
|
||||
version = "1.3.5"
|
||||
version = "1.3.6"
|
||||
edition = "2021"
|
||||
description = "RustDesk Remote Desktop"
|
||||
|
||||
|
||||
@@ -371,14 +371,6 @@ pub fn call_clipboard_manager_update_clipboard(data: &[u8]) -> JniResult<()> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_clipboard_manager_enable_service_clipboard(enable: bool) -> JniResult<()> {
|
||||
_call_clipboard_manager(
|
||||
"rustEnableServiceClipboard",
|
||||
"(Z)V",
|
||||
&[JValue::Bool(jboolean::from(enable))],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn call_clipboard_manager_enable_client_clipboard(enable: bool) -> JniResult<()> {
|
||||
_call_clipboard_manager(
|
||||
"rustEnableClientClipboard",
|
||||
|
||||
@@ -692,8 +692,8 @@ pub fn check_available_hwcodec() -> String {
|
||||
#[cfg(not(feature = "vram"))]
|
||||
let vram_string = "".to_owned();
|
||||
let c = HwCodecConfig {
|
||||
ram_encode: Encoder::available_encoders(ctx, Some(vram_string.clone())),
|
||||
ram_decode: Decoder::available_decoders(Some(vram_string)),
|
||||
ram_encode: Encoder::available_encoders(ctx, Some(vram_string)),
|
||||
ram_decode: Decoder::available_decoders(),
|
||||
#[cfg(feature = "vram")]
|
||||
vram_encode: vram.0,
|
||||
#[cfg(feature = "vram")]
|
||||
|
||||
@@ -5,7 +5,7 @@ set -e
|
||||
if [ "$1" = configure ]; then
|
||||
|
||||
INITSYS=$(ls -al /proc/1/exe | awk -F' ' '{print $NF}' | awk -F'/' '{print $NF}')
|
||||
ln -s /usr/lib/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
ln -s /usr/share/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
|
||||
if [ "systemd" == "$INITSYS" ]; then
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
pkgname=rustdesk
|
||||
pkgver=1.3.5
|
||||
pkgver=1.3.6
|
||||
pkgrel=0
|
||||
epoch=
|
||||
pkgdesc=""
|
||||
@@ -23,10 +23,10 @@ md5sums=() #generate with 'makepkg -g'
|
||||
|
||||
package() {
|
||||
if [[ ${FLUTTER} ]]; then
|
||||
mkdir -p "${pkgdir}/usr/lib/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "${pkgdir}/usr/lib/rustdesk"
|
||||
mkdir -p "${pkgdir}/usr/share/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "${pkgdir}/usr/share/rustdesk"
|
||||
fi
|
||||
mkdir -p "${pkgdir}/usr/bin"
|
||||
pushd ${pkgdir} && ln -s /usr/lib/rustdesk/rustdesk usr/bin/rustdesk && popd
|
||||
pushd ${pkgdir} && ln -s /usr/share/rustdesk/rustdesk usr/bin/rustdesk && popd
|
||||
install -Dm 644 $HBB/res/rustdesk.service -t "${pkgdir}/usr/share/rustdesk/files"
|
||||
install -Dm 644 $HBB/res/rustdesk.desktop -t "${pkgdir}/usr/share/rustdesk/files"
|
||||
install -Dm 644 $HBB/res/rustdesk-link.desktop -t "${pkgdir}/usr/share/rustdesk/files"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: rustdesk
|
||||
Version: 1.3.5
|
||||
Version: 1.3.6
|
||||
Release: 0
|
||||
Summary: RPM package
|
||||
License: GPL-3.0
|
||||
@@ -9,6 +9,8 @@ Requires: gtk3 libxcb1 xdotool libXfixes3 alsa-utils libXtst6 libva2 pam gstre
|
||||
Recommends: libayatana-appindicator3-1
|
||||
Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libfile_selector_linux_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit)
|
||||
|
||||
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
|
||||
|
||||
%description
|
||||
The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
@@ -22,7 +24,7 @@ The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
%install
|
||||
|
||||
mkdir -p "%{buildroot}/usr/lib/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "%{buildroot}/usr/lib/rustdesk"
|
||||
mkdir -p "%{buildroot}/usr/share/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "%{buildroot}/usr/share/rustdesk"
|
||||
mkdir -p "%{buildroot}/usr/bin"
|
||||
install -Dm 644 $HBB/res/rustdesk.service -t "%{buildroot}/usr/share/rustdesk/files"
|
||||
install -Dm 644 $HBB/res/rustdesk.desktop -t "%{buildroot}/usr/share/rustdesk/files"
|
||||
@@ -31,7 +33,7 @@ install -Dm 644 $HBB/res/128x128@2x.png "%{buildroot}/usr/share/icons/hicolor/25
|
||||
install -Dm 644 $HBB/res/scalable.svg "%{buildroot}/usr/share/icons/hicolor/scalable/apps/rustdesk.svg"
|
||||
|
||||
%files
|
||||
/usr/lib/rustdesk/*
|
||||
/usr/share/rustdesk/*
|
||||
/usr/share/rustdesk/files/rustdesk.service
|
||||
/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -41,7 +43,6 @@ install -Dm 644 $HBB/res/scalable.svg "%{buildroot}/usr/share/icons/hicolor/scal
|
||||
%changelog
|
||||
# let's skip this for now
|
||||
|
||||
# https://www.cnblogs.com/xingmuxin/p/8990255.html
|
||||
%pre
|
||||
# can do something for centos7
|
||||
case "$1" in
|
||||
@@ -58,7 +59,7 @@ esac
|
||||
cp /usr/share/rustdesk/files/rustdesk.service /etc/systemd/system/rustdesk.service
|
||||
cp /usr/share/rustdesk/files/rustdesk.desktop /usr/share/applications/
|
||||
cp /usr/share/rustdesk/files/rustdesk-link.desktop /usr/share/applications/
|
||||
ln -s /usr/lib/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
ln -sf /usr/share/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
systemctl daemon-reload
|
||||
systemctl enable rustdesk
|
||||
systemctl start rustdesk
|
||||
@@ -81,12 +82,17 @@ esac
|
||||
case "$1" in
|
||||
0)
|
||||
# for uninstall
|
||||
rm /usr/bin/rustdesk || true
|
||||
rmdir /usr/lib/rustdesk || true
|
||||
rmdir /usr/local/rustdesk || true
|
||||
rmdir /usr/share/rustdesk || true
|
||||
rm /usr/share/applications/rustdesk.desktop || true
|
||||
rm /usr/share/applications/rustdesk-link.desktop || true
|
||||
rm /usr/bin/rustdesk || true
|
||||
update-desktop-database
|
||||
;;
|
||||
1)
|
||||
# for upgrade
|
||||
rmdir /usr/lib/rustdesk || true
|
||||
rmdir /usr/local/rustdesk || true
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: rustdesk
|
||||
Version: 1.3.5
|
||||
Version: 1.3.6
|
||||
Release: 0
|
||||
Summary: RPM package
|
||||
License: GPL-3.0
|
||||
@@ -9,6 +9,8 @@ Requires: gtk3 libxcb libxdo libXfixes alsa-lib libva pam gstreamer1-plugins-b
|
||||
Recommends: libayatana-appindicator-gtk3
|
||||
Provides: libdesktop_drop_plugin.so()(64bit), libdesktop_multi_window_plugin.so()(64bit), libfile_selector_linux_plugin.so()(64bit), libflutter_custom_cursor_plugin.so()(64bit), libflutter_linux_gtk.so()(64bit), libscreen_retriever_plugin.so()(64bit), libtray_manager_plugin.so()(64bit), liburl_launcher_linux_plugin.so()(64bit), libwindow_manager_plugin.so()(64bit), libwindow_size_plugin.so()(64bit), libtexture_rgba_renderer_plugin.so()(64bit)
|
||||
|
||||
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
|
||||
|
||||
%description
|
||||
The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
@@ -22,7 +24,7 @@ The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
%install
|
||||
|
||||
mkdir -p "%{buildroot}/usr/lib/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "%{buildroot}/usr/lib/rustdesk"
|
||||
mkdir -p "%{buildroot}/usr/share/rustdesk" && cp -r ${HBB}/flutter/build/linux/x64/release/bundle/* -t "%{buildroot}/usr/share/rustdesk"
|
||||
mkdir -p "%{buildroot}/usr/bin"
|
||||
install -Dm 644 $HBB/res/rustdesk.service -t "%{buildroot}/usr/share/rustdesk/files"
|
||||
install -Dm 644 $HBB/res/rustdesk.desktop -t "%{buildroot}/usr/share/rustdesk/files"
|
||||
@@ -31,7 +33,7 @@ install -Dm 644 $HBB/res/128x128@2x.png "%{buildroot}/usr/share/icons/hicolor/25
|
||||
install -Dm 644 $HBB/res/scalable.svg "%{buildroot}/usr/share/icons/hicolor/scalable/apps/rustdesk.svg"
|
||||
|
||||
%files
|
||||
/usr/lib/rustdesk/*
|
||||
/usr/share/rustdesk/*
|
||||
/usr/share/rustdesk/files/rustdesk.service
|
||||
/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -41,7 +43,6 @@ install -Dm 644 $HBB/res/scalable.svg "%{buildroot}/usr/share/icons/hicolor/scal
|
||||
%changelog
|
||||
# let's skip this for now
|
||||
|
||||
# https://www.cnblogs.com/xingmuxin/p/8990255.html
|
||||
%pre
|
||||
# can do something for centos7
|
||||
case "$1" in
|
||||
@@ -58,7 +59,7 @@ esac
|
||||
cp /usr/share/rustdesk/files/rustdesk.service /etc/systemd/system/rustdesk.service
|
||||
cp /usr/share/rustdesk/files/rustdesk.desktop /usr/share/applications/
|
||||
cp /usr/share/rustdesk/files/rustdesk-link.desktop /usr/share/applications/
|
||||
ln -s /usr/lib/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
ln -sf /usr/share/rustdesk/rustdesk /usr/bin/rustdesk
|
||||
systemctl daemon-reload
|
||||
systemctl enable rustdesk
|
||||
systemctl start rustdesk
|
||||
@@ -81,12 +82,17 @@ esac
|
||||
case "$1" in
|
||||
0)
|
||||
# for uninstall
|
||||
rm /usr/bin/rustdesk || true
|
||||
rmdir /usr/lib/rustdesk || true
|
||||
rmdir /usr/local/rustdesk || true
|
||||
rmdir /usr/share/rustdesk || true
|
||||
rm /usr/share/applications/rustdesk.desktop || true
|
||||
rm /usr/share/applications/rustdesk-link.desktop || true
|
||||
rm /usr/bin/rustdesk || true
|
||||
update-desktop-database
|
||||
;;
|
||||
1)
|
||||
# for upgrade
|
||||
rmdir /usr/lib/rustdesk || true
|
||||
rmdir /usr/local/rustdesk || true
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -6,6 +6,8 @@ License: GPL-3.0
|
||||
Requires: gtk3 libxcb1 xdotool libXfixes3 alsa-utils libXtst6 libva2 pam gstreamer-plugins-base gstreamer-plugin-pipewire
|
||||
Recommends: libayatana-appindicator3-1
|
||||
|
||||
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
|
||||
|
||||
%description
|
||||
The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
@@ -19,12 +21,12 @@ The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/usr/bin/
|
||||
mkdir -p %{buildroot}/usr/lib/rustdesk/
|
||||
mkdir -p %{buildroot}/usr/share/rustdesk/
|
||||
mkdir -p %{buildroot}/usr/share/rustdesk/files/
|
||||
mkdir -p %{buildroot}/usr/share/icons/hicolor/256x256/apps/
|
||||
mkdir -p %{buildroot}/usr/share/icons/hicolor/scalable/apps/
|
||||
install -m 755 $HBB/target/release/rustdesk %{buildroot}/usr/bin/rustdesk
|
||||
install $HBB/libsciter-gtk.so %{buildroot}/usr/lib/rustdesk/libsciter-gtk.so
|
||||
install $HBB/libsciter-gtk.so %{buildroot}/usr/share/rustdesk/libsciter-gtk.so
|
||||
install $HBB/res/rustdesk.service %{buildroot}/usr/share/rustdesk/files/
|
||||
install $HBB/res/128x128@2x.png %{buildroot}/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
install $HBB/res/scalable.svg %{buildroot}/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -33,7 +35,7 @@ install $HBB/res/rustdesk-link.desktop %{buildroot}/usr/share/rustdesk/files/
|
||||
|
||||
%files
|
||||
/usr/bin/rustdesk
|
||||
/usr/lib/rustdesk/libsciter-gtk.so
|
||||
/usr/share/rustdesk/libsciter-gtk.so
|
||||
/usr/share/rustdesk/files/rustdesk.service
|
||||
/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -43,7 +45,6 @@ install $HBB/res/rustdesk-link.desktop %{buildroot}/usr/share/rustdesk/files/
|
||||
%changelog
|
||||
# let's skip this for now
|
||||
|
||||
# https://www.cnblogs.com/xingmuxin/p/8990255.html
|
||||
%pre
|
||||
# can do something for centos7
|
||||
case "$1" in
|
||||
|
||||
11
res/rpm.spec
11
res/rpm.spec
@@ -1,5 +1,5 @@
|
||||
Name: rustdesk
|
||||
Version: 1.3.5
|
||||
Version: 1.3.6
|
||||
Release: 0
|
||||
Summary: RPM package
|
||||
License: GPL-3.0
|
||||
@@ -8,6 +8,8 @@ Vendor: rustdesk <info@rustdesk.com>
|
||||
Requires: gtk3 libxcb libxdo libXfixes alsa-lib libva2 pam gstreamer1-plugins-base
|
||||
Recommends: libayatana-appindicator-gtk3
|
||||
|
||||
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/
|
||||
|
||||
%description
|
||||
The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
@@ -21,12 +23,12 @@ The best open-source remote desktop client software, written in Rust.
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/usr/bin/
|
||||
mkdir -p %{buildroot}/usr/lib/rustdesk/
|
||||
mkdir -p %{buildroot}/usr/share/rustdesk/
|
||||
mkdir -p %{buildroot}/usr/share/rustdesk/files/
|
||||
mkdir -p %{buildroot}/usr/share/icons/hicolor/256x256/apps/
|
||||
mkdir -p %{buildroot}/usr/share/icons/hicolor/scalable/apps/
|
||||
install -m 755 $HBB/target/release/rustdesk %{buildroot}/usr/bin/rustdesk
|
||||
install $HBB/libsciter-gtk.so %{buildroot}/usr/lib/rustdesk/libsciter-gtk.so
|
||||
install $HBB/libsciter-gtk.so %{buildroot}/usr/share/rustdesk/libsciter-gtk.so
|
||||
install $HBB/res/rustdesk.service %{buildroot}/usr/share/rustdesk/files/
|
||||
install $HBB/res/128x128@2x.png %{buildroot}/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
install $HBB/res/scalable.svg %{buildroot}/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -35,7 +37,7 @@ install $HBB/res/rustdesk-link.desktop %{buildroot}/usr/share/rustdesk/files/
|
||||
|
||||
%files
|
||||
/usr/bin/rustdesk
|
||||
/usr/lib/rustdesk/libsciter-gtk.so
|
||||
/usr/share/rustdesk/libsciter-gtk.so
|
||||
/usr/share/rustdesk/files/rustdesk.service
|
||||
/usr/share/icons/hicolor/256x256/apps/rustdesk.png
|
||||
/usr/share/icons/hicolor/scalable/apps/rustdesk.svg
|
||||
@@ -46,7 +48,6 @@ install $HBB/res/rustdesk-link.desktop %{buildroot}/usr/share/rustdesk/files/
|
||||
%changelog
|
||||
# let's skip this for now
|
||||
|
||||
# https://www.cnblogs.com/xingmuxin/p/8990255.html
|
||||
%pre
|
||||
# can do something for centos7
|
||||
case "$1" in
|
||||
|
||||
@@ -8,16 +8,28 @@ vcpkg_find_acquire_program(PERL)
|
||||
get_filename_component(PERL_PATH ${PERL} DIRECTORY)
|
||||
vcpkg_add_to_path(${PERL_PATH})
|
||||
|
||||
vcpkg_from_git(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
URL "https://aomedia.googlesource.com/aom"
|
||||
REF 8ad484f8a18ed1853c094e7d3a4e023b2a92df28 # 3.9.1
|
||||
PATCHES
|
||||
aom-uninitialized-pointer.diff
|
||||
aom-avx2.diff
|
||||
# Can be dropped when https://bugs.chromium.org/p/aomedia/issues/detail?id=3029 is merged into the upstream
|
||||
aom-install.diff
|
||||
)
|
||||
if(DEFINED ENV{USE_AOM_391})
|
||||
vcpkg_from_git(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
URL "https://aomedia.googlesource.com/aom"
|
||||
REF 8ad484f8a18ed1853c094e7d3a4e023b2a92df28 # 3.9.1
|
||||
PATCHES
|
||||
aom-uninitialized-pointer.diff
|
||||
aom-avx2.diff
|
||||
aom-install.diff
|
||||
)
|
||||
else()
|
||||
vcpkg_from_git(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
URL "https://aomedia.googlesource.com/aom"
|
||||
REF d6f30ae474dd6c358f26de0a0fc26a0d7340a84c # 3.11.0
|
||||
PATCHES
|
||||
aom-uninitialized-pointer.diff
|
||||
# aom-avx2.diff
|
||||
# Can be dropped when https://bugs.chromium.org/p/aomedia/issues/detail?id=3029 is merged into the upstream
|
||||
aom-install.diff
|
||||
)
|
||||
endif()
|
||||
|
||||
set(aom_target_cpu "")
|
||||
if(VCPKG_TARGET_IS_UWP OR (VCPKG_TARGET_IS_WINDOWS AND VCPKG_TARGET_ARCHITECTURE MATCHES "^arm"))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "aom",
|
||||
"version-semver": "3.9.1",
|
||||
"version-semver": "3.11.0",
|
||||
"port-version": 0,
|
||||
"description": "AV1 codec library",
|
||||
"homepage": "https://aomedia.googlesource.com/aom",
|
||||
|
||||
27
res/vcpkg/ffmpeg/0001-create-lib-libraries.patch
Normal file
27
res/vcpkg/ffmpeg/0001-create-lib-libraries.patch
Normal file
@@ -0,0 +1,27 @@
|
||||
diff --git a/configure b/configure
|
||||
index 1f0b9497cb..3243e23021 100644
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -5697,17 +5697,19 @@ case $target_os in
|
||||
;;
|
||||
win32|win64)
|
||||
disable symver
|
||||
- if enabled shared; then
|
||||
+# if enabled shared; then
|
||||
# Link to the import library instead of the normal static library
|
||||
# for shared libs.
|
||||
LD_LIB='%.lib'
|
||||
# Cannot build both shared and static libs with MSVC or icl.
|
||||
- disable static
|
||||
- fi
|
||||
+# disable static
|
||||
+# fi
|
||||
! enabled small && test_cmd $windres --version && enable gnu_windres
|
||||
enabled x86_32 && check_ldflags -LARGEADDRESSAWARE
|
||||
add_cppflags -DWIN32_LEAN_AND_MEAN
|
||||
shlibdir_default="$bindir_default"
|
||||
+ LIBPREF=""
|
||||
+ LIBSUF=".lib"
|
||||
SLIBPREF=""
|
||||
SLIBSUF=".dll"
|
||||
SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)'
|
||||
65
res/vcpkg/ffmpeg/0004-dependencies.patch
Normal file
65
res/vcpkg/ffmpeg/0004-dependencies.patch
Normal file
@@ -0,0 +1,65 @@
|
||||
diff --git a/configure b/configure
|
||||
index a8b74e0..c99f41c 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -6633,7 +6633,7 @@ fi
|
||||
|
||||
enabled zlib && { check_pkg_config zlib zlib "zlib.h" zlibVersion ||
|
||||
check_lib zlib zlib.h zlibVersion -lz; }
|
||||
-enabled bzlib && check_lib bzlib bzlib.h BZ2_bzlibVersion -lbz2
|
||||
+enabled bzlib && require_pkg_config bzlib bzip2 bzlib.h BZ2_bzlibVersion
|
||||
enabled lzma && check_lib lzma lzma.h lzma_version_number -llzma
|
||||
|
||||
enabled zlib && test_exec $zlib_extralibs <<EOF && enable zlib_gzip
|
||||
@@ -6757,7 +6757,8 @@ if enabled libmfx; then
|
||||
fi
|
||||
|
||||
enabled libmodplug && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load
|
||||
-enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs
|
||||
+enabled libmp3lame && { check_lib libmp3lame lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs ||
|
||||
+ require libmp3lame lame/lame.h lame_set_VBR_quality -llibmp3lame-static -llibmpghip-static $libm_extralibs; }
|
||||
enabled libmysofa && { check_pkg_config libmysofa libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine ||
|
||||
require libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine -lmysofa $zlib_extralibs; }
|
||||
enabled libnpp && { check_lib libnpp npp.h nppGetLibVersion -lnppig -lnppicc -lnppc -lnppidei -lnppif ||
|
||||
@@ -6772,7 +6773,7 @@ require_pkg_config libopencv opencv opencv/cxcore.h cvCreateImageHeader; }
|
||||
enabled libopenh264 && require_pkg_config libopenh264 "openh264 >= 1.3.0" wels/codec_api.h WelsGetCodecVersion
|
||||
enabled libopenjpeg && { check_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version ||
|
||||
{ require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } }
|
||||
-enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++"
|
||||
+enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create
|
||||
enabled libopenvino && { { check_pkg_config libopenvino openvino openvino/c/openvino.h ov_core_create && enable openvino2; } ||
|
||||
{ check_pkg_config libopenvino openvino c_api/ie_c_api.h ie_c_api_version ||
|
||||
require libopenvino c_api/ie_c_api.h ie_c_api_version -linference_engine_c_api; } }
|
||||
@@ -6796,8 +6797,8 @@ enabled libshaderc && require_pkg_config spirv_compiler "shaderc >= 2019.
|
||||
enabled libshine && require_pkg_config libshine shine shine/layer3.h shine_encode_buffer
|
||||
enabled libsmbclient && { check_pkg_config libsmbclient smbclient libsmbclient.h smbc_init ||
|
||||
require libsmbclient libsmbclient.h smbc_init -lsmbclient; }
|
||||
-enabled libsnappy && require libsnappy snappy-c.h snappy_compress -lsnappy -lstdc++
|
||||
-enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr
|
||||
+enabled libsnappy && require_pkg_config libsnappy snappy snappy-c.h snappy_compress
|
||||
+enabled libsoxr && require libsoxr soxr.h soxr_create -lsoxr $libm_extralibs
|
||||
enabled libssh && require_pkg_config libssh "libssh >= 0.6.0" libssh/sftp.h sftp_init
|
||||
enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init
|
||||
enabled libsrt && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket
|
||||
@@ -6880,6 +6881,8 @@ enabled openal && { check_pkg_config openal "openal >= 1.1" "AL/al.h"
|
||||
enabled opencl && { check_pkg_config opencl OpenCL CL/cl.h clEnqueueNDRangeKernel ||
|
||||
check_lib opencl OpenCL/cl.h clEnqueueNDRangeKernel "-framework OpenCL" ||
|
||||
check_lib opencl CL/cl.h clEnqueueNDRangeKernel -lOpenCL ||
|
||||
+ check_lib opencl CL/cl.h clEnqueueNDRangeKernel -lOpenCL -lAdvapi32 -lOle32 -lCfgmgr32||
|
||||
+ check_lib opencl CL/cl.h clEnqueueNDRangeKernel -lOpenCL -pthread -ldl ||
|
||||
die "ERROR: opencl not found"; } &&
|
||||
{ test_cpp_condition "OpenCL/cl.h" "defined(CL_VERSION_1_2)" ||
|
||||
test_cpp_condition "CL/cl.h" "defined(CL_VERSION_1_2)" ||
|
||||
@@ -7204,10 +7207,10 @@ enabled amf &&
|
||||
"(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400210000"
|
||||
|
||||
# Funny iconv installations are not unusual, so check it after all flags have been set
|
||||
-if enabled libc_iconv; then
|
||||
+if enabled libc_iconv && disabled iconv; then
|
||||
check_func_headers iconv.h iconv
|
||||
elif enabled iconv; then
|
||||
- check_func_headers iconv.h iconv || check_lib iconv iconv.h iconv -liconv
|
||||
+ check_func_headers iconv.h iconv || check_lib iconv iconv.h iconv -liconv || check_lib iconv iconv.h iconv -liconv -lcharset
|
||||
fi
|
||||
|
||||
enabled debug && add_cflags -g"$debuglevel" && add_asflags -g"$debuglevel"
|
||||
@@ -1,55 +1,78 @@
|
||||
diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile
|
||||
--- a/libavcodec/x86/Makefile
|
||||
+++ b/libavcodec/x86/Makefile
|
||||
@@ -158,6 +158,8 @@ X86ASM-OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_APNG_DECODER) += x86/pngdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsidct.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_CFHD_ENCODER) += x86/cfhdencdsp.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_CFHD_DECODER) += x86/cfhddsp.o
|
||||
X86ASM-OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp.o x86/synth_filter.o
|
||||
X86ASM-OBJS-$(CONFIG_DIRAC_DECODER) += x86/diracdsp.o \
|
||||
@@ -175,15 +177,21 @@ x86/hevc_sao_10bit.o
|
||||
X86ASM-OBJS-$(CONFIG_JPEG2000_DECODER) += x86/jpeg2000dsp.o
|
||||
X86ASM-OBJS-$(CONFIG_LSCR_DECODER) += x86/pngdsp.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_MLP_DECODER) += x86/mlpdsp.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_MPEG4_DECODER) += x86/xvididct.o
|
||||
X86ASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_PRORES_LGPL_DECODER) += x86/proresdsp.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv40dsp.o
|
||||
X86ASM-OBJS-$(CONFIG_SBC_ENCODER) += x86/sbcdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc.o
|
||||
X86ASM-OBJS-$(CONFIG_TAK_DECODER) += x86/takdsp.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_TRUEHD_DECODER) += x86/mlpdsp.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_TTA_DECODER) += x86/ttadsp.o
|
||||
X86ASM-OBJS-$(CONFIG_TTA_ENCODER) += x86/ttaencdsp.o
|
||||
X86ASM-OBJS-$(CONFIG_UTVIDEO_DECODER) += x86/utvideodsp.o
|
||||
diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile
|
||||
--- a/libavfilter/x86/Makefile
|
||||
+++ b/libavfilter/x86/Makefile
|
||||
@@ -44,6 +44,8 @@
|
||||
X86ASM-OBJS-$(CONFIG_AFIR_FILTER) += x86/af_afir.o
|
||||
X86ASM-OBJS-$(CONFIG_ANLMDN_FILTER) += x86/af_anlmdn.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_ATADENOISE_FILTER) += x86/vf_atadenoise.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend.o
|
||||
X86ASM-OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif.o
|
||||
X86ASM-OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp.o
|
||||
@@ -62,6 +62,8 @@ X86ASM-OBJS-$(CONFIG_LUT3D_FILTER) += x86/vf_lut3d.o
|
||||
X86ASM-OBJS-$(CONFIG_MASKEDCLAMP_FILTER) += x86/vf_maskedclamp.o
|
||||
X86ASM-OBJS-$(CONFIG_MASKEDMERGE_FILTER) += x86/vf_maskedmerge.o
|
||||
+ifdef ARCH_X86_64
|
||||
X86ASM-OBJS-$(CONFIG_NLMEANS_FILTER) += x86/vf_nlmeans.o
|
||||
+endif
|
||||
X86ASM-OBJS-$(CONFIG_OVERLAY_FILTER) += x86/vf_overlay.o
|
||||
X86ASM-OBJS-$(CONFIG_PP7_FILTER) += x86/vf_pp7.o
|
||||
X86ASM-OBJS-$(CONFIG_PSNR_FILTER) += x86/vf_psnr.o
|
||||
diff --git a/libavcodec/x86/mlpdsp.asm b/libavcodec/x86/mlpdsp.asm
|
||||
index 3dc641e..609b834 100644
|
||||
--- a/libavcodec/x86/mlpdsp.asm
|
||||
+++ b/libavcodec/x86/mlpdsp.asm
|
||||
@@ -23,7 +23,9 @@
|
||||
|
||||
SECTION .text
|
||||
|
||||
-%if ARCH_X86_64
|
||||
+%ifn ARCH_X86_64
|
||||
+mlpdsp_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
%macro SHLX 2
|
||||
%if cpuflag(bmi2)
|
||||
diff --git a/libavcodec/x86/proresdsp.asm b/libavcodec/x86/proresdsp.asm
|
||||
index 65c9fad..5ad73f3 100644
|
||||
--- a/libavcodec/x86/proresdsp.asm
|
||||
+++ b/libavcodec/x86/proresdsp.asm
|
||||
@@ -24,7 +24,10 @@
|
||||
|
||||
%include "libavutil/x86/x86util.asm"
|
||||
|
||||
-%if ARCH_X86_64
|
||||
+%ifn ARCH_X86_64
|
||||
+SECTION .rdata
|
||||
+proresdsp_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
SECTION_RODATA
|
||||
|
||||
diff --git a/libavcodec/x86/vvc/vvc_mc.asm b/libavcodec/x86/vvc/vvc_mc.asm
|
||||
index 30aa97c..3975f98 100644
|
||||
--- a/libavcodec/x86/vvc/vvc_mc.asm
|
||||
+++ b/libavcodec/x86/vvc/vvc_mc.asm
|
||||
@@ -31,7 +31,9 @@
|
||||
|
||||
SECTION_RODATA 32
|
||||
|
||||
-%if ARCH_X86_64
|
||||
+%ifn ARCH_X86_64
|
||||
+vvc_mc_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
%if HAVE_AVX2_EXTERNAL
|
||||
|
||||
diff --git a/libavfilter/x86/vf_atadenoise.asm b/libavfilter/x86/vf_atadenoise.asm
|
||||
index 4945ad3..748b65a 100644
|
||||
--- a/libavfilter/x86/vf_atadenoise.asm
|
||||
+++ b/libavfilter/x86/vf_atadenoise.asm
|
||||
@@ -20,7 +20,10 @@
|
||||
;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
;******************************************************************************
|
||||
|
||||
-%if ARCH_X86_64
|
||||
+%ifn ARCH_X86_64
|
||||
+SECTION .rdata
|
||||
+vf_atadenoise_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
%include "libavutil/x86/x86util.asm"
|
||||
|
||||
diff --git a/libavfilter/x86/vf_nlmeans.asm b/libavfilter/x86/vf_nlmeans.asm
|
||||
index 8f57801..9aef3a4 100644
|
||||
--- a/libavfilter/x86/vf_nlmeans.asm
|
||||
+++ b/libavfilter/x86/vf_nlmeans.asm
|
||||
@@ -21,7 +21,10 @@
|
||||
|
||||
%include "libavutil/x86/x86util.asm"
|
||||
|
||||
-%if HAVE_AVX2_EXTERNAL && ARCH_X86_64
|
||||
+%ifn HAVE_AVX2_EXTERNAL && ARCH_X86_64
|
||||
+SECTION .rdata
|
||||
+vf_nlmeans_placeholder: times 4 db 0
|
||||
+%else
|
||||
|
||||
SECTION_RODATA 32
|
||||
|
||||
|
||||
12
res/vcpkg/ffmpeg/0007-fix-lib-naming.patch
Normal file
12
res/vcpkg/ffmpeg/0007-fix-lib-naming.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/configure b/configure
|
||||
index d6c4388..75b96c3 100644
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -4781,6 +4781,7 @@ msvc_common_flags(){
|
||||
-mfp16-format=*) ;;
|
||||
-lz) echo zlib.lib ;;
|
||||
-lx264) echo libx264.lib ;;
|
||||
+ -lmp3lame) echo libmp3lame.lib ;;
|
||||
-lstdc++) ;;
|
||||
-l*) echo ${flag#-l}.lib ;;
|
||||
-LARGEADDRESSAWARE) echo $flag ;;
|
||||
@@ -1,14 +0,0 @@
|
||||
diff --git a/configure b/configure
|
||||
index 2be953f7e7..e075949ffc 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -6497,6 +6497,7 @@ enabled openssl && { { check_pkg_config openssl "openssl >= 3.0.0
|
||||
{ enabled gplv3 || ! enabled gpl || enabled nonfree || die "ERROR: OpenSSL >=3.0.0 requires --enable-version3"; }; } ||
|
||||
{ enabled gpl && ! enabled nonfree && die "ERROR: OpenSSL <3.0.0 is incompatible with the gpl"; } ||
|
||||
check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl ||
|
||||
check_pkg_config openssl openssl openssl/ssl.h SSL_library_init ||
|
||||
+ check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto $pthreads_extralibs -ldl ||
|
||||
check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto ||
|
||||
check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto ||
|
||||
check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 ||
|
||||
|
||||
28
res/vcpkg/ffmpeg/0020-fix-aarch64-libswscale.patch
Normal file
28
res/vcpkg/ffmpeg/0020-fix-aarch64-libswscale.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
diff --git a/libswscale/aarch64/yuv2rgb_neon.S b/libswscale/aarch64/yuv2rgb_neon.S
|
||||
index 89d69e7f6c..4bc1607a7a 100644
|
||||
--- a/libswscale/aarch64/yuv2rgb_neon.S
|
||||
+++ b/libswscale/aarch64/yuv2rgb_neon.S
|
||||
@@ -169,19 +169,19 @@ function ff_\ifmt\()_to_\ofmt\()_neon, export=1
|
||||
sqdmulh v26.8h, v26.8h, v0.8h // ((Y1*(1<<3) - y_offset) * y_coeff) >> 15
|
||||
sqdmulh v27.8h, v27.8h, v0.8h // ((Y2*(1<<3) - y_offset) * y_coeff) >> 15
|
||||
|
||||
-.ifc \ofmt,argb // 1 2 3 0
|
||||
+.ifc \ofmt,argb
|
||||
compute_rgba v5.8b,v6.8b,v7.8b,v4.8b, v17.8b,v18.8b,v19.8b,v16.8b
|
||||
.endif
|
||||
|
||||
-.ifc \ofmt,rgba // 0 1 2 3
|
||||
+.ifc \ofmt,rgba
|
||||
compute_rgba v4.8b,v5.8b,v6.8b,v7.8b, v16.8b,v17.8b,v18.8b,v19.8b
|
||||
.endif
|
||||
|
||||
-.ifc \ofmt,abgr // 3 2 1 0
|
||||
+.ifc \ofmt,abgr
|
||||
compute_rgba v7.8b,v6.8b,v5.8b,v4.8b, v19.8b,v18.8b,v17.8b,v16.8b
|
||||
.endif
|
||||
|
||||
-.ifc \ofmt,bgra // 2 1 0 3
|
||||
+.ifc \ofmt,bgra
|
||||
compute_rgba v6.8b,v5.8b,v4.8b,v7.8b, v18.8b,v17.8b,v16.8b,v19.8b
|
||||
.endif
|
||||
|
||||
15
res/vcpkg/ffmpeg/0024-fix-osx-host-c11.patch
Normal file
15
res/vcpkg/ffmpeg/0024-fix-osx-host-c11.patch
Normal file
@@ -0,0 +1,15 @@
|
||||
diff --git a/configure b/configure
|
||||
index 4f5353f84b..dd9147c677 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -5607,8 +5607,8 @@ check_cppflags -D_FILE_OFFSET_BITS=64
|
||||
check_cppflags -D_LARGEFILE_SOURCE
|
||||
|
||||
add_host_cppflags -D_ISOC11_SOURCE
|
||||
check_host_cflags_cc -std=$stdc ctype.h "__STDC_VERSION__ >= 201112L" ||
|
||||
- check_host_cflags_cc -std=c11 ctype.h "__STDC_VERSION__ >= 201112L" || die "Host compiler lacks C11 support"
|
||||
+ check_host_cflags_cc -std=c11 ctype.h "__STDC_VERSION__ >= 201112L"
|
||||
|
||||
check_host_cflags -Wall
|
||||
check_host_cflags $host_cflags_speed
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
|
||||
index cd7b0d941c..b4a6dce885 100644
|
||||
--- a/libavformat/avformat.h
|
||||
+++ b/libavformat/avformat.h
|
||||
@@ -1169,7 +1169,11 @@ typedef struct AVStreamGroup {
|
||||
} AVStreamGroup;
|
||||
|
||||
struct AVCodecParserContext *av_stream_get_parser(const AVStream *s);
|
||||
|
||||
+// Chromium: We use the internal field first_dts vvv
|
||||
+int64_t av_stream_get_first_dts(const AVStream *st);
|
||||
+// Chromium: We use the internal field first_dts ^^^
|
||||
+
|
||||
#define AV_PROGRAM_RUNNING 1
|
||||
|
||||
/**
|
||||
diff --git a/libavformat/mux_utils.c b/libavformat/mux_utils.c
|
||||
index de7580c32d..0ef0fe530e 100644
|
||||
--- a/libavformat/mux_utils.c
|
||||
+++ b/libavformat/mux_utils.c
|
||||
@@ -29,7 +29,14 @@ #include "avformat.h"
|
||||
#include "avio.h"
|
||||
#include "internal.h"
|
||||
#include "mux.h"
|
||||
|
||||
+// Chromium: We use the internal field first_dts vvv
|
||||
+int64_t av_stream_get_first_dts(const AVStream *st)
|
||||
+{
|
||||
+ return cffstream(st)->first_dts;
|
||||
+}
|
||||
+// Chromium: We use the internal field first_dts ^^^
|
||||
+
|
||||
int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
|
||||
int std_compliance)
|
||||
{
|
||||
13
res/vcpkg/ffmpeg/0041-add-const-for-opengl-definition.patch
Normal file
13
res/vcpkg/ffmpeg/0041-add-const-for-opengl-definition.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c
|
||||
index b2ac6eb..6351614 100644
|
||||
--- a/libavdevice/opengl_enc.c
|
||||
+++ b/libavdevice/opengl_enc.c
|
||||
@@ -116,7 +116,7 @@ typedef void (APIENTRY *FF_PFNGLATTACHSHADERPROC) (GLuint program, GLuint shad
|
||||
typedef GLuint (APIENTRY *FF_PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRY *FF_PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRY *FF_PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
-typedef void (APIENTRY *FF_PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const char* *string, const GLint *length);
|
||||
+typedef void (APIENTRY *FF_PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const char* const *string, const GLint *length);
|
||||
typedef void (APIENTRY *FF_PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRY *FF_PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, char *infoLog);
|
||||
|
||||
9
res/vcpkg/ffmpeg/0042-fix-arm64-linux.patch
Normal file
9
res/vcpkg/ffmpeg/0042-fix-arm64-linux.patch
Normal file
@@ -0,0 +1,9 @@
|
||||
diff --git a/ffbuild/libversion.sh b/ffbuild/libversion.sh
|
||||
index a94ab58..ecaa90c 100644
|
||||
--- a/ffbuild/libversion.sh
|
||||
+++ b/ffbuild/libversion.sh
|
||||
@@ -1,3 +1,4 @@
|
||||
+#!/bin/sh
|
||||
toupper(){
|
||||
echo "$@" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
}
|
||||
12
res/vcpkg/ffmpeg/0043-fix-miss-head.patch
Normal file
12
res/vcpkg/ffmpeg/0043-fix-miss-head.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/libavfilter/textutils.c b/libavfilter/textutils.c
|
||||
index ef658d0..c61b0ad 100644
|
||||
--- a/libavfilter/textutils.c
|
||||
+++ b/libavfilter/textutils.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "libavutil/file.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/time.h"
|
||||
+#include "libavutil/time_internal.h"
|
||||
|
||||
static int ff_expand_text_function_internal(FFExpandTextContext *expand_text, AVBPrint *bp,
|
||||
char *name, unsigned argc, char **argv)
|
||||
@@ -1,7 +1,7 @@
|
||||
From f6988e5424e041ff6f6e241f4d8fa69a04c05e64 Mon Sep 17 00:00:00 2001
|
||||
From da6921d5bcb50961193526f47aa2dbe71ee5fe81 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Thu, 5 Sep 2024 16:26:20 +0800
|
||||
Subject: [PATCH 1/3] avcodec/amfenc: add query_timeout option for h264/hevc
|
||||
Date: Tue, 10 Dec 2024 13:40:46 +0800
|
||||
Subject: [PATCH 1/5] avcodec/amfenc: add query_timeout option for h264/hevc
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
@@ -11,10 +11,10 @@ Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
3 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
|
||||
index 2dbd378ef8..d636673a9d 100644
|
||||
index d985d01bb1..320c66919e 100644
|
||||
--- a/libavcodec/amfenc.h
|
||||
+++ b/libavcodec/amfenc.h
|
||||
@@ -89,6 +89,7 @@ typedef struct AmfContext {
|
||||
@@ -91,6 +91,7 @@ typedef struct AmfContext {
|
||||
int quality;
|
||||
int b_frame_delta_qp;
|
||||
int ref_b_frame_delta_qp;
|
||||
@@ -23,40 +23,40 @@ index 2dbd378ef8..d636673a9d 100644
|
||||
// Dynamic options, can be set after Init() call
|
||||
|
||||
diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c
|
||||
index c1d5f4054e..415828f005 100644
|
||||
index 8edd39c633..6ad4961b2f 100644
|
||||
--- a/libavcodec/amfenc_h264.c
|
||||
+++ b/libavcodec/amfenc_h264.c
|
||||
@@ -135,6 +135,7 @@ static const AVOption options[] = {
|
||||
{ "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
@@ -137,6 +137,7 @@ static const AVOption options[] = {
|
||||
|
||||
|
||||
{ "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg) , AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
+ { "query_timeout", "Timeout for QueryOutput call in ms", OFFSET(query_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, 1000, VE },
|
||||
|
||||
//Pre Analysis options
|
||||
{ "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE },
|
||||
@@ -222,6 +223,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
@@ -228,6 +229,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
|
||||
AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMERATE, framerate);
|
||||
|
||||
+ if (ctx->query_timeout >= 0)
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, ctx->query_timeout);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, ctx->query_timeout);
|
||||
+
|
||||
switch (avctx->profile) {
|
||||
case AV_PROFILE_H264_BASELINE:
|
||||
profile = AMF_VIDEO_ENCODER_PROFILE_BASELINE;
|
||||
diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c
|
||||
index 33a167aa52..65259d7153 100644
|
||||
index 4898824f3a..22cb95c7ce 100644
|
||||
--- a/libavcodec/amfenc_hevc.c
|
||||
+++ b/libavcodec/amfenc_hevc.c
|
||||
@@ -98,6 +98,7 @@ static const AVOption options[] = {
|
||||
{ "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE },
|
||||
@@ -104,6 +104,7 @@ static const AVOption options[] = {
|
||||
|
||||
|
||||
{ "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE },
|
||||
+ { "query_timeout", "Timeout for QueryOutput call in ms", OFFSET(query_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, 1000, VE },
|
||||
|
||||
//Pre Analysis options
|
||||
{ "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE },
|
||||
@@ -183,6 +184,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
@@ -194,6 +195,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
|
||||
AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMERATE, framerate);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 6e76c57cf2c0e790228f19c88089eef110fd74aa Mon Sep 17 00:00:00 2001
|
||||
From 8d061adb7b00fc765b8001307c025437ef1cad88 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Thu, 5 Sep 2024 16:32:16 +0800
|
||||
Subject: [PATCH 2/3] libavcodec/amfenc: reconfig when bitrate change
|
||||
Subject: [PATCH 2/5] libavcodec/amfenc: reconfig when bitrate change
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
@@ -10,10 +10,10 @@ Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
2 files changed, 21 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
|
||||
index 061859f85c..97587fe66b 100644
|
||||
index a47aea6108..f70f0109f6 100644
|
||||
--- a/libavcodec/amfenc.c
|
||||
+++ b/libavcodec/amfenc.c
|
||||
@@ -222,6 +222,7 @@ static int amf_init_context(AVCodecContext *avctx)
|
||||
@@ -275,6 +275,7 @@ static int amf_init_context(AVCodecContext *avctx)
|
||||
|
||||
ctx->hwsurfaces_in_queue = 0;
|
||||
ctx->hwsurfaces_in_queue_max = 16;
|
||||
@@ -21,7 +21,7 @@ index 061859f85c..97587fe66b 100644
|
||||
|
||||
// configure AMF logger
|
||||
// the return of these functions indicates old state and do not affect behaviour
|
||||
@@ -583,6 +584,23 @@ static void amf_release_buffer_with_frame_ref(AMFBuffer *frame_ref_storage_buffe
|
||||
@@ -640,6 +641,23 @@ static void amf_release_buffer_with_frame_ref(AMFBuffer *frame_ref_storage_buffe
|
||||
frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ index 061859f85c..97587fe66b 100644
|
||||
int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
|
||||
{
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
@@ -596,6 +614,8 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
|
||||
@@ -653,6 +671,8 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
|
||||
int query_output_data_flag = 0;
|
||||
AMF_RESULT res_resubmit;
|
||||
|
||||
@@ -55,10 +55,10 @@ index 061859f85c..97587fe66b 100644
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
|
||||
index d636673a9d..09506ee2e0 100644
|
||||
index 320c66919e..481e0fb75d 100644
|
||||
--- a/libavcodec/amfenc.h
|
||||
+++ b/libavcodec/amfenc.h
|
||||
@@ -113,6 +113,7 @@ typedef struct AmfContext {
|
||||
@@ -115,6 +115,7 @@ typedef struct AmfContext {
|
||||
int max_b_frames;
|
||||
int qvbr_quality_level;
|
||||
int hw_high_motion_quality_boost;
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
From 14b77216106eaaff9cf701528039ae4264eaf420 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Thu, 5 Sep 2024 16:41:59 +0800
|
||||
Subject: [PATCH 3/3] amf colorspace
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
libavcodec/amfenc.h | 1 +
|
||||
libavcodec/amfenc_h264.c | 40 ++++++++++++++++++++++++++++++++++
|
||||
libavcodec/amfenc_hevc.c | 47 ++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 88 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
|
||||
index 09506ee2e0..7f458b14f7 100644
|
||||
--- a/libavcodec/amfenc.h
|
||||
+++ b/libavcodec/amfenc.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <AMF/components/VideoEncoderVCE.h>
|
||||
#include <AMF/components/VideoEncoderHEVC.h>
|
||||
#include <AMF/components/VideoEncoderAV1.h>
|
||||
+#include <AMF/components/ColorSpace.h>
|
||||
|
||||
#include "libavutil/fifo.h"
|
||||
|
||||
diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c
|
||||
index 415828f005..7da5a96c71 100644
|
||||
--- a/libavcodec/amfenc_h264.c
|
||||
+++ b/libavcodec/amfenc_h264.c
|
||||
@@ -200,6 +200,9 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx)
|
||||
AMFRate framerate;
|
||||
AMFSize framesize = AMFConstructSize(avctx->width, avctx->height);
|
||||
int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
|
||||
+ amf_int64 color_depth;
|
||||
+ amf_int64 color_profile;
|
||||
+ enum AVPixelFormat pix_fmt;
|
||||
|
||||
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
|
||||
framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den);
|
||||
@@ -266,10 +269,47 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio);
|
||||
}
|
||||
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
|
||||
/// Color Range (Partial/TV/MPEG or Full/PC/JPEG)
|
||||
if (avctx->color_range == AVCOL_RANGE_JPEG) {
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1);
|
||||
+ switch (avctx->colorspace) {
|
||||
+ case AVCOL_SPC_SMPTE170M:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT709:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT2020_NCL:
|
||||
+ case AVCOL_SPC_BT2020_CL:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 0);
|
||||
+ switch (avctx->colorspace) {
|
||||
+ case AVCOL_SPC_SMPTE170M:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT709:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT2020_NCL:
|
||||
+ case AVCOL_SPC_BT2020_CL:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
+ pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format : avctx->pix_fmt;
|
||||
+ color_depth = AMF_COLOR_BIT_DEPTH_8;
|
||||
+ if (pix_fmt == AV_PIX_FMT_P010) {
|
||||
+ color_depth = AMF_COLOR_BIT_DEPTH_10;
|
||||
+ }
|
||||
+
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_COLOR_BIT_DEPTH, color_depth);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PROFILE, color_profile);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_TRANSFER_CHARACTERISTIC, (amf_int64)avctx->color_trc);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PRIMARIES, (amf_int64)avctx->color_primaries);
|
||||
|
||||
// autodetect rate control method
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN) {
|
||||
diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c
|
||||
index 65259d7153..7c930d3ccc 100644
|
||||
--- a/libavcodec/amfenc_hevc.c
|
||||
+++ b/libavcodec/amfenc_hevc.c
|
||||
@@ -161,6 +161,9 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx)
|
||||
AMFRate framerate;
|
||||
AMFSize framesize = AMFConstructSize(avctx->width, avctx->height);
|
||||
int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
|
||||
+ amf_int64 color_depth;
|
||||
+ amf_int64 color_profile;
|
||||
+ enum AVPixelFormat pix_fmt;
|
||||
|
||||
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
|
||||
framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den);
|
||||
@@ -191,6 +194,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
case AV_PROFILE_HEVC_MAIN:
|
||||
profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN;
|
||||
break;
|
||||
+ case AV_PROFILE_HEVC_MAIN_10:
|
||||
+ profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10;
|
||||
+ break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -219,6 +225,47 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio);
|
||||
}
|
||||
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
|
||||
+ if (avctx->color_range == AVCOL_RANGE_JPEG) {
|
||||
+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE, 1);
|
||||
+ switch (avctx->colorspace) {
|
||||
+ case AVCOL_SPC_SMPTE170M:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT709:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT2020_NCL:
|
||||
+ case AVCOL_SPC_BT2020_CL:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE, 0);
|
||||
+ switch (avctx->colorspace) {
|
||||
+ case AVCOL_SPC_SMPTE170M:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT709:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709;
|
||||
+ break;
|
||||
+ case AVCOL_SPC_BT2020_NCL:
|
||||
+ case AVCOL_SPC_BT2020_CL:
|
||||
+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format : avctx->pix_fmt;
|
||||
+ color_depth = AMF_COLOR_BIT_DEPTH_8;
|
||||
+ if (pix_fmt == AV_PIX_FMT_P010) {
|
||||
+ color_depth = AMF_COLOR_BIT_DEPTH_10;
|
||||
+ }
|
||||
+
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_COLOR_BIT_DEPTH, color_depth);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PROFILE, color_profile);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_TRANSFER_CHARACTERISTIC, (amf_int64)avctx->color_trc);
|
||||
+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PRIMARIES, (amf_int64)avctx->color_primaries);
|
||||
+
|
||||
// Picture control properties
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr);
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size);
|
||||
--
|
||||
2.43.0.windows.1
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
From 7f12898fe8fd12c1042c98b34825ab2eda89e54d Mon Sep 17 00:00:00 2001
|
||||
From d74de94b49efcf7a0b25673ace6016938d1b9272 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Sun, 24 Nov 2024 12:58:39 +0800
|
||||
Subject: [PATCH 1/2] videotoolbox changing bitrate
|
||||
Date: Tue, 10 Dec 2024 14:12:01 +0800
|
||||
Subject: [PATCH 3/5] videotoolbox changing bitrate
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
libavcodec/videotoolboxenc.c | 39 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 39 insertions(+)
|
||||
libavcodec/videotoolboxenc.c | 40 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 40 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
|
||||
index 5ea9afee22..89c927cdcc 100644
|
||||
index da7b291b03..3c866177f5 100644
|
||||
--- a/libavcodec/videotoolboxenc.c
|
||||
+++ b/libavcodec/videotoolboxenc.c
|
||||
@@ -278,6 +278,8 @@ typedef struct VTEncContext {
|
||||
@@ -279,6 +279,8 @@ typedef struct VTEncContext {
|
||||
int max_slice_bytes;
|
||||
int power_efficient;
|
||||
int max_ref_frames;
|
||||
@@ -20,8 +20,8 @@ index 5ea9afee22..89c927cdcc 100644
|
||||
+ int last_bit_rate;
|
||||
} VTEncContext;
|
||||
|
||||
static int vt_dump_encoder(AVCodecContext *avctx)
|
||||
@@ -1174,6 +1176,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx,
|
||||
static void vtenc_free_buf_node(BufNode *info)
|
||||
@@ -1180,6 +1182,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx,
|
||||
int64_t one_second_value = 0;
|
||||
void *nums[2];
|
||||
|
||||
@@ -29,8 +29,8 @@ index 5ea9afee22..89c927cdcc 100644
|
||||
int status = VTCompressionSessionCreate(kCFAllocatorDefault,
|
||||
avctx->width,
|
||||
avctx->height,
|
||||
@@ -2618,6 +2621,41 @@ static int vtenc_send_frame(AVCodecContext *avctx,
|
||||
return 0;
|
||||
@@ -2638,6 +2641,42 @@ out:
|
||||
return status;
|
||||
}
|
||||
|
||||
+static void update_config(AVCodecContext *avctx)
|
||||
@@ -67,13 +67,14 @@ index 5ea9afee22..89c927cdcc 100644
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
static av_cold int vtenc_frame(
|
||||
AVCodecContext *avctx,
|
||||
AVPacket *pkt,
|
||||
@@ -2630,6 +2668,7 @@ static av_cold int vtenc_frame(
|
||||
@@ -2650,6 +2689,7 @@ static av_cold int vtenc_frame(
|
||||
CMSampleBufferRef buf = NULL;
|
||||
ExtraSEI *sei = NULL;
|
||||
ExtraSEI sei = {0};
|
||||
|
||||
+ update_config(avctx);
|
||||
if (frame) {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
From ed73f8f6494d74ae47218f9503c7e3de385d9253 Mon Sep 17 00:00:00 2001
|
||||
From 7323bd68c1b34e9298ea557ff7a3e1883b653957 Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Sun, 24 Nov 2024 14:17:39 +0800
|
||||
Subject: [PATCH 1/2] mediacodec changing bitrate
|
||||
Date: Tue, 10 Dec 2024 14:28:16 +0800
|
||||
Subject: [PATCH 4/5] mediacodec changing bitrate
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
libavcodec/mediacodec_wrapper.c | 97 +++++++++++++++++++++++++++++++++
|
||||
libavcodec/mediacodec_wrapper.c | 98 +++++++++++++++++++++++++++++++++
|
||||
libavcodec/mediacodec_wrapper.h | 7 +++
|
||||
libavcodec/mediacodecenc.c | 18 ++++++
|
||||
3 files changed, 122 insertions(+)
|
||||
3 files changed, 123 insertions(+)
|
||||
|
||||
diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c
|
||||
index 306359071e..7edb38a7d7 100644
|
||||
index 96c886666a..06b8504304 100644
|
||||
--- a/libavcodec/mediacodec_wrapper.c
|
||||
+++ b/libavcodec/mediacodec_wrapper.c
|
||||
@@ -35,6 +35,8 @@
|
||||
@@ -66,10 +66,11 @@ index 306359071e..7edb38a7d7 100644
|
||||
#define JNI_GET_ENV_OR_RETURN(env, log_ctx, ret) do { \
|
||||
(env) = ff_jni_get_env(log_ctx); \
|
||||
if (!(env)) { \
|
||||
@@ -1761,6 +1785,69 @@ static int mediacodec_jni_signalEndOfInputStream(FFAMediaCodec *ctx)
|
||||
@@ -1762,6 +1786,70 @@ static int mediacodec_jni_signalEndOfInputStream(FFAMediaCodec *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+
|
||||
+static int mediacodec_jni_setParameter(FFAMediaCodec *ctx, const char* name, int value)
|
||||
+{
|
||||
+ JNIEnv *env = NULL;
|
||||
@@ -136,7 +137,7 @@ index 306359071e..7edb38a7d7 100644
|
||||
static const FFAMediaFormat media_format_jni = {
|
||||
.class = &amediaformat_class,
|
||||
|
||||
@@ -1820,6 +1907,8 @@ static const FFAMediaCodec media_codec_jni = {
|
||||
@@ -1821,6 +1909,8 @@ static const FFAMediaCodec media_codec_jni = {
|
||||
.getConfigureFlagEncode = mediacodec_jni_getConfigureFlagEncode,
|
||||
.cleanOutputBuffers = mediacodec_jni_cleanOutputBuffers,
|
||||
.signalEndOfInputStream = mediacodec_jni_signalEndOfInputStream,
|
||||
@@ -145,7 +146,7 @@ index 306359071e..7edb38a7d7 100644
|
||||
};
|
||||
|
||||
typedef struct FFAMediaFormatNdk {
|
||||
@@ -2428,6 +2517,12 @@ static int mediacodec_ndk_signalEndOfInputStream(FFAMediaCodec *ctx)
|
||||
@@ -2335,6 +2425,12 @@ static int mediacodec_ndk_signalEndOfInputStream(FFAMediaCodec *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -158,7 +159,7 @@ index 306359071e..7edb38a7d7 100644
|
||||
static const FFAMediaFormat media_format_ndk = {
|
||||
.class = &amediaformat_ndk_class,
|
||||
|
||||
@@ -2489,6 +2584,8 @@ static const FFAMediaCodec media_codec_ndk = {
|
||||
@@ -2396,6 +2492,8 @@ static const FFAMediaCodec media_codec_ndk = {
|
||||
.getConfigureFlagEncode = mediacodec_ndk_getConfigureFlagEncode,
|
||||
.cleanOutputBuffers = mediacodec_ndk_cleanOutputBuffers,
|
||||
.signalEndOfInputStream = mediacodec_ndk_signalEndOfInputStream,
|
||||
@@ -193,19 +194,19 @@ index 11a4260497..86c64556ad 100644
|
||||
|
||||
enum FFAMediaFormatColorRange {
|
||||
diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c
|
||||
index d3bf27cb7f..621529d686 100644
|
||||
index 6ca3968a24..221f7360f4 100644
|
||||
--- a/libavcodec/mediacodecenc.c
|
||||
+++ b/libavcodec/mediacodecenc.c
|
||||
@@ -73,6 +73,8 @@ typedef struct MediaCodecEncContext {
|
||||
int bitrate_mode;
|
||||
@@ -76,6 +76,8 @@ typedef struct MediaCodecEncContext {
|
||||
int level;
|
||||
int pts_as_dts;
|
||||
int extract_extradata;
|
||||
+
|
||||
+ int last_bit_rate;
|
||||
} MediaCodecEncContext;
|
||||
|
||||
enum {
|
||||
@@ -155,6 +157,8 @@ static av_cold int mediacodec_init(AVCodecContext *avctx)
|
||||
@@ -193,6 +195,8 @@ static av_cold int mediacodec_init(AVCodecContext *avctx)
|
||||
int ret;
|
||||
int gop;
|
||||
|
||||
@@ -214,7 +215,7 @@ index d3bf27cb7f..621529d686 100644
|
||||
if (s->use_ndk_codec < 0)
|
||||
s->use_ndk_codec = !av_jni_get_java_vm(avctx);
|
||||
|
||||
@@ -515,12 +519,26 @@ static int mediacodec_send(AVCodecContext *avctx,
|
||||
@@ -542,11 +546,25 @@ static int mediacodec_send(AVCodecContext *avctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -235,12 +236,11 @@ index d3bf27cb7f..621529d686 100644
|
||||
{
|
||||
MediaCodecEncContext *s = avctx->priv_data;
|
||||
int ret;
|
||||
int got_packet = 0;
|
||||
|
||||
+ update_config(avctx);
|
||||
// Return on three case:
|
||||
// 1. Serious error
|
||||
// 2. Got a packet success
|
||||
--
|
||||
2.34.1
|
||||
2.43.0.windows.1
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
30
res/vcpkg/ffmpeg/patch/0007-fix-linux-configure.patch
Normal file
30
res/vcpkg/ffmpeg/patch/0007-fix-linux-configure.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
From 595f0468e127f204741b6c37a479d71daaf571eb Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Tue, 10 Dec 2024 21:17:14 +0800
|
||||
Subject: [PATCH] fix linux configure
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
configure | 6 ------
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index d77a55b653..48ca90ac5e 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -7071,12 +7071,6 @@ enabled mmal && { check_lib mmal interface/mmal/mmal.h mmal_port_co
|
||||
check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host; } ||
|
||||
die "ERROR: mmal not found" &&
|
||||
check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; }
|
||||
-enabled openal && { check_pkg_config openal "openal >= 1.1" "AL/al.h" alGetError ||
|
||||
- { for al_extralibs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do
|
||||
- check_lib openal 'AL/al.h' alGetError "${al_extralibs}" && break; done } ||
|
||||
- die "ERROR: openal not found"; } &&
|
||||
- { test_cpp_condition "AL/al.h" "defined(AL_VERSION_1_1)" ||
|
||||
- die "ERROR: openal must be installed and version must be 1.1 or compatible"; }
|
||||
enabled opencl && { check_pkg_config opencl OpenCL CL/cl.h clEnqueueNDRangeKernel ||
|
||||
check_lib opencl OpenCL/cl.h clEnqueueNDRangeKernel "-framework OpenCL" ||
|
||||
check_lib opencl CL/cl.h clEnqueueNDRangeKernel -lOpenCL ||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
26
res/vcpkg/ffmpeg/patch/0008-remove-amf-loop-query.patch
Normal file
26
res/vcpkg/ffmpeg/patch/0008-remove-amf-loop-query.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 1440f556234d135ce58a2ef38916c6a63b05870e Mon Sep 17 00:00:00 2001
|
||||
From: 21pages <sunboeasy@gmail.com>
|
||||
Date: Sat, 14 Dec 2024 21:39:44 +0800
|
||||
Subject: [PATCH] remove amf loop query
|
||||
|
||||
Signed-off-by: 21pages <sunboeasy@gmail.com>
|
||||
---
|
||||
libavcodec/amfenc.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
|
||||
index f70f0109f6..a53a05b16b 100644
|
||||
--- a/libavcodec/amfenc.c
|
||||
+++ b/libavcodec/amfenc.c
|
||||
@@ -886,7 +886,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
|
||||
av_usleep(1000);
|
||||
}
|
||||
}
|
||||
- } while (block_and_wait);
|
||||
+ } while (false); // already set query timeout
|
||||
|
||||
if (res_query == AMF_EOF) {
|
||||
ret = AVERROR_EOF;
|
||||
--
|
||||
2.43.0.windows.1
|
||||
|
||||
@@ -2,20 +2,28 @@ vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO ffmpeg/ffmpeg
|
||||
REF "n${VERSION}"
|
||||
SHA512 3ba02e8b979c80bf61d55f414bdac2c756578bb36498ed7486151755c6ccf8bd8ff2b8c7afa3c5d1acd862ce48314886a86a105613c05e36601984c334f8f6bf
|
||||
SHA512 3b273769ef1a1b63aed0691eef317a760f8c83b1d0e1c232b67bbee26db60b4864aafbc88df0e86d6bebf07185bbd057f33e2d5258fde6d97763b9994cd48b6f
|
||||
HEAD_REF master
|
||||
PATCHES
|
||||
0002-fix-msvc-link.patch # upstreamed in future version
|
||||
0001-create-lib-libraries.patch
|
||||
0002-fix-msvc-link.patch
|
||||
0003-fix-windowsinclude.patch
|
||||
0005-fix-nasm.patch # upstreamed in future version
|
||||
0012-Fix-ssl-110-detection.patch
|
||||
0004-dependencies.patch
|
||||
0005-fix-nasm.patch
|
||||
0007-fix-lib-naming.patch
|
||||
0013-define-WINVER.patch
|
||||
0020-fix-aarch64-libswscale.patch
|
||||
0024-fix-osx-host-c11.patch
|
||||
0040-ffmpeg-add-av_stream_get_first_dts-for-chromium.patch # Do not remove this patch. It is required by chromium
|
||||
0041-add-const-for-opengl-definition.patch
|
||||
0043-fix-miss-head.patch
|
||||
patch/0001-avcodec-amfenc-add-query_timeout-option-for-h264-hev.patch
|
||||
patch/0002-libavcodec-amfenc-reconfig-when-bitrate-change.patch
|
||||
patch/0003-amf-colorspace.patch
|
||||
patch/0004-videotoolbox-changing-bitrate.patch
|
||||
patch/0005-mediacodec-changing-bitrate.patch
|
||||
patch/0006-dlopen-libva.patch
|
||||
patch/0007-fix-linux-configure.patch
|
||||
patch/0008-remove-amf-loop-query.patch
|
||||
)
|
||||
|
||||
if(SOURCE_PATH MATCHES " ")
|
||||
@@ -51,6 +59,7 @@ set(OPTIONS "\
|
||||
--disable-debug \
|
||||
--disable-valgrind-backtrace \
|
||||
--disable-large-tests \
|
||||
--disable-bzlib \
|
||||
--disable-avdevice \
|
||||
--enable-avcodec \
|
||||
--enable-avformat \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ffmpeg",
|
||||
"version": "7.0.2",
|
||||
"port-version": 0,
|
||||
"version": "7.1",
|
||||
"port-version": 1,
|
||||
"description": [
|
||||
"a library to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created.",
|
||||
"FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created. It supports the most obscure ancient formats up to the cutting edge. No matter if they were designed by some standards committee, the community or a corporation. It is also highly portable: FFmpeg compiles, runs, and passes our testing infrastructure FATE across Linux, Mac OS X, Microsoft Windows, the BSDs, Solaris, etc. under a wide variety of build environments, machine architectures, and configurations."
|
||||
|
||||
@@ -4,7 +4,7 @@ vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO webmproject/libvpx
|
||||
REF "v${VERSION}"
|
||||
SHA512 3e3bfad3d035c0bc3db7cb5a194d56d3c90f5963fb1ad527ae5252054e7c48ce2973de1346c97d94b59f7a95d4801bec44214cce10faf123f92b36fca79a8d1e
|
||||
SHA512 8f483653a324c710fd431b87fd0d5d6f476f006bd8c8e9c6d1fa6abd105d6a40ac81c8fd5638b431c455d57ab2ee823c165e9875eb3932e6e518477422da3a7b
|
||||
HEAD_REF master
|
||||
PATCHES
|
||||
0002-Fix-nasm-debug-format-flag.patch
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "libvpx",
|
||||
"version": "1.14.1",
|
||||
"version": "1.15.0",
|
||||
"port-version": 0,
|
||||
"description": "The reference software implementation for the video coding formats VP8 and VP9.",
|
||||
"homepage": "https://github.com/webmproject/libvpx",
|
||||
|
||||
@@ -2,12 +2,14 @@ use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use clipboard_master::{CallbackResult, ClipboardHandler};
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
use cpal::{
|
||||
traits::{DeviceTrait, HostTrait, StreamTrait},
|
||||
Device, Host, StreamConfig,
|
||||
};
|
||||
use crossbeam_queue::ArrayQueue;
|
||||
use magnum_opus::{Channels::*, Decoder as AudioDecoder};
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
use ringbuf::{ring_buffer::RbBase, Rb};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
@@ -117,6 +119,7 @@ pub const SCRAP_OTHER_VERSION_OR_X11_REQUIRED: &str =
|
||||
pub const SCRAP_X11_REQUIRED: &str = "x11 expected";
|
||||
pub const SCRAP_X11_REF_URL: &str = "https://rustdesk.com/docs/en/manual/linux/#x11-required";
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub const AUDIO_BUFFER_MS: usize = 3000;
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
@@ -139,6 +142,7 @@ struct TextClipboardState {
|
||||
running: bool,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
lazy_static::lazy_static! {
|
||||
static ref AUDIO_HOST: Host = cpal::default_host();
|
||||
}
|
||||
@@ -861,20 +865,28 @@ impl ClipboardHandler for ClientClipboardHandler {
|
||||
#[derive(Default)]
|
||||
pub struct AudioHandler {
|
||||
audio_decoder: Option<(AudioDecoder, Vec<f32>)>,
|
||||
#[cfg(target_os = "linux")]
|
||||
simple: Option<psimple::Simple>,
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
audio_buffer: AudioBuffer,
|
||||
sample_rate: (u32, u32),
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
audio_stream: Option<Box<dyn StreamTrait>>,
|
||||
channels: u16,
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
device_channel: u16,
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
ready: Arc<std::sync::Mutex<bool>>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
struct AudioBuffer(
|
||||
pub Arc<std::sync::Mutex<ringbuf::HeapRb<f32>>>,
|
||||
usize,
|
||||
[usize; 30],
|
||||
);
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
impl Default for AudioBuffer {
|
||||
fn default() -> Self {
|
||||
Self(
|
||||
@@ -887,6 +899,7 @@ impl Default for AudioBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
impl AudioBuffer {
|
||||
pub fn resize(&mut self, sample_rate: usize, channels: usize) {
|
||||
let capacity = sample_rate * channels * AUDIO_BUFFER_MS / 1000;
|
||||
@@ -989,7 +1002,37 @@ impl AudioBuffer {
|
||||
}
|
||||
|
||||
impl AudioHandler {
|
||||
#[cfg(target_os = "linux")]
|
||||
fn start_audio(&mut self, format0: AudioFormat) -> ResultType<()> {
|
||||
use psimple::Simple;
|
||||
use pulse::sample::{Format, Spec};
|
||||
use pulse::stream::Direction;
|
||||
|
||||
let spec = Spec {
|
||||
format: Format::F32le,
|
||||
channels: format0.channels as _,
|
||||
rate: format0.sample_rate as _,
|
||||
};
|
||||
if !spec.is_valid() {
|
||||
bail!("Invalid audio format");
|
||||
}
|
||||
|
||||
self.simple = Some(Simple::new(
|
||||
None, // Use the default server
|
||||
&crate::get_app_name(), // Our application’s name
|
||||
Direction::Playback, // We want a playback stream
|
||||
None, // Use the default device
|
||||
"playback", // Description of our stream
|
||||
&spec, // Our sample format
|
||||
None, // Use default channel map
|
||||
None, // Use default buffering attributes
|
||||
)?);
|
||||
self.sample_rate = (format0.sample_rate, format0.sample_rate);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Start the audio playback.
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn start_audio(&mut self, format0: AudioFormat) -> ResultType<()> {
|
||||
let device = AUDIO_HOST
|
||||
.default_output_device()
|
||||
@@ -1002,8 +1045,13 @@ impl AudioHandler {
|
||||
let sample_format = config.sample_format();
|
||||
log::info!("Default output format: {:?}", config);
|
||||
log::info!("Remote input format: {:?}", format0);
|
||||
#[allow(unused_mut)]
|
||||
let mut config: StreamConfig = config.into();
|
||||
config.buffer_size = cpal::BufferSize::Fixed(64);
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
{
|
||||
// this makes ios audio output not work
|
||||
config.buffer_size = cpal::BufferSize::Fixed(64);
|
||||
}
|
||||
|
||||
self.sample_rate = (format0.sample_rate, config.sample_rate.0);
|
||||
let mut build_output_stream = |config: StreamConfig| match sample_format {
|
||||
@@ -1052,13 +1100,20 @@ impl AudioHandler {
|
||||
/// Handle audio frame and play it.
|
||||
#[inline]
|
||||
pub fn handle_frame(&mut self, frame: AudioFrame) {
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
if self.audio_stream.is_none() || !self.ready.lock().unwrap().clone() {
|
||||
return;
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
if self.simple.is_none() {
|
||||
log::debug!("PulseAudio simple binding does not exists");
|
||||
return;
|
||||
}
|
||||
self.audio_decoder.as_mut().map(|(d, buffer)| {
|
||||
if let Ok(n) = d.decode_float(&frame.data, buffer, false) {
|
||||
let channels = self.channels;
|
||||
let n = n * (channels as usize);
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
let sample_rate0 = self.sample_rate.0;
|
||||
let sample_rate = self.sample_rate.1;
|
||||
@@ -1082,11 +1137,18 @@ impl AudioHandler {
|
||||
}
|
||||
self.audio_buffer.append_pcm(&buffer);
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let data_u8 =
|
||||
unsafe { std::slice::from_raw_parts::<u8>(buffer.as_ptr() as _, n * 4) };
|
||||
self.simple.as_mut().map(|x| x.write(data_u8));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Build audio output stream for current device.
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn build_output_stream<T: cpal::Sample + cpal::SizedSample + cpal::FromSample<f32>>(
|
||||
&mut self,
|
||||
config: &StreamConfig,
|
||||
@@ -1379,7 +1441,8 @@ pub struct LoginConfigHandler {
|
||||
password_source: PasswordSource, // where the sent password comes from
|
||||
shared_password: Option<String>, // Store the shared password
|
||||
pub enable_trusted_devices: bool,
|
||||
pub record: bool,
|
||||
pub record_state: bool,
|
||||
pub record_permission: bool,
|
||||
}
|
||||
|
||||
impl Deref for LoginConfigHandler {
|
||||
@@ -1484,7 +1547,8 @@ impl LoginConfigHandler {
|
||||
self.adapter_luid = adapter_luid;
|
||||
self.selected_windows_session_id = None;
|
||||
self.shared_password = shared_password;
|
||||
self.record = LocalConfig::get_bool_option(OPTION_ALLOW_AUTO_RECORD_OUTGOING);
|
||||
self.record_state = false;
|
||||
self.record_permission = true;
|
||||
}
|
||||
|
||||
/// Check if the client should auto login.
|
||||
@@ -2349,10 +2413,11 @@ pub fn start_video_thread<F, T>(
|
||||
let format = CodecFormat::from(&vf);
|
||||
if video_handler.is_none() {
|
||||
let mut handler = VideoHandler::new(format, display);
|
||||
let record = session.lc.read().unwrap().record;
|
||||
let record_state = session.lc.read().unwrap().record_state;
|
||||
let record_permission = session.lc.read().unwrap().record_permission;
|
||||
let id = session.lc.read().unwrap().id.clone();
|
||||
if record {
|
||||
handler.record_screen(record, id, display);
|
||||
if record_state && record_permission {
|
||||
handler.record_screen(true, id, display);
|
||||
}
|
||||
video_handler = Some(handler);
|
||||
}
|
||||
@@ -2431,8 +2496,6 @@ pub fn start_video_thread<F, T>(
|
||||
}
|
||||
}
|
||||
MediaData::RecordScreen(start) => {
|
||||
log::info!("record screen command: start: {start}");
|
||||
session.update_record_status(start);
|
||||
let id = session.lc.read().unwrap().id.clone();
|
||||
if let Some(handler) = video_handler.as_mut() {
|
||||
handler.record_screen(start, id, display);
|
||||
@@ -2748,6 +2811,7 @@ fn _input_os_password(p: String, activate: bool, interface: impl Interface) {
|
||||
return;
|
||||
}
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.mode = KeyboardMode::Legacy.into();
|
||||
key_event.press = true;
|
||||
let mut msg_out = Message::new();
|
||||
key_event.set_seq(p);
|
||||
|
||||
@@ -27,7 +27,7 @@ use crossbeam_queue::ArrayQueue;
|
||||
use hbb_common::tokio::sync::mpsc::error::TryRecvError;
|
||||
use hbb_common::{
|
||||
allow_err,
|
||||
config::{self, PeerConfig, TransferSerde},
|
||||
config::{self, LocalConfig, PeerConfig, TransferSerde},
|
||||
fs::{
|
||||
self, can_enable_overwrite_detection, get_job, get_string, new_send_confirm,
|
||||
DigestCheckResult, RemoveJobMeta,
|
||||
@@ -71,6 +71,7 @@ pub struct Remote<T: InvokeUiSession> {
|
||||
peer_info: ParsedPeerInfo,
|
||||
video_threads: HashMap<usize, VideoThread>,
|
||||
chroma: Arc<RwLock<Option<Chroma>>>,
|
||||
last_record_state: bool,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -116,6 +117,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
peer_info: Default::default(),
|
||||
video_threads: Default::default(),
|
||||
chroma: Default::default(),
|
||||
last_record_state: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,10 +848,8 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
}
|
||||
Data::RecordScreen(start) => {
|
||||
self.handler.lc.write().unwrap().record = start;
|
||||
for (_, v) in self.video_threads.iter_mut() {
|
||||
v.video_sender.send(MediaData::RecordScreen(start)).ok();
|
||||
}
|
||||
self.handler.lc.write().unwrap().record_state = start;
|
||||
self.update_record_state();
|
||||
}
|
||||
Data::ElevateDirect => {
|
||||
let mut request = ElevationRequest::new();
|
||||
@@ -1484,6 +1484,8 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
self.handler.set_permission("restart", p.enabled);
|
||||
}
|
||||
Ok(Permission::Recording) => {
|
||||
self.handler.lc.write().unwrap().record_permission = p.enabled;
|
||||
self.update_record_state();
|
||||
self.handler.set_permission("recording", p.enabled);
|
||||
}
|
||||
Ok(Permission::BlockInput) => {
|
||||
@@ -1983,15 +1985,39 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
},
|
||||
);
|
||||
self.video_threads.insert(display, video_thread);
|
||||
let auto_record = self.handler.lc.read().unwrap().record;
|
||||
if auto_record && self.video_threads.len() == 1 {
|
||||
let mut misc = Misc::new();
|
||||
misc.set_client_record_status(true);
|
||||
let mut msg = Message::new();
|
||||
msg.set_misc(misc);
|
||||
self.sender.send(Data::Message(msg)).ok();
|
||||
if self.video_threads.len() == 1 {
|
||||
let auto_record =
|
||||
LocalConfig::get_bool_option(config::keys::OPTION_ALLOW_AUTO_RECORD_OUTGOING);
|
||||
self.handler.lc.write().unwrap().record_state = auto_record;
|
||||
self.update_record_state();
|
||||
}
|
||||
}
|
||||
|
||||
fn update_record_state(&mut self) {
|
||||
// state
|
||||
let permission = self.handler.lc.read().unwrap().record_permission;
|
||||
if !permission {
|
||||
self.handler.lc.write().unwrap().record_state = false;
|
||||
}
|
||||
let state = self.handler.lc.read().unwrap().record_state;
|
||||
let start = state && permission;
|
||||
if self.last_record_state == start {
|
||||
return;
|
||||
}
|
||||
self.last_record_state = start;
|
||||
log::info!("record screen start: {start}");
|
||||
// update local
|
||||
for (_, v) in self.video_threads.iter_mut() {
|
||||
v.video_sender.send(MediaData::RecordScreen(start)).ok();
|
||||
}
|
||||
self.handler.update_record_status(start);
|
||||
// update remote
|
||||
let mut misc = Misc::new();
|
||||
misc.set_client_record_status(start);
|
||||
let mut msg = Message::new();
|
||||
msg.set_misc(misc);
|
||||
self.sender.send(Data::Message(msg)).ok();
|
||||
}
|
||||
}
|
||||
|
||||
struct RemoveJob {
|
||||
@@ -2040,3 +2066,10 @@ struct VideoThread {
|
||||
discard_queue: Arc<RwLock<bool>>,
|
||||
fps_control: FpsControl,
|
||||
}
|
||||
|
||||
impl Drop for VideoThread {
|
||||
fn drop(&mut self) {
|
||||
// since channels are buffered, messages sent before the disconnect will still be properly received.
|
||||
*self.discard_queue.write().unwrap() = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::keyboard::input_source::{change_input_source, get_cur_session_input_source};
|
||||
use crate::{
|
||||
client::file_trait::FileManager,
|
||||
common::{make_fd_to_json, make_vec_fd_to_json},
|
||||
@@ -7,11 +9,6 @@ use crate::{
|
||||
input::*,
|
||||
ui_interface::{self, *},
|
||||
};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::{
|
||||
common::get_default_sound_input,
|
||||
keyboard::input_source::{change_input_source, get_cur_session_input_source},
|
||||
};
|
||||
use flutter_rust_bridge::{StreamSink, SyncReturn};
|
||||
#[cfg(feature = "plugin_framework")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
@@ -831,30 +828,22 @@ pub fn main_show_option(_key: String) -> SyncReturn<bool> {
|
||||
SyncReturn(false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_os = "android")]
|
||||
fn enable_server_clipboard(keyboard_enabled: &str, clip_enabled: &str) {
|
||||
use scrap::android::ffi::call_clipboard_manager_enable_service_clipboard;
|
||||
let keyboard_enabled =
|
||||
config::option2bool(config::keys::OPTION_ENABLE_KEYBOARD, &keyboard_enabled);
|
||||
let clip_enabled = config::option2bool(config::keys::OPTION_ENABLE_CLIPBOARD, &clip_enabled);
|
||||
crate::ui_cm_interface::switch_permission_all("clipboard".to_owned(), clip_enabled);
|
||||
let _ = call_clipboard_manager_enable_service_clipboard(keyboard_enabled && clip_enabled);
|
||||
}
|
||||
|
||||
pub fn main_set_option(key: String, value: String) {
|
||||
#[cfg(target_os = "android")]
|
||||
if key.eq(config::keys::OPTION_ENABLE_KEYBOARD) {
|
||||
crate::ui_cm_interface::notify_input_control(config::option2bool(
|
||||
config::keys::OPTION_ENABLE_KEYBOARD,
|
||||
&value,
|
||||
));
|
||||
enable_server_clipboard(&value, &get_option(config::keys::OPTION_ENABLE_CLIPBOARD));
|
||||
crate::ui_cm_interface::switch_permission_all(
|
||||
"keyboard".to_owned(),
|
||||
config::option2bool(&key, &value),
|
||||
);
|
||||
}
|
||||
#[cfg(target_os = "android")]
|
||||
if key.eq(config::keys::OPTION_ENABLE_CLIPBOARD) {
|
||||
enable_server_clipboard(&get_option(config::keys::OPTION_ENABLE_KEYBOARD), &value);
|
||||
crate::ui_cm_interface::switch_permission_all(
|
||||
"clipboard".to_owned(),
|
||||
config::option2bool(&key, &value),
|
||||
);
|
||||
}
|
||||
|
||||
if key.eq("custom-rendezvous-server") {
|
||||
set_option(key, value.clone());
|
||||
#[cfg(target_os = "android")]
|
||||
@@ -2348,7 +2337,7 @@ pub mod server_side {
|
||||
use jni::{
|
||||
errors::{Error as JniError, Result as JniResult},
|
||||
objects::{JClass, JObject, JString},
|
||||
sys::jstring,
|
||||
sys::{jboolean, jstring},
|
||||
JNIEnv,
|
||||
};
|
||||
|
||||
@@ -2421,4 +2410,12 @@ pub mod server_side {
|
||||
};
|
||||
return env.new_string(res).unwrap_or_default().into_raw();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "system" fn Java_ffi_FFI_isServiceClipboardEnabled(
|
||||
env: JNIEnv,
|
||||
_class: JClass,
|
||||
) -> jboolean {
|
||||
jboolean::from(crate::server::is_clipboard_service_ok())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,8 +217,6 @@ pub enum Data {
|
||||
MouseMoveTime(i64),
|
||||
Authorize,
|
||||
Close,
|
||||
#[cfg(target_os = "android")]
|
||||
InputControl(bool),
|
||||
#[cfg(windows)]
|
||||
SAS,
|
||||
UserSid(Option<u32>),
|
||||
@@ -268,6 +266,7 @@ pub enum Data {
|
||||
ControlledSessionCount(usize),
|
||||
CmErr(String),
|
||||
CheckHwcodec,
|
||||
#[cfg(feature = "flutter")]
|
||||
VideoConnCount(Option<usize>),
|
||||
// Although the key is not neccessary, it is used to avoid hardcoding the key.
|
||||
WaylandScreencastRestoreToken((String, String)),
|
||||
@@ -457,6 +456,7 @@ async fn handle(data: Data, stream: &mut Connection) {
|
||||
log::info!("socks updated");
|
||||
}
|
||||
},
|
||||
#[cfg(feature = "flutter")]
|
||||
Data::VideoConnCount(None) => {
|
||||
let n = crate::server::AUTHED_CONNS
|
||||
.lock()
|
||||
|
||||
@@ -417,6 +417,17 @@ pub fn is_modifier(key: &rdev::Key) -> bool {
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_modifier_code(evt: &KeyEvent) -> bool {
|
||||
match evt.union {
|
||||
Some(key_event::Union::Chr(code)) => {
|
||||
let key = rdev::linux_key_from_code(code);
|
||||
is_modifier(&key)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_numpad_rdev_key(key: &rdev::Key) -> bool {
|
||||
matches!(
|
||||
@@ -869,24 +880,11 @@ pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Vec<KeyEv
|
||||
events
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn map_keyboard_mode(_peer: &str, event: &Event, key_event: KeyEvent) -> Vec<KeyEvent> {
|
||||
match _map_keyboard_mode(_peer, event, key_event) {
|
||||
Some(key_event) => {
|
||||
if _peer == OS_LOWER_LINUX {
|
||||
if let EventType::KeyPress(k) = &event.event_type {
|
||||
#[cfg(target_os = "ios")]
|
||||
let try_workaround = true;
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
let try_workaround = !is_modifier(k);
|
||||
if try_workaround {
|
||||
return try_workaround_linux_long_press(key_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
vec![key_event]
|
||||
}
|
||||
None => Vec::new(),
|
||||
}
|
||||
_map_keyboard_mode(_peer, event, key_event)
|
||||
.map(|e| vec![e])
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn _map_keyboard_mode(_peer: &str, event: &Event, mut key_event: KeyEvent) -> Option<KeyEvent> {
|
||||
@@ -958,14 +956,6 @@ fn _map_keyboard_mode(_peer: &str, event: &Event, mut key_event: KeyEvent) -> Op
|
||||
Some(key_event)
|
||||
}
|
||||
|
||||
// https://github.com/rustdesk/rustdesk/issues/6793
|
||||
#[inline]
|
||||
fn try_workaround_linux_long_press(key_event: KeyEvent) -> Vec<KeyEvent> {
|
||||
let mut key_event_up = key_event.clone();
|
||||
key_event_up.down = false;
|
||||
vec![key_event, key_event_up]
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "ios")))]
|
||||
fn try_fill_unicode(_peer: &str, event: &Event, key_event: &KeyEvent, events: &mut Vec<KeyEvent>) {
|
||||
match &event.unicode {
|
||||
|
||||
@@ -655,5 +655,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
("Untagged", ""),
|
||||
("new-version-of-{}-tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -655,5 +655,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
("Untagged", ""),
|
||||
("new-version-of-{}-tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -655,5 +655,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
("Untagged", ""),
|
||||
("new-version-of-{}-tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -655,5 +655,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
("Untagged", ""),
|
||||
("new-version-of-{}-tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -655,5 +655,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Clipboard is synchronized", "剪贴板已同步"),
|
||||
("Update client clipboard", "更新客户端的粘贴板"),
|
||||
("Untagged", "无标签"),
|
||||
("new-version-of-{}-tip", "{} 版本更新"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -655,5 +655,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
("Untagged", ""),
|
||||
("new-version-of-{}-tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -655,5 +655,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
("Untagged", ""),
|
||||
("new-version-of-{}-tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -654,6 +654,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Upload files", "Dateien hochladen"),
|
||||
("Clipboard is synchronized", "Zwischenablage ist synchronisiert"),
|
||||
("Update client clipboard", "Client-Zwischenablage aktualisieren"),
|
||||
("Untagged", ""),
|
||||
("Untagged", "Unmarkiert"),
|
||||
("new-version-of-{}-tip", "Es ist eine neue Version von {} verfügbar"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -655,5 +655,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Clipboard is synchronized", ""),
|
||||
("Update client clipboard", ""),
|
||||
("Untagged", ""),
|
||||
("new-version-of-{}-tip", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user