From 63436a413f4edb6873a43d9e89106be72cc7c87a Mon Sep 17 00:00:00 2001 From: Nanako <469449812@qq.com> Date: Wed, 28 Feb 2024 11:08:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=AA=97=E5=8F=A3=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/application/application.cpp | 23 ++--- core/application/application.h | 8 +- core/application/window_manager.cpp | 90 +++++++++++++++++++ core/application/window_manager.h | 41 +++++++++ core/audio/device/audio_device_manager.cpp | 4 + core/audio/device/audio_device_manager.h | 2 + core/audio/device/port_audio_device.cpp | 32 ++++--- core/audio/device/port_audio_device.h | 3 + core/audio/mixer/mixer.cpp | 4 +- core/audio/plugin_host/plugin_host.cpp | 4 +- .../audio/plugin_host/plugin_host_manager.cpp | 8 +- .../plugin_host/vst2/vst2_plugin_host.cpp | 5 +- 12 files changed, 188 insertions(+), 36 deletions(-) create mode 100644 core/application/window_manager.cpp create mode 100644 core/application/window_manager.h diff --git a/core/application/application.cpp b/core/application/application.cpp index f53ac3d..31a264e 100644 --- a/core/application/application.cpp +++ b/core/application/application.cpp @@ -5,6 +5,7 @@ #include "command_line.h" #include "imgui_impl_sdl3.h" #include "imgui_internal.h" +#include "window_manager.h" #include "filesystem/stb_image.h" #include "rhi/texture.h" #include "rhi/renderer.h" @@ -35,27 +36,26 @@ void application::init(const window_params& in_window_params, int argc, char** a renderer_->pre_init(); + const auto window = g_window_manager.create_main_window(in_window_params.title.c_str(), in_window_params.width, in_window_params.height); // new glfw window - window_ = glfwCreateWindow(in_window_params.width, in_window_params.height, in_window_params.title.c_str(), nullptr, - nullptr); - if (!window_) { + if (!window) { spdlog::error("Failed to create glfw window"); return; } - renderer_->init(window_); + renderer_->init(window); g_is_running = true; } int application::run() { const ImGuiIO& io = ImGui::GetIO(); while (!g_exit_requested) { - glfwPollEvents(); - g_exit_requested = g_exit_requested || glfwWindowShouldClose(window_); + g_window_manager.tick(); + g_exit_requested = g_exit_requested || g_window_manager.should_close(); tick(io.DeltaTime); - renderer_->new_frame(window_); + renderer_->new_frame(g_window_manager.get_main_window()); draw_gui(); - renderer_->end_frame(window_); + renderer_->end_frame(g_window_manager.get_main_window()); } shutdown(); @@ -74,6 +74,11 @@ void application::shutdown() { g_is_running = false; } +void application::request_exit() { + g_window_manager.request_exit(); + g_exit_requested = true; +} + std::shared_ptr application::load_texture(const std::string& path, vk::Format format) { int width = 0; int height = 0; @@ -116,8 +121,6 @@ void application::init_imgui() { } void application::destroy_glfw() { - glfwDestroyWindow(window_); - window_ = nullptr; glfwTerminate(); } diff --git a/core/application/application.h b/core/application/application.h index 3f7a788..f689755 100644 --- a/core/application/application.h +++ b/core/application/application.h @@ -48,10 +48,7 @@ public: virtual void shutdown(); - void request_exit() { - glfwSetWindowShouldClose(window_, GLFW_TRUE); - g_exit_requested = true; - } + void request_exit(); virtual void draw_gui() = 0; virtual void tick(float delta_time) {} @@ -68,11 +65,8 @@ public: [[nodiscard]] virtual const char* get_draw_ps_vertex_shader_entry() const = 0; // Vertex Shader used for drawing ps [[nodiscard]] renderer* get_renderer() const { return renderer_; } - [[nodiscard]] GLFWwindow* get_window() const { return window_; } - protected: renderer* renderer_ = nullptr; - GLFWwindow* window_ = nullptr; std::shared_ptr async_spdlog_; private: diff --git a/core/application/window_manager.cpp b/core/application/window_manager.cpp new file mode 100644 index 0000000..9a9713d --- /dev/null +++ b/core/application/window_manager.cpp @@ -0,0 +1,90 @@ +#include "window_manager.h" + +#include + +#include "audio/plugin_host/plugin_host.h" + +window_manager::window_manager() { + main_window_ = nullptr; +} + +void window_manager::init(singleton_initliazer& initliazer) { + singleton_t::init(initliazer); + start_idle_thread(); +} + +void window_manager::release() { + singleton_t::release(); + if (main_window_) + glfwDestroyWindow(main_window_); + stop_idle_thread(); +} + +void window_manager::tick() { + glfwPollEvents(); + if (should_close()) { + destroy_all_plugin_host_window(); + } +} + +void window_manager::destroy_all_plugin_host_window() { + for (const auto& window: host_window_map_ | std::views::values) { + glfwDestroyWindow(window); + } + host_window_map_.clear(); +} + +GLFWwindow* window_manager::create_main_window(const char* title, int width, int height) { + if (!main_window_) + main_window_ = glfwCreateWindow(width, height, title, nullptr, nullptr); + return main_window_; +} + +GLFWwindow* window_manager::create_plugin_host_window(plugin_host* host) { + if (!host->has_editor()) + return nullptr; + if (host_window_map_.contains(host)) + return host_window_map_[host]; + auto editor_size = host->get_editor_size(); + auto new_window = glfwCreateWindow(editor_size.x, editor_size.y, host->name.c_str(), nullptr, nullptr); + host_window_map_[host] = new_window; + return new_window; +} + +void window_manager::destroy_plugin_host_window(plugin_host* host) { + if (!host_window_map_.contains(host)) + return; + glfwDestroyWindow(host_window_map_[host]); + host_window_map_.erase(host); +} + +void window_manager::resize_plugin_host_window(plugin_host* host, int width, int height) { + if (!host_window_map_.contains(host)) + return; + glfwSetWindowSize(host_window_map_[host], width, height); +} + +void window_manager::idle_plugin_host_window() const { + for (const auto& window_map: host_window_map_) { + window_map.first->idle_editor(); + } +} + +void window_manager::start_idle_thread() { + idle_thread_ = std::thread(&window_manager::idle_thread_func, this); + idle_thread_.detach(); +} + +void window_manager::stop_idle_thread() { + idle_thread_running_ = false; + if (idle_thread_.joinable()) + idle_thread_.join(); +} + +void window_manager::idle_thread_func() { + idle_thread_running_ = true; + while (idle_thread_running_) { + idle_plugin_host_window(); + std::this_thread::yield(); + } +} diff --git a/core/application/window_manager.h b/core/application/window_manager.h new file mode 100644 index 0000000..ab7cf41 --- /dev/null +++ b/core/application/window_manager.h @@ -0,0 +1,41 @@ +#pragma once +#include "GLFW/glfw3.h" +#include "misc/singleton/singleton.h" +#include + +class plugin_host; + +class window_manager : public singleton_t { +public: + window_manager(); + void init(singleton_initliazer& initliazer) override; + void release() override; + void tick(); + bool should_close() const { return glfwWindowShouldClose(main_window_); } + void destroy_all_plugin_host_window(); + + GLFWwindow* create_main_window(const char* title, int width, int height); + void request_exit() const { glfwSetWindowShouldClose(main_window_, GLFW_TRUE); } + GLFWwindow* get_main_window() const { return main_window_; } + + GLFWwindow* create_plugin_host_window(plugin_host* host); + void destroy_plugin_host_window(plugin_host* host); + void resize_plugin_host_window(plugin_host* host, int width, int height); + void idle_plugin_host_window() const; + + const char* get_name() override { return "window_manager"; } +private: + +#pragma region idle_thread + void start_idle_thread(); + void stop_idle_thread(); + void idle_thread_func(); + std::thread idle_thread_; + std::atomic_bool idle_thread_running_; +#pragma endregion + + GLFWwindow* main_window_; + std::map host_window_map_; +}; + +DEFINE_SINGLETON_INSTANCE(window_manager) diff --git a/core/audio/device/audio_device_manager.cpp b/core/audio/device/audio_device_manager.cpp index 0902526..914a8ae 100644 --- a/core/audio/device/audio_device_manager.cpp +++ b/core/audio/device/audio_device_manager.cpp @@ -20,6 +20,10 @@ void audio_device_manager::release() { delete main_audio_device_; } +void audio_device_manager::start() { + main_audio_device_->start(); +} + double audio_device_manager::get_sample_rate() const { return main_audio_device_->sample_rate(); } diff --git a/core/audio/device/audio_device_manager.h b/core/audio/device/audio_device_manager.h index 2636117..5ba20a9 100644 --- a/core/audio/device/audio_device_manager.h +++ b/core/audio/device/audio_device_manager.h @@ -9,6 +9,8 @@ public: void init(singleton_initliazer& initliazer) override; void release() override; + void start(); + [[nodiscard]] const char* get_name() override { return "audio_device_manager"; } [[nodiscard]] double get_sample_rate() const; diff --git a/core/audio/device/port_audio_device.cpp b/core/audio/device/port_audio_device.cpp index 568a95a..0899b30 100644 --- a/core/audio/device/port_audio_device.cpp +++ b/core/audio/device/port_audio_device.cpp @@ -18,12 +18,6 @@ port_audio_device::~port_audio_device() { bool port_audio_device::init() { Pa_Initialize(); - try { - open_stream(-1, Pa_GetDefaultOutputDevice(), sample_rate(), buffer_size()); - } catch (const std::exception& e) { - spdlog::error("Init failed: {}", e.what()); - return false; - } return true; } @@ -36,11 +30,18 @@ void port_audio_device::stop() { Pa_StopStream(stream_); Pa_CloseStream(stream_); stream_ = nullptr; - while (!render_thread_running_) - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + stop_render_thread(); spdlog::info("port_audio stopped"); } +void port_audio_device::start() { + try { + open_stream(-1, Pa_GetDefaultOutputDevice(), sample_rate(), buffer_size()); + } catch (const std::exception& e) { + spdlog::error("Init failed: {}", e.what()); + } +} + void port_audio_device::open_stream(PaDeviceIndex input_device, PaDeviceIndex output_device, double in_sample_rate, uint32_t in_buffer_size) { const PaStreamParameters* input_params = nullptr; if (input_device >= 0) { @@ -65,8 +66,7 @@ void port_audio_device::open_stream(PaDeviceIndex input_device, PaDeviceIndex ou if (err != paNoError) { throw std::runtime_error(Pa_GetErrorText(err)); } - render_thread_ = std::thread(&port_audio_device::render_thread, this); - render_thread_.detach(); + start_render_thread(); } int port_audio_device::stream_callback(float** input, float** output, unsigned long frame_count, @@ -102,9 +102,18 @@ bool port_audio_device::on_set_sample_rate(double in_sample_rate) { return true; } +void port_audio_device::start_render_thread() { + render_thread_ = std::thread(&port_audio_device::render_thread, this); + render_thread_.detach(); +} + +void port_audio_device::stop_render_thread() { + if (render_thread_.joinable()) + render_thread_.join(); +} + void port_audio_device::render_thread() { dummy_track* master = g_mixer.get_master(); - render_thread_running_ = true; spdlog::info("port_audio render thread started"); while (stream_) { const uint32_t frames = buffer_size(); @@ -128,5 +137,4 @@ void port_audio_device::render_thread() { } } spdlog::info("port_audio render thread stopped"); - render_thread_running_ = false; } diff --git a/core/audio/device/port_audio_device.h b/core/audio/device/port_audio_device.h index a77c5f7..9815728 100644 --- a/core/audio/device/port_audio_device.h +++ b/core/audio/device/port_audio_device.h @@ -12,6 +12,7 @@ public: void stop(); + void start(); void open_stream(PaDeviceIndex input_device, PaDeviceIndex output_device, double in_sample_rate, uint32_t in_buffer_size); int stream_callback(float** input, float** output, unsigned long frame_count, const PaStreamCallbackTimeInfo* time_info, PaStreamCallbackFlags status_flags); @@ -21,6 +22,8 @@ protected: private: #pragma region render_thread + void start_render_thread(); + void stop_render_thread(); void render_thread(); std::thread render_thread_; circular_audio_buffer render_buffer_; diff --git a/core/audio/mixer/mixer.cpp b/core/audio/mixer/mixer.cpp index af710fc..544e35f 100644 --- a/core/audio/mixer/mixer.cpp +++ b/core/audio/mixer/mixer.cpp @@ -62,7 +62,7 @@ void build_instrument_process_node(const plugin_host* host, std::map::init(initliazer); - initliazer.require(); + auto device_manager = initliazer.require(); zero_track = new dummy_track(); zero_track->rename("zero"); zero_track->init(); @@ -71,6 +71,8 @@ void mixer::init(singleton_initliazer& initliazer) { master->rename("master"); master->init(); tracks_.push_back(master); + + device_manager->start(); } void mixer::release() { diff --git a/core/audio/plugin_host/plugin_host.cpp b/core/audio/plugin_host/plugin_host.cpp index 9aa2d09..e33e3eb 100644 --- a/core/audio/plugin_host/plugin_host.cpp +++ b/core/audio/plugin_host/plugin_host.cpp @@ -1,5 +1,6 @@ #include "plugin_host.h" +#include "application/window_manager.h" #include "audio/mixer/channel_interface.h" plugin_host::~plugin_host() { @@ -7,8 +8,7 @@ plugin_host::~plugin_host() { } void plugin_host::try_open_editor() { - auto editor_size = get_editor_size(); - editor_window = glfwCreateWindow(editor_size.x, editor_size.y, name.c_str(), nullptr, nullptr); + editor_window = g_window_manager.create_plugin_host_window(this); open_editor(editor_window); } diff --git a/core/audio/plugin_host/plugin_host_manager.cpp b/core/audio/plugin_host/plugin_host_manager.cpp index 02f4217..0ff58f7 100644 --- a/core/audio/plugin_host/plugin_host_manager.cpp +++ b/core/audio/plugin_host/plugin_host_manager.cpp @@ -16,7 +16,13 @@ void plugin_host_manager::init(singleton_initliazer& initliazer) { plugin_host* plugin_host_manager::load_plugin(const char* path) { auto host = new vst2_plugin_host(); - host->load_plugin(path); + try { + host->load_plugin(path); + } catch (std::exception& e) { + spdlog::error("Failed to load plugin: {}", e.what()); + delete host; + return nullptr; + } host->init_channel_interface(); plugin_hosts_.push_back(host); host->try_open_editor(); diff --git a/core/audio/plugin_host/vst2/vst2_plugin_host.cpp b/core/audio/plugin_host/vst2/vst2_plugin_host.cpp index 0846590..411e604 100644 --- a/core/audio/plugin_host/vst2/vst2_plugin_host.cpp +++ b/core/audio/plugin_host/vst2/vst2_plugin_host.cpp @@ -1,5 +1,6 @@ #include "vst2_plugin_host.h" +#include "application/window_manager.h" #include "audio/device/audio_device_manager.h" #include "audio/mixer/channel_interface.h" #include "misc/glfw_misc.h" @@ -64,9 +65,7 @@ VstIntPtr vst_master_callback(AEffect* effect, VstInt32 opcode, VstInt32 index, case audioMasterSizeWindow: { // 设置插件窗口大小 - // FVST2PluginHost* Host = static_cast(Effect->user); - // if (const TSharedPtr Window = FWindowManager::Get().FindPluginEditor(Host)) - // Window->Resize(FVector2D(Index, Value)); + g_window_manager.resize_plugin_host_window((plugin_host*)effect->user, index, value); return 1; } case audioMasterGetTime: