From 71178ffa33fb1d0d0718ea8fcafa6e377aa2df69 Mon Sep 17 00:00:00 2001 From: dijunkun Date: Mon, 17 Jun 2024 17:31:57 +0800 Subject: [PATCH] Separate render window from main window --- src/localization/localization.h | 6 +- src/multiple_windows/layout_style.h | 81 ++ src/multiple_windows/main_window.cpp | 898 ++++++++++++++++++ src/multiple_windows/main_window.h | 191 ++++ .../main_window_callback_func.cpp | 0 src/multiple_windows/sub_window.cpp | 0 src/multiple_windows/sub_window.h | 10 + .../layout_style.h | 0 .../main_window.cpp | 0 .../main_window.h | 0 .../main_window_callback_func.cpp | 216 +++++ xmake.lua | 19 +- 12 files changed, 1414 insertions(+), 7 deletions(-) create mode 100644 src/multiple_windows/layout_style.h create mode 100644 src/multiple_windows/main_window.cpp create mode 100644 src/multiple_windows/main_window.h rename src/{main_window => multiple_windows}/main_window_callback_func.cpp (100%) create mode 100644 src/multiple_windows/sub_window.cpp create mode 100644 src/multiple_windows/sub_window.h rename src/{main_window => single_window}/layout_style.h (100%) rename src/{main_window => single_window}/main_window.cpp (100%) rename src/{main_window => single_window}/main_window.h (100%) create mode 100644 src/single_window/main_window_callback_func.cpp diff --git a/src/localization/localization.h b/src/localization/localization.h index 1dfcf1c..c0ed7da 100644 --- a/src/localization/localization.h +++ b/src/localization/localization.h @@ -11,11 +11,11 @@ namespace localization { static std::vector menu = {u8"菜单", "Menu"}; -static std::vector local_id = {u8"本机ID:", "Local ID:"}; -static std::vector password = {u8"密码:", "Password:"}; +static std::vector local_id = {u8"本机ID", "Local ID"}; +static std::vector password = {u8"密码", "Password"}; static std::vector max_password_len = {u8"最大6个字符", "Max 6 chars"}; -static std::vector remote_id = {u8"对端ID:", "Remote ID:"}; +static std::vector remote_id = {u8"对端ID", "Remote ID"}; static std::vector connect = {u8"连接", "Connect"}; static std::vector disconnect = {u8"断开连接", "Disconnect"}; static std::vector fullscreen = {u8"全屏", "Fullscreen"}; diff --git a/src/multiple_windows/layout_style.h b/src/multiple_windows/layout_style.h new file mode 100644 index 0000000..e6eb34f --- /dev/null +++ b/src/multiple_windows/layout_style.h @@ -0,0 +1,81 @@ +/* + * @Author: DI JUNKUN + * @Date: 2024-06-14 + * Copyright (c) 2024 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _LAYOUT_STYLE_H_ +#define _LAYOUT_STYLE_H_ + +#ifdef _WIN32 +#define MENU_WINDOW_WIDTH_CN 300 +#define MENU_WINDOW_HEIGHT_CN 245 +#define MENU_WINDOW_WIDTH_EN 190 +#define MENU_WINDOW_HEIGHT_EN 245 +#define IPUT_WINDOW_WIDTH 190 +#define INPUT_WINDOW_PADDING_CN 66 +#define INPUT_WINDOW_PADDING_EN 96 +#define SETTINGS_WINDOW_WIDTH_CN 181 +#define SETTINGS_WINDOW_WIDTH_EN 228 +#define SETTINGS_WINDOW_HEIGHT_CN 190 +#define SETTINGS_WINDOW_HEIGHT_EN 190 +#define LANGUAGE_SELECT_WINDOW_PADDING_CN 100 +#define LANGUAGE_SELECT_WINDOW_PADDING_EN 147 +#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_CN 100 +#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_EN 147 +#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_CN 100 +#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_EN 147 +#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_CN 154 +#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_EN 201 +#define SETTINGS_SELECT_WINDOW_WIDTH 73 +#define SETTINGS_OK_BUTTON_PADDING_CN 55 +#define SETTINGS_OK_BUTTON_PADDING_EN 78 +#elif __linux__ +#define MENU_WINDOW_WIDTH_CN 160 +#define MENU_WINDOW_HEIGHT_CN 245 +#define MENU_WINDOW_WIDTH_EN 190 +#define MENU_WINDOW_HEIGHT_EN 245 +#define IPUT_WINDOW_WIDTH 90 +#define INPUT_WINDOW_PADDING_CN 60 +#define INPUT_WINDOW_PADDING_EN 80 +#define SETTINGS_WINDOW_WIDTH_CN 188 +#define SETTINGS_WINDOW_WIDTH_EN 228 +#define SETTINGS_WINDOW_HEIGHT_CN 190 +#define SETTINGS_WINDOW_HEIGHT_EN 190 +#define LANGUAGE_SELECT_WINDOW_PADDING_CN 100 +#define LANGUAGE_SELECT_WINDOW_PADDING_EN 140 +#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_CN 100 +#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_EN 140 +#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_CN 100 +#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_EN 140 +#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_CN 161 +#define ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_EN 201 +#define SETTINGS_SELECT_WINDOW_WIDTH 60 +#define SETTINGS_OK_BUTTON_PADDING_CN 60 +#define SETTINGS_OK_BUTTON_PADDING_EN 80 +#elif __APPLE__ +#define MENU_WINDOW_WIDTH_CN 148 +#define MENU_WINDOW_HEIGHT_CN 244 +#define MENU_WINDOW_WIDTH_EN 148 +#define MENU_WINDOW_HEIGHT_EN 244 +#define IPUT_WINDOW_WIDTH 77 +#define INPUT_WINDOW_PADDING_CN 63 +#define INPUT_WINDOW_PADDING_EN 63 +#define SETTINGS_WINDOW_WIDTH_CN 160 +#define SETTINGS_WINDOW_WIDTH_EN 220 +#define SETTINGS_WINDOW_HEIGHT_CN 190 +#define SETTINGS_WINDOW_HEIGHT_EN 190 +#define LANGUAGE_SELECT_WINDOW_PADDING_CN 90 +#define LANGUAGE_SELECT_WINDOW_PADDING_EN 150 +#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_CN 90 +#define VIDEO_QUALITY_SELECT_WINDOW_PADDING_EN 150 +#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_CN 90 +#define VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_EN 150 +#define ENABLE_HARDWARE_VIDEO_CODEC_CHECK_WINDOW_PADDING_CN 133 +#define ENABLE_HARDWARE_VIDEO_CODEC_CHECK_WINDOW_PADDING_EN 193 +#define SETTINGS_SELECT_WINDOW_WIDTH 62 +#define SETTINGS_OK_BUTTON_PADDING_CN 50 +#define SETTINGS_OK_BUTTON_PADDING_EN 80 +#endif + +#endif \ No newline at end of file diff --git a/src/multiple_windows/main_window.cpp b/src/multiple_windows/main_window.cpp new file mode 100644 index 0000000..08c741b --- /dev/null +++ b/src/multiple_windows/main_window.cpp @@ -0,0 +1,898 @@ +#include "main_window.h" + +#include +#include +#include + +#include "device_controller_factory.h" +#include "layout_style.h" +#include "localization.h" +#include "log.h" +#include "platform.h" +#include "screen_capturer_factory.h" + +// Refresh Event +#define REFRESH_EVENT (SDL_USEREVENT + 1) +#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 + +MainWindow::MainWindow() {} + +MainWindow::~MainWindow() {} + +int MainWindow::SaveSettingsIntoCacheFile() { + cd_cache_file_ = fopen("cache.cd", "w+"); + if (!cd_cache_file_) { + return -1; + } + + fseek(cd_cache_file_, 0, SEEK_SET); + strncpy(cd_cache_.password, input_password_, sizeof(input_password_)); + memcpy(&cd_cache_.language, &language_button_value_, + sizeof(language_button_value_)); + memcpy(&cd_cache_.video_quality, &video_quality_button_value_, + sizeof(video_quality_button_value_)); + memcpy(&cd_cache_.video_encode_format, &video_encode_format_button_value_, + sizeof(video_encode_format_button_value_)); + memcpy(&cd_cache_.enable_hardware_video_codec, &enable_hardware_video_codec_, + sizeof(enable_hardware_video_codec_)); + fwrite(&cd_cache_, sizeof(cd_cache_), 1, cd_cache_file_); + fclose(cd_cache_file_); + + return 0; +} + +int MainWindow::LoadSettingsIntoCacheFile() { + cd_cache_file_ = fopen("cache.cd", "r+"); + if (!cd_cache_file_) { + return -1; + } + + fseek(cd_cache_file_, 0, SEEK_SET); + fread(&cd_cache_, sizeof(cd_cache_), 1, cd_cache_file_); + fclose(cd_cache_file_); + strncpy(input_password_, cd_cache_.password, sizeof(cd_cache_.password)); + language_button_value_ = cd_cache_.language; + video_quality_button_value_ = cd_cache_.video_quality; + video_encode_format_button_value_ = cd_cache_.video_encode_format; + enable_hardware_video_codec_ = cd_cache_.enable_hardware_video_codec; + + return 0; +} + +int MainWindow::StartScreenCapture() { + screen_capturer_ = (ScreenCapturer *)screen_capturer_factory_->Create(); + ScreenCapturer::RECORD_DESKTOP_RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = screen_width_; + rect.bottom = screen_height_; + last_frame_time_ = std::chrono::high_resolution_clock::now(); + + int screen_capturer_init_ret = screen_capturer_->Init( + rect, 60, + [this](unsigned char *data, int size, int width, int height) -> void { + auto now_time = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = now_time - last_frame_time_; + auto tc = duration.count() * 1000; + + if (tc >= 0) { + SendData(peer_, DATA_TYPE::VIDEO, (const char *)data, + NV12_BUFFER_SIZE); + last_frame_time_ = now_time; + } + }); + + if (0 == screen_capturer_init_ret) { + screen_capturer_->Start(); + } else { + screen_capturer_->Destroy(); + delete screen_capturer_; + screen_capturer_ = nullptr; + } + + return 0; +} + +int MainWindow::StopScreenCapture() { + if (screen_capturer_) { + LOG_INFO("Destroy screen capturer") + screen_capturer_->Destroy(); + delete screen_capturer_; + screen_capturer_ = nullptr; + } + + return 0; +} + +int MainWindow::StartMouseControl() { + device_controller_factory_ = new DeviceControllerFactory(); + mouse_controller_ = (MouseController *)device_controller_factory_->Create( + DeviceControllerFactory::Device::Mouse); + int mouse_controller_init_ret = + mouse_controller_->Init(screen_width_, screen_height_); + if (0 != mouse_controller_init_ret) { + LOG_INFO("Destroy mouse controller") + mouse_controller_->Destroy(); + mouse_controller_ = nullptr; + } + + return 0; +} + +int MainWindow::StopMouseControl() { + if (mouse_controller_) { + mouse_controller_->Destroy(); + delete mouse_controller_; + mouse_controller_ = nullptr; + } + return 0; +} + +int MainWindow::CreateConnectionPeer() { + mac_addr_str_ = GetMac(); + + params_.use_cfg_file = false; + params_.signal_server_ip = "150.158.81.30"; + params_.signal_server_port = 9099; + params_.stun_server_ip = "150.158.81.30"; + params_.stun_server_port = 3478; + params_.turn_server_ip = "150.158.81.30"; + params_.turn_server_port = 3478; + params_.turn_server_username = "dijunkun"; + params_.turn_server_password = "dijunkunpw"; + params_.hardware_acceleration = config_center_.IsHardwareVideoCodec(); + params_.av1_encoding = config_center_.GetVideoEncodeFormat() == + ConfigCenter::VIDEO_ENCODE_FORMAT::AV1 + ? true + : false; + params_.on_receive_video_buffer = OnReceiveVideoBufferCb; + params_.on_receive_audio_buffer = OnReceiveAudioBufferCb; + params_.on_receive_data_buffer = OnReceiveDataBufferCb; + params_.on_signal_status = OnSignalStatusCb; + params_.on_connection_status = OnConnectionStatusCb; + params_.user_data = this; + + peer_ = CreatePeer(¶ms_); + if (peer_) { + LOG_INFO("Create peer instance successful"); + local_id_ = mac_addr_str_; + Init(peer_, local_id_.c_str()); + LOG_INFO("Peer init finish"); + } else { + LOG_INFO("Create peer instance failed"); + } + + return 0; +} + +int MainWindow::Run() { + LoadSettingsIntoCacheFile(); + + localization_language_ = (ConfigCenter::LANGUAGE)language_button_value_; + localization_language_index_ = language_button_value_; + + // Setup SDL + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | + SDL_INIT_GAMECONTROLLER) != 0) { + printf("Error: %s\n", SDL_GetError()); + return -1; + } + + // From 2.0.18: Enable native IME. +#ifdef SDL_HINT_IME_SHOW_UI + SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1"); +#endif + + // Create main window with SDL_Renderer graphics context + SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_ALLOW_HIGHDPI); + main_window_ = SDL_CreateWindow("Remote Desk", SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, main_window_width_, + main_window_height_, window_flags); + + SDL_DisplayMode DM; + SDL_GetCurrentDisplayMode(0, &DM); + screen_width_ = DM.w; + screen_height_ = DM.h; + + sdl_renderer_ = SDL_CreateRenderer( + main_window_, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + if (sdl_renderer_ == nullptr) { + SDL_Log("Error creating SDL_Renderer!"); + return 0; + } + + pixformat_ = SDL_PIXELFORMAT_NV12; + + sdl_texture_ = + SDL_CreateTexture(sdl_renderer_, pixformat_, SDL_TEXTUREACCESS_STREAMING, + texture_width_, texture_height_); + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO &io = ImGui::GetIO(); + + io.ConfigFlags |= + ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= + ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + + if (config_center_.GetLanguage() == ConfigCenter::LANGUAGE::CHINESE) { + // Load Fonts +#ifdef _WIN32 + std::string default_font_path = "c:/windows/fonts/simhei.ttf"; + std::ifstream font_path_f(default_font_path.c_str()); + std::string font_path = + font_path_f.good() ? "c:/windows/fonts/simhei.ttf" : ""; + if (!font_path.empty()) { + io.Fonts->AddFontFromFileTTF(font_path.c_str(), 30.0f, NULL, + io.Fonts->GetGlyphRangesChineseFull()); + } +#elif __APPLE__ + std::string default_font_path = "/System/Library/Fonts/PingFang.ttc"; + std::ifstream font_path_f(default_font_path.c_str()); + std::string font_path = + font_path_f.good() ? "/System/Library/Fonts/PingFang.ttc" : ""; + if (!font_path.empty()) { + io.Fonts->AddFontFromFileTTF(font_path.c_str(), 13.0f, NULL, + io.Fonts->GetGlyphRangesChineseFull()); + } +#elif __linux__ + io.Fonts->AddFontFromFileTTF("c:/windows/fonts/msyh.ttc", 13.0f, NULL, + io.Fonts->GetGlyphRangesChineseFull()); +#endif + } + + // Setup Dear ImGui style + // ImGui::StyleColorsDark(); + ImGui::StyleColorsLight(); + + // Setup Platform/Renderer backends + ImGui_ImplSDL2_InitForSDLRenderer(main_window_, sdl_renderer_); + ImGui_ImplSDLRenderer2_Init(sdl_renderer_); + + CreateConnectionPeer(); + + { + nv12_buffer_ = new char[NV12_BUFFER_SIZE]; + + // Screen capture + screen_capturer_factory_ = new ScreenCapturerFactory(); + + // Mouse control + device_controller_factory_ = new DeviceControllerFactory(); + } + + // Main loop + while (!exit_) { + if (SignalStatus::SignalConnected == signal_status_ && + !is_create_connection_) { + is_create_connection_ = + CreateConnection(peer_, mac_addr_str_.c_str(), input_password_) + ? false + : true; + LOG_INFO("Connected with signal server, create p2p connection"); + } + + if (!inited_ || + localization_language_index_last_ != localization_language_index_) { + connect_button_label_ = + connect_button_pressed_ + ? localization::disconnect[localization_language_index_] + : localization::connect[localization_language_index_]; + fullscreen_button_label_ = + fullscreen_button_pressed_ + ? localization::exit_fullscreen[localization_language_index_] + : localization::fullscreen[localization_language_index_]; + + mouse_control_button_label_ = + mouse_control_button_pressed_ + ? localization::release_mouse[localization_language_index_] + : localization::control_mouse[localization_language_index_]; + + settings_button_label_ = + localization::settings[localization_language_index_]; + inited_ = true; + localization_language_index_last_ = localization_language_index_; + } + + if (start_screen_capture_ && !screen_capture_is_started_) { + StartScreenCapture(); + screen_capture_is_started_ = true; + } else if (!start_screen_capture_ && screen_capture_is_started_) { + StopScreenCapture(); + screen_capture_is_started_ = false; + } + + if (start_mouse_control_ && !mouse_control_is_started_) { + StartMouseControl(); + mouse_control_is_started_ = true; + } else if (!start_mouse_control_ && mouse_control_is_started_) { + StopMouseControl(); + mouse_control_is_started_ = false; + } + + // Start the Dear ImGui frame + ImGui_ImplSDLRenderer2_NewFrame(); + ImGui_ImplSDL2_NewFrame(); + ImGui::NewFrame(); + + // main window layout + { + ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Once); + + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetNextWindowSize( + ImVec2(MENU_WINDOW_WIDTH_CN, MENU_WINDOW_HEIGHT_CN)); + } else { + ImGui::SetNextWindowSize( + ImVec2(MENU_WINDOW_WIDTH_EN, MENU_WINDOW_HEIGHT_EN)); + } + + if (!connection_established_) { + ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); + ImGui::Begin(localization::menu[localization_language_index_].c_str(), + nullptr, + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar); + ImGui::SetWindowFontScale(0.5f); + ImGui::Text(u8""); + } else { + // ImGui::SetNextWindowCollapsed(true, ImGuiCond_Once); + ImGui::Begin(localization::menu[localization_language_index_].c_str(), + nullptr, ImGuiWindowFlags_None); + } + + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Spacing(); + + { + // local + { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 0, 0, 0.3)); + ImGui::Text( + localization::local_id[localization_language_index_].c_str()); + ImGui::PopStyleColor(); + + ImGui::SetNextItemWidth(IPUT_WINDOW_WIDTH); + ImGui::Spacing(); + ImGui::SetWindowFontScale(1.0f); + ImGui::InputText("##local_id", (char *)mac_addr_str_.c_str(), + mac_addr_str_.length() + 1, + ImGuiInputTextFlags_CharsUppercase | + ImGuiInputTextFlags_ReadOnly); + ImGui::SetWindowFontScale(0.5f); + ImGui::Text( + localization::password[localization_language_index_].c_str()); + + strncpy(input_password_tmp_, input_password_, + sizeof(input_password_)); + ImGui::SetNextItemWidth(IPUT_WINDOW_WIDTH); + ImGui::Spacing(); + ImGui::SetWindowFontScale(1.0f); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 0, 0, 0.3)); + + ImGui::InputTextWithHint( + "##server_pwd", + localization::max_password_len[localization_language_index_] + .c_str(), + input_password_, IM_ARRAYSIZE(input_password_), + show_password_ ? ImGuiInputTextFlags_CharsNoBlank + : ImGuiInputTextFlags_CharsNoBlank | + ImGuiInputTextFlags_Password); + ImGui::SameLine(); + ImGui::SetWindowFontScale(0.5f); + if (ImGui::Button(u8"鿴", ImVec2(80, 35))) { + show_password_ = !show_password_; + } + + ImGui::PopStyleColor(); + + if (strcmp(input_password_tmp_, input_password_)) { + SaveSettingsIntoCacheFile(); + } + } + } + + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Spacing(); + + ImGui::SetWindowFontScale(0.5f); + // Mouse control + if (ImGui::Button(mouse_control_button_label_.c_str())) { + if (mouse_control_button_label_ == + localization::control_mouse[localization_language_index_] && + connection_established_) { + mouse_control_button_pressed_ = true; + control_mouse_ = true; + mouse_control_button_label_ = + localization::release_mouse[localization_language_index_]; + } else { + control_mouse_ = false; + mouse_control_button_label_ = + localization::control_mouse[localization_language_index_]; + } + mouse_control_button_pressed_ = !mouse_control_button_pressed_; + } + + ImGui::SameLine(); + // Fullscreen + if (ImGui::Button(fullscreen_button_label_.c_str())) { + if (fullscreen_button_label_ == + localization::fullscreen[localization_language_index_]) { + main_window_width_before_fullscreen_ = main_window_width_; + main_window_height_before_fullscreen_ = main_window_height_; + SDL_SetWindowFullscreen(main_window_, SDL_WINDOW_FULLSCREEN_DESKTOP); + fullscreen_button_label_ = + localization::exit_fullscreen[localization_language_index_]; + } else { + SDL_SetWindowFullscreen(main_window_, SDL_FALSE); + SDL_SetWindowSize(main_window_, main_window_width_before_fullscreen_, + main_window_height_before_fullscreen_); + main_window_width_ = main_window_width_before_fullscreen_; + main_window_height_ = main_window_height_before_fullscreen_; + fullscreen_button_label_ = + localization::fullscreen[localization_language_index_]; + } + fullscreen_button_pressed_ = !fullscreen_button_pressed_; + } + + ImGui::Spacing(); + + ImGui::Separator(); + + ImGui::Spacing(); + + if (ImGui::Button(settings_button_label_.c_str())) { + settings_button_pressed_ = !settings_button_pressed_; + settings_window_pos_reset_ = true; + } + + if (settings_button_pressed_) { + if (settings_window_pos_reset_) { + const ImGuiViewport *viewport = ImGui::GetMainViewport(); + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetNextWindowPos( + ImVec2((viewport->WorkSize.x - viewport->WorkPos.x - + SETTINGS_WINDOW_WIDTH_CN) / + 2, + (viewport->WorkSize.y - viewport->WorkPos.y - + SETTINGS_WINDOW_HEIGHT_CN) / + 2)); + + ImGui::SetNextWindowSize( + ImVec2(SETTINGS_WINDOW_WIDTH_CN, SETTINGS_WINDOW_HEIGHT_CN)); + } else { + ImGui::SetNextWindowPos( + ImVec2((viewport->WorkSize.x - viewport->WorkPos.x - + SETTINGS_WINDOW_WIDTH_EN) / + 2, + (viewport->WorkSize.y - viewport->WorkPos.y - + SETTINGS_WINDOW_HEIGHT_EN) / + 2)); + + ImGui::SetNextWindowSize( + ImVec2(SETTINGS_WINDOW_WIDTH_EN, SETTINGS_WINDOW_HEIGHT_EN)); + } + + settings_window_pos_reset_ = false; + } + + // Settings + ImGui::Begin( + localization::settings[localization_language_index_].c_str(), + nullptr, + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoSavedSettings); + + { + const char *language_items[] = { + localization::language_zh[localization_language_index_].c_str(), + localization::language_en[localization_language_index_].c_str()}; + + ImGui::SetCursorPosY(32); + ImGui::Text( + localization::language[localization_language_index_].c_str()); + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetCursorPosX(LANGUAGE_SELECT_WINDOW_PADDING_CN); + } else { + ImGui::SetCursorPosX(LANGUAGE_SELECT_WINDOW_PADDING_EN); + } + ImGui::SetCursorPosY(30); + ImGui::SetNextItemWidth(SETTINGS_SELECT_WINDOW_WIDTH); + + ImGui::Combo("##language", &language_button_value_, language_items, + IM_ARRAYSIZE(language_items)); + } + + ImGui::Separator(); + + { + const char *video_quality_items[] = { + localization::video_quality_high[localization_language_index_] + .c_str(), + localization::video_quality_medium[localization_language_index_] + .c_str(), + localization::video_quality_low[localization_language_index_] + .c_str()}; + + ImGui::SetCursorPosY(62); + ImGui::Text(localization::video_quality[localization_language_index_] + .c_str()); + + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetCursorPosX(VIDEO_QUALITY_SELECT_WINDOW_PADDING_CN); + } else { + ImGui::SetCursorPosX(VIDEO_QUALITY_SELECT_WINDOW_PADDING_EN); + } + ImGui::SetCursorPosY(60); + ImGui::SetNextItemWidth(SETTINGS_SELECT_WINDOW_WIDTH); + + ImGui::Combo("##video_quality", &video_quality_button_value_, + video_quality_items, IM_ARRAYSIZE(video_quality_items)); + } + + ImGui::Separator(); + + { + const char *video_encode_format_items[] = { + localization::av1[localization_language_index_].c_str(), + localization::h264[localization_language_index_].c_str()}; + + ImGui::SetCursorPosY(92); + ImGui::Text( + localization::video_encode_format[localization_language_index_] + .c_str()); + + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetCursorPosX(VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_CN); + } else { + ImGui::SetCursorPosX(VIDEO_ENCODE_FORMAT_SELECT_WINDOW_PADDING_EN); + } + ImGui::SetCursorPosY(90); + ImGui::SetNextItemWidth(SETTINGS_SELECT_WINDOW_WIDTH); + + ImGui::Combo("##video_encode_format", + &video_encode_format_button_value_, + video_encode_format_items, + IM_ARRAYSIZE(video_encode_format_items)); + } + + ImGui::Separator(); + + { + ImGui::SetCursorPosY(122); + ImGui::Text(localization::enable_hardware_video_codec + [localization_language_index_] + .c_str()); + + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetCursorPosX( + ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_CN); + } else { + ImGui::SetCursorPosX( + ENABLE_HARDWARE_VIDEO_CODEC_CHECKBOX_PADDING_EN); + } + ImGui::SetCursorPosY(120); + ImGui::Checkbox("##enable_hardware_video_codec", + &enable_hardware_video_codec_); + } + + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetCursorPosX(SETTINGS_OK_BUTTON_PADDING_CN); + } else { + ImGui::SetCursorPosX(SETTINGS_OK_BUTTON_PADDING_EN); + } + ImGui::SetCursorPosY(160.0f); + + // OK + if (ImGui::Button( + localization::ok[localization_language_index_].c_str())) { + settings_button_pressed_ = false; + + // Language + if (language_button_value_ == 0) { + config_center_.SetLanguage(ConfigCenter::LANGUAGE::CHINESE); + } else { + config_center_.SetLanguage(ConfigCenter::LANGUAGE::ENGLISH); + } + language_button_value_last_ = language_button_value_; + localization_language_ = + (ConfigCenter::LANGUAGE)language_button_value_; + localization_language_index_ = language_button_value_; + LOG_INFO("Set localization language: {}", + localization_language_index_ == 0 ? "zh" : "en"); + + // Video quality + if (video_quality_button_value_ == 0) { + config_center_.SetVideoQuality(ConfigCenter::VIDEO_QUALITY::HIGH); + } else if (video_quality_button_value_ == 1) { + config_center_.SetVideoQuality(ConfigCenter::VIDEO_QUALITY::MEDIUM); + } else { + config_center_.SetVideoQuality(ConfigCenter::VIDEO_QUALITY::LOW); + } + video_quality_button_value_last_ = video_quality_button_value_; + + // Video encode format + if (video_encode_format_button_value_ == 0) { + config_center_.SetVideoEncodeFormat( + ConfigCenter::VIDEO_ENCODE_FORMAT::AV1); + } else if (video_encode_format_button_value_ == 1) { + config_center_.SetVideoEncodeFormat( + ConfigCenter::VIDEO_ENCODE_FORMAT::H264); + } + video_encode_format_button_value_last_ = + video_encode_format_button_value_; + + // Hardware video codec + if (enable_hardware_video_codec_) { + config_center_.SetHardwareVideoCodec(true); + } else { + config_center_.SetHardwareVideoCodec(false); + } + enable_hardware_video_codec_last_ = enable_hardware_video_codec_; + + SaveSettingsIntoCacheFile(); + settings_window_pos_reset_ = true; + + // Recreate peer instance + LoadSettingsIntoCacheFile(); + + // Recreate peer instance + { + DestroyPeer(peer_); + CreateConnectionPeer(); + LOG_INFO("Recreate peer instance successful"); + } + } + ImGui::SameLine(); + // Cancel + if (ImGui::Button( + localization::cancel[localization_language_index_].c_str())) { + settings_button_pressed_ = false; + if (language_button_value_ != language_button_value_last_) { + language_button_value_ = language_button_value_last_; + } + + if (video_quality_button_value_ != video_quality_button_value_last_) { + video_quality_button_value_ = video_quality_button_value_last_; + } + + if (video_encode_format_button_value_ != + video_encode_format_button_value_last_) { + video_encode_format_button_value_ = + video_encode_format_button_value_last_; + } + + if (enable_hardware_video_codec_ != + enable_hardware_video_codec_last_) { + enable_hardware_video_codec_ = enable_hardware_video_codec_last_; + } + + settings_window_pos_reset_ = true; + } + + ImGui::End(); + } + + ImGui::End(); + } + + { + ImGui::SetNextWindowPos(ImVec2(MENU_WINDOW_WIDTH_CN, 0), + ImGuiCond_Always); + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetNextWindowSize( + ImVec2(MENU_WINDOW_WIDTH_CN, MENU_WINDOW_HEIGHT_CN)); + } else { + ImGui::SetNextWindowSize( + ImVec2(MENU_WINDOW_WIDTH_EN, MENU_WINDOW_HEIGHT_EN)); + } + ImGui::Begin("test", nullptr, + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar); + + ImGui::SetWindowFontScale(0.5f); + ImGui::Text(u8"Զ̿"); + + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Spacing(); + + { + ImGui::Text( + localization::remote_id[localization_language_index_].c_str()); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(IPUT_WINDOW_WIDTH); + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetCursorPosX(INPUT_WINDOW_PADDING_CN); + } else { + ImGui::SetCursorPosX(INPUT_WINDOW_PADDING_EN); + } + ImGui::SetWindowFontScale(1.0f); + ImGui::InputTextWithHint("##remote_id_", mac_addr_str_.c_str(), + remote_id_, IM_ARRAYSIZE(remote_id_), + ImGuiInputTextFlags_CharsUppercase | + ImGuiInputTextFlags_CharsNoBlank); + + ImGui::Spacing(); + ImGui::SetWindowFontScale(0.5f); + ImGui::Text( + localization::password[localization_language_index_].c_str()); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(IPUT_WINDOW_WIDTH); + + if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { + ImGui::SetCursorPosX(INPUT_WINDOW_PADDING_CN); + } else { + ImGui::SetCursorPosX(INPUT_WINDOW_PADDING_EN); + } + ImGui::SetWindowFontScale(1.0f); + ImGui::InputTextWithHint( + "##client_pwd", + localization::max_password_len[localization_language_index_] + .c_str(), + client_password_, IM_ARRAYSIZE(client_password_), + ImGuiInputTextFlags_CharsNoBlank); + + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Spacing(); + + if (ImGui::Button(connect_button_label_.c_str(), + ImVec2(MENU_WINDOW_WIDTH_CN - 16, 40)) || + rejoin_) { + int ret = -1; + if ("SignalConnected" == signal_status_str_) { + if (connect_button_label_ == + localization::connect[localization_language_index_] && + !connection_established_ && strlen(remote_id_)) { + if (remote_id_ == local_id_ && !peer_reserved_) { + peer_reserved_ = CreatePeer(¶ms_); + if (peer_reserved_) { + LOG_INFO("Create peer[reserved] instance successful"); + std::string local_id = "C-" + mac_addr_str_; + Init(peer_reserved_, local_id.c_str()); + LOG_INFO("Peer[reserved] init finish"); + } else { + LOG_INFO("Create peer[reserved] instance failed"); + } + } + ret = JoinConnection(peer_reserved_ ? peer_reserved_ : peer_, + remote_id_, client_password_); + if (0 == ret) { + if (!peer_reserved_) { + is_client_mode_ = true; + } + rejoin_ = false; + } else { + rejoin_ = true; + } + + } else if (connect_button_label_ == + localization::disconnect + [localization_language_index_] && + connection_established_) { + ret = LeaveConnection(peer_reserved_ ? peer_reserved_ : peer_); + + if (0 == ret) { + rejoin_ = false; + memset(audio_buffer_, 0, 960); + connection_established_ = false; + received_frame_ = false; + is_client_mode_ = false; + } + } + + if (0 == ret) { + connect_button_pressed_ = !connect_button_pressed_; + connect_button_label_ = + connect_button_pressed_ + ? localization::disconnect[localization_language_index_] + : localization::connect[localization_language_index_]; + } + } + } + } + ImGui::End(); + } + + SDL_Event event; + while (SDL_PollEvent(&event)) { + ImGui_ImplSDL2_ProcessEvent(&event); + if (event.type == SDL_QUIT) { + exit_ = true; + } else if (event.type == SDL_WINDOWEVENT && + event.window.event == SDL_WINDOWEVENT_RESIZED) { + int window_w_last = main_window_width_; + int window_h_last = main_window_height_; + + SDL_GetWindowSize(main_window_, &main_window_width_, + &main_window_height_); + + int w_change_ratio = abs(main_window_width_ - window_w_last) / 16; + int h_change_ratio = abs(main_window_height_ - window_h_last) / 9; + + if (w_change_ratio > h_change_ratio) { + main_window_height_ = main_window_width_ * 9 / 16; + } else { + main_window_width_ = main_window_height_ * 16 / 9; + } + + SDL_SetWindowSize(main_window_, main_window_width_, + main_window_height_); + } else if (event.type == SDL_WINDOWEVENT && + event.window.event == SDL_WINDOWEVENT_CLOSE && + event.window.windowID == SDL_GetWindowID(main_window_)) { + exit_ = true; + } else if (event.type == REFRESH_EVENT) { + sdl_rect_.x = 0; + sdl_rect_.y = 0; + sdl_rect_.w = main_window_width_; + sdl_rect_.h = main_window_height_; + + // SDL_UpdateTexture(sdl_texture_, NULL, dst_buffer_, 1280); + } else { + if (connection_established_) { + ProcessMouseKeyEven(event); + } + } + } + + // Rendering + ImGui::Render(); + SDL_RenderSetScale(sdl_renderer_, io.DisplayFramebufferScale.x, + io.DisplayFramebufferScale.y); + SDL_SetRenderDrawColor(sdl_renderer_, 255, 255, 255, 255); + SDL_RenderClear(sdl_renderer_); + ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData()); + SDL_RenderPresent(sdl_renderer_); + + frame_count_++; + end_time_ = SDL_GetTicks(); + elapsed_time_ = end_time_ - start_time_; + if (elapsed_time_ >= 1000) { + fps_ = frame_count_ / (elapsed_time_ / 1000); + frame_count_ = 0; + window_title = "Remote Desk Client FPS [" + std::to_string(fps_) + + "] status [" + connection_status_str_ + "|" + + connection_status_str_ + "]"; + // For MacOS, UI frameworks can only be called from the main thread + SDL_SetWindowTitle(main_window_, window_title.c_str()); + start_time_ = end_time_; + } + } + + // Cleanup + if (is_create_connection_) { + LeaveConnection(peer_); + is_client_mode_ = false; + } + + if (peer_) { + DestroyPeer(peer_); + } + + if (peer_reserved_) { + DestroyPeer(peer_reserved_); + } + + SDL_CloseAudioDevice(output_dev_); + SDL_CloseAudioDevice(input_dev_); + + ImGui_ImplSDLRenderer2_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); + + SDL_DestroyRenderer(sdl_renderer_); + SDL_DestroyWindow(main_window_); + + SDL_CloseAudio(); + SDL_Quit(); + + return 0; +} \ No newline at end of file diff --git a/src/multiple_windows/main_window.h b/src/multiple_windows/main_window.h new file mode 100644 index 0000000..ee9e9ec --- /dev/null +++ b/src/multiple_windows/main_window.h @@ -0,0 +1,191 @@ +/* + * @Author: DI JUNKUN + * @Date: 2024-05-29 + * Copyright (c) 2024 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _MAIN_WINDOW_H_ +#define _MAIN_WINDOW_H_ + +#include + +#include +#include +#include + +#include "../../thirdparty/projectx/src/interface/x.h" +#include "config_center.h" +#include "device_controller_factory.h" +#include "imgui.h" +#include "imgui_impl_sdl2.h" +#include "imgui_impl_sdlrenderer2.h" +#include "screen_capturer_factory.h" + +class MainWindow { + public: + MainWindow(); + ~MainWindow(); + + public: + int Run(); + + public: + static void OnReceiveVideoBufferCb(const char *data, size_t size, + const char *user_id, size_t user_id_size, + void *user_data); + + static void OnReceiveAudioBufferCb(const char *data, size_t size, + const char *user_id, size_t user_id_size, + void *user_data); + + static void OnReceiveDataBufferCb(const char *data, size_t size, + const char *user_id, size_t user_id_size, + void *user_data); + + static void OnSignalStatusCb(SignalStatus status, void *user_data); + + static void OnConnectionStatusCb(ConnectionStatus status, void *user_data); + + private: + int ProcessMouseKeyEven(SDL_Event &ev); + void SdlCaptureAudioIn(void *userdata, Uint8 *stream, int len); + void SdlCaptureAudioOut(void *userdata, Uint8 *stream, int len); + + private: + int SaveSettingsIntoCacheFile(); + int LoadSettingsIntoCacheFile(); + + int StartScreenCapture(); + int StopScreenCapture(); + + int StartMouseControl(); + int StopMouseControl(); + + int CreateConnectionPeer(); + + private: + typedef struct { + char password[7]; + int language; + int video_quality; + int video_encode_format; + bool enable_hardware_video_codec; + } CDCache; + + private: + FILE *cd_cache_file_ = nullptr; + CDCache cd_cache_; + + ConfigCenter config_center_; + + ConfigCenter::LANGUAGE localization_language_ = + ConfigCenter::LANGUAGE::CHINESE; + + int localization_language_index_ = -1; + int localization_language_index_last_ = -1; + + private: + std::string window_title = "Remote Desk Client"; + std::string mac_addr_str_ = ""; + std::string connect_button_label_ = "Connect"; + std::string fullscreen_button_label_ = "Fullscreen"; + std::string mouse_control_button_label_ = "Mouse Control"; + std::string settings_button_label_ = "Setting"; + char input_password_tmp_[7] = ""; + char input_password_[7] = ""; + std::string local_id_ = ""; + char remote_id_[20] = ""; + char client_password_[20] = ""; + bool is_client_mode_ = false; + + private: + int screen_width_ = 1280; + int screen_height_ = 720; + int main_window_width_ = 640; + int main_window_height_ = 360; + int main_window_width_before_fullscreen_ = 1280; + int main_window_height_before_fullscreen_ = 720; + + int texture_width_ = 1280; + int texture_height_ = 720; + + SDL_Texture *sdl_texture_ = nullptr; + SDL_Renderer *sdl_renderer_ = nullptr; + SDL_Rect sdl_rect_; + SDL_Window *main_window_; + uint32_t pixformat_ = 0; + + bool inited_ = false; + bool exit_ = false; + bool connection_established_ = false; + bool subwindow_hovered_ = false; + bool connect_button_pressed_ = false; + bool fullscreen_button_pressed_ = false; + bool mouse_control_button_pressed_ = false; + bool settings_button_pressed_ = false; + bool received_frame_ = false; + bool is_create_connection_ = false; + bool audio_buffer_fresh_ = false; + bool rejoin_ = false; + bool control_mouse_ = false; + bool show_password_ = false; + + int fps_ = 0; + uint32_t start_time_; + uint32_t end_time_; + uint32_t elapsed_time_; + uint32_t frame_count_ = 0; + + private: + ConnectionStatus connection_status_ = ConnectionStatus::Closed; + SignalStatus signal_status_ = SignalStatus::SignalClosed; + std::string signal_status_str_ = ""; + std::string connection_status_str_ = ""; + + private: + PeerPtr *peer_ = nullptr; + PeerPtr *peer_reserved_ = nullptr; + Params params_; + + private: + SDL_AudioDeviceID input_dev_; + SDL_AudioDeviceID output_dev_; + unsigned char audio_buffer_[960]; + int audio_len_ = 0; + char *nv12_buffer_ = nullptr; + unsigned char *dst_buffer_ = new unsigned char[1280 * 720 * 3]; + + private: + ScreenCapturerFactory *screen_capturer_factory_ = nullptr; + ScreenCapturer *screen_capturer_ = nullptr; + DeviceControllerFactory *device_controller_factory_ = nullptr; + MouseController *mouse_controller_ = nullptr; + +#ifdef __linux__ + std::chrono::_V2::system_clock::time_point last_frame_time_; +#else + std::chrono::steady_clock::time_point last_frame_time_; +#endif + + private: + int language_button_value_ = 0; + int video_quality_button_value_ = 0; + int video_encode_format_button_value_ = 0; + bool enable_hardware_video_codec_ = false; + + int language_button_value_last_ = 0; + int video_quality_button_value_last_ = 0; + int video_encode_format_button_value_last_ = 0; + bool enable_hardware_video_codec_last_ = false; + + private: + std::atomic start_screen_capture_{false}; + std::atomic start_mouse_control_{false}; + std::atomic screen_capture_is_started_{false}; + std::atomic mouse_control_is_started_{false}; + + private: + bool settings_window_pos_reset_ = true; +}; + +#endif \ No newline at end of file diff --git a/src/main_window/main_window_callback_func.cpp b/src/multiple_windows/main_window_callback_func.cpp similarity index 100% rename from src/main_window/main_window_callback_func.cpp rename to src/multiple_windows/main_window_callback_func.cpp diff --git a/src/multiple_windows/sub_window.cpp b/src/multiple_windows/sub_window.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/multiple_windows/sub_window.h b/src/multiple_windows/sub_window.h new file mode 100644 index 0000000..9e9b443 --- /dev/null +++ b/src/multiple_windows/sub_window.h @@ -0,0 +1,10 @@ +/* + * @Author: DI JUNKUN + * @Date: 2024-06-17 + * Copyright (c) 2024 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _SUB_WINDOW_H_ +#define _SUB_WINDOW_H_ + +#endif \ No newline at end of file diff --git a/src/main_window/layout_style.h b/src/single_window/layout_style.h similarity index 100% rename from src/main_window/layout_style.h rename to src/single_window/layout_style.h diff --git a/src/main_window/main_window.cpp b/src/single_window/main_window.cpp similarity index 100% rename from src/main_window/main_window.cpp rename to src/single_window/main_window.cpp diff --git a/src/main_window/main_window.h b/src/single_window/main_window.h similarity index 100% rename from src/main_window/main_window.h rename to src/single_window/main_window.h diff --git a/src/single_window/main_window_callback_func.cpp b/src/single_window/main_window_callback_func.cpp new file mode 100644 index 0000000..3929154 --- /dev/null +++ b/src/single_window/main_window_callback_func.cpp @@ -0,0 +1,216 @@ +#include "device_controller.h" +#include "localization.h" +#include "main_window.h" + +// Refresh Event +#define REFRESH_EVENT (SDL_USEREVENT + 1) +#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 + +#ifdef REMOTE_DESK_DEBUG +#else +#define MOUSE_CONTROL 1 +#endif + +int MainWindow::ProcessMouseKeyEven(SDL_Event &ev) { + if (!control_mouse_) { + return 0; + } + + float ratio = (float)(1280.0 / main_window_width_); + + RemoteAction remote_action; + remote_action.m.x = (size_t)(ev.button.x * ratio); + remote_action.m.y = (size_t)(ev.button.y * ratio); + + if (SDL_KEYDOWN == ev.type) // SDL_KEYUP + { + // printf("SDLK_DOWN: %d\n", SDL_KeyCode(ev.key.keysym.sym)); + if (SDLK_DOWN == ev.key.keysym.sym) { + // printf("SDLK_DOWN \n"); + + } else if (SDLK_UP == ev.key.keysym.sym) { + // printf("SDLK_UP \n"); + + } else if (SDLK_LEFT == ev.key.keysym.sym) { + // printf("SDLK_LEFT \n"); + + } else if (SDLK_RIGHT == ev.key.keysym.sym) { + // printf("SDLK_RIGHT \n"); + } + } else if (SDL_MOUSEBUTTONDOWN == ev.type) { + remote_action.type = ControlType::mouse; + if (SDL_BUTTON_LEFT == ev.button.button) { + remote_action.m.flag = MouseFlag::left_down; + } else if (SDL_BUTTON_RIGHT == ev.button.button) { + remote_action.m.flag = MouseFlag::right_down; + } + if (subwindow_hovered_) { + remote_action.m.flag = MouseFlag::move; + } + SendData(peer_, DATA_TYPE::DATA, (const char *)&remote_action, + sizeof(remote_action)); + } else if (SDL_MOUSEBUTTONUP == ev.type) { + remote_action.type = ControlType::mouse; + if (SDL_BUTTON_LEFT == ev.button.button) { + remote_action.m.flag = MouseFlag::left_up; + } else if (SDL_BUTTON_RIGHT == ev.button.button) { + remote_action.m.flag = MouseFlag::right_up; + } + if (subwindow_hovered_) { + remote_action.m.flag = MouseFlag::move; + } + SendData(peer_, DATA_TYPE::DATA, (const char *)&remote_action, + sizeof(remote_action)); + } else if (SDL_MOUSEMOTION == ev.type) { + remote_action.type = ControlType::mouse; + remote_action.m.flag = MouseFlag::move; + SendData(peer_, DATA_TYPE::DATA, (const char *)&remote_action, + sizeof(remote_action)); + } else if (SDL_QUIT == ev.type) { + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); + printf("SDL_QUIT\n"); + return 0; + } + + return 0; +} + +void MainWindow::SdlCaptureAudioIn(void *userdata, Uint8 *stream, int len) { + if (1) { + if ("Connected" == connection_status_str_) { + SendData(peer_, DATA_TYPE::AUDIO, (const char *)stream, len); + } + } else { + memcpy(audio_buffer_, stream, len); + audio_len_ = len; + SDL_Delay(10); + audio_buffer_fresh_ = true; + } +} + +void MainWindow::SdlCaptureAudioOut(void *userdata, Uint8 *stream, int len) { + if (!audio_buffer_fresh_) { + return; + } + + SDL_memset(stream, 0, len); + + if (audio_len_ == 0) { + return; + } else { + } + + len = (len > audio_len_ ? audio_len_ : len); + SDL_MixAudioFormat(stream, audio_buffer_, AUDIO_S16LSB, len, + SDL_MIX_MAXVOLUME); + audio_buffer_fresh_ = false; +} + +void MainWindow::OnReceiveVideoBufferCb(const char *data, size_t size, + const char *user_id, + size_t user_id_size, void *user_data) { + MainWindow *main_window = (MainWindow *)user_data; + if (main_window->connection_established_) { + memcpy(main_window->dst_buffer_, data, size); + SDL_Event event; + event.type = REFRESH_EVENT; + SDL_PushEvent(&event); + main_window->received_frame_ = true; + } +} + +void MainWindow::OnReceiveAudioBufferCb(const char *data, size_t size, + const char *user_id, + size_t user_id_size, void *user_data) { + MainWindow *main_window = (MainWindow *)user_data; + main_window->audio_buffer_fresh_ = true; + SDL_QueueAudio(main_window->output_dev_, data, (uint32_t)size); +} + +void MainWindow::OnReceiveDataBufferCb(const char *data, size_t size, + const char *user_id, size_t user_id_size, + void *user_data) { + MainWindow *main_window = (MainWindow *)user_data; + std::string user(user_id, user_id_size); + RemoteAction remote_action; + memcpy(&remote_action, data, sizeof(remote_action)); + +#if MOUSE_CONTROL + if (main_window->mouse_controller_) { + main_window->mouse_controller_->SendCommand(remote_action); + } +#endif +} + +void MainWindow::OnSignalStatusCb(SignalStatus status, void *user_data) { + MainWindow *main_window = (MainWindow *)user_data; + main_window->signal_status_ = status; + if (SignalStatus::SignalConnecting == status) { + main_window->signal_status_str_ = "SignalConnecting"; + } else if (SignalStatus::SignalConnected == status) { + main_window->signal_status_str_ = "SignalConnected"; + } else if (SignalStatus::SignalFailed == status) { + main_window->signal_status_str_ = "SignalFailed"; + } else if (SignalStatus::SignalClosed == status) { + main_window->signal_status_str_ = "SignalClosed"; + } else if (SignalStatus::SignalReconnecting == status) { + main_window->signal_status_str_ = "SignalReconnecting"; + } +} + +void MainWindow::OnConnectionStatusCb(ConnectionStatus status, + void *user_data) { + MainWindow *main_window = (MainWindow *)user_data; + main_window->connection_status_ = status; + if (ConnectionStatus::Connecting == status) { + main_window->connection_status_str_ = "Connecting"; + } else if (ConnectionStatus::Connected == status) { + main_window->connection_status_str_ = "Connected"; + main_window->connection_established_ = true; + if (!main_window->is_client_mode_) { + main_window->start_screen_capture_ = true; + main_window->start_mouse_control_ = true; + } + } else if (ConnectionStatus::Disconnected == status) { + main_window->connection_status_str_ = "Disconnected"; + } else if (ConnectionStatus::Failed == status) { + main_window->connection_status_str_ = "Failed"; + } else if (ConnectionStatus::Closed == status) { + main_window->connection_status_str_ = "Closed"; + main_window->start_screen_capture_ = false; + main_window->start_mouse_control_ = false; + main_window->connection_established_ = false; + main_window->control_mouse_ = false; + if (main_window->dst_buffer_) { + memset(main_window->dst_buffer_, 0, 1280 * 720 * 3); + SDL_UpdateTexture(main_window->sdl_texture_, NULL, + main_window->dst_buffer_, 1280); + } + } else if (ConnectionStatus::IncorrectPassword == status) { + main_window->connection_status_str_ = "Incorrect password"; + if (main_window->connect_button_pressed_) { + main_window->connect_button_pressed_ = false; + main_window->connection_established_ = false; + main_window->connect_button_label_ = + main_window->connect_button_pressed_ + ? localization::disconnect[main_window + ->localization_language_index_] + : localization::connect[main_window + ->localization_language_index_]; + } + } else if (ConnectionStatus::NoSuchTransmissionId == status) { + main_window->connection_status_str_ = "No such transmission id"; + if (main_window->connect_button_pressed_) { + main_window->connect_button_pressed_ = false; + main_window->connection_established_ = false; + main_window->connect_button_label_ = + main_window->connect_button_pressed_ + ? localization::disconnect[main_window + ->localization_language_index_] + : localization::connect[main_window + ->localization_language_index_]; + } + } +} diff --git a/xmake.lua b/xmake.lua index aaf8808..2921cd5 100644 --- a/xmake.lua +++ b/xmake.lua @@ -99,7 +99,7 @@ target("localization") set_kind("headeronly") add_includedirs("src/localization", {public = true}) -target("main_window") +target("single_window") set_kind("object") add_deps("log", "common", "localization", "config_center", "projectx", "screen_capturer", "device_controller") if is_os("macosx") then @@ -107,12 +107,23 @@ target("main_window") elseif is_os("linux") then add_packages("ffmpeg") end - add_files("src/main_window/*.cpp") - add_includedirs("src/main_window", {public = true}) + add_files("src/single_window/*.cpp") + add_includedirs("src/single_window", {public = true}) + +target("multiple_windows") + set_kind("object") + add_deps("log", "common", "localization", "config_center", "projectx", "screen_capturer", "device_controller") + if is_os("macosx") then + add_packages("ffmpeg") + elseif is_os("linux") then + add_packages("ffmpeg") + end + add_files("src/multiple_windows/*.cpp") + add_includedirs("src/multiple_windows", {public = true}) target("remote_desk") set_kind("binary") - add_deps("log", "common", "main_window") + add_deps("log", "common", "multiple_windows") if is_os("macosx") then add_packages("ffmpeg") elseif is_os("linux") then