添加 GLFW 支持,创建 VST2 插件宿主,更新 CMake 配置和源文件
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ cmake-build-*/
|
||||
/src/frontend/obj/
|
||||
/build
|
||||
/.vs
|
||||
*.DotSettings.user
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ==============================================================================
|
||||
# NinaEngine - 构建脚本
|
||||
# AlichoEngine - 构建脚本
|
||||
#
|
||||
# 核心职责:
|
||||
# 该 CMakeLists.txt 文件负责定义 "NinaEngine" 可执行文件的完整构建流程。
|
||||
@@ -24,6 +24,7 @@ include(cmake_script/retrieve_files.cmake) # 负责递归查找源文件。
|
||||
include(cmake_script/utils.cmake) # 提供其他工具函数,如 compile_proto_files。
|
||||
include(cmake_script/detect_os.cmake)
|
||||
include(cmake_script/plugin_host_register.cmake)
|
||||
include(cmake_script/configure_glfw_native.cmake)
|
||||
|
||||
# 使用自定义函数来配置项目的编译选项。
|
||||
# @param STANDARD: 指定C++语言标准,此处为 C++23。
|
||||
@@ -63,6 +64,7 @@ compile_proto_files(
|
||||
GRPC_ENABLED TRUE
|
||||
)
|
||||
|
||||
add_subdirectory(src/misc)
|
||||
add_subdirectory(src/vst2_host)
|
||||
add_subdirectory(src/vst3_host)
|
||||
add_subdirectory(src/engine)
|
||||
|
||||
42
src/backend/cmake_script/configure_glfw_native.cmake
Normal file
42
src/backend/cmake_script/configure_glfw_native.cmake
Normal file
@@ -0,0 +1,42 @@
|
||||
function(configure_glfw_native target)
|
||||
# 检测操作系统
|
||||
if(WIN32)
|
||||
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_WIN32)
|
||||
message(STATUS "公开 GLFW 原生 Win32 API")
|
||||
elseif(APPLE)
|
||||
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_COCOA)
|
||||
message(STATUS "公开 GLFW 原生 Cocoa API")
|
||||
elseif(UNIX)
|
||||
# 对于 Unix-like 系统,我们需要进一步检测
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# 检测 Wayland
|
||||
find_package(Wayland)
|
||||
if(Wayland_FOUND)
|
||||
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_WAYLAND)
|
||||
message(STATUS "公开 GLFW 原生 Wayland API")
|
||||
else()
|
||||
# 如果没有 Wayland,默认使用 X11
|
||||
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_X11)
|
||||
message(STATUS "公开 GLFW 原生 X11 API")
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD|OpenBSD|NetBSD")
|
||||
# BSD 系统通常使用 X11
|
||||
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_X11)
|
||||
message(STATUS "公开 BSD 的 GLFW 原生 X11 API")
|
||||
else()
|
||||
message(WARNING "未知的类 Unix 系统,GLFW 原生 API 可能无法正确暴露")
|
||||
endif()
|
||||
elseif (ANDROID)
|
||||
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_ANDROID)
|
||||
message(STATUS "公开 GLFW 原生 Android API")
|
||||
else()
|
||||
message(WARNING "未知作系统,GLFW 原生 API 可能无法正确暴露")
|
||||
endif()
|
||||
|
||||
# 对于 EGL 支持,你可能需要额外的检测
|
||||
# 这里我们简单地为所有非 Windows 和非 macOS 系统启用它
|
||||
if(NOT WIN32 AND NOT APPLE)
|
||||
target_compile_definitions(${target} PRIVATE GLFW_EXPOSE_NATIVE_EGL)
|
||||
message(STATUS "公开 GLFW 原生 EGL API")
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -10,62 +10,65 @@ function(add_os_definitions target)
|
||||
# --- 阶段 1: 确定宏的值 ---
|
||||
|
||||
# 初始化所有平台、架构和特性宏的值为 0
|
||||
set(piko_def_windows 0)
|
||||
set(piko_def_macos 0)
|
||||
set(piko_def_linux 0)
|
||||
set(piko_def_freebsd 0)
|
||||
set(piko_def_ios 0)
|
||||
set(piko_def_android 0)
|
||||
set(piko_def_cygwin 0)
|
||||
set(piko_def_unix 0)
|
||||
set(piko_def_posix 0)
|
||||
set(piko_def_mobile 0)
|
||||
set(piko_def_arch_64bit 0)
|
||||
set(piko_def_arch_32bit 0)
|
||||
set(alicho_def_windows 0)
|
||||
set(alicho_def_macos 0)
|
||||
set(alicho_def_linux 0)
|
||||
set(alicho_def_freebsd 0)
|
||||
set(alicho_def_ios 0)
|
||||
set(alicho_def_android 0)
|
||||
set(alicho_def_cygwin 0)
|
||||
set(alicho_def_unix 0)
|
||||
set(alicho_def_posix 0)
|
||||
set(alicho_def_mobile 0)
|
||||
set(alicho_def_arch_64bit 0)
|
||||
set(alicho_def_arch_32bit 0)
|
||||
set(alicho_def_apple 0) # 用于 iOS 和 macOS 的通用定义
|
||||
|
||||
# -- 操作系统检测与赋值 --
|
||||
# 注意检测顺序:优先检测更具体的平台
|
||||
if(CYGWIN)
|
||||
# Cygwin 环境比较特殊,它在 Windows 上模拟 Unix
|
||||
set(piko_def_windows 1) # 基础是 Windows
|
||||
set(piko_def_cygwin 1) # 明确是 Cygwin
|
||||
set(piko_def_unix 1) # 提供 Unix API
|
||||
set(piko_def_posix 1) # 提供 POSIX API
|
||||
set(alicho_def_windows 1) # 基础是 Windows
|
||||
set(alicho_def_cygwin 1) # 明确是 Cygwin
|
||||
set(alicho_def_unix 1) # 提供 Unix API
|
||||
set(alicho_def_posix 1) # 提供 POSIX API
|
||||
message(STATUS "检测到 **Cygwin** 环境 (运行于 Windows)")
|
||||
elseif(WIN32)
|
||||
# 非 Cygwin 的 Windows 环境 (MSVC, MinGW, etc.)
|
||||
set(piko_def_windows 1)
|
||||
set(alicho_def_windows 1)
|
||||
message(STATUS "检测到 **Windows** 操作系统 (非 Cygwin)")
|
||||
elseif(ANDROID)
|
||||
# Android 平台 (通常需要特定工具链设置 ANDROID 变量)
|
||||
set(piko_def_android 1)
|
||||
set(piko_def_unix 1) # Android NDK 基于 Unix
|
||||
set(piko_def_posix 1) # NDK 提供 POSIX API
|
||||
set(piko_def_mobile 1) # 移动平台
|
||||
set(alicho_def_android 1)
|
||||
set(alicho_def_unix 1) # Android NDK 基于 Unix
|
||||
set(alicho_def_posix 1) # NDK 提供 POSIX API
|
||||
set(alicho_def_mobile 1) # 移动平台
|
||||
message(STATUS "检测到 **Android** 操作系统")
|
||||
elseif(IOS)
|
||||
# iOS 平台 (通常需要特定工具链设置 IOS 变量)
|
||||
# 需要在 APPLE 之前判断,因为 iOS 下 APPLE 也为 TRUE
|
||||
set(piko_def_ios 1)
|
||||
set(piko_def_unix 1) # iOS (Darwin) 基于 Unix
|
||||
set(piko_def_posix 1) # 提供 POSIX API
|
||||
set(piko_def_mobile 1) # 移动平台
|
||||
set(alicho_def_ios 1)
|
||||
set(alicho_def_unix 1) # iOS (Darwin) 基于 Unix
|
||||
set(alicho_def_posix 1) # 提供 POSIX API
|
||||
set(alicho_def_mobile 1) # 移动平台
|
||||
set(alicho_def_apple 1) # iOS 是 Apple 生态的一部分
|
||||
message(STATUS "检测到 **iOS** 操作系统")
|
||||
elseif(APPLE)
|
||||
# 此时排除了 iOS,确定是 macOS
|
||||
set(piko_def_macos 1)
|
||||
set(piko_def_unix 1) # macOS (Darwin) 基于 Unix
|
||||
set(piko_def_posix 1) # 提供 POSIX API
|
||||
set(alicho_def_macos 1)
|
||||
set(alicho_def_unix 1) # macOS (Darwin) 基于 Unix
|
||||
set(alicho_def_posix 1) # 提供 POSIX API
|
||||
set(alicho_def_apple 1) # macOS 是 Apple 生态的一部分
|
||||
message(STATUS "检测到 **macOS** 操作系统")
|
||||
elseif(UNIX)
|
||||
# 此时排除了 Apple, Android, Cygwin 的其他 Unix-like 系统
|
||||
set(piko_def_unix 1)
|
||||
set(piko_def_posix 1)
|
||||
set(alicho_def_unix 1)
|
||||
set(alicho_def_posix 1)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(piko_def_linux 1)
|
||||
set(alicho_def_linux 1)
|
||||
message(STATUS "检测到 **Linux** 操作系统")
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
set(piko_def_freebsd 1)
|
||||
set(alicho_def_freebsd 1)
|
||||
message(STATUS "检测到 **FreeBSD** 操作系统")
|
||||
else()
|
||||
message(WARNING "检测到未知的 类Unix 操作系统: ${CMAKE_SYSTEM_NAME}")
|
||||
@@ -76,12 +79,12 @@ function(add_os_definitions target)
|
||||
|
||||
# -- 架构检测与赋值 --
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(piko_def_arch_64bit 1)
|
||||
set(piko_def_arch_32bit 0) # 明确设置为 0
|
||||
set(alicho_def_arch_64bit 1)
|
||||
set(alicho_def_arch_32bit 0) # 明确设置为 0
|
||||
message(STATUS "检测到 **64-bit** 架构")
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(piko_def_arch_64bit 0) # 明确设置为 0
|
||||
set(piko_def_arch_32bit 1)
|
||||
set(alicho_def_arch_64bit 0) # 明确设置为 0
|
||||
set(alicho_def_arch_32bit 1)
|
||||
message(STATUS "检测到 **32-bit** 架构")
|
||||
else()
|
||||
# 对于未知或未定义的指针大小,两者都保持 0
|
||||
@@ -92,22 +95,23 @@ function(add_os_definitions target)
|
||||
set(definitions_list "") # 初始化空列表
|
||||
|
||||
# 添加平台定义
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_WINDOWS=${piko_def_windows}")
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_MACOS=${piko_def_macos}")
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_LINUX=${piko_def_linux}")
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_FREEBSD=${piko_def_freebsd}")
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_IOS=${piko_def_ios}")
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_ANDROID=${piko_def_android}")
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_CYGWIN=${piko_def_cygwin}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_WINDOWS=${alicho_def_windows}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_MACOS=${alicho_def_macos}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_LINUX=${alicho_def_linux}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_FREEBSD=${alicho_def_freebsd}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_IOS=${alicho_def_ios}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_ANDROID=${alicho_def_android}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_CYGWIN=${alicho_def_cygwin}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_APPLE=${alicho_def_apple}") # 用于 iOS 和 macOS 的通用定义
|
||||
|
||||
# 添加架构定义
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_ARCH_64BIT=${piko_def_arch_64bit}")
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_ARCH_32BIT=${piko_def_arch_32bit}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_ARCH_64BIT=${alicho_def_arch_64bit}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_ARCH_32BIT=${alicho_def_arch_32bit}")
|
||||
|
||||
# 添加特性定义
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_UNIX=${piko_def_unix}")
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_POSIX=${piko_def_posix}")
|
||||
list(APPEND definitions_list "PIKO_PLATFORM_IS_MOBILE=${piko_def_mobile}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_UNIX=${alicho_def_unix}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_POSIX=${alicho_def_posix}")
|
||||
list(APPEND definitions_list "ALICHO_PLATFORM_IS_MOBILE=${alicho_def_mobile}")
|
||||
|
||||
# --- 阶段 3: 应用所有定义 ---
|
||||
# **关键:使用一次调用将所有定义添加到目标**
|
||||
@@ -115,7 +119,7 @@ function(add_os_definitions target)
|
||||
target_compile_definitions(${target} PUBLIC ${definitions_list})
|
||||
endif()
|
||||
|
||||
# 函数作用域结束时,piko_def_* 变量会自动销毁,无需显式 unset
|
||||
# 函数作用域结束时,alicho_def_* 变量会自动销毁,无需显式 unset
|
||||
|
||||
endfunction()
|
||||
|
||||
|
||||
29
src/backend/src/misc/CMakeLists.txt
Normal file
29
src/backend/src/misc/CMakeLists.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
project(AlichoMisc)
|
||||
|
||||
# --- 源代码文件管理 (Source File Management) ---
|
||||
# 初始化一个变量用于存储所有源文件的路径。
|
||||
set(SRC_FILES "")
|
||||
|
||||
# 调用自定义函数递归地从 'src' 目录中检索所有源文件,
|
||||
# 并将文件列表追加到 SRC_FILES 变量中。
|
||||
# @param CMAKE_CURRENT_SOURCE_DIR/src: 要搜索的源文件根目录。
|
||||
# @param SRC_FILES: 用于接收文件列表的输出变量。
|
||||
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)
|
||||
|
||||
# --- 可执行文件目标定义 (Executable Target Definition) ---
|
||||
# 创建一个名为 NinaEngine (与项目名相同) 的可执行文件。
|
||||
# @param ${PROJECT_NAME}: 目标名称。
|
||||
# @param ${SRC_FILES}: 构成该目标的所有源文件。
|
||||
add_library(${PROJECT_NAME} STATIC ${SRC_FILES})
|
||||
|
||||
# 将依赖库链接到我们的可执行文件目标。
|
||||
# @param ${PROJECT_NAME}: 要链接的目标。
|
||||
# @param PRIVATE: 表示链接的依赖项仅对 ${PROJECT_NAME} 自身可见,
|
||||
# 不会传递给链接到 ${PROJECT_NAME} 的其他目标。
|
||||
# @param config_target: 链接之前创建的接口目标,以应用通用的编译设置。
|
||||
# @param gRPC::grpc++: gRPC 库提供的 C++ 目标。
|
||||
# @param protobuf::libprotobuf: Protobuf 运行时库目标。
|
||||
# @param zmq: ZeroMQ 库目标。
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE config_target)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
add_os_definitions(${PROJECT_NAME})
|
||||
28
src/backend/src/misc/src/library_handle.h
Normal file
28
src/backend/src/misc/src/library_handle.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
||||
class library_handle {
|
||||
friend class std::shared_ptr<library_handle>;
|
||||
public:
|
||||
virtual ~library_handle() = default;
|
||||
static library_handle* create(const std::filesystem::path& in_path);
|
||||
|
||||
void* get_func_address(const char* in_name) const;
|
||||
|
||||
template<typename FuncType>
|
||||
auto get_func(const char* in_name) const -> FuncType {
|
||||
void* addr = get_func_address(in_name);
|
||||
if (!addr)
|
||||
return nullptr;
|
||||
return reinterpret_cast<FuncType>(addr);
|
||||
}
|
||||
|
||||
[[nodiscard]] const auto& get_path() const noexcept {
|
||||
return path_;
|
||||
}
|
||||
protected:
|
||||
library_handle() = default;
|
||||
std::filesystem::path path_;
|
||||
void* handle_ = nullptr;
|
||||
};
|
||||
11
src/backend/src/misc/src/size_type.h
Normal file
11
src/backend/src/misc/src/size_type.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
template<typename T>
|
||||
struct vec {
|
||||
T x, y;
|
||||
vec() : x(0), y(0) {}
|
||||
};
|
||||
|
||||
using i_vec2 = vec<int32_t>;
|
||||
using f_vec2 = vec<float>;
|
||||
21
src/backend/src/misc/src/windows/library_handle.cpp
Normal file
21
src/backend/src/misc/src/windows/library_handle.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "library_handle.h"
|
||||
#include <windows.h>
|
||||
|
||||
library_handle* library_handle::create(const std::filesystem::path& in_path) {
|
||||
const auto lib_handle = LoadLibraryA(in_path.string().c_str());
|
||||
if (!lib_handle) {
|
||||
throw std::runtime_error("Failed to load library: " + in_path.string());
|
||||
}
|
||||
auto lib = new library_handle();
|
||||
lib->path_ = in_path;
|
||||
lib->handle_ = lib_handle;
|
||||
return lib;
|
||||
}
|
||||
|
||||
void* library_handle::get_func_address(const char* in_name) const {
|
||||
void* func_address = GetProcAddress(static_cast<HMODULE>(handle_), in_name);
|
||||
if (!func_address) {
|
||||
throw std::runtime_error("Failed to get function address: " + std::string(in_name));
|
||||
}
|
||||
return func_address;
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
project(AlichoPluginHostVst2)
|
||||
|
||||
find_package(glfw3 CONFIG REQUIRED)
|
||||
|
||||
# --- 源代码文件管理 (Source File Management) ---
|
||||
# 初始化一个变量用于存储所有源文件的路径。
|
||||
set(SRC_FILES "")
|
||||
@@ -17,5 +19,10 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
gRPC::grpc++
|
||||
protobuf::libprotobuf
|
||||
libzmq
|
||||
glfw
|
||||
AlichoMisc
|
||||
)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
register_plugin_host(${PROJECT_NAME})
|
||||
configure_glfw_native(${PROJECT_NAME})
|
||||
add_os_definitions(${PROJECT_NAME})
|
||||
|
||||
3
src/backend/src/vst2_host/src/linux/editor.cpp
Normal file
3
src/backend/src/vst2_host/src/linux/editor.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
//
|
||||
// Created by 46944 on 25-8-14.
|
||||
//
|
||||
3
src/backend/src/vst2_host/src/macos/editor.cpp
Normal file
3
src/backend/src/vst2_host/src/macos/editor.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
//
|
||||
// Created by 46944 on 25-8-14.
|
||||
//
|
||||
@@ -1,42 +1,32 @@
|
||||
//
|
||||
// Created by A on 2025/8/13.
|
||||
//
|
||||
#include "daw_api.grpc.pb.h"
|
||||
#include "GLFW/glfw3.h"
|
||||
#include <iostream>
|
||||
|
||||
class test_service : public daw::api::TrackService::Service {
|
||||
public:
|
||||
virtual ~test_service() override;
|
||||
|
||||
virtual grpc::Status AddTrack(grpc::ServerContext* context,
|
||||
const daw::api::AddTrackRequest* request,
|
||||
daw::api::TrackInfo* response) override {
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
virtual grpc::Status RemoveTrack(grpc::ServerContext* context,
|
||||
const daw::api::TrackIdRequest* request,
|
||||
daw::api::StatusResponse* response) override {
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
virtual grpc::Status SetTrackVolume(grpc::ServerContext* context,
|
||||
const daw::api::SetTrackVolumeRequest* request,
|
||||
daw::api::StatusResponse* response) override {
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
virtual grpc::Status SetTrackPan(grpc::ServerContext* context,
|
||||
const daw::api::SetTrackPanRequest* request,
|
||||
daw::api::StatusResponse* response) override {
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
};
|
||||
#include "vst2host.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
glfwSetErrorCallback([](int error, const char* description) {
|
||||
std::println(std::cerr, "GLFW Error {}: {}", error, description);
|
||||
});
|
||||
glfwInit(); // 初始化 GLFW
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // 仅使用 GLFW 的窗口功能,不使用 OpenGL
|
||||
|
||||
auto plugin_path = argv[1];
|
||||
|
||||
load_plugin(plugin_path, 44100, 512);
|
||||
open_editor();
|
||||
|
||||
while (true) {
|
||||
if (is_editor_open()) {
|
||||
glfwPollEvents();
|
||||
idle_editor();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
unload_plugin();
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
351
src/backend/src/vst2_host/src/pluginterfaces/vst2.x/aeffect.h
Normal file
351
src/backend/src/vst2_host/src/pluginterfaces/vst2.x/aeffect.h
Normal file
@@ -0,0 +1,351 @@
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// VST Plug-Ins SDK
|
||||
// Version 2.4 $Date: 2006/06/20 17:22:55 $
|
||||
//
|
||||
// Category : VST 2.x Interfaces
|
||||
// Filename : aeffect.h
|
||||
// Created by : Steinberg Media Technologies
|
||||
// Description : Definition of AEffect structure
|
||||
//
|
||||
// © 2006, Steinberg Media Technologies, All Rights Reserved
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __aeffect__
|
||||
#define __aeffect__
|
||||
|
||||
// gcc based compiler, or CodeWarrior on Mac OS X
|
||||
#if ((defined(__GNUC__) && (defined(__APPLE_CPP__) || defined(__APPLE_CC__))) || (defined (__MWERKS__) && defined (__MACH__)))
|
||||
#ifndef TARGET_API_MAC_CARBON
|
||||
#define TARGET_API_MAC_CARBON 1
|
||||
#endif
|
||||
#if __ppc__
|
||||
#ifndef VST_FORCE_DEPRECATED
|
||||
#define VST_FORCE_DEPRECATED 0
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TARGET_API_MAC_CARBON
|
||||
#ifdef __LP64__
|
||||
#pragma options align=power
|
||||
#else
|
||||
#pragma options align=mac68k
|
||||
#endif
|
||||
#define VSTCALLBACK
|
||||
#elif defined __BORLANDC__
|
||||
#pragma -a8
|
||||
#elif defined(__GNUC__)
|
||||
#pragma pack(push,8)
|
||||
#define VSTCALLBACK __cdecl
|
||||
#elif defined(WIN32) || defined(__FLAT__) || defined CBUILDER
|
||||
#pragma pack(push)
|
||||
#pragma pack(8)
|
||||
#define VSTCALLBACK __cdecl
|
||||
#else
|
||||
#define VSTCALLBACK
|
||||
#endif
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
#include <string.h> // for strncpy
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// VST Version
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Define SDK Version (you can generate different versions (from 2.0 to 2.4) of this SDK by setting the unwanted extensions to 0). */
|
||||
#define VST_2_1_EXTENSIONS 1 ///< Version 2.1 extensions (08-06-2000)
|
||||
#define VST_2_2_EXTENSIONS 1 ///< Version 2.2 extensions (08-06-2001)
|
||||
#define VST_2_3_EXTENSIONS 1 ///< Version 2.3 extensions (20-05-2003)
|
||||
#ifndef VST_2_4_EXTENSIONS
|
||||
#define VST_2_4_EXTENSIONS 1 ///< Version 2.4 extensions (01-01-2006)
|
||||
#endif
|
||||
|
||||
/** Current VST Version */
|
||||
#if VST_2_4_EXTENSIONS
|
||||
#define kVstVersion 2400
|
||||
#elif VST_2_3_EXTENSIONS
|
||||
#define kVstVersion 2300
|
||||
#elif VST_2_2_EXTENSIONS
|
||||
#define kVstVersion 2200
|
||||
#elif VST_2_1_EXTENSIONS
|
||||
#define kVstVersion 2100
|
||||
#else
|
||||
#define kVstVersion 2
|
||||
#endif
|
||||
|
||||
/** Disable for Hosts to serve Plug-ins below VST 2.4 */
|
||||
#ifndef VST_FORCE_DEPRECATED
|
||||
#define VST_FORCE_DEPRECATED VST_2_4_EXTENSIONS
|
||||
#endif
|
||||
|
||||
/** Declares identifier as deprecated. */
|
||||
#if VST_FORCE_DEPRECATED
|
||||
#define DECLARE_VST_DEPRECATED(identifier) __##identifier##Deprecated
|
||||
#else
|
||||
#define DECLARE_VST_DEPRECATED(identifier) identifier
|
||||
#endif
|
||||
|
||||
/** Define for 64 Bit Platform. */
|
||||
#ifndef VST_64BIT_PLATFORM
|
||||
#define VST_64BIT_PLATFORM _WIN64 || __LP64__
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// Integral Types
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef WIN32
|
||||
typedef short VstInt16; ///< 16 bit integer type
|
||||
typedef int VstInt32; ///< 32 bit integer type
|
||||
typedef __int64 VstInt64; ///< 64 bit integer type
|
||||
#else
|
||||
#include <stdint.h>
|
||||
typedef int16_t VstInt16; ///< 16 bit integer type
|
||||
typedef int32_t VstInt32; ///< 32 bit integer type
|
||||
typedef int64_t VstInt64; ///< 64 bit integer type
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// Generic Types
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if VST_64BIT_PLATFORM
|
||||
typedef VstInt64 VstIntPtr; ///< platform-dependent integer type, same size as pointer
|
||||
#else
|
||||
typedef VstInt32 VstIntPtr; ///< platform-dependent integer type, same size as pointer
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// Misc. Definition
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
#undef CCONST
|
||||
struct AEffect;
|
||||
|
||||
/// @cond ignore
|
||||
typedef VstIntPtr (VSTCALLBACK *audioMasterCallback) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);
|
||||
typedef VstIntPtr (VSTCALLBACK *AEffectDispatcherProc) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);
|
||||
typedef void (VSTCALLBACK *AEffectProcessProc) (AEffect* effect, float** inputs, float** outputs, VstInt32 sampleFrames);
|
||||
typedef void (VSTCALLBACK *AEffectProcessDoubleProc) (AEffect* effect, double** inputs, double** outputs, VstInt32 sampleFrames);
|
||||
typedef void (VSTCALLBACK *AEffectSetParameterProc) (AEffect* effect, VstInt32 index, float parameter);
|
||||
typedef float (VSTCALLBACK *AEffectGetParameterProc) (AEffect* effect, VstInt32 index);
|
||||
/// @endcond
|
||||
|
||||
/** Four Character Constant (for AEffect->uniqueID) */
|
||||
#define CCONST(a, b, c, d) \
|
||||
((((VstInt32)a) << 24) | (((VstInt32)b) << 16) | (((VstInt32)c) << 8) | (((VstInt32)d) << 0))
|
||||
|
||||
/** AEffect magic number */
|
||||
#define kEffectMagic CCONST ('V', 's', 't', 'P')
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Basic VST Effect "C" Interface. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
struct AEffect
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VstInt32 magic; ///< must be #kEffectMagic ('VstP')
|
||||
|
||||
/** Host to Plug-in dispatcher @see AudioEffect::dispatcher */
|
||||
AEffectDispatcherProc dispatcher;
|
||||
|
||||
/** \deprecated Accumulating process mode is deprecated in VST 2.4! Use AEffect::processReplacing instead! */
|
||||
AEffectProcessProc DECLARE_VST_DEPRECATED (process);
|
||||
|
||||
/** Set new value of automatable parameter @see AudioEffect::setParameter */
|
||||
AEffectSetParameterProc setParameter;
|
||||
|
||||
/** Returns current value of automatable parameter @see AudioEffect::getParameter*/
|
||||
AEffectGetParameterProc getParameter;
|
||||
|
||||
VstInt32 numPrograms; ///< number of programs
|
||||
VstInt32 numParams; ///< all programs are assumed to have numParams parameters
|
||||
VstInt32 numInputs; ///< number of audio inputs
|
||||
VstInt32 numOutputs; ///< number of audio outputs
|
||||
|
||||
VstInt32 flags; ///< @see VstAEffectFlags
|
||||
|
||||
VstIntPtr resvd1; ///< reserved for Host, must be 0
|
||||
VstIntPtr resvd2; ///< reserved for Host, must be 0
|
||||
|
||||
VstInt32 initialDelay; ///< for algorithms which need input in the first place (Group delay or latency in Samples). This value should be initialized in a resume state.
|
||||
|
||||
VstInt32 DECLARE_VST_DEPRECATED (realQualities); ///< \deprecated unused member
|
||||
VstInt32 DECLARE_VST_DEPRECATED (offQualities); ///< \deprecated unused member
|
||||
float DECLARE_VST_DEPRECATED (ioRatio); ///< \deprecated unused member
|
||||
|
||||
void* object; ///< #AudioEffect class pointer
|
||||
void* user; ///< user-defined pointer
|
||||
|
||||
VstInt32 uniqueID; ///< registered unique identifier (register it at Steinberg 3rd party support Web). This is used to identify a plug-in during save+load of preset and project.
|
||||
VstInt32 version; ///< plug-in version (example 1100 for version 1.1.0.0)
|
||||
|
||||
/** Process audio samples in replacing mode @see AudioEffect::processReplacing */
|
||||
AEffectProcessProc processReplacing;
|
||||
|
||||
#if VST_2_4_EXTENSIONS
|
||||
/** Process double-precision audio samples in replacing mode @see AudioEffect::processDoubleReplacing */
|
||||
AEffectProcessDoubleProc processDoubleReplacing;
|
||||
|
||||
char future[56]; ///< reserved for future use (please zero)
|
||||
#else
|
||||
char future[60]; ///< reserved for future use (please zero)
|
||||
#endif
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** AEffect flags */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
enum VstAEffectFlags
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
effFlagsHasEditor = 1 << 0, ///< set if the plug-in provides a custom editor
|
||||
effFlagsCanReplacing = 1 << 4, ///< supports replacing process mode (which should the default mode in VST 2.4)
|
||||
effFlagsProgramChunks = 1 << 5, ///< program data is handled in formatless chunks
|
||||
effFlagsIsSynth = 1 << 8, ///< plug-in is a synth (VSTi), Host may assign mixer channels for its outputs
|
||||
effFlagsNoSoundInStop = 1 << 9, ///< plug-in does not produce sound when input is all silence
|
||||
|
||||
#if VST_2_4_EXTENSIONS
|
||||
effFlagsCanDoubleReplacing = 1 << 12, ///< plug-in supports double precision processing
|
||||
#endif
|
||||
|
||||
DECLARE_VST_DEPRECATED (effFlagsHasClip) = 1 << 1, ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effFlagsHasVu) = 1 << 2, ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effFlagsCanMono) = 1 << 3, ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effFlagsExtIsAsync) = 1 << 10, ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effFlagsExtHasBuffer) = 1 << 11 ///< \deprecated deprecated in VST 2.4
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Basic dispatcher Opcodes (Host to Plug-in) */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
enum AEffectOpcodes
|
||||
{
|
||||
effOpen = 0, ///< no arguments @see AudioEffect::open
|
||||
effClose, ///< no arguments @see AudioEffect::close
|
||||
|
||||
effSetProgram, ///< [value]: new program number @see AudioEffect::setProgram
|
||||
effGetProgram, ///< [return value]: current program number @see AudioEffect::getProgram
|
||||
effSetProgramName, ///< [ptr]: char* with new program name, limited to #kVstMaxProgNameLen @see AudioEffect::setProgramName
|
||||
effGetProgramName, ///< [ptr]: char buffer for current program name, limited to #kVstMaxProgNameLen @see AudioEffect::getProgramName
|
||||
|
||||
effGetParamLabel, ///< [ptr]: char buffer for parameter label, limited to #kVstMaxParamStrLen @see AudioEffect::getParameterLabel
|
||||
effGetParamDisplay, ///< [ptr]: char buffer for parameter display, limited to #kVstMaxParamStrLen @see AudioEffect::getParameterDisplay
|
||||
effGetParamName, ///< [ptr]: char buffer for parameter name, limited to #kVstMaxParamStrLen @see AudioEffect::getParameterName
|
||||
|
||||
DECLARE_VST_DEPRECATED (effGetVu), ///< \deprecated deprecated in VST 2.4
|
||||
|
||||
effSetSampleRate, ///< [opt]: new sample rate for audio processing @see AudioEffect::setSampleRate
|
||||
effSetBlockSize, ///< [value]: new maximum block size for audio processing @see AudioEffect::setBlockSize
|
||||
effMainsChanged, ///< [value]: 0 means "turn off", 1 means "turn on" @see AudioEffect::suspend @see AudioEffect::resume
|
||||
|
||||
effEditGetRect, ///< [ptr]: #ERect** receiving pointer to editor size @see ERect @see AEffEditor::getRect
|
||||
effEditOpen, ///< [ptr]: system dependent Window pointer, e.g. HWND on Windows @see AEffEditor::open
|
||||
effEditClose, ///< no arguments @see AEffEditor::close
|
||||
|
||||
DECLARE_VST_DEPRECATED (effEditDraw), ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effEditMouse), ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effEditKey), ///< \deprecated deprecated in VST 2.4
|
||||
|
||||
effEditIdle, ///< no arguments @see AEffEditor::idle
|
||||
|
||||
DECLARE_VST_DEPRECATED (effEditTop), ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effEditSleep), ///< \deprecated deprecated in VST 2.4
|
||||
DECLARE_VST_DEPRECATED (effIdentify), ///< \deprecated deprecated in VST 2.4
|
||||
|
||||
effGetChunk, ///< [ptr]: void** for chunk data address [index]: 0 for bank, 1 for program @see AudioEffect::getChunk
|
||||
effSetChunk, ///< [ptr]: chunk data [value]: byte size [index]: 0 for bank, 1 for program @see AudioEffect::setChunk
|
||||
|
||||
effNumOpcodes
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Basic dispatcher Opcodes (Plug-in to Host) */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
enum AudioMasterOpcodes
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
audioMasterAutomate = 0, ///< [index]: parameter index [opt]: parameter value @see AudioEffect::setParameterAutomated
|
||||
audioMasterVersion, ///< [return value]: Host VST version (for example 2400 for VST 2.4) @see AudioEffect::getMasterVersion
|
||||
audioMasterCurrentId, ///< [return value]: current unique identifier on shell plug-in @see AudioEffect::getCurrentUniqueId
|
||||
audioMasterIdle, ///< no arguments @see AudioEffect::masterIdle
|
||||
DECLARE_VST_DEPRECATED (audioMasterPinConnected) ///< \deprecated deprecated in VST 2.4 r2
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** String length limits (in characters excl. 0 byte) */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
enum VstStringConstants
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
kVstMaxProgNameLen = 24, ///< used for #effGetProgramName, #effSetProgramName, #effGetProgramNameIndexed
|
||||
kVstMaxParamStrLen = 8, ///< used for #effGetParamLabel, #effGetParamDisplay, #effGetParamName
|
||||
kVstMaxVendorStrLen = 64, ///< used for #effGetVendorString, #audioMasterGetVendorString
|
||||
kVstMaxProductStrLen = 64, ///< used for #effGetProductString, #audioMasterGetProductString
|
||||
kVstMaxEffectNameLen = 32 ///< used for #effGetEffectName
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** String copy taking care of null terminator. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
inline char* vst_strncpy (char* dst, const char* src, size_t maxLen)
|
||||
{
|
||||
char* result = strncpy (dst, src, maxLen);
|
||||
dst[maxLen] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** String concatenation taking care of null terminator. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
inline char* vst_strncat (char* dst, const char* src, size_t maxLen)
|
||||
{
|
||||
char* result = strncat (dst, src, maxLen);
|
||||
dst[maxLen] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Cast #VstIntPtr to pointer. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
template <class T> inline T* FromVstPtr (VstIntPtr& arg)
|
||||
{
|
||||
T** address = (T**)&arg;
|
||||
return *address;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Cast pointer to #VstIntPtr. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
template <class T> inline VstIntPtr ToVstPtr (T* ptr)
|
||||
{
|
||||
VstIntPtr* address = (VstIntPtr*)&ptr;
|
||||
return *address;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Structure used for #effEditGetRect. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
struct ERect
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VstInt16 top; ///< top coordinate
|
||||
VstInt16 left; ///< left coordinate
|
||||
VstInt16 bottom; ///< bottom coordinate
|
||||
VstInt16 right; ///< right coordinate
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
#if TARGET_API_MAC_CARBON
|
||||
#pragma options align=reset
|
||||
#elif defined(WIN32) || defined(__FLAT__) || defined(__GNUC__)
|
||||
#pragma pack(pop)
|
||||
#elif defined __BORLANDC__
|
||||
#pragma -a-
|
||||
#endif
|
||||
|
||||
#endif // __aeffect__
|
||||
1143
src/backend/src/vst2_host/src/pluginterfaces/vst2.x/aeffectx.h
Normal file
1143
src/backend/src/vst2_host/src/pluginterfaces/vst2.x/aeffectx.h
Normal file
File diff suppressed because it is too large
Load Diff
106
src/backend/src/vst2_host/src/pluginterfaces/vst2.x/vstfxstore.h
Normal file
106
src/backend/src/vst2_host/src/pluginterfaces/vst2.x/vstfxstore.h
Normal file
@@ -0,0 +1,106 @@
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
// VST Plug-Ins SDK
|
||||
// Version 2.4 $Date: 2006/02/09 11:05:51 $
|
||||
//
|
||||
// Category : VST 2.x Interfaces
|
||||
// Filename : vstfxstore.h
|
||||
// Created by : Steinberg Media Technologies
|
||||
// Description : Definition of Program (fxp) and Bank (fxb) structures
|
||||
//
|
||||
// © 2006, Steinberg Media Technologies, All Rights Reserved
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __vstfxstore__
|
||||
#define __vstfxstore__
|
||||
|
||||
#ifndef __aeffect__
|
||||
#include "aeffect.h"
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Root chunk identifier for Programs (fxp) and Banks (fxb). */
|
||||
#define cMagic 'CcnK'
|
||||
|
||||
/** Regular Program (fxp) identifier. */
|
||||
#define fMagic 'FxCk'
|
||||
|
||||
/** Regular Bank (fxb) identifier. */
|
||||
#define bankMagic 'FxBk'
|
||||
|
||||
/** Program (fxp) identifier for opaque chunk data. */
|
||||
#define chunkPresetMagic 'FPCh'
|
||||
|
||||
/** Bank (fxb) identifier for opaque chunk data. */
|
||||
#define chunkBankMagic 'FBCh'
|
||||
|
||||
/*
|
||||
Note: The C data structures below are for illustration only. You can not read/write them directly.
|
||||
The byte order on disk of fxp and fxb files is Big Endian. You have to swap integer
|
||||
and floating-point values on Little Endian platforms (Windows, MacIntel)!
|
||||
*/
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Program (fxp) structure. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
struct fxProgram
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VstInt32 chunkMagic; ///< 'CcnK'
|
||||
VstInt32 byteSize; ///< size of this chunk, excl. magic + byteSize
|
||||
|
||||
VstInt32 fxMagic; ///< 'FxCk' (regular) or 'FPCh' (opaque chunk)
|
||||
VstInt32 version; ///< format version (currently 1)
|
||||
VstInt32 fxID; ///< fx unique ID
|
||||
VstInt32 fxVersion; ///< fx version
|
||||
|
||||
VstInt32 numParams; ///< number of parameters
|
||||
char prgName[28]; ///< program name (null-terminated ASCII string)
|
||||
|
||||
union
|
||||
{
|
||||
float params[1]; ///< variable sized array with parameter values
|
||||
struct
|
||||
{
|
||||
VstInt32 size; ///< size of program data
|
||||
char chunk[1]; ///< variable sized array with opaque program data
|
||||
} data; ///< program chunk data
|
||||
} content; ///< program content depending on fxMagic
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
/** Bank (fxb) structure. */
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
struct fxBank
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
VstInt32 chunkMagic; ///< 'CcnK'
|
||||
VstInt32 byteSize; ///< size of this chunk, excl. magic + byteSize
|
||||
|
||||
VstInt32 fxMagic; ///< 'FxBk' (regular) or 'FBCh' (opaque chunk)
|
||||
VstInt32 version; ///< format version (1 or 2)
|
||||
VstInt32 fxID; ///< fx unique ID
|
||||
VstInt32 fxVersion; ///< fx version
|
||||
|
||||
VstInt32 numPrograms; ///< number of programs
|
||||
|
||||
#if VST_2_4_EXTENSIONS
|
||||
VstInt32 currentProgram; ///< version 2: current program number
|
||||
char future[124]; ///< reserved, should be zero
|
||||
#else
|
||||
char future[128]; ///< reserved, should be zero
|
||||
#endif
|
||||
|
||||
union
|
||||
{
|
||||
fxProgram programs[1]; ///< variable number of programs
|
||||
struct
|
||||
{
|
||||
VstInt32 size; ///< size of bank data
|
||||
char chunk[1]; ///< variable sized array with opaque bank data
|
||||
} data; ///< bank chunk data
|
||||
} content; ///< bank content depending on fxMagic
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
#endif // __vstfxstore__
|
||||
149
src/backend/src/vst2_host/src/vst2host.cpp
Normal file
149
src/backend/src/vst2_host/src/vst2host.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
#include "vst2host.h"
|
||||
|
||||
using vst_plugin_entry = AEffect* (*)(audioMasterCallback);
|
||||
|
||||
/* ===== Host-Callback 分发 ===== */
|
||||
inline VstIntPtr VSTCALLBACK host_callback(AEffect* effect,
|
||||
VstInt32 opcode,
|
||||
VstInt32 index,
|
||||
VstIntPtr value,
|
||||
void* ptr,
|
||||
float opt) {
|
||||
switch (opcode) {
|
||||
/* -------- 基础能力 -------- */
|
||||
case audioMasterVersion:
|
||||
return kVstVersion;
|
||||
|
||||
/* -------- 参数自动化 -------- */
|
||||
case audioMasterAutomate:
|
||||
/* index = paramId, opt = value (float 转型于 hostCallback 调用方) */
|
||||
/* 此处可转发至宿主自动化系统,示例仅打印 */
|
||||
// printf("Param %d automated to %f\n", index, *reinterpret_cast<float*>(&value));
|
||||
return 1;
|
||||
|
||||
/* -------- 时基信息 -------- */
|
||||
case audioMasterGetTime:
|
||||
if (ptr) {
|
||||
static VstTimeInfo ti{};
|
||||
ti.sampleRate = current_sample_rate;
|
||||
ti.samplePos = 0; // demo: 由宿主时钟更新
|
||||
ti.flags = kVstPpqPosValid | kVstTempoValid;
|
||||
ti.tempo = current_bpm;
|
||||
*reinterpret_cast<VstTimeInfo**>(ptr) = &ti;
|
||||
return kVstTempoValid | kVstPpqPosValid;
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* -------- Buffer/Latency -------- */
|
||||
case audioMasterGetSampleRate:
|
||||
return static_cast<VstIntPtr>(current_sample_rate);
|
||||
case audioMasterGetBlockSize:
|
||||
return current_block_size;
|
||||
case audioMasterGetInputLatency:
|
||||
case audioMasterGetOutputLatency:
|
||||
return 0;
|
||||
|
||||
/* -------- 显示刷新 -------- */
|
||||
case audioMasterUpdateDisplay:
|
||||
return 1;
|
||||
|
||||
/* -------- 其他默认 -------- */
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void load_plugin(const std::filesystem::path& in_lib_path, float in_sample_rate, int in_block_size) {
|
||||
lib_ = library_handle::create(in_lib_path);
|
||||
auto main_entry = lib_->get_func<vst_plugin_entry>("VSTPluginMain");
|
||||
if (!main_entry) {
|
||||
throw std::runtime_error("未找到 VSTPluginMain : " + in_lib_path.string());
|
||||
}
|
||||
effect_ = main_entry(host_callback);
|
||||
if (!is_valid()) {
|
||||
throw std::runtime_error("插件返回的 AEffect 无效: " + in_lib_path.string());
|
||||
}
|
||||
current_sample_rate = in_sample_rate;
|
||||
current_block_size = in_block_size;
|
||||
|
||||
open_plugin();
|
||||
set_sample_rate(in_sample_rate);
|
||||
set_block_size(in_block_size);
|
||||
resume_plugin();
|
||||
}
|
||||
|
||||
void unload_plugin() {
|
||||
if (!effect_)
|
||||
return;
|
||||
suspend_plugin();
|
||||
close_plugin();
|
||||
delete lib_;
|
||||
lib_ = nullptr;
|
||||
}
|
||||
|
||||
void process(std::span<float*> in_buffers, std::span<float*> out_buffers, int32_t in_frames) {
|
||||
if (effect_->processReplacing)
|
||||
effect_->processReplacing(effect_, in_buffers.data(), out_buffers.data(), in_frames);
|
||||
}
|
||||
|
||||
void process(std::span<double*> in_buffers, std::span<double*> out_buffers, int32_t in_frames) {
|
||||
if (effect_->processDoubleReplacing)
|
||||
effect_->processDoubleReplacing(effect_, in_buffers.data(), out_buffers.data(), in_frames);
|
||||
}
|
||||
|
||||
void open_editor() {
|
||||
if (window_handle)
|
||||
return;
|
||||
// 获取插件编辑器大小
|
||||
const auto& rect = get_editor_rect();
|
||||
const auto width = rect.right - rect.left;
|
||||
const auto height = rect.bottom - rect.top;
|
||||
// 获取插件名称
|
||||
const auto& name = get_name();
|
||||
// 创建 GLFW 窗口
|
||||
window_handle = glfwCreateWindow(width, height, name.c_str(), nullptr, nullptr);
|
||||
if (!window_handle)
|
||||
throw std::runtime_error("无法为 VST 编辑器创建 GLFW 窗口");
|
||||
glfwSetWindowCloseCallback(window_handle, [](GLFWwindow* win) {
|
||||
// 窗口关闭时,关闭编辑器
|
||||
close_editor();
|
||||
});
|
||||
// 如果有最后位置,设置窗口位置
|
||||
if (editor_pos) {
|
||||
glfwSetWindowPos(window_handle, editor_pos->x, editor_pos->y);
|
||||
}
|
||||
// 否则居中显示
|
||||
else {
|
||||
if (const auto monitor = glfwGetPrimaryMonitor()) {
|
||||
if (const auto mode = glfwGetVideoMode(monitor)) {
|
||||
const int x = (mode->width - width) / 2;
|
||||
const int y = (mode->height - height) / 2;
|
||||
glfwSetWindowPos(window_handle, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设置不可以调整窗口大小
|
||||
glfwSetWindowAttrib(window_handle, GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
// 获取窗口句柄
|
||||
auto editor_handle = get_glfw_window_handle(window_handle);
|
||||
if (!editor_handle)
|
||||
throw std::runtime_error("无法获取 VST 编辑器窗口句柄");
|
||||
|
||||
dispatch(effEditOpen, 0, 0, editor_handle, 0);
|
||||
}
|
||||
|
||||
void close_editor() {
|
||||
if (!window_handle)
|
||||
return;
|
||||
// 保存编辑器位置
|
||||
{
|
||||
i_vec2 temp;
|
||||
glfwGetWindowPos(window_handle, &temp.x, &temp.y);
|
||||
editor_pos = temp;
|
||||
}
|
||||
|
||||
dispatch(effEditClose, 0, 0);
|
||||
glfwDestroyWindow(window_handle);
|
||||
window_handle = nullptr;
|
||||
}
|
||||
135
src/backend/src/vst2_host/src/vst2host.h
Normal file
135
src/backend/src/vst2_host/src/vst2host.h
Normal file
@@ -0,0 +1,135 @@
|
||||
#pragma once
|
||||
#include "pluginterfaces/vst2.x/aeffectx.h" // Steinberg 官方头
|
||||
#include <span>
|
||||
|
||||
#include "library_handle.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "size_type.h"
|
||||
|
||||
|
||||
inline library_handle* lib_ = nullptr;
|
||||
inline AEffect* effect_ = nullptr;
|
||||
inline float current_sample_rate;
|
||||
inline int32_t current_block_size;
|
||||
inline double current_bpm = 120.0; // 默认 120 BPM
|
||||
inline GLFWwindow* window_handle = nullptr;
|
||||
inline std::optional<i_vec2> editor_pos{}; // 编辑器最后位置
|
||||
|
||||
void load_plugin(const std::filesystem::path& in_lib_path, float in_sample_rate, int in_block_size);
|
||||
void unload_plugin();
|
||||
|
||||
/* -------- 调度分发 -------- */
|
||||
inline VstIntPtr dispatch(VstInt32 opcode, VstInt32 index = 0, VstIntPtr value = 0, void* ptr = nullptr, float opt = 0.0f) {
|
||||
return effect_->dispatcher(effect_, opcode, index, value, ptr, opt);
|
||||
}
|
||||
|
||||
/* -------- 音频处理 -------- */
|
||||
void process(std::span<float*> in_buffers, std::span<float*> out_buffers, int32_t nFrames);
|
||||
void process(std::span<double*> in_buffers, std::span<double*> out_buffers, int32_t nFrames);
|
||||
|
||||
/* -------- MIDI / 事件 -------- */
|
||||
inline bool send_events(VstEvents* ev) { return dispatch(effProcessEvents, 0, 0, ev) != 0; }
|
||||
|
||||
/* -------- 帮助函数 -------- */
|
||||
inline int get_num_inputs() noexcept { return effect_->numInputs; }
|
||||
inline int get_num_outputs() noexcept { return effect_->numOutputs; }
|
||||
inline int get_num_params() noexcept { return effect_->numParams; }
|
||||
inline bool can_double() noexcept { return effect_->flags & effFlagsCanDoubleReplacing; }
|
||||
inline bool is_synth() noexcept { return effect_->flags & effFlagsIsSynth; }
|
||||
inline int get_unique_id() noexcept { return effect_->uniqueID; }
|
||||
inline float get_parameter(int idx) { return effect_->getParameter(effect_, idx); }
|
||||
inline void set_parameter(int idx, float v) { effect_->setParameter(effect_, idx, v); }
|
||||
inline bool is_valid() noexcept { return effect_ && effect_->magic == kEffectMagic; }
|
||||
inline void set_sample_rate(float in_sample_rate) {
|
||||
current_sample_rate = in_sample_rate;
|
||||
dispatch(effSetSampleRate, 0, 0, nullptr, in_sample_rate);
|
||||
}
|
||||
inline void set_block_size(int in_block_size) {
|
||||
current_block_size = in_block_size;
|
||||
dispatch(effSetBlockSize, 0, in_block_size);
|
||||
}
|
||||
inline std::string get_name() {
|
||||
char name[kVstMaxEffectNameLen];
|
||||
dispatch(effGetEffectName, 0, 0, name);
|
||||
return name;
|
||||
}
|
||||
inline std::string get_vendor() {
|
||||
char vendor[kVstMaxVendorStrLen];
|
||||
dispatch(effGetVendorString, 0, 0, vendor);
|
||||
return vendor;
|
||||
}
|
||||
inline std::string get_product() {
|
||||
char product[kVstMaxProductStrLen];
|
||||
dispatch(effGetProductString, 0, 0, product);
|
||||
return product;
|
||||
}
|
||||
inline std::string get_program_name() {
|
||||
char name[kVstMaxProgNameLen];
|
||||
dispatch(effGetProgramName, 0, 0, name);
|
||||
return name;
|
||||
}
|
||||
inline void set_program_name(const std::string& name) {
|
||||
char buf[kVstMaxProgNameLen];
|
||||
vst_strncpy(buf, name.c_str(), kVstMaxProgNameLen);
|
||||
dispatch(effSetProgramName, 0, 0, buf);
|
||||
}
|
||||
inline void set_program(int idx) {
|
||||
if (idx < 0 || idx >= effect_->numPrograms)
|
||||
return;
|
||||
dispatch(effSetProgram, idx);
|
||||
}
|
||||
inline int32_t get_program() {
|
||||
return static_cast<int32_t>(dispatch(effGetProgram, 0, 0));
|
||||
}
|
||||
inline std::string get_param_label(int idx) {
|
||||
char label[kVstMaxParamStrLen];
|
||||
dispatch(effGetParamLabel, idx, 0, label);
|
||||
return label;
|
||||
}
|
||||
inline std::string get_param_display(int idx) {
|
||||
char display[kVstMaxParamStrLen];
|
||||
dispatch(effGetParamDisplay, idx, 0, display);
|
||||
return display;
|
||||
}
|
||||
inline std::string get_param_name(int idx) {
|
||||
char name[kVstMaxParamStrLen];
|
||||
dispatch(effGetParamName, idx, 0, name);
|
||||
return name;
|
||||
}
|
||||
inline void open_plugin() { dispatch(effOpen); }
|
||||
inline void close_plugin() { dispatch(effClose); }
|
||||
inline void suspend_plugin() { dispatch(effMainsChanged, 0, 0); }
|
||||
inline void resume_plugin() { dispatch(effMainsChanged, 0, 1); }
|
||||
inline bool is_editor_open() {
|
||||
return effect_->flags & effFlagsHasEditor && window_handle != nullptr;
|
||||
}
|
||||
void open_editor();
|
||||
void close_editor();
|
||||
void* get_glfw_window_handle(GLFWwindow* in_glfw_window);
|
||||
|
||||
inline ERect get_editor_rect() {
|
||||
ERect* rect = nullptr;
|
||||
dispatch(effEditGetRect, 0, 0, &rect);
|
||||
return *rect;
|
||||
}
|
||||
|
||||
inline void idle_editor() {
|
||||
if (effect_->flags & effFlagsHasEditor) {
|
||||
dispatch(effEditIdle);
|
||||
}
|
||||
}
|
||||
inline std::vector<uint8_t> get_chunk(int index) {
|
||||
std::vector<uint8_t> chunk;
|
||||
const auto size = dispatch(effGetChunk, index, 0, nullptr);
|
||||
if (size > 0) {
|
||||
chunk.resize(size);
|
||||
dispatch(effGetChunk, index, size, chunk.data());
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
inline void set_chunk(const std::span<uint8_t>& chunk, int index) {
|
||||
if (chunk.empty())
|
||||
return;
|
||||
dispatch(effSetChunk, index, chunk.size(), chunk.data());
|
||||
}
|
||||
11
src/backend/src/vst2_host/src/windows/editor.cpp
Normal file
11
src/backend/src/vst2_host/src/windows/editor.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <windows.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <GLFW/glfw3native.h>
|
||||
|
||||
void* get_glfw_window_handle(GLFWwindow* in_glfw_window) {
|
||||
if (!in_glfw_window) {
|
||||
return nullptr;
|
||||
}
|
||||
// 获取 GLFW 窗口的原生句柄
|
||||
return glfwGetWin32Window(in_glfw_window);
|
||||
}
|
||||
BIN
src/backend/src/vst2_host/test/4Front Piano x64.dll
Normal file
BIN
src/backend/src/vst2_host/test/4Front Piano x64.dll
Normal file
Binary file not shown.
@@ -3,6 +3,7 @@
|
||||
"grpc",
|
||||
"protobuf",
|
||||
"cppzmq",
|
||||
"glfw3",
|
||||
"gtest"
|
||||
],
|
||||
"version": "0.0.1",
|
||||
|
||||
Reference in New Issue
Block a user