diff --git a/src/device_controller/device_controller.h b/src/device_controller/device_controller.h index 93be044..f063108 100644 --- a/src/device_controller/device_controller.h +++ b/src/device_controller/device_controller.h @@ -53,7 +53,7 @@ class DeviceController { public: // virtual int Init(int screen_width, int screen_height); // virtual int Destroy(); - // virtual int SendCommand(RemoteAction remote_action); + // virtual int SendMouseCommand(RemoteAction remote_action); // virtual int Hook(); // virtual int Unhook(); diff --git a/src/device_controller/mouse/linux/mouse_controller.cpp b/src/device_controller/mouse/linux/mouse_controller.cpp index 32c3d7c..a413930 100644 --- a/src/device_controller/mouse/linux/mouse_controller.cpp +++ b/src/device_controller/mouse/linux/mouse_controller.cpp @@ -48,7 +48,7 @@ int MouseController::Init(int screen_width, int screen_height) { int MouseController::Destroy() { return 0; } -int MouseController::SendCommand(RemoteAction remote_action) { +int MouseController::SendMouseCommand(RemoteAction remote_action) { int mouse_pos_x = remote_action.m.x; int mouse_pos_y = remote_action.m.y; diff --git a/src/device_controller/mouse/linux/mouse_controller.h b/src/device_controller/mouse/linux/mouse_controller.h index f31fa44..cfdde1a 100644 --- a/src/device_controller/mouse/linux/mouse_controller.h +++ b/src/device_controller/mouse/linux/mouse_controller.h @@ -24,7 +24,7 @@ class MouseController : public DeviceController { public: virtual int Init(int screen_width, int screen_height); virtual int Destroy(); - virtual int SendCommand(RemoteAction remote_action); + virtual int SendMouseCommand(RemoteAction remote_action); private: void SimulateKeyDown(int fd, int kval); diff --git a/src/device_controller/mouse/mac/mouse_controller.cpp b/src/device_controller/mouse/mac/mouse_controller.cpp index 24ee943..bb70f73 100644 --- a/src/device_controller/mouse/mac/mouse_controller.cpp +++ b/src/device_controller/mouse/mac/mouse_controller.cpp @@ -22,7 +22,7 @@ int MouseController::Init(int screen_width, int screen_height) { int MouseController::Destroy() { return 0; } -int MouseController::SendCommand(RemoteAction remote_action) { +int MouseController::SendMouseCommand(RemoteAction remote_action) { int mouse_pos_x = remote_action.m.x * screen_width_ / pixel_width_; int mouse_pos_y = remote_action.m.y * screen_height_ / pixel_height_; diff --git a/src/device_controller/mouse/mac/mouse_controller.h b/src/device_controller/mouse/mac/mouse_controller.h index 8c07df6..526f8eb 100644 --- a/src/device_controller/mouse/mac/mouse_controller.h +++ b/src/device_controller/mouse/mac/mouse_controller.h @@ -17,7 +17,7 @@ class MouseController : public DeviceController { public: virtual int Init(int screen_width, int screen_height); virtual int Destroy(); - virtual int SendCommand(RemoteAction remote_action); + virtual int SendMouseCommand(RemoteAction remote_action); private: int screen_width_ = 0; diff --git a/src/device_controller/mouse/windows/mouse_controller.cpp b/src/device_controller/mouse/windows/mouse_controller.cpp index 5b13f27..271de08 100644 --- a/src/device_controller/mouse/windows/mouse_controller.cpp +++ b/src/device_controller/mouse/windows/mouse_controller.cpp @@ -15,7 +15,7 @@ int MouseController::Init(int screen_width, int screen_height) { int MouseController::Destroy() { return 0; } -int MouseController::SendCommand(RemoteAction remote_action) { +int MouseController::SendMouseCommand(RemoteAction remote_action) { INPUT ip; if (remote_action.type == ControlType::mouse) { diff --git a/src/device_controller/mouse/windows/mouse_controller.h b/src/device_controller/mouse/windows/mouse_controller.h index 7ad3e9c..276d5a1 100644 --- a/src/device_controller/mouse/windows/mouse_controller.h +++ b/src/device_controller/mouse/windows/mouse_controller.h @@ -17,7 +17,7 @@ class MouseController : public DeviceController { public: virtual int Init(int screen_width, int screen_height); virtual int Destroy(); - virtual int SendCommand(RemoteAction remote_action); + virtual int SendMouseCommand(RemoteAction remote_action); private: int screen_width_ = 0; diff --git a/src/single_window/remote_peer_window.cpp b/src/single_window/remote_peer_window.cpp index 4041101..7007c8f 100644 --- a/src/single_window/remote_peer_window.cpp +++ b/src/single_window/remote_peer_window.cpp @@ -78,9 +78,13 @@ int Render::RemoteWindow() { ConnectTo(remote_id_, remote_password_, false); } - if (rejoin_) { - ConnectTo(remote_id_, remote_password_, - client_properties_[remote_id_]->remember_password_); + std::string client_id = "C-" + remote_id_; + if (client_properties_.find(client_id) != client_properties_.end()) { + auto props = client_properties_[client_id]; + if (props->rejoin_) { + ConnectTo(remote_id_, remote_password_, + client_properties_[remote_id_]->remember_password_); + } } } ImGui::EndChild(); @@ -106,40 +110,41 @@ static int InputTextCallback(ImGuiInputTextCallbackData *data) { int Render::ConnectTo(const std::string &host_name, const char *password, bool remember_password) { LOG_INFO("Connect to [{}]", host_name); - if (client_properties_.find(host_name) == client_properties_.end()) { - client_properties_[host_name] = + + std::string client_id = "C-" + host_name; + if (client_properties_.find(client_id) == client_properties_.end()) { + client_properties_[client_id] = std::make_shared(); } - auto props = client_properties_[host_name]; + auto props = client_properties_[client_id]; props->connection_status_ = ConnectionStatus::Connecting; props->remember_password_ = remember_password; memcpy(props->remote_password_, password, 6); int ret = -1; - if (signal_connected_) { - if (!props->connection_established_) { - if (0 == strcmp(host_name.c_str(), client_id_) && !peer_reserved_) { - std::string client_id = "C-"; - client_id += client_id_; - peer_reserved_ = CreatePeer(¶ms_); - if (peer_reserved_) { - LOG_INFO("[{}] Create peer instance successful", client_id); - Init(peer_reserved_, client_id.c_str()); - LOG_INFO("[{}] Peer init finish", client_id); - } else { - LOG_INFO("Create peer [{}] instance failed", client_id); - } - } - ret = JoinConnection(peer_reserved_ ? peer_reserved_ : peer_, - host_name.c_str(), password); - if (0 == ret) { - is_client_mode_ = true; - rejoin_ = false; - } else { - rejoin_ = true; - } + if (!props->connection_established_) { + if (peer_map_.find(client_id) == peer_map_.end()) { + memcpy(&props->params_, ¶ms_, sizeof(Params)); + props->params_.user_id = client_id.c_str(); + peer_map_[client_id] = CreatePeer(&props->params_); + } + + if (peer_map_[client_id]) { + LOG_INFO("[{}] Create peer instance successful", client_id); + Init(peer_map_[client_id]); + LOG_INFO("[{}] Peer init finish", client_id); + } else { + LOG_INFO("Create peer [{}] instance failed", client_id); + } + + ret = JoinConnection(peer_map_[client_id], host_name.c_str(), password); + if (0 == ret) { + is_client_mode_ = true; + props->rejoin_ = false; + } else { + props->rejoin_ = true; } } diff --git a/src/single_window/render.cpp b/src/single_window/render.cpp index eea810d..a081b83 100644 --- a/src/single_window/render.cpp +++ b/src/single_window/render.cpp @@ -299,7 +299,7 @@ int Render::StartKeyboardCapturer() { [](int key_code, bool is_down, void* user_ptr) { if (user_ptr) { Render* render = (Render*)user_ptr; - render->SendKeyEvent(key_code, is_down); + render->SendKeyCommand(key_code, is_down); } }, this); @@ -345,12 +345,14 @@ int Render::CreateConnectionPeer() { params_.on_signal_status = OnSignalStatusCb; params_.on_connection_status = OnConnectionStatusCb; params_.net_status_report = NetStatusReport; + + params_.user_id = client_id_; params_.user_data = this; peer_ = CreatePeer(¶ms_); if (peer_) { LOG_INFO("[{}] Create peer instance successful", client_id_); - Init(peer_, client_id_); + Init(peer_); LOG_INFO("[{}] Peer init finish", client_id_); } else { LOG_INFO("Create peer [{}] instance failed", client_id_); @@ -855,16 +857,19 @@ int Render::Run() { props->remember_password_ ? props->remote_password_ : ""); } - if (peer_reserved_) { - std::string client_id = "C-"; - client_id += client_id_; - LOG_INFO("[{}] Leave connection [{}]", client_id, it.first); - LeaveConnection(peer_reserved_, it.first.c_str()); + std::string host_name = it.first; + PeerPtr* peer_client = peer_map_[host_name]; + if (peer_client) { + 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(peer_client, host_name.c_str()); LOG_INFO("Destroy peer [{}]", client_id); - DestroyPeer(&peer_reserved_); - } else { - LOG_INFO("[{}] Leave connection [{}]", client_id_, it.first); - LeaveConnection(peer_, it.first.c_str()); + DestroyPeer(&peer_client); } props->streaming_ = false; @@ -995,6 +1000,8 @@ int Render::Run() { SDL_UpdateTexture(props->stream_texture_, NULL, props->dst_buffer_, props->texture_width_); + } else { + ProcessMouseEvent(event); } } @@ -1086,9 +1093,29 @@ int Render::Run() { DestroyPeer(&peer_); } - if (peer_reserved_) { - LOG_INFO("Destroy peer[reserved]"); - DestroyPeer(&peer_reserved_); + 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; + PeerPtr* peer_client = peer_map_[host_name]; + if (peer_client) { + 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(peer_client, host_name.c_str()); + LOG_INFO("Destroy peer [{}]", client_id); + DestroyPeer(&peer_client); + } } AudioDeviceDestroy(); diff --git a/src/single_window/render.h b/src/single_window/render.h index c2222a2..f24f345 100644 --- a/src/single_window/render.h +++ b/src/single_window/render.h @@ -30,8 +30,12 @@ extern const Uint32 STREAM_FRASH; class Render { public: struct SubStreamWindowProperties { + Params params_; bool exit_ = false; + bool signal_connected_ = false; + SignalStatus signal_status_ = SignalStatus::SignalClosed; bool connection_established_ = false; + bool rejoin_ = false; bool net_traffic_stats_button_pressed_ = false; bool mouse_control_button_pressed_ = false; bool mouse_controller_is_started_ = false; @@ -142,7 +146,8 @@ class Render { const char *user_id, size_t user_id_size, void *user_data); - static void OnSignalStatusCb(SignalStatus status, void *user_data); + static void OnSignalStatusCb(SignalStatus status, const char *user_id, + size_t user_id_size, void *user_data); static void OnConnectionStatusCb(ConnectionStatus status, const char *user_id, size_t user_id_size, void *user_data); @@ -157,8 +162,8 @@ class Render { const SDL_Point *area, void *data); private: - int SendKeyEvent(int key_code, bool is_down); - int ProcessKeyEvent(int key_code, bool is_down); + int SendKeyCommand(int key_code, bool is_down); + int ProcessMouseEvent(SDL_Event &event); static void SdlCaptureAudioIn(void *userdata, Uint8 *stream, int len); static void SdlCaptureAudioOut(void *userdata, Uint8 *stream, int len); @@ -363,6 +368,7 @@ class Render { /* ------ sub stream window property start ------ */ std::unordered_map> client_properties_; + std::unordered_map peer_map_; /* ------ stream window property end ------ */ std::unordered_map> diff --git a/src/single_window/render_callback_func.cpp b/src/single_window/render_callback_func.cpp index 7b2f462..71d24ce 100644 --- a/src/single_window/render_callback_func.cpp +++ b/src/single_window/render_callback_func.cpp @@ -11,7 +11,7 @@ #define MOUSE_CONTROL 1 #endif -int Render::SendKeyEvent(int key_code, bool is_down) { +int Render::SendKeyCommand(int key_code, bool is_down) { RemoteAction remote_action; remote_action.type = ControlType::keyboard; if (is_down) { @@ -26,9 +26,55 @@ int Render::SendKeyEvent(int key_code, bool is_down) { return 0; } -int Render::ProcessKeyEvent(int key_code, bool is_down) { - if (keyboard_capturer_) { - keyboard_capturer_->SendKeyboardCommand(key_code, is_down); +int Render::ProcessMouseEvent(SDL_Event &event) { + std::string remote_id = ""; + int video_width, video_height = 0; + int render_width, render_height = 0; + for (auto &it : client_properties_) { + auto props = it.second; + if (event.button.x >= props->stream_render_rect_.x && + event.button.x <= + props->stream_render_rect_.x + props->stream_render_rect_.w && + event.button.y >= props->stream_render_rect_.y && + event.button.y <= + props->stream_render_rect_.y + props->stream_render_rect_.h) { + remote_id = it.first; + video_width = props->video_width_; + video_height = props->video_height_; + render_width = props->stream_render_rect_.w; + render_height = props->stream_render_rect_.h; + } + } + + float ratio_x = (float)video_width / (float)render_width; + float ratio_y = (float)video_height / (float)render_height; + + RemoteAction remote_action; + remote_action.m.x = (size_t)(event.button.x * ratio_x); + remote_action.m.y = (size_t)(event.button.y * ratio_y); + + if (SDL_MOUSEBUTTONDOWN == event.type) { + remote_action.type = ControlType::mouse; + if (SDL_BUTTON_LEFT == event.button.button) { + remote_action.m.flag = MouseFlag::left_down; + } else if (SDL_BUTTON_RIGHT == event.button.button) { + remote_action.m.flag = MouseFlag::right_down; + } + remote_action.m.flag = MouseFlag::move; + SendDataFrame(peer_, (const char *)&remote_action, sizeof(remote_action)); + } else if (SDL_MOUSEBUTTONUP == event.type) { + remote_action.type = ControlType::mouse; + if (SDL_BUTTON_LEFT == event.button.button) { + remote_action.m.flag = MouseFlag::left_up; + } else if (SDL_BUTTON_RIGHT == event.button.button) { + remote_action.m.flag = MouseFlag::right_up; + } + remote_action.m.flag = MouseFlag::move; + SendDataFrame(peer_, (const char *)&remote_action, sizeof(remote_action)); + } else if (SDL_MOUSEMOTION == event.type) { + remote_action.type = ControlType::mouse; + remote_action.m.flag = MouseFlag::move; + SendDataFrame(peer_, (const char *)&remote_action, sizeof(remote_action)); } return 0; @@ -150,7 +196,7 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size, memcpy(&remote_action, data, size); if (ControlType::mouse == remote_action.type && render->mouse_controller_) { - render->mouse_controller_->SendCommand(remote_action); + render->mouse_controller_->SendMouseCommand(remote_action); } else if (ControlType::audio_capture == remote_action.type) { if (remote_action.a) { render->StartSpeakerCapturer(); @@ -159,9 +205,11 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size, render->StopSpeakerCapturer(); render->audio_capture_ = false; } - } else if (ControlType::keyboard == remote_action.type) { - render->ProcessKeyEvent((int)remote_action.k.key_value, - remote_action.k.flag == KeyFlag::key_down); + } else if (ControlType::keyboard == remote_action.type && + render->keyboard_capturer_) { + render->keyboard_capturer_->SendKeyboardCommand( + (int)remote_action.k.key_value, + remote_action.k.flag == KeyFlag::key_down); } else if (ControlType::host_infomation == remote_action.type) { props->remote_host_name_ = std::string(remote_action.i.host_name, remote_action.i.host_name_size); @@ -169,32 +217,51 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size, } } -void Render::OnSignalStatusCb(SignalStatus status, void *user_data) { +void Render::OnSignalStatusCb(SignalStatus status, const char *user_id, + size_t user_id_size, void *user_data) { Render *render = (Render *)user_data; if (!render) { return; } + std::string remote_id(user_id, user_id_size); - render->signal_status_ = status; - if (SignalStatus::SignalConnecting == status) { - render->signal_status_str_ = "SignalConnecting"; - render->signal_connected_ = false; - } else if (SignalStatus::SignalConnected == status) { - render->signal_status_str_ = "SignalConnected"; - render->signal_connected_ = true; - } else if (SignalStatus::SignalFailed == status) { - render->signal_status_str_ = "SignalFailed"; - render->signal_connected_ = false; - } else if (SignalStatus::SignalClosed == status) { - render->signal_status_str_ = "SignalClosed"; - render->signal_connected_ = false; - } else if (SignalStatus::SignalReconnecting == status) { - render->signal_status_str_ = "SignalReconnecting"; - render->signal_connected_ = false; - } else if (SignalStatus::SignalServerClosed == status) { - render->signal_status_str_ = "SignalServerClosed"; - render->signal_connected_ = false; - render->is_create_connection_ = false; + if (remote_id == render->client_id_) { + render->signal_status_ = status; + if (SignalStatus::SignalConnecting == status) { + render->signal_connected_ = false; + } else if (SignalStatus::SignalConnected == status) { + render->signal_connected_ = true; + LOG_INFO("[{}] connected to signal server", remote_id); + } else if (SignalStatus::SignalFailed == status) { + render->signal_connected_ = false; + } else if (SignalStatus::SignalClosed == status) { + render->signal_connected_ = false; + } else if (SignalStatus::SignalReconnecting == status) { + render->signal_connected_ = false; + } else if (SignalStatus::SignalServerClosed == status) { + render->signal_connected_ = false; + } + } else { + if (render->client_properties_.find(remote_id) == + render->client_properties_.end()) { + return; + } + auto props = render->client_properties_.find(remote_id)->second; + props->signal_status_ = status; + if (SignalStatus::SignalConnecting == status) { + props->signal_connected_ = false; + } else if (SignalStatus::SignalConnected == status) { + props->signal_connected_ = true; + LOG_INFO("[{}] connected to signal server", remote_id); + } else if (SignalStatus::SignalFailed == status) { + props->signal_connected_ = false; + } else if (SignalStatus::SignalClosed == status) { + props->signal_connected_ = false; + } else if (SignalStatus::SignalReconnecting == status) { + props->signal_connected_ = false; + } else if (SignalStatus::SignalServerClosed == status) { + props->signal_connected_ = false; + } } } diff --git a/thirdparty/projectx b/thirdparty/projectx index dff7948..9972047 160000 --- a/thirdparty/projectx +++ b/thirdparty/projectx @@ -1 +1 @@ -Subproject commit dff7948245711f77f9a76349d9a8aef9638c1d1b +Subproject commit 9972047199857df55e8b3715689b642b301ec593