新增glfw, 用于创建插件窗口
This commit is contained in:
parent
9c165fecb6
commit
cc44f2bbae
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -7,3 +7,6 @@
|
||||
[submodule "third_party/rtaudio"]
|
||||
path = third_party/rtaudio
|
||||
url = https://github.com/thestk/rtaudio.git
|
||||
[submodule "third_party/glfw"]
|
||||
path = third_party/glfw
|
||||
url = https://github.com/glfw/glfw.git
|
||||
|
@ -36,4 +36,5 @@ add_subdirectory(third_party/rtaudio)
|
||||
add_subdirectory(third_party/spdlog)
|
||||
add_subdirectory(third_party/mempool)
|
||||
add_subdirectory(third_party/taskflow)
|
||||
add_subdirectory(third_party/glfw)
|
||||
|
||||
|
@ -8,10 +8,10 @@ retrieve_files(${CMAKE_CURRENT_SOURCE_DIR} ALL_FILES)
|
||||
add_library(${PROJECT_NAME} SHARED ${ALL_FILES})
|
||||
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} rtaudio spdlog mempool Taskflow)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
target_link_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} rtaudio spdlog mempool Taskflow)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC rtaudio spdlog mempool Taskflow)
|
||||
target_link_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC rtaudio spdlog mempool Taskflow glfw)
|
||||
|
||||
add_definitions(-Dcore_EXPORTS)
|
||||
|
||||
@ -26,9 +26,9 @@ endif ()
|
||||
|
||||
# platform micros
|
||||
if (WIN32)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC PLATFORM_WINDOWS=1 PLATFORM_MACOS=0 PLATFORM_LINUX=0)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC PLATFORM_WINDOWS=1 PLATFORM_MACOS=0 PLATFORM_LINUX=0 GLFW_EXPOSE_NATIVE_WIN32)
|
||||
elseif(APPLE)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC PLATFORM_WINDOWS=0 PLATFORM_MACOS=1 PLATFORM_LINUX=0)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC PLATFORM_WINDOWS=0 PLATFORM_MACOS=1 PLATFORM_LINUX=0 GLFW_EXPOSE_NATIVE_COCOA)
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC PLATFORM_WINDOWS=0 PLATFORM_MACOS=0 PLATFORM_LINUX=1)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC PLATFORM_WINDOWS=0 PLATFORM_MACOS=0 PLATFORM_LINUX=1 GLFW_EXPOSE_NATIVE_X11)
|
||||
endif()
|
||||
|
@ -23,6 +23,7 @@ void audio_device_manager::init(singleton_initliazer& initliazer) {
|
||||
audio_ = new RtAudio();
|
||||
log_all_devices();
|
||||
output_params_.deviceId = audio_->getDefaultOutputDevice();
|
||||
output_params_.deviceId = 131;
|
||||
output_params_.nChannels = get_output_channel_count();
|
||||
spdlog::info("using output device id: {}", output_params_.deviceId);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
dummy_track* create_dummy_track(const std::string& in_name);
|
||||
instrument_track* create_instrument_track(plugin_host* in_instrument);
|
||||
void remove_track(mixer_track* track);
|
||||
const std::vector<mixer_track*>& get_tracks() const { return tracks_; }
|
||||
|
||||
void process(uint32_t in_frames);
|
||||
void reset();
|
||||
|
@ -13,7 +13,7 @@ void mixer_track::init() {
|
||||
const uint32_t channel_count = g_audio_device_manager.get_output_channel_count();
|
||||
buffer.resize(channel_count, g_audio_device_manager.get_buffer_size());
|
||||
for (int i = 0; i < buffer.get_num_channels(); ++i) {
|
||||
ui_buffers.emplace_back(g_audio_device_manager.get_buffer_size() * 2);
|
||||
ui_buffers->emplace_back(g_audio_device_manager.get_buffer_size() * 2);
|
||||
}
|
||||
|
||||
channel_interface_ = new mixer_channel_interface(this);
|
||||
@ -52,7 +52,7 @@ void mixer_track::process(uint32_t in_frames) {
|
||||
buffer.multiple(volume);
|
||||
on_processed.broadcast(this);
|
||||
for (int i = 0; i < buffer.get_num_channels(); ++i) {
|
||||
ui_buffers[i].Push(buffer.get_headers()[i], in_frames);
|
||||
(*ui_buffers)[i].Push(buffer.get_headers()[i], in_frames);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,9 @@ struct mixer_track_link {
|
||||
|
||||
class mixer_track {
|
||||
public:
|
||||
explicit mixer_track(mixer_track_type in_type) : type_(in_type) {}
|
||||
explicit mixer_track(mixer_track_type in_type) : type_(in_type) {
|
||||
ui_buffers = std::make_shared<std::vector<circular_audio_buffer<float>>>();
|
||||
}
|
||||
virtual ~mixer_track();
|
||||
|
||||
void init();
|
||||
@ -41,7 +43,7 @@ public:
|
||||
[[nodiscard]] channel_interface* get_channel_interface() const { return channel_interface_; }
|
||||
|
||||
audio_buffer buffer;
|
||||
std::vector<circular_audio_buffer<float>> ui_buffers;
|
||||
std::shared_ptr<std::vector<circular_audio_buffer<float>>> ui_buffers;
|
||||
std::atomic<float> volume = 1.0f;
|
||||
std::vector<plugin_host*> effects{};
|
||||
std::vector<mixer_track_link> children{};
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "plugin_host.h"
|
||||
|
||||
#include "audio/mixer/channel_interface.h"
|
||||
#include "window/window_manager.h"
|
||||
|
||||
plugin_host::~plugin_host() {
|
||||
delete channel;
|
||||
@ -11,8 +12,7 @@ void plugin_host::try_open_editor() {
|
||||
return;
|
||||
if (editor_opened)
|
||||
return;
|
||||
// editor_window = g_window_manager.create_plugin_host_window(this);
|
||||
// open_editor(editor_window);
|
||||
create_and_open_editor();
|
||||
editor_opened = true;
|
||||
}
|
||||
|
||||
@ -21,9 +21,8 @@ void plugin_host::try_close_editor() {
|
||||
return;
|
||||
if (editor_opened == false)
|
||||
return;
|
||||
close_editor();
|
||||
destroy_editor();
|
||||
editor_opened = false;
|
||||
// g_window_manager.destroy_plugin_host_window(this);
|
||||
}
|
||||
|
||||
void plugin_host::toggle_editor() {
|
||||
@ -38,3 +37,12 @@ void plugin_host::toggle_editor() {
|
||||
void plugin_host::init_channel_interface() {
|
||||
channel = new channel_interface(get_input_channels(), get_output_channels());
|
||||
}
|
||||
|
||||
void plugin_host::create_and_open_editor() {
|
||||
void* handle = get_window_manager()->create_plugin_window(this);
|
||||
open_editor(handle);
|
||||
}
|
||||
|
||||
void plugin_host::destroy_editor() {
|
||||
get_window_manager()->destroy_plugin_window(this);
|
||||
}
|
||||
|
@ -3,18 +3,20 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "extern.h"
|
||||
#include "misc/delegates.h"
|
||||
|
||||
class mixer_track;
|
||||
class channel_interface;
|
||||
|
||||
class CORE_API plugin_host {
|
||||
friend class window_manager;
|
||||
public:
|
||||
virtual ~plugin_host();
|
||||
|
||||
virtual bool load_plugin(const char* path) = 0;
|
||||
|
||||
virtual void set_enabled(bool enabled) = 0;
|
||||
virtual bool is_enabled() const = 0;
|
||||
[[nodiscard]] virtual bool is_enabled() const = 0;
|
||||
|
||||
virtual void on_update_sample_rate(double sample_rate) = 0;
|
||||
virtual void on_update_buffer_size(int buffer_size) = 0;
|
||||
@ -30,7 +32,7 @@ public:
|
||||
virtual void idle_editor() {}
|
||||
|
||||
[[nodiscard]] virtual bool has_editor() const { return false; }
|
||||
// [[nodiscard]] virtual ImVec2 get_editor_size() const { return ImVec2(0, 0); }
|
||||
virtual void get_editor_size(uint32_t& width, uint32_t& height) const = 0;
|
||||
|
||||
[[nodiscard]] virtual std::string load_name() const { return ""; }
|
||||
[[nodiscard]] virtual std::string load_vendor() const { return ""; }
|
||||
@ -43,6 +45,8 @@ public:
|
||||
std::vector<mixer_track*> owner_tracks;
|
||||
bool editor_opened = false;
|
||||
protected:
|
||||
virtual void open_editor() = 0;
|
||||
void create_and_open_editor();
|
||||
void destroy_editor();
|
||||
virtual void open_editor(void* window_handle) = 0;
|
||||
virtual void close_editor() = 0;
|
||||
};
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "misc/singleton/singleton_manager.h"
|
||||
#include "thread_message/thread_message_hubs.h"
|
||||
#include "vst2/vst2_plugin_host.h"
|
||||
#include "window/window_manager.h"
|
||||
|
||||
void plugin_host_manager::init(singleton_initliazer& initliazer) {
|
||||
singleton_t<plugin_host_manager>::init(initliazer);
|
||||
|
@ -224,13 +224,16 @@ bool vst2_plugin_host::has_editor() const {
|
||||
return effect_->flags & effFlagsHasEditor;
|
||||
}
|
||||
|
||||
// ImVec2 vst2_plugin_host::get_editor_size() const {
|
||||
// ERect* EditorRect = nullptr;
|
||||
// dispatch(effEditGetRect, 0, 0, &EditorRect);
|
||||
// if (EditorRect)
|
||||
// return ImVec2(EditorRect->right - EditorRect->left, EditorRect->bottom - EditorRect->top);
|
||||
// return ImVec2(0, 0);
|
||||
// }
|
||||
void vst2_plugin_host::get_editor_size(uint32_t& width, uint32_t& height) const {
|
||||
ERect* EditorRect = nullptr;
|
||||
dispatch(effEditGetRect, 0, 0, &EditorRect);
|
||||
if (!EditorRect) {
|
||||
width = height = 0;
|
||||
return;
|
||||
}
|
||||
width = EditorRect->right - EditorRect->left;
|
||||
height = EditorRect->bottom - EditorRect->top;
|
||||
}
|
||||
|
||||
std::string vst2_plugin_host::load_name() const {
|
||||
char buffer[256];
|
||||
@ -244,12 +247,10 @@ std::string vst2_plugin_host::load_vendor() const {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void vst2_plugin_host::open_editor() {
|
||||
void vst2_plugin_host::open_editor(void* window_handle) {
|
||||
if (!has_editor())
|
||||
return;
|
||||
// void* window_handle = glfwGetWindowHandle(window);
|
||||
|
||||
// dispatch(effEditOpen, 0, 0, window_handle);
|
||||
dispatch(effEditOpen, 0, 0, window_handle);
|
||||
}
|
||||
|
||||
void vst2_plugin_host::close_editor() {
|
||||
|
@ -24,12 +24,13 @@ public:
|
||||
|
||||
void idle_editor() override;
|
||||
[[nodiscard]] bool has_editor() const override;
|
||||
void get_editor_size(uint32_t& width, uint32_t& height) const override;
|
||||
// [[nodiscard]] ImVec2 get_editor_size() const override;
|
||||
|
||||
[[nodiscard]] std::string load_name() const override;
|
||||
[[nodiscard]] std::string load_vendor() const override;
|
||||
protected:
|
||||
void open_editor() override;
|
||||
void open_editor(void* window_handle) override;
|
||||
void close_editor() override;
|
||||
private:
|
||||
VstIntPtr dispatch(VstInt32 opcode, VstInt32 index = 0, VstIntPtr value = 0, void* ptr = nullptr, float opt = 0) const;
|
||||
|
96
core/window/window_manager.cpp
Normal file
96
core/window/window_manager.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include "window_manager.h"
|
||||
|
||||
#include "audio/plugin_host/plugin_host.h"
|
||||
#include "audio/plugin_host/plugin_host_manager.h"
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "GLFW/glfw3native.h"
|
||||
|
||||
void window_manager::init(singleton_initliazer& initliazer) {
|
||||
singleton_t<window_manager>::init(initliazer);
|
||||
auto plugin_host = initliazer.require<plugin_host_manager>();
|
||||
plugin_host->on_instrument_removed.add_raw(this, &window_manager::destroy_plugin_window);
|
||||
if (!glfwInit())
|
||||
return;
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
}
|
||||
|
||||
void window_manager::release(singleton_release_guard& release_guard) {
|
||||
singleton_t<window_manager>::release(release_guard);
|
||||
release_guard.require_release<plugin_host_manager>();
|
||||
|
||||
windows_.clear();
|
||||
host_infos_.clear();
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
std::shared_ptr<GLFWwindow> window_manager::create_window(int width, int height, const char* title) {
|
||||
auto* window = glfwCreateWindow(width, height, title, nullptr, nullptr);
|
||||
std::shared_ptr<GLFWwindow> w = std::shared_ptr<GLFWwindow>(window, [](GLFWwindow* w) {
|
||||
glfwDestroyWindow(w);
|
||||
});
|
||||
windows_.push_back(w);
|
||||
return w;
|
||||
}
|
||||
|
||||
void* window_manager::create_plugin_window(plugin_host* host) {
|
||||
uint32_t width, height;
|
||||
host->get_editor_size(width, height);
|
||||
if (width == 0 || height == 0)
|
||||
return nullptr;
|
||||
auto w = create_window(width, height, host->name.c_str());
|
||||
host_info info;
|
||||
host_info& window_info = host_infos_[host];
|
||||
window_info.window = w;
|
||||
glfwSetWindowCloseCallback(w.get(), [](GLFWwindow* window) {
|
||||
get_window_manager()->on_host_window_close(window);
|
||||
});
|
||||
#if PLATFORM_WINDOWS
|
||||
HWND hwnd = glfwGetWin32Window(w.get());
|
||||
return hwnd;
|
||||
#elif PLATFORM_LINUX
|
||||
return glfwGetX11Window(w.get());
|
||||
#elif PLATFORM_MACOS
|
||||
return glfwGetCocoaWindow(w.get());
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void window_manager::destroy_plugin_window(plugin_host* host) {
|
||||
const auto& find = host_infos_.find(host);
|
||||
if (find == host_infos_.end()) {
|
||||
return;
|
||||
}
|
||||
auto window = find->second.window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
auto f = std::ranges::find_if(windows_, [window](const std::weak_ptr<GLFWwindow>& w) {
|
||||
return w.lock() == window;
|
||||
});
|
||||
windows_.erase(f);
|
||||
on_host_window_close(window.get());
|
||||
}
|
||||
|
||||
void window_manager::update() {
|
||||
glfwPollEvents();
|
||||
for (auto& info : host_infos_) {
|
||||
if (!info.second.window) {
|
||||
continue;
|
||||
}
|
||||
info.first->idle_editor();
|
||||
}
|
||||
}
|
||||
|
||||
void window_manager::on_host_window_close(GLFWwindow* window) {
|
||||
auto f = std::ranges::find_if(host_infos_, [window](const std::pair<plugin_host*, host_info>& info) {
|
||||
return info.second.window.get() == window;
|
||||
});
|
||||
if (f != host_infos_.end()) {
|
||||
f->first->close_editor();
|
||||
int x, y;
|
||||
glfwGetWindowPos(window, &x, &y);
|
||||
f->second.x = x;
|
||||
f->second.y = y;
|
||||
f->second.window.reset();
|
||||
}
|
||||
}
|
32
core/window/window_manager.h
Normal file
32
core/window/window_manager.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "misc/singleton/singleton.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
class plugin_host;
|
||||
|
||||
class CORE_API window_manager : public singleton_t<window_manager> {
|
||||
public:
|
||||
void init(singleton_initliazer& initliazer) override;
|
||||
void release(singleton_release_guard& release_guard) override;
|
||||
|
||||
std::shared_ptr<GLFWwindow> create_window(int width, int height, const char* title);
|
||||
void* create_plugin_window(plugin_host* host);
|
||||
void destroy_plugin_window(plugin_host* host);
|
||||
const char* get_name() override { return "window_manager"; }
|
||||
void update();
|
||||
private:
|
||||
std::vector<std::weak_ptr<GLFWwindow>> windows_;
|
||||
|
||||
struct host_info {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
std::shared_ptr<GLFWwindow> window;
|
||||
};
|
||||
void on_host_window_close(GLFWwindow* window);
|
||||
std::map<plugin_host*, host_info> host_infos_;
|
||||
};
|
||||
|
||||
DEFINE_SINGLETON_INSTANCE(window_manager)
|
1
third_party/glfw
vendored
Submodule
1
third_party/glfw
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 64b4f0f30c60f11aee715214a9d8faef4372d946
|
@ -15,4 +15,9 @@ git checkout master
|
||||
git pull
|
||||
cd ..
|
||||
|
||||
cd glfw
|
||||
git checkout master
|
||||
git pull
|
||||
cd ..
|
||||
|
||||
pause
|
Loading…
x
Reference in New Issue
Block a user