mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-12-17 04:26:47 +08:00
Compare commits
22 Commits
v1.0.2-bet
...
v1.0.4-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
538c17d182 | ||
|
|
2ad32ec2b4 | ||
|
|
b28f1dca81 | ||
|
|
6947f7e1c3 | ||
|
|
b1df10c0de | ||
|
|
3817b222fd | ||
|
|
910cc9b587 | ||
|
|
2ee3e93afe | ||
|
|
8875c6a6a1 | ||
|
|
28062f5574 | ||
|
|
017af3eea4 | ||
|
|
78eb069cc8 | ||
|
|
0d591f769d | ||
|
|
d4726355a7 | ||
|
|
b78c9cf7d1 | ||
|
|
b3132db785 | ||
|
|
43db021326 | ||
|
|
2c622bc76e | ||
|
|
b790c7d08e | ||
|
|
0ca90d2516 | ||
|
|
401bfe4483 | ||
|
|
3b34c26555 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -144,7 +144,7 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x64
|
||||
runner: macos-15-intel
|
||||
runner: macos-13
|
||||
cache-key: intel
|
||||
out-dir: ./build/macosx/x86_64/release/crossdesk
|
||||
package_script: ./scripts/macosx/pkg_x64.sh
|
||||
|
||||
12
.github/workflows/update-pages.yml
vendored
12
.github/workflows/update-pages.yml
vendored
@@ -31,11 +31,13 @@ jobs:
|
||||
- name: Update download links
|
||||
run: |
|
||||
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
|
||||
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-macos-arm64-[0-9]+\.[0-9]+\.[0-9]+\.pkg/crossdesk-macos-arm64-${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-linux-arm64-[0-9]+\.[0-9]+\.[0-9]+\.deb/crossdesk-linux-arm64-${VERSION_NUM}.deb/g" index.html
|
||||
echo "Updating download links to ${VERSION_NUM}"
|
||||
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-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-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-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
|
||||
run: |
|
||||
|
||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "thirdparty/minirtc"]
|
||||
path = thirdparty/minirtc
|
||||
[submodule "submodules/minirtc"]
|
||||
path = submodules/minirtc
|
||||
url = https://github.com/kunkundi/minirtc.git
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# CrossDesk
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[](https://www.gnu.org/licenses/lgpl-3.0)
|
||||
[](https://github.com/kunkundi/crossdesk/commits/self-hosted-server)
|
||||
[](https://github.com/kunkundi/crossdesk/actions)
|
||||
@@ -164,9 +164,9 @@ sudo docker run -d \
|
||||
|
||||
- CROSSDESK_SERVER_PORT:自托管服务使用的端口,对应 CrossDesk 客户端**自托管服务器配置**中填写的**服务器端口**
|
||||
|
||||
- COTURN_PORT: COTURN 服务使用的端口, 对应 CrossDesk 客户端**自托管服务器配置**中填写的**COTURN 服务端口**
|
||||
- COTURN_PORT: COTURN 服务使用的端口, 对应 CrossDesk 客户端**自托管服务器配置**中填写的**中继服务端口**
|
||||
|
||||
- MIN_PORT/MAX_PORT:COTURN 服务使用的端口范围
|
||||
- MIN_PORT/MAX_PORT:COTURN 服务使用的端口范围,例如:MIN_PORT=50000, MAX_PORT=60000,范围可根据客户端数量调整。
|
||||
|
||||
- /path/to/your/certs:证书文件目录
|
||||
|
||||
@@ -176,7 +176,7 @@ sudo docker run -d \
|
||||
|
||||
**注意**:
|
||||
- **/path/to/your/ 是示例路径,请替换为你自己的实际路径。挂载的目录必须事先创建好,否则容器会报错。**
|
||||
- **服务器需开放端口:3478/udp,3478/tcp,30000-60000/udp,CROSSDESK_SERVER_PORT/tcp,443/tcp。**
|
||||
- **服务器需开放端口:3478/udp,3478/tcp,MIN_PORT-MAX_PORT/udp,CROSSDESK_SERVER_PORT/tcp。**
|
||||
|
||||
## 证书文件
|
||||
客户端需加载根证书文件,服务端需加载服务器私钥和服务器证书文件。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# CrossDesk
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[](https://www.gnu.org/licenses/lgpl-3.0)
|
||||
[](https://github.com/kunkundi/crossdesk/commits/self-hosted-server)
|
||||
[](https://github.com/kunkundi/crossdesk/actions)
|
||||
@@ -169,9 +169,9 @@ The parameters you need to pay attention to are as follows:
|
||||
|
||||
- **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 **Coturn 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**.
|
||||
- **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.
|
||||
|
||||
@@ -181,7 +181,7 @@ The parameters you need to pay attention to are as follows:
|
||||
|
||||
**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, 443/tcp.**
|
||||
- **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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifdef _WIN32
|
||||
#ifdef DESK_PORT_DEBUG
|
||||
#ifdef CROSSDESK_DEBUG
|
||||
#pragma comment(linker, "/subsystem:\"console\"")
|
||||
#else
|
||||
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
|
||||
@@ -9,8 +9,8 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
int main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) {
|
||||
Render render;
|
||||
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
|
||||
crossdesk::Render render;
|
||||
render.Run();
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class DisplayInfo {
|
||||
public:
|
||||
DisplayInfo(std::string name, int left, int top, int right, int bottom)
|
||||
@@ -40,5 +42,5 @@ class DisplayInfo {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
std::string GetMac() {
|
||||
char mac_addr[16];
|
||||
int len = 0;
|
||||
@@ -39,21 +41,21 @@ std::string GetMac() {
|
||||
#elif __APPLE__
|
||||
std::string if_name = "en0";
|
||||
|
||||
struct ifaddrs *addrs;
|
||||
struct ifaddrs *cursor;
|
||||
const struct sockaddr_dl *dlAddr;
|
||||
struct ifaddrs* addrs;
|
||||
struct ifaddrs* cursor;
|
||||
const struct sockaddr_dl* dlAddr;
|
||||
|
||||
if (!getifaddrs(&addrs)) {
|
||||
cursor = addrs;
|
||||
while (cursor != 0) {
|
||||
const struct sockaddr_dl *socAddr =
|
||||
(const struct sockaddr_dl *)cursor->ifa_addr;
|
||||
const struct sockaddr_dl* socAddr =
|
||||
(const struct sockaddr_dl*)cursor->ifa_addr;
|
||||
if ((cursor->ifa_addr->sa_family == AF_LINK) &&
|
||||
(socAddr->sdl_type == IFT_ETHER) &&
|
||||
strcmp(if_name.c_str(), cursor->ifa_name) == 0) {
|
||||
dlAddr = (const struct sockaddr_dl *)cursor->ifa_addr;
|
||||
const unsigned char *base =
|
||||
(const unsigned char *)&dlAddr->sdl_data[dlAddr->sdl_nlen];
|
||||
dlAddr = (const struct sockaddr_dl*)cursor->ifa_addr;
|
||||
const unsigned char* base =
|
||||
(const unsigned char*)&dlAddr->sdl_data[dlAddr->sdl_nlen];
|
||||
for (int i = 0; i < dlAddr->sdl_alen; i++) {
|
||||
len +=
|
||||
snprintf(mac_addr + len, sizeof(mac_addr) - len, "%.2X", base[i]);
|
||||
@@ -77,8 +79,8 @@ std::string GetMac() {
|
||||
close(sock);
|
||||
return "";
|
||||
}
|
||||
struct ifreq *it = ifc.ifc_req;
|
||||
const struct ifreq *const end = it + (ifc.ifc_len / sizeof(struct ifreq));
|
||||
struct ifreq* it = ifc.ifc_req;
|
||||
const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
|
||||
for (; it != end; ++it) {
|
||||
std::strcpy(ifr.ifr_name, it->ifr_name);
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
@@ -122,4 +124,5 @@ std::string GetHostName() {
|
||||
}
|
||||
#endif
|
||||
return hostname;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -9,7 +9,10 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
std::string GetMac();
|
||||
std::string GetHostName();
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "config_center.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
ConfigCenter::ConfigCenter(const std::string& config_path,
|
||||
const std::string& cert_file_path)
|
||||
: config_path_(config_path),
|
||||
@@ -36,9 +38,12 @@ int ConfigCenter::Load() {
|
||||
|
||||
enable_turn_ = ini_.GetBoolValue(section_, "enable_turn", enable_turn_);
|
||||
enable_srtp_ = ini_.GetBoolValue(section_, "enable_srtp", enable_srtp_);
|
||||
server_host_ = ini_.GetValue(section_, "server_host", server_host_.c_str());
|
||||
server_port_ = static_cast<int>(
|
||||
ini_.GetLongValue(section_, "server_port", server_port_));
|
||||
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_ =
|
||||
@@ -61,8 +66,9 @@ int ConfigCenter::Save() {
|
||||
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_, "server_host", server_host_.c_str());
|
||||
ini_.SetLongValue(section_, "server_port", static_cast<long>(server_port_));
|
||||
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",
|
||||
@@ -152,9 +158,9 @@ int ConfigCenter::SetSrtp(bool enable_srtp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConfigCenter::SetServerHost(const std::string& server_host) {
|
||||
server_host_ = server_host;
|
||||
ini_.SetValue(section_, "server_host", server_host_.c_str());
|
||||
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;
|
||||
@@ -162,9 +168,21 @@ int ConfigCenter::SetServerHost(const std::string& server_host) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConfigCenter::SetServerPort(int server_port) {
|
||||
server_port_ = server_port;
|
||||
ini_.SetLongValue(section_, "server_port", static_cast<long>(server_port_));
|
||||
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;
|
||||
ini_.SetLongValue(section_, "coturn_server_port",
|
||||
static_cast<long>(coturn_server_port_));
|
||||
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
@@ -184,6 +202,7 @@ int ConfigCenter::SetCertFilePath(const std::string& cert_file_path) {
|
||||
|
||||
int ConfigCenter::SetSelfHosted(bool enable_self_hosted) {
|
||||
enable_self_hosted_ = enable_self_hosted;
|
||||
ini_.SetBoolValue(section_, "enable_self_hosted", enable_self_hosted_);
|
||||
SI_Error rc = ini_.SaveFile(config_path_.c_str());
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
@@ -193,6 +212,12 @@ int ConfigCenter::SetSelfHosted(bool enable_self_hosted) {
|
||||
|
||||
int ConfigCenter::SetMinimizeToTray(bool enable_minimize_to_tray) {
|
||||
enable_minimize_to_tray_ = enable_minimize_to_tray;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -220,17 +245,27 @@ bool ConfigCenter::IsEnableTurn() const { return enable_turn_; }
|
||||
|
||||
bool ConfigCenter::IsEnableSrtp() const { return enable_srtp_; }
|
||||
|
||||
std::string ConfigCenter::GetServerHost() const { return server_host_; }
|
||||
std::string ConfigCenter::GetSignalServerHost() const {
|
||||
return signal_server_host_;
|
||||
}
|
||||
|
||||
int ConfigCenter::GetServerPort() const { return server_port_; }
|
||||
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 server_host_default_;
|
||||
return signal_server_host_default_;
|
||||
}
|
||||
|
||||
int ConfigCenter::GetDefaultServerPort() const { return server_port_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_;
|
||||
@@ -238,4 +273,5 @@ std::string ConfigCenter::GetDefaultCertFilePath() const {
|
||||
|
||||
bool ConfigCenter::IsSelfHosted() const { return enable_self_hosted_; }
|
||||
|
||||
bool ConfigCenter::IsMinimizeToTray() const { return enable_minimize_to_tray_; }
|
||||
bool ConfigCenter::IsMinimizeToTray() const { return enable_minimize_to_tray_; }
|
||||
} // namespace crossdesk
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "SimpleIni.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class ConfigCenter {
|
||||
public:
|
||||
enum class LANGUAGE { CHINESE = 0, ENGLISH = 1 };
|
||||
@@ -32,8 +34,9 @@ class ConfigCenter {
|
||||
int SetHardwareVideoCodec(bool hardware_video_codec);
|
||||
int SetTurn(bool enable_turn);
|
||||
int SetSrtp(bool enable_srtp);
|
||||
int SetServerHost(const std::string& server_host);
|
||||
int SetServerPort(int server_port);
|
||||
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);
|
||||
@@ -47,11 +50,13 @@ class ConfigCenter {
|
||||
bool IsHardwareVideoCodec() const;
|
||||
bool IsEnableTurn() const;
|
||||
bool IsEnableSrtp() const;
|
||||
std::string GetServerHost() const;
|
||||
int GetServerPort() const;
|
||||
std::string GetSignalServerHost() const;
|
||||
int GetSignalServerPort() const;
|
||||
int GetCoturnServerPort() const;
|
||||
std::string GetCertFilePath() const;
|
||||
std::string GetDefaultServerHost() const;
|
||||
int GetDefaultServerPort() const;
|
||||
int GetDefaultSignalServerPort() const;
|
||||
int GetDefaultCoturnServerPort() const;
|
||||
std::string GetDefaultCertFilePath() const;
|
||||
bool IsSelfHosted() const;
|
||||
bool IsMinimizeToTray() const;
|
||||
@@ -67,18 +72,20 @@ class ConfigCenter {
|
||||
|
||||
LANGUAGE language_ = LANGUAGE::CHINESE;
|
||||
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_60;
|
||||
VIDEO_ENCODE_FORMAT video_encode_format_ = VIDEO_ENCODE_FORMAT::H264;
|
||||
bool hardware_video_codec_ = false;
|
||||
bool enable_turn_ = false;
|
||||
bool enable_srtp_ = false;
|
||||
std::string server_host_ = "api.crossdesk.cn";
|
||||
int server_port_ = 9099;
|
||||
std::string server_host_default_ = "api.crossdesk.cn";
|
||||
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
|
||||
@@ -9,7 +9,13 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
|
||||
#include "display_info.h"
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
typedef enum {
|
||||
mouse = 0,
|
||||
@@ -53,7 +59,7 @@ typedef struct {
|
||||
int* bottom;
|
||||
} HostInfo;
|
||||
|
||||
typedef struct {
|
||||
struct RemoteAction {
|
||||
ControlType type;
|
||||
union {
|
||||
Mouse m;
|
||||
@@ -62,7 +68,111 @@ typedef struct {
|
||||
bool a;
|
||||
int d;
|
||||
};
|
||||
} RemoteAction;
|
||||
|
||||
// parse
|
||||
std::string to_json() const { return ToJson(*this); }
|
||||
|
||||
bool from_json(const std::string& json_str) {
|
||||
RemoteAction temp;
|
||||
if (!FromJson(json_str, temp)) return false;
|
||||
*this = temp;
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string ToJson(const RemoteAction& a) {
|
||||
json j;
|
||||
j["type"] = a.type;
|
||||
switch (a.type) {
|
||||
case ControlType::mouse:
|
||||
j["mouse"] = {
|
||||
{"x", a.m.x}, {"y", a.m.y}, {"s", a.m.s}, {"flag", a.m.flag}};
|
||||
break;
|
||||
case ControlType::keyboard:
|
||||
j["keyboard"] = {{"key_value", a.k.key_value}, {"flag", a.k.flag}};
|
||||
break;
|
||||
case ControlType::audio_capture:
|
||||
j["audio_capture"] = a.a;
|
||||
break;
|
||||
case ControlType::display_id:
|
||||
j["display_id"] = a.d;
|
||||
break;
|
||||
case ControlType::host_infomation: {
|
||||
json displays = json::array();
|
||||
for (size_t idx = 0; idx < a.i.display_num; idx++) {
|
||||
displays.push_back(
|
||||
{{"name", a.i.display_list ? a.i.display_list[idx] : ""},
|
||||
{"left", a.i.left ? a.i.left[idx] : 0},
|
||||
{"top", a.i.top ? a.i.top[idx] : 0},
|
||||
{"right", a.i.right ? a.i.right[idx] : 0},
|
||||
{"bottom", a.i.bottom ? a.i.bottom[idx] : 0}});
|
||||
}
|
||||
|
||||
j["host_info"] = {{"host_name", a.i.host_name},
|
||||
{"display_num", a.i.display_num},
|
||||
{"displays", displays}};
|
||||
break;
|
||||
}
|
||||
}
|
||||
return j.dump();
|
||||
}
|
||||
|
||||
static bool FromJson(const std::string& json_str, RemoteAction& out) {
|
||||
try {
|
||||
json j = json::parse(json_str);
|
||||
out.type = (ControlType)j.at("type").get<int>();
|
||||
switch (out.type) {
|
||||
case ControlType::mouse:
|
||||
out.m.x = j.at("mouse").at("x").get<float>();
|
||||
out.m.y = j.at("mouse").at("y").get<float>();
|
||||
out.m.s = j.at("mouse").at("s").get<int>();
|
||||
out.m.flag = (MouseFlag)j.at("mouse").at("flag").get<int>();
|
||||
break;
|
||||
case ControlType::keyboard:
|
||||
out.k.key_value = j.at("keyboard").at("key_value").get<size_t>();
|
||||
out.k.flag = (KeyFlag)j.at("keyboard").at("flag").get<int>();
|
||||
break;
|
||||
case ControlType::audio_capture:
|
||||
out.a = j.at("audio_capture").get<bool>();
|
||||
break;
|
||||
case ControlType::display_id:
|
||||
out.d = j.at("display_id").get<int>();
|
||||
break;
|
||||
case ControlType::host_infomation: {
|
||||
std::string host_name =
|
||||
j.at("host_info").at("host_name").get<std::string>();
|
||||
strncpy(out.i.host_name, host_name.c_str(), sizeof(out.i.host_name));
|
||||
out.i.host_name[sizeof(out.i.host_name) - 1] = '\0';
|
||||
out.i.host_name_size = host_name.size();
|
||||
|
||||
out.i.display_num = j.at("host_info").at("display_num").get<size_t>();
|
||||
auto displays = j.at("host_info").at("displays");
|
||||
|
||||
out.i.display_list =
|
||||
(char**)malloc(out.i.display_num * sizeof(char*));
|
||||
out.i.left = (int*)malloc(out.i.display_num * sizeof(int));
|
||||
out.i.top = (int*)malloc(out.i.display_num * sizeof(int));
|
||||
out.i.right = (int*)malloc(out.i.display_num * sizeof(int));
|
||||
out.i.bottom = (int*)malloc(out.i.display_num * sizeof(int));
|
||||
|
||||
for (size_t idx = 0; idx < out.i.display_num; idx++) {
|
||||
std::string name = displays[idx].at("name").get<std::string>();
|
||||
out.i.display_list[idx] = (char*)malloc(name.size() + 1);
|
||||
strcpy(out.i.display_list[idx], name.c_str());
|
||||
out.i.left[idx] = displays[idx].at("left").get<int>();
|
||||
out.i.top[idx] = displays[idx].at("top").get<int>();
|
||||
out.i.right[idx] = displays[idx].at("right").get<int>();
|
||||
out.i.bottom[idx] = displays[idx].at("bottom").get<int>();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
printf("Failed to parse RemoteAction JSON: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// int key_code, bool is_down
|
||||
typedef void (*OnKeyAction)(int, bool, void*);
|
||||
@@ -79,5 +189,5 @@ class DeviceController {
|
||||
// virtual int Hook();
|
||||
// virtual int Unhook();
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "keyboard_capturer.h"
|
||||
#include "mouse_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class DeviceControllerFactory {
|
||||
public:
|
||||
enum Device { Mouse = 0, Keyboard };
|
||||
@@ -30,5 +32,5 @@ class DeviceControllerFactory {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "keyboard_converter.h"
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
static OnKeyAction g_on_key_action = nullptr;
|
||||
static void* g_user_ptr = nullptr;
|
||||
|
||||
@@ -67,3 +69,4 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -13,20 +13,22 @@
|
||||
|
||||
#include "device_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class KeyboardCapturer : public DeviceController {
|
||||
public:
|
||||
KeyboardCapturer();
|
||||
virtual ~KeyboardCapturer();
|
||||
|
||||
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 SendKeyboardCommand(int key_code, bool is_down);
|
||||
|
||||
private:
|
||||
Display *display_;
|
||||
Display* display_;
|
||||
Window root_;
|
||||
bool running_;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -3,12 +3,14 @@
|
||||
#include "keyboard_converter.h"
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
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 event, void *userInfo) {
|
||||
KeyboardCapturer *keyboard_capturer = (KeyboardCapturer *)userInfo;
|
||||
CGEventRef event, void* userInfo) {
|
||||
KeyboardCapturer* keyboard_capturer = (KeyboardCapturer*)userInfo;
|
||||
if (!keyboard_capturer) {
|
||||
LOG_ERROR("keyboard_capturer is nullptr");
|
||||
return event;
|
||||
@@ -91,7 +93,7 @@ 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_user_ptr = user_ptr;
|
||||
|
||||
@@ -164,4 +166,5 @@ int KeyboardCapturer::SendKeyboardCommand(int key_code, bool is_down) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -11,13 +11,15 @@
|
||||
|
||||
#include "device_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class KeyboardCapturer : public DeviceController {
|
||||
public:
|
||||
KeyboardCapturer();
|
||||
virtual ~KeyboardCapturer();
|
||||
|
||||
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 SendKeyboardCommand(int key_code, bool is_down);
|
||||
|
||||
@@ -33,5 +35,5 @@ class KeyboardCapturer : public DeviceController {
|
||||
bool command_flag_ = false;
|
||||
int fn_key_code_ = 0x3F;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
static OnKeyAction g_on_key_action = 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));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -11,18 +11,21 @@
|
||||
|
||||
#include "device_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class KeyboardCapturer : public DeviceController {
|
||||
public:
|
||||
KeyboardCapturer();
|
||||
virtual ~KeyboardCapturer();
|
||||
|
||||
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 SendKeyboardCommand(int key_code, bool is_down);
|
||||
|
||||
private:
|
||||
HHOOK keyboard_hook_ = nullptr;
|
||||
};
|
||||
} // namespace crossdesk
|
||||
|
||||
#endif
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
// Windows vkCode to macOS CGKeyCode (104 keys)
|
||||
std::map<int, int> vkCodeToCGKeyCode = {
|
||||
// A-Z
|
||||
@@ -736,5 +738,5 @@ std::map<int, int> x11KeySymToCgKeyCode = {
|
||||
{0xFFEB, 0x37}, // Left Command
|
||||
{0xFFEC, 0x36}, // Right Command
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
MouseController::MouseController() {}
|
||||
|
||||
MouseController::~MouseController() { Destroy(); }
|
||||
@@ -121,4 +123,5 @@ void MouseController::SimulateMouseWheel(int direction_button, int count) {
|
||||
XTestFakeButtonEvent(display_, direction_button, False, CurrentTime);
|
||||
}
|
||||
XFlush(display_);
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "device_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class MouseController : public DeviceController {
|
||||
public:
|
||||
MouseController();
|
||||
@@ -37,5 +39,5 @@ class MouseController : public DeviceController {
|
||||
int screen_width_ = 0;
|
||||
int screen_height_ = 0;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
MouseController::MouseController() {}
|
||||
|
||||
MouseController::~MouseController() {}
|
||||
@@ -98,4 +100,5 @@ int MouseController::SendMouseCommand(RemoteAction remote_action,
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "device_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class MouseController : public DeviceController {
|
||||
public:
|
||||
MouseController();
|
||||
@@ -26,5 +28,5 @@ class MouseController : public DeviceController {
|
||||
bool left_dragging_ = false;
|
||||
bool right_dragging_ = false;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
MouseController::MouseController() {}
|
||||
|
||||
MouseController::~MouseController() {}
|
||||
@@ -69,4 +71,5 @@ int MouseController::SendMouseCommand(RemoteAction remote_action,
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "device_controller.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class MouseController : public DeviceController {
|
||||
public:
|
||||
MouseController();
|
||||
@@ -24,5 +26,5 @@ class MouseController : public DeviceController {
|
||||
private:
|
||||
std::vector<DisplayInfo> display_info_list_;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,8 +29,8 @@
|
||||
#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 165
|
||||
#define SELF_HOSTED_SERVER_CONFIG_WINDOW_HEIGHT_EN 165
|
||||
#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
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#if _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
namespace localization {
|
||||
|
||||
static std::vector<std::string> local_desktop = {
|
||||
@@ -106,7 +109,9 @@ static std::vector<std::string> 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"服务器端口:"), "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 = {
|
||||
@@ -167,4 +172,5 @@ static std::vector<std::string> minimize_to_tray = {
|
||||
static std::vector<LPCWSTR> exit_program = {L"退出", L"Exit"};
|
||||
#endif
|
||||
} // namespace localization
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
int Render::LocalWindow() {
|
||||
ImGui::SetNextWindowPos(ImVec2(-1.0f, title_bar_height_), ImGuiCond_Always);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
|
||||
@@ -287,4 +289,5 @@ int Render::LocalWindow() {
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
int Render::RecentConnectionsWindow() {
|
||||
ImGui::SetNextWindowPos(
|
||||
ImVec2(0, title_bar_height_ + local_window_height_ - 1.0f),
|
||||
@@ -284,3 +286,4 @@ int Render::ConfirmDeleteConnection() {
|
||||
ImGui::PopStyleVar();
|
||||
return 0;
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -3,7 +3,9 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
static int InputTextCallback(ImGuiInputTextCallbackData *data);
|
||||
namespace crossdesk {
|
||||
|
||||
static int InputTextCallback(ImGuiInputTextCallbackData* data);
|
||||
|
||||
int Render::RemoteWindow() {
|
||||
ImGui::SetNextWindowPos(ImVec2(local_window_width_ + 1.0f, title_bar_height_),
|
||||
@@ -77,7 +79,7 @@ int Render::RemoteWindow() {
|
||||
enter_pressed) {
|
||||
connect_button_pressed_ = true;
|
||||
bool found = false;
|
||||
for (auto &[id, props] : recent_connections_) {
|
||||
for (auto& [id, props] : recent_connections_) {
|
||||
if (id.find(remote_id) != std::string::npos) {
|
||||
found = true;
|
||||
if (client_properties_.find(remote_id) !=
|
||||
@@ -101,7 +103,7 @@ int Render::RemoteWindow() {
|
||||
|
||||
if (need_to_rejoin_) {
|
||||
need_to_rejoin_ = false;
|
||||
for (const auto &[_, props] : client_properties_) {
|
||||
for (const auto& [_, props] : client_properties_) {
|
||||
if (props->rejoin_) {
|
||||
ConnectTo(props->remote_id_, props->remote_password_,
|
||||
props->remember_password_);
|
||||
@@ -117,7 +119,7 @@ int Render::RemoteWindow() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int InputTextCallback(ImGuiInputTextCallbackData *data) {
|
||||
static int InputTextCallback(ImGuiInputTextCallbackData* data) {
|
||||
if (data->BufTextLen > 3 && data->Buf[3] != ' ') {
|
||||
data->InsertChars(3, " ");
|
||||
}
|
||||
@@ -129,7 +131,7 @@ static int InputTextCallback(ImGuiInputTextCallbackData *data) {
|
||||
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) {
|
||||
LOG_INFO("Connect to [{}]", remote_id);
|
||||
focused_remote_id_ = remote_id;
|
||||
@@ -143,6 +145,10 @@ int Render::ConnectTo(const std::string &remote_id, const char *password,
|
||||
memcpy(&props->params_, ¶ms_, sizeof(Params));
|
||||
props->params_.user_id = props->local_id_.c_str();
|
||||
props->peer_ = CreatePeer(&props->params_);
|
||||
|
||||
for (auto& display_info : display_info_list_) {
|
||||
AddVideoStream(peer_, display_info.name.c_str());
|
||||
}
|
||||
AddAudioStream(props->peer_, props->audio_label_.c_str());
|
||||
AddDataStream(props->peer_, props->data_label_.c_str());
|
||||
|
||||
@@ -178,4 +184,5 @@ int Render::ConnectTo(const std::string &remote_id, const char *password,
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#define MOUSE_GRAB_PADDING 5
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
std::vector<char> Render::SerializeRemoteAction(const RemoteAction& action) {
|
||||
std::vector<char> buffer;
|
||||
buffer.push_back(static_cast<char>(action.type));
|
||||
@@ -256,6 +258,7 @@ int Render::LoadSettingsFromCacheFile() {
|
||||
enable_hardware_video_codec_ = config_center_->IsHardwareVideoCodec();
|
||||
enable_turn_ = config_center_->IsEnableTurn();
|
||||
enable_srtp_ = config_center_->IsEnableSrtp();
|
||||
enable_self_hosted_ = config_center_->IsSelfHosted();
|
||||
|
||||
language_button_value_last_ = language_button_value_;
|
||||
video_quality_button_value_last_ = video_quality_button_value_;
|
||||
@@ -263,6 +266,7 @@ int Render::LoadSettingsFromCacheFile() {
|
||||
enable_hardware_video_codec_last_ = enable_hardware_video_codec_;
|
||||
enable_turn_last_ = enable_turn_;
|
||||
enable_srtp_last_ = enable_srtp_;
|
||||
enable_self_hosted_last_ = enable_self_hosted_;
|
||||
|
||||
LOG_INFO("Load settings from cache file");
|
||||
|
||||
@@ -427,39 +431,57 @@ int Render::StopKeyboardCapturer() {
|
||||
int Render::CreateConnectionPeer() {
|
||||
params_.use_cfg_file = false;
|
||||
|
||||
std::string server_ip;
|
||||
int server_port;
|
||||
std::string server_cert_path;
|
||||
std::string signal_server_ip;
|
||||
int signal_server_port;
|
||||
int coturn_server_port;
|
||||
std::string tls_cert_path;
|
||||
|
||||
if (config_center_->IsSelfHosted()) {
|
||||
server_ip = config_center_->GetServerHost();
|
||||
server_port = config_center_->GetServerPort();
|
||||
server_cert_path = config_center_->GetCertFilePath();
|
||||
signal_server_ip = config_center_->GetSignalServerHost();
|
||||
signal_server_port = config_center_->GetSignalServerPort();
|
||||
coturn_server_port = config_center_->GetCoturnServerPort();
|
||||
tls_cert_path = config_center_->GetCertFilePath();
|
||||
} else {
|
||||
server_ip = config_center_->GetDefaultServerHost();
|
||||
server_port = config_center_->GetDefaultServerPort();
|
||||
server_cert_path = config_center_->GetDefaultCertFilePath();
|
||||
signal_server_ip = config_center_->GetDefaultServerHost();
|
||||
signal_server_port = config_center_->GetDefaultSignalServerPort();
|
||||
coturn_server_port = config_center_->GetDefaultCoturnServerPort();
|
||||
tls_cert_path = config_center_->GetDefaultCertFilePath();
|
||||
}
|
||||
|
||||
strncpy((char*)params_.signal_server_ip, server_ip.c_str(),
|
||||
// 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 = server_port;
|
||||
strncpy((char*)params_.stun_server_ip, server_ip.c_str(),
|
||||
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 = 3478;
|
||||
strncpy((char*)params_.turn_server_ip, server_ip.c_str(),
|
||||
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 = 3478;
|
||||
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, server_cert_path.c_str(),
|
||||
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';
|
||||
|
||||
@@ -473,6 +495,8 @@ int Render::CreateConnectionPeer() {
|
||||
: false;
|
||||
params_.enable_turn = config_center_->IsEnableTurn();
|
||||
params_.enable_srtp = config_center_->IsEnableSrtp();
|
||||
params_.video_quality =
|
||||
static_cast<VideoQuality>(config_center_->GetVideoQuality());
|
||||
params_.on_receive_video_buffer = nullptr;
|
||||
params_.on_receive_audio_buffer = OnReceiveAudioBufferCb;
|
||||
params_.on_receive_data_buffer = OnReceiveDataBufferCb;
|
||||
@@ -544,6 +568,14 @@ void Render::UpdateInteractions() {
|
||||
screen_capturer_is_started_ = false;
|
||||
}
|
||||
|
||||
if (start_speaker_capturer_ && !speaker_capturer_is_started_) {
|
||||
StartSpeakerCapturer();
|
||||
speaker_capturer_is_started_ = true;
|
||||
} else if (!start_speaker_capturer_ && speaker_capturer_is_started_) {
|
||||
StopSpeakerCapturer();
|
||||
speaker_capturer_is_started_ = false;
|
||||
}
|
||||
|
||||
if (start_mouse_controller_ && !mouse_controller_is_started_) {
|
||||
StartMouseController();
|
||||
mouse_controller_is_started_ = true;
|
||||
@@ -883,13 +915,14 @@ int Render::Run() {
|
||||
cache_path_ = path_manager_->GetCachePath().string();
|
||||
config_center_ =
|
||||
std::make_unique<ConfigCenter>(cache_path_ + "/config.ini", cert_path_);
|
||||
strncpy(signal_server_ip_tmp_, config_center_->GetServerHost().c_str(),
|
||||
sizeof(signal_server_ip_tmp_) - 1);
|
||||
signal_server_ip_tmp_[sizeof(signal_server_ip_tmp_) - 1] = '\0';
|
||||
strncpy(signal_server_port_tmp_,
|
||||
std::to_string(config_center_->GetServerPort()).c_str(),
|
||||
sizeof(signal_server_port_tmp_) - 1);
|
||||
signal_server_port_tmp_[sizeof(signal_server_port_tmp_) - 1] = '\0';
|
||||
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 {
|
||||
@@ -1032,9 +1065,9 @@ void Render::MainLoop() {
|
||||
remote_action.i.host_name[host_name.size()] = '\0';
|
||||
remote_action.i.host_name_size = host_name.size();
|
||||
|
||||
std::vector<char> serialized = SerializeRemoteAction(remote_action);
|
||||
int ret = SendDataFrame(peer_, serialized.data(), serialized.size(),
|
||||
data_label_.c_str());
|
||||
std::string msg = remote_action.to_json();
|
||||
int ret =
|
||||
SendDataFrame(peer_, msg.data(), msg.size(), data_label_.c_str());
|
||||
FreeRemoteAction(remote_action);
|
||||
if (0 == ret) {
|
||||
need_to_send_host_info_ = false;
|
||||
@@ -1160,6 +1193,10 @@ void Render::CleanupPeers() {
|
||||
LOG_INFO("[{}] Leave connection [{}]", client_id_, client_id_);
|
||||
LeaveConnection(peer_, client_id_);
|
||||
is_client_mode_ = false;
|
||||
StopScreenCapturer();
|
||||
StopSpeakerCapturer();
|
||||
StopMouseController();
|
||||
StopKeyboardCapturer();
|
||||
LOG_INFO("Destroy peer [{}]", client_id_);
|
||||
DestroyPeer(&peer_);
|
||||
}
|
||||
@@ -1412,4 +1449,5 @@ void Render::ProcessSdlEvent(const SDL_Event& event) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "win_tray.h"
|
||||
#endif
|
||||
|
||||
namespace crossdesk {
|
||||
class Render {
|
||||
public:
|
||||
struct SubStreamWindowProperties {
|
||||
@@ -48,10 +49,10 @@ class Render {
|
||||
bool connection_established_ = false;
|
||||
bool rejoin_ = false;
|
||||
bool net_traffic_stats_button_pressed_ = false;
|
||||
bool mouse_control_button_pressed_ = false;
|
||||
bool mouse_control_button_pressed_ = true;
|
||||
bool mouse_controller_is_started_ = false;
|
||||
bool audio_capture_button_pressed_ = false;
|
||||
bool control_mouse_ = false;
|
||||
bool audio_capture_button_pressed_ = true;
|
||||
bool control_mouse_ = true;
|
||||
bool streaming_ = false;
|
||||
bool is_control_bar_in_left_ = true;
|
||||
bool control_bar_hovered_ = false;
|
||||
@@ -310,7 +311,9 @@ class Render {
|
||||
bool mouse_controller_is_started_ = false;
|
||||
bool start_screen_capturer_ = false;
|
||||
bool screen_capturer_is_started_ = false;
|
||||
bool start_keyboard_capturer_ = false;
|
||||
bool start_speaker_capturer_ = false;
|
||||
bool speaker_capturer_is_started_ = false;
|
||||
bool start_keyboard_capturer_ = true;
|
||||
bool keyboard_capturer_is_started_ = false;
|
||||
bool foucs_on_main_window_ = false;
|
||||
bool foucs_on_stream_window_ = false;
|
||||
@@ -435,29 +438,33 @@ class Render {
|
||||
char password_saved_[7] = "";
|
||||
int language_button_value_ = 0;
|
||||
int video_quality_button_value_ = 0;
|
||||
int video_frame_rate_button_value_ = 0;
|
||||
int video_frame_rate_button_value_ = 1;
|
||||
int video_encode_format_button_value_ = 0;
|
||||
bool enable_hardware_video_codec_ = false;
|
||||
bool enable_turn_ = 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;
|
||||
bool enable_self_hosted_ = false;
|
||||
int language_button_value_last_ = 0;
|
||||
int video_quality_button_value_last_ = 0;
|
||||
int video_frame_rate_button_value_last_ = 0;
|
||||
int video_encode_format_button_value_last_ = 0;
|
||||
bool enable_hardware_video_codec_last_ = false;
|
||||
bool enable_turn_last_ = false;
|
||||
bool enable_srtp_last_ = false;
|
||||
bool enable_self_hosted_last_ = false;
|
||||
bool enable_minimize_to_tray_ = false;
|
||||
bool enable_minimize_to_tray_last_ = false;
|
||||
char signal_server_ip_tmp_[256] = "api.crossdesk.cn";
|
||||
char signal_server_port_tmp_[6] = "9099";
|
||||
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 self_hosted_server_config_window_pos_reset_ = true;
|
||||
std::string selected_current_file_path_ = "";
|
||||
std::string selected_file_ = "";
|
||||
bool show_file_browser_ = true;
|
||||
/* ------ main window property end ------ */
|
||||
|
||||
@@ -466,6 +473,9 @@ class Render {
|
||||
client_properties_;
|
||||
void CloseTab(decltype(client_properties_)::iterator& it);
|
||||
/* ------ stream window property end ------ */
|
||||
};
|
||||
|
||||
/* ------ server mode ------ */
|
||||
std::unordered_map<std::string, ConnectionStatus> connection_status_;
|
||||
};
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -6,10 +6,7 @@
|
||||
|
||||
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
|
||||
|
||||
#ifdef DESK_PORT_DEBUG
|
||||
#else
|
||||
#define MOUSE_CONTROL 1
|
||||
#endif
|
||||
namespace crossdesk {
|
||||
|
||||
int Render::SendKeyCommand(int key_code, bool is_down) {
|
||||
RemoteAction remote_action;
|
||||
@@ -26,8 +23,9 @@ int Render::SendKeyCommand(int key_code, bool is_down) {
|
||||
client_properties_.end()) {
|
||||
auto props = client_properties_[controlled_remote_id_];
|
||||
if (props->connection_status_ == ConnectionStatus::Connected) {
|
||||
SendDataFrame(props->peer_, (const char*)&remote_action,
|
||||
sizeof(remote_action), props->data_label_.c_str());
|
||||
std::string msg = remote_action.to_json();
|
||||
SendDataFrame(props->peer_, msg.c_str(), msg.size(),
|
||||
props->data_label_.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,8 +90,10 @@ int Render::ProcessMouseEvent(const SDL_Event& event) {
|
||||
if (props->control_bar_hovered_ || props->display_selectable_hovered_) {
|
||||
remote_action.m.flag = MouseFlag::move;
|
||||
}
|
||||
SendDataFrame(props->peer_, (const char*)&remote_action,
|
||||
sizeof(remote_action), props->data_label_.c_str());
|
||||
|
||||
std::string msg = remote_action.to_json();
|
||||
SendDataFrame(props->peer_, msg.c_str(), msg.size(),
|
||||
props->data_label_.c_str());
|
||||
} else if (SDL_EVENT_MOUSE_WHEEL == event.type &&
|
||||
last_mouse_event.button.x >= props->stream_render_rect_.x &&
|
||||
last_mouse_event.button.x <= props->stream_render_rect_.x +
|
||||
@@ -125,8 +125,9 @@ int Render::ProcessMouseEvent(const SDL_Event& event) {
|
||||
(float)(event.button.y - props->stream_render_rect_.y) /
|
||||
render_height;
|
||||
|
||||
SendDataFrame(props->peer_, (const char*)&remote_action,
|
||||
sizeof(remote_action), props->data_label_.c_str());
|
||||
std::string msg = remote_action.to_json();
|
||||
SendDataFrame(props->peer_, msg.c_str(), msg.size(),
|
||||
props->data_label_.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +225,8 @@ void Render::OnReceiveVideoBufferCb(const XVideoFrame* video_frame,
|
||||
props->video_height_ = video_frame->height;
|
||||
props->video_size_ = video_frame->size;
|
||||
|
||||
LOG_ERROR("receive: {}x{}", props->video_width_, props->video_height_);
|
||||
|
||||
if (need_to_update_render_rect) {
|
||||
render->UpdateRenderRect();
|
||||
}
|
||||
@@ -277,64 +280,54 @@ void Render::OnReceiveDataBufferCb(const char* data, size_t size,
|
||||
return;
|
||||
}
|
||||
|
||||
std::string json_str(data, size);
|
||||
RemoteAction remote_action;
|
||||
memcpy(&remote_action, data, size);
|
||||
|
||||
try {
|
||||
remote_action.from_json(json_str);
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR("Failed to parse RemoteAction JSON: {}", e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
std::string remote_id(user_id, user_id_size);
|
||||
if (render->client_properties_.find(remote_id) !=
|
||||
render->client_properties_.end()) {
|
||||
// local
|
||||
auto props = render->client_properties_.find(remote_id)->second;
|
||||
RemoteAction host_info;
|
||||
if (DeserializeRemoteAction(data, size, host_info)) {
|
||||
if (ControlType::host_infomation == host_info.type &&
|
||||
props->remote_host_name_.empty()) {
|
||||
props->remote_host_name_ =
|
||||
std::string(host_info.i.host_name, host_info.i.host_name_size);
|
||||
LOG_INFO("Remote hostname: [{}]", props->remote_host_name_);
|
||||
|
||||
for (int i = 0; i < host_info.i.display_num; i++) {
|
||||
props->display_info_list_.push_back(DisplayInfo(
|
||||
std::string(host_info.i.display_list[i]), host_info.i.left[i],
|
||||
host_info.i.top[i], host_info.i.right[i], host_info.i.bottom[i]));
|
||||
LOG_INFO("Remote display [{}:{}], bound [({}, {}) ({}, {})]", i + 1,
|
||||
props->display_info_list_[i].name,
|
||||
props->display_info_list_[i].left,
|
||||
props->display_info_list_[i].top,
|
||||
props->display_info_list_[i].right,
|
||||
props->display_info_list_[i].bottom);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (remote_action.type == ControlType::host_infomation &&
|
||||
props->remote_host_name_.empty()) {
|
||||
props->remote_host_name_ = std::string(remote_action.i.host_name,
|
||||
remote_action.i.host_name_size);
|
||||
LOG_INFO("Remote hostname: [{}]", props->remote_host_name_);
|
||||
LOG_ERROR("No remote display detected");
|
||||
|
||||
for (int i = 0; i < remote_action.i.display_num; i++) {
|
||||
props->display_info_list_.push_back(
|
||||
DisplayInfo(remote_action.i.display_list[i],
|
||||
remote_action.i.left[i], remote_action.i.top[i],
|
||||
remote_action.i.right[i], remote_action.i.bottom[i]));
|
||||
}
|
||||
}
|
||||
FreeRemoteAction(host_info);
|
||||
FreeRemoteAction(remote_action);
|
||||
} else {
|
||||
// remote
|
||||
if (ControlType::mouse == remote_action.type && render->mouse_controller_) {
|
||||
if (remote_action.type == ControlType::mouse && render->mouse_controller_) {
|
||||
render->mouse_controller_->SendMouseCommand(remote_action,
|
||||
render->selected_display_);
|
||||
} else if (ControlType::audio_capture == remote_action.type) {
|
||||
if (remote_action.a) {
|
||||
} else if (remote_action.type == ControlType::audio_capture) {
|
||||
if (remote_action.a && !render->start_speaker_capturer_)
|
||||
render->StartSpeakerCapturer();
|
||||
render->audio_capture_ = true;
|
||||
} else {
|
||||
else if (!remote_action.a && render->start_speaker_capturer_)
|
||||
render->StopSpeakerCapturer();
|
||||
render->audio_capture_ = false;
|
||||
}
|
||||
} else if (ControlType::keyboard == remote_action.type &&
|
||||
} else if (remote_action.type == ControlType::keyboard &&
|
||||
render->keyboard_capturer_) {
|
||||
render->keyboard_capturer_->SendKeyboardCommand(
|
||||
(int)remote_action.k.key_value,
|
||||
remote_action.k.flag == KeyFlag::key_down);
|
||||
} else if (ControlType::display_id == remote_action.type) {
|
||||
if (render->screen_capturer_) {
|
||||
render->selected_display_ = remote_action.d;
|
||||
render->screen_capturer_->SwitchTo(remote_action.d);
|
||||
}
|
||||
} else if (remote_action.type == ControlType::display_id &&
|
||||
render->screen_capturer_) {
|
||||
render->selected_display_ = remote_action.d;
|
||||
render->screen_capturer_->SwitchTo(remote_action.d);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -407,7 +400,7 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char* user_id,
|
||||
props->connection_status_ = status;
|
||||
|
||||
switch (status) {
|
||||
case ConnectionStatus::Connected:
|
||||
case ConnectionStatus::Connected: {
|
||||
if (!render->need_to_create_stream_window_ &&
|
||||
!render->client_properties_.empty()) {
|
||||
render->need_to_create_stream_window_ = true;
|
||||
@@ -418,14 +411,10 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char* user_id,
|
||||
(int)render->stream_window_width_,
|
||||
(int)(render->stream_window_height_ - render->title_bar_height_)};
|
||||
break;
|
||||
}
|
||||
case ConnectionStatus::Disconnected:
|
||||
case ConnectionStatus::Failed:
|
||||
case ConnectionStatus::Closed:
|
||||
render->password_validating_time_ = 0;
|
||||
render->start_screen_capturer_ = false;
|
||||
render->start_mouse_controller_ = false;
|
||||
render->start_keyboard_capturer_ = false;
|
||||
render->control_mouse_ = false;
|
||||
case ConnectionStatus::Closed: {
|
||||
props->connection_established_ = false;
|
||||
props->mouse_control_button_pressed_ = false;
|
||||
if (props->dst_buffer_) {
|
||||
@@ -434,8 +423,10 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char* user_id,
|
||||
props->texture_width_);
|
||||
}
|
||||
render->CleanSubStreamWindowProperties(props);
|
||||
|
||||
break;
|
||||
case ConnectionStatus::IncorrectPassword:
|
||||
}
|
||||
case ConnectionStatus::IncorrectPassword: {
|
||||
render->password_validating_ = false;
|
||||
render->password_validating_time_++;
|
||||
if (render->connect_button_pressed_) {
|
||||
@@ -445,37 +436,58 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char* user_id,
|
||||
localization::connect[render->localization_language_index_];
|
||||
}
|
||||
break;
|
||||
case ConnectionStatus::NoSuchTransmissionId:
|
||||
}
|
||||
case ConnectionStatus::NoSuchTransmissionId: {
|
||||
if (render->connect_button_pressed_) {
|
||||
props->connection_established_ = false;
|
||||
render->connect_button_label_ =
|
||||
localization::connect[render->localization_language_index_];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
render->is_client_mode_ = false;
|
||||
render->show_connection_status_window_ = true;
|
||||
render->connection_status_[remote_id] = status;
|
||||
|
||||
switch (status) {
|
||||
case ConnectionStatus::Connected:
|
||||
case ConnectionStatus::Connected: {
|
||||
render->need_to_send_host_info_ = true;
|
||||
render->start_screen_capturer_ = true;
|
||||
render->start_mouse_controller_ = true;
|
||||
break;
|
||||
case ConnectionStatus::Closed:
|
||||
render->start_screen_capturer_ = false;
|
||||
render->start_speaker_capturer_ = true;
|
||||
#ifdef CROSSDESK_DEBUG
|
||||
render->start_mouse_controller_ = false;
|
||||
render->start_keyboard_capturer_ = false;
|
||||
render->need_to_send_host_info_ = false;
|
||||
if (props) props->connection_established_ = false;
|
||||
if (render->audio_capture_) {
|
||||
render->StopSpeakerCapturer();
|
||||
render->audio_capture_ = false;
|
||||
#else
|
||||
render->start_mouse_controller_ = true;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case ConnectionStatus::Closed: {
|
||||
if (std::all_of(render->connection_status_.begin(),
|
||||
render->connection_status_.end(), [](const auto& kv) {
|
||||
return kv.second == ConnectionStatus::Closed ||
|
||||
kv.second == ConnectionStatus::Failed ||
|
||||
kv.second == ConnectionStatus::Disconnected;
|
||||
})) {
|
||||
render->start_screen_capturer_ = false;
|
||||
render->start_speaker_capturer_ = false;
|
||||
render->start_mouse_controller_ = false;
|
||||
render->start_keyboard_capturer_ = false;
|
||||
render->need_to_send_host_info_ = false;
|
||||
if (props) props->connection_established_ = false;
|
||||
if (render->audio_capture_) {
|
||||
render->StopSpeakerCapturer();
|
||||
render->audio_capture_ = false;
|
||||
}
|
||||
|
||||
render->connection_status_.erase(remote_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -542,4 +554,5 @@ void Render::NetStatusReport(const char* client_id, size_t client_id_size,
|
||||
if (!(render->peer_reserved_ && !strstr(client_id, "C-"))) {
|
||||
props->net_traffic_stats_ = *net_traffic_stats;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
int CountDigits(int number) {
|
||||
if (number == 0) return 1;
|
||||
return (int)std::floor(std::log10(std::abs(number))) + 1;
|
||||
@@ -66,8 +68,9 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||
remote_action.type = ControlType::display_id;
|
||||
remote_action.d = i;
|
||||
if (props->connection_status_ == ConnectionStatus::Connected) {
|
||||
SendDataFrame(props->peer_, (const char*)&remote_action,
|
||||
sizeof(remote_action), props->data_label_.c_str());
|
||||
std::string msg = remote_action.to_json();
|
||||
SendDataFrame(props->peer_, msg.c_str(), msg.size(),
|
||||
props->data_label_.c_str());
|
||||
}
|
||||
}
|
||||
props->display_selectable_hovered_ = ImGui::IsWindowHovered();
|
||||
@@ -140,8 +143,9 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||
RemoteAction remote_action;
|
||||
remote_action.type = ControlType::audio_capture;
|
||||
remote_action.a = props->audio_capture_button_pressed_;
|
||||
SendDataFrame(props->peer_, (const char*)&remote_action,
|
||||
sizeof(remote_action), props->data_label_.c_str());
|
||||
std::string msg = remote_action.to_json();
|
||||
SendDataFrame(props->peer_, msg.c_str(), msg.size(),
|
||||
props->data_label_.c_str());
|
||||
}
|
||||
}
|
||||
if (!props->audio_capture_button_pressed_) {
|
||||
@@ -324,3 +328,4 @@ int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "localization.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
int Render::StatusBar() {
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
static bool a, b, c, d, e;
|
||||
@@ -35,4 +37,5 @@ int Render::StatusBar() {
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndChild();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#define BUTTON_PADDING 36.0f
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
int Render::TitleBar(bool main_window) {
|
||||
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));
|
||||
@@ -171,4 +173,5 @@ int Render::TitleBar(bool main_window) {
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleColor();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#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) {
|
||||
@@ -109,4 +111,5 @@ bool WinTray::HandleTrayMessage(MSG* msg) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#define WM_TRAY_CALLBACK (WM_USER + 1)
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class WinTray {
|
||||
public:
|
||||
WinTray(HWND app_hwnd, HICON icon, const std::wstring& tooltip,
|
||||
@@ -32,5 +34,5 @@ class WinTray {
|
||||
int language_index_;
|
||||
NOTIFYICONDATA nid_;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -3,9 +3,11 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
int Render::AboutWindow() {
|
||||
if (show_about_window_) {
|
||||
const ImGuiViewport *viewport = ImGui::GetMainViewport();
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(
|
||||
(viewport->WorkSize.x - viewport->WorkPos.x - about_window_width_) / 2,
|
||||
@@ -58,4 +60,5 @@ int Render::AboutWindow() {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -3,9 +3,11 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
bool Render::ConnectionStatusWindow(
|
||||
std::shared_ptr<SubStreamWindowProperties> &props) {
|
||||
const ImGuiViewport *viewport = ImGui::GetMainViewport();
|
||||
std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
bool ret_flag = false;
|
||||
ImGui::SetNextWindowPos(ImVec2((viewport->WorkSize.x - viewport->WorkPos.x -
|
||||
connection_status_window_width_) /
|
||||
@@ -168,4 +170,5 @@ bool Render::ConnectionStatusWindow(
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
return ret_flag;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "rd_log.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 =
|
||||
ImGui::GetTime() - props->control_bar_button_pressed_time_;
|
||||
if (props->control_window_width_is_changing_) {
|
||||
@@ -220,4 +222,5 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties> &props) {
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
int Render::SettingWindow() {
|
||||
if (show_settings_window_) {
|
||||
if (settings_window_pos_reset_) {
|
||||
@@ -80,11 +82,11 @@ int Render::SettingWindow() {
|
||||
|
||||
{
|
||||
const char* video_quality_items[] = {
|
||||
localization::video_quality_high[localization_language_index_]
|
||||
localization::video_quality_low[localization_language_index_]
|
||||
.c_str(),
|
||||
localization::video_quality_medium[localization_language_index_]
|
||||
.c_str(),
|
||||
localization::video_quality_low[localization_language_index_]
|
||||
localization::video_quality_high[localization_language_index_]
|
||||
.c_str()};
|
||||
|
||||
settings_items_offset += settings_items_padding;
|
||||
@@ -229,8 +231,7 @@ int Render::SettingWindow() {
|
||||
ImGui::SetCursorPosX(ENABLE_SELF_HOSTED_SERVER_CHECKBOX_PADDING_EN);
|
||||
}
|
||||
ImGui::SetCursorPosY(settings_items_offset);
|
||||
ImGui::Checkbox("##enable_self_hosted_server",
|
||||
&enable_self_hosted_server_);
|
||||
ImGui::Checkbox("##enable_self_hosted", &enable_self_hosted_);
|
||||
}
|
||||
#if _WIN32
|
||||
ImGui::Separator();
|
||||
@@ -287,14 +288,23 @@ int Render::SettingWindow() {
|
||||
|
||||
// Video quality
|
||||
if (video_quality_button_value_ == 0) {
|
||||
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::HIGH);
|
||||
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::LOW);
|
||||
} else if (video_quality_button_value_ == 1) {
|
||||
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::MEDIUM);
|
||||
} else {
|
||||
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::LOW);
|
||||
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::HIGH);
|
||||
}
|
||||
video_quality_button_value_last_ = video_quality_button_value_;
|
||||
|
||||
if (video_frame_rate_button_value_ == 0) {
|
||||
config_center_->SetVideoFrameRate(
|
||||
ConfigCenter::VIDEO_FRAME_RATE::FPS_30);
|
||||
} else if (video_frame_rate_button_value_ == 1) {
|
||||
config_center_->SetVideoFrameRate(
|
||||
ConfigCenter::VIDEO_FRAME_RATE::FPS_60);
|
||||
}
|
||||
video_frame_rate_button_value_last_ = video_frame_rate_button_value_;
|
||||
|
||||
// Video encode format
|
||||
if (video_encode_format_button_value_ == 0) {
|
||||
config_center_->SetVideoEncodeFormat(
|
||||
@@ -330,11 +340,12 @@ int Render::SettingWindow() {
|
||||
}
|
||||
enable_srtp_last_ = enable_srtp_;
|
||||
|
||||
if (enable_self_hosted_server_) {
|
||||
if (enable_self_hosted_) {
|
||||
config_center_->SetSelfHosted(true);
|
||||
} else {
|
||||
config_center_->SetSelfHosted(false);
|
||||
}
|
||||
enable_self_hosted_last_ = enable_self_hosted_;
|
||||
|
||||
settings_window_pos_reset_ = true;
|
||||
|
||||
@@ -364,6 +375,11 @@ int Render::SettingWindow() {
|
||||
video_quality_button_value_ = video_quality_button_value_last_;
|
||||
}
|
||||
|
||||
if (video_frame_rate_button_value_ !=
|
||||
video_frame_rate_button_value_last_) {
|
||||
video_frame_rate_button_value_ = video_frame_rate_button_value_last_;
|
||||
}
|
||||
|
||||
if (video_encode_format_button_value_ !=
|
||||
video_encode_format_button_value_last_) {
|
||||
video_encode_format_button_value_ =
|
||||
@@ -390,4 +406,5 @@ int Render::SettingWindow() {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
int Render::MainWindow() {
|
||||
ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_), ImGuiCond_Always);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
@@ -47,3 +49,4 @@ int Render::MainWindow() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
std::vector<std::string> GetRootEntries() {
|
||||
std::vector<std::string> roots;
|
||||
#ifdef _WIN32
|
||||
@@ -33,8 +35,9 @@ int Render::ShowSimpleFileBrowser() {
|
||||
selected_current_file_path_ = std::filesystem::current_path().string();
|
||||
}
|
||||
|
||||
if (!selected_file_.empty()) {
|
||||
display_text = std::filesystem::path(selected_file_).filename().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();
|
||||
@@ -66,7 +69,7 @@ int Render::ShowSimpleFileBrowser() {
|
||||
for (const auto& root : roots) {
|
||||
if (ImGui::Selectable(root.c_str())) {
|
||||
selected_current_file_path_ = root;
|
||||
selected_file_.clear();
|
||||
tls_cert_path_self_.clear();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -81,7 +84,7 @@ int Render::ShowSimpleFileBrowser() {
|
||||
} else {
|
||||
selected_current_file_path_ = "Root";
|
||||
}
|
||||
selected_file_.clear();
|
||||
tls_cert_path_self_.clear();
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -91,11 +94,11 @@ int Render::ShowSimpleFileBrowser() {
|
||||
if (entry.is_directory()) {
|
||||
if (ImGui::Selectable(name.c_str())) {
|
||||
selected_current_file_path_ = entry.path().string();
|
||||
selected_file_.clear();
|
||||
tls_cert_path_self_.clear();
|
||||
}
|
||||
} else {
|
||||
if (ImGui::Selectable(name.c_str())) {
|
||||
selected_file_ = entry.path().string();
|
||||
tls_cert_path_self_ = entry.path().string();
|
||||
file_selected = true;
|
||||
show_file_browser_ = false;
|
||||
}
|
||||
@@ -182,8 +185,8 @@ int Render::SelfHostedServerWindow() {
|
||||
ImGui::SetCursorPosY(settings_items_offset);
|
||||
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
||||
|
||||
ImGui::InputText("##signal_server_ip_tmp_", signal_server_ip_tmp_,
|
||||
IM_ARRAYSIZE(signal_server_ip_tmp_),
|
||||
ImGui::InputText("##signal_server_ip_self_", signal_server_ip_self_,
|
||||
IM_ARRAYSIZE(signal_server_ip_self_),
|
||||
ImGuiInputTextFlags_AlwaysOverwrite);
|
||||
}
|
||||
|
||||
@@ -205,8 +208,29 @@ int Render::SelfHostedServerWindow() {
|
||||
ImGui::SetCursorPosY(settings_items_offset);
|
||||
ImGui::SetNextItemWidth(SELF_HOSTED_SERVER_INPUT_WINDOW_WIDTH);
|
||||
|
||||
ImGui::InputText("##signal_server_port_tmp_", signal_server_port_tmp_,
|
||||
IM_ARRAYSIZE(signal_server_port_tmp_));
|
||||
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();
|
||||
@@ -248,16 +272,20 @@ int Render::SelfHostedServerWindow() {
|
||||
localization::ok[localization_language_index_].c_str())) {
|
||||
show_self_hosted_server_config_window_ = false;
|
||||
|
||||
config_center_->SetServerHost(signal_server_ip_tmp_);
|
||||
config_center_->SetServerPort(atoi(signal_server_port_tmp_));
|
||||
config_center_->SetCertFilePath(selected_file_);
|
||||
strncpy(signal_server_ip_, signal_server_ip_tmp_,
|
||||
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_tmp_,
|
||||
strncpy(signal_server_port_, signal_server_port_self_,
|
||||
sizeof(signal_server_port_) - 1);
|
||||
signal_server_port_[sizeof(signal_server_port_) - 1] = '\0';
|
||||
strncpy(cert_file_path_, selected_file_.c_str(),
|
||||
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';
|
||||
|
||||
@@ -271,15 +299,15 @@ int Render::SelfHostedServerWindow() {
|
||||
show_self_hosted_server_config_window_ = false;
|
||||
self_hosted_server_config_window_pos_reset_ = true;
|
||||
|
||||
strncpy(signal_server_ip_tmp_, signal_server_ip_,
|
||||
sizeof(signal_server_ip_tmp_) - 1);
|
||||
signal_server_ip_tmp_[sizeof(signal_server_ip_tmp_) - 1] = '\0';
|
||||
strncpy(signal_server_port_tmp_, signal_server_port_,
|
||||
sizeof(signal_server_port_tmp_) - 1);
|
||||
signal_server_port_tmp_[sizeof(signal_server_port_tmp_) - 1] = '\0';
|
||||
config_center_->SetServerHost(signal_server_ip_tmp_);
|
||||
config_center_->SetServerPort(atoi(signal_server_port_tmp_));
|
||||
selected_file_.clear();
|
||||
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);
|
||||
@@ -292,4 +320,5 @@ int Render::SelfHostedServerWindow() {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "rd_log.h"
|
||||
#include "render.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
void Render::DrawConnectionStatusText(
|
||||
std::shared_ptr<SubStreamWindowProperties>& props) {
|
||||
std::string text;
|
||||
@@ -199,4 +201,5 @@ int Render::StreamWindow() {
|
||||
ImGui::End(); // End VideoBg
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <atomic>
|
||||
#include <filesystem>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string g_log_dir = "logs";
|
||||
@@ -60,3 +62,4 @@ std::shared_ptr<spdlog::logger> get_logger() {
|
||||
|
||||
return g_logger;
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
constexpr auto LOGGER_NAME = "crossdesk";
|
||||
|
||||
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_ERROR(...) SPDLOG_LOGGER_ERROR(get_logger(), __VA_ARGS__)
|
||||
#define LOG_FATAL(...) SPDLOG_LOGGER_CRITICAL(get_logger(), __VA_ARGS__)
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
PathManager::PathManager(const std::string& app_name) : app_name_(app_name) {}
|
||||
|
||||
std::filesystem::path PathManager::GetConfigPath() {
|
||||
@@ -16,7 +18,11 @@ std::filesystem::path PathManager::GetConfigPath() {
|
||||
|
||||
std::filesystem::path PathManager::GetCachePath() {
|
||||
#ifdef _WIN32
|
||||
#ifdef CROSSDESK_DEBUG
|
||||
return "cache";
|
||||
#else
|
||||
return GetKnownFolder(FOLDERID_LocalAppData) / app_name_ / "cache";
|
||||
#endif
|
||||
#elif __APPLE__
|
||||
return GetEnvOrDefault("XDG_CACHE_HOME", GetHome() + "/.cache") / app_name_;
|
||||
#else
|
||||
@@ -70,22 +76,35 @@ std::filesystem::path PathManager::GetKnownFolder(REFKNOWNFOLDERID id) {
|
||||
#endif
|
||||
|
||||
std::string PathManager::GetHome() {
|
||||
if (const char* home = getenv("HOME")) {
|
||||
return std::string(home);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, path)))
|
||||
return std::string(path);
|
||||
#else
|
||||
if (const char* home = getenv("HOME")) {
|
||||
return std::string(home);
|
||||
}
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
std::filesystem::path PathManager::GetEnvOrDefault(const char* env_var,
|
||||
const std::string& def) {
|
||||
#ifdef _WIN32
|
||||
char* buffer = nullptr;
|
||||
size_t size = 0;
|
||||
|
||||
if (_dupenv_s(&buffer, &size, env_var) == 0 && buffer != nullptr) {
|
||||
std::filesystem::path result(buffer);
|
||||
free(buffer);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
if (const char* val = getenv(env_var)) {
|
||||
return std::filesystem::path(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
return std::filesystem::path(def);
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class PathManager {
|
||||
public:
|
||||
explicit PathManager(const std::string& app_name);
|
||||
@@ -40,5 +42,5 @@ class PathManager {
|
||||
private:
|
||||
std::string app_name_;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "libyuv.h"
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
ScreenCapturerX11::ScreenCapturerX11() {}
|
||||
|
||||
ScreenCapturerX11::~ScreenCapturerX11() { Destroy(); }
|
||||
@@ -171,4 +173,5 @@ void ScreenCapturerX11::OnFrame() {
|
||||
}
|
||||
|
||||
XDestroyImage(image);
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "screen_capturer.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class ScreenCapturerX11 : public ScreenCapturer {
|
||||
public:
|
||||
ScreenCapturerX11();
|
||||
@@ -60,5 +62,5 @@ class ScreenCapturerX11 : public ScreenCapturer {
|
||||
std::vector<uint8_t> y_plane_;
|
||||
std::vector<uint8_t> uv_plane_;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
ScreenCapturerSck::ScreenCapturerSck() {}
|
||||
ScreenCapturerSck::~ScreenCapturerSck() {}
|
||||
|
||||
@@ -70,4 +72,5 @@ std::vector<DisplayInfo> ScreenCapturerSck::GetDisplayInfoList() {
|
||||
|
||||
void ScreenCapturerSck::OnFrame() {}
|
||||
|
||||
void ScreenCapturerSck::CleanUp() {}
|
||||
void ScreenCapturerSck::CleanUp() {}
|
||||
} // namespace crossdesk
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "screen_capturer.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class ScreenCapturerSck : public ScreenCapturer {
|
||||
public:
|
||||
ScreenCapturerSck();
|
||||
@@ -55,5 +57,5 @@ class ScreenCapturerSck : public ScreenCapturer {
|
||||
private:
|
||||
std::unique_ptr<ScreenCapturer> screen_capturer_sck_impl_;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -22,9 +22,12 @@
|
||||
#include "display_info.h"
|
||||
#include "rd_log.h"
|
||||
|
||||
static const int kFullDesktopScreenId = -1;
|
||||
using namespace crossdesk;
|
||||
|
||||
class ScreenCapturerSckImpl;
|
||||
|
||||
static const int kFullDesktopScreenId = -1;
|
||||
|
||||
// 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.
|
||||
// Also, the `SCContentFilter` fields `contentRect` and `pointPixelScale` were
|
||||
@@ -424,10 +427,6 @@ void ScreenCapturerSckImpl::StartOrReconfigureCapturer() {
|
||||
[SCShareableContent getShareableContentWithCompletionHandler:handler];
|
||||
}
|
||||
|
||||
std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
||||
return std::make_unique<ScreenCapturerSckImpl>();
|
||||
}
|
||||
|
||||
@implementation SckHelper {
|
||||
// This lock is to prevent the capturer being destroyed while an instance
|
||||
// method is still running on another thread.
|
||||
@@ -485,4 +484,8 @@ std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
||||
_capturer = nullptr;
|
||||
}
|
||||
|
||||
@end
|
||||
@end
|
||||
|
||||
std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
||||
return std::make_unique<ScreenCapturerSckImpl>();
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "display_info.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class ScreenCapturer {
|
||||
public:
|
||||
typedef std::function<void(unsigned char*, int, int, int, const char*)>
|
||||
@@ -30,5 +32,5 @@ class ScreenCapturer {
|
||||
virtual std::vector<DisplayInfo> GetDisplayInfoList() = 0;
|
||||
virtual int SwitchTo(int monitor_index) = 0;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "screen_capturer_sck.h"
|
||||
#endif
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class ScreenCapturerFactory {
|
||||
public:
|
||||
virtual ~ScreenCapturerFactory() {}
|
||||
@@ -34,5 +36,5 @@ class ScreenCapturerFactory {
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -10,35 +10,46 @@
|
||||
#include "libyuv.h"
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
static std::vector<DisplayInfo> gs_display_list;
|
||||
|
||||
std::string WideToUtf8(const wchar_t *wideStr) {
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, nullptr, 0,
|
||||
nullptr, nullptr);
|
||||
std::string WideToUtf8(const std::wstring& wstr) {
|
||||
if (wstr.empty()) return {};
|
||||
int size_needed = WideCharToMultiByte(
|
||||
CP_UTF8, 0, wstr.data(), (int)wstr.size(), nullptr, 0, nullptr, nullptr);
|
||||
std::string result(size_needed, 0);
|
||||
WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, &result[0], size_needed, nullptr,
|
||||
nullptr);
|
||||
result.pop_back();
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), result.data(),
|
||||
size_needed, nullptr, nullptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string CleanDisplayName(const std::wstring& wide_name) {
|
||||
std::string name = WideToUtf8(wide_name);
|
||||
name.erase(std::remove_if(name.begin(), name.end(),
|
||||
[](unsigned char c) { return !std::isalnum(c); }),
|
||||
name.end());
|
||||
return name;
|
||||
}
|
||||
|
||||
BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc,
|
||||
[[maybe_unused]] LPRECT lprc, LPARAM data) {
|
||||
MONITORINFOEX monitor_info_;
|
||||
monitor_info_.cbSize = sizeof(MONITORINFOEX);
|
||||
|
||||
if (GetMonitorInfo(hmonitor, &monitor_info_)) {
|
||||
std::string display_name = CleanDisplayName(monitor_info_.szDevice);
|
||||
if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) {
|
||||
gs_display_list.insert(
|
||||
gs_display_list.begin(),
|
||||
{(void *)hmonitor, WideToUtf8(monitor_info_.szDevice),
|
||||
{(void*)hmonitor, display_name,
|
||||
(monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false,
|
||||
monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top,
|
||||
monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom});
|
||||
*(HMONITOR *)data = hmonitor;
|
||||
*(HMONITOR*)data = hmonitor;
|
||||
} else {
|
||||
gs_display_list.push_back(DisplayInfo(
|
||||
(void *)hmonitor, WideToUtf8(monitor_info_.szDevice),
|
||||
(void*)hmonitor, display_name,
|
||||
(monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false,
|
||||
monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top,
|
||||
monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom));
|
||||
@@ -81,7 +92,7 @@ bool ScreenCapturerWgc::IsWgcSupported() {
|
||||
/* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */
|
||||
return winrt::Windows::Foundation::Metadata::ApiInformation::
|
||||
IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 8);
|
||||
} catch (const winrt::hresult_error &) {
|
||||
} catch (const winrt::hresult_error&) {
|
||||
return false;
|
||||
} catch (...) {
|
||||
return false;
|
||||
@@ -115,7 +126,7 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) {
|
||||
}
|
||||
|
||||
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(
|
||||
"index: {}, display name: {}, is primary: {}, bounds: ({}, {}) - "
|
||||
"({}, {})",
|
||||
@@ -243,16 +254,16 @@ int ScreenCapturerWgc::SwitchTo(int monitor_index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame,
|
||||
void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame& frame,
|
||||
int id) {
|
||||
if (on_data_) {
|
||||
if (!nv12_frame_) {
|
||||
nv12_frame_ = new unsigned char[frame.width * frame.height * 3 / 2];
|
||||
}
|
||||
|
||||
libyuv::ARGBToNV12((const uint8_t *)frame.data, frame.width * 4,
|
||||
(uint8_t *)nv12_frame_, frame.width,
|
||||
(uint8_t *)(nv12_frame_ + frame.width * frame.height),
|
||||
libyuv::ARGBToNV12((const uint8_t*)frame.data, frame.width * 4,
|
||||
(uint8_t*)nv12_frame_, frame.width,
|
||||
(uint8_t*)(nv12_frame_ + frame.width * frame.height),
|
||||
frame.width, frame.width, frame.height);
|
||||
|
||||
on_data_(nv12_frame_, frame.width * frame.height * 3 / 2, frame.width,
|
||||
@@ -262,7 +273,7 @@ void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame,
|
||||
|
||||
void ScreenCapturerWgc::CleanUp() {
|
||||
if (inited_) {
|
||||
for (auto &session : sessions_) {
|
||||
for (auto& session : sessions_) {
|
||||
if (session.session_) {
|
||||
session.session_->Stop();
|
||||
}
|
||||
@@ -270,3 +281,4 @@ void ScreenCapturerWgc::CleanUp() {
|
||||
sessions_.clear();
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "wgc_session.h"
|
||||
#include "wgc_session_impl.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class ScreenCapturerWgc : public ScreenCapturer,
|
||||
public WgcSession::wgc_session_observer {
|
||||
public:
|
||||
@@ -64,5 +66,5 @@ class ScreenCapturerWgc : public ScreenCapturer,
|
||||
unsigned char* nv12_frame_ = nullptr;
|
||||
unsigned char* nv12_frame_scaled_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class WgcSession {
|
||||
public:
|
||||
struct wgc_session_frame {
|
||||
@@ -10,13 +12,13 @@ class WgcSession {
|
||||
unsigned int height;
|
||||
unsigned int row_pitch;
|
||||
|
||||
const unsigned char *data;
|
||||
const unsigned char* data;
|
||||
};
|
||||
|
||||
class wgc_session_observer {
|
||||
public:
|
||||
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:
|
||||
@@ -25,7 +27,7 @@ class WgcSession {
|
||||
virtual int Initialize(HWND hwnd) = 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 Stop() = 0;
|
||||
@@ -33,7 +35,7 @@ class WgcSession {
|
||||
virtual int Pause() = 0;
|
||||
virtual int Resume() = 0;
|
||||
|
||||
virtual ~WgcSession(){};
|
||||
virtual ~WgcSession() {};
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -18,9 +18,11 @@
|
||||
throw winrt::hresult_error(RO_E_CLOSED); \
|
||||
}
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
extern "C" {
|
||||
HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice(
|
||||
::IDXGIDevice *dxgiDevice, ::IInspectable **graphicsDevice);
|
||||
::IDXGIDevice* dxgiDevice, ::IInspectable** graphicsDevice);
|
||||
}
|
||||
|
||||
WgcSessionImpl::WgcSessionImpl(int id) : id_(id) {}
|
||||
@@ -48,7 +50,7 @@ int WgcSessionImpl::Initialize(HMONITOR hmonitor) {
|
||||
return Initialize();
|
||||
}
|
||||
|
||||
void WgcSessionImpl::RegisterObserver(wgc_session_observer *observer) {
|
||||
void WgcSessionImpl::RegisterObserver(wgc_session_observer* observer) {
|
||||
std::lock_guard locker(lock_);
|
||||
observer_ = observer;
|
||||
}
|
||||
@@ -175,7 +177,7 @@ auto WgcSessionImpl::CreateCaptureItemForWindow(HWND hwnd) {
|
||||
interop_factory->CreateForWindow(
|
||||
hwnd,
|
||||
winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
|
||||
reinterpret_cast<void **>(winrt::put_abi(item)));
|
||||
reinterpret_cast<void**>(winrt::put_abi(item)));
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -187,7 +189,7 @@ auto WgcSessionImpl::CreateCaptureItemForMonitor(HMONITOR hmonitor) {
|
||||
interop_factory->CreateForMonitor(
|
||||
hmonitor,
|
||||
winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
|
||||
reinterpret_cast<void **>(winrt::put_abi(item)));
|
||||
reinterpret_cast<void**>(winrt::put_abi(item)));
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -216,8 +218,8 @@ HRESULT WgcSessionImpl::CreateMappedTexture(
|
||||
}
|
||||
|
||||
void WgcSessionImpl::OnFrame(
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const &sender,
|
||||
[[maybe_unused]] winrt::Windows::Foundation::IInspectable const &args) {
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const& sender,
|
||||
[[maybe_unused]] winrt::Windows::Foundation::IInspectable const& args) {
|
||||
std::lock_guard locker(lock_);
|
||||
|
||||
auto is_new_size = false;
|
||||
@@ -268,8 +270,8 @@ void WgcSessionImpl::OnFrame(
|
||||
wgc_session_frame{static_cast<unsigned int>(frame_size.Width),
|
||||
static_cast<unsigned int>(frame_size.Height),
|
||||
map_result.RowPitch,
|
||||
const_cast<const unsigned char *>(
|
||||
(unsigned char *)map_result.pData)},
|
||||
const_cast<const unsigned char*>(
|
||||
(unsigned char*)map_result.pData)},
|
||||
id_);
|
||||
}
|
||||
|
||||
@@ -286,8 +288,8 @@ void WgcSessionImpl::OnFrame(
|
||||
}
|
||||
|
||||
void WgcSessionImpl::OnClosed(
|
||||
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
|
||||
winrt::Windows::Foundation::IInspectable const &) {
|
||||
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const&,
|
||||
winrt::Windows::Foundation::IInspectable const&) {
|
||||
OutputDebugStringW(L"WgcSessionImpl::OnClosed");
|
||||
}
|
||||
|
||||
@@ -375,4 +377,5 @@ LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM w_param,
|
||||
|
||||
// ::CloseWindow(hwnd_);
|
||||
// ::DestroyWindow(hwnd_);
|
||||
// }
|
||||
// }
|
||||
} // namespace crossdesk
|
||||
@@ -10,15 +10,17 @@
|
||||
|
||||
#include "wgc_session.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class WgcSessionImpl : public WgcSession {
|
||||
struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
|
||||
IDirect3DDxgiInterfaceAccess : ::IUnknown {
|
||||
virtual HRESULT __stdcall GetInterface(GUID const &id, void **object) = 0;
|
||||
IDirect3DDxgiInterfaceAccess : ::IUnknown {
|
||||
virtual HRESULT __stdcall GetInterface(GUID const& id, void** object) = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline auto GetDXGIInterfaceFromObject(
|
||||
winrt::Windows::Foundation::IInspectable const &object) {
|
||||
winrt::Windows::Foundation::IInspectable const& object) {
|
||||
auto access = object.as<IDirect3DDxgiInterfaceAccess>();
|
||||
winrt::com_ptr<T> result;
|
||||
winrt::check_hresult(
|
||||
@@ -44,7 +46,7 @@ class WgcSessionImpl : public WgcSession {
|
||||
int Initialize(HWND hwnd) override;
|
||||
int Initialize(HMONITOR hmonitor) override;
|
||||
|
||||
void RegisterObserver(wgc_session_observer *observer) override;
|
||||
void RegisterObserver(wgc_session_observer* observer) override;
|
||||
|
||||
int Start() override;
|
||||
int Stop() override;
|
||||
@@ -60,11 +62,11 @@ class WgcSessionImpl : public WgcSession {
|
||||
HRESULT CreateMappedTexture(winrt::com_ptr<ID3D11Texture2D> src_texture,
|
||||
unsigned int width = 0, unsigned int height = 0);
|
||||
void OnFrame(
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const
|
||||
&sender,
|
||||
winrt::Windows::Foundation::IInspectable const &args);
|
||||
void OnClosed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
|
||||
winrt::Windows::Foundation::IInspectable const &);
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const&
|
||||
sender,
|
||||
winrt::Windows::Foundation::IInspectable const& args);
|
||||
void OnClosed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const&,
|
||||
winrt::Windows::Foundation::IInspectable const&);
|
||||
|
||||
int Initialize();
|
||||
void CleanUp();
|
||||
@@ -78,7 +80,7 @@ class WgcSessionImpl : public WgcSession {
|
||||
bool is_running_ = false;
|
||||
bool is_paused_ = false;
|
||||
|
||||
wgc_session_observer *observer_ = nullptr;
|
||||
wgc_session_observer* observer_ = nullptr;
|
||||
|
||||
// wgc
|
||||
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()));
|
||||
// return result;
|
||||
// }
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "rd_log.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
constexpr int kSampleRate = 48000;
|
||||
constexpr pa_sample_format_t kFormat = PA_SAMPLE_S16LE;
|
||||
constexpr int kChannels = 1;
|
||||
@@ -265,4 +267,5 @@ int SpeakerCapturerLinux::Pause() {
|
||||
int SpeakerCapturerLinux::Resume() {
|
||||
paused_ = false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include "speaker_capturer.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class SpeakerCapturerLinux : public SpeakerCapturer {
|
||||
public:
|
||||
SpeakerCapturerLinux();
|
||||
@@ -50,5 +52,5 @@ class SpeakerCapturerLinux : public SpeakerCapturer {
|
||||
std::mutex state_mtx_;
|
||||
std::vector<uint8_t> frame_cache_;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include "speaker_capturer.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class SpeakerCapturerMacosx : public SpeakerCapturer {
|
||||
public:
|
||||
SpeakerCapturerMacosx();
|
||||
@@ -33,5 +35,5 @@ class SpeakerCapturerMacosx : public SpeakerCapturer {
|
||||
class Impl;
|
||||
Impl* impl_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -5,13 +5,17 @@
|
||||
#include "rd_log.h"
|
||||
#include "speaker_capturer_macosx.h"
|
||||
|
||||
namespace crossdesk {
|
||||
class SpeakerCapturerMacosx;
|
||||
}
|
||||
|
||||
@interface SpeakerCaptureDelegate : NSObject <SCStreamDelegate, SCStreamOutput>
|
||||
@property(nonatomic, assign) SpeakerCapturerMacosx* owner;
|
||||
- (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner;
|
||||
@property(nonatomic, assign) crossdesk::SpeakerCapturerMacosx* owner;
|
||||
- (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner;
|
||||
@end
|
||||
|
||||
@implementation SpeakerCaptureDelegate
|
||||
- (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner {
|
||||
- (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_owner = owner;
|
||||
@@ -22,72 +26,32 @@
|
||||
- (void)stream:(SCStream*)stream
|
||||
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||
ofType:(SCStreamOutputType)type {
|
||||
if (type == SCStreamOutputTypeAudio) {
|
||||
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 (type != SCStreamOutputTypeAudio) return;
|
||||
|
||||
if (_owner->cb_ && dataPtr && length > 0 && asbd) {
|
||||
std::vector<short> out_pcm16;
|
||||
if (asbd->mFormatFlags & kAudioFormatFlagIsFloat) {
|
||||
int channels = asbd->mChannelsPerFrame;
|
||||
int samples = (int)(length / sizeof(float));
|
||||
float* floatData = (float*)dataPtr;
|
||||
std::vector<short> pcm16(samples);
|
||||
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);
|
||||
}
|
||||
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 (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 += pcm16[i * channels + c];
|
||||
}
|
||||
out_pcm16[i] = sum / channels;
|
||||
}
|
||||
} 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");
|
||||
}
|
||||
if (_owner->cb_ && dataPtr && length > 0 && asbd) {
|
||||
std::vector<short> out_pcm16;
|
||||
// ... 数据转换逻辑保持不变 ...
|
||||
// 调用回调
|
||||
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
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class SpeakerCapturerMacosx::Impl {
|
||||
public:
|
||||
SCStreamConfiguration* config = nil;
|
||||
@@ -262,3 +226,4 @@ int SpeakerCapturerMacosx::Destroy() {
|
||||
int SpeakerCapturerMacosx::Pause() { return 0; }
|
||||
|
||||
int SpeakerCapturerMacosx::Resume() { return Start(); }
|
||||
} // namespace crossdesk
|
||||
@@ -9,9 +9,11 @@
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class SpeakerCapturer {
|
||||
public:
|
||||
typedef std::function<void(unsigned char *, size_t, const char *)>
|
||||
typedef std::function<void(unsigned char*, size_t, const char*)>
|
||||
speaker_data_cb;
|
||||
|
||||
public:
|
||||
@@ -23,5 +25,5 @@ class SpeakerCapturer {
|
||||
virtual int Start() = 0;
|
||||
virtual int Stop() = 0;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "speaker_capturer_macosx.h"
|
||||
#endif
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class SpeakerCapturerFactory {
|
||||
public:
|
||||
virtual ~SpeakerCapturerFactory() {}
|
||||
@@ -32,5 +34,5 @@ class SpeakerCapturerFactory {
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#define SAVE_AUDIO_FILE 0
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
static ma_device_config device_config_;
|
||||
static ma_device device_;
|
||||
static ma_format format_ = ma_format_s16;
|
||||
@@ -99,3 +101,4 @@ int SpeakerCapturerWasapi::Destroy() {
|
||||
}
|
||||
|
||||
int SpeakerCapturerWasapi::Pause() { return 0; }
|
||||
} // namespace crossdesk
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "speaker_capturer.h"
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class SpeakerCapturerWasapi : public SpeakerCapturer {
|
||||
public:
|
||||
SpeakerCapturerWasapi();
|
||||
@@ -31,5 +33,5 @@ class SpeakerCapturerWasapi : public SpeakerCapturer {
|
||||
private:
|
||||
bool inited_ = false;
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
@@ -21,7 +21,7 @@
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
|
||||
static std::string test;
|
||||
namespace crossdesk {
|
||||
|
||||
bool LoadTextureFromMemory(const void* data, size_t data_size,
|
||||
SDL_Renderer* renderer, SDL_Texture** out_texture,
|
||||
@@ -118,13 +118,13 @@ void ScaleNv12ToABGR(char* src, int src_w, int src_h, int dst_w, int dst_h,
|
||||
|
||||
memset(dst_rgba, 0, dst_w * dst_h * 4);
|
||||
for (int i = 0; i < dst_w * dst_h; ++i) {
|
||||
dst_rgba[i * 4 + 3] = 0xFF;
|
||||
dst_rgba[i * 4 + 3] = static_cast<char>(0xFF);
|
||||
}
|
||||
|
||||
for (int y = 0; y < fit_h; ++y) {
|
||||
for (int row = 0; row < fit_h; ++row) {
|
||||
int dst_offset =
|
||||
((y + (dst_h - fit_h) / 2) * dst_w + (dst_w - fit_w) / 2) * 4;
|
||||
memcpy(dst_rgba + dst_offset, abgr.data() + y * fit_w * 4, fit_w * 4);
|
||||
((row + (dst_h - fit_h) / 2) * dst_w + (dst_w - fit_w) / 2) * 4;
|
||||
memcpy(dst_rgba + dst_offset, abgr.data() + row * fit_w * 4, fit_w * 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ int Thumbnail::SaveToThumbnail(const char* yuv420p, int width, int height,
|
||||
memset(rgba_buffer_, 0x00, thumbnail_width_ * thumbnail_height_ * 4);
|
||||
for (int i = 0; i < thumbnail_width_ * thumbnail_height_; ++i) {
|
||||
// Set alpha channel to opaque
|
||||
rgba_buffer_[i * 4 + 3] = 0xFF;
|
||||
rgba_buffer_[i * 4 + 3] = static_cast<char>(0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ int Thumbnail::LoadThumbnail(
|
||||
return -1;
|
||||
} else {
|
||||
for (int i = 0; i < image_paths.size(); i++) {
|
||||
size_t pos1 = image_paths[i].string().find('/') + 1;
|
||||
// size_t pos1 = image_paths[i].string().find('/') + 1;
|
||||
std::string cipher_image_name = image_paths[i].filename().string();
|
||||
std::string remote_id;
|
||||
std::string cipher_password;
|
||||
@@ -241,7 +241,7 @@ int Thumbnail::LoadThumbnail(
|
||||
AES_decrypt(cipher_password, aes128_key_, aes128_iv_);
|
||||
} else {
|
||||
size_t pos_n = cipher_image_name.find('N');
|
||||
size_t pos_at = cipher_image_name.find('@');
|
||||
// size_t pos_at = cipher_image_name.find('@');
|
||||
|
||||
if (pos_n == std::string::npos) {
|
||||
LOG_ERROR("Invalid filename");
|
||||
@@ -430,3 +430,4 @@ std::string Thumbnail::AES_decrypt(const std::string& ciphertext,
|
||||
|
||||
return std::string(reinterpret_cast<char*>(plaintext), plaintext_len);
|
||||
}
|
||||
} // namespace crossdesk
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace crossdesk {
|
||||
|
||||
class Thumbnail {
|
||||
public:
|
||||
struct RecentConnection {
|
||||
@@ -83,5 +85,5 @@ class Thumbnail {
|
||||
unsigned char ciphertext_[64];
|
||||
unsigned char decryptedtext_[64];
|
||||
};
|
||||
|
||||
} // namespace crossdesk
|
||||
#endif
|
||||
1
submodules/minirtc
Submodule
1
submodules/minirtc
Submodule
Submodule submodules/minirtc added at 2f8b0c1ff4
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 40eaf93b42
@@ -13,15 +13,17 @@ set_encodings("utf-8")
|
||||
|
||||
-- set_policy("build.warning", true)
|
||||
-- set_warnings("all", "extra")
|
||||
-- add_cxxflags("/W4", "/WX")
|
||||
|
||||
add_defines("UNICODE")
|
||||
if is_mode("debug") then
|
||||
add_defines("DESK_PORT_DEBUG")
|
||||
add_defines("CROSSDESK_DEBUG")
|
||||
end
|
||||
|
||||
add_requires("spdlog 1.14.1", {system = false})
|
||||
add_requires("imgui v1.91.5-docking", {configs = {sdl3 = true, sdl3_renderer = true}})
|
||||
add_requires("openssl3 3.3.2", {system = false})
|
||||
add_requires("nlohmann_json 3.11.3")
|
||||
|
||||
if is_os("windows") then
|
||||
add_requires("libyuv", "miniaudio 0.11.21")
|
||||
@@ -44,9 +46,9 @@ elseif is_os("macosx") then
|
||||
"CoreMedia", "CoreVideo", "CoreAudio", "AudioToolbox")
|
||||
end
|
||||
|
||||
add_packages("spdlog", "imgui")
|
||||
add_packages("spdlog", "imgui", "nlohmann_json")
|
||||
|
||||
includes("thirdparty")
|
||||
includes("submodules")
|
||||
|
||||
target("rd_log")
|
||||
set_kind("object")
|
||||
|
||||
Reference in New Issue
Block a user