mirror of
				https://github.com/kunkundi/crossdesk.git
				synced 2025-10-26 20:25:34 +08:00 
			
		
		
		
	[fix] fix screen capture error in client mode
This commit is contained in:
		| @@ -1,81 +0,0 @@ | ||||
| /* | ||||
|  * @Author: DI JUNKUN | ||||
|  * @Date: 2024-06-14 | ||||
|  * Copyright (c) 2024 by DI JUNKUN, All Rights Reserved. | ||||
|  */ | ||||
|  | ||||
| #ifndef _LAYOUT_STYLE_H_ | ||||
| #define _LAYOUT_STYLE_H_ | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| #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 86 | ||||
| #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 | ||||
| @@ -1,886 +0,0 @@ | ||||
| #include "render.h" | ||||
|  | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <string> | ||||
|  | ||||
| #include "device_controller_factory.h" | ||||
| #include "layout_style.h" | ||||
| #include "localization.h" | ||||
| #include "platform.h" | ||||
| #include "rd_log.h" | ||||
| #include "screen_capturer_factory.h" | ||||
|  | ||||
| // Refresh Event | ||||
| #define REFRESH_EVENT (SDL_USEREVENT + 1) | ||||
| #define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 | ||||
|  | ||||
| Render::Render() {} | ||||
|  | ||||
| Render::~Render() {} | ||||
|  | ||||
| int Render::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 Render::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 Render::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::steady_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::steady_clock::now(); | ||||
|         std::chrono::duration<double> 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 Render::StopScreenCapture() { | ||||
|   if (screen_capturer_) { | ||||
|     LOG_INFO("Destroy screen capturer") | ||||
|     screen_capturer_->Destroy(); | ||||
|     delete screen_capturer_; | ||||
|     screen_capturer_ = nullptr; | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int Render::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 Render::StopMouseControl() { | ||||
|   if (mouse_controller_) { | ||||
|     mouse_controller_->Destroy(); | ||||
|     delete mouse_controller_; | ||||
|     mouse_controller_ = nullptr; | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int Render::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 Render::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_RESIZABLE | 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(), 13.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_); | ||||
|  | ||||
|   // Our state | ||||
|   ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); | ||||
|  | ||||
|   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(); | ||||
|  | ||||
|     if (connection_established_ && !subwindow_hovered_ && control_mouse_) { | ||||
|       ImGui::SetMouseCursor(ImGuiMouseCursor_None); | ||||
|     } | ||||
|  | ||||
|     // 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("MainWindow", nullptr, | ||||
|                      ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | | ||||
|                          ImGuiWindowFlags_NoMove); | ||||
|       } else { | ||||
|         // ImGui::SetNextWindowCollapsed(true, ImGuiCond_Once); | ||||
|         ImGui::Begin("MainWindow", nullptr, ImGuiWindowFlags_None); | ||||
|       } | ||||
|  | ||||
|       { | ||||
|         subwindow_hovered_ = ImGui::IsWindowHovered(); | ||||
|  | ||||
|         // local | ||||
|         { | ||||
|           ImGui::Text( | ||||
|               localization::local_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::InputText("##local_id", (char *)mac_addr_str_.c_str(), | ||||
|                            mac_addr_str_.length() + 1, | ||||
|                            ImGuiInputTextFlags_CharsUppercase | | ||||
|                                ImGuiInputTextFlags_ReadOnly); | ||||
|  | ||||
|           ImGui::Text( | ||||
|               localization::password[localization_language_index_].c_str()); | ||||
|  | ||||
|           ImGui::SameLine(); | ||||
|  | ||||
|           strncpy(input_password_tmp_, input_password_, | ||||
|                   sizeof(input_password_)); | ||||
|           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::InputTextWithHint( | ||||
|               "##server_pwd", | ||||
|               localization::max_password_len[localization_language_index_] | ||||
|                   .c_str(), | ||||
|               input_password_, IM_ARRAYSIZE(input_password_), | ||||
|               ImGuiInputTextFlags_CharsNoBlank); | ||||
|  | ||||
|           if (strcmp(input_password_tmp_, input_password_)) { | ||||
|             SaveSettingsIntoCacheFile(); | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         ImGui::Spacing(); | ||||
|         ImGui::Separator(); | ||||
|         ImGui::Spacing(); | ||||
|  | ||||
|         // remote | ||||
|         { | ||||
|           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::InputTextWithHint("##remote_id_", mac_addr_str_.c_str(), | ||||
|                                    remote_id_, IM_ARRAYSIZE(remote_id_), | ||||
|                                    ImGuiInputTextFlags_CharsUppercase | | ||||
|                                        ImGuiInputTextFlags_CharsNoBlank); | ||||
|  | ||||
|           ImGui::Spacing(); | ||||
|  | ||||
|           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::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()) || 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::Spacing(); | ||||
|  | ||||
|       ImGui::Separator(); | ||||
|  | ||||
|       ImGui::Spacing(); | ||||
|       // 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())) { | ||||
|         show_settings_window_ = !show_settings_window_; | ||||
|         settings_window_pos_reset_ = true; | ||||
|       } | ||||
|  | ||||
|       if (show_settings_window_) { | ||||
|         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); | ||||
|  | ||||
|         { | ||||
|           subwindow_hovered_ = ImGui::IsWindowHovered(); | ||||
|  | ||||
|           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())) { | ||||
|           show_settings_window_ = 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())) { | ||||
|           show_settings_window_ = 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(); | ||||
|     } | ||||
|  | ||||
|     // Rendering | ||||
|     ImGui::Render(); | ||||
|     SDL_RenderSetScale(sdl_renderer_, io.DisplayFramebufferScale.x, | ||||
|                        io.DisplayFramebufferScale.y); | ||||
|  | ||||
|     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); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     SDL_RenderClear(sdl_renderer_); | ||||
|     SDL_RenderCopy(sdl_renderer_, sdl_texture_, NULL, &sdl_rect_); | ||||
|  | ||||
|     if (!connection_established_ || !received_frame_) { | ||||
|       SDL_RenderClear(sdl_renderer_); | ||||
|       SDL_SetRenderDrawColor( | ||||
|           sdl_renderer_, (Uint8)(clear_color.x * 0), (Uint8)(clear_color.y * 0), | ||||
|           (Uint8)(clear_color.z * 0), (Uint8)(clear_color.w * 0)); | ||||
|     } | ||||
|  | ||||
|     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; | ||||
| } | ||||
| @@ -1,190 +0,0 @@ | ||||
| /* | ||||
|  * @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 <SDL.h> | ||||
|  | ||||
| #include <atomic> | ||||
| #include <chrono> | ||||
| #include <string> | ||||
|  | ||||
| #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 Render { | ||||
|  public: | ||||
|   Render(); | ||||
|   ~Render(); | ||||
|  | ||||
|  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_ = 1280; | ||||
|   int main_window_height_ = 720; | ||||
|   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 show_settings_window_ = false; | ||||
|   bool received_frame_ = false; | ||||
|   bool is_create_connection_ = false; | ||||
|   bool audio_buffer_fresh_ = false; | ||||
|   bool rejoin_ = false; | ||||
|   bool control_mouse_ = 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<bool> start_screen_capture_{false}; | ||||
|   std::atomic<bool> start_mouse_control_{false}; | ||||
|   std::atomic<bool> screen_capture_is_started_{false}; | ||||
|   std::atomic<bool> mouse_control_is_started_{false}; | ||||
|  | ||||
|  private: | ||||
|   bool settings_window_pos_reset_ = true; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -1,215 +0,0 @@ | ||||
| #include "device_controller.h" | ||||
| #include "localization.h" | ||||
| #include "render.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 Render::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 Render::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 Render::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 Render::OnReceiveVideoBufferCb(const char *data, size_t size, | ||||
|                                     const char *user_id, size_t user_id_size, | ||||
|                                     void *user_data) { | ||||
|   Render *main_window = (Render *)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 Render::OnReceiveAudioBufferCb(const char *data, size_t size, | ||||
|                                     const char *user_id, size_t user_id_size, | ||||
|                                     void *user_data) { | ||||
|   Render *main_window = (Render *)user_data; | ||||
|   main_window->audio_buffer_fresh_ = true; | ||||
|   SDL_QueueAudio(main_window->output_dev_, data, (uint32_t)size); | ||||
| } | ||||
|  | ||||
| void Render::OnReceiveDataBufferCb(const char *data, size_t size, | ||||
|                                    const char *user_id, size_t user_id_size, | ||||
|                                    void *user_data) { | ||||
|   Render *main_window = (Render *)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 Render::OnSignalStatusCb(SignalStatus status, void *user_data) { | ||||
|   Render *main_window = (Render *)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 Render::OnConnectionStatusCb(ConnectionStatus status, void *user_data) { | ||||
|   Render *main_window = (Render *)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_]; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -152,7 +152,69 @@ int Render::LoadSettingsFromCacheFile() { | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int Render::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::steady_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::steady_clock::now(); | ||||
|         std::chrono::duration<double> duration = now_time - last_frame_time_; | ||||
|         auto tc = duration.count() * 1000; | ||||
|  | ||||
|         if (tc >= 0 && connection_established_) { | ||||
|           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 Render::StopScreenCapture() { | ||||
|   if (screen_capturer_) { | ||||
|     LOG_INFO("Stop screen capturer") | ||||
|     screen_capturer_->Stop(); | ||||
|     screen_capturer_->Destroy(); | ||||
|     delete screen_capturer_; | ||||
|     screen_capturer_ = nullptr; | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int Render::StartSpeakerCapture() { | ||||
|   if (!speaker_capturer_) { | ||||
|     speaker_capturer_ = (SpeakerCapturer *)speaker_capturer_factory_->Create(); | ||||
|     int speaker_capturer_init_ret = speaker_capturer_->Init( | ||||
|         [this](unsigned char *data, size_t size) -> void { | ||||
|           if (connection_established_) { | ||||
|             SendData(peer_, DATA_TYPE::AUDIO, (const char *)data, size); | ||||
|           } | ||||
|         }); | ||||
|  | ||||
|     if (0 != speaker_capturer_init_ret) { | ||||
|       speaker_capturer_->Destroy(); | ||||
|       delete speaker_capturer_; | ||||
|       speaker_capturer_ = nullptr; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (speaker_capturer_) { | ||||
|     speaker_capturer_->Start(); | ||||
|   } | ||||
| @@ -359,51 +421,9 @@ int Render::Run() { | ||||
|  | ||||
|     // Screen capture init | ||||
|     screen_capturer_factory_ = new ScreenCapturerFactory(); | ||||
|     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::steady_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::steady_clock::now(); | ||||
|           std::chrono::duration<double> duration = now_time - last_frame_time_; | ||||
|           auto tc = duration.count() * 1000; | ||||
|  | ||||
|           if (tc >= 0 && connection_established_) { | ||||
|             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; | ||||
|     } | ||||
|  | ||||
|     // Speaker capture init | ||||
|     speaker_capturer_factory_ = new SpeakerCapturerFactory(); | ||||
|     speaker_capturer_ = (SpeakerCapturer *)speaker_capturer_factory_->Create(); | ||||
|     int speaker_capturer_init_ret = speaker_capturer_->Init( | ||||
|         [this](unsigned char *data, size_t size) -> void { | ||||
|           if (connection_established_) { | ||||
|             SendData(peer_, DATA_TYPE::AUDIO, (const char *)data, size); | ||||
|           } | ||||
|         }); | ||||
|  | ||||
|     if (0 != speaker_capturer_init_ret) { | ||||
|       speaker_capturer_->Destroy(); | ||||
|       delete speaker_capturer_; | ||||
|       speaker_capturer_ = nullptr; | ||||
|     } | ||||
|  | ||||
|     // Mouse control | ||||
|     device_controller_factory_ = new DeviceControllerFactory(); | ||||
| @@ -447,13 +467,13 @@ int Render::Run() { | ||||
|       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_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(); | ||||
|   | ||||
| @@ -77,6 +77,9 @@ class Render { | ||||
|   int SaveSettingsIntoCacheFile(); | ||||
|   int LoadSettingsFromCacheFile(); | ||||
|  | ||||
|   int StartScreenCapture(); | ||||
|   int StopScreenCapture(); | ||||
|  | ||||
|   int StartSpeakerCapture(); | ||||
|   int StopSpeakerCapture(); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user