mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-29 04:10:17 +08:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c622bc76e | ||
|
|
b790c7d08e | ||
|
|
0ca90d2516 | ||
|
|
401bfe4483 | ||
|
|
3b34c26555 | ||
|
|
b668b3c936 | ||
|
|
cc19ec125a | ||
|
|
ffa77fdf44 | ||
|
|
47cf806532 | ||
|
|
911dce2e71 | ||
|
|
9f80d4f69d | ||
|
|
cba644f055 | ||
|
|
f733fe9e49 | ||
|
|
27263fe1db | ||
|
|
698bf72a6c | ||
|
|
0bd27d0b17 | ||
|
|
ee5612da8b | ||
|
|
c7a2023c88 | ||
|
|
c031a8c145 | ||
|
|
0bf83f07ad | ||
|
|
3638b712bd | ||
|
|
b2ab940f20 | ||
|
|
17f9536476 | ||
|
|
0ef51e3faf | ||
|
|
cccf5dadb2 | ||
|
|
2f0b0ffc22 | ||
|
|
c7411b59f1 | ||
|
|
8222782522 | ||
|
|
5fed09c1aa | ||
|
|
8e499772f9 | ||
|
|
0da812e7e9 | ||
|
|
3d67b6e9d6 | ||
|
|
506b2893c6 | ||
|
|
56abe9e690 | ||
|
|
ab13fa582d | ||
|
|
b9e8192eee | ||
|
|
5590aaeb1e | ||
|
|
adfe14809f | ||
|
|
a21dbc8d69 | ||
|
|
b9c70f54d3 | ||
|
|
9cd617d078 |
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
*.h linguist-language=C++
|
||||||
|
*.cpp linguist-language=C++
|
||||||
|
*.lua linguist-language=Xmake
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Build and Release CrossDesk
|
name: Build and Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -34,10 +34,11 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
id: set_deb_version
|
id: set_deb_version
|
||||||
run: |
|
run: |
|
||||||
|
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
||||||
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
|
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
|
||||||
LEGAL_VERSION="0.0.0-${VERSION_NUM}"
|
LEGAL_VERSION="0.0.0-${VERSION_NUM}-${SHORT_SHA}"
|
||||||
else
|
else
|
||||||
LEGAL_VERSION="${VERSION_NUM}"
|
LEGAL_VERSION="${VERSION_NUM}-${SHORT_SHA}"
|
||||||
fi
|
fi
|
||||||
echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV
|
echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@ jobs:
|
|||||||
XMAKE_GLOBALDIR: /data
|
XMAKE_GLOBALDIR: /data
|
||||||
run: |
|
run: |
|
||||||
ls -la $XMAKE_GLOBALDIR
|
ls -la $XMAKE_GLOBALDIR
|
||||||
|
xmake f --CROSSDESK_VERSION=${LEGAL_VERSION} --root -y
|
||||||
xmake b -vy --root crossdesk
|
xmake b -vy --root crossdesk
|
||||||
|
|
||||||
- name: Decode and save certificate
|
- name: Decode and save certificate
|
||||||
@@ -96,10 +98,11 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
id: set_deb_version
|
id: set_deb_version
|
||||||
run: |
|
run: |
|
||||||
|
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
||||||
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
|
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
|
||||||
LEGAL_VERSION="0.0.0-${VERSION_NUM}"
|
LEGAL_VERSION="0.0.0-${VERSION_NUM}-${SHORT_SHA}"
|
||||||
else
|
else
|
||||||
LEGAL_VERSION="${VERSION_NUM}"
|
LEGAL_VERSION="${VERSION_NUM}-${SHORT_SHA}"
|
||||||
fi
|
fi
|
||||||
echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV
|
echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV
|
||||||
|
|
||||||
@@ -113,6 +116,7 @@ jobs:
|
|||||||
CUDA_PATH: /usr/local/cuda
|
CUDA_PATH: /usr/local/cuda
|
||||||
XMAKE_GLOBALDIR: /data
|
XMAKE_GLOBALDIR: /data
|
||||||
run: |
|
run: |
|
||||||
|
xmake f --CROSSDESK_VERSION=${LEGAL_VERSION} --root -y
|
||||||
xmake b -vy --root crossdesk
|
xmake b -vy --root crossdesk
|
||||||
|
|
||||||
- name: Decode and save certificate
|
- name: Decode and save certificate
|
||||||
@@ -155,7 +159,8 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
VERSION="${GITHUB_REF##*/}"
|
VERSION="${GITHUB_REF##*/}"
|
||||||
VERSION_NUM="${VERSION#v}"
|
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
||||||
|
VERSION_NUM="${VERSION#v}-${SHORT_SHA}"
|
||||||
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
|
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
|
||||||
echo "VERSION_NUM=${VERSION_NUM}"
|
echo "VERSION_NUM=${VERSION_NUM}"
|
||||||
|
|
||||||
@@ -177,7 +182,9 @@ jobs:
|
|||||||
run: git submodule update --init --recursive
|
run: git submodule update --init --recursive
|
||||||
|
|
||||||
- name: Build CrossDesk
|
- name: Build CrossDesk
|
||||||
run: xmake b -vy crossdesk
|
run: |
|
||||||
|
xmake f --CROSSDESK_VERSION=${VERSION_NUM} -y
|
||||||
|
xmake b -vy crossdesk
|
||||||
|
|
||||||
- name: Decode and save certificate
|
- name: Decode and save certificate
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -215,7 +222,8 @@ jobs:
|
|||||||
$version = $ref -replace '^refs/(tags|heads)/', ''
|
$version = $ref -replace '^refs/(tags|heads)/', ''
|
||||||
$version = $version -replace '^v', ''
|
$version = $version -replace '^v', ''
|
||||||
$version = $version -replace '/', '-'
|
$version = $version -replace '/', '-'
|
||||||
echo "VERSION_NUM=$version" >> $env:GITHUB_ENV
|
$SHORT_SHA = $env:GITHUB_SHA.Substring(0,7)
|
||||||
|
echo "VERSION_NUM=$version-$SHORT_SHA" >> $env:GITHUB_ENV
|
||||||
|
|
||||||
- name: Cache xmake dependencies
|
- name: Cache xmake dependencies
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
@@ -281,8 +289,10 @@ jobs:
|
|||||||
copy "${{ github.workspace }}\scripts\windows\nsProcess.dll" $nsisPluginDir
|
copy "${{ github.workspace }}\scripts\windows\nsProcess.dll" $nsisPluginDir
|
||||||
|
|
||||||
- name: Build CrossDesk
|
- name: Build CrossDesk
|
||||||
run: xmake b -vy crossdesk
|
run: |
|
||||||
|
xmake f --CROSSDESK_VERSION=${{ env.VERSION_NUM }} -y
|
||||||
|
xmake b -vy crossdesk
|
||||||
|
|
||||||
- name: Decode and save certificate
|
- name: Decode and save certificate
|
||||||
shell: powershell
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
@@ -321,7 +331,8 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
VERSION="${GITHUB_REF##*/}"
|
VERSION="${GITHUB_REF##*/}"
|
||||||
VERSION_NUM="${VERSION#v}"
|
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
||||||
|
VERSION_NUM="${VERSION#v}-${SHORT_SHA}"
|
||||||
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_OUTPUT
|
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Rename artifacts
|
- name: Rename artifacts
|
||||||
80
.github/workflows/close-issue.yml
vendored
Normal file
80
.github/workflows/close-issue.yml
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
name: Close Inactive Issues
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# run every day at midnight
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
close_inactive_issues:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check inactive issues and close them
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const { data: issues } = await github.rest.issues.listForRepo({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
state: 'open',
|
||||||
|
per_page: 100,
|
||||||
|
});
|
||||||
|
|
||||||
|
const now = new Date().getTime();
|
||||||
|
const inactivePeriod = 7 * 24 * 60 * 60 * 1000; // 7 days
|
||||||
|
|
||||||
|
for (const issue of issues) {
|
||||||
|
// skip pull requests (they are also returned by listForRepo)
|
||||||
|
if (issue.pull_request) continue;
|
||||||
|
|
||||||
|
// skip labeled issues
|
||||||
|
if (issue.labels.length > 0) {
|
||||||
|
console.log(`Skipping issue #${issue.number} (Has labels).`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch comments for this issue
|
||||||
|
const { data: comments } = await github.rest.issues.listComments({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
per_page: 100,
|
||||||
|
});
|
||||||
|
|
||||||
|
// determine the "last activity" time
|
||||||
|
let lastActivityTime;
|
||||||
|
if (comments.length > 0) {
|
||||||
|
const lastComment = comments[comments.length - 1];
|
||||||
|
lastActivityTime = new Date(lastComment.updated_at).getTime();
|
||||||
|
} else {
|
||||||
|
lastActivityTime = new Date(issue.created_at).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check inactivity
|
||||||
|
if (now - lastActivityTime > inactivePeriod) {
|
||||||
|
console.log(`Closing inactive issue: #${issue.number} (No recent replies for 7 days)`);
|
||||||
|
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
body: "This issue has been automatically closed due to inactivity for 7 days."
|
||||||
|
});
|
||||||
|
|
||||||
|
await github.rest.issues.update({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue.number,
|
||||||
|
state: 'closed',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log(`Skipping issue #${issue.number} (Active within 7 days).`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -15,8 +15,9 @@ jobs:
|
|||||||
- name: Set version number
|
- name: Set version number
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
|
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
|
||||||
VERSION_NUM="${GITHUB_REF##*/}"
|
VERSION_NUM="${GITHUB_REF##*/}"
|
||||||
VERSION_NUM="${VERSION_NUM#v}"
|
VERSION_NUM="${VERSION_NUM#v}-${SHORT_SHA}"
|
||||||
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
|
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
|
||||||
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_OUTPUT
|
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
@@ -30,11 +31,13 @@ jobs:
|
|||||||
- name: Update download links
|
- name: Update download links
|
||||||
run: |
|
run: |
|
||||||
cd pages
|
cd pages
|
||||||
sed -E -i "s/crossdesk-win-x64-[0-9]+\.[0-9]+\.[0-9]+\.exe/crossdesk-win-x64-${VERSION_NUM}.exe/g" index.html
|
echo "Updating download links to ${VERSION_NUM}"
|
||||||
sed -E -i "s/crossdesk-macos-x64-[0-9]+\.[0-9]+\.[0-9]+\.pkg/crossdesk-macos-x64-${VERSION_NUM}.pkg/g" index.html
|
sed -E -i "s/crossdesk-win-x64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.exe/crossdesk-win-x64-${VERSION_NUM}.exe/g" index.html
|
||||||
sed -E -i "s/crossdesk-macos-arm64-[0-9]+\.[0-9]+\.[0-9]+\.pkg/crossdesk-macos-arm64-${VERSION_NUM}.pkg/g" index.html
|
sed -E -i "s/crossdesk-macos-x64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.pkg/crossdesk-macos-x64-${VERSION_NUM}.pkg/g" index.html
|
||||||
sed -E -i "s/crossdesk-linux-amd64-[0-9]+\.[0-9]+\.[0-9]+\.deb/crossdesk-linux-amd64-${VERSION_NUM}.deb/g" index.html
|
sed -E -i "s/crossdesk-macos-arm64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.pkg/crossdesk-macos-arm64-${VERSION_NUM}.pkg/g" index.html
|
||||||
sed -E -i "s/crossdesk-linux-arm64-[0-9]+\.[0-9]+\.[0-9]+\.deb/crossdesk-linux-arm64-${VERSION_NUM}.deb/g" index.html
|
sed -E -i "s/crossdesk-linux-amd64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.deb/crossdesk-linux-amd64-${VERSION_NUM}.deb/g" index.html
|
||||||
|
sed -E -i "s/crossdesk-linux-arm64-[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9._-]+)?\.deb/crossdesk-linux-arm64-${VERSION_NUM}.deb/g" index.html
|
||||||
|
git diff index.html || true
|
||||||
|
|
||||||
- name: Commit & Push changes
|
- name: Commit & Push changes
|
||||||
run: |
|
run: |
|
||||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
|||||||
[submodule "thirdparty/minirtc"]
|
[submodule "submodules/minirtc"]
|
||||||
path = thirdparty/minirtc
|
path = submodules/minirtc
|
||||||
url = https://github.com/kunkundi/minirtc.git
|
url = https://github.com/kunkundi/minirtc.git
|
||||||
|
|||||||
229
README.md
229
README.md
@@ -1,9 +1,15 @@
|
|||||||
# CrossDesk
|
# CrossDesk
|
||||||
|
|
||||||
#### 跨界连接,高效如一
|
[]()
|
||||||
|
[](https://www.gnu.org/licenses/lgpl-3.0)
|
||||||
|
[](https://github.com/kunkundi/crossdesk/commits/self-hosted-server)
|
||||||
|
[](https://github.com/kunkundi/crossdesk/actions)
|
||||||
|
[](https://hub.docker.com/r/crossdesk/crossdesk-server/tags)
|
||||||
|
[]()
|
||||||
|
[]()
|
||||||
|
[]()
|
||||||
|
|
||||||
----
|
[ [English](README_EN.md) / 中文 ]
|
||||||
[English](README_EN.md) / [中文](README.md)
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -49,19 +55,7 @@ git submodule init
|
|||||||
|
|
||||||
git submodule update
|
git submodule update
|
||||||
|
|
||||||
xmake b crossdesk
|
xmake b -vy crossdesk
|
||||||
```
|
|
||||||
#### 无 CUDA 环境下的开发支持
|
|
||||||
|
|
||||||
对于未安装 **CUDA 环境** 的Linux开发者,这里提供了预配置的 [Ubuntu 22.04 Docker 镜像](https://hub.docker.com/r/crossdesk/ubuntu22.04)。
|
|
||||||
该镜像内置必要的构建依赖,可在容器中开箱即用,无需额外配置即可直接编译项目。
|
|
||||||
|
|
||||||
进入容器,下载工程后执行:
|
|
||||||
```
|
|
||||||
export CUDA_PATH=/usr/local/cuda
|
|
||||||
export XMAKE_GLOBALDIR=/data
|
|
||||||
|
|
||||||
xmake b --root crossdesk
|
|
||||||
```
|
```
|
||||||
|
|
||||||
运行
|
运行
|
||||||
@@ -69,10 +63,43 @@ xmake b --root crossdesk
|
|||||||
xmake r crossdesk
|
xmake r crossdesk
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 无 CUDA 环境下的开发支持
|
||||||
|
|
||||||
|
对于**未安装 CUDA 环境的 Linux 开发者**,这里提供了预配置的 [Ubuntu 22.04 Docker 镜像](https://hub.docker.com/r/crossdesk/ubuntu22.04)。该镜像内置必要的构建依赖,可在容器中开箱即用,无需额外配置即可直接编译项目。
|
||||||
|
|
||||||
|
进入容器,下载工程后执行:
|
||||||
|
```
|
||||||
|
export CUDA_PATH=/usr/local/cuda
|
||||||
|
export XMAKE_GLOBALDIR=/data
|
||||||
|
|
||||||
|
xmake b --root -vy crossdesk
|
||||||
|
```
|
||||||
|
|
||||||
|
对于**未安装 CUDA 环境的 Windows 开发者**,执行下面的命令安装 CUDA 编译环境:
|
||||||
|
```
|
||||||
|
xmake require -vy "cuda 12.6.3"
|
||||||
|
```
|
||||||
|
安装完成后执行:
|
||||||
|
```
|
||||||
|
xmake require --info "cuda 12.6.3"
|
||||||
|
```
|
||||||
|
输出如下:
|
||||||
|
|
||||||
|
<img width="860" height="226" alt="Image" src="https://github.com/user-attachments/assets/999ac365-581a-4b9a-806e-05eb3e4cf44d" />
|
||||||
|
|
||||||
|
根据上述输出获取到 CUDA 的安装目录,即 installdir 指向的位置。将 CUDA_PATH 加入系统环境变量,或在终端中输入:
|
||||||
|
```
|
||||||
|
set CUDA_PATH=path_to_cuda_installdir
|
||||||
|
```
|
||||||
|
重新执行:
|
||||||
|
```
|
||||||
|
xmake b -vy crossdesk
|
||||||
|
```
|
||||||
|
|
||||||
#### 注意
|
#### 注意
|
||||||
运行时如果客户端状态栏显示 **未连接服务器**,请先在 [CrossDesk 官方网站](https://www.crossdesk.cn/) 安装客户端,以便在环境中安装所需的证书文件。
|
运行时如果客户端状态栏显示 **未连接服务器**,请先在 [CrossDesk 官方网站](https://www.crossdesk.cn/) 安装客户端,以便在环境中安装所需的证书文件。
|
||||||
|
|
||||||
<img width="129" height="60" alt="image" src="https://github.com/user-attachments/assets/1812f7d6-516b-4b4f-8a3d-98bee505cc5a" />
|
<img width="256" height="120" alt="image" src="https://github.com/user-attachments/assets/1812f7d6-516b-4b4f-8a3d-98bee505cc5a" />
|
||||||
|
|
||||||
## 关于 Xmake
|
## 关于 Xmake
|
||||||
|
|
||||||
@@ -110,3 +137,171 @@ xmake b -vy crossdesk
|
|||||||
xmake r -d crossdesk
|
xmake r -d crossdesk
|
||||||
```
|
```
|
||||||
更多使用方法可参考 [Xmake官方文档](https://xmake.io/guide/quick-start.html) 。
|
更多使用方法可参考 [Xmake官方文档](https://xmake.io/guide/quick-start.html) 。
|
||||||
|
|
||||||
|
## 自托管服务器
|
||||||
|
推荐使用Docker部署CrossDesk Server。
|
||||||
|
```
|
||||||
|
sudo docker run -d \
|
||||||
|
--name crossdesk_server \
|
||||||
|
--network host \
|
||||||
|
-e EXTERNAL_IP=xxx.xxx.xxx.xxx \
|
||||||
|
-e INTERNAL_IP=xxx.xxx.xxx.xxx \
|
||||||
|
-e CROSSDESK_SERVER_PORT=xxxx \
|
||||||
|
-e COTURN_PORT=xxxx \
|
||||||
|
-e MIN_PORT=xxxxx \
|
||||||
|
-e MAX_PORT=xxxxx \
|
||||||
|
-v /path/to/your/certs:/crossdesk-server/certs \
|
||||||
|
-v /path/to/your/db:/crossdesk-server/db \
|
||||||
|
-v /path/to/your/logs:/crossdesk-server/logs \
|
||||||
|
crossdesk/crossdesk-server:v1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
上述命令中,用户需注意的参数如下:
|
||||||
|
|
||||||
|
- EXTERNAL_IP:服务器公网 IP , 对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器地址**
|
||||||
|
|
||||||
|
- INTERNAL_IP:服务器内网 IP
|
||||||
|
|
||||||
|
- CROSSDESK_SERVER_PORT:自托管服务使用的端口,对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器端口**
|
||||||
|
|
||||||
|
- COTURN_PORT: COTURN 服务使用的端口, 对应 CrossDesk 客户端**自托管服务器配置**中填写的**中继服务端口**
|
||||||
|
|
||||||
|
- MIN_PORT/MAX_PORT:COTURN 服务使用的端口范围,例如:MIN_PORT=50000, MAX_PORT=60000,范围可根据客户端数量调整。
|
||||||
|
|
||||||
|
- /path/to/your/certs:证书文件目录
|
||||||
|
|
||||||
|
- /path/to/your/db:CrossDesk Server 设备管理数据库
|
||||||
|
|
||||||
|
- /path/to/your/logs:日志目录
|
||||||
|
|
||||||
|
**注意**:
|
||||||
|
- **/path/to/your/ 是示例路径,请替换为你自己的实际路径。挂载的目录必须事先创建好,否则容器会报错。**
|
||||||
|
- **服务器需开放端口:3478/udp,3478/tcp,MIN_PORT-MAX_PORT/udp,CROSSDESK_SERVER_PORT/tcp。**
|
||||||
|
|
||||||
|
## 证书文件
|
||||||
|
客户端需加载根证书文件,服务端需加载服务器私钥和服务器证书文件。
|
||||||
|
|
||||||
|
如果已有SSL证书的用户,可以忽略下面的证书生成步骤。
|
||||||
|
|
||||||
|
对于无证书的用户,可使用下面的脚本自行生成证书文件:
|
||||||
|
```
|
||||||
|
# 创建证书生成脚本
|
||||||
|
vim generate_certs.sh
|
||||||
|
```
|
||||||
|
拷贝到脚本中
|
||||||
|
```
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 检查参数
|
||||||
|
if [ "$#" -ne 1 ]; then
|
||||||
|
echo "Usage: $0 <SERVER_IP>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SERVER_IP="$1"
|
||||||
|
|
||||||
|
# 文件名
|
||||||
|
ROOT_KEY="crossdesk.cn_root.key"
|
||||||
|
ROOT_CERT="crossdesk.cn_root.crt"
|
||||||
|
SERVER_KEY="crossdesk.cn.key"
|
||||||
|
SERVER_CSR="crossdesk.cn.csr"
|
||||||
|
SERVER_CERT="crossdesk.cn_bundle.crt"
|
||||||
|
FULLCHAIN_CERT="crossdesk.cn_fullchain.crt"
|
||||||
|
|
||||||
|
# 证书主题
|
||||||
|
SUBJ="/C=CN/ST=Zhejiang/L=Hangzhou/O=CrossDesk/OU=CrossDesk/CN=$SERVER_IP"
|
||||||
|
|
||||||
|
# 1. 生成根证书
|
||||||
|
echo "Generating root private key..."
|
||||||
|
openssl genrsa -out "$ROOT_KEY" 4096
|
||||||
|
|
||||||
|
echo "Generating self-signed root certificate..."
|
||||||
|
openssl req -x509 -new -nodes -key "$ROOT_KEY" -sha256 -days 3650 -out "$ROOT_CERT" -subj "$SUBJ"
|
||||||
|
|
||||||
|
# 2. 生成服务器私钥
|
||||||
|
echo "Generating server private key..."
|
||||||
|
openssl genrsa -out "$SERVER_KEY" 2048
|
||||||
|
|
||||||
|
# 3. 生成服务器 CSR
|
||||||
|
echo "Generating server CSR..."
|
||||||
|
openssl req -new -key "$SERVER_KEY" -out "$SERVER_CSR" -subj "$SUBJ"
|
||||||
|
|
||||||
|
# 4. 生成临时 OpenSSL 配置文件,加入 SAN
|
||||||
|
SAN_CONF="san.cnf"
|
||||||
|
cat > $SAN_CONF <<EOL
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
req_extensions = req_ext
|
||||||
|
prompt = no
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
C = CN
|
||||||
|
ST = Zhejiang
|
||||||
|
L = Hangzhou
|
||||||
|
O = CrossDesk
|
||||||
|
OU = CrossDesk
|
||||||
|
CN = $SERVER_IP
|
||||||
|
|
||||||
|
[ req_ext ]
|
||||||
|
subjectAltName = IP:$SERVER_IP
|
||||||
|
EOL
|
||||||
|
|
||||||
|
# 5. 用根证书签发服务器证书(包含 SAN)
|
||||||
|
echo "Signing server certificate with root certificate..."
|
||||||
|
openssl x509 -req -in "$SERVER_CSR" -CA "$ROOT_CERT" -CAkey "$ROOT_KEY" -CAcreateserial \
|
||||||
|
-out "$SERVER_CERT" -days 3650 -sha256 -extfile "$SAN_CONF" -extensions req_ext
|
||||||
|
|
||||||
|
# 6. 生成完整链证书
|
||||||
|
cat "$SERVER_CERT" "$ROOT_CERT" > "$FULLCHAIN_CERT"
|
||||||
|
|
||||||
|
# 7. 清理中间文件
|
||||||
|
rm -f "$ROOT_CERT.srl" "$SAN_CONF" "$ROOT_KEY" "$SERVER_CSR" "FULLCHAIN_CERT"
|
||||||
|
|
||||||
|
echo "Generation complete. Deployment files:"
|
||||||
|
echo " Client root certificate: $ROOT_CERT"
|
||||||
|
echo " Server private key: $SERVER_KEY"
|
||||||
|
echo " Server certificate: $SERVER_CERT"
|
||||||
|
```
|
||||||
|
执行
|
||||||
|
```
|
||||||
|
chmod +x generate_certs.sh
|
||||||
|
./generate_certs.sh 服务器公网IP
|
||||||
|
|
||||||
|
# 例如 ./generate_certs.sh 111.111.111.111
|
||||||
|
```
|
||||||
|
输出如下:
|
||||||
|
```
|
||||||
|
Generating root private key...
|
||||||
|
Generating self-signed root certificate...
|
||||||
|
Generating server private key...
|
||||||
|
Generating server CSR...
|
||||||
|
Signing server certificate with root certificate...
|
||||||
|
Certificate request self-signature ok
|
||||||
|
subject=C = CN, ST = Zhejiang, L = Hangzhou, O = CrossDesk, OU = CrossDesk, CN = xxx.xxx.xxx.xxx
|
||||||
|
cleaning up intermediate files...
|
||||||
|
Generation complete. Deployment files::
|
||||||
|
Client root certificate:: crossdesk.cn_root.crt
|
||||||
|
Server private key: crossdesk.cn.key
|
||||||
|
Server certificate: crossdesk.cn_bundle.crt
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 服务端
|
||||||
|
将 **crossdesk.cn.key** 和 **crossdesk.cn_bundle.crt** 放置到 **/path/to/your/certs** 目录下。
|
||||||
|
|
||||||
|
#### 客户端
|
||||||
|
1. 点击右上角设置进入设置页面。<br>
|
||||||
|
<img width="600" height="210" alt="image" src="https://github.com/user-attachments/assets/6431131d-b32a-4726-8783-6788f47baa3b" /><br><br>
|
||||||
|
|
||||||
|
3. 点击点击**自托管服务器配置**。<br><br>
|
||||||
|
<img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/24c761a3-1985-4d7e-84be-787383c2afb8" /><br><br>
|
||||||
|
|
||||||
|
5. 在**证书文件路径**选择框中找到 **crossdesk.cn_root.crt** 的存放路径,选中 **crossdesk.cn_root.crt**,点击确认。<br><br>
|
||||||
|
<img width="600" height="220" alt="image" src="https://github.com/user-attachments/assets/4af7cd3a-c72e-44fb-b032-30e050019c2a" /><br><br>
|
||||||
|
|
||||||
|
7. 勾选使用**自托管服务器配置**,点击确认配置生效。<br><br>
|
||||||
|
<img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/1e455dc3-4087-4f37-a544-1ff9f8789383" /><br><br>
|
||||||
|
|
||||||
|
# 常见问题
|
||||||
|
见 [常见问题](https://github.com/kunkundi/crossdesk/blob/self-hosted-server/docs/FAQ.md) 。
|
||||||
238
README_EN.md
238
README_EN.md
@@ -1,9 +1,15 @@
|
|||||||
# CrossDesk
|
# CrossDesk
|
||||||
|
|
||||||
#### Bridging work, uniting efficiency
|
[]()
|
||||||
|
[](https://www.gnu.org/licenses/lgpl-3.0)
|
||||||
|
[](https://github.com/kunkundi/crossdesk/commits/self-hosted-server)
|
||||||
|
[](https://github.com/kunkundi/crossdesk/actions)
|
||||||
|
[](https://hub.docker.com/r/crossdesk/crossdesk-server/tags)
|
||||||
|
[]()
|
||||||
|
[]()
|
||||||
|
[]()
|
||||||
|
|
||||||
----
|
[ [中文](README.md) / English ]
|
||||||
[中文](README.md) / [English](README_EN.md)
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -17,15 +23,15 @@ CrossDesk is an experimental application of [MiniRTC](https://github.com/kunkund
|
|||||||
|
|
||||||
Enter the remote desktop ID in the menu bar’s “Remote ID” field and click “→” to initiate a remote connection.
|
Enter the remote desktop ID in the menu bar’s “Remote ID” field and click “→” to initiate a remote connection.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
If the remote desktop requires a connection password, you must enter the correct password on your side to successfully establish the connection.
|
If the remote desktop requires a connection password, you must enter the correct password on your side to successfully establish the connection.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Before connecting, you can customize configuration options in the settings, such as language and video encoding format.
|
Before connecting, you can customize configuration options in the settings, such as language and video encoding format.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## How to build
|
## How to build
|
||||||
|
|
||||||
@@ -49,20 +55,7 @@ git submodule init
|
|||||||
|
|
||||||
git submodule update
|
git submodule update
|
||||||
|
|
||||||
xmake b crossdesk
|
xmake b -vy crossdesk
|
||||||
```
|
|
||||||
|
|
||||||
#### Development Without CUDA Environment
|
|
||||||
|
|
||||||
For developers who do not have a **CUDA environment** installed, a preconfigured [Ubuntu 22.04 Docker image](https://hub.docker.com/r/crossdesk/ubuntu22.04) is provided.
|
|
||||||
This image comes with all required build dependencies and allows you to build the project directly inside the container without any additional setup.
|
|
||||||
|
|
||||||
After entering the container, download the project and run:
|
|
||||||
```
|
|
||||||
export CUDA_PATH=/usr/local/cuda
|
|
||||||
export XMAKE_GLOBALDIR=/data
|
|
||||||
|
|
||||||
xmake b --root crossdesk
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
@@ -70,10 +63,45 @@ Run:
|
|||||||
xmake r crossdesk
|
xmake r crossdesk
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Development Without CUDA Environment
|
||||||
|
|
||||||
|
For **Linux developers who do not have a CUDA environment** installed, a preconfigured [Ubuntu 22.04 Docker image](https://hub.docker.com/r/crossdesk/ubuntu22.04) is provided.
|
||||||
|
This image comes with all required build dependencies and allows you to build the project directly inside the container without any additional setup.
|
||||||
|
|
||||||
|
After entering the container, download the project and run:
|
||||||
|
```
|
||||||
|
export CUDA_PATH=/usr/local/cuda
|
||||||
|
export XMAKE_GLOBALDIR=/data
|
||||||
|
|
||||||
|
xmake b --root -vy crossdesk
|
||||||
|
```
|
||||||
|
|
||||||
|
For **Windows developers without a CUDA environment** installed, run the following command to install the CUDA build environment:
|
||||||
|
```
|
||||||
|
xmake require -vy "cuda 12.6.3"
|
||||||
|
```
|
||||||
|
After the installation is complete, execute:
|
||||||
|
```
|
||||||
|
xmake require --info "cuda 12.6.3"
|
||||||
|
```
|
||||||
|
The output will look like this:
|
||||||
|
|
||||||
|
<img width="860" height="226" alt="Image" src="https://github.com/user-attachments/assets/999ac365-581a-4b9a-806e-05eb3e4cf44d" />
|
||||||
|
|
||||||
|
From the output above, locate the CUDA installation directory — this is the path pointed to by installdir.
|
||||||
|
Add this path to your system environment variable CUDA_PATH, or set it in the terminal using:
|
||||||
|
```
|
||||||
|
set CUDA_PATH=path_to_cuda_installdir:
|
||||||
|
```
|
||||||
|
Then re-run:
|
||||||
|
```
|
||||||
|
xmake b -vy crossdesk
|
||||||
|
```
|
||||||
|
|
||||||
#### Notice
|
#### Notice
|
||||||
If the client status bar shows **Disconnected** during runtime, please first install the client from the [CrossDesk official website](https://www.crossdesk.cn/) to ensure the required certificate files are available in the environment.
|
If the client status bar shows **Disconnected** during runtime, please first install the client from the [CrossDesk official website](https://www.crossdesk.cn/) to ensure the required certificate files are available in the environment.
|
||||||
|
|
||||||
<img width="108" height="57" alt="image" src="https://github.com/user-attachments/assets/26e8b9f3-b326-410e-9466-dd073eaf675a" />
|
<img width="256" height="120" alt="image" src="https://github.com/user-attachments/assets/1812f7d6-516b-4b4f-8a3d-98bee505cc5a" />
|
||||||
|
|
||||||
## About Xmake
|
## About Xmake
|
||||||
#### Installing Xmake
|
#### Installing Xmake
|
||||||
@@ -114,3 +142,171 @@ xmake r -d crossdesk
|
|||||||
```
|
```
|
||||||
|
|
||||||
For more information, please refer to the [official Xmake documentation](https://xmake.io/guide/quick-start.html) .
|
For more information, please refer to the [official Xmake documentation](https://xmake.io/guide/quick-start.html) .
|
||||||
|
|
||||||
|
## Self-Hosted Server
|
||||||
|
It is recommended to deploy CrossDesk Server using Docker.
|
||||||
|
```
|
||||||
|
sudo docker run -d \
|
||||||
|
--name crossdesk_server \
|
||||||
|
--network host \
|
||||||
|
-e EXTERNAL_IP=xxx.xxx.xxx.xxx \
|
||||||
|
-e INTERNAL_IP=xxx.xxx.xxx.xxx \
|
||||||
|
-e CROSSDESK_SERVER_PORT=xxxx \
|
||||||
|
-e COTURN_PORT=xxxx \
|
||||||
|
-e MIN_PORT=xxxxx \
|
||||||
|
-e MAX_PORT=xxxxx \
|
||||||
|
-v /path/to/your/certs:/crossdesk-server/certs \
|
||||||
|
-v /path/to/your/db:/crossdesk-server/db \
|
||||||
|
-v /path/to/your/logs:/crossdesk-server/logs \
|
||||||
|
crossdesk/crossdesk-server:v1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
The parameters you need to pay attention to are as follows:
|
||||||
|
|
||||||
|
- **EXTERNAL_IP**: The server's public IP, corresponding to the **Server Address** in the CrossDesk client **Self-Hosted Server Configuration**.
|
||||||
|
|
||||||
|
- **INTERNAL_IP**: The server's internal IP.
|
||||||
|
|
||||||
|
- **CROSSDESK_SERVER_PORT**: The port used by the self-hosted server, corresponding to the **Server Port** in the CrossDesk client **Self-Hosted Server Configuration**.
|
||||||
|
|
||||||
|
- **COTURN_PORT**: The port used by Coturn, corresponding to the **Relay Server Port** in the CrossDesk client **Self-Hosted Server Configuration**.
|
||||||
|
|
||||||
|
- **MIN_PORT** and **MAX_PORT**: The range of ports used by the self-hosted server, corresponding to the **Minimum Port** and **Maximum Port** in the CrossDesk client **Self-Hosted Server Configuration**. Example: 50000-60000. It depends on the number of devices connected to the server.
|
||||||
|
|
||||||
|
- **/path/to/your/certs**: Directory for certificate files.
|
||||||
|
|
||||||
|
- **/path/to/your/db**: CrossDesk Server device management database.
|
||||||
|
|
||||||
|
- **/path/to/your/logs**: Log directory.
|
||||||
|
|
||||||
|
**Note**:
|
||||||
|
- **/path/to/your/ is an example path; please replace it with your actual path. The mounted directories must be created in advance, otherwise the container will fail.**
|
||||||
|
- **The server must open the following ports: 3478/udp, 3478/tcp, 30000-60000/udp, CROSSDESK_SERVER_PORT/tcp.**
|
||||||
|
|
||||||
|
## Certificate Files
|
||||||
|
The client needs to load the root certificate, and the server needs to load the server private key and server certificate.
|
||||||
|
|
||||||
|
If you already have an SSL certificate, you can skip the following certificate generation steps.
|
||||||
|
|
||||||
|
For users without a certificate, you can use the script below to generate the certificate files:
|
||||||
|
```
|
||||||
|
# Create certificate generation script
|
||||||
|
vim generate_certs.sh
|
||||||
|
```
|
||||||
|
Copy the following into the script:
|
||||||
|
```
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Check arguments
|
||||||
|
if [ "$#" -ne 1 ]; then
|
||||||
|
echo "Usage: $0 <SERVER_IP>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SERVER_IP="$1"
|
||||||
|
|
||||||
|
# Filenames
|
||||||
|
ROOT_KEY="crossdesk.cn_root.key"
|
||||||
|
ROOT_CERT="crossdesk.cn_root.crt"
|
||||||
|
SERVER_KEY="crossdesk.cn.key"
|
||||||
|
SERVER_CSR="crossdesk.cn.csr"
|
||||||
|
SERVER_CERT="crossdesk.cn_bundle.crt"
|
||||||
|
FULLCHAIN_CERT="crossdesk.cn_fullchain.crt"
|
||||||
|
|
||||||
|
# Certificate subject
|
||||||
|
SUBJ="/C=CN/ST=Zhejiang/L=Hangzhou/O=CrossDesk/OU=CrossDesk/CN=$SERVER_IP"
|
||||||
|
|
||||||
|
# 1. Generate root certificate
|
||||||
|
echo "Generating root private key..."
|
||||||
|
openssl genrsa -out "$ROOT_KEY" 4096
|
||||||
|
|
||||||
|
echo "Generating self-signed root certificate..."
|
||||||
|
openssl req -x509 -new -nodes -key "$ROOT_KEY" -sha256 -days 3650 -out "$ROOT_CERT" -subj "$SUBJ"
|
||||||
|
|
||||||
|
# 2. Generate server private key
|
||||||
|
echo "Generating server private key..."
|
||||||
|
openssl genrsa -out "$SERVER_KEY" 2048
|
||||||
|
|
||||||
|
# 3. Generate server CSR
|
||||||
|
echo "Generating server CSR..."
|
||||||
|
openssl req -new -key "$SERVER_KEY" -out "$SERVER_CSR" -subj "$SUBJ"
|
||||||
|
|
||||||
|
# 4. Create temporary OpenSSL config file with SAN
|
||||||
|
SAN_CONF="san.cnf"
|
||||||
|
cat > $SAN_CONF <<EOL
|
||||||
|
[ req ]
|
||||||
|
default_bits = 2048
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
req_extensions = req_ext
|
||||||
|
prompt = no
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
C = CN
|
||||||
|
ST = Zhejiang
|
||||||
|
L = Hangzhou
|
||||||
|
O = CrossDesk
|
||||||
|
OU = CrossDesk
|
||||||
|
CN = $SERVER_IP
|
||||||
|
|
||||||
|
[ req_ext ]
|
||||||
|
subjectAltName = IP:$SERVER_IP
|
||||||
|
EOL
|
||||||
|
|
||||||
|
# 5. Sign server certificate with root certificate (including SAN)
|
||||||
|
echo "Signing server certificate with root certificate..."
|
||||||
|
openssl x509 -req -in "$SERVER_CSR" -CA "$ROOT_CERT" -CAkey "$ROOT_KEY" -CAcreateserial \
|
||||||
|
-out "$SERVER_CERT" -days 3650 -sha256 -extfile "$SAN_CONF" -extensions req_ext
|
||||||
|
|
||||||
|
# 6. Generate full chain certificate
|
||||||
|
cat "$SERVER_CERT" "$ROOT_CERT" > "$FULLCHAIN_CERT"
|
||||||
|
|
||||||
|
# 7. Clean up intermediate files
|
||||||
|
rm -f "$ROOT_CERT.srl" "$SAN_CONF" "$ROOT_KEY" "$SERVER_CSR" "FULLCHAIN_CERT"
|
||||||
|
|
||||||
|
echo "Generation complete. Deployment files:"
|
||||||
|
echo " Client root certificate: $ROOT_CERT"
|
||||||
|
echo " Server private key: $SERVER_KEY"
|
||||||
|
echo " Server certificate: $SERVER_CERT"
|
||||||
|
```
|
||||||
|
Execute:
|
||||||
|
```
|
||||||
|
chmod +x generate_certs.sh
|
||||||
|
./generate_certs.sh EXTERNAL_IP
|
||||||
|
|
||||||
|
# example ./generate_certs.sh 111.111.111.111
|
||||||
|
```
|
||||||
|
Expected output:
|
||||||
|
```
|
||||||
|
Generating root private key...
|
||||||
|
Generating self-signed root certificate...
|
||||||
|
Generating server private key...
|
||||||
|
Generating server CSR...
|
||||||
|
Signing server certificate with root certificate...
|
||||||
|
Certificate request self-signature ok
|
||||||
|
subject=C = CN, ST = Zhejiang, L = Hangzhou, O = CrossDesk, OU = CrossDesk, CN = xxx.xxx.xxx.xxx
|
||||||
|
cleaning up intermediate files...
|
||||||
|
Generation complete. Deployment files::
|
||||||
|
Client root certificate:: crossdesk.cn_root.crt
|
||||||
|
Server private key: crossdesk.cn.key
|
||||||
|
Server certificate: crossdesk.cn_bundle.crt
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Server Side
|
||||||
|
Place **crossdesk.cn.key** and **crossdesk.cn_bundle.crt** into the **/path/to/your/certs** directory.
|
||||||
|
|
||||||
|
#### Client Side
|
||||||
|
1. Click the settings icon in the top-right corner to enter the settings page.<br>
|
||||||
|
<img width="600" height="210" alt="image" src="https://github.com/user-attachments/assets/6431131d-b32a-4726-8783-6788f47baa3b" /><br><br>
|
||||||
|
|
||||||
|
2. Click **Self-Hosted Server Configuration**.<br><br>
|
||||||
|
<img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/24c761a3-1985-4d7e-84be-787383c2afb8" /><br><br>
|
||||||
|
|
||||||
|
3. In the **Certificate File Path** selection, locate and select the **crossdesk.cn_root.crt** file.<br><br>
|
||||||
|
<img width="600" height="220" alt="image" src="https://github.com/user-attachments/assets/4af7cd3a-c72e-44fb-b032-30e050019c2a" /><br><br>
|
||||||
|
|
||||||
|
4. Check the option to use **Self-Hosted Server Configuration**.<br><br>
|
||||||
|
<img width="600" height="160" alt="image" src="https://github.com/user-attachments/assets/1e455dc3-4087-4f37-a544-1ff9f8789383" /><br><br>
|
||||||
|
|
||||||
|
# FAQ
|
||||||
|
See [FAQ](https://github.com/kunkundi/crosssesk/blob/self-hosted-server/docs/FAQ.md) .
|
||||||
33
docs/FAQ.md
Normal file
33
docs/FAQ.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# 常见问题(FAQ)
|
||||||
|
|
||||||
|
欢迎来到 **CrossDesk 常见问题** 页面!
|
||||||
|
这里整理了用户和开发者最常见的一些疑问。如果你没有找到答案,欢迎在 [Issues](https://github.com/kunkundi/crossdesk/issues) 中反馈。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Q1. 对等连接失败
|
||||||
|
**A:**
|
||||||
|
打开设置,勾选 **启用中继服务** 选项,尝试重新发起连接。
|
||||||
|
|
||||||
|
<img width="396" height="306" alt="Image" src="https://github.com/user-attachments/assets/fd8db148-c782-4f4d-b874-8f1b2a7ec7d6" />
|
||||||
|
|
||||||
|
由于公共中继服务器带宽较小,连接的清晰度流畅度可能会下降,建议自建服务器。 [Issue #8](https://github.com/kunkundi/crossdesk/issues/8)
|
||||||
|
|
||||||
|
### Q2. Windows 无 CUDA 环境下编译
|
||||||
|
**A:**
|
||||||
|
运行下面的命令安装 CUDA 编译环境。
|
||||||
|
```
|
||||||
|
xmake require -vy "cuda 12.6.3"
|
||||||
|
```
|
||||||
|
安装完成后执行
|
||||||
|
```
|
||||||
|
xmake require --info "cuda 12.6.3"
|
||||||
|
```
|
||||||
|
输出如下
|
||||||
|
|
||||||
|
<img width="860" height="226" alt="Image" src="https://github.com/user-attachments/assets/999ac365-581a-4b9a-806e-05eb3e4cf44d" />
|
||||||
|
|
||||||
|
根据上述输出获取到 CUDA 的安装目录,即 installdir 指向的位置。将 CUDA_PATH 加入系统环境变量,或在终端中输入 set CUDA_PATH=path_to_cuda_installdir,重新执行 xmake b -vy crossdesk 即可。
|
||||||
|
[Issue #6](https://github.com/kunkundi/crossdesk/issues/6)
|
||||||
|
|
||||||
|
---
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
int main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) {
|
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
|
||||||
Render render;
|
crossdesk::Render render;
|
||||||
render.Run();
|
render.Run();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class DisplayInfo {
|
class DisplayInfo {
|
||||||
public:
|
public:
|
||||||
DisplayInfo(std::string name, int left, int top, int right, int bottom)
|
DisplayInfo(std::string name, int left, int top, int right, int bottom)
|
||||||
@@ -40,5 +42,5 @@ class DisplayInfo {
|
|||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
std::string GetMac() {
|
std::string GetMac() {
|
||||||
char mac_addr[16];
|
char mac_addr[16];
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -39,21 +41,21 @@ std::string GetMac() {
|
|||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
std::string if_name = "en0";
|
std::string if_name = "en0";
|
||||||
|
|
||||||
struct ifaddrs *addrs;
|
struct ifaddrs* addrs;
|
||||||
struct ifaddrs *cursor;
|
struct ifaddrs* cursor;
|
||||||
const struct sockaddr_dl *dlAddr;
|
const struct sockaddr_dl* dlAddr;
|
||||||
|
|
||||||
if (!getifaddrs(&addrs)) {
|
if (!getifaddrs(&addrs)) {
|
||||||
cursor = addrs;
|
cursor = addrs;
|
||||||
while (cursor != 0) {
|
while (cursor != 0) {
|
||||||
const struct sockaddr_dl *socAddr =
|
const struct sockaddr_dl* socAddr =
|
||||||
(const struct sockaddr_dl *)cursor->ifa_addr;
|
(const struct sockaddr_dl*)cursor->ifa_addr;
|
||||||
if ((cursor->ifa_addr->sa_family == AF_LINK) &&
|
if ((cursor->ifa_addr->sa_family == AF_LINK) &&
|
||||||
(socAddr->sdl_type == IFT_ETHER) &&
|
(socAddr->sdl_type == IFT_ETHER) &&
|
||||||
strcmp(if_name.c_str(), cursor->ifa_name) == 0) {
|
strcmp(if_name.c_str(), cursor->ifa_name) == 0) {
|
||||||
dlAddr = (const struct sockaddr_dl *)cursor->ifa_addr;
|
dlAddr = (const struct sockaddr_dl*)cursor->ifa_addr;
|
||||||
const unsigned char *base =
|
const unsigned char* base =
|
||||||
(const unsigned char *)&dlAddr->sdl_data[dlAddr->sdl_nlen];
|
(const unsigned char*)&dlAddr->sdl_data[dlAddr->sdl_nlen];
|
||||||
for (int i = 0; i < dlAddr->sdl_alen; i++) {
|
for (int i = 0; i < dlAddr->sdl_alen; i++) {
|
||||||
len +=
|
len +=
|
||||||
snprintf(mac_addr + len, sizeof(mac_addr) - len, "%.2X", base[i]);
|
snprintf(mac_addr + len, sizeof(mac_addr) - len, "%.2X", base[i]);
|
||||||
@@ -77,8 +79,8 @@ std::string GetMac() {
|
|||||||
close(sock);
|
close(sock);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
struct ifreq *it = ifc.ifc_req;
|
struct ifreq* it = ifc.ifc_req;
|
||||||
const struct ifreq *const end = it + (ifc.ifc_len / sizeof(struct ifreq));
|
const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
std::strcpy(ifr.ifr_name, it->ifr_name);
|
std::strcpy(ifr.ifr_name, it->ifr_name);
|
||||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
|
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||||
@@ -122,4 +124,5 @@ std::string GetHostName() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return hostname;
|
return hostname;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -9,7 +9,10 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
std::string GetMac();
|
std::string GetMac();
|
||||||
std::string GetHostName();
|
std::string GetHostName();
|
||||||
|
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
3644
src/config_center/SimpleIni.h
Normal file
3644
src/config_center/SimpleIni.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,64 +1,269 @@
|
|||||||
#include "config_center.h"
|
#include "config_center.h"
|
||||||
|
|
||||||
#include "rd_log.h"
|
namespace crossdesk {
|
||||||
|
|
||||||
ConfigCenter::ConfigCenter() {}
|
ConfigCenter::ConfigCenter(const std::string& config_path,
|
||||||
|
const std::string& cert_file_path)
|
||||||
|
: config_path_(config_path),
|
||||||
|
cert_file_path_(cert_file_path),
|
||||||
|
cert_file_path_default_(cert_file_path) {
|
||||||
|
ini_.SetUnicode(true);
|
||||||
|
Load();
|
||||||
|
}
|
||||||
|
|
||||||
ConfigCenter::~ConfigCenter() {}
|
ConfigCenter::~ConfigCenter() {}
|
||||||
|
|
||||||
|
int ConfigCenter::Load() {
|
||||||
|
SI_Error rc = ini_.LoadFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
Save();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
language_ = static_cast<LANGUAGE>(
|
||||||
|
ini_.GetLongValue(section_, "language", static_cast<long>(language_)));
|
||||||
|
|
||||||
|
video_quality_ = static_cast<VIDEO_QUALITY>(ini_.GetLongValue(
|
||||||
|
section_, "video_quality", static_cast<long>(video_quality_)));
|
||||||
|
|
||||||
|
video_frame_rate_ = static_cast<VIDEO_FRAME_RATE>(ini_.GetLongValue(
|
||||||
|
section_, "video_frame_rate", static_cast<long>(video_frame_rate_)));
|
||||||
|
|
||||||
|
video_encode_format_ = static_cast<VIDEO_ENCODE_FORMAT>(
|
||||||
|
ini_.GetLongValue(section_, "video_encode_format",
|
||||||
|
static_cast<long>(video_encode_format_)));
|
||||||
|
|
||||||
|
hardware_video_codec_ = ini_.GetBoolValue(section_, "hardware_video_codec",
|
||||||
|
hardware_video_codec_);
|
||||||
|
|
||||||
|
enable_turn_ = ini_.GetBoolValue(section_, "enable_turn", enable_turn_);
|
||||||
|
enable_srtp_ = ini_.GetBoolValue(section_, "enable_srtp", enable_srtp_);
|
||||||
|
signal_server_host_ = ini_.GetValue(section_, "signal_server_host",
|
||||||
|
signal_server_host_.c_str());
|
||||||
|
signal_server_port_ = static_cast<int>(
|
||||||
|
ini_.GetLongValue(section_, "signal_server_port", signal_server_port_));
|
||||||
|
coturn_server_port_ = static_cast<int>(
|
||||||
|
ini_.GetLongValue(section_, "coturn_server_port", coturn_server_port_));
|
||||||
|
cert_file_path_ =
|
||||||
|
ini_.GetValue(section_, "cert_file_path", cert_file_path_.c_str());
|
||||||
|
enable_self_hosted_ =
|
||||||
|
ini_.GetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
||||||
|
|
||||||
|
enable_minimize_to_tray_ = ini_.GetBoolValue(
|
||||||
|
section_, "enable_minimize_to_tray", enable_minimize_to_tray_);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::Save() {
|
||||||
|
ini_.SetLongValue(section_, "language", static_cast<long>(language_));
|
||||||
|
ini_.SetLongValue(section_, "video_quality",
|
||||||
|
static_cast<long>(video_quality_));
|
||||||
|
ini_.SetLongValue(section_, "video_frame_rate",
|
||||||
|
static_cast<long>(video_frame_rate_));
|
||||||
|
ini_.SetLongValue(section_, "video_encode_format",
|
||||||
|
static_cast<long>(video_encode_format_));
|
||||||
|
ini_.SetBoolValue(section_, "hardware_video_codec", hardware_video_codec_);
|
||||||
|
ini_.SetBoolValue(section_, "enable_turn", enable_turn_);
|
||||||
|
ini_.SetBoolValue(section_, "enable_srtp", enable_srtp_);
|
||||||
|
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
|
||||||
|
ini_.SetLongValue(section_, "signal_server_port",
|
||||||
|
static_cast<long>(signal_server_port_));
|
||||||
|
ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str());
|
||||||
|
ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
||||||
|
ini_.SetBoolValue(section_, "enable_minimize_to_tray",
|
||||||
|
enable_minimize_to_tray_);
|
||||||
|
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setters
|
||||||
|
|
||||||
int ConfigCenter::SetLanguage(LANGUAGE language) {
|
int ConfigCenter::SetLanguage(LANGUAGE language) {
|
||||||
language_ = language;
|
language_ = language;
|
||||||
|
ini_.SetLongValue(section_, "language", static_cast<long>(language_));
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigCenter::SetVideoQuality(VIDEO_QUALITY video_quality) {
|
int ConfigCenter::SetVideoQuality(VIDEO_QUALITY video_quality) {
|
||||||
video_quality_ = video_quality;
|
video_quality_ = video_quality;
|
||||||
|
ini_.SetLongValue(section_, "video_quality",
|
||||||
|
static_cast<long>(video_quality_));
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigCenter::SetVideoFrameRate(VIDEO_FRAME_RATE video_frame_rate) {
|
int ConfigCenter::SetVideoFrameRate(VIDEO_FRAME_RATE video_frame_rate) {
|
||||||
video_frame_rate_ = video_frame_rate;
|
video_frame_rate_ = video_frame_rate;
|
||||||
|
ini_.SetLongValue(section_, "video_frame_rate",
|
||||||
|
static_cast<long>(video_frame_rate_));
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigCenter::SetVideoEncodeFormat(
|
int ConfigCenter::SetVideoEncodeFormat(
|
||||||
VIDEO_ENCODE_FORMAT video_encode_format) {
|
VIDEO_ENCODE_FORMAT video_encode_format) {
|
||||||
video_encode_format_ = video_encode_format;
|
video_encode_format_ = video_encode_format;
|
||||||
|
ini_.SetLongValue(section_, "video_encode_format",
|
||||||
|
static_cast<long>(video_encode_format_));
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigCenter::SetHardwareVideoCodec(bool hardware_video_codec) {
|
int ConfigCenter::SetHardwareVideoCodec(bool hardware_video_codec) {
|
||||||
hardware_video_codec_ = hardware_video_codec;
|
hardware_video_codec_ = hardware_video_codec;
|
||||||
|
ini_.SetBoolValue(section_, "hardware_video_codec", hardware_video_codec_);
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigCenter::SetTurn(bool enable_turn) {
|
int ConfigCenter::SetTurn(bool enable_turn) {
|
||||||
enable_turn_ = enable_turn;
|
enable_turn_ = enable_turn;
|
||||||
|
ini_.SetBoolValue(section_, "enable_turn", enable_turn_);
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigCenter::SetSrtp(bool enable_srtp) {
|
int ConfigCenter::SetSrtp(bool enable_srtp) {
|
||||||
enable_srtp_ = enable_srtp;
|
enable_srtp_ = enable_srtp;
|
||||||
|
ini_.SetBoolValue(section_, "enable_srtp", enable_srtp_);
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigCenter::LANGUAGE ConfigCenter::GetLanguage() { return language_; }
|
int ConfigCenter::SetServerHost(const std::string& signal_server_host) {
|
||||||
|
signal_server_host_ = signal_server_host;
|
||||||
|
ini_.SetValue(section_, "signal_server_host", signal_server_host_.c_str());
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ConfigCenter::VIDEO_QUALITY ConfigCenter::GetVideoQuality() {
|
int ConfigCenter::SetServerPort(int signal_server_port) {
|
||||||
|
signal_server_port_ = signal_server_port;
|
||||||
|
ini_.SetLongValue(section_, "signal_server_port",
|
||||||
|
static_cast<long>(signal_server_port_));
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::SetCoturnServerPort(int coturn_server_port) {
|
||||||
|
coturn_server_port_ = coturn_server_port;
|
||||||
|
SI_Error rc = ini_.SetLongValue(section_, "coturn_server_port",
|
||||||
|
static_cast<long>(coturn_server_port_));
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::SetCertFilePath(const std::string& cert_file_path) {
|
||||||
|
cert_file_path_ = cert_file_path;
|
||||||
|
ini_.SetValue(section_, "cert_file_path", cert_file_path_.c_str());
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::SetSelfHosted(bool enable_self_hosted) {
|
||||||
|
enable_self_hosted_ = enable_self_hosted;
|
||||||
|
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||||
|
if (rc < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::SetMinimizeToTray(bool enable_minimize_to_tray) {
|
||||||
|
enable_minimize_to_tray_ = enable_minimize_to_tray;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// getters
|
||||||
|
|
||||||
|
ConfigCenter::LANGUAGE ConfigCenter::GetLanguage() const { return language_; }
|
||||||
|
|
||||||
|
ConfigCenter::VIDEO_QUALITY ConfigCenter::GetVideoQuality() const {
|
||||||
return video_quality_;
|
return video_quality_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConfigCenter::GetVideoFrameRate() {
|
ConfigCenter::VIDEO_FRAME_RATE ConfigCenter::GetVideoFrameRate() const {
|
||||||
int fps = video_frame_rate_ == VIDEO_FRAME_RATE::FPS_30 ? 30 : 60;
|
return video_frame_rate_;
|
||||||
return fps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigCenter::VIDEO_ENCODE_FORMAT ConfigCenter::GetVideoEncodeFormat() {
|
ConfigCenter::VIDEO_ENCODE_FORMAT ConfigCenter::GetVideoEncodeFormat() const {
|
||||||
return video_encode_format_;
|
return video_encode_format_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigCenter::IsHardwareVideoCodec() { return hardware_video_codec_; }
|
bool ConfigCenter::IsHardwareVideoCodec() const {
|
||||||
|
return hardware_video_codec_;
|
||||||
|
}
|
||||||
|
|
||||||
bool ConfigCenter::IsEnableTurn() { return enable_turn_; }
|
bool ConfigCenter::IsEnableTurn() const { return enable_turn_; }
|
||||||
|
|
||||||
bool ConfigCenter::IsEnableSrtp() { return enable_srtp_; }
|
bool ConfigCenter::IsEnableSrtp() const { return enable_srtp_; }
|
||||||
|
|
||||||
|
std::string ConfigCenter::GetSignalServerHost() const {
|
||||||
|
return signal_server_host_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::GetSignalServerPort() const { return signal_server_port_; }
|
||||||
|
|
||||||
|
int ConfigCenter::GetCoturnServerPort() const { return coturn_server_port_; }
|
||||||
|
|
||||||
|
std::string ConfigCenter::GetCertFilePath() const { return cert_file_path_; }
|
||||||
|
|
||||||
|
std::string ConfigCenter::GetDefaultServerHost() const {
|
||||||
|
return signal_server_host_default_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::GetDefaultSignalServerPort() const {
|
||||||
|
return server_port_default_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigCenter::GetDefaultCoturnServerPort() const {
|
||||||
|
return coturn_server_port_default_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ConfigCenter::GetDefaultCertFilePath() const {
|
||||||
|
return cert_file_path_default_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigCenter::IsSelfHosted() const { return enable_self_hosted_; }
|
||||||
|
|
||||||
|
bool ConfigCenter::IsMinimizeToTray() const { return enable_minimize_to_tray_; }
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -7,18 +7,26 @@
|
|||||||
#ifndef _CONFIG_CENTER_H_
|
#ifndef _CONFIG_CENTER_H_
|
||||||
#define _CONFIG_CENTER_H_
|
#define _CONFIG_CENTER_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "SimpleIni.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class ConfigCenter {
|
class ConfigCenter {
|
||||||
public:
|
public:
|
||||||
enum class LANGUAGE { CHINESE = 0, ENGLISH = 1 };
|
enum class LANGUAGE { CHINESE = 0, ENGLISH = 1 };
|
||||||
enum class VIDEO_QUALITY { LOW = 0, MEDIUM = 1, HIGH = 2 };
|
enum class VIDEO_QUALITY { LOW = 0, MEDIUM = 1, HIGH = 2 };
|
||||||
enum class VIDEO_FRAME_RATE { FPS_30 = 0, FPS_60 = 1 };
|
enum class VIDEO_FRAME_RATE { FPS_30 = 0, FPS_60 = 1 };
|
||||||
enum class VIDEO_ENCODE_FORMAT { AV1 = 0, H264 = 1 };
|
enum class VIDEO_ENCODE_FORMAT { H264 = 0, AV1 = 1 };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConfigCenter();
|
explicit ConfigCenter(
|
||||||
|
const std::string& config_path = "config.ini",
|
||||||
|
const std::string& cert_file_path = "crossdesk.cn_root.crt");
|
||||||
~ConfigCenter();
|
~ConfigCenter();
|
||||||
|
|
||||||
public:
|
// write config
|
||||||
int SetLanguage(LANGUAGE language);
|
int SetLanguage(LANGUAGE language);
|
||||||
int SetVideoQuality(VIDEO_QUALITY video_quality);
|
int SetVideoQuality(VIDEO_QUALITY video_quality);
|
||||||
int SetVideoFrameRate(VIDEO_FRAME_RATE video_frame_rate);
|
int SetVideoFrameRate(VIDEO_FRAME_RATE video_frame_rate);
|
||||||
@@ -26,25 +34,58 @@ class ConfigCenter {
|
|||||||
int SetHardwareVideoCodec(bool hardware_video_codec);
|
int SetHardwareVideoCodec(bool hardware_video_codec);
|
||||||
int SetTurn(bool enable_turn);
|
int SetTurn(bool enable_turn);
|
||||||
int SetSrtp(bool enable_srtp);
|
int SetSrtp(bool enable_srtp);
|
||||||
|
int SetServerHost(const std::string& signal_server_host);
|
||||||
|
int SetServerPort(int signal_server_port);
|
||||||
|
int SetCoturnServerPort(int coturn_server_port);
|
||||||
|
int SetCertFilePath(const std::string& cert_file_path);
|
||||||
|
int SetSelfHosted(bool enable_self_hosted);
|
||||||
|
int SetMinimizeToTray(bool enable_minimize_to_tray);
|
||||||
|
|
||||||
public:
|
// read config
|
||||||
LANGUAGE GetLanguage();
|
|
||||||
VIDEO_QUALITY GetVideoQuality();
|
LANGUAGE GetLanguage() const;
|
||||||
int GetVideoFrameRate();
|
VIDEO_QUALITY GetVideoQuality() const;
|
||||||
VIDEO_ENCODE_FORMAT GetVideoEncodeFormat();
|
VIDEO_FRAME_RATE GetVideoFrameRate() const;
|
||||||
bool IsHardwareVideoCodec();
|
VIDEO_ENCODE_FORMAT GetVideoEncodeFormat() const;
|
||||||
bool IsEnableTurn();
|
bool IsHardwareVideoCodec() const;
|
||||||
bool IsEnableSrtp();
|
bool IsEnableTurn() const;
|
||||||
|
bool IsEnableSrtp() const;
|
||||||
|
std::string GetSignalServerHost() const;
|
||||||
|
int GetSignalServerPort() const;
|
||||||
|
int GetCoturnServerPort() const;
|
||||||
|
std::string GetCertFilePath() const;
|
||||||
|
std::string GetDefaultServerHost() const;
|
||||||
|
int GetDefaultSignalServerPort() const;
|
||||||
|
int GetDefaultCoturnServerPort() const;
|
||||||
|
std::string GetDefaultCertFilePath() const;
|
||||||
|
bool IsSelfHosted() const;
|
||||||
|
bool IsMinimizeToTray() const;
|
||||||
|
|
||||||
|
int Load();
|
||||||
|
int Save();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Default value should be same with parameters in localization.h
|
std::string config_path_;
|
||||||
|
std::string cert_file_path_;
|
||||||
|
CSimpleIniA ini_;
|
||||||
|
const char* section_ = "Settings";
|
||||||
|
|
||||||
LANGUAGE language_ = LANGUAGE::CHINESE;
|
LANGUAGE language_ = LANGUAGE::CHINESE;
|
||||||
VIDEO_QUALITY video_quality_ = VIDEO_QUALITY::MEDIUM;
|
VIDEO_QUALITY video_quality_ = VIDEO_QUALITY::MEDIUM;
|
||||||
VIDEO_FRAME_RATE video_frame_rate_ = VIDEO_FRAME_RATE::FPS_30;
|
VIDEO_FRAME_RATE video_frame_rate_ = VIDEO_FRAME_RATE::FPS_30;
|
||||||
VIDEO_ENCODE_FORMAT video_encode_format_ = VIDEO_ENCODE_FORMAT::AV1;
|
VIDEO_ENCODE_FORMAT video_encode_format_ = VIDEO_ENCODE_FORMAT::H264;
|
||||||
bool hardware_video_codec_ = false;
|
bool hardware_video_codec_ = false;
|
||||||
bool enable_turn_ = false;
|
bool enable_turn_ = false;
|
||||||
bool enable_srtp_ = false;
|
bool enable_srtp_ = false;
|
||||||
|
std::string signal_server_host_ = "api.crossdesk.cn";
|
||||||
|
std::string signal_server_host_default_ = "api.crossdesk.cn";
|
||||||
|
int signal_server_port_ = 9099;
|
||||||
|
int server_port_default_ = 9099;
|
||||||
|
int coturn_server_port_ = 3478;
|
||||||
|
int coturn_server_port_default_ = 3478;
|
||||||
|
std::string cert_file_path_default_ = "";
|
||||||
|
bool enable_self_hosted_ = false;
|
||||||
|
bool enable_minimize_to_tray_ = false;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "display_info.h"
|
#include "display_info.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
mouse = 0,
|
mouse = 0,
|
||||||
keyboard,
|
keyboard,
|
||||||
@@ -79,5 +81,5 @@ class DeviceController {
|
|||||||
// virtual int Hook();
|
// virtual int Hook();
|
||||||
// virtual int Unhook();
|
// virtual int Unhook();
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "keyboard_capturer.h"
|
#include "keyboard_capturer.h"
|
||||||
#include "mouse_controller.h"
|
#include "mouse_controller.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class DeviceControllerFactory {
|
class DeviceControllerFactory {
|
||||||
public:
|
public:
|
||||||
enum Device { Mouse = 0, Keyboard };
|
enum Device { Mouse = 0, Keyboard };
|
||||||
@@ -30,5 +32,5 @@ class DeviceControllerFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "keyboard_converter.h"
|
#include "keyboard_converter.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
static OnKeyAction g_on_key_action = nullptr;
|
static OnKeyAction g_on_key_action = nullptr;
|
||||||
static void* g_user_ptr = nullptr;
|
static void* g_user_ptr = nullptr;
|
||||||
|
|
||||||
@@ -67,3 +69,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -13,20 +13,22 @@
|
|||||||
|
|
||||||
#include "device_controller.h"
|
#include "device_controller.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class KeyboardCapturer : public DeviceController {
|
class KeyboardCapturer : public DeviceController {
|
||||||
public:
|
public:
|
||||||
KeyboardCapturer();
|
KeyboardCapturer();
|
||||||
virtual ~KeyboardCapturer();
|
virtual ~KeyboardCapturer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int Hook(OnKeyAction on_key_action, void *user_ptr);
|
virtual int Hook(OnKeyAction on_key_action, void* user_ptr);
|
||||||
virtual int Unhook();
|
virtual int Unhook();
|
||||||
virtual int SendKeyboardCommand(int key_code, bool is_down);
|
virtual int SendKeyboardCommand(int key_code, bool is_down);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Display *display_;
|
Display* display_;
|
||||||
Window root_;
|
Window root_;
|
||||||
bool running_;
|
bool running_;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -3,12 +3,14 @@
|
|||||||
#include "keyboard_converter.h"
|
#include "keyboard_converter.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
static OnKeyAction g_on_key_action = nullptr;
|
static OnKeyAction g_on_key_action = nullptr;
|
||||||
static void *g_user_ptr = nullptr;
|
static void* g_user_ptr = nullptr;
|
||||||
|
|
||||||
CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type,
|
CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type,
|
||||||
CGEventRef event, void *userInfo) {
|
CGEventRef event, void* userInfo) {
|
||||||
KeyboardCapturer *keyboard_capturer = (KeyboardCapturer *)userInfo;
|
KeyboardCapturer* keyboard_capturer = (KeyboardCapturer*)userInfo;
|
||||||
if (!keyboard_capturer) {
|
if (!keyboard_capturer) {
|
||||||
LOG_ERROR("keyboard_capturer is nullptr");
|
LOG_ERROR("keyboard_capturer is nullptr");
|
||||||
return event;
|
return event;
|
||||||
@@ -91,7 +93,7 @@ KeyboardCapturer::KeyboardCapturer() {}
|
|||||||
|
|
||||||
KeyboardCapturer::~KeyboardCapturer() {}
|
KeyboardCapturer::~KeyboardCapturer() {}
|
||||||
|
|
||||||
int KeyboardCapturer::Hook(OnKeyAction on_key_action, void *user_ptr) {
|
int KeyboardCapturer::Hook(OnKeyAction on_key_action, void* user_ptr) {
|
||||||
g_on_key_action = on_key_action;
|
g_on_key_action = on_key_action;
|
||||||
g_user_ptr = user_ptr;
|
g_user_ptr = user_ptr;
|
||||||
|
|
||||||
@@ -164,4 +166,5 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -11,13 +11,15 @@
|
|||||||
|
|
||||||
#include "device_controller.h"
|
#include "device_controller.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class KeyboardCapturer : public DeviceController {
|
class KeyboardCapturer : public DeviceController {
|
||||||
public:
|
public:
|
||||||
KeyboardCapturer();
|
KeyboardCapturer();
|
||||||
virtual ~KeyboardCapturer();
|
virtual ~KeyboardCapturer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int Hook(OnKeyAction on_key_action, void *user_ptr);
|
virtual int Hook(OnKeyAction on_key_action, void* user_ptr);
|
||||||
virtual int Unhook();
|
virtual int Unhook();
|
||||||
virtual int SendKeyboardCommand(int key_code, bool is_down);
|
virtual int SendKeyboardCommand(int key_code, bool is_down);
|
||||||
|
|
||||||
@@ -33,5 +35,5 @@ class KeyboardCapturer : public DeviceController {
|
|||||||
bool command_flag_ = false;
|
bool command_flag_ = false;
|
||||||
int fn_key_code_ = 0x3F;
|
int fn_key_code_ = 0x3F;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
static OnKeyAction g_on_key_action = nullptr;
|
static OnKeyAction g_on_key_action = nullptr;
|
||||||
static void* g_user_ptr = nullptr;
|
static void* g_user_ptr = nullptr;
|
||||||
|
|
||||||
@@ -53,4 +55,5 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) {
|
|||||||
SendInput(1, &input, sizeof(INPUT));
|
SendInput(1, &input, sizeof(INPUT));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -11,18 +11,21 @@
|
|||||||
|
|
||||||
#include "device_controller.h"
|
#include "device_controller.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class KeyboardCapturer : public DeviceController {
|
class KeyboardCapturer : public DeviceController {
|
||||||
public:
|
public:
|
||||||
KeyboardCapturer();
|
KeyboardCapturer();
|
||||||
virtual ~KeyboardCapturer();
|
virtual ~KeyboardCapturer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int Hook(OnKeyAction on_key_action, void *user_ptr);
|
virtual int Hook(OnKeyAction on_key_action, void* user_ptr);
|
||||||
virtual int Unhook();
|
virtual int Unhook();
|
||||||
virtual int SendKeyboardCommand(int key_code, bool is_down);
|
virtual int SendKeyboardCommand(int key_code, bool is_down);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HHOOK keyboard_hook_ = nullptr;
|
HHOOK keyboard_hook_ = nullptr;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
// Windows vkCode to macOS CGKeyCode (104 keys)
|
// Windows vkCode to macOS CGKeyCode (104 keys)
|
||||||
std::map<int, int> vkCodeToCGKeyCode = {
|
std::map<int, int> vkCodeToCGKeyCode = {
|
||||||
// A-Z
|
// A-Z
|
||||||
@@ -736,5 +738,5 @@ std::map<int, int> x11KeySymToCgKeyCode = {
|
|||||||
{0xFFEB, 0x37}, // Left Command
|
{0xFFEB, 0x37}, // Left Command
|
||||||
{0xFFEC, 0x36}, // Right Command
|
{0xFFEC, 0x36}, // Right Command
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
MouseController::MouseController() {}
|
MouseController::MouseController() {}
|
||||||
|
|
||||||
MouseController::~MouseController() { Destroy(); }
|
MouseController::~MouseController() { Destroy(); }
|
||||||
@@ -121,4 +123,5 @@ void MouseController::SimulateMouseWheel(int direction_button, int count) {
|
|||||||
XTestFakeButtonEvent(display_, direction_button, False, CurrentTime);
|
XTestFakeButtonEvent(display_, direction_button, False, CurrentTime);
|
||||||
}
|
}
|
||||||
XFlush(display_);
|
XFlush(display_);
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include "device_controller.h"
|
#include "device_controller.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class MouseController : public DeviceController {
|
class MouseController : public DeviceController {
|
||||||
public:
|
public:
|
||||||
MouseController();
|
MouseController();
|
||||||
@@ -37,5 +39,5 @@ class MouseController : public DeviceController {
|
|||||||
int screen_width_ = 0;
|
int screen_width_ = 0;
|
||||||
int screen_height_ = 0;
|
int screen_height_ = 0;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
MouseController::MouseController() {}
|
MouseController::MouseController() {}
|
||||||
|
|
||||||
MouseController::~MouseController() {}
|
MouseController::~MouseController() {}
|
||||||
@@ -98,4 +100,5 @@ int MouseController::SendMouseCommand(RemoteAction remote_action,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "device_controller.h"
|
#include "device_controller.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class MouseController : public DeviceController {
|
class MouseController : public DeviceController {
|
||||||
public:
|
public:
|
||||||
MouseController();
|
MouseController();
|
||||||
@@ -26,5 +28,5 @@ class MouseController : public DeviceController {
|
|||||||
bool left_dragging_ = false;
|
bool left_dragging_ = false;
|
||||||
bool right_dragging_ = false;
|
bool right_dragging_ = false;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
MouseController::MouseController() {}
|
MouseController::MouseController() {}
|
||||||
|
|
||||||
MouseController::~MouseController() {}
|
MouseController::~MouseController() {}
|
||||||
@@ -69,4 +71,5 @@ int MouseController::SendMouseCommand(RemoteAction remote_action,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "device_controller.h"
|
#include "device_controller.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class MouseController : public DeviceController {
|
class MouseController : public DeviceController {
|
||||||
public:
|
public:
|
||||||
MouseController();
|
MouseController();
|
||||||
@@ -24,5 +26,5 @@ class MouseController : public DeviceController {
|
|||||||
private:
|
private:
|
||||||
std::vector<DisplayInfo> display_info_list_;
|
std::vector<DisplayInfo> display_info_list_;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
63
src/gui/assets/layouts/layout.h
Normal file
63
src/gui/assets/layouts/layout.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* @Author: DI JUNKUN
|
||||||
|
* @Date: 2024-06-14
|
||||||
|
* Copyright (c) 2024 by DI JUNKUN, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LAYOUT_STYLE_H_
|
||||||
|
#define _LAYOUT_STYLE_H_
|
||||||
|
|
||||||
|
#define MENU_WINDOW_WIDTH_CN 300
|
||||||
|
#define MENU_WINDOW_HEIGHT_CN 280
|
||||||
|
#define LOCAL_WINDOW_WIDTH_CN 300
|
||||||
|
#define LOCAL_WINDOW_HEIGHT_CN 280
|
||||||
|
#define REMOTE_WINDOW_WIDTH_CN 300
|
||||||
|
#define REMOTE_WINDOW_HEIGHT_CN 280
|
||||||
|
#define MENU_WINDOW_WIDTH_EN 190
|
||||||
|
#define MENU_WINDOW_HEIGHT_EN 245
|
||||||
|
#define IPUT_WINDOW_WIDTH 160
|
||||||
|
#define INPUT_WINDOW_PADDING_CN 66
|
||||||
|
#define INPUT_WINDOW_PADDING_EN 96
|
||||||
|
#define SETTINGS_WINDOW_WIDTH_CN 202
|
||||||
|
#define SETTINGS_WINDOW_WIDTH_EN 248
|
||||||
|
#if _WIN32
|
||||||
|
#define SETTINGS_WINDOW_HEIGHT_CN 345
|
||||||
|
#define SETTINGS_WINDOW_HEIGHT_EN 345
|
||||||
|
#else
|
||||||
|
#define SETTINGS_WINDOW_HEIGHT_CN 315
|
||||||
|
#define SETTINGS_WINDOW_HEIGHT_EN 315
|
||||||
|
#endif
|
||||||
|
#define SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_CN 228
|
||||||
|
#define SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_EN 275
|
||||||
|
#define SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_CN 195
|
||||||
|
#define SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_EN 195
|
||||||
|
#define LANGUAGE_SELECT_WINDOW_PADDING_CN 120
|
||||||
|
#define LANGUAGE_SELECT_WINDOW_PADDING_EN 167
|
||||||
|
#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_CN 120
|
||||||
|
#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_EN 167
|
||||||
|
#define VIDEO_FRAME_RATE_SELECT_WINDOW_PADDING_CN 120
|
||||||
|
#define VIDEO_FRAME_RATE_SELECT_WINDOW_PADDING_EN 167
|
||||||
|
#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_CN 120
|
||||||
|
#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_EN 167
|
||||||
|
#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_CN 171
|
||||||
|
#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_EN 218
|
||||||
|
#define ENABLE_TURN_CHECKBOX_PADDING_CN 171
|
||||||
|
#define ENABLE_TURN_CHECKBOX_PADDING_EN 218
|
||||||
|
#define ENABLE_SRTP_CHECKBOX_PADDING_CN 171
|
||||||
|
#define ENABLE_SRTP_CHECKBOX_PADDING_EN 218
|
||||||
|
#define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_CN 171
|
||||||
|
#define ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_EN 218
|
||||||
|
#define ENABLE_MINIZE_TO_TRAY_PADDING_CN 171
|
||||||
|
#define ENABLE_MINIZE_TO_TRAY_PADDING_EN 218
|
||||||
|
#define SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_CN 90
|
||||||
|
#define SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_EN 137
|
||||||
|
#define SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN 90
|
||||||
|
#define SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_EN 137
|
||||||
|
#define SETTINGS_SELECT_WINDOW_WIDTH 73
|
||||||
|
#define SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH 130
|
||||||
|
#define SETTINGS_OK_BUTTON_PADDING_CN 65
|
||||||
|
#define SETTINGS_OK_BUTTON_PADDING_EN 83
|
||||||
|
#define SELF_HOSTED_SERVER_CONFIG_OK_BUTTON_PADDING_CN 78
|
||||||
|
#define SELF_HOSTED_SERVER_CONFIG_OK_BUTTON_PADDING_EN 91
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -8,6 +8,13 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
namespace localization {
|
namespace localization {
|
||||||
|
|
||||||
static std::vector<std::string> local_desktop = {
|
static std::vector<std::string> local_desktop = {
|
||||||
@@ -91,10 +98,24 @@ static std::vector<std::string> enable_hardware_video_codec = {
|
|||||||
"Enable Hardware Video Codec:"};
|
"Enable Hardware Video Codec:"};
|
||||||
static std::vector<std::string> enable_turn = {
|
static std::vector<std::string> enable_turn = {
|
||||||
reinterpret_cast<const char*>(u8"启用中继服务:"), "Enable TURN Service:"};
|
reinterpret_cast<const char*>(u8"启用中继服务:"), "Enable TURN Service:"};
|
||||||
|
|
||||||
static std::vector<std::string> enable_srtp = {
|
static std::vector<std::string> enable_srtp = {
|
||||||
reinterpret_cast<const char*>(u8"启用SRTP:"), "Enable SRTP:"};
|
reinterpret_cast<const char*>(u8"启用SRTP:"), "Enable SRTP:"};
|
||||||
|
static std::vector<std::string> self_hosted_server_config = {
|
||||||
|
reinterpret_cast<const char*>(u8"自托管服务器配置"),
|
||||||
|
"Self-Hosted Server Config"};
|
||||||
|
static std::vector<std::string> self_hosted_server_settings = {
|
||||||
|
reinterpret_cast<const char*>(u8"自托管服务器设置"),
|
||||||
|
"Self-Hosted Server Settings"};
|
||||||
|
static std::vector<std::string> self_hosted_server_address = {
|
||||||
|
reinterpret_cast<const char*>(u8"服务器地址:"), "Server Address:"};
|
||||||
|
static std::vector<std::string> self_hosted_server_port = {
|
||||||
|
reinterpret_cast<const char*>(u8"信令服务端口:"), "Signal Service Port:"};
|
||||||
|
static std::vector<std::string> self_hosted_server_coturn_server_port = {
|
||||||
|
reinterpret_cast<const char*>(u8"中继服务端口:"), "Relay Service Port:"};
|
||||||
|
static std::vector<std::string> self_hosted_server_certificate_path = {
|
||||||
|
reinterpret_cast<const char*>(u8"证书文件路径:"), "Certificate File Path:"};
|
||||||
|
static std::vector<std::string> select_a_file = {
|
||||||
|
reinterpret_cast<const char*>(u8"请选择文件"), "Please select a file"};
|
||||||
static std::vector<std::string> ok = {reinterpret_cast<const char*>(u8"确认"),
|
static std::vector<std::string> ok = {reinterpret_cast<const char*>(u8"确认"),
|
||||||
"OK"};
|
"OK"};
|
||||||
static std::vector<std::string> cancel = {
|
static std::vector<std::string> cancel = {
|
||||||
@@ -143,6 +164,13 @@ static std::vector<std::string> version = {
|
|||||||
static std::vector<std::string> confirm_delete_connection = {
|
static std::vector<std::string> confirm_delete_connection = {
|
||||||
reinterpret_cast<const char*>(u8"确认删除此连接"),
|
reinterpret_cast<const char*>(u8"确认删除此连接"),
|
||||||
"Confirm to delete this connection"};
|
"Confirm to delete this connection"};
|
||||||
} // namespace localization
|
#if _WIN32
|
||||||
|
|
||||||
|
static std::vector<std::string> minimize_to_tray = {
|
||||||
|
reinterpret_cast<const char*>(u8"退出时最小化到系统托盘:"),
|
||||||
|
"Minimize to system tray when exit:"};
|
||||||
|
static std::vector<LPCWSTR> exit_program = {L"退出", L"Exit"};
|
||||||
|
#endif
|
||||||
|
} // namespace localization
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#include "layout_style.h"
|
#include "layout.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::LocalWindow() {
|
int Render::LocalWindow() {
|
||||||
ImGui::SetNextWindowPos(ImVec2(-1.0f, title_bar_height_), ImGuiCond_Always);
|
ImGui::SetNextWindowPos(ImVec2(-1.0f, title_bar_height_), ImGuiCond_Always);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
||||||
@@ -287,4 +289,5 @@ int Render::LocalWindow() {
|
|||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::RecentConnectionsWindow() {
|
int Render::RecentConnectionsWindow() {
|
||||||
ImGui::SetNextWindowPos(
|
ImGui::SetNextWindowPos(
|
||||||
ImVec2(0, title_bar_height_ + local_window_height_ - 1.0f),
|
ImVec2(0, title_bar_height_ + local_window_height_ - 1.0f),
|
||||||
@@ -284,3 +286,4 @@ int Render::ConfirmDeleteConnection() {
|
|||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
#include "layout_style.h"
|
#include "layout.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
static int InputTextCallback(ImGuiInputTextCallbackData *data);
|
namespace crossdesk {
|
||||||
|
|
||||||
|
static int InputTextCallback(ImGuiInputTextCallbackData* data);
|
||||||
|
|
||||||
int Render::RemoteWindow() {
|
int Render::RemoteWindow() {
|
||||||
ImGui::SetNextWindowPos(ImVec2(local_window_width_ + 1.0f, title_bar_height_),
|
ImGui::SetNextWindowPos(ImVec2(local_window_width_ + 1.0f, title_bar_height_),
|
||||||
@@ -77,7 +79,7 @@ int Render::RemoteWindow() {
|
|||||||
enter_pressed) {
|
enter_pressed) {
|
||||||
connect_button_pressed_ = true;
|
connect_button_pressed_ = true;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto &[id, props] : recent_connections_) {
|
for (auto& [id, props] : recent_connections_) {
|
||||||
if (id.find(remote_id) != std::string::npos) {
|
if (id.find(remote_id) != std::string::npos) {
|
||||||
found = true;
|
found = true;
|
||||||
if (client_properties_.find(remote_id) !=
|
if (client_properties_.find(remote_id) !=
|
||||||
@@ -101,7 +103,7 @@ int Render::RemoteWindow() {
|
|||||||
|
|
||||||
if (need_to_rejoin_) {
|
if (need_to_rejoin_) {
|
||||||
need_to_rejoin_ = false;
|
need_to_rejoin_ = false;
|
||||||
for (const auto &[_, props] : client_properties_) {
|
for (const auto& [_, props] : client_properties_) {
|
||||||
if (props->rejoin_) {
|
if (props->rejoin_) {
|
||||||
ConnectTo(props->remote_id_, props->remote_password_,
|
ConnectTo(props->remote_id_, props->remote_password_,
|
||||||
props->remember_password_);
|
props->remember_password_);
|
||||||
@@ -117,7 +119,7 @@ int Render::RemoteWindow() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int InputTextCallback(ImGuiInputTextCallbackData *data) {
|
static int InputTextCallback(ImGuiInputTextCallbackData* data) {
|
||||||
if (data->BufTextLen > 3 && data->Buf[3] != ' ') {
|
if (data->BufTextLen > 3 && data->Buf[3] != ' ') {
|
||||||
data->InsertChars(3, " ");
|
data->InsertChars(3, " ");
|
||||||
}
|
}
|
||||||
@@ -129,7 +131,7 @@ static int InputTextCallback(ImGuiInputTextCallbackData *data) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Render::ConnectTo(const std::string &remote_id, const char *password,
|
int Render::ConnectTo(const std::string& remote_id, const char* password,
|
||||||
bool remember_password) {
|
bool remember_password) {
|
||||||
LOG_INFO("Connect to [{}]", remote_id);
|
LOG_INFO("Connect to [{}]", remote_id);
|
||||||
focused_remote_id_ = remote_id;
|
focused_remote_id_ = remote_id;
|
||||||
@@ -178,4 +180,5 @@ int Render::ConnectTo(const std::string &remote_id, const char *password,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "device_controller_factory.h"
|
#include "device_controller_factory.h"
|
||||||
#include "fa_regular_400.h"
|
#include "fa_regular_400.h"
|
||||||
#include "fa_solid_900.h"
|
#include "fa_solid_900.h"
|
||||||
#include "layout_style.h"
|
#include "layout.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#define MOUSE_GRAB_PADDING 5
|
#define MOUSE_GRAB_PADDING 5
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
std::vector<char> Render::SerializeRemoteAction(const RemoteAction& action) {
|
std::vector<char> Render::SerializeRemoteAction(const RemoteAction& action) {
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
buffer.push_back(static_cast<char>(action.type));
|
buffer.push_back(static_cast<char>(action.type));
|
||||||
@@ -171,7 +173,8 @@ Render::~Render() {}
|
|||||||
|
|
||||||
int Render::SaveSettingsIntoCacheFile() {
|
int Render::SaveSettingsIntoCacheFile() {
|
||||||
cd_cache_mutex_.lock();
|
cd_cache_mutex_.lock();
|
||||||
std::ofstream cd_cache_file(cache_path_ + "/cache.cd", std::ios::binary);
|
std::ofstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
||||||
|
std::ios::binary);
|
||||||
if (!cd_cache_file) {
|
if (!cd_cache_file) {
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
return -1;
|
return -1;
|
||||||
@@ -181,18 +184,6 @@ int Render::SaveSettingsIntoCacheFile() {
|
|||||||
sizeof(cd_cache_.client_id_with_password));
|
sizeof(cd_cache_.client_id_with_password));
|
||||||
memcpy(cd_cache_.client_id_with_password, client_id_with_password_,
|
memcpy(cd_cache_.client_id_with_password, client_id_with_password_,
|
||||||
sizeof(client_id_with_password_));
|
sizeof(client_id_with_password_));
|
||||||
memcpy(&cd_cache_.language, &language_button_value_,
|
|
||||||
sizeof(language_button_value_));
|
|
||||||
memcpy(&cd_cache_.video_quality, &video_quality_button_value_,
|
|
||||||
sizeof(video_quality_button_value_));
|
|
||||||
memcpy(&cd_cache_.video_frame_rate, &video_frame_rate_button_value_,
|
|
||||||
sizeof(video_frame_rate_button_value_));
|
|
||||||
memcpy(&cd_cache_.video_encode_format, &video_encode_format_button_value_,
|
|
||||||
sizeof(video_encode_format_button_value_));
|
|
||||||
memcpy(&cd_cache_.enable_hardware_video_codec, &enable_hardware_video_codec_,
|
|
||||||
sizeof(enable_hardware_video_codec_));
|
|
||||||
memcpy(&cd_cache_.enable_turn, &enable_turn_, sizeof(enable_turn_));
|
|
||||||
memcpy(&cd_cache_.enable_srtp, &enable_srtp_, sizeof(enable_srtp_));
|
|
||||||
memcpy(&cd_cache_.key, &aes128_key_, sizeof(aes128_key_));
|
memcpy(&cd_cache_.key, &aes128_key_, sizeof(aes128_key_));
|
||||||
memcpy(&cd_cache_.iv, &aes128_iv_, sizeof(aes128_iv_));
|
memcpy(&cd_cache_.iv, &aes128_iv_, sizeof(aes128_iv_));
|
||||||
|
|
||||||
@@ -200,49 +191,19 @@ int Render::SaveSettingsIntoCacheFile() {
|
|||||||
cd_cache_file.close();
|
cd_cache_file.close();
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
config_center_.SetLanguage((ConfigCenter::LANGUAGE)language_button_value_);
|
|
||||||
config_center_.SetVideoQuality(
|
|
||||||
(ConfigCenter::VIDEO_QUALITY)video_quality_button_value_);
|
|
||||||
config_center_.SetVideoFrameRate(
|
|
||||||
(ConfigCenter::VIDEO_FRAME_RATE)video_frame_rate_button_value_);
|
|
||||||
config_center_.SetVideoEncodeFormat(
|
|
||||||
(ConfigCenter::VIDEO_ENCODE_FORMAT)video_encode_format_button_value_);
|
|
||||||
config_center_.SetHardwareVideoCodec(enable_hardware_video_codec_);
|
|
||||||
config_center_.SetTurn(enable_turn_);
|
|
||||||
config_center_.SetSrtp(enable_srtp_);
|
|
||||||
|
|
||||||
LOG_INFO("Save settings into cache file success");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Render::LoadSettingsFromCacheFile() {
|
int Render::LoadSettingsFromCacheFile() {
|
||||||
cd_cache_mutex_.lock();
|
cd_cache_mutex_.lock();
|
||||||
std::ifstream cd_cache_file(cache_path_ + "/cache.cd", std::ios::binary);
|
std::ifstream cd_cache_file(cache_path_ + "/secure_cache.enc",
|
||||||
|
std::ios::binary);
|
||||||
if (!cd_cache_file) {
|
if (!cd_cache_file) {
|
||||||
cd_cache_mutex_.unlock();
|
cd_cache_mutex_.unlock();
|
||||||
|
|
||||||
LOG_INFO("Init cache file by using default settings");
|
|
||||||
memset(password_saved_, 0, sizeof(password_saved_));
|
memset(password_saved_, 0, sizeof(password_saved_));
|
||||||
memset(aes128_key_, 0, sizeof(aes128_key_));
|
memset(aes128_key_, 0, sizeof(aes128_key_));
|
||||||
memset(aes128_iv_, 0, sizeof(aes128_iv_));
|
memset(aes128_iv_, 0, sizeof(aes128_iv_));
|
||||||
language_button_value_ = 0;
|
|
||||||
video_quality_button_value_ = 0;
|
|
||||||
video_encode_format_button_value_ = 1;
|
|
||||||
enable_hardware_video_codec_ = false;
|
|
||||||
enable_turn_ = false;
|
|
||||||
enable_srtp_ = false;
|
|
||||||
|
|
||||||
config_center_.SetLanguage((ConfigCenter::LANGUAGE)language_button_value_);
|
|
||||||
config_center_.SetVideoQuality(
|
|
||||||
(ConfigCenter::VIDEO_QUALITY)video_quality_button_value_);
|
|
||||||
config_center_.SetVideoFrameRate(
|
|
||||||
(ConfigCenter::VIDEO_FRAME_RATE)video_frame_rate_button_value_);
|
|
||||||
config_center_.SetVideoEncodeFormat(
|
|
||||||
(ConfigCenter::VIDEO_ENCODE_FORMAT)video_encode_format_button_value_);
|
|
||||||
config_center_.SetHardwareVideoCodec(enable_hardware_video_codec_);
|
|
||||||
config_center_.SetTurn(enable_turn_);
|
|
||||||
config_center_.SetSrtp(enable_srtp_);
|
|
||||||
|
|
||||||
thumbnail_.reset();
|
thumbnail_.reset();
|
||||||
thumbnail_ = std::make_unique<Thumbnail>(cache_path_ + "/thumbnails/");
|
thumbnail_ = std::make_unique<Thumbnail>(cache_path_ + "/thumbnails/");
|
||||||
@@ -289,13 +250,14 @@ int Render::LoadSettingsFromCacheFile() {
|
|||||||
thumbnail_ = std::make_unique<Thumbnail>(cache_path_ + "/thumbnails/",
|
thumbnail_ = std::make_unique<Thumbnail>(cache_path_ + "/thumbnails/",
|
||||||
aes128_key_, aes128_iv_);
|
aes128_key_, aes128_iv_);
|
||||||
|
|
||||||
language_button_value_ = cd_cache_.language;
|
language_button_value_ = (int)config_center_->GetLanguage();
|
||||||
video_quality_button_value_ = cd_cache_.video_quality;
|
video_quality_button_value_ = (int)config_center_->GetVideoQuality();
|
||||||
video_frame_rate_button_value_ = cd_cache_.video_frame_rate;
|
video_frame_rate_button_value_ = (int)config_center_->GetVideoFrameRate();
|
||||||
video_encode_format_button_value_ = cd_cache_.video_encode_format;
|
video_encode_format_button_value_ =
|
||||||
enable_hardware_video_codec_ = cd_cache_.enable_hardware_video_codec;
|
(int)config_center_->GetVideoEncodeFormat();
|
||||||
enable_turn_ = cd_cache_.enable_turn;
|
enable_hardware_video_codec_ = config_center_->IsHardwareVideoCodec();
|
||||||
enable_srtp_ = cd_cache_.enable_srtp;
|
enable_turn_ = config_center_->IsEnableTurn();
|
||||||
|
enable_srtp_ = config_center_->IsEnableSrtp();
|
||||||
|
|
||||||
language_button_value_last_ = language_button_value_;
|
language_button_value_last_ = language_button_value_;
|
||||||
video_quality_button_value_last_ = video_quality_button_value_;
|
video_quality_button_value_last_ = video_quality_button_value_;
|
||||||
@@ -304,17 +266,6 @@ int Render::LoadSettingsFromCacheFile() {
|
|||||||
enable_turn_last_ = enable_turn_;
|
enable_turn_last_ = enable_turn_;
|
||||||
enable_srtp_last_ = enable_srtp_;
|
enable_srtp_last_ = enable_srtp_;
|
||||||
|
|
||||||
config_center_.SetLanguage((ConfigCenter::LANGUAGE)language_button_value_);
|
|
||||||
config_center_.SetVideoQuality(
|
|
||||||
(ConfigCenter::VIDEO_QUALITY)video_quality_button_value_);
|
|
||||||
config_center_.SetVideoFrameRate(
|
|
||||||
(ConfigCenter::VIDEO_FRAME_RATE)video_frame_rate_button_value_);
|
|
||||||
config_center_.SetVideoEncodeFormat(
|
|
||||||
(ConfigCenter::VIDEO_ENCODE_FORMAT)video_encode_format_button_value_);
|
|
||||||
config_center_.SetHardwareVideoCodec(enable_hardware_video_codec_);
|
|
||||||
config_center_.SetTurn(enable_turn_);
|
|
||||||
config_center_.SetSrtp(enable_srtp_);
|
|
||||||
|
|
||||||
LOG_INFO("Load settings from cache file");
|
LOG_INFO("Load settings from cache file");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -328,18 +279,21 @@ int Render::ScreenCapturerInit() {
|
|||||||
last_frame_time_ = std::chrono::duration_cast<std::chrono::milliseconds>(
|
last_frame_time_ = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
std::chrono::steady_clock::now().time_since_epoch())
|
std::chrono::steady_clock::now().time_since_epoch())
|
||||||
.count();
|
.count();
|
||||||
int fps = config_center_.GetVideoFrameRate();
|
int fps = config_center_->GetVideoFrameRate() ==
|
||||||
|
ConfigCenter::VIDEO_FRAME_RATE::FPS_30
|
||||||
|
? 30
|
||||||
|
: 60;
|
||||||
LOG_INFO("Init screen capturer with {} fps", fps);
|
LOG_INFO("Init screen capturer with {} fps", fps);
|
||||||
|
|
||||||
int screen_capturer_init_ret = screen_capturer_->Init(
|
int screen_capturer_init_ret = screen_capturer_->Init(
|
||||||
fps,
|
fps,
|
||||||
[this](unsigned char* data, int size, int width, int height,
|
[this, fps](unsigned char* data, int size, int width, int height,
|
||||||
const char* display_name) -> void {
|
const char* display_name) -> void {
|
||||||
auto now_time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
auto now_time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
std::chrono::steady_clock::now().time_since_epoch())
|
std::chrono::steady_clock::now().time_since_epoch())
|
||||||
.count();
|
.count();
|
||||||
auto duration = now_time - last_frame_time_;
|
auto duration = now_time - last_frame_time_;
|
||||||
if (duration * config_center_.GetVideoFrameRate() >= 1000) { // ~60 FPS
|
if (duration * fps >= 1000) { // ~60 FPS
|
||||||
XVideoFrame frame;
|
XVideoFrame frame;
|
||||||
frame.data = (const char*)data;
|
frame.data = (const char*)data;
|
||||||
frame.size = size;
|
frame.size = size;
|
||||||
@@ -474,25 +428,71 @@ int Render::StopKeyboardCapturer() {
|
|||||||
|
|
||||||
int Render::CreateConnectionPeer() {
|
int Render::CreateConnectionPeer() {
|
||||||
params_.use_cfg_file = false;
|
params_.use_cfg_file = false;
|
||||||
params_.signal_server_ip = "api.crossdesk.cn";
|
|
||||||
params_.signal_server_port = 9099;
|
std::string signal_server_ip;
|
||||||
params_.stun_server_ip = "150.158.81.30";
|
int signal_server_port;
|
||||||
params_.stun_server_port = 3478;
|
int coturn_server_port;
|
||||||
params_.turn_server_ip = "150.158.81.30";
|
std::string tls_cert_path;
|
||||||
params_.turn_server_port = 3478;
|
|
||||||
params_.turn_server_username = "dijunkun";
|
if (config_center_->IsSelfHosted()) {
|
||||||
params_.turn_server_password = "dijunkunpw";
|
signal_server_ip = config_center_->GetSignalServerHost();
|
||||||
params_.tls_cert_path = std::filesystem::exists(cert_path_)
|
signal_server_port = config_center_->GetSignalServerPort();
|
||||||
? cert_path_.c_str()
|
coturn_server_port = config_center_->GetCoturnServerPort();
|
||||||
: "certs/crossdesk.cn_root.crt";
|
tls_cert_path = config_center_->GetCertFilePath();
|
||||||
params_.log_path = dll_log_path_.c_str();
|
} else {
|
||||||
params_.hardware_acceleration = config_center_.IsHardwareVideoCodec();
|
signal_server_ip = config_center_->GetDefaultServerHost();
|
||||||
params_.av1_encoding = config_center_.GetVideoEncodeFormat() ==
|
signal_server_port = config_center_->GetDefaultSignalServerPort();
|
||||||
|
coturn_server_port = config_center_->GetDefaultCoturnServerPort();
|
||||||
|
tls_cert_path = config_center_->GetDefaultCertFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// self hosted server config
|
||||||
|
strncpy(signal_server_ip_self_, config_center_->GetSignalServerHost().c_str(),
|
||||||
|
sizeof(signal_server_ip_self_) - 1);
|
||||||
|
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
||||||
|
strncpy(signal_server_port_self_,
|
||||||
|
std::to_string(config_center_->GetSignalServerPort()).c_str(),
|
||||||
|
sizeof(signal_server_port_self_) - 1);
|
||||||
|
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
||||||
|
strncpy(coturn_server_port_self_,
|
||||||
|
std::to_string(config_center_->GetCoturnServerPort()).c_str(),
|
||||||
|
sizeof(coturn_server_port_self_) - 1);
|
||||||
|
coturn_server_port_self_[sizeof(coturn_server_port_self_) - 1] = '\0';
|
||||||
|
tls_cert_path_self_ = config_center_->GetCertFilePath();
|
||||||
|
|
||||||
|
// peer config
|
||||||
|
strncpy((char*)params_.signal_server_ip, signal_server_ip.c_str(),
|
||||||
|
sizeof(params_.signal_server_ip) - 1);
|
||||||
|
params_.signal_server_ip[sizeof(params_.signal_server_ip) - 1] = '\0';
|
||||||
|
params_.signal_server_port = signal_server_port;
|
||||||
|
strncpy((char*)params_.stun_server_ip, signal_server_ip.c_str(),
|
||||||
|
sizeof(params_.stun_server_ip) - 1);
|
||||||
|
params_.stun_server_ip[sizeof(params_.stun_server_ip) - 1] = '\0';
|
||||||
|
params_.stun_server_port = coturn_server_port;
|
||||||
|
strncpy((char*)params_.turn_server_ip, signal_server_ip.c_str(),
|
||||||
|
sizeof(params_.turn_server_ip) - 1);
|
||||||
|
params_.turn_server_ip[sizeof(params_.turn_server_ip) - 1] = '\0';
|
||||||
|
params_.turn_server_port = coturn_server_port;
|
||||||
|
strncpy((char*)params_.turn_server_username, "crossdesk",
|
||||||
|
sizeof(params_.turn_server_username) - 1);
|
||||||
|
params_.turn_server_username[sizeof(params_.turn_server_username) - 1] = '\0';
|
||||||
|
strncpy((char*)params_.turn_server_password, "crossdeskpw",
|
||||||
|
sizeof(params_.turn_server_password) - 1);
|
||||||
|
params_.turn_server_password[sizeof(params_.turn_server_password) - 1] = '\0';
|
||||||
|
strncpy(params_.tls_cert_path, tls_cert_path.c_str(),
|
||||||
|
sizeof(params_.tls_cert_path) - 1);
|
||||||
|
params_.tls_cert_path[sizeof(params_.tls_cert_path) - 1] = '\0';
|
||||||
|
|
||||||
|
strncpy(params_.log_path, dll_log_path_.c_str(),
|
||||||
|
sizeof(params_.log_path) - 1);
|
||||||
|
params_.log_path[sizeof(params_.log_path) - 1] = '\0';
|
||||||
|
params_.hardware_acceleration = config_center_->IsHardwareVideoCodec();
|
||||||
|
params_.av1_encoding = config_center_->GetVideoEncodeFormat() ==
|
||||||
ConfigCenter::VIDEO_ENCODE_FORMAT::AV1
|
ConfigCenter::VIDEO_ENCODE_FORMAT::AV1
|
||||||
? true
|
? true
|
||||||
: false;
|
: false;
|
||||||
params_.enable_turn = config_center_.IsEnableTurn();
|
params_.enable_turn = config_center_->IsEnableTurn();
|
||||||
params_.enable_srtp = config_center_.IsEnableSrtp();
|
params_.enable_srtp = config_center_->IsEnableSrtp();
|
||||||
params_.on_receive_video_buffer = nullptr;
|
params_.on_receive_video_buffer = nullptr;
|
||||||
params_.on_receive_audio_buffer = OnReceiveAudioBufferCb;
|
params_.on_receive_audio_buffer = OnReceiveAudioBufferCb;
|
||||||
params_.on_receive_data_buffer = OnReceiveDataBufferCb;
|
params_.on_receive_data_buffer = OnReceiveDataBufferCb;
|
||||||
@@ -608,6 +608,17 @@ int Render::CreateMainWindow() {
|
|||||||
// for window region action
|
// for window region action
|
||||||
SDL_SetWindowHitTest(main_window_, HitTestCallback, this);
|
SDL_SetWindowHitTest(main_window_, HitTestCallback, this);
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
SDL_PropertiesID props = SDL_GetWindowProperties(main_window_);
|
||||||
|
HWND main_hwnd = (HWND)SDL_GetPointerProperty(
|
||||||
|
props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
|
||||||
|
|
||||||
|
HICON tray_icon = (HICON)LoadImageW(NULL, L"crossdesk.ico", IMAGE_ICON, 0, 0,
|
||||||
|
LR_LOADFROMFILE | LR_DEFAULTSIZE);
|
||||||
|
tray_ = std::make_unique<WinTray>(main_hwnd, tray_icon, L"CrossDesk",
|
||||||
|
localization_language_index_);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -890,6 +901,21 @@ int Render::Run() {
|
|||||||
exec_log_path_ = path_manager_->GetLogPath().string();
|
exec_log_path_ = path_manager_->GetLogPath().string();
|
||||||
dll_log_path_ = path_manager_->GetLogPath().string();
|
dll_log_path_ = path_manager_->GetLogPath().string();
|
||||||
cache_path_ = path_manager_->GetCachePath().string();
|
cache_path_ = path_manager_->GetCachePath().string();
|
||||||
|
config_center_ =
|
||||||
|
std::make_unique<ConfigCenter>(cache_path_ + "/config.ini", cert_path_);
|
||||||
|
strncpy(signal_server_ip_self_,
|
||||||
|
config_center_->GetSignalServerHost().c_str(),
|
||||||
|
sizeof(signal_server_ip_self_) - 1);
|
||||||
|
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
||||||
|
strncpy(signal_server_port_self_,
|
||||||
|
std::to_string(config_center_->GetSignalServerPort()).c_str(),
|
||||||
|
sizeof(signal_server_port_self_) - 1);
|
||||||
|
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
||||||
|
strncpy(cert_file_path_, cert_path_.c_str(), sizeof(cert_file_path_) - 1);
|
||||||
|
cert_file_path_[sizeof(cert_file_path_) - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
std::cerr << "Failed to create PathManager" << std::endl;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeLogger();
|
InitializeLogger();
|
||||||
@@ -974,6 +1000,14 @@ void Render::MainLoop() {
|
|||||||
ProcessSdlEvent(event);
|
ProcessSdlEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
MSG msg;
|
||||||
|
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
UpdateLabels();
|
UpdateLabels();
|
||||||
HandleRecentConnections();
|
HandleRecentConnections();
|
||||||
HandleStreamWindow();
|
HandleStreamWindow();
|
||||||
@@ -1399,4 +1433,5 @@ void Render::ProcessSdlEvent(const SDL_Event& event) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -29,7 +29,11 @@
|
|||||||
#include "screen_capturer_factory.h"
|
#include "screen_capturer_factory.h"
|
||||||
#include "speaker_capturer_factory.h"
|
#include "speaker_capturer_factory.h"
|
||||||
#include "thumbnail.h"
|
#include "thumbnail.h"
|
||||||
|
#if _WIN32
|
||||||
|
#include "win_tray.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
class Render {
|
class Render {
|
||||||
public:
|
public:
|
||||||
struct SubStreamWindowProperties {
|
struct SubStreamWindowProperties {
|
||||||
@@ -152,6 +156,8 @@ class Render {
|
|||||||
int RemoteWindow();
|
int RemoteWindow();
|
||||||
int RecentConnectionsWindow();
|
int RecentConnectionsWindow();
|
||||||
int SettingWindow();
|
int SettingWindow();
|
||||||
|
int SelfHostedServerWindow();
|
||||||
|
int ShowSimpleFileBrowser();
|
||||||
int ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props);
|
int ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props);
|
||||||
int ControlBar(std::shared_ptr<SubStreamWindowProperties>& props);
|
int ControlBar(std::shared_ptr<SubStreamWindowProperties>& props);
|
||||||
int AboutWindow();
|
int AboutWindow();
|
||||||
@@ -261,7 +267,7 @@ class Render {
|
|||||||
private:
|
private:
|
||||||
CDCache cd_cache_;
|
CDCache cd_cache_;
|
||||||
std::mutex cd_cache_mutex_;
|
std::mutex cd_cache_mutex_;
|
||||||
ConfigCenter config_center_;
|
std::unique_ptr<ConfigCenter> config_center_;
|
||||||
ConfigCenter::LANGUAGE localization_language_ =
|
ConfigCenter::LANGUAGE localization_language_ =
|
||||||
ConfigCenter::LANGUAGE::CHINESE;
|
ConfigCenter::LANGUAGE::CHINESE;
|
||||||
std::unique_ptr<PathManager> path_manager_;
|
std::unique_ptr<PathManager> path_manager_;
|
||||||
@@ -296,6 +302,9 @@ class Render {
|
|||||||
ImGuiContext* main_ctx_ = nullptr;
|
ImGuiContext* main_ctx_ = nullptr;
|
||||||
bool exit_ = false;
|
bool exit_ = false;
|
||||||
const int sdl_refresh_ms_ = 16; // ~60 FPS
|
const int sdl_refresh_ms_ = 16; // ~60 FPS
|
||||||
|
#if _WIN32
|
||||||
|
std::unique_ptr<WinTray> tray_;
|
||||||
|
#endif
|
||||||
|
|
||||||
// main window properties
|
// main window properties
|
||||||
bool start_mouse_controller_ = false;
|
bool start_mouse_controller_ = false;
|
||||||
@@ -333,8 +342,8 @@ class Render {
|
|||||||
float connection_status_window_height_ = 150;
|
float connection_status_window_height_ = 150;
|
||||||
float notification_window_width_ = 200;
|
float notification_window_width_ = 200;
|
||||||
float notification_window_height_ = 80;
|
float notification_window_height_ = 80;
|
||||||
float about_window_width_ = 200;
|
float about_window_width_ = 300;
|
||||||
float about_window_height_ = 150;
|
float about_window_height_ = 170;
|
||||||
int screen_width_ = 1280;
|
int screen_width_ = 1280;
|
||||||
int screen_height_ = 720;
|
int screen_height_ = 720;
|
||||||
int selected_display_ = 0;
|
int selected_display_ = 0;
|
||||||
@@ -383,6 +392,7 @@ class Render {
|
|||||||
bool password_validating_ = false;
|
bool password_validating_ = false;
|
||||||
uint32_t password_validating_time_ = 0;
|
uint32_t password_validating_time_ = 0;
|
||||||
bool show_settings_window_ = false;
|
bool show_settings_window_ = false;
|
||||||
|
bool show_self_hosted_server_config_window_ = false;
|
||||||
bool rejoin_ = false;
|
bool rejoin_ = false;
|
||||||
bool local_id_copied_ = false;
|
bool local_id_copied_ = false;
|
||||||
bool show_password_ = true;
|
bool show_password_ = true;
|
||||||
@@ -431,13 +441,27 @@ class Render {
|
|||||||
bool enable_hardware_video_codec_ = false;
|
bool enable_hardware_video_codec_ = false;
|
||||||
bool enable_turn_ = false;
|
bool enable_turn_ = false;
|
||||||
bool enable_srtp_ = false;
|
bool enable_srtp_ = false;
|
||||||
|
char signal_server_ip_[256] = "api.crossdesk.cn";
|
||||||
|
char signal_server_port_[6] = "9099";
|
||||||
|
char coturn_server_port_[6] = "3478";
|
||||||
|
char cert_file_path_[256] = "";
|
||||||
|
bool enable_self_hosted_server_ = false;
|
||||||
int language_button_value_last_ = 0;
|
int language_button_value_last_ = 0;
|
||||||
int video_quality_button_value_last_ = 0;
|
int video_quality_button_value_last_ = 0;
|
||||||
int video_encode_format_button_value_last_ = 0;
|
int video_encode_format_button_value_last_ = 0;
|
||||||
bool enable_hardware_video_codec_last_ = false;
|
bool enable_hardware_video_codec_last_ = false;
|
||||||
bool enable_turn_last_ = false;
|
bool enable_turn_last_ = false;
|
||||||
bool enable_srtp_last_ = false;
|
bool enable_srtp_last_ = false;
|
||||||
|
bool enable_minimize_to_tray_ = false;
|
||||||
|
bool enable_minimize_to_tray_last_ = false;
|
||||||
|
char signal_server_ip_self_[256] = "";
|
||||||
|
char signal_server_port_self_[6] = "";
|
||||||
|
char coturn_server_port_self_[6] = "";
|
||||||
|
std::string tls_cert_path_self_ = "";
|
||||||
bool settings_window_pos_reset_ = true;
|
bool settings_window_pos_reset_ = true;
|
||||||
|
bool self_hosted_server_config_window_pos_reset_ = true;
|
||||||
|
std::string selected_current_file_path_ = "";
|
||||||
|
bool show_file_browser_ = true;
|
||||||
/* ------ main window property end ------ */
|
/* ------ main window property end ------ */
|
||||||
|
|
||||||
/* ------ sub stream window property start ------ */
|
/* ------ sub stream window property start ------ */
|
||||||
@@ -446,5 +470,5 @@ class Render {
|
|||||||
void CloseTab(decltype(client_properties_)::iterator& it);
|
void CloseTab(decltype(client_properties_)::iterator& it);
|
||||||
/* ------ stream window property end ------ */
|
/* ------ stream window property end ------ */
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
#define MOUSE_CONTROL 1
|
#define MOUSE_CONTROL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::SendKeyCommand(int key_code, bool is_down) {
|
int Render::SendKeyCommand(int key_code, bool is_down) {
|
||||||
RemoteAction remote_action;
|
RemoteAction remote_action;
|
||||||
remote_action.type = ControlType::keyboard;
|
remote_action.type = ControlType::keyboard;
|
||||||
@@ -542,4 +544,5 @@ void Render::NetStatusReport(const char* client_id, size_t client_id_size,
|
|||||||
if (!(render->peer_reserved_ && !strstr(client_id, "C-"))) {
|
if (!(render->peer_reserved_ && !strstr(client_id, "C-"))) {
|
||||||
props->net_traffic_stats_ = *net_traffic_stats;
|
props->net_traffic_stats_ = *net_traffic_stats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
#include "layout_style.h"
|
#include "layout.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
int CountDigits(int number) {
|
int CountDigits(int number) {
|
||||||
if (number == 0) return 1;
|
if (number == 0) return 1;
|
||||||
return (int)std::floor(std::log10(std::abs(number))) + 1;
|
return (int)std::floor(std::log10(std::abs(number))) + 1;
|
||||||
@@ -324,3 +326,4 @@ int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::StatusBar() {
|
int Render::StatusBar() {
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
static bool a, b, c, d, e;
|
static bool a, b, c, d, e;
|
||||||
@@ -35,4 +37,5 @@ int Render::StatusBar() {
|
|||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#define BUTTON_PADDING 36.0f
|
#define BUTTON_PADDING 36.0f
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::TitleBar(bool main_window) {
|
int Render::TitleBar(bool main_window) {
|
||||||
ImGui::PushStyleColor(ImGuiCol_MenuBarBg, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
|
ImGui::PushStyleColor(ImGuiCol_MenuBarBg, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
@@ -57,6 +59,7 @@ int Render::TitleBar(bool main_window) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
SettingWindow();
|
SettingWindow();
|
||||||
|
SelfHostedServerWindow();
|
||||||
AboutWindow();
|
AboutWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,9 +141,17 @@ int Render::TitleBar(bool main_window) {
|
|||||||
float xmark_size = 12.0f;
|
float xmark_size = 12.0f;
|
||||||
std::string close_button = "##xmark"; // ICON_FA_XMARK;
|
std::string close_button = "##xmark"; // ICON_FA_XMARK;
|
||||||
if (ImGui::Button(close_button.c_str(), ImVec2(BUTTON_PADDING, 30))) {
|
if (ImGui::Button(close_button.c_str(), ImVec2(BUTTON_PADDING, 30))) {
|
||||||
SDL_Event event;
|
#if _WIN32
|
||||||
event.type = SDL_EVENT_QUIT;
|
if (enable_minimize_to_tray_) {
|
||||||
SDL_PushEvent(&event);
|
tray_->MinimizeToTray();
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
SDL_Event event;
|
||||||
|
event.type = SDL_EVENT_QUIT;
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
#if _WIN32
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
draw_list->AddLine(ImVec2(xmark_pos_x - xmark_size / 2 - 0.25f,
|
draw_list->AddLine(ImVec2(xmark_pos_x - xmark_size / 2 - 0.25f,
|
||||||
xmark_pos_y - xmark_size / 2 + 0.75f),
|
xmark_pos_y - xmark_size / 2 + 0.75f),
|
||||||
@@ -162,4 +173,5 @@ int Render::TitleBar(bool main_window) {
|
|||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
115
src/gui/tray/win_tray.cpp
Normal file
115
src/gui/tray/win_tray.cpp
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#include "win_tray.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include "localization.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
|
// callback for the message-only window that handles tray icon messages
|
||||||
|
static LRESULT CALLBACK MsgWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
|
LPARAM lParam) {
|
||||||
|
WinTray* tray =
|
||||||
|
reinterpret_cast<WinTray*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||||
|
if (!tray) {
|
||||||
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg == WM_TRAY_CALLBACK) {
|
||||||
|
MSG tmpMsg = {};
|
||||||
|
tmpMsg.message = msg;
|
||||||
|
tmpMsg.wParam = wParam;
|
||||||
|
tmpMsg.lParam = lParam;
|
||||||
|
tray->HandleTrayMessage(&tmpMsg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
WinTray::WinTray(HWND app_hwnd, HICON icon, const std::wstring& tooltip,
|
||||||
|
int language_index)
|
||||||
|
: app_hwnd_(app_hwnd),
|
||||||
|
icon_(icon),
|
||||||
|
tip_(tooltip),
|
||||||
|
hwnd_message_only_(nullptr),
|
||||||
|
language_index_(language_index) {
|
||||||
|
WNDCLASS wc = {};
|
||||||
|
wc.lpfnWndProc = MsgWndProc;
|
||||||
|
wc.hInstance = GetModuleHandle(nullptr);
|
||||||
|
wc.lpszClassName = L"TrayMessageWindow";
|
||||||
|
RegisterClass(&wc);
|
||||||
|
|
||||||
|
// create a message-only window to receive tray messages
|
||||||
|
hwnd_message_only_ =
|
||||||
|
CreateWindowEx(0, wc.lpszClassName, L"TrayMsg", 0, 0, 0, 0, 0,
|
||||||
|
HWND_MESSAGE, nullptr, wc.hInstance, nullptr);
|
||||||
|
|
||||||
|
// store pointer to this WinTray instance in window data
|
||||||
|
SetWindowLongPtr(hwnd_message_only_, GWLP_USERDATA,
|
||||||
|
reinterpret_cast<LONG_PTR>(this));
|
||||||
|
|
||||||
|
// initialize NOTIFYICONDATA structure
|
||||||
|
ZeroMemory(&nid_, sizeof(nid_));
|
||||||
|
nid_.cbSize = sizeof(nid_);
|
||||||
|
nid_.hWnd = hwnd_message_only_;
|
||||||
|
nid_.uID = 1;
|
||||||
|
nid_.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
|
||||||
|
nid_.uCallbackMessage = WM_TRAY_CALLBACK;
|
||||||
|
nid_.hIcon = icon_;
|
||||||
|
wcsncpy_s(nid_.szTip, tip_.c_str(), _TRUNCATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
WinTray::~WinTray() {
|
||||||
|
RemoveTrayIcon();
|
||||||
|
if (hwnd_message_only_) DestroyWindow(hwnd_message_only_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinTray::MinimizeToTray() {
|
||||||
|
Shell_NotifyIcon(NIM_ADD, &nid_);
|
||||||
|
// hide application window
|
||||||
|
ShowWindow(app_hwnd_, SW_HIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinTray::RemoveTrayIcon() { Shell_NotifyIcon(NIM_DELETE, &nid_); }
|
||||||
|
|
||||||
|
bool WinTray::HandleTrayMessage(MSG* msg) {
|
||||||
|
if (!msg || msg->message != WM_TRAY_CALLBACK) return false;
|
||||||
|
|
||||||
|
switch (LOWORD(msg->lParam)) {
|
||||||
|
case WM_LBUTTONDBLCLK:
|
||||||
|
case WM_LBUTTONUP: {
|
||||||
|
ShowWindow(app_hwnd_, SW_SHOW);
|
||||||
|
SetForegroundWindow(app_hwnd_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_RBUTTONUP: {
|
||||||
|
POINT pt;
|
||||||
|
GetCursorPos(&pt);
|
||||||
|
HMENU menu = CreatePopupMenu();
|
||||||
|
AppendMenuW(menu, MF_STRING, 1001,
|
||||||
|
localization::exit_program[language_index_]);
|
||||||
|
|
||||||
|
SetForegroundWindow(hwnd_message_only_);
|
||||||
|
int cmd =
|
||||||
|
TrackPopupMenu(menu, TPM_RETURNCMD | TPM_NONOTIFY | TPM_LEFTALIGN,
|
||||||
|
pt.x, pt.y, 0, hwnd_message_only_, nullptr);
|
||||||
|
DestroyMenu(menu);
|
||||||
|
|
||||||
|
// handle menu command
|
||||||
|
if (cmd == 1001) {
|
||||||
|
// exit application
|
||||||
|
SDL_Event event;
|
||||||
|
event.type = SDL_EVENT_QUIT;
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
} else if (cmd == 1002) {
|
||||||
|
ShowWindow(app_hwnd_, SW_SHOW); // show main window
|
||||||
|
SetForegroundWindow(app_hwnd_);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
38
src/gui/tray/win_tray.h
Normal file
38
src/gui/tray/win_tray.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* @Author: DI JUNKUN
|
||||||
|
* @Date: 2025-10-22
|
||||||
|
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WIN_TRAY_H_
|
||||||
|
#define _WIN_TRAY_H_
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#define WM_TRAY_CALLBACK (WM_USER + 1)
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
|
class WinTray {
|
||||||
|
public:
|
||||||
|
WinTray(HWND app_hwnd, HICON icon, const std::wstring& tooltip,
|
||||||
|
int language_index);
|
||||||
|
~WinTray();
|
||||||
|
|
||||||
|
void MinimizeToTray();
|
||||||
|
void RemoveTrayIcon();
|
||||||
|
bool HandleTrayMessage(MSG* msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
HWND app_hwnd_;
|
||||||
|
HWND hwnd_message_only_;
|
||||||
|
HICON icon_;
|
||||||
|
std::wstring tip_;
|
||||||
|
int language_index_;
|
||||||
|
NOTIFYICONDATA nid_;
|
||||||
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
|
#endif
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
#include "layout_style.h"
|
#include "layout.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::AboutWindow() {
|
int Render::AboutWindow() {
|
||||||
if (show_about_window_) {
|
if (show_about_window_) {
|
||||||
const ImGuiViewport *viewport = ImGui::GetMainViewport();
|
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(ImVec2(
|
ImGui::SetNextWindowPos(ImVec2(
|
||||||
(viewport->WorkSize.x - viewport->WorkPos.x - about_window_width_) / 2,
|
(viewport->WorkSize.x - viewport->WorkPos.x - about_window_width_) / 2,
|
||||||
@@ -27,15 +29,21 @@ int Render::AboutWindow() {
|
|||||||
ImGui::SetWindowFontScale(0.5f);
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
|
|
||||||
std::string version;
|
std::string version;
|
||||||
#ifdef RD_VERSION
|
#ifdef CROSSDESK_VERSION
|
||||||
version = RD_VERSION;
|
version = CROSSDESK_VERSION;
|
||||||
#else
|
#else
|
||||||
version = "Unknown";
|
version = "Unknown";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string text =
|
std::string text = localization::version[localization_language_index_] +
|
||||||
localization::version[localization_language_index_] + ": " + version;
|
": CrossDesk v" + version;
|
||||||
ImGui::Text("%s", text.c_str());
|
ImGui::Text("%s", text.c_str());
|
||||||
|
ImGui::Text("");
|
||||||
|
|
||||||
|
std::string copyright_text = "© 2025 by JUNKUN DI. All rights reserved.";
|
||||||
|
std::string license_text = "Licensed under GNU LGPL v3.";
|
||||||
|
ImGui::Text("%s", copyright_text.c_str());
|
||||||
|
ImGui::Text("%s", license_text.c_str());
|
||||||
|
|
||||||
ImGui::SetCursorPosX(about_window_width_ * 0.42f);
|
ImGui::SetCursorPosX(about_window_width_ * 0.42f);
|
||||||
ImGui::SetCursorPosY(about_window_height_ * 0.75f);
|
ImGui::SetCursorPosY(about_window_height_ * 0.75f);
|
||||||
@@ -52,4 +60,5 @@ int Render::AboutWindow() {
|
|||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
#include "layout_style.h"
|
#include "layout.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
bool Render::ConnectionStatusWindow(
|
bool Render::ConnectionStatusWindow(
|
||||||
std::shared_ptr<SubStreamWindowProperties> &props) {
|
std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||||
const ImGuiViewport *viewport = ImGui::GetMainViewport();
|
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||||
bool ret_flag = false;
|
bool ret_flag = false;
|
||||||
ImGui::SetNextWindowPos(ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
ImGui::SetNextWindowPos(ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
||||||
connection_status_window_width_) /
|
connection_status_window_width_) /
|
||||||
@@ -168,4 +170,5 @@ bool Render::ConnectionStatusWindow(
|
|||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
return ret_flag;
|
return ret_flag;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties> &props) {
|
namespace crossdesk {
|
||||||
|
|
||||||
|
int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||||
double time_duration =
|
double time_duration =
|
||||||
ImGui::GetTime() - props->control_bar_button_pressed_time_;
|
ImGui::GetTime() - props->control_bar_button_pressed_time_;
|
||||||
if (props->control_window_width_is_changing_) {
|
if (props->control_window_width_is_changing_) {
|
||||||
@@ -220,4 +222,5 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties> &props) {
|
|||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
#include "layout_style.h"
|
#include "layout.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::SettingWindow() {
|
int Render::SettingWindow() {
|
||||||
if (show_settings_window_) {
|
if (show_settings_window_) {
|
||||||
if (settings_window_pos_reset_) {
|
if (settings_window_pos_reset_) {
|
||||||
@@ -57,7 +59,7 @@ int Render::SettingWindow() {
|
|||||||
localization::language_en[localization_language_index_].c_str()};
|
localization::language_en[localization_language_index_].c_str()};
|
||||||
|
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
ImGui::SetCursorPosY(settings_items_offset + 4);
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s", localization::language[localization_language_index_].c_str());
|
"%s", localization::language[localization_language_index_].c_str());
|
||||||
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
@@ -88,7 +90,7 @@ int Render::SettingWindow() {
|
|||||||
.c_str()};
|
.c_str()};
|
||||||
|
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
ImGui::SetCursorPosY(settings_items_offset + 4);
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::video_quality[localization_language_index_].c_str());
|
localization::video_quality[localization_language_index_].c_str());
|
||||||
@@ -108,10 +110,10 @@ int Render::SettingWindow() {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
{
|
{
|
||||||
const char* video_frame_rate_items[] = {"30", "60"};
|
const char* video_frame_rate_items[] = {"30 fps", "60 fps"};
|
||||||
|
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
ImGui::SetCursorPosY(settings_items_offset + 4);
|
||||||
ImGui::Text("%s",
|
ImGui::Text("%s",
|
||||||
localization::video_frame_rate[localization_language_index_]
|
localization::video_frame_rate[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
@@ -133,11 +135,11 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
const char* video_encode_format_items[] = {
|
const char* video_encode_format_items[] = {
|
||||||
localization::av1[localization_language_index_].c_str(),
|
localization::h264[localization_language_index_].c_str(),
|
||||||
localization::h264[localization_language_index_].c_str()};
|
localization::av1[localization_language_index_].c_str()};
|
||||||
|
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
ImGui::SetCursorPosY(settings_items_offset + 4);
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::video_encode_format[localization_language_index_]
|
localization::video_encode_format[localization_language_index_]
|
||||||
@@ -160,7 +162,7 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
ImGui::SetCursorPosY(settings_items_offset + 4);
|
||||||
ImGui::Text("%s", localization::enable_hardware_video_codec
|
ImGui::Text("%s", localization::enable_hardware_video_codec
|
||||||
[localization_language_index_]
|
[localization_language_index_]
|
||||||
.c_str());
|
.c_str());
|
||||||
@@ -179,7 +181,7 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
ImGui::SetCursorPosY(settings_items_offset + 4);
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::enable_turn[localization_language_index_].c_str());
|
localization::enable_turn[localization_language_index_].c_str());
|
||||||
@@ -197,7 +199,7 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding;
|
||||||
ImGui::SetCursorPosY(settings_items_offset + 2);
|
ImGui::SetCursorPosY(settings_items_offset + 4);
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"%s",
|
"%s",
|
||||||
localization::enable_srtp[localization_language_index_].c_str());
|
localization::enable_srtp[localization_language_index_].c_str());
|
||||||
@@ -211,6 +213,48 @@ int Render::SettingWindow() {
|
|||||||
ImGui::Checkbox("##enable_srtp", &enable_srtp_);
|
ImGui::Checkbox("##enable_srtp", &enable_srtp_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
{
|
||||||
|
settings_items_offset += settings_items_padding;
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset + 1);
|
||||||
|
|
||||||
|
if (ImGui::Button(localization::self_hosted_server_config
|
||||||
|
[localization_language_index_]
|
||||||
|
.c_str())) {
|
||||||
|
show_self_hosted_server_config_window_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
|
ImGui::SetCursorPosX(ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_CN);
|
||||||
|
} else {
|
||||||
|
ImGui::SetCursorPosX(ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_EN);
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::Checkbox("##enable_self_hosted_server",
|
||||||
|
&enable_self_hosted_server_);
|
||||||
|
}
|
||||||
|
#if _WIN32
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
{
|
||||||
|
settings_items_offset += settings_items_padding;
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset + 4);
|
||||||
|
|
||||||
|
ImGui::Text("%s",
|
||||||
|
localization::minimize_to_tray[localization_language_index_]
|
||||||
|
.c_str());
|
||||||
|
|
||||||
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
|
ImGui::SetCursorPosX(ENABLE_MINIZE_TO_TRAY_PADDING_CN);
|
||||||
|
} else {
|
||||||
|
ImGui::SetCursorPosX(ENABLE_MINIZE_TO_TRAY_PADDING_EN);
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::Checkbox("##enable_minimize_to_tray_",
|
||||||
|
&enable_minimize_to_tray_);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (stream_window_inited_) {
|
if (stream_window_inited_) {
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
@@ -221,7 +265,7 @@ int Render::SettingWindow() {
|
|||||||
ImGui::SetCursorPosX(SETTINGS_OK_BUTTON_PADDING_EN);
|
ImGui::SetCursorPosX(SETTINGS_OK_BUTTON_PADDING_EN);
|
||||||
}
|
}
|
||||||
|
|
||||||
settings_items_offset += settings_items_padding;
|
settings_items_offset += settings_items_padding + 10;
|
||||||
ImGui::SetCursorPosY(settings_items_offset);
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
@@ -229,12 +273,13 @@ int Render::SettingWindow() {
|
|||||||
if (ImGui::Button(
|
if (ImGui::Button(
|
||||||
localization::ok[localization_language_index_].c_str())) {
|
localization::ok[localization_language_index_].c_str())) {
|
||||||
show_settings_window_ = false;
|
show_settings_window_ = false;
|
||||||
|
show_self_hosted_server_config_window_ = false;
|
||||||
|
|
||||||
// Language
|
// Language
|
||||||
if (language_button_value_ == 0) {
|
if (language_button_value_ == 0) {
|
||||||
config_center_.SetLanguage(ConfigCenter::LANGUAGE::CHINESE);
|
config_center_->SetLanguage(ConfigCenter::LANGUAGE::CHINESE);
|
||||||
} else {
|
} else {
|
||||||
config_center_.SetLanguage(ConfigCenter::LANGUAGE::ENGLISH);
|
config_center_->SetLanguage(ConfigCenter::LANGUAGE::ENGLISH);
|
||||||
}
|
}
|
||||||
language_button_value_last_ = language_button_value_;
|
language_button_value_last_ = language_button_value_;
|
||||||
localization_language_ = (ConfigCenter::LANGUAGE)language_button_value_;
|
localization_language_ = (ConfigCenter::LANGUAGE)language_button_value_;
|
||||||
@@ -244,50 +289,55 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
// Video quality
|
// Video quality
|
||||||
if (video_quality_button_value_ == 0) {
|
if (video_quality_button_value_ == 0) {
|
||||||
config_center_.SetVideoQuality(ConfigCenter::VIDEO_QUALITY::HIGH);
|
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::HIGH);
|
||||||
} else if (video_quality_button_value_ == 1) {
|
} else if (video_quality_button_value_ == 1) {
|
||||||
config_center_.SetVideoQuality(ConfigCenter::VIDEO_QUALITY::MEDIUM);
|
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::MEDIUM);
|
||||||
} else {
|
} else {
|
||||||
config_center_.SetVideoQuality(ConfigCenter::VIDEO_QUALITY::LOW);
|
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::LOW);
|
||||||
}
|
}
|
||||||
video_quality_button_value_last_ = video_quality_button_value_;
|
video_quality_button_value_last_ = video_quality_button_value_;
|
||||||
|
|
||||||
// Video encode format
|
// Video encode format
|
||||||
if (video_encode_format_button_value_ == 0) {
|
if (video_encode_format_button_value_ == 0) {
|
||||||
config_center_.SetVideoEncodeFormat(
|
config_center_->SetVideoEncodeFormat(
|
||||||
ConfigCenter::VIDEO_ENCODE_FORMAT::AV1);
|
|
||||||
} else if (video_encode_format_button_value_ == 1) {
|
|
||||||
config_center_.SetVideoEncodeFormat(
|
|
||||||
ConfigCenter::VIDEO_ENCODE_FORMAT::H264);
|
ConfigCenter::VIDEO_ENCODE_FORMAT::H264);
|
||||||
|
} else if (video_encode_format_button_value_ == 1) {
|
||||||
|
config_center_->SetVideoEncodeFormat(
|
||||||
|
ConfigCenter::VIDEO_ENCODE_FORMAT::AV1);
|
||||||
}
|
}
|
||||||
video_encode_format_button_value_last_ =
|
video_encode_format_button_value_last_ =
|
||||||
video_encode_format_button_value_;
|
video_encode_format_button_value_;
|
||||||
|
|
||||||
// Hardware video codec
|
// Hardware video codec
|
||||||
if (enable_hardware_video_codec_) {
|
if (enable_hardware_video_codec_) {
|
||||||
config_center_.SetHardwareVideoCodec(true);
|
config_center_->SetHardwareVideoCodec(true);
|
||||||
} else {
|
} else {
|
||||||
config_center_.SetHardwareVideoCodec(false);
|
config_center_->SetHardwareVideoCodec(false);
|
||||||
}
|
}
|
||||||
enable_hardware_video_codec_last_ = enable_hardware_video_codec_;
|
enable_hardware_video_codec_last_ = enable_hardware_video_codec_;
|
||||||
|
|
||||||
// TURN mode
|
// TURN mode
|
||||||
if (enable_turn_) {
|
if (enable_turn_) {
|
||||||
config_center_.SetTurn(true);
|
config_center_->SetTurn(true);
|
||||||
} else {
|
} else {
|
||||||
config_center_.SetTurn(false);
|
config_center_->SetTurn(false);
|
||||||
}
|
}
|
||||||
enable_turn_last_ = enable_turn_;
|
enable_turn_last_ = enable_turn_;
|
||||||
|
|
||||||
// SRTP
|
// SRTP
|
||||||
if (enable_srtp_) {
|
if (enable_srtp_) {
|
||||||
config_center_.SetSrtp(true);
|
config_center_->SetSrtp(true);
|
||||||
} else {
|
} else {
|
||||||
config_center_.SetSrtp(false);
|
config_center_->SetSrtp(false);
|
||||||
}
|
}
|
||||||
enable_srtp_last_ = enable_srtp_;
|
enable_srtp_last_ = enable_srtp_;
|
||||||
|
|
||||||
SaveSettingsIntoCacheFile();
|
if (enable_self_hosted_server_) {
|
||||||
|
config_center_->SetSelfHosted(true);
|
||||||
|
} else {
|
||||||
|
config_center_->SetSelfHosted(false);
|
||||||
|
}
|
||||||
|
|
||||||
settings_window_pos_reset_ = true;
|
settings_window_pos_reset_ = true;
|
||||||
|
|
||||||
// Recreate peer instance
|
// Recreate peer instance
|
||||||
@@ -306,6 +356,8 @@ int Render::SettingWindow() {
|
|||||||
if (ImGui::Button(
|
if (ImGui::Button(
|
||||||
localization::cancel[localization_language_index_].c_str())) {
|
localization::cancel[localization_language_index_].c_str())) {
|
||||||
show_settings_window_ = false;
|
show_settings_window_ = false;
|
||||||
|
show_self_hosted_server_config_window_ = false;
|
||||||
|
|
||||||
if (language_button_value_ != language_button_value_last_) {
|
if (language_button_value_ != language_button_value_last_) {
|
||||||
language_button_value_ = language_button_value_last_;
|
language_button_value_ = language_button_value_last_;
|
||||||
}
|
}
|
||||||
@@ -340,4 +392,5 @@ int Render::SettingWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
int Render::MainWindow() {
|
int Render::MainWindow() {
|
||||||
ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_), ImGuiCond_Always);
|
ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_), ImGuiCond_Always);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
@@ -47,3 +49,4 @@ int Render::MainWindow() {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
324
src/gui/windows/server_settings_window.cpp
Normal file
324
src/gui/windows/server_settings_window.cpp
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
#include <filesystem>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "layout.h"
|
||||||
|
#include "localization.h"
|
||||||
|
#include "rd_log.h"
|
||||||
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
|
std::vector<std::string> GetRootEntries() {
|
||||||
|
std::vector<std::string> roots;
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD mask = GetLogicalDrives();
|
||||||
|
for (char letter = 'A'; letter <= 'Z'; ++letter) {
|
||||||
|
if (mask & 1) {
|
||||||
|
roots.push_back(std::string(1, letter) + ":\\");
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
roots.push_back("/");
|
||||||
|
#endif
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Render::ShowSimpleFileBrowser() {
|
||||||
|
std::string display_text;
|
||||||
|
|
||||||
|
if (selected_current_file_path_.empty()) {
|
||||||
|
selected_current_file_path_ = std::filesystem::current_path().string();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tls_cert_path_self_.empty()) {
|
||||||
|
display_text =
|
||||||
|
std::filesystem::path(tls_cert_path_self_).filename().string();
|
||||||
|
} else if (selected_current_file_path_ != "Root") {
|
||||||
|
display_text =
|
||||||
|
std::filesystem::path(selected_current_file_path_).filename().string();
|
||||||
|
if (display_text.empty()) {
|
||||||
|
display_text = selected_current_file_path_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (display_text.empty()) {
|
||||||
|
display_text =
|
||||||
|
localization::select_a_file[localization_language_index_].c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_file_browser_) {
|
||||||
|
ImGui::PushItemFlag(ImGuiItemFlags_AutoClosePopups, false);
|
||||||
|
|
||||||
|
float fixed_width = 130.0f;
|
||||||
|
ImGui::SetNextItemWidth(fixed_width);
|
||||||
|
ImGui::SetNextWindowSizeConstraints(ImVec2(fixed_width, 0),
|
||||||
|
ImVec2(fixed_width, 100.0f));
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("##select_a_file", display_text.c_str(), 0)) {
|
||||||
|
bool file_selected = false;
|
||||||
|
|
||||||
|
auto roots = GetRootEntries();
|
||||||
|
if (selected_current_file_path_ == "Root" ||
|
||||||
|
!std::filesystem::exists(selected_current_file_path_) ||
|
||||||
|
!std::filesystem::is_directory(selected_current_file_path_)) {
|
||||||
|
for (const auto& root : roots) {
|
||||||
|
if (ImGui::Selectable(root.c_str())) {
|
||||||
|
selected_current_file_path_ = root;
|
||||||
|
tls_cert_path_self_.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::filesystem::path p(selected_current_file_path_);
|
||||||
|
|
||||||
|
if (ImGui::Selectable("..")) {
|
||||||
|
if (std::find(roots.begin(), roots.end(),
|
||||||
|
selected_current_file_path_) != roots.end()) {
|
||||||
|
selected_current_file_path_ = "Root";
|
||||||
|
} else if (p.has_parent_path()) {
|
||||||
|
selected_current_file_path_ = p.parent_path().string();
|
||||||
|
} else {
|
||||||
|
selected_current_file_path_ = "Root";
|
||||||
|
}
|
||||||
|
tls_cert_path_self_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (const auto& entry : std::filesystem::directory_iterator(
|
||||||
|
selected_current_file_path_)) {
|
||||||
|
std::string name = entry.path().filename().string();
|
||||||
|
if (entry.is_directory()) {
|
||||||
|
if (ImGui::Selectable(name.c_str())) {
|
||||||
|
selected_current_file_path_ = entry.path().string();
|
||||||
|
tls_cert_path_self_.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ImGui::Selectable(name.c_str())) {
|
||||||
|
tls_cert_path_self_ = entry.path().string();
|
||||||
|
file_selected = true;
|
||||||
|
show_file_browser_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Error: %s", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
ImGui::PopItemFlag();
|
||||||
|
} else {
|
||||||
|
show_file_browser_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Render::SelfHostedServerWindow() {
|
||||||
|
if (show_self_hosted_server_config_window_) {
|
||||||
|
if (self_hosted_server_config_window_pos_reset_) {
|
||||||
|
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||||
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
|
ImGui::SetNextWindowPos(
|
||||||
|
ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
||||||
|
SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_CN) /
|
||||||
|
2,
|
||||||
|
(viewport->WorkSize.y - viewport->WorkPos.y -
|
||||||
|
SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_CN) /
|
||||||
|
2));
|
||||||
|
|
||||||
|
ImGui::SetNextWindowSize(
|
||||||
|
ImVec2(SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_CN,
|
||||||
|
SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_CN));
|
||||||
|
} else {
|
||||||
|
ImGui::SetNextWindowPos(
|
||||||
|
ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
||||||
|
SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_EN) /
|
||||||
|
2,
|
||||||
|
(viewport->WorkSize.y - viewport->WorkPos.y -
|
||||||
|
SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_EN) /
|
||||||
|
2));
|
||||||
|
|
||||||
|
ImGui::SetNextWindowSize(
|
||||||
|
ImVec2(SELF_HOSTED_SERVER_CONFIG_WINDOW_WIDTH_EN,
|
||||||
|
SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_EN));
|
||||||
|
}
|
||||||
|
|
||||||
|
self_hosted_server_config_window_pos_reset_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
{
|
||||||
|
static int settings_items_padding = 30;
|
||||||
|
int settings_items_offset = 0;
|
||||||
|
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
||||||
|
|
||||||
|
ImGui::Begin(localization::self_hosted_server_settings
|
||||||
|
[localization_language_index_]
|
||||||
|
.c_str(),
|
||||||
|
nullptr,
|
||||||
|
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
|
||||||
|
ImGuiWindowFlags_NoSavedSettings);
|
||||||
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||||
|
{
|
||||||
|
settings_items_offset += settings_items_padding;
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset + 2);
|
||||||
|
ImGui::Text("%s", localization::self_hosted_server_address
|
||||||
|
[localization_language_index_]
|
||||||
|
.c_str());
|
||||||
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_CN);
|
||||||
|
} else {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_HOST_INPUT_BOX_PADDING_EN);
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
||||||
|
|
||||||
|
ImGui::InputText("##signal_server_ip_self_", signal_server_ip_self_,
|
||||||
|
IM_ARRAYSIZE(signal_server_ip_self_),
|
||||||
|
ImGuiInputTextFlags_AlwaysOverwrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
{
|
||||||
|
settings_items_offset += settings_items_padding;
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset + 2);
|
||||||
|
ImGui::Text(
|
||||||
|
"%s",
|
||||||
|
localization::self_hosted_server_port[localization_language_index_]
|
||||||
|
.c_str());
|
||||||
|
|
||||||
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN);
|
||||||
|
} else {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_EN);
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
||||||
|
|
||||||
|
ImGui::InputText("##signal_server_port_self_", signal_server_port_self_,
|
||||||
|
IM_ARRAYSIZE(signal_server_port_self_));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
{
|
||||||
|
settings_items_offset += settings_items_padding;
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset + 2);
|
||||||
|
ImGui::Text("%s", localization::self_hosted_server_coturn_server_port
|
||||||
|
[localization_language_index_]
|
||||||
|
.c_str());
|
||||||
|
|
||||||
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN);
|
||||||
|
} else {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_EN);
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
||||||
|
|
||||||
|
ImGui::InputText("##coturn_server_port_self_", coturn_server_port_self_,
|
||||||
|
IM_ARRAYSIZE(coturn_server_port_self_));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
{
|
||||||
|
settings_items_offset += settings_items_padding;
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset + 2);
|
||||||
|
ImGui::Text("%s", localization::self_hosted_server_certificate_path
|
||||||
|
[localization_language_index_]
|
||||||
|
.c_str());
|
||||||
|
|
||||||
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_CN);
|
||||||
|
} else {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_PORT_INPUT_BOX_PADDING_EN);
|
||||||
|
}
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
||||||
|
|
||||||
|
ShowSimpleFileBrowser();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream_window_inited_) {
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_CONFIG_OK_BUTTON_PADDING_CN);
|
||||||
|
} else {
|
||||||
|
ImGui::SetCursorPosX(SELF_HOSTED_SERVER_CONFIG_OK_BUTTON_PADDING_EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
settings_items_offset += settings_items_padding + 10;
|
||||||
|
ImGui::SetCursorPosY(settings_items_offset);
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
|
// OK
|
||||||
|
if (ImGui::Button(
|
||||||
|
localization::ok[localization_language_index_].c_str())) {
|
||||||
|
show_self_hosted_server_config_window_ = false;
|
||||||
|
|
||||||
|
config_center_->SetServerHost(signal_server_ip_self_);
|
||||||
|
config_center_->SetServerPort(atoi(signal_server_port_self_));
|
||||||
|
config_center_->SetCoturnServerPort(atoi(coturn_server_port_self_));
|
||||||
|
config_center_->SetCertFilePath(tls_cert_path_self_);
|
||||||
|
strncpy(signal_server_ip_, signal_server_ip_self_,
|
||||||
|
sizeof(signal_server_ip_) - 1);
|
||||||
|
signal_server_ip_[sizeof(signal_server_ip_) - 1] = '\0';
|
||||||
|
strncpy(signal_server_port_, signal_server_port_self_,
|
||||||
|
sizeof(signal_server_port_) - 1);
|
||||||
|
signal_server_port_[sizeof(signal_server_port_) - 1] = '\0';
|
||||||
|
strncpy(coturn_server_port_, coturn_server_port_self_,
|
||||||
|
sizeof(coturn_server_port_) - 1);
|
||||||
|
coturn_server_port_[sizeof(coturn_server_port_) - 1] = '\0';
|
||||||
|
strncpy(cert_file_path_, tls_cert_path_self_.c_str(),
|
||||||
|
sizeof(cert_file_path_) - 1);
|
||||||
|
cert_file_path_[sizeof(cert_file_path_) - 1] = '\0';
|
||||||
|
|
||||||
|
self_hosted_server_config_window_pos_reset_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
// Cancel
|
||||||
|
if (ImGui::Button(
|
||||||
|
localization::cancel[localization_language_index_].c_str())) {
|
||||||
|
show_self_hosted_server_config_window_ = false;
|
||||||
|
self_hosted_server_config_window_pos_reset_ = true;
|
||||||
|
|
||||||
|
strncpy(signal_server_ip_self_, signal_server_ip_,
|
||||||
|
sizeof(signal_server_ip_self_) - 1);
|
||||||
|
signal_server_ip_self_[sizeof(signal_server_ip_self_) - 1] = '\0';
|
||||||
|
strncpy(signal_server_port_self_, signal_server_port_,
|
||||||
|
sizeof(signal_server_port_self_) - 1);
|
||||||
|
signal_server_port_self_[sizeof(signal_server_port_self_) - 1] = '\0';
|
||||||
|
config_center_->SetServerHost(signal_server_ip_self_);
|
||||||
|
config_center_->SetServerPort(atoi(signal_server_port_self_));
|
||||||
|
tls_cert_path_self_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
ImGui::SetWindowFontScale(0.5f);
|
||||||
|
ImGui::End();
|
||||||
|
ImGui::PopStyleVar(2);
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::SetWindowFontScale(1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
void Render::DrawConnectionStatusText(
|
void Render::DrawConnectionStatusText(
|
||||||
std::shared_ptr<SubStreamWindowProperties>& props) {
|
std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||||
std::string text;
|
std::string text;
|
||||||
@@ -199,4 +201,5 @@ int Render::StreamWindow() {
|
|||||||
ImGui::End(); // End VideoBg
|
ImGui::End(); // End VideoBg
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::string g_log_dir = "logs";
|
std::string g_log_dir = "logs";
|
||||||
@@ -60,3 +62,4 @@ std::shared_ptr<spdlog::logger> get_logger() {
|
|||||||
|
|
||||||
return g_logger;
|
return g_logger;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
|
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
constexpr auto LOGGER_NAME = "crossdesk";
|
constexpr auto LOGGER_NAME = "crossdesk";
|
||||||
|
|
||||||
void InitLogger(const std::string& log_dir);
|
void InitLogger(const std::string& log_dir);
|
||||||
@@ -35,5 +37,5 @@ std::shared_ptr<spdlog::logger> get_logger();
|
|||||||
#define LOG_WARN(...) SPDLOG_LOGGER_WARN(get_logger(), __VA_ARGS__)
|
#define LOG_WARN(...) SPDLOG_LOGGER_WARN(get_logger(), __VA_ARGS__)
|
||||||
#define LOG_ERROR(...) SPDLOG_LOGGER_ERROR(get_logger(), __VA_ARGS__)
|
#define LOG_ERROR(...) SPDLOG_LOGGER_ERROR(get_logger(), __VA_ARGS__)
|
||||||
#define LOG_FATAL(...) SPDLOG_LOGGER_CRITICAL(get_logger(), __VA_ARGS__)
|
#define LOG_FATAL(...) SPDLOG_LOGGER_CRITICAL(get_logger(), __VA_ARGS__)
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
PathManager::PathManager(const std::string& app_name) : app_name_(app_name) {}
|
PathManager::PathManager(const std::string& app_name) : app_name_(app_name) {}
|
||||||
|
|
||||||
std::filesystem::path PathManager::GetConfigPath() {
|
std::filesystem::path PathManager::GetConfigPath() {
|
||||||
@@ -89,3 +91,4 @@ std::filesystem::path PathManager::GetEnvOrDefault(const char* env_var,
|
|||||||
|
|
||||||
return std::filesystem::path(def);
|
return std::filesystem::path(def);
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class PathManager {
|
class PathManager {
|
||||||
public:
|
public:
|
||||||
explicit PathManager(const std::string& app_name);
|
explicit PathManager(const std::string& app_name);
|
||||||
@@ -40,5 +42,5 @@ class PathManager {
|
|||||||
private:
|
private:
|
||||||
std::string app_name_;
|
std::string app_name_;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
#include "libyuv.h"
|
#include "libyuv.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
ScreenCapturerX11::ScreenCapturerX11() {}
|
ScreenCapturerX11::ScreenCapturerX11() {}
|
||||||
|
|
||||||
ScreenCapturerX11::~ScreenCapturerX11() { Destroy(); }
|
ScreenCapturerX11::~ScreenCapturerX11() { Destroy(); }
|
||||||
@@ -171,4 +173,5 @@ void ScreenCapturerX11::OnFrame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
XDestroyImage(image);
|
XDestroyImage(image);
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include "screen_capturer.h"
|
#include "screen_capturer.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class ScreenCapturerX11 : public ScreenCapturer {
|
class ScreenCapturerX11 : public ScreenCapturer {
|
||||||
public:
|
public:
|
||||||
ScreenCapturerX11();
|
ScreenCapturerX11();
|
||||||
@@ -60,5 +62,5 @@ class ScreenCapturerX11 : public ScreenCapturer {
|
|||||||
std::vector<uint8_t> y_plane_;
|
std::vector<uint8_t> y_plane_;
|
||||||
std::vector<uint8_t> uv_plane_;
|
std::vector<uint8_t> uv_plane_;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
ScreenCapturerSck::ScreenCapturerSck() {}
|
ScreenCapturerSck::ScreenCapturerSck() {}
|
||||||
ScreenCapturerSck::~ScreenCapturerSck() {}
|
ScreenCapturerSck::~ScreenCapturerSck() {}
|
||||||
|
|
||||||
@@ -70,4 +72,5 @@ std::vector<DisplayInfo> ScreenCapturerSck::GetDisplayInfoList() {
|
|||||||
|
|
||||||
void ScreenCapturerSck::OnFrame() {}
|
void ScreenCapturerSck::OnFrame() {}
|
||||||
|
|
||||||
void ScreenCapturerSck::CleanUp() {}
|
void ScreenCapturerSck::CleanUp() {}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#include "screen_capturer.h"
|
#include "screen_capturer.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class ScreenCapturerSck : public ScreenCapturer {
|
class ScreenCapturerSck : public ScreenCapturer {
|
||||||
public:
|
public:
|
||||||
ScreenCapturerSck();
|
ScreenCapturerSck();
|
||||||
@@ -55,5 +57,5 @@ class ScreenCapturerSck : public ScreenCapturer {
|
|||||||
private:
|
private:
|
||||||
std::unique_ptr<ScreenCapturer> screen_capturer_sck_impl_;
|
std::unique_ptr<ScreenCapturer> screen_capturer_sck_impl_;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -22,9 +22,12 @@
|
|||||||
#include "display_info.h"
|
#include "display_info.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
static const int kFullDesktopScreenId = -1;
|
using namespace crossdesk;
|
||||||
|
|
||||||
class ScreenCapturerSckImpl;
|
class ScreenCapturerSckImpl;
|
||||||
|
|
||||||
|
static const int kFullDesktopScreenId = -1;
|
||||||
|
|
||||||
// The ScreenCaptureKit API was available in macOS 12.3, but full-screen capture
|
// The ScreenCaptureKit API was available in macOS 12.3, but full-screen capture
|
||||||
// was reported to be broken before macOS 13 - see http://crbug.com/40234870.
|
// was reported to be broken before macOS 13 - see http://crbug.com/40234870.
|
||||||
// Also, the `SCContentFilter` fields `contentRect` and `pointPixelScale` were
|
// Also, the `SCContentFilter` fields `contentRect` and `pointPixelScale` were
|
||||||
@@ -424,10 +427,6 @@ void ScreenCapturerSckImpl::StartOrReconfigureCapturer() {
|
|||||||
[SCShareableContent getShareableContentWithCompletionHandler:handler];
|
[SCShareableContent getShareableContentWithCompletionHandler:handler];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
|
||||||
return std::make_unique<ScreenCapturerSckImpl>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@implementation SckHelper {
|
@implementation SckHelper {
|
||||||
// This lock is to prevent the capturer being destroyed while an instance
|
// This lock is to prevent the capturer being destroyed while an instance
|
||||||
// method is still running on another thread.
|
// method is still running on another thread.
|
||||||
@@ -485,4 +484,8 @@ std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
|||||||
_capturer = nullptr;
|
_capturer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
||||||
|
return std::make_unique<ScreenCapturerSckImpl>();
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "display_info.h"
|
#include "display_info.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class ScreenCapturer {
|
class ScreenCapturer {
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(unsigned char*, int, int, int, const char*)>
|
typedef std::function<void(unsigned char*, int, int, int, const char*)>
|
||||||
@@ -30,5 +32,5 @@ class ScreenCapturer {
|
|||||||
virtual std::vector<DisplayInfo> GetDisplayInfoList() = 0;
|
virtual std::vector<DisplayInfo> GetDisplayInfoList() = 0;
|
||||||
virtual int SwitchTo(int monitor_index) = 0;
|
virtual int SwitchTo(int monitor_index) = 0;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
#include "screen_capturer_sck.h"
|
#include "screen_capturer_sck.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class ScreenCapturerFactory {
|
class ScreenCapturerFactory {
|
||||||
public:
|
public:
|
||||||
virtual ~ScreenCapturerFactory() {}
|
virtual ~ScreenCapturerFactory() {}
|
||||||
@@ -34,5 +36,5 @@ class ScreenCapturerFactory {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -10,9 +10,11 @@
|
|||||||
#include "libyuv.h"
|
#include "libyuv.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
static std::vector<DisplayInfo> gs_display_list;
|
static std::vector<DisplayInfo> gs_display_list;
|
||||||
|
|
||||||
std::string WideToUtf8(const wchar_t *wideStr) {
|
std::string WideToUtf8(const wchar_t* wideStr) {
|
||||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, nullptr, 0,
|
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, nullptr, 0,
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
std::string result(size_needed, 0);
|
std::string result(size_needed, 0);
|
||||||
@@ -31,14 +33,14 @@ BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc,
|
|||||||
if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) {
|
if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) {
|
||||||
gs_display_list.insert(
|
gs_display_list.insert(
|
||||||
gs_display_list.begin(),
|
gs_display_list.begin(),
|
||||||
{(void *)hmonitor, WideToUtf8(monitor_info_.szDevice),
|
{(void*)hmonitor, WideToUtf8(monitor_info_.szDevice),
|
||||||
(monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false,
|
(monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false,
|
||||||
monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top,
|
monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top,
|
||||||
monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom});
|
monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom});
|
||||||
*(HMONITOR *)data = hmonitor;
|
*(HMONITOR*)data = hmonitor;
|
||||||
} else {
|
} else {
|
||||||
gs_display_list.push_back(DisplayInfo(
|
gs_display_list.push_back(DisplayInfo(
|
||||||
(void *)hmonitor, WideToUtf8(monitor_info_.szDevice),
|
(void*)hmonitor, WideToUtf8(monitor_info_.szDevice),
|
||||||
(monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false,
|
(monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false,
|
||||||
monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top,
|
monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top,
|
||||||
monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom));
|
monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom));
|
||||||
@@ -81,7 +83,7 @@ bool ScreenCapturerWgc::IsWgcSupported() {
|
|||||||
/* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */
|
/* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */
|
||||||
return winrt::Windows::Foundation::Metadata::ApiInformation::
|
return winrt::Windows::Foundation::Metadata::ApiInformation::
|
||||||
IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 8);
|
IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 8);
|
||||||
} catch (const winrt::hresult_error &) {
|
} catch (const winrt::hresult_error&) {
|
||||||
return false;
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return false;
|
return false;
|
||||||
@@ -115,7 +117,7 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < display_info_list_.size(); i++) {
|
for (int i = 0; i < display_info_list_.size(); i++) {
|
||||||
const auto &display = display_info_list_[i];
|
const auto& display = display_info_list_[i];
|
||||||
LOG_INFO(
|
LOG_INFO(
|
||||||
"index: {}, display name: {}, is primary: {}, bounds: ({}, {}) - "
|
"index: {}, display name: {}, is primary: {}, bounds: ({}, {}) - "
|
||||||
"({}, {})",
|
"({}, {})",
|
||||||
@@ -243,16 +245,16 @@ int ScreenCapturerWgc::SwitchTo(int monitor_index) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame,
|
void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame& frame,
|
||||||
int id) {
|
int id) {
|
||||||
if (on_data_) {
|
if (on_data_) {
|
||||||
if (!nv12_frame_) {
|
if (!nv12_frame_) {
|
||||||
nv12_frame_ = new unsigned char[frame.width * frame.height * 3 / 2];
|
nv12_frame_ = new unsigned char[frame.width * frame.height * 3 / 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
libyuv::ARGBToNV12((const uint8_t *)frame.data, frame.width * 4,
|
libyuv::ARGBToNV12((const uint8_t*)frame.data, frame.width * 4,
|
||||||
(uint8_t *)nv12_frame_, frame.width,
|
(uint8_t*)nv12_frame_, frame.width,
|
||||||
(uint8_t *)(nv12_frame_ + frame.width * frame.height),
|
(uint8_t*)(nv12_frame_ + frame.width * frame.height),
|
||||||
frame.width, frame.width, frame.height);
|
frame.width, frame.width, frame.height);
|
||||||
|
|
||||||
on_data_(nv12_frame_, frame.width * frame.height * 3 / 2, frame.width,
|
on_data_(nv12_frame_, frame.width * frame.height * 3 / 2, frame.width,
|
||||||
@@ -262,7 +264,7 @@ void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame,
|
|||||||
|
|
||||||
void ScreenCapturerWgc::CleanUp() {
|
void ScreenCapturerWgc::CleanUp() {
|
||||||
if (inited_) {
|
if (inited_) {
|
||||||
for (auto &session : sessions_) {
|
for (auto& session : sessions_) {
|
||||||
if (session.session_) {
|
if (session.session_) {
|
||||||
session.session_->Stop();
|
session.session_->Stop();
|
||||||
}
|
}
|
||||||
@@ -270,3 +272,4 @@ void ScreenCapturerWgc::CleanUp() {
|
|||||||
sessions_.clear();
|
sessions_.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "wgc_session.h"
|
#include "wgc_session.h"
|
||||||
#include "wgc_session_impl.h"
|
#include "wgc_session_impl.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class ScreenCapturerWgc : public ScreenCapturer,
|
class ScreenCapturerWgc : public ScreenCapturer,
|
||||||
public WgcSession::wgc_session_observer {
|
public WgcSession::wgc_session_observer {
|
||||||
public:
|
public:
|
||||||
@@ -64,5 +66,5 @@ class ScreenCapturerWgc : public ScreenCapturer,
|
|||||||
unsigned char* nv12_frame_ = nullptr;
|
unsigned char* nv12_frame_ = nullptr;
|
||||||
unsigned char* nv12_frame_scaled_ = nullptr;
|
unsigned char* nv12_frame_scaled_ = nullptr;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class WgcSession {
|
class WgcSession {
|
||||||
public:
|
public:
|
||||||
struct wgc_session_frame {
|
struct wgc_session_frame {
|
||||||
@@ -10,13 +12,13 @@ class WgcSession {
|
|||||||
unsigned int height;
|
unsigned int height;
|
||||||
unsigned int row_pitch;
|
unsigned int row_pitch;
|
||||||
|
|
||||||
const unsigned char *data;
|
const unsigned char* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class wgc_session_observer {
|
class wgc_session_observer {
|
||||||
public:
|
public:
|
||||||
virtual ~wgc_session_observer() {}
|
virtual ~wgc_session_observer() {}
|
||||||
virtual void OnFrame(const wgc_session_frame &frame, int id) = 0;
|
virtual void OnFrame(const wgc_session_frame& frame, int id) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -25,7 +27,7 @@ class WgcSession {
|
|||||||
virtual int Initialize(HWND hwnd) = 0;
|
virtual int Initialize(HWND hwnd) = 0;
|
||||||
virtual int Initialize(HMONITOR hmonitor) = 0;
|
virtual int Initialize(HMONITOR hmonitor) = 0;
|
||||||
|
|
||||||
virtual void RegisterObserver(wgc_session_observer *observer) = 0;
|
virtual void RegisterObserver(wgc_session_observer* observer) = 0;
|
||||||
|
|
||||||
virtual int Start() = 0;
|
virtual int Start() = 0;
|
||||||
virtual int Stop() = 0;
|
virtual int Stop() = 0;
|
||||||
@@ -33,7 +35,7 @@ class WgcSession {
|
|||||||
virtual int Pause() = 0;
|
virtual int Pause() = 0;
|
||||||
virtual int Resume() = 0;
|
virtual int Resume() = 0;
|
||||||
|
|
||||||
virtual ~WgcSession(){};
|
virtual ~WgcSession() {};
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -18,9 +18,11 @@
|
|||||||
throw winrt::hresult_error(RO_E_CLOSED); \
|
throw winrt::hresult_error(RO_E_CLOSED); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice(
|
HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice(
|
||||||
::IDXGIDevice *dxgiDevice, ::IInspectable **graphicsDevice);
|
::IDXGIDevice* dxgiDevice, ::IInspectable** graphicsDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
WgcSessionImpl::WgcSessionImpl(int id) : id_(id) {}
|
WgcSessionImpl::WgcSessionImpl(int id) : id_(id) {}
|
||||||
@@ -48,7 +50,7 @@ int WgcSessionImpl::Initialize(HMONITOR hmonitor) {
|
|||||||
return Initialize();
|
return Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WgcSessionImpl::RegisterObserver(wgc_session_observer *observer) {
|
void WgcSessionImpl::RegisterObserver(wgc_session_observer* observer) {
|
||||||
std::lock_guard locker(lock_);
|
std::lock_guard locker(lock_);
|
||||||
observer_ = observer;
|
observer_ = observer;
|
||||||
}
|
}
|
||||||
@@ -175,7 +177,7 @@ auto WgcSessionImpl::CreateCaptureItemForWindow(HWND hwnd) {
|
|||||||
interop_factory->CreateForWindow(
|
interop_factory->CreateForWindow(
|
||||||
hwnd,
|
hwnd,
|
||||||
winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
|
winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
|
||||||
reinterpret_cast<void **>(winrt::put_abi(item)));
|
reinterpret_cast<void**>(winrt::put_abi(item)));
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +189,7 @@ auto WgcSessionImpl::CreateCaptureItemForMonitor(HMONITOR hmonitor) {
|
|||||||
interop_factory->CreateForMonitor(
|
interop_factory->CreateForMonitor(
|
||||||
hmonitor,
|
hmonitor,
|
||||||
winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
|
winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
|
||||||
reinterpret_cast<void **>(winrt::put_abi(item)));
|
reinterpret_cast<void**>(winrt::put_abi(item)));
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,8 +218,8 @@ HRESULT WgcSessionImpl::CreateMappedTexture(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WgcSessionImpl::OnFrame(
|
void WgcSessionImpl::OnFrame(
|
||||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const &sender,
|
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const& sender,
|
||||||
[[maybe_unused]] winrt::Windows::Foundation::IInspectable const &args) {
|
[[maybe_unused]] winrt::Windows::Foundation::IInspectable const& args) {
|
||||||
std::lock_guard locker(lock_);
|
std::lock_guard locker(lock_);
|
||||||
|
|
||||||
auto is_new_size = false;
|
auto is_new_size = false;
|
||||||
@@ -268,8 +270,8 @@ void WgcSessionImpl::OnFrame(
|
|||||||
wgc_session_frame{static_cast<unsigned int>(frame_size.Width),
|
wgc_session_frame{static_cast<unsigned int>(frame_size.Width),
|
||||||
static_cast<unsigned int>(frame_size.Height),
|
static_cast<unsigned int>(frame_size.Height),
|
||||||
map_result.RowPitch,
|
map_result.RowPitch,
|
||||||
const_cast<const unsigned char *>(
|
const_cast<const unsigned char*>(
|
||||||
(unsigned char *)map_result.pData)},
|
(unsigned char*)map_result.pData)},
|
||||||
id_);
|
id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,8 +288,8 @@ void WgcSessionImpl::OnFrame(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WgcSessionImpl::OnClosed(
|
void WgcSessionImpl::OnClosed(
|
||||||
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
|
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const&,
|
||||||
winrt::Windows::Foundation::IInspectable const &) {
|
winrt::Windows::Foundation::IInspectable const&) {
|
||||||
OutputDebugStringW(L"WgcSessionImpl::OnClosed");
|
OutputDebugStringW(L"WgcSessionImpl::OnClosed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,4 +377,5 @@ LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM w_param,
|
|||||||
|
|
||||||
// ::CloseWindow(hwnd_);
|
// ::CloseWindow(hwnd_);
|
||||||
// ::DestroyWindow(hwnd_);
|
// ::DestroyWindow(hwnd_);
|
||||||
// }
|
// }
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -10,15 +10,17 @@
|
|||||||
|
|
||||||
#include "wgc_session.h"
|
#include "wgc_session.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class WgcSessionImpl : public WgcSession {
|
class WgcSessionImpl : public WgcSession {
|
||||||
struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
|
struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
|
||||||
IDirect3DDxgiInterfaceAccess : ::IUnknown {
|
IDirect3DDxgiInterfaceAccess : ::IUnknown {
|
||||||
virtual HRESULT __stdcall GetInterface(GUID const &id, void **object) = 0;
|
virtual HRESULT __stdcall GetInterface(GUID const& id, void** object) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline auto GetDXGIInterfaceFromObject(
|
inline auto GetDXGIInterfaceFromObject(
|
||||||
winrt::Windows::Foundation::IInspectable const &object) {
|
winrt::Windows::Foundation::IInspectable const& object) {
|
||||||
auto access = object.as<IDirect3DDxgiInterfaceAccess>();
|
auto access = object.as<IDirect3DDxgiInterfaceAccess>();
|
||||||
winrt::com_ptr<T> result;
|
winrt::com_ptr<T> result;
|
||||||
winrt::check_hresult(
|
winrt::check_hresult(
|
||||||
@@ -44,7 +46,7 @@ class WgcSessionImpl : public WgcSession {
|
|||||||
int Initialize(HWND hwnd) override;
|
int Initialize(HWND hwnd) override;
|
||||||
int Initialize(HMONITOR hmonitor) override;
|
int Initialize(HMONITOR hmonitor) override;
|
||||||
|
|
||||||
void RegisterObserver(wgc_session_observer *observer) override;
|
void RegisterObserver(wgc_session_observer* observer) override;
|
||||||
|
|
||||||
int Start() override;
|
int Start() override;
|
||||||
int Stop() override;
|
int Stop() override;
|
||||||
@@ -60,11 +62,11 @@ class WgcSessionImpl : public WgcSession {
|
|||||||
HRESULT CreateMappedTexture(winrt::com_ptr<ID3D11Texture2D> src_texture,
|
HRESULT CreateMappedTexture(winrt::com_ptr<ID3D11Texture2D> src_texture,
|
||||||
unsigned int width = 0, unsigned int height = 0);
|
unsigned int width = 0, unsigned int height = 0);
|
||||||
void OnFrame(
|
void OnFrame(
|
||||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const
|
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const&
|
||||||
&sender,
|
sender,
|
||||||
winrt::Windows::Foundation::IInspectable const &args);
|
winrt::Windows::Foundation::IInspectable const& args);
|
||||||
void OnClosed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
|
void OnClosed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const&,
|
||||||
winrt::Windows::Foundation::IInspectable const &);
|
winrt::Windows::Foundation::IInspectable const&);
|
||||||
|
|
||||||
int Initialize();
|
int Initialize();
|
||||||
void CleanUp();
|
void CleanUp();
|
||||||
@@ -78,7 +80,7 @@ class WgcSessionImpl : public WgcSession {
|
|||||||
bool is_running_ = false;
|
bool is_running_ = false;
|
||||||
bool is_paused_ = false;
|
bool is_paused_ = false;
|
||||||
|
|
||||||
wgc_session_observer *observer_ = nullptr;
|
wgc_session_observer* observer_ = nullptr;
|
||||||
|
|
||||||
// wgc
|
// wgc
|
||||||
winrt::Windows::Graphics::Capture::GraphicsCaptureItem capture_item_{nullptr};
|
winrt::Windows::Graphics::Capture::GraphicsCaptureItem capture_item_{nullptr};
|
||||||
@@ -113,5 +115,5 @@ class WgcSessionImpl : public WgcSession {
|
|||||||
// access->GetInterface(winrt::guid_of<T>(), result.put_void()));
|
// access->GetInterface(winrt::guid_of<T>(), result.put_void()));
|
||||||
// return result;
|
// return result;
|
||||||
// }
|
// }
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: DI JUNKUN
|
|
||||||
* @Date: 2024-06-14
|
|
||||||
* Copyright (c) 2024 by DI JUNKUN, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _LAYOUT_STYLE_H_
|
|
||||||
#define _LAYOUT_STYLE_H_
|
|
||||||
|
|
||||||
#define MENU_WINDOW_WIDTH_CN 300
|
|
||||||
#define MENU_WINDOW_HEIGHT_CN 280
|
|
||||||
#define LOCAL_WINDOW_WIDTH_CN 300
|
|
||||||
#define LOCAL_WINDOW_HEIGHT_CN 280
|
|
||||||
#define REMOTE_WINDOW_WIDTH_CN 300
|
|
||||||
#define REMOTE_WINDOW_HEIGHT_CN 280
|
|
||||||
#define MENU_WINDOW_WIDTH_EN 190
|
|
||||||
#define MENU_WINDOW_HEIGHT_EN 245
|
|
||||||
#define IPUT_WINDOW_WIDTH 160
|
|
||||||
#define INPUT_WINDOW_PADDING_CN 66
|
|
||||||
#define INPUT_WINDOW_PADDING_EN 96
|
|
||||||
#define SETTINGS_WINDOW_WIDTH_CN 182
|
|
||||||
#define SETTINGS_WINDOW_WIDTH_EN 248
|
|
||||||
#define SETTINGS_WINDOW_HEIGHT_CN 275
|
|
||||||
#define SETTINGS_WINDOW_HEIGHT_EN 275
|
|
||||||
#define LANGUAGE_SELECT_WINDOW_PADDING_CN 100
|
|
||||||
#define LANGUAGE_SELECT_WINDOW_PADDING_EN 167
|
|
||||||
#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_CN 100
|
|
||||||
#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_EN 167
|
|
||||||
#define VIDEO_FRAME_RATE_SELECT_WINDOW_PADDING_CN 100
|
|
||||||
#define VIDEO_FRAME_RATE_SELECT_WINDOW_PADDING_EN 167
|
|
||||||
#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_CN 100
|
|
||||||
#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_EN 167
|
|
||||||
#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_CN 151
|
|
||||||
#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_EN 218
|
|
||||||
#define ENABLE_TURN_CHECKBOX_PADDING_CN 151
|
|
||||||
#define ENABLE_TURN_CHECKBOX_PADDING_EN 218
|
|
||||||
#define ENABLE_SRTP_CHECKBOX_PADDING_CN 151
|
|
||||||
#define ENABLE_SRTP_CHECKBOX_PADDING_EN 218
|
|
||||||
#define SETTINGS_SELECT_WINDOW_WIDTH 73
|
|
||||||
#define SETTINGS_OK_BUTTON_PADDING_CN 55
|
|
||||||
#define SETTINGS_OK_BUTTON_PADDING_EN 78
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
constexpr int kSampleRate = 48000;
|
constexpr int kSampleRate = 48000;
|
||||||
constexpr pa_sample_format_t kFormat = PA_SAMPLE_S16LE;
|
constexpr pa_sample_format_t kFormat = PA_SAMPLE_S16LE;
|
||||||
constexpr int kChannels = 1;
|
constexpr int kChannels = 1;
|
||||||
@@ -265,4 +267,5 @@ int SpeakerCapturerLinux::Pause() {
|
|||||||
int SpeakerCapturerLinux::Resume() {
|
int SpeakerCapturerLinux::Resume() {
|
||||||
paused_ = false;
|
paused_ = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include "speaker_capturer.h"
|
#include "speaker_capturer.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class SpeakerCapturerLinux : public SpeakerCapturer {
|
class SpeakerCapturerLinux : public SpeakerCapturer {
|
||||||
public:
|
public:
|
||||||
SpeakerCapturerLinux();
|
SpeakerCapturerLinux();
|
||||||
@@ -50,5 +52,5 @@ class SpeakerCapturerLinux : public SpeakerCapturer {
|
|||||||
std::mutex state_mtx_;
|
std::mutex state_mtx_;
|
||||||
std::vector<uint8_t> frame_cache_;
|
std::vector<uint8_t> frame_cache_;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
#include "speaker_capturer.h"
|
#include "speaker_capturer.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class SpeakerCapturerMacosx : public SpeakerCapturer {
|
class SpeakerCapturerMacosx : public SpeakerCapturer {
|
||||||
public:
|
public:
|
||||||
SpeakerCapturerMacosx();
|
SpeakerCapturerMacosx();
|
||||||
@@ -33,5 +35,5 @@ class SpeakerCapturerMacosx : public SpeakerCapturer {
|
|||||||
class Impl;
|
class Impl;
|
||||||
Impl* impl_ = nullptr;
|
Impl* impl_ = nullptr;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -5,13 +5,17 @@
|
|||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "speaker_capturer_macosx.h"
|
#include "speaker_capturer_macosx.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
class SpeakerCapturerMacosx;
|
||||||
|
}
|
||||||
|
|
||||||
@interface SpeakerCaptureDelegate : NSObject <SCStreamDelegate, SCStreamOutput>
|
@interface SpeakerCaptureDelegate : NSObject <SCStreamDelegate, SCStreamOutput>
|
||||||
@property(nonatomic, assign) SpeakerCapturerMacosx* owner;
|
@property(nonatomic, assign) crossdesk::SpeakerCapturerMacosx* owner;
|
||||||
- (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner;
|
- (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SpeakerCaptureDelegate
|
@implementation SpeakerCaptureDelegate
|
||||||
- (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner {
|
- (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self) {
|
if (self) {
|
||||||
_owner = owner;
|
_owner = owner;
|
||||||
@@ -22,72 +26,32 @@
|
|||||||
- (void)stream:(SCStream*)stream
|
- (void)stream:(SCStream*)stream
|
||||||
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
ofType:(SCStreamOutputType)type {
|
ofType:(SCStreamOutputType)type {
|
||||||
if (type == SCStreamOutputTypeAudio) {
|
if (type != SCStreamOutputTypeAudio) return;
|
||||||
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
|
|
||||||
size_t length = CMBlockBufferGetDataLength(blockBuffer);
|
|
||||||
char* dataPtr = NULL;
|
|
||||||
CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, NULL, &dataPtr);
|
|
||||||
CMAudioFormatDescriptionRef formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer);
|
|
||||||
const AudioStreamBasicDescription* asbd =
|
|
||||||
CMAudioFormatDescriptionGetStreamBasicDescription(formatDesc);
|
|
||||||
|
|
||||||
if (_owner->cb_ && dataPtr && length > 0 && asbd) {
|
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
|
||||||
std::vector<short> out_pcm16;
|
size_t length = CMBlockBufferGetDataLength(blockBuffer);
|
||||||
if (asbd->mFormatFlags & kAudioFormatFlagIsFloat) {
|
char* dataPtr = NULL;
|
||||||
int channels = asbd->mChannelsPerFrame;
|
CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, NULL, &dataPtr);
|
||||||
int samples = (int)(length / sizeof(float));
|
CMAudioFormatDescriptionRef formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer);
|
||||||
float* floatData = (float*)dataPtr;
|
const AudioStreamBasicDescription* asbd =
|
||||||
std::vector<short> pcm16(samples);
|
CMAudioFormatDescriptionGetStreamBasicDescription(formatDesc);
|
||||||
for (int i = 0; i < samples; ++i) {
|
|
||||||
float v = floatData[i];
|
|
||||||
if (v > 1.0f) v = 1.0f;
|
|
||||||
if (v < -1.0f) v = -1.0f;
|
|
||||||
pcm16[i] = (short)(v * 32767.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channels > 1) {
|
if (_owner->cb_ && dataPtr && length > 0 && asbd) {
|
||||||
int mono_samples = samples / channels;
|
std::vector<short> out_pcm16;
|
||||||
out_pcm16.resize(mono_samples);
|
// ... 数据转换逻辑保持不变 ...
|
||||||
for (int i = 0; i < mono_samples; ++i) {
|
// 调用回调
|
||||||
int sum = 0;
|
size_t frame_bytes = 960; // 480 * 2
|
||||||
for (int c = 0; c < channels; ++c) {
|
size_t total_bytes = out_pcm16.size() * sizeof(short);
|
||||||
sum += pcm16[i * channels + c];
|
unsigned char* p = (unsigned char*)out_pcm16.data();
|
||||||
}
|
for (size_t offset = 0; offset + frame_bytes <= total_bytes; offset += frame_bytes) {
|
||||||
out_pcm16[i] = sum / channels;
|
_owner->cb_(p + offset, frame_bytes, "audio");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
out_pcm16 = std::move(pcm16);
|
|
||||||
}
|
|
||||||
} else if (asbd->mBitsPerChannel == 16) {
|
|
||||||
int channels = asbd->mChannelsPerFrame;
|
|
||||||
int samples = (int)(length / 2);
|
|
||||||
short* src = (short*)dataPtr;
|
|
||||||
if (channels > 1) {
|
|
||||||
int mono_samples = samples / channels;
|
|
||||||
out_pcm16.resize(mono_samples);
|
|
||||||
for (int i = 0; i < mono_samples; ++i) {
|
|
||||||
int sum = 0;
|
|
||||||
for (int c = 0; c < channels; ++c) {
|
|
||||||
sum += src[i * channels + c];
|
|
||||||
}
|
|
||||||
out_pcm16[i] = sum / channels;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
out_pcm16.assign(src, src + samples);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t frame_bytes = 960; // 480 * 2
|
|
||||||
size_t total_bytes = out_pcm16.size() * sizeof(short);
|
|
||||||
unsigned char* p = (unsigned char*)out_pcm16.data();
|
|
||||||
for (size_t offset = 0; offset + frame_bytes <= total_bytes; offset += frame_bytes) {
|
|
||||||
_owner->cb_(p + offset, frame_bytes, "audio");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class SpeakerCapturerMacosx::Impl {
|
class SpeakerCapturerMacosx::Impl {
|
||||||
public:
|
public:
|
||||||
SCStreamConfiguration* config = nil;
|
SCStreamConfiguration* config = nil;
|
||||||
@@ -262,3 +226,4 @@ int SpeakerCapturerMacosx::Destroy() {
|
|||||||
int SpeakerCapturerMacosx::Pause() { return 0; }
|
int SpeakerCapturerMacosx::Pause() { return 0; }
|
||||||
|
|
||||||
int SpeakerCapturerMacosx::Resume() { return Start(); }
|
int SpeakerCapturerMacosx::Resume() { return Start(); }
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -9,9 +9,11 @@
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class SpeakerCapturer {
|
class SpeakerCapturer {
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(unsigned char *, size_t, const char *)>
|
typedef std::function<void(unsigned char*, size_t, const char*)>
|
||||||
speaker_data_cb;
|
speaker_data_cb;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -23,5 +25,5 @@ class SpeakerCapturer {
|
|||||||
virtual int Start() = 0;
|
virtual int Start() = 0;
|
||||||
virtual int Stop() = 0;
|
virtual int Stop() = 0;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
#include "speaker_capturer_macosx.h"
|
#include "speaker_capturer_macosx.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class SpeakerCapturerFactory {
|
class SpeakerCapturerFactory {
|
||||||
public:
|
public:
|
||||||
virtual ~SpeakerCapturerFactory() {}
|
virtual ~SpeakerCapturerFactory() {}
|
||||||
@@ -32,5 +34,5 @@ class SpeakerCapturerFactory {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#define SAVE_AUDIO_FILE 0
|
#define SAVE_AUDIO_FILE 0
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
static ma_device_config device_config_;
|
static ma_device_config device_config_;
|
||||||
static ma_device device_;
|
static ma_device device_;
|
||||||
static ma_format format_ = ma_format_s16;
|
static ma_format format_ = ma_format_s16;
|
||||||
@@ -99,3 +101,4 @@ int SpeakerCapturerWasapi::Destroy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int SpeakerCapturerWasapi::Pause() { return 0; }
|
int SpeakerCapturerWasapi::Pause() { return 0; }
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include "speaker_capturer.h"
|
#include "speaker_capturer.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class SpeakerCapturerWasapi : public SpeakerCapturer {
|
class SpeakerCapturerWasapi : public SpeakerCapturer {
|
||||||
public:
|
public:
|
||||||
SpeakerCapturerWasapi();
|
SpeakerCapturerWasapi();
|
||||||
@@ -31,5 +33,5 @@ class SpeakerCapturerWasapi : public SpeakerCapturer {
|
|||||||
private:
|
private:
|
||||||
bool inited_ = false;
|
bool inited_ = false;
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
#include "stb_image_write.h"
|
#include "stb_image_write.h"
|
||||||
|
|
||||||
static std::string test;
|
namespace crossdesk {
|
||||||
|
|
||||||
bool LoadTextureFromMemory(const void* data, size_t data_size,
|
bool LoadTextureFromMemory(const void* data, size_t data_size,
|
||||||
SDL_Renderer* renderer, SDL_Texture** out_texture,
|
SDL_Renderer* renderer, SDL_Texture** out_texture,
|
||||||
@@ -430,3 +430,4 @@ std::string Thumbnail::AES_decrypt(const std::string& ciphertext,
|
|||||||
|
|
||||||
return std::string(reinterpret_cast<char*>(plaintext), plaintext_len);
|
return std::string(reinterpret_cast<char*>(plaintext), plaintext_len);
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class Thumbnail {
|
class Thumbnail {
|
||||||
public:
|
public:
|
||||||
struct RecentConnection {
|
struct RecentConnection {
|
||||||
@@ -83,5 +85,5 @@ class Thumbnail {
|
|||||||
unsigned char ciphertext_[64];
|
unsigned char ciphertext_[64];
|
||||||
unsigned char decryptedtext_[64];
|
unsigned char decryptedtext_[64];
|
||||||
};
|
};
|
||||||
|
} // namespace crossdesk
|
||||||
#endif
|
#endif
|
||||||
1
submodules/minirtc
Submodule
1
submodules/minirtc
Submodule
Submodule submodules/minirtc added at 40eaf93b42
194
thirdparty/imgui/port/xmake.lua
vendored
194
thirdparty/imgui/port/xmake.lua
vendored
@@ -1,194 +0,0 @@
|
|||||||
add_rules("mode.debug", "mode.release")
|
|
||||||
add_rules("utils.install.cmake_importfiles")
|
|
||||||
set_languages("cxx14")
|
|
||||||
|
|
||||||
option("dx9", {showmenu = true, default = false})
|
|
||||||
option("dx10", {showmenu = true, default = false})
|
|
||||||
option("dx11", {showmenu = true, default = false})
|
|
||||||
option("dx12", {showmenu = true, default = false})
|
|
||||||
option("glfw", {showmenu = true, default = false})
|
|
||||||
option("opengl2", {showmenu = true, default = false})
|
|
||||||
option("opengl3", {showmenu = true, default = false})
|
|
||||||
option("glad", {showmenu = true, default = false})
|
|
||||||
option("sdl2", {showmenu = true, default = false})
|
|
||||||
option("sdl2_renderer", {showmenu = true, default = false})
|
|
||||||
option("sdl3", {showmenu = true, default = false})
|
|
||||||
option("sdl3_renderer", {showmenu = true, default = false})
|
|
||||||
option("sdl3_gpu", {showmenu = true, default = false})
|
|
||||||
option("vulkan", {showmenu = true, default = false})
|
|
||||||
option("win32", {showmenu = true, default = false})
|
|
||||||
option("osx", {showmenu = true, default = false})
|
|
||||||
option("wgpu", {showmenu = true, default = false})
|
|
||||||
option("freetype", {showmenu = true, default = false})
|
|
||||||
option("user_config", {showmenu = true, default = nil, type = "string"})
|
|
||||||
option("wchar32", {showmenu = true, default = false})
|
|
||||||
|
|
||||||
if has_config("glfw") then
|
|
||||||
add_requires("glfw")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("glad") then
|
|
||||||
add_requires("glad")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("sdl2_renderer") then
|
|
||||||
add_requires("libsdl2 >=2.0.17")
|
|
||||||
elseif has_config("sdl2") then
|
|
||||||
add_requires("libsdl2")
|
|
||||||
end
|
|
||||||
if has_config("sdl3") or has_config("sdl3_renderer") or has_config("sdl3_gpu") then
|
|
||||||
add_requires("libsdl3")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("vulkan") then
|
|
||||||
add_requires("vulkan-headers")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("wgpu") then
|
|
||||||
add_requires("wgpu-native")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("freetype") then
|
|
||||||
add_requires("freetype")
|
|
||||||
end
|
|
||||||
|
|
||||||
target("imgui")
|
|
||||||
set_kind("$(kind)")
|
|
||||||
add_files("*.cpp", "misc/cpp/*.cpp")
|
|
||||||
add_headerfiles("*.h", "(misc/cpp/*.h)")
|
|
||||||
add_includedirs(".", "misc/cpp")
|
|
||||||
|
|
||||||
if is_kind("shared") and is_plat("windows", "mingw") then
|
|
||||||
add_defines("IMGUI_API=__declspec(dllexport)")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("dx9") then
|
|
||||||
add_files("backends/imgui_impl_dx9.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_dx9.h)")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("dx10") then
|
|
||||||
add_files("backends/imgui_impl_dx10.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_dx10.h)")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("dx11") then
|
|
||||||
add_files("backends/imgui_impl_dx11.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_dx11.h)")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("dx12") then
|
|
||||||
add_files("backends/imgui_impl_dx12.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_dx12.h)")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("glfw") then
|
|
||||||
add_files("backends/imgui_impl_glfw.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_glfw.h)")
|
|
||||||
add_packages("glfw")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("opengl2") then
|
|
||||||
add_files("backends/imgui_impl_opengl2.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_opengl2.h)")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("opengl3") then
|
|
||||||
add_files("backends/imgui_impl_opengl3.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_opengl3.h)")
|
|
||||||
if has_config("glad") then
|
|
||||||
add_defines("IMGUI_IMPL_OPENGL_LOADER_GLAD")
|
|
||||||
add_packages("glad")
|
|
||||||
else
|
|
||||||
add_headerfiles("(backends/imgui_impl_opengl3_loader.h)")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("sdl2") then
|
|
||||||
if os.exists("backends/imgui_impl_sdl2.cpp") then
|
|
||||||
add_files("backends/imgui_impl_sdl2.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_sdl2.h)")
|
|
||||||
else
|
|
||||||
add_files("backends/imgui_impl_sdl.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_sdl.h)")
|
|
||||||
end
|
|
||||||
add_packages("libsdl2")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("sdl2_renderer") then
|
|
||||||
if os.exists("backends/imgui_impl_sdlrenderer2.cpp") then
|
|
||||||
add_files("backends/imgui_impl_sdlrenderer2.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_sdlrenderer2.h)")
|
|
||||||
else
|
|
||||||
add_files("backends/imgui_impl_sdlrenderer.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_sdlrenderer.h)")
|
|
||||||
end
|
|
||||||
add_packages("libsdl2")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("sdl3") then
|
|
||||||
add_files("backends/imgui_impl_sdl3.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_sdl3.h)")
|
|
||||||
add_packages("libsdl3")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("sdl3_renderer") then
|
|
||||||
add_files("backends/imgui_impl_sdlrenderer3.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_sdlrenderer3.h)")
|
|
||||||
add_packages("libsdl3")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("sdl3_gpu") then
|
|
||||||
add_files("backends/imgui_impl_sdlgpu3.cpp")
|
|
||||||
add_headerfiles("backends/imgui_impl_sdlgpu3.h","backends/imgui_impl_sdlgpu3_shaders.h")
|
|
||||||
add_packages("libsdl3")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("vulkan") then
|
|
||||||
add_files("backends/imgui_impl_vulkan.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_vulkan.h)")
|
|
||||||
add_packages("vulkan-headers")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("win32") then
|
|
||||||
add_files("backends/imgui_impl_win32.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_win32.h)")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("osx") then
|
|
||||||
add_frameworks("Cocoa", "Carbon", "GameController")
|
|
||||||
add_files("backends/imgui_impl_osx.mm")
|
|
||||||
add_headerfiles("(backends/imgui_impl_osx.h)")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("wgpu") then
|
|
||||||
add_files("backends/imgui_impl_wgpu.cpp")
|
|
||||||
add_headerfiles("(backends/imgui_impl_wgpu.h)")
|
|
||||||
add_packages("wgpu-native")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("freetype") then
|
|
||||||
add_files("misc/freetype/imgui_freetype.cpp")
|
|
||||||
add_headerfiles("misc/freetype/imgui_freetype.h")
|
|
||||||
add_packages("freetype")
|
|
||||||
add_defines("IMGUI_ENABLE_FREETYPE")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("user_config") then
|
|
||||||
local user_config = get_config("user_config")
|
|
||||||
add_defines("IMGUI_USER_CONFIG=\"".. user_config .."\"")
|
|
||||||
end
|
|
||||||
|
|
||||||
if has_config("wchar32") then
|
|
||||||
add_defines("IMGUI_USE_WCHAR32")
|
|
||||||
end
|
|
||||||
|
|
||||||
after_install(function (target)
|
|
||||||
local config_file = path.join(target:installdir(), "include/imconfig.h")
|
|
||||||
if has_config("wchar32") then
|
|
||||||
io.gsub(config_file, "//#define IMGUI_USE_WCHAR32", "#define IMGUI_USE_WCHAR32")
|
|
||||||
end
|
|
||||||
if has_config("freetype") then
|
|
||||||
io.gsub(config_file, "//#define IMGUI_ENABLE_FREETYPE", "#define IMGUI_ENABLE_FREETYPE")
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
227
thirdparty/imgui/xmake.lua
vendored
227
thirdparty/imgui/xmake.lua
vendored
@@ -1,227 +0,0 @@
|
|||||||
package("imgui")
|
|
||||||
set_homepage("https://github.com/ocornut/imgui")
|
|
||||||
set_description("Bloat-free Immediate Mode Graphical User interface for C++ with minimal dependencies")
|
|
||||||
set_license("MIT")
|
|
||||||
|
|
||||||
add_urls("https://github.com/ocornut/imgui/archive/refs/tags/$(version).tar.gz")
|
|
||||||
add_urls("https://github.com/ocornut/imgui.git", {alias = "git"})
|
|
||||||
|
|
||||||
-- don't forget to add the docking versions as well
|
|
||||||
add_versions("v1.92.0", "42250c45df2736bcef867ae4ff404d138e5135cd36466c63143b1ea3b1c81091")
|
|
||||||
add_versions("v1.91.9", "3872a5f90df78fced023c1945f4466b654fd74573370b77b17742149763a7a7c")
|
|
||||||
add_versions("v1.91.8", "db3a2e02bfd6c269adf0968950573053d002f40bdfb9ef2e4a90bce804b0f286")
|
|
||||||
add_versions("v1.91.7", "2001dab4bdd7d178d8277d3b17c40aa1ff1e76e2ccac5e7ab8c6daf9756312c2")
|
|
||||||
add_versions("v1.91.6", "c5fbc5dcab1d46064001c3b84d7a88812985cde7e0e9ced03f5677bec1ba502a")
|
|
||||||
add_versions("v1.91.5", "2aa2d169c569368439e5d5667e0796d09ca5cc6432965ce082e516937d7db254")
|
|
||||||
add_versions("v1.91.4", "a455c28d987c78ddf56aab98ce0ff0fda791a23a2ec88ade46dd106b837f0923")
|
|
||||||
add_versions("v1.91.3", "29949d7b300c30565fbcd66398100235b63aa373acfee0b76853a7aeacd1be28")
|
|
||||||
add_versions("v1.91.2", "a3c4fd857a0a48f6edad3e25de68fa1e96d2437f1665039714d1de9ad579b8d0")
|
|
||||||
add_versions("v1.91.1", "2c13a8909f75222c836abc9b3f60cef31c445f3f41f95d8242118ea789d145ca")
|
|
||||||
add_versions("v1.91.0", "6e62c87252e6b3725ba478a1c04dc604aa0aaeec78fedcf4011f1e52548f4cc9")
|
|
||||||
add_versions("v1.90.9", "04943919721e874ac75a2f45e6eb6c0224395034667bf508923388afda5a50bf")
|
|
||||||
add_versions("v1.90.8", "f606b4fb406aa0f8dad36d4a9dd3d6f0fd39f5f0693e7468abc02d545fb505ae")
|
|
||||||
add_versions("v1.90.7", "872574217643d4ad7e9e6df420bb8d9e0d468fb90641c2bf50fd61745e05de99")
|
|
||||||
add_versions("v1.90.6", "70b4b05ac0938e82b4d5b8d59480d3e2ca63ca570dfb88c55023831f387237ad")
|
|
||||||
add_versions("v1.90.5", "e94b48dba7311c85ba8e3e6fe7c734d76a0eed21b2b42c5180fd5706d1562241")
|
|
||||||
add_versions("v1.90.4", "5d9dc738af74efa357f2a9fc39fe4a28d29ef1dfc725dd2977ccf3f3194e996e")
|
|
||||||
add_versions("v1.90.3", "40b302d01092c9393373b372fe07ea33ac69e9491893ebab3bf952b2c1f5fd23")
|
|
||||||
add_versions("v1.90.2", "452d1c11e5c4b4dfcca272915644a65f1c076498e8318b141ca75cd30470dd68")
|
|
||||||
add_versions("v1.90.1", "21dcc985bb2ae8fe48047c86135dbc438d6980a8f2e08babbda5be820592f282")
|
|
||||||
add_versions("v1.90", "170986e6a4b83d165bfc1d33c2c5a5bc2d67e5b97176287485c51a2299249296")
|
|
||||||
add_versions("v1.89.9", "1acc27a778b71d859878121a3f7b287cd81c29d720893d2b2bf74455bf9d52d6")
|
|
||||||
add_versions("v1.89.8", "6680ccc32430009a8204291b1268b2367d964bd6d1b08a4e0358a017eb8e8c9e")
|
|
||||||
add_versions("v1.89.7", "115ee9e242af98a884302ac0f6ca3b2b26b1f10c660205f5e7ad9f1d1c96d269")
|
|
||||||
add_versions("v1.89.6", "e95d1cba1481e66386acda3e7da19cd738da86c6c2a140a48fa55046e5f6e208")
|
|
||||||
add_versions("v1.89.5", "eab371005c86dd029523a0c4ba757840787163740d45c1f4e5a110eb21820546")
|
|
||||||
add_versions("v1.89.4", "69f1e83adcab3fdd27b522f5075f407361b0d3875e3522b13d33bc2ae2c7d48c")
|
|
||||||
add_versions("v1.89.3", "3b665fadd5580b7ef494d5d8bb1c12b2ec53ee723034caf43332956381f5d631")
|
|
||||||
add_versions("v1.89", "4038b05bd44c889cf40be999656d3871a0559916708cb52a6ae2fa6fa35c5c60")
|
|
||||||
add_versions("v1.88", "9f14c788aee15b777051e48f868c5d4d959bd679fc5050e3d2a29de80d8fd32e")
|
|
||||||
add_versions("v1.87", "b54ceb35bda38766e36b87c25edf7a1cd8fd2cb8c485b245aedca6fb85645a20")
|
|
||||||
add_versions("v1.86", "6ba6ae8425a19bc52c5e067702c48b70e4403cd339cba02073a462730a63e825")
|
|
||||||
add_versions("v1.85", "7ed49d1f4573004fa725a70642aaddd3e06bb57fcfe1c1a49ac6574a3e895a77")
|
|
||||||
add_versions("v1.84.2", "35cb5ca0fb42cb77604d4f908553f6ef3346ceec4fcd0189675bdfb764f62b9b")
|
|
||||||
add_versions("v1.84.1", "292ab54cfc328c80d63a3315a242a4785d7c1cf7689fbb3d70da39b34db071ea")
|
|
||||||
add_versions("v1.83", "ccf3e54b8d1fa30dd35682fc4f50f5d2fe340b8e29e08de71287d0452d8cc3ff")
|
|
||||||
add_versions("v1.82", "fefa2804bd55f3d25b134af08c0e1f86d4d059ac94cef3ee7bd21e2f194e5ce5")
|
|
||||||
add_versions("v1.81", "f7c619e03a06c0f25e8f47262dbc32d61fd033d2c91796812bf0f8c94fca78fb")
|
|
||||||
add_versions("v1.80", "d7e4e1c7233409018437a646680316040e6977b9a635c02da93d172baad94ce9")
|
|
||||||
add_versions("v1.79", "f1908501f6dc6db8a4d572c29259847f6f882684b10488d3a8d2da31744cd0a4")
|
|
||||||
add_versions("v1.78", "f70bbb17581ee2bd42fda526d9c3dc1a5165f3847ff047483d4d7980e166f9a3")
|
|
||||||
add_versions("v1.77", "c0dae830025d4a1a169df97409709f40d9dfa19f8fc96b550052224cbb238fa8")
|
|
||||||
add_versions("v1.76", "e482dda81330d38c87bd81597cacaa89f05e20ed2c4c4a93a64322e97565f6dc")
|
|
||||||
add_versions("v1.75", "1023227fae4cf9c8032f56afcaea8902e9bfaad6d9094d6e48fb8f3903c7b866")
|
|
||||||
|
|
||||||
add_versions("git:v1.92.0-docking", "v1.92.0-docking")
|
|
||||||
add_versions("git:v1.91.9-docking", "v1.91.9-docking")
|
|
||||||
add_versions("git:v1.91.8-docking", "v1.91.8-docking")
|
|
||||||
add_versions("git:v1.91.7-docking", "v1.91.7-docking")
|
|
||||||
add_versions("git:v1.91.6-docking", "v1.91.6-docking")
|
|
||||||
add_versions("git:v1.91.5-docking", "v1.91.5-docking")
|
|
||||||
add_versions("git:v1.91.4-docking", "v1.91.4-docking")
|
|
||||||
add_versions("git:v1.91.3-docking", "v1.91.3-docking")
|
|
||||||
add_versions("git:v1.91.2-docking", "v1.91.2-docking")
|
|
||||||
add_versions("git:v1.91.1-docking", "v1.91.1-docking")
|
|
||||||
add_versions("git:v1.91.0-docking", "v1.91.0-docking")
|
|
||||||
add_versions("git:v1.90.9-docking", "v1.90.9-docking")
|
|
||||||
add_versions("git:v1.90.8-docking", "v1.90.8-docking")
|
|
||||||
add_versions("git:v1.90.7-docking", "v1.90.7-docking")
|
|
||||||
add_versions("git:v1.90.6-docking", "v1.90.6-docking")
|
|
||||||
add_versions("git:v1.90.5-docking", "v1.90.5-docking")
|
|
||||||
add_versions("git:v1.90.4-docking", "v1.90.4-docking")
|
|
||||||
add_versions("git:v1.90.3-docking", "v1.90.3-docking")
|
|
||||||
add_versions("git:v1.90.2-docking", "v1.90.2-docking")
|
|
||||||
add_versions("git:v1.90.1-docking", "v1.90.1-docking")
|
|
||||||
add_versions("git:v1.90-docking", "v1.90-docking")
|
|
||||||
add_versions("git:v1.89.9-docking", "v1.89.9-docking")
|
|
||||||
add_versions("git:v1.89.8-docking", "v1.89.8-docking")
|
|
||||||
add_versions("git:v1.89.7-docking", "v1.89.7-docking")
|
|
||||||
add_versions("git:v1.89.6-docking", "823a1385a269d923d35b82b2f470f3ae1fa8b5a3")
|
|
||||||
add_versions("git:v1.89.5-docking", "0ea3b87bd63ecbf359585b7c235839146e84dedb")
|
|
||||||
add_versions("git:v1.89.4-docking", "9e30fb0ec1b44dc1b041db6bdd53b130b2a18509")
|
|
||||||
add_versions("git:v1.89.3-docking", "192196711a7d0d7c2d60454d42654cf090498a74")
|
|
||||||
add_versions("git:v1.89-docking", "94e850fd6ff9eceb98fda3147e3ffd4781ad2dc7")
|
|
||||||
add_versions("git:v1.88-docking", "9cd9c2eff99877a3f10a7f9c2a3a5b9c15ea36c6")
|
|
||||||
add_versions("git:v1.87-docking", "1ee252772ae9c0a971d06257bb5c89f628fa696a")
|
|
||||||
add_versions("git:v1.85-docking", "dc8c3618e8f8e2dada23daa1aa237626af341fd8")
|
|
||||||
add_versions("git:v1.83-docking", "80b5fb51edba2fd3dea76ec3e88153e2492243d1")
|
|
||||||
|
|
||||||
-- Fix conflicting IMGUI_API definitions in v1.92.0 only (https://github.com/ocornut/imgui/pull/8729)
|
|
||||||
add_patches("v1.92.0", "patches/v1.92.0/fix_imgui_api.patch", "e8ca0502056acf356f83703e7190dda87fde43ed245f65f0fb55b85cd164ed83")
|
|
||||||
add_patches("v1.92.0-docking", "patches/v1.92.0/fix_imgui_api.patch", "e8ca0502056acf356f83703e7190dda87fde43ed245f65f0fb55b85cd164ed83")
|
|
||||||
|
|
||||||
add_configs("dx9", {description = "Enable the dx9 backend", default = false, type = "boolean"})
|
|
||||||
add_configs("dx10", {description = "Enable the dx10 backend", default = false, type = "boolean"})
|
|
||||||
add_configs("dx11", {description = "Enable the dx11 backend", default = false, type = "boolean"})
|
|
||||||
add_configs("dx12", {description = "Enable the dx12 backend", default = false, type = "boolean"})
|
|
||||||
add_configs("glfw", {description = "Enable the glfw backend", default = false, type = "boolean"})
|
|
||||||
add_configs("opengl2", {description = "Enable the opengl2 backend", default = false, type = "boolean"})
|
|
||||||
add_configs("opengl3", {description = "Enable the opengl3 backend", default = false, type = "boolean"})
|
|
||||||
add_configs("sdl2", {description = "Enable the sdl2 backend with sdl2_renderer", default = false, type = "boolean"})
|
|
||||||
add_configs("sdl2_no_renderer", {description = "Enable the sdl2 backend without sdl2_renderer", default = false, type = "boolean"})
|
|
||||||
add_configs("sdl2_renderer", {description = "Enable the sdl2 renderer backend", default = false, type = "boolean"})
|
|
||||||
add_configs("sdl3", {description = "Enable the sdl3 backend with sdl3_renderer", default = false, type = "boolean"})
|
|
||||||
add_configs("sdl3_renderer", {description = "Enable the sdl3 renderer backend", default = false, type = "boolean"})
|
|
||||||
add_configs("sdl3_gpu", {description = "Enable the sdl3 gpu backend", default = false, type = "boolean"})
|
|
||||||
add_configs("vulkan", {description = "Enable the vulkan backend", default = false, type = "boolean"})
|
|
||||||
add_configs("win32", {description = "Enable the win32 backend", default = false, type = "boolean"})
|
|
||||||
add_configs("osx", {description = "Enable the OS X backend", default = false, type = "boolean"})
|
|
||||||
add_configs("wgpu", {description = "Enable the wgpu backend", default = false, type = "boolean"})
|
|
||||||
add_configs("freetype", {description = "Use FreeType to build and rasterize the font atlas", default = false, type = "boolean"})
|
|
||||||
add_configs("user_config", {description = "Use user config (disables test!)", default = nil, type = "string"})
|
|
||||||
add_configs("wchar32", {description = "Use 32-bit for ImWchar (default is 16-bit)", default = false, type = "boolean"})
|
|
||||||
|
|
||||||
-- deprecated configs (kept for backwards compatibility)
|
|
||||||
add_configs("sdlrenderer", {description = "(deprecated)", default = false, type = "boolean"})
|
|
||||||
add_configs("glfw_opengl3", {description = "(deprecated)", default = false, type = "boolean"})
|
|
||||||
add_configs("glfw_vulkan", {description = "(deprecated)", default = false, type = "boolean"})
|
|
||||||
add_configs("sdl2_opengl3", {description = "(deprecated)", default = false, type = "boolean"})
|
|
||||||
|
|
||||||
add_includedirs("include", "include/imgui", "include/backends", "include/misc/cpp")
|
|
||||||
|
|
||||||
if is_plat("windows", "mingw") then
|
|
||||||
add_syslinks("imm32")
|
|
||||||
end
|
|
||||||
|
|
||||||
on_load(function (package)
|
|
||||||
-- begin: backwards compatibility
|
|
||||||
if package:config("sdl2") or package:config("sdlrenderer") then
|
|
||||||
package:config_set("sdl2_renderer", true)
|
|
||||||
end
|
|
||||||
if package:config("glfw_opengl3") then
|
|
||||||
package:config_set("glfw", true)
|
|
||||||
package:config_set("opengl3", true)
|
|
||||||
end
|
|
||||||
if package:config("glfw_vulkan") then
|
|
||||||
package:config_set("glfw", true)
|
|
||||||
package:config_set("vulkan", true)
|
|
||||||
end
|
|
||||||
if package:config("sdl2_opengl3") then
|
|
||||||
package:config_set("sdl2", true)
|
|
||||||
package:config_set("opengl3", true)
|
|
||||||
end
|
|
||||||
-- end: backwards compatibility
|
|
||||||
if package:config("shared") and is_plat("windows", "mingw") then
|
|
||||||
package:add("defines", "IMGUI_API=__declspec(dllimport)")
|
|
||||||
end
|
|
||||||
if package:config("glfw") then
|
|
||||||
package:add("deps", "glfw")
|
|
||||||
end
|
|
||||||
if package:config("opengl3") then
|
|
||||||
if not package:gitref() and package:version():lt("1.84") then
|
|
||||||
package:add("deps", "glad")
|
|
||||||
package:add("defines", "IMGUI_IMPL_OPENGL_LOADER_GLAD")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if package:config("sdl2_no_renderer") then
|
|
||||||
package:add("deps", "libsdl2")
|
|
||||||
end
|
|
||||||
if package:config("sdl2_renderer") then
|
|
||||||
package:add("deps", "libsdl2 >=2.0.17")
|
|
||||||
end
|
|
||||||
if package:config("sdl3") or package:config("sdl3_renderer") or package:config("sdl3_gpu") then
|
|
||||||
package:add("deps", "libsdl3")
|
|
||||||
end
|
|
||||||
if package:config("vulkan") then
|
|
||||||
package:add("deps", "vulkan-headers")
|
|
||||||
end
|
|
||||||
if package:config("wgpu") then
|
|
||||||
package:add("deps", "wgpu-native")
|
|
||||||
end
|
|
||||||
if package:config("freetype") then
|
|
||||||
package:add("deps", "freetype")
|
|
||||||
end
|
|
||||||
if package:config("osx") then
|
|
||||||
package:add("frameworks", "Cocoa", "Carbon", "GameController")
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
on_install(function (package)
|
|
||||||
local configs = {
|
|
||||||
dx9 = package:config("dx9"),
|
|
||||||
dx10 = package:config("dx10"),
|
|
||||||
dx11 = package:config("dx11"),
|
|
||||||
dx12 = package:config("dx12"),
|
|
||||||
glfw = package:config("glfw"),
|
|
||||||
opengl2 = package:config("opengl2"),
|
|
||||||
opengl3 = package:config("opengl3"),
|
|
||||||
glad = package:config("opengl3") and (not package:gitref() and package:version():lt("1.84")),
|
|
||||||
sdl2 = package:config("sdl2") or package:config("sdl2_no_renderer"),
|
|
||||||
sdl2_renderer = package:config("sdl2_renderer"),
|
|
||||||
sdl3 = package:config("sdl3"),
|
|
||||||
sdl3_renderer = package:config("sdl3_renderer"),
|
|
||||||
sdl3_gpu = package:config("sdl3_gpu"),
|
|
||||||
vulkan = package:config("vulkan"),
|
|
||||||
win32 = package:config("win32"),
|
|
||||||
osx = package:config("osx"),
|
|
||||||
wgpu = package:config("wgpu"),
|
|
||||||
freetype = package:config("freetype"),
|
|
||||||
user_config = package:config("user_config"),
|
|
||||||
wchar32 = package:config("wchar32")
|
|
||||||
}
|
|
||||||
|
|
||||||
os.cp(path.join(package:scriptdir(), "port", "xmake.lua"), "xmake.lua")
|
|
||||||
import("package.tools.xmake").install(package, configs)
|
|
||||||
end)
|
|
||||||
|
|
||||||
on_test(function (package)
|
|
||||||
if package:config("user_config") ~= nil then return end
|
|
||||||
local includes = {"imgui.h"}
|
|
||||||
local defines
|
|
||||||
if package:config("sdl2_renderer") or package:config("sdl2_no_renderer") then
|
|
||||||
table.insert(includes, "SDL.h")
|
|
||||||
defines = "SDL_MAIN_HANDLED"
|
|
||||||
end
|
|
||||||
assert(package:check_cxxsnippets({test = [[
|
|
||||||
void test() {
|
|
||||||
IMGUI_CHECKVERSION();
|
|
||||||
ImGui::CreateContext();
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
ImGui::NewFrame();
|
|
||||||
ImGui::Text("Hello, world!");
|
|
||||||
ImGui::ShowDemoWindow(NULL);
|
|
||||||
ImGui::Render();
|
|
||||||
ImGui::DestroyContext();
|
|
||||||
}
|
|
||||||
]]}, {configs = {languages = "c++14", defines = defines}, includes = includes}))
|
|
||||||
end)
|
|
||||||
1
thirdparty/minirtc
vendored
1
thirdparty/minirtc
vendored
Submodule thirdparty/minirtc deleted from dd3f6df18b
48
xmake.lua
48
xmake.lua
@@ -1,8 +1,11 @@
|
|||||||
set_project("crossdesk")
|
set_project("crossdesk")
|
||||||
set_license("LGPL-3.0")
|
set_license("LGPL-3.0")
|
||||||
|
|
||||||
set_version("0.0.1")
|
option("CROSSDESK_VERSION")
|
||||||
add_defines("RD_VERSION=\"0.0.1\"");
|
set_default("0.0.0")
|
||||||
|
set_showmenu(true)
|
||||||
|
set_description("Set CROSSDESK_VERSION for build")
|
||||||
|
option_end()
|
||||||
|
|
||||||
add_rules("mode.release", "mode.debug")
|
add_rules("mode.release", "mode.debug")
|
||||||
set_languages("c++17")
|
set_languages("c++17")
|
||||||
@@ -43,7 +46,7 @@ end
|
|||||||
|
|
||||||
add_packages("spdlog", "imgui")
|
add_packages("spdlog", "imgui")
|
||||||
|
|
||||||
includes("thirdparty")
|
includes("submodules")
|
||||||
|
|
||||||
target("rd_log")
|
target("rd_log")
|
||||||
set_kind("object")
|
set_kind("object")
|
||||||
@@ -120,26 +123,43 @@ target("device_controller")
|
|||||||
"src/device_controller/keyboard/linux", {public = true})
|
"src/device_controller/keyboard/linux", {public = true})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
target("thumbnail")
|
||||||
|
set_kind("object")
|
||||||
|
add_packages("libyuv", "openssl3")
|
||||||
|
add_deps("rd_log", "common")
|
||||||
|
add_files("src/thumbnail/*.cpp")
|
||||||
|
add_includedirs("src/thumbnail", {public = true})
|
||||||
|
|
||||||
target("config_center")
|
target("config_center")
|
||||||
set_kind("object")
|
set_kind("object")
|
||||||
add_deps("rd_log")
|
add_deps("rd_log")
|
||||||
add_files("src/config_center/*.cpp")
|
add_files("src/config_center/*.cpp")
|
||||||
add_includedirs("src/config_center", {public = true})
|
add_includedirs("src/config_center", {public = true})
|
||||||
|
|
||||||
target("localization")
|
target("assets")
|
||||||
set_kind("headeronly")
|
set_kind("headeronly")
|
||||||
add_includedirs("src/localization", {public = true})
|
add_includedirs("src/gui/assets/localization",
|
||||||
|
"src/gui/assets/fonts",
|
||||||
|
"src/gui/assets/icons",
|
||||||
|
"src/gui/assets/layouts", {public = true})
|
||||||
|
|
||||||
target("single_window")
|
target("gui")
|
||||||
set_kind("object")
|
set_kind("object")
|
||||||
add_packages("libyuv", "openssl3")
|
add_packages("libyuv")
|
||||||
add_deps("rd_log", "common", "localization", "config_center", "minirtc",
|
add_defines("CROSSDESK_VERSION=\"" .. (get_config("CROSSDESK_VERSION") or "Unknown") .. "\"")
|
||||||
"path_manager", "screen_capturer", "speaker_capturer", "device_controller")
|
add_deps("rd_log", "common", "assets", "config_center", "minirtc",
|
||||||
add_files("src/single_window/*.cpp")
|
"path_manager", "screen_capturer", "speaker_capturer",
|
||||||
add_includedirs("src/single_window", {public = true})
|
"device_controller", "thumbnail")
|
||||||
add_includedirs("fonts", {public = true})
|
add_files("src/gui/*.cpp", "src/gui/panels/*.cpp", "src/gui/toolbars/*.cpp",
|
||||||
|
"src/gui/windows/*.cpp")
|
||||||
|
add_includedirs("src/gui", "src/gui/panels", "src/gui/toolbars",
|
||||||
|
"src/gui/windows", {public = true})
|
||||||
|
if is_os("windows") then
|
||||||
|
add_files("src/gui/tray/*.cpp")
|
||||||
|
add_includedirs("src/gui/tray", {public = true})
|
||||||
|
end
|
||||||
|
|
||||||
target("crossdesk")
|
target("crossdesk")
|
||||||
set_kind("binary")
|
set_kind("binary")
|
||||||
add_deps("rd_log", "common", "single_window")
|
add_deps("rd_log", "common", "gui")
|
||||||
add_files("src/gui/main.cpp")
|
add_files("src/app/main.cpp")
|
||||||
Reference in New Issue
Block a user