mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-12-19 22:09:09 +08:00
Compare commits
4 Commits
0d591f769d
...
v1.0.4-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bd5b002d1 | ||
|
|
2f83301de7 | ||
|
|
c8152b5cbf | ||
|
|
b1df10c0de |
17
.github/workflows/build.yml
vendored
17
.github/workflows/build.yml
vendored
@@ -385,3 +385,20 @@ jobs:
|
|||||||
remote_host: ${{ secrets.SERVER_HOST }}
|
remote_host: ${{ secrets.SERVER_HOST }}
|
||||||
remote_user: ${{ secrets.SERVER_USER }}
|
remote_user: ${{ secrets.SERVER_USER }}
|
||||||
remote_key: ${{ secrets.SERVER_KEY }}
|
remote_key: ${{ secrets.SERVER_KEY }}
|
||||||
|
|
||||||
|
- name: Generate version.json
|
||||||
|
run: |
|
||||||
|
echo "{" > version.json
|
||||||
|
echo " \"latest_version\": \"${{ steps.version.outputs.VERSION_NUM }}\"" >> version.json
|
||||||
|
echo "}" >> version.json
|
||||||
|
cat version.json
|
||||||
|
|
||||||
|
- name: Upload version.json to server
|
||||||
|
uses: burnett01/rsync-deployments@5.2
|
||||||
|
with:
|
||||||
|
switches: -avzr --delete
|
||||||
|
path: version.json
|
||||||
|
remote_path: /var/www/html/version/
|
||||||
|
remote_host: ${{ secrets.SERVER_HOST }}
|
||||||
|
remote_user: ${{ secrets.SERVER_USER }}
|
||||||
|
remote_key: ${{ secrets.SERVER_KEY }}
|
||||||
|
|||||||
@@ -9,11 +9,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "display_info.h"
|
#include "display_info.h"
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace crossdesk {
|
namespace crossdesk {
|
||||||
|
|
||||||
@@ -59,7 +55,7 @@ typedef struct {
|
|||||||
int* bottom;
|
int* bottom;
|
||||||
} HostInfo;
|
} HostInfo;
|
||||||
|
|
||||||
struct RemoteAction {
|
typedef struct {
|
||||||
ControlType type;
|
ControlType type;
|
||||||
union {
|
union {
|
||||||
Mouse m;
|
Mouse m;
|
||||||
@@ -68,111 +64,7 @@ struct RemoteAction {
|
|||||||
bool a;
|
bool a;
|
||||||
int d;
|
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
|
// int key_code, bool is_down
|
||||||
typedef void (*OnKeyAction)(int, bool, void*);
|
typedef void (*OnKeyAction)(int, bool, void*);
|
||||||
|
|||||||
@@ -448,6 +448,7 @@ class Render {
|
|||||||
bool enable_self_hosted_ = false;
|
bool enable_self_hosted_ = false;
|
||||||
int language_button_value_last_ = 0;
|
int language_button_value_last_ = 0;
|
||||||
int video_quality_button_value_last_ = 0;
|
int video_quality_button_value_last_ = 0;
|
||||||
|
int video_frame_rate_button_value_last_ = 0;
|
||||||
int video_encode_format_button_value_last_ = 0;
|
int video_encode_format_button_value_last_ = 0;
|
||||||
bool enable_hardware_video_codec_last_ = false;
|
bool enable_hardware_video_codec_last_ = false;
|
||||||
bool enable_turn_last_ = false;
|
bool enable_turn_last_ = false;
|
||||||
|
|||||||
@@ -28,10 +28,8 @@ int Render::SendKeyCommand(int key_code, bool is_down) {
|
|||||||
client_properties_.end()) {
|
client_properties_.end()) {
|
||||||
auto props = client_properties_[controlled_remote_id_];
|
auto props = client_properties_[controlled_remote_id_];
|
||||||
if (props->connection_status_ == ConnectionStatus::Connected) {
|
if (props->connection_status_ == ConnectionStatus::Connected) {
|
||||||
json j = remote_action.to_json();
|
SendDataFrame(props->peer_, (const char*)&remote_action,
|
||||||
std::string msg = j.dump();
|
sizeof(remote_action), props->data_label_.c_str());
|
||||||
SendDataFrame(props->peer_, msg.c_str(), msg.size(),
|
|
||||||
props->data_label_.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,11 +94,8 @@ int Render::ProcessMouseEvent(const SDL_Event& event) {
|
|||||||
if (props->control_bar_hovered_ || props->display_selectable_hovered_) {
|
if (props->control_bar_hovered_ || props->display_selectable_hovered_) {
|
||||||
remote_action.m.flag = MouseFlag::move;
|
remote_action.m.flag = MouseFlag::move;
|
||||||
}
|
}
|
||||||
|
SendDataFrame(props->peer_, (const char*)&remote_action,
|
||||||
json j = remote_action.to_json();
|
sizeof(remote_action), props->data_label_.c_str());
|
||||||
std::string msg = j.dump();
|
|
||||||
SendDataFrame(props->peer_, msg.c_str(), msg.size(),
|
|
||||||
props->data_label_.c_str());
|
|
||||||
} else if (SDL_EVENT_MOUSE_WHEEL == event.type &&
|
} 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 &&
|
||||||
last_mouse_event.button.x <= props->stream_render_rect_.x +
|
last_mouse_event.button.x <= props->stream_render_rect_.x +
|
||||||
@@ -132,10 +127,8 @@ int Render::ProcessMouseEvent(const SDL_Event& event) {
|
|||||||
(float)(event.button.y - props->stream_render_rect_.y) /
|
(float)(event.button.y - props->stream_render_rect_.y) /
|
||||||
render_height;
|
render_height;
|
||||||
|
|
||||||
json j = remote_action.to_json();
|
SendDataFrame(props->peer_, (const char*)&remote_action,
|
||||||
std::string msg = j.dump();
|
sizeof(remote_action), props->data_label_.c_str());
|
||||||
SendDataFrame(props->peer_, msg.c_str(), msg.size(),
|
|
||||||
props->data_label_.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,54 +279,64 @@ void Render::OnReceiveDataBufferCb(const char* data, size_t size,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string json_str(data, size);
|
|
||||||
RemoteAction remote_action;
|
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);
|
std::string remote_id(user_id, user_id_size);
|
||||||
if (render->client_properties_.find(remote_id) !=
|
if (render->client_properties_.find(remote_id) !=
|
||||||
render->client_properties_.end()) {
|
render->client_properties_.end()) {
|
||||||
// local
|
// local
|
||||||
auto props = render->client_properties_.find(remote_id)->second;
|
auto props = render->client_properties_.find(remote_id)->second;
|
||||||
if (remote_action.type == ControlType::host_infomation &&
|
RemoteAction host_info;
|
||||||
props->remote_host_name_.empty()) {
|
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 {
|
||||||
props->remote_host_name_ = std::string(remote_action.i.host_name,
|
props->remote_host_name_ = std::string(remote_action.i.host_name,
|
||||||
remote_action.i.host_name_size);
|
remote_action.i.host_name_size);
|
||||||
LOG_INFO("Remote hostname: [{}]", props->remote_host_name_);
|
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(remote_action);
|
FreeRemoteAction(host_info);
|
||||||
} else {
|
} else {
|
||||||
// remote
|
// remote
|
||||||
if (remote_action.type == ControlType::mouse && render->mouse_controller_) {
|
if (ControlType::mouse == remote_action.type && render->mouse_controller_) {
|
||||||
render->mouse_controller_->SendMouseCommand(remote_action,
|
render->mouse_controller_->SendMouseCommand(remote_action,
|
||||||
render->selected_display_);
|
render->selected_display_);
|
||||||
} else if (remote_action.type == ControlType::audio_capture) {
|
} else if (ControlType::audio_capture == remote_action.type) {
|
||||||
if (remote_action.a)
|
if (remote_action.a) {
|
||||||
render->StartSpeakerCapturer();
|
render->StartSpeakerCapturer();
|
||||||
else
|
render->audio_capture_ = true;
|
||||||
|
} else {
|
||||||
render->StopSpeakerCapturer();
|
render->StopSpeakerCapturer();
|
||||||
} else if (remote_action.type == ControlType::keyboard &&
|
render->audio_capture_ = false;
|
||||||
|
}
|
||||||
|
} else if (ControlType::keyboard == remote_action.type &&
|
||||||
render->keyboard_capturer_) {
|
render->keyboard_capturer_) {
|
||||||
render->keyboard_capturer_->SendKeyboardCommand(
|
render->keyboard_capturer_->SendKeyboardCommand(
|
||||||
(int)remote_action.k.key_value,
|
(int)remote_action.k.key_value,
|
||||||
remote_action.k.flag == KeyFlag::key_down);
|
remote_action.k.flag == KeyFlag::key_down);
|
||||||
} else if (remote_action.type == ControlType::display_id &&
|
} else if (ControlType::display_id == remote_action.type) {
|
||||||
render->screen_capturer_) {
|
if (render->screen_capturer_) {
|
||||||
render->selected_display_ = remote_action.d;
|
render->selected_display_ = remote_action.d;
|
||||||
render->screen_capturer_->SwitchTo(remote_action.d);
|
render->screen_capturer_->SwitchTo(remote_action.d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,14 +288,23 @@ int Render::SettingWindow() {
|
|||||||
|
|
||||||
// Video quality
|
// Video quality
|
||||||
if (video_quality_button_value_ == 0) {
|
if (video_quality_button_value_ == 0) {
|
||||||
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::HIGH);
|
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::LOW);
|
||||||
} else if (video_quality_button_value_ == 1) {
|
} else if (video_quality_button_value_ == 1) {
|
||||||
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::MEDIUM);
|
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::MEDIUM);
|
||||||
} else {
|
} else {
|
||||||
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::LOW);
|
config_center_->SetVideoQuality(ConfigCenter::VIDEO_QUALITY::HIGH);
|
||||||
}
|
}
|
||||||
video_quality_button_value_last_ = video_quality_button_value_;
|
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
|
// Video encode format
|
||||||
if (video_encode_format_button_value_ == 0) {
|
if (video_encode_format_button_value_ == 0) {
|
||||||
config_center_->SetVideoEncodeFormat(
|
config_center_->SetVideoEncodeFormat(
|
||||||
@@ -366,6 +375,11 @@ int Render::SettingWindow() {
|
|||||||
video_quality_button_value_ = video_quality_button_value_last_;
|
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_ !=
|
if (video_encode_format_button_value_ !=
|
||||||
video_encode_format_button_value_last_) {
|
video_encode_format_button_value_last_) {
|
||||||
video_encode_format_button_value_ =
|
video_encode_format_button_value_ =
|
||||||
|
|||||||
Submodule submodules/minirtc updated: ff6b79807e...1f999dbe1f
@@ -23,7 +23,6 @@ end
|
|||||||
add_requires("spdlog 1.14.1", {system = false})
|
add_requires("spdlog 1.14.1", {system = false})
|
||||||
add_requires("imgui v1.91.5-docking", {configs = {sdl3 = true, sdl3_renderer = true}})
|
add_requires("imgui v1.91.5-docking", {configs = {sdl3 = true, sdl3_renderer = true}})
|
||||||
add_requires("openssl3 3.3.2", {system = false})
|
add_requires("openssl3 3.3.2", {system = false})
|
||||||
add_requires("nlohmann_json 3.11.3")
|
|
||||||
|
|
||||||
if is_os("windows") then
|
if is_os("windows") then
|
||||||
add_requires("libyuv", "miniaudio 0.11.21")
|
add_requires("libyuv", "miniaudio 0.11.21")
|
||||||
@@ -46,7 +45,7 @@ elseif is_os("macosx") then
|
|||||||
"CoreMedia", "CoreVideo", "CoreAudio", "AudioToolbox")
|
"CoreMedia", "CoreVideo", "CoreAudio", "AudioToolbox")
|
||||||
end
|
end
|
||||||
|
|
||||||
add_packages("spdlog", "imgui", "nlohmann_json")
|
add_packages("spdlog", "imgui")
|
||||||
|
|
||||||
includes("submodules")
|
includes("submodules")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user