[feat] separate function Run() into several functions

This commit is contained in:
dijunkun
2025-04-09 16:51:33 +08:00
parent badcd6a05c
commit cf078be53f
3 changed files with 312 additions and 320 deletions

View File

@@ -19,7 +19,7 @@
#define MOUSE_GRAB_PADDING 5
const Uint32 STREAM_FRASH = SDL_RegisterEvents(29);
#define STREAM_FRASH (SDL_USEREVENT + 1)
SDL_HitTestResult Render::HitTestCallback(SDL_Window* window,
const SDL_Point* area, void* data) {
@@ -406,15 +406,7 @@ int Render::AudioDeviceDestroy() {
return 0;
}
int Render::CreateRtcConnection() {
// create connection
if (SignalStatus::SignalConnected == signal_status_ &&
!is_create_connection_ && password_inited_) {
LOG_INFO("Connected with signal server, create p2p connection");
is_create_connection_ =
CreateConnection(peer_, client_id_, password_saved_) ? false : true;
}
void Render::UpdateInteractions() {
if (start_screen_capturer_ && !screen_capturer_is_started_) {
StartScreenCapturer();
screen_capturer_is_started_ = true;
@@ -440,8 +432,6 @@ int Render::CreateRtcConnection() {
StopKeyboardCapturer();
keyboard_capturer_is_started_ = false;
}
return 0;
}
int Render::CreateMainWindow() {
@@ -747,9 +737,24 @@ int Render::DrawStreamWindow() {
return 0;
}
int Render::LoadRecentConnections() { return 0; }
int Render::Run() {
InitializeSettings();
InitializeSDL();
InitializeModules();
InitializeMainWindow();
const int scaled_video_width_ = 160;
const int scaled_video_height_ = 90;
argb_buffer_ = new char[scaled_video_width_ * scaled_video_height_ * 40];
MainLoop();
Cleanup();
return 0;
}
void Render::InitializeSettings() {
LoadSettingsFromCacheFile();
localization_language_ = (ConfigCenter::LANGUAGE)language_button_value_;
@@ -759,60 +764,68 @@ int Render::Run() {
LOG_ERROR("Invalid language index: [{}], use [0] by default",
localization_language_index_);
}
}
// Setup SDL
void Render::InitializeSDL() {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER |
SDL_INIT_GAMECONTROLLER) != 0) {
printf("Error: %s\n", SDL_GetError());
return -1;
exit(-1);
}
// get screen resolution
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM);
screen_width_ = DM.w;
screen_height_ = DM.h;
// use linear filtering to render textures otherwise the graphics will be
// blurry
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
}
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
// init modules
void Render::InitializeModules() {
if (!modules_inited_) {
// audio
AudioDeviceInit();
// screen capture init
screen_capturer_factory_ = new ScreenCapturerFactory();
// speaker capture init
speaker_capturer_factory_ = new SpeakerCapturerFactory();
// mouse control/keyboard capturer
device_controller_factory_ = new DeviceControllerFactory();
keyboard_capturer_ = (KeyboardCapturer*)device_controller_factory_->Create(
DeviceControllerFactory::Device::Keyboard);
// RTC
CreateConnectionPeer();
modules_inited_ = true;
}
}
// create window
void Render::InitializeMainWindow() {
CreateMainWindow();
SetupMainWindow();
if (SDL_WINDOW_HIDDEN & SDL_GetWindowFlags(main_window_)) {
SDL_ShowWindow(main_window_);
}
}
const int scaled_video_width_ = 160;
const int scaled_video_height_ = 90;
char* argb_buffer_ =
new char[scaled_video_width_ * scaled_video_height_ * 40];
// Main loop
void Render::MainLoop() {
while (!exit_) {
UpdateLabels();
ProcessSdlEvent();
HandleRecentConnections();
HandleStreamWindow();
DrawMainWindow();
if (stream_window_inited_) {
DrawStreamWindow();
}
UpdateInteractions();
if (SignalStatus::SignalConnected == signal_status_ &&
!is_create_connection_ && password_inited_) {
LOG_INFO("Connected with signal server, create p2p connection");
is_create_connection_ =
CreateConnection(peer_, client_id_, password_saved_) ? false : true;
}
}
}
void Render::UpdateLabels() {
if (!label_inited_ ||
localization_language_index_last_ != localization_language_index_) {
connect_button_label_ =
@@ -822,233 +835,10 @@ int Render::Run() {
label_inited_ = true;
localization_language_index_last_ = localization_language_index_;
}
}
SDL_Event event;
while (SDL_PollEvent(&event)) {
{
if (!main_ctx_) {
LOG_ERROR("Main context is null");
return -1;
}
ImGui::SetCurrentContext(main_ctx_);
ImGui_ImplSDL2_ProcessEvent(&event);
}
if (stream_window_inited_) {
if (!stream_ctx_) {
LOG_ERROR("Stream context is null");
return -1;
}
ImGui::SetCurrentContext(stream_ctx_);
ImGui_ImplSDL2_ProcessEvent(&event);
}
if (event.type == SDL_QUIT) {
if (stream_window_inited_) {
LOG_INFO("Destroy stream window");
SDL_SetWindowGrab(stream_window_, SDL_FALSE);
DestroyStreamWindow();
DestroyStreamWindowContext();
for (auto& it : client_properties_) {
auto props = it.second;
if (props->dst_buffer_) {
thumbnail_->SaveToThumbnail(
(char*)props->dst_buffer_, props->video_width_,
props->video_height_, it.first, props->remote_host_name_,
props->remember_password_ ? props->remote_password_ : "");
}
std::string host_name = it.first;
if (props->peer_) {
std::string client_id;
if (host_name == client_id_) {
client_id = "C-" + std::string(client_id_);
} else {
client_id = client_id_;
}
LOG_INFO("[{}] Leave connection [{}]", client_id, host_name);
LeaveConnection(props->peer_, host_name.c_str());
LOG_INFO("Destroy peer [{}]", client_id);
DestroyPeer(&props->peer_);
}
props->streaming_ = false;
props->remember_password_ = false;
props->connection_established_ = false;
props->audio_capture_button_pressed_ = false;
memset(&props->net_traffic_stats_, 0,
sizeof(props->net_traffic_stats_));
SDL_SetWindowFullscreen(main_window_, SDL_FALSE);
SDL_DestroyTexture(props->stream_texture_);
memset(audio_buffer_, 0, 720);
}
client_properties_.clear();
rejoin_ = false;
is_client_mode_ = false;
reload_recent_connections_ = true;
fullscreen_button_pressed_ = false;
recent_connection_image_save_time_ = SDL_GetTicks();
continue;
} else {
LOG_INFO("Quit program");
exit_ = true;
}
} else if (event.window.event == SDL_WINDOWEVENT_MAXIMIZED) {
} else if (event.window.event == SDL_WINDOWEVENT_MINIMIZED) {
} else if (event.window.event == SDL_WINDOWEVENT_RESTORED) {
window_maximized_ = false;
} else if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED &&
stream_window_created_ &&
event.window.windowID == SDL_GetWindowID(stream_window_)) {
for (auto& it : client_properties_) {
auto props = it.second;
// to prevent cursor relocation
if (!props->reset_control_bar_pos_) {
props->mouse_diff_control_bar_pos_x_ = 0;
props->mouse_diff_control_bar_pos_y_ = 0;
}
props->reset_control_bar_pos_ = true;
int stream_window_width, stream_window_height;
SDL_GetWindowSize(stream_window_, &stream_window_width,
&stream_window_height);
stream_window_width_ = (float)stream_window_width;
stream_window_height_ = (float)stream_window_height;
float video_ratio =
(float)props->video_width_ / (float)props->video_height_;
float video_ratio_reverse =
(float)props->video_height_ / (float)props->video_width_;
float render_area_width = stream_window_width_;
float render_area_height =
stream_window_height_ -
(fullscreen_button_pressed_ ? 0 : title_bar_height_);
props->stream_render_rect_last_ = props->stream_render_rect_;
if (render_area_width < render_area_height * video_ratio) {
props->stream_render_rect_.x = 0;
props->stream_render_rect_.y =
(int)(abs(render_area_height -
render_area_width * video_ratio_reverse) /
2 +
(fullscreen_button_pressed_ ? 0 : title_bar_height_));
props->stream_render_rect_.w = (int)render_area_width;
props->stream_render_rect_.h =
(int)(render_area_width * video_ratio_reverse);
} else if (render_area_width > render_area_height * video_ratio) {
props->stream_render_rect_.x =
(int)abs(render_area_width - render_area_height * video_ratio) /
2;
props->stream_render_rect_.y =
fullscreen_button_pressed_ ? 0 : (int)title_bar_height_;
props->stream_render_rect_.w =
(int)(render_area_height * video_ratio);
props->stream_render_rect_.h = (int)render_area_height;
} else {
props->stream_render_rect_.x = 0;
props->stream_render_rect_.y =
fullscreen_button_pressed_ ? 0 : (int)title_bar_height_;
props->stream_render_rect_.w = (int)render_area_width;
props->stream_render_rect_.h = (int)render_area_height;
}
}
} else if (event.type == SDL_WINDOWEVENT &&
event.window.event == SDL_WINDOWEVENT_CLOSE) {
if (event.window.windowID == SDL_GetWindowID(stream_window_)) {
continue;
} else {
exit_ = true;
}
} else if (event.type == STREAM_FRASH) {
SubStreamWindowProperties* props =
static_cast<SubStreamWindowProperties*>(event.user.data1);
if (!props) {
LOG_ERROR("Invalid stream window properties");
continue;
}
if (props->stream_texture_) {
if (props->video_width_ != props->texture_width_ ||
props->video_height_ != props->texture_height_) {
LOG_WARN("Resolution changed, old: [{}x{}], new: [{}x{}]",
props->texture_width_, props->texture_height_,
props->video_width_, props->video_height_);
props->texture_width_ = props->video_width_;
props->texture_height_ = props->video_height_;
SDL_DestroyTexture(props->stream_texture_);
props->stream_texture_ = SDL_CreateTexture(
stream_renderer_, stream_pixformat_,
SDL_TEXTUREACCESS_STREAMING, props->texture_width_,
props->texture_height_);
}
} else {
if (props->video_width_ != props->texture_width_ ||
props->video_height_ != props->texture_height_) {
props->texture_width_ = props->video_width_;
props->texture_height_ = props->video_height_;
}
props->stream_texture_ = SDL_CreateTexture(
stream_renderer_, stream_pixformat_, SDL_TEXTUREACCESS_STREAMING,
props->texture_width_, props->texture_height_);
}
SDL_UpdateTexture(props->stream_texture_, NULL, props->dst_buffer_,
props->texture_width_);
} else if (event.type == SDL_MOUSEMOTION ||
event.type == SDL_MOUSEBUTTONDOWN ||
event.type == SDL_MOUSEBUTTONUP ||
event.type == SDL_MOUSEWHEEL) {
if (!foucs_on_stream_window_) {
continue;
}
for (auto& it : client_properties_) {
auto props = it.second;
if (props->control_mouse_) {
ProcessMouseEvent(event);
}
}
} else if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
if (stream_window_) {
if (SDL_GetWindowID(stream_window_) == event.window.windowID) {
foucs_on_stream_window_ = true;
LOG_INFO("Focus on stream window");
}
}
if (main_window_) {
if (SDL_GetWindowID(main_window_) == event.window.windowID) {
foucs_on_main_window_ = true;
LOG_INFO("Focus on main window");
}
}
} else if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) {
if (stream_window_) {
if (SDL_GetWindowID(stream_window_) == event.window.windowID) {
foucs_on_stream_window_ = false;
LOG_INFO("Lost focus on stream window");
}
}
if (main_window_) {
if (SDL_GetWindowID(main_window_) == event.window.windowID) {
foucs_on_main_window_ = false;
LOG_INFO("Lost focus on main window");
}
}
} else {
}
}
void Render::HandleRecentConnections() {
if (reload_recent_connections_ && main_renderer_) {
// loal recent connection thumbnails after saving for 0.05 second
uint32_t now_time = SDL_GetTicks();
if (now_time - recent_connection_image_save_time_ >= 50) {
int ret = thumbnail_->LoadThumbnail(
@@ -1060,7 +850,9 @@ int Render::Run() {
reload_recent_connections_ = false;
}
}
}
void Render::HandleStreamWindow() {
if (need_to_create_stream_window_) {
CreateStreamWindow();
SetupStreamWindow();
@@ -1076,24 +868,11 @@ int Render::Run() {
stream_window_grabbed_ = false;
}
}
}
DrawMainWindow();
if (SDL_WINDOW_HIDDEN & SDL_GetWindowFlags(main_window_)) {
SDL_ShowWindow(main_window_);
}
if (stream_window_inited_) {
DrawStreamWindow();
}
// create connection
CreateRtcConnection();
}
void Render::Cleanup() {
delete[] argb_buffer_;
// Cleanup
if (screen_capturer_) {
screen_capturer_->Destroy();
delete screen_capturer_;
@@ -1112,6 +891,15 @@ int Render::Run() {
mouse_controller_ = nullptr;
}
CleanupFactories();
CleanupPeers();
AudioDeviceDestroy();
DestroyMainWindow();
DestroyMainWindowContext();
SDL_Quit();
}
void Render::CleanupFactories() {
if (screen_capturer_factory_) {
delete screen_capturer_factory_;
screen_capturer_factory_ = nullptr;
@@ -1126,7 +914,9 @@ int Render::Run() {
delete device_controller_factory_;
device_controller_factory_ = nullptr;
}
}
void Render::CleanupPeers() {
if (peer_) {
LOG_INFO("[{}] Leave connection [{}]", client_id_, client_id_);
LeaveConnection(peer_, client_id_);
@@ -1159,13 +949,201 @@ int Render::Run() {
DestroyPeer(&peer_client);
}
}
AudioDeviceDestroy();
DestroyMainWindow();
DestroyMainWindowContext();
SDL_Quit();
return 0;
}
void Render::ProcessSdlEvent() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (main_ctx_) {
ImGui::SetCurrentContext(main_ctx_);
ImGui_ImplSDL2_ProcessEvent(&event);
} else {
LOG_ERROR("Main context is null");
return;
}
if (stream_window_inited_) {
if (stream_ctx_) {
ImGui::SetCurrentContext(stream_ctx_);
ImGui_ImplSDL2_ProcessEvent(&event);
} else {
LOG_ERROR("Stream context is null");
return;
}
}
switch (event.type) {
case SDL_QUIT:
if (stream_window_inited_) {
LOG_INFO("Destroy stream window");
SDL_SetWindowGrab(stream_window_, SDL_FALSE);
DestroyStreamWindow();
DestroyStreamWindowContext();
for (auto& [host_name, props] : client_properties_) {
if (props->dst_buffer_) {
thumbnail_->SaveToThumbnail(
(char*)props->dst_buffer_, props->video_width_,
props->video_height_, host_name, props->remote_host_name_,
props->remember_password_ ? props->remote_password_ : "");
}
if (props->peer_) {
std::string client_id = (host_name == client_id_)
? "C-" + std::string(client_id_)
: client_id_;
LOG_INFO("[{}] Leave connection [{}]", client_id, host_name);
LeaveConnection(props->peer_, host_name.c_str());
LOG_INFO("Destroy peer [{}]", client_id);
DestroyPeer(&props->peer_);
}
props->streaming_ = false;
props->remember_password_ = false;
props->connection_established_ = false;
props->audio_capture_button_pressed_ = false;
memset(&props->net_traffic_stats_, 0,
sizeof(props->net_traffic_stats_));
SDL_SetWindowFullscreen(main_window_, SDL_FALSE);
SDL_DestroyTexture(props->stream_texture_);
memset(audio_buffer_, 0, 720);
}
client_properties_.clear();
rejoin_ = false;
is_client_mode_ = false;
reload_recent_connections_ = true;
fullscreen_button_pressed_ = false;
recent_connection_image_save_time_ = SDL_GetTicks();
} else {
LOG_INFO("Quit program");
exit_ = true;
}
break;
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_CLOSE &&
event.window.windowID != SDL_GetWindowID(stream_window_)) {
exit_ = true;
} else if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED &&
stream_window_created_ &&
event.window.windowID == SDL_GetWindowID(stream_window_)) {
for (auto& [_, props] : client_properties_) {
if (!props->reset_control_bar_pos_) {
props->mouse_diff_control_bar_pos_x_ = 0;
props->mouse_diff_control_bar_pos_y_ = 0;
}
props->reset_control_bar_pos_ = true;
int stream_window_width, stream_window_height;
SDL_GetWindowSize(stream_window_, &stream_window_width,
&stream_window_height);
stream_window_width_ = (float)stream_window_width;
stream_window_height_ = (float)stream_window_height;
float video_ratio =
(float)props->video_width_ / (float)props->video_height_;
float video_ratio_reverse =
(float)props->video_height_ / (float)props->video_width_;
float render_area_width = stream_window_width_;
float render_area_height =
stream_window_height_ -
(fullscreen_button_pressed_ ? 0 : title_bar_height_);
props->stream_render_rect_last_ = props->stream_render_rect_;
if (render_area_width < render_area_height * video_ratio) {
props->stream_render_rect_ = {
0,
(int)(abs(render_area_height -
render_area_width * video_ratio_reverse) /
2 +
(fullscreen_button_pressed_ ? 0 : title_bar_height_)),
(int)render_area_width,
(int)(render_area_width * video_ratio_reverse)};
} else if (render_area_width > render_area_height * video_ratio) {
props->stream_render_rect_ = {
(int)abs(render_area_width -
render_area_height * video_ratio) /
2,
fullscreen_button_pressed_ ? 0 : (int)title_bar_height_,
(int)(render_area_height * video_ratio),
(int)render_area_height};
} else {
props->stream_render_rect_ = {
0, fullscreen_button_pressed_ ? 0 : (int)title_bar_height_,
(int)render_area_width, (int)render_area_height};
}
}
} else if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ||
event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) {
bool focus_gained =
event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED;
if (stream_window_ &&
SDL_GetWindowID(stream_window_) == event.window.windowID) {
foucs_on_stream_window_ = focus_gained;
LOG_INFO("{} focus on stream window",
focus_gained ? "Gained" : "Lost");
} else if (main_window_ &&
SDL_GetWindowID(main_window_) == event.window.windowID) {
foucs_on_main_window_ = focus_gained;
LOG_INFO("{} focus on main window",
focus_gained ? "Gained" : "Lost");
}
}
break;
case STREAM_FRASH: {
auto* props = static_cast<SubStreamWindowProperties*>(event.user.data1);
if (!props) {
LOG_ERROR("Invalid stream window properties");
continue;
}
if (props->stream_texture_) {
if (props->video_width_ != props->texture_width_ ||
props->video_height_ != props->texture_height_) {
LOG_WARN("Resolution changed, old: [{}x{}], new: [{}x{}]",
props->texture_width_, props->texture_height_,
props->video_width_, props->video_height_);
props->texture_width_ = props->video_width_;
props->texture_height_ = props->video_height_;
SDL_DestroyTexture(props->stream_texture_);
props->stream_texture_ = SDL_CreateTexture(
stream_renderer_, stream_pixformat_,
SDL_TEXTUREACCESS_STREAMING, props->texture_width_,
props->texture_height_);
}
} else {
props->texture_width_ = props->video_width_;
props->texture_height_ = props->video_height_;
props->stream_texture_ = SDL_CreateTexture(
stream_renderer_, stream_pixformat_, SDL_TEXTUREACCESS_STREAMING,
props->texture_width_, props->texture_height_);
}
SDL_UpdateTexture(props->stream_texture_, NULL, props->dst_buffer_,
props->texture_width_);
break;
}
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEWHEEL:
if (foucs_on_stream_window_) {
for (auto& [_, props] : client_properties_) {
if (props->control_mouse_) {
ProcessMouseEvent(event);
}
}
}
break;
default:
break;
}
}
}

View File

@@ -25,8 +25,6 @@
#include "speaker_capturer_factory.h"
#include "thumbnail.h"
extern const Uint32 STREAM_FRASH;
class Render {
public:
struct SubStreamWindowProperties {
@@ -101,6 +99,21 @@ class Render {
public:
int Run();
private:
void InitializeSettings();
void InitializeSDL();
void InitializeModules();
void InitializeMainWindow();
void MainLoop();
void UpdateLabels();
void UpdateInteractions();
void HandleRecentConnections();
void HandleStreamWindow();
void Cleanup();
void CleanupFactories();
void CleanupPeers();
void ProcessSdlEvent();
private:
int CreateStreamRenderWindow();
int TitleBar(bool main_window);
@@ -116,11 +129,9 @@ class Render {
int StatusBar();
int ConnectionStatusWindow(
std::shared_ptr<SubStreamWindowProperties> &properties);
int LoadRecentConnections();
int ShowRecentConnections();
private:
int CreateRtcConnection();
int ConnectTo(const std::string &remote_id, const char *password,
bool remember_password);
int CreateMainWindow();
@@ -239,6 +250,7 @@ class Render {
SDL_Renderer *main_renderer_ = nullptr;
ImGuiContext *main_ctx_ = nullptr;
bool exit_ = false;
char *argb_buffer_ = nullptr;
// main window properties
bool start_mouse_controller_ = false;

View File

@@ -6,6 +6,8 @@
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
#define STREAM_FRASH (SDL_USEREVENT + 1)
#ifdef REMOTE_DESK_DEBUG
#else
#define MOUSE_CONTROL 1