新增窗口管理
This commit is contained in:
parent
2f1fc152ff
commit
63436a413f
@ -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<texture> 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();
|
||||
}
|
||||
|
||||
|
@ -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<spdlog::logger> async_spdlog_;
|
||||
|
||||
private:
|
||||
|
90
core/application/window_manager.cpp
Normal file
90
core/application/window_manager.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
#include "window_manager.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "audio/plugin_host/plugin_host.h"
|
||||
|
||||
window_manager::window_manager() {
|
||||
main_window_ = nullptr;
|
||||
}
|
||||
|
||||
void window_manager::init(singleton_initliazer& initliazer) {
|
||||
singleton_t<window_manager>::init(initliazer);
|
||||
start_idle_thread();
|
||||
}
|
||||
|
||||
void window_manager::release() {
|
||||
singleton_t<window_manager>::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();
|
||||
}
|
||||
}
|
41
core/application/window_manager.h
Normal file
41
core/application/window_manager.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "misc/singleton/singleton.h"
|
||||
#include <map>
|
||||
|
||||
class plugin_host;
|
||||
|
||||
class window_manager : public singleton_t<window_manager> {
|
||||
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<plugin_host*, GLFWwindow*> host_window_map_;
|
||||
};
|
||||
|
||||
DEFINE_SINGLETON_INSTANCE(window_manager)
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<float> render_buffer_;
|
||||
|
@ -62,7 +62,7 @@ void build_instrument_process_node(const plugin_host* host, std::map<mixer_track
|
||||
|
||||
void mixer::init(singleton_initliazer& initliazer) {
|
||||
singleton_t<mixer>::init(initliazer);
|
||||
initliazer.require<audio_device_manager>();
|
||||
auto device_manager = initliazer.require<audio_device_manager>();
|
||||
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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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<FVST2PluginHost*>(Effect->user);
|
||||
// if (const TSharedPtr<SWindow> 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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user