obs-vst: Remove submodule in favour of direct merge 2/2

Please visit the submodule repo for blame history:
https://github.com/obsproject/obs-vst

This also replaces the obs-vst .clang-format with obs-studio's.

This commit depends on the previous commit, which removes the submodule
separately as Git complains otherwise.

Co-authored-by: Alex Anderson <anderson.john.alexander@gmail.com>
Co-authored-by: Anton <camotank12345@gmail.com>
Co-authored-by: Blue Cat Audio <support@bluecataudio.com>
Co-authored-by: Cephas Reis <c3r1c3@nevermindonline.com>
Co-authored-by: Colin Edwards <colin@recursivepenguin.com>
Co-authored-by: Florian Zwoch <fzwoch@gmail.com>
Co-authored-by: Fogmoon <i@fogmoon.com>
Co-authored-by: Gol-D-Ace <Gol-D-Ace@users.noreply.github.com>
Co-authored-by: Igor Bochkariov <ujifgc@gmail.com>
Co-authored-by: Jesse Chappell <jesse@sonosaurus.com>
Co-authored-by: Keen <523059842@qq.com>
Co-authored-by: Kurt Kartaltepe <kkartaltepe@gmail.com>
Co-authored-by: Matt Gajownik <matt@obsproject.com>
Co-authored-by: Matt Gajownik <matt@wizardcm.com>
Co-authored-by: Richard Stanway <notr1ch@users.noreply.github.com>
Co-authored-by: Ryan Foster <RytoEX@gmail.com>
Co-authored-by: follower <github@rancidbacon.com>
Co-authored-by: gxalpha <beckmann.sebastian@outlook.de>
Co-authored-by: jp9000 <obs.jim@gmail.com>
Co-authored-by: jpark37 <jpark37@users.noreply.github.com>
Co-authored-by: mntone <sd8@live.jp>
Co-authored-by: tytan652 <tytan652@tytanium.xyz>
Co-authored-by: wangshaohui <97082645@qq.com>
Co-authored-by: wangshaohui <wang.shaohui@navercorp.com>
This commit is contained in:
Matt Gajownik
2022-07-26 22:12:23 -04:00
committed by Ryan Foster
co-authored by Alex Anderson Anton Blue Cat Audio Cephas Reis Colin Edwards Florian Zwoch Fogmoon Gol-D-Ace Igor Bochkariov Jesse Chappell Keen Kurt Kartaltepe Matt Gajownik Richard Stanway Ryan Foster follower gxalpha jp9000 jpark37 mntone tytan652 wangshaohui wangshaohui
parent 34ff76c0e7
commit a7c3d94e4c
66 changed files with 2110 additions and 2 deletions
+3
View File
@@ -24,6 +24,7 @@ if(OS_WINDOWS)
add_subdirectory(obs-qsv11)
add_subdirectory(obs-text)
add_subdirectory(vlc-video)
add_subdirectory(obs-vst)
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/enc-amf/CMakeLists.txt")
add_subdirectory(enc-amf)
@@ -45,6 +46,7 @@ elseif(OS_MACOS)
add_subdirectory(decklink)
add_subdirectory(vlc-video)
add_subdirectory(linux-jack)
add_subdirectory(obs-vst)
check_obs_browser()
elseif(OS_LINUX)
@@ -57,6 +59,7 @@ elseif(OS_LINUX)
add_subdirectory(decklink)
add_subdirectory(vlc-video)
add_subdirectory(sndio)
add_subdirectory(obs-vst)
check_obs_browser()
elseif(OS_FREEBSD)
+88
View File
@@ -0,0 +1,88 @@
project(obs-vst)
option(ENABLE_VST "Enable building OBS with VST plugin" ON)
if(NOT ENABLE_VST)
message(STATUS "OBS: DISABLED obs-vst")
return()
endif()
option(ENABLE_VST_BUNDLED_HEADERS "Build with Bundled Headers" ON)
mark_as_advanced(ENABLE_VST_BUNDLED_HEADERS)
add_library(obs-vst MODULE)
add_library(OBS::vst ALIAS obs-vst)
find_qt(COMPONENTS Widgets)
set_target_properties(
obs-vst
PROPERTIES AUTOMOC ON
AUTOUIC ON
AUTORCC ON)
target_include_directories(
obs-vst PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR})
target_sources(
obs-vst
PRIVATE obs-vst.cpp VSTPlugin.cpp EditorWidget.cpp
headers/vst-plugin-callbacks.hpp headers/EditorWidget.h
headers/VSTPlugin.h)
target_link_libraries(obs-vst PRIVATE OBS::libobs Qt::Widgets)
target_include_directories(
obs-vst PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/headers)
target_compile_features(obs-vst PRIVATE cxx_std_17)
if(ENABLE_VST_BUNDLED_HEADERS)
message(STATUS "OBS: - obs-vst uses bundled VST headers")
target_sources(obs-vst PRIVATE vst_header/aeffectx.h)
target_include_directories(obs-vst
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/vst_header)
else()
set(VST_INCLUDE_DIR
""
CACHE PATH
"Path to Steinburg headers (e.g. C:/VST3 SDK/pluginterfaces/vst2.x)"
FORCE)
mark_as_advanced(VST_INCLUDE_DIR)
message(
WARNING
"OBS: You should only use the Steinburg headers for debugging or local builds. "
"It is illegal to distribute the Steinburg headers with anything, and "
"possibly against the GPL to distribute the binaries from the resultant compile."
)
target_sources(obs-vst PRIVATE ${VST_INCLUDE_DIR}/aeffectx.h)
endif()
if(OS_MACOS)
find_library(FOUNDATION Foundation)
find_library(COCOA Cocoa)
mark_as_advanced(COCOA FOUNDATION)
target_sources(obs-vst PRIVATE mac/VSTPlugin-osx.mm mac/EditorWidget-osx.mm)
target_link_libraries(obs-vst PRIVATE ${COCOA} ${FOUNDATION})
elseif(OS_WINDOWS)
target_sources(obs-vst PRIVATE win/VSTPlugin-win.cpp win/EditorWidget-win.cpp)
target_compile_definitions(obs-vst PRIVATE UNICODE _UNICODE)
elseif(OS_POSIX)
target_sources(obs-vst PRIVATE linux/VSTPlugin-linux.cpp
linux/EditorWidget-linux.cpp)
endif()
set_target_properties(obs-vst PROPERTIES FOLDER "plugins" PREFIX "")
setup_plugin_target(obs-vst)
+32
View File
@@ -0,0 +1,32 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "headers/EditorWidget.h"
#include <QCloseEvent>
EditorWidget::EditorWidget(QWidget *parent, VSTPlugin *plugin)
: QWidget(parent), plugin(plugin)
{
setWindowFlags(this->windowFlags() |= Qt::MSWindowsFixedSizeDialogHint);
}
void EditorWidget::closeEvent(QCloseEvent *event)
{
plugin->onEditorClosed();
UNUSED_PARAMETER(event);
}
+464
View File
@@ -0,0 +1,464 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "headers/VSTPlugin.h"
#include <util/platform.h>
intptr_t VSTPlugin::hostCallback_static(AEffect *effect, int32_t opcode,
int32_t index, intptr_t value,
void *ptr, float opt)
{
UNUSED_PARAMETER(opt);
UNUSED_PARAMETER(ptr);
VSTPlugin *plugin = nullptr;
if (effect && effect->user) {
plugin = static_cast<VSTPlugin *>(effect->user);
}
switch (opcode) {
case audioMasterVersion:
return (intptr_t)2400;
case audioMasterGetCurrentProcessLevel:
return 1;
// We always replace, never accumulate
case audioMasterWillReplaceOrAccumulate:
return 1;
case audioMasterGetSampleRate:
if (plugin) {
return (intptr_t)plugin->GetSampleRate();
}
return 0;
case audioMasterGetTime:
if (plugin) {
return (intptr_t)plugin->GetTimeInfo();
}
return 0;
// index: width, value: height
case audioMasterSizeWindow:
if (plugin && plugin->editorWidget) {
plugin->editorWidget->handleResizeRequest(index, value);
}
return 1;
default:
return 0;
}
}
VstTimeInfo *VSTPlugin::GetTimeInfo()
{
mTimeInfo.nanoSeconds = os_gettime_ns() / 1000000;
return &mTimeInfo;
}
float VSTPlugin::GetSampleRate()
{
return mTimeInfo.sampleRate;
}
VSTPlugin::VSTPlugin(obs_source_t *sourceContext) : sourceContext{sourceContext}
{
}
VSTPlugin::~VSTPlugin()
{
unloadEffect();
cleanupChannelBuffers();
}
void VSTPlugin::createChannelBuffers(size_t count)
{
cleanupChannelBuffers();
int blocksize = BLOCK_SIZE;
numChannels = (std::max)((size_t)0, count);
if (numChannels > 0) {
inputs = (float **)malloc(sizeof(float *) * numChannels);
outputs = (float **)malloc(sizeof(float *) * numChannels);
channelrefs = (float **)malloc(sizeof(float *) * numChannels);
for (size_t channel = 0; channel < numChannels; channel++) {
inputs[channel] =
(float *)malloc(sizeof(float) * blocksize);
outputs[channel] =
(float *)malloc(sizeof(float) * blocksize);
}
}
}
void VSTPlugin::cleanupChannelBuffers()
{
for (size_t channel = 0; channel < numChannels; channel++) {
if (inputs && inputs[channel]) {
free(inputs[channel]);
inputs[channel] = NULL;
}
if (outputs && outputs[channel]) {
free(outputs[channel]);
outputs[channel] = NULL;
}
}
if (inputs) {
free(inputs);
inputs = NULL;
}
if (outputs) {
free(outputs);
outputs = NULL;
}
if (channelrefs) {
free(channelrefs);
channelrefs = NULL;
}
numChannels = 0;
}
void VSTPlugin::loadEffectFromPath(std::string path)
{
if (this->pluginPath.compare(path) != 0) {
unloadEffect();
blog(LOG_INFO, "User selected new VST plugin: '%s'",
path.c_str());
}
if (!effect) {
// TODO: alert user of error if VST is not available.
pluginPath = path;
AEffect *effectTemp = loadEffect();
if (!effectTemp) {
blog(LOG_WARNING, "VST Plug-in: Can't load effect!");
return;
}
{
std::lock_guard<std::recursive_mutex> lock(lockEffect);
effect = effectTemp;
}
// Check plug-in's magic number
// If incorrect, then the file either was not loaded properly,
// is not a real VST plug-in, or is otherwise corrupt.
if (effect->magic != kEffectMagic) {
blog(LOG_WARNING, "VST Plug-in's magic number is bad");
return;
}
int maxchans =
(std::max)(effect->numInputs, effect->numOutputs);
// sanity check
if (maxchans < 0 || maxchans > 256) {
blog(LOG_WARNING,
"VST Plug-in has invalid number of channels");
return;
}
createChannelBuffers(maxchans);
// It is better to invoke this code after checking magic number
effect->dispatcher(effect, effGetEffectName, 0, 0, effectName,
0);
effect->dispatcher(effect, effGetVendorString, 0, 0,
vendorString, 0);
// This check logic is refer to open source project : Audacity
if ((effect->flags & effFlagsIsSynth) ||
!(effect->flags & effFlagsCanReplacing)) {
blog(LOG_WARNING,
"VST Plug-in can't support replacing. '%s'",
path.c_str());
return;
}
// Ask the plugin to identify itself...might be needed for older plugins
effect->dispatcher(effect, effIdentify, 0, 0, nullptr, 0.0f);
effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
// Set some default properties
size_t sampleRate =
audio_output_get_sample_rate(obs_get_audio());
// Initialize time info
memset(&mTimeInfo, 0, sizeof(mTimeInfo));
mTimeInfo.sampleRate = sampleRate;
mTimeInfo.nanoSeconds = os_gettime_ns() / 1000000;
mTimeInfo.tempo = 120.0;
mTimeInfo.timeSigNumerator = 4;
mTimeInfo.timeSigDenominator = 4;
mTimeInfo.flags = kVstTempoValid | kVstNanosValid |
kVstTransportPlaying;
effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr,
sampleRate);
int blocksize = BLOCK_SIZE;
effect->dispatcher(effect, effSetBlockSize, 0, blocksize,
nullptr, 0.0f);
effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0);
effectReady = true;
if (openInterfaceWhenActive) {
openEditor();
}
}
}
static void silenceChannel(float **channelData, size_t numChannels,
long numFrames)
{
for (size_t channel = 0; channel < numChannels; ++channel) {
for (long frame = 0; frame < numFrames; ++frame) {
channelData[channel][frame] = 0.0f;
}
}
}
obs_audio_data *VSTPlugin::process(struct obs_audio_data *audio)
{
// Here we check the status firstly,
// which help avoid waiting for lock while unloadEffect() is running.
bool effectValid = (effect && effectReady && numChannels > 0);
if (!effectValid)
return audio;
std::lock_guard<std::recursive_mutex> lock(lockEffect);
if (effect && effectReady && numChannels > 0) {
uint passes = (audio->frames + BLOCK_SIZE - 1) / BLOCK_SIZE;
uint extra = audio->frames % BLOCK_SIZE;
for (uint pass = 0; pass < passes; pass++) {
uint frames = pass == passes - 1 && extra ? extra
: BLOCK_SIZE;
silenceChannel(outputs, numChannels, BLOCK_SIZE);
for (size_t d = 0; d < numChannels; d++) {
if (d < MAX_AV_PLANES &&
audio->data[d] != nullptr) {
channelrefs[d] =
((float *)audio->data[d]) +
(pass * BLOCK_SIZE);
} else {
channelrefs[d] = inputs[d];
}
};
effect->processReplacing(effect, channelrefs, outputs,
frames);
// only copy back the channels the plugin may have generated
for (size_t c = 0; c < (size_t)effect->numOutputs &&
c < MAX_AV_PLANES;
c++) {
if (audio->data[c]) {
for (size_t i = 0; i < frames; i++) {
channelrefs[c][i] =
outputs[c][i];
}
}
}
}
}
return audio;
}
void VSTPlugin::unloadEffect()
{
closeEditor();
{
std::lock_guard<std::recursive_mutex> lock(lockEffect);
// Reset the status firstly to avoid VSTPlugin::process is blocked
effectReady = false;
if (effect) {
effect->dispatcher(effect, effMainsChanged, 0, 0,
nullptr, 0);
effect->dispatcher(effect, effClose, 0, 0, nullptr,
0.0f);
}
effect = nullptr;
}
unloadLibrary();
pluginPath = "";
}
bool VSTPlugin::isEditorOpen()
{
return editorWidget ? true : false;
}
void VSTPlugin::onEditorClosed()
{
if (!editorWidget)
return;
editorWidget->deleteLater();
editorWidget = nullptr;
if (effect && editorOpened) {
editorOpened = false;
effect->dispatcher(effect, effEditClose, 0, 0, nullptr, 0);
}
}
void VSTPlugin::openEditor()
{
if (effect && !editorWidget) {
// This check logic is refer to open source project : Audacity
if (!(effect->flags & effFlagsHasEditor)) {
blog(LOG_WARNING,
"VST Plug-in: Can't support edit feature. '%s'",
pluginPath.c_str());
return;
}
editorOpened = true;
editorWidget = new EditorWidget(nullptr, this);
editorWidget->buildEffectContainer(effect);
if (sourceName.empty()) {
sourceName = "VST 2.x";
}
if (filterName.empty()) {
editorWidget->setWindowTitle(QString("%1 - %2").arg(
sourceName.c_str(), effectName));
} else {
editorWidget->setWindowTitle(
QString("%1: %2 - %3")
.arg(sourceName.c_str(),
filterName.c_str(), effectName));
}
editorWidget->show();
}
}
void VSTPlugin::closeEditor()
{
if (editorWidget)
editorWidget->close();
}
std::string VSTPlugin::getEffectPath()
{
return pluginPath;
}
std::string VSTPlugin::getChunk()
{
if (!effect) {
return "";
}
if (effect->flags & effFlagsProgramChunks) {
void *buf = nullptr;
intptr_t chunkSize = effect->dispatcher(effect, effGetChunk, 1,
0, &buf, 0.0);
QByteArray data = QByteArray((char *)buf, chunkSize);
return QString(data.toBase64()).toStdString();
} else {
std::vector<float> params;
for (int i = 0; i < effect->numParams; i++) {
float parameter = effect->getParameter(effect, i);
params.push_back(parameter);
}
const char *bytes = reinterpret_cast<const char *>(&params[0]);
QByteArray data =
QByteArray(bytes, (int)(sizeof(float) * params.size()));
std::string encoded = QString(data.toBase64()).toStdString();
return encoded;
}
}
void VSTPlugin::setChunk(std::string data)
{
if (!effect) {
return;
}
if (effect->flags & effFlagsProgramChunks) {
QByteArray base64Data =
QByteArray(data.c_str(), (int)data.length());
QByteArray chunkData = QByteArray::fromBase64(base64Data);
void *buf = nullptr;
buf = chunkData.data();
effect->dispatcher(effect, effSetChunk, 1, chunkData.length(),
buf, 0);
} else {
QByteArray base64Data =
QByteArray(data.c_str(), (int)data.length());
QByteArray paramData = QByteArray::fromBase64(base64Data);
const char *p_chars = paramData.data();
const float *p_floats =
reinterpret_cast<const float *>(p_chars);
const size_t size = paramData.length() / sizeof(float);
std::vector<float> params(p_floats, p_floats + size);
if (params.size() != (size_t)effect->numParams) {
return;
}
for (int i = 0; i < effect->numParams; i++) {
effect->setParameter(effect, i, params[i]);
}
}
}
void VSTPlugin::setProgram(const int programNumber)
{
if (programNumber < effect->numPrograms) {
effect->dispatcher(effect, effSetProgram, 0, programNumber,
NULL, 0.0f);
} else {
blog(LOG_ERROR,
"Failed to load program, number was outside possible program range.");
}
}
int VSTPlugin::getProgram()
{
return effect->dispatcher(effect, effGetProgram, 0, 0, NULL, 0.0f);
}
void VSTPlugin::getSourceNames()
{
/* Only call inside the vst_filter_audio function! */
sourceName = obs_source_get_name(obs_filter_get_parent(sourceContext));
filterName = obs_source_get_name(sourceContext);
}
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Ubrir la interfaz d'a extensión"
ClosePluginInterface="Zarrar la interfaz d'a extension"
VstPlugin="Extensión VST 2.x"
OpenInterfaceWhenActive="Ubrir la interfaz quan siga activo"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="فتح واجهة الإضافة"
ClosePluginInterface="إغلاق واجهة الإضافة"
VstPlugin="إضافة VST 2.x"
OpenInterfaceWhenActive="فتح الواجهة عند النشاط"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Отваряне на интерфейса на приставката"
ClosePluginInterface="Затваряне на интерфейса на приставката"
VstPlugin="Приставка VST 2.x"
OpenInterfaceWhenActive="Отваряне на интерфейса при задействане"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="প্লাগ-ইন ইন্টারফেসের খুলুন"
ClosePluginInterface="প্লাগ-ইন ইন্টারফেস বন্ধ করুন"
VstPlugin="ভিএসটি ২.x প্লাগ-ইন"
OpenInterfaceWhenActive="সক্রিয় থাকাকালীন ইন্টারফেস খুলুন"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Obre l'interfície de l'extensió"
ClosePluginInterface="Tanca la interfície de l'extensió"
VstPlugin="Extensió VST 2.x"
OpenInterfaceWhenActive="Obre l'interfície quan està actiu"
+3
View File
@@ -0,0 +1,3 @@
OpenPluginInterface="Otevřít rozhraní Plug-inu"
ClosePluginInterface="Zavřít rozhraní Plug-inu"
OpenInterfaceWhenActive="Otevřít rozhraní, pokud je aktivní"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Åbn plug-in grænseflade"
ClosePluginInterface="Luk plug-in grænseflade"
VstPlugin="VST 2.x plug-in"
OpenInterfaceWhenActive="Åbn grænseflade, når aktiv"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Pluginschnittstelle öffnen"
ClosePluginInterface="Pluginschnittstelle schließen"
VstPlugin="VST-2.x-Plugin"
OpenInterfaceWhenActive="Schnittstelle öffnen, wenn aktiv"
+3
View File
@@ -0,0 +1,3 @@
OpenPluginInterface="Άνοιγμα διεπαφής Plug-in"
ClosePluginInterface="Κλείσιμο διεπαφής Plug-in"
OpenInterfaceWhenActive="Άνοιγμα διεπαφής όταν είναι ενεργό"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Open Plug-in Interface"
ClosePluginInterface="Close Plug-in Interface"
VstPlugin="VST 2.x Plug-in"
OpenInterfaceWhenActive="Open interface when active"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Abrir la interfaz de la extensión"
ClosePluginInterface="Cerrar la interfaz de la extensión"
VstPlugin="Extensión VST 2.x"
OpenInterfaceWhenActive="Abrir interfaz cuando está activo"
+3
View File
@@ -0,0 +1,3 @@
OpenPluginInterface="Avatud Plug-in liides"
ClosePluginInterface="Sulgege Plug-in liides"
OpenInterfaceWhenActive="Ava liides kui aktiivne"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Ireki pluginaren interfazea"
ClosePluginInterface="Itxi pluginaren interfazea"
VstPlugin="VST 2.x Plugina"
OpenInterfaceWhenActive="Ireki interfazea aktibatzen denean"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="بازکردن رابط افزونه"
ClosePluginInterface="بستن رابط افزونه"
VstPlugin="VST 2.x افزونه"
OpenInterfaceWhenActive="رابط کاربری باز زمانی که فعال"
+3
View File
@@ -0,0 +1,3 @@
OpenPluginInterface="Avaa liitännäisen käyttöliittymä"
ClosePluginInterface="Sulje liitännäisen käyttöliittymä"
OpenInterfaceWhenActive="Avaa käyttöliittymä kun aktiivinen"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Buksan ang interface at isaksak"
ClosePluginInterface="Isarado ang interface at isaksak"
VstPlugin="VST 2. x Isaksak"
OpenInterfaceWhenActive="Buksan ang interface kapag aktibo"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Afficher l'interface graphique du plug-in"
ClosePluginInterface="Fermer l'interface graphique du plug-in"
VstPlugin="Plug-in VST 2.x"
OpenInterfaceWhenActive="Ouvrir l'interface graphique du plug-in quand il est actif"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Fosgail eadar-aghaidh a’ phlugain"
ClosePluginInterface="Dùin eadar-aghaidh a’ phlugain"
VstPlugin="Plugan VST 2.x"
OpenInterfaceWhenActive="Fosgail an eadar-aghaidh nuair a bhios e gnìomhach"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Abrir a interface do engadido"
ClosePluginInterface="Pechar a interface do engadido"
VstPlugin="Engadido VST 2.x"
OpenInterfaceWhenActive="Abrir a interface cando estea activo"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="פתיחת ממשק התוספים"
ClosePluginInterface="סגירת ממשק התוספים"
VstPlugin="תוסף VST 2.x"
OpenInterfaceWhenActive="פתח ממשק כאשר פעיל"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="प्लग-इन इंटरफ़ेस खोलें"
ClosePluginInterface="प्लग-इन इंटरफ़ेस बंद करें"
VstPlugin="VST 2.x प्लग-इन"
OpenInterfaceWhenActive="सक्रिय होने पर इंटरफ़ेस खोलें"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Bővítmény interfész megnyitása"
ClosePluginInterface="Bővítmény interfész bezárása"
VstPlugin="VST 2.x Bővítmény"
OpenInterfaceWhenActive="Interfész megnyitása, amikor aktív"
+3
View File
@@ -0,0 +1,3 @@
OpenPluginInterface="Buka Antarmuka Plug-in"
ClosePluginInterface="Tutup Antarmuka Plug-in"
OpenInterfaceWhenActive="Buka antarmuka ketika aktif"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Apri l'interfaccia del plugin"
ClosePluginInterface="Chiudi l'interfaccia del plugin"
VstPlugin="Plugin VST 2.x"
OpenInterfaceWhenActive="Apri l'interfaccia quando attivo"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="プラグインインターフェイスを開く"
ClosePluginInterface="プラグインインターフェイスを閉じる"
VstPlugin="VST 2.x プラグイン"
OpenInterfaceWhenActive="アクティブな時にインターフェイスを開く"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="მოდულის სამართავის გახსნა"
ClosePluginInterface="მოდულის სამართავის დახურვა"
VstPlugin="VST 2.x მოდული"
OpenInterfaceWhenActive="სამართავის გახსნა ამოქმედებისას"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Ldi agrudem n usiɣzef"
ClosePluginInterface="Mdel agrudem n usiɣzef"
VstPlugin="Asiɣzef VST 2.x"
OpenInterfaceWhenActive="Ldi agrudemp ticki yermed"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Navrûya pêvekê veke"
ClosePluginInterface="Navrûya pêvekê bigire"
VstPlugin="Pêveka VST 2.x"
OpenInterfaceWhenActive="Dema çalak be navrûyê veke"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="플러그인 설정 열기"
ClosePluginInterface="플러그인 설정 닫기"
VstPlugin="VST 2.x 플러그인"
OpenInterfaceWhenActive="활성화 시 인터페이스 열기"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Buka Antara Muka Pemalam"
ClosePluginInterface="Tutup Antara Muka Pemalam"
VstPlugin="Pemalam VST 2.x"
OpenInterfaceWhenActive="Buka antara muka bila aktif"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Åpne utvidelsesgrensesnittet"
ClosePluginInterface="Lukk utvidelsesgrensesnittet"
VstPlugin="VST 2.x-utvidelse"
OpenInterfaceWhenActive="Åpne grensesnittet når den er aktiv"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Open Plugin Interface"
ClosePluginInterface="Sluit Plugin Interface"
VstPlugin="VST 2.x Plugin"
OpenInterfaceWhenActive="Open interface indien actief"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Otwórz panel wtyczki"
ClosePluginInterface="Zamknij panel wtyczki"
VstPlugin="Wtyczka VST 2.x"
OpenInterfaceWhenActive="Otwórz panel, gdy wtyczka aktywna"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Abrir Interface do Plugin"
ClosePluginInterface="Fechar Interface do Plugin"
VstPlugin="Plugin VST 2.x"
OpenInterfaceWhenActive="Abrir interface quando ativo"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Abrir interface da extensão"
ClosePluginInterface="Fechar interface da extensão"
VstPlugin="Extensão VST 2.x"
OpenInterfaceWhenActive="Abrir interface quando ativo"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Deschide interfața pluginului"
ClosePluginInterface="Închide interfața pluginului"
VstPlugin="Plug-in VST 2.x"
OpenInterfaceWhenActive="Deschide interfața pluginului când este activ"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Открыть интерфейс плагина"
ClosePluginInterface="Закрыть интерфейс плагина"
VstPlugin="Плагин VST 2.x"
OpenInterfaceWhenActive="Открыть интерфейс при активации"
+3
View File
@@ -0,0 +1,3 @@
OpenPluginInterface="Otvoriť rozhranie Plug-inu"
ClosePluginInterface="Zavrieť rozhranie Plug-inu"
OpenInterfaceWhenActive="Otvoriť rozhranie, keď je aktívny"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Odpri vmesnik vtičnikov"
ClosePluginInterface="Zapri vmesnik vtičnikov"
VstPlugin="Vtičnik VST 2.x"
OpenInterfaceWhenActive="Odpri vmesnik, ko je dejaven"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Prikaži interfejs za priključak"
ClosePluginInterface="Zatvori interfejs za priključak"
VstPlugin="VST 2.x priključak"
OpenInterfaceWhenActive="Prikaži interfejs kada je priključak aktivan"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Прикажи интерфејс за прикључак"
ClosePluginInterface="Затвори интерфејс за прикључак"
VstPlugin="VST 2.x прикључак"
OpenInterfaceWhenActive="Прикажи интерфејс када је прикључак активан"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Öppna tilläggets gränssnitt"
ClosePluginInterface="Stäng tilläggets gränssnitt"
VstPlugin="VST 2.x-tillägg"
OpenInterfaceWhenActive="Öppna gränssnitt vid aktiv"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Ôtwōrz panel pluginu"
ClosePluginInterface="Zawrzij panel pluginu"
VstPlugin="Plugin VST 2.x"
OpenInterfaceWhenActive="Ôtwōrz panel, kej plugin je aktywny"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="I-open ang Plug-in na Interface"
ClosePluginInterface="I-close ang Plug-in na Interface"
VstPlugin="VST 2.x na Plug-in"
OpenInterfaceWhenActive="I-open ang interface kung itoy aktibo"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Eklenti Arabirimi Aç"
ClosePluginInterface="Eklenti Arabirimi Kapa"
VstPlugin="VST 2.x Eklentisi"
OpenInterfaceWhenActive="Etkinken Arabirimi Aç"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Відкрити інтерфейс плагіна"
ClosePluginInterface="Закрити інтерфейс плагіна"
VstPlugin="Плагін VST 2.x"
OpenInterfaceWhenActive="Щоразу відкривати інтерфейс плагіна"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="Mở giao diện bổ trợ"
ClosePluginInterface="Đóng giao diện bổ trợ"
VstPlugin="Bổ trợ VST 2.x"
OpenInterfaceWhenActive="Mở giao diện khi hoạt động"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="打开插件界面"
ClosePluginInterface="关闭插件界面"
VstPlugin="VST 2.x 插件"
OpenInterfaceWhenActive="活跃时打开界面"
+4
View File
@@ -0,0 +1,4 @@
OpenPluginInterface="開啟外掛程式界面"
ClosePluginInterface="關閉外掛程式介面"
VstPlugin="VST 2.x 外掛程式"
OpenInterfaceWhenActive="啟動時開啟界面"
+63
View File
@@ -0,0 +1,63 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#ifndef OBS_STUDIO_EDITORDIALOG_H
#define OBS_STUDIO_EDITORDIALOG_H
#include <QWidget>
#if defined(_WIN32)
#include <QWindow>
#include <Windows.h>
#elif defined(__linux__)
#include <QWindow>
#include <xcb/xcb.h>
#endif
#include "aeffectx.h"
#include "VSTPlugin.h"
class VSTPlugin;
class VstRect {
public:
short top;
short left;
short bottom;
short right;
};
class EditorWidget : public QWidget {
VSTPlugin *plugin;
#if defined(__APPLE__)
QWidget *cocoaViewContainer = NULL;
#elif defined(_WIN32)
HWND windowHandle = NULL;
#endif
public:
EditorWidget(QWidget *parent, VSTPlugin *plugin);
void buildEffectContainer(AEffect *effect);
void closeEvent(QCloseEvent *event) override;
void handleResizeRequest(int width, int height);
};
#endif // OBS_STUDIO_EDITORDIALOG_H
+110
View File
@@ -0,0 +1,110 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#ifndef OBS_STUDIO_VSTPLUGIN_H
#define OBS_STUDIO_VSTPLUGIN_H
#define BLOCK_SIZE 512
#include <mutex>
#include <atomic>
#include <string>
#include <QDirIterator>
#include <obs-module.h>
#include "aeffectx.h"
#include "vst-plugin-callbacks.hpp"
#include "EditorWidget.h"
#ifdef __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#endif
class EditorWidget;
class VSTPlugin : public QObject {
Q_OBJECT
/* Because effect is always changed in UI thread, so lockEffect is only necessary for these situations:
1. access effect object outside of UI thread;
2. close/delete effect object any where. */
std::recursive_mutex lockEffect;
AEffect *effect = nullptr;
obs_source_t *sourceContext;
std::string pluginPath;
float **inputs = nullptr;
float **outputs = nullptr;
float **channelrefs = nullptr;
size_t numChannels = 0;
void createChannelBuffers(size_t count);
void cleanupChannelBuffers();
EditorWidget *editorWidget = nullptr;
bool editorOpened = false;
AEffect *loadEffect();
std::atomic_bool effectReady = false;
std::string sourceName;
std::string filterName;
char effectName[64];
// Remove below... or comment out
char vendorString[64];
VstTimeInfo mTimeInfo;
#ifdef __APPLE__
CFBundleRef bundle = NULL;
#elif WIN32
HINSTANCE dllHandle = nullptr;
#elif __linux__
void *soHandle = nullptr;
#endif
void unloadLibrary();
static intptr_t hostCallback_static(AEffect *effect, int32_t opcode,
int32_t index, intptr_t value,
void *ptr, float opt);
VstTimeInfo *GetTimeInfo();
float GetSampleRate();
public:
VSTPlugin(obs_source_t *sourceContext);
~VSTPlugin();
void loadEffectFromPath(std::string path);
void unloadEffect();
std::string getEffectPath();
std::string getChunk();
void setChunk(std::string data);
void setProgram(const int programNumber);
int getProgram();
void getSourceNames();
obs_audio_data *process(struct obs_audio_data *audio);
bool openInterfaceWhenActive = false;
bool isEditorOpen();
void onEditorClosed();
public slots:
void openEditor();
void closeEditor();
};
#endif // OBS_STUDIO_VSTPLUGIN_H
@@ -0,0 +1,21 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#pragma once
#include "aeffectx.h"
typedef AEffect *(*vstPluginMain)(audioMasterCallback audioMaster);
@@ -0,0 +1,37 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "../headers/EditorWidget.h"
void EditorWidget::buildEffectContainer(AEffect *effect)
{
WId id = winId();
effect->dispatcher(effect, effEditOpen, 0, 0, (void *)id, 0);
VstRect *vstRect = nullptr;
effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0);
if (vstRect) {
setFixedSize(vstRect->right - vstRect->left,
vstRect->bottom - vstRect->top);
}
}
void EditorWidget::handleResizeRequest(int width, int height)
{
setFixedSize(width, height);
}
+65
View File
@@ -0,0 +1,65 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "../headers/VSTPlugin.h"
#include <util/platform.h>
AEffect *VSTPlugin::loadEffect()
{
AEffect *plugin = nullptr;
soHandle = os_dlopen(pluginPath.c_str());
if (soHandle == nullptr) {
blog(LOG_WARNING,
"Failed trying to load VST from '%s',"
"error %d\n",
pluginPath.c_str(), errno);
return nullptr;
}
vstPluginMain mainEntryPoint;
mainEntryPoint = (vstPluginMain)os_dlsym(soHandle, "VSTPluginMain");
if (mainEntryPoint == nullptr) {
mainEntryPoint =
(vstPluginMain)os_dlsym(soHandle, "VstPluginMain()");
}
if (mainEntryPoint == nullptr) {
mainEntryPoint = (vstPluginMain)os_dlsym(soHandle, "main");
}
if (mainEntryPoint == nullptr) {
blog(LOG_WARNING, "Couldn't get a pointer to plug-in's main()");
return nullptr;
}
// Instantiate the plug-in
plugin = mainEntryPoint(hostCallback_static);
plugin->user = this;
return plugin;
}
void VSTPlugin::unloadLibrary()
{
if (soHandle) {
os_dlclose(soHandle);
soHandle = nullptr;
}
}
+62
View File
@@ -0,0 +1,62 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#import "../headers/EditorWidget.h"
#import <Cocoa/Cocoa.h>
#include <QLayout>
#include <QWindow>
#import "../headers/VSTPlugin.h"
void EditorWidget::buildEffectContainer(AEffect *effect)
{
NSView *view =
[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300)];
cocoaViewContainer =
QWidget::createWindowContainer(QWindow::fromWinId(WId(view)));
cocoaViewContainer->move(0, 0);
cocoaViewContainer->resize(300, 300);
cocoaViewContainer->show();
QGridLayout *hblParams = new QGridLayout();
hblParams->setContentsMargins(0, 0, 0, 0);
hblParams->setSpacing(0);
hblParams->addWidget(cocoaViewContainer);
VstRect *vstRect = nullptr;
effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0);
if (vstRect) {
NSRect frame = NSMakeRect(vstRect->left, vstRect->top,
vstRect->right, vstRect->bottom);
[view setFrame:frame];
cocoaViewContainer->resize(vstRect->right - vstRect->left,
vstRect->bottom - vstRect->top);
setFixedSize(vstRect->right - vstRect->left,
vstRect->bottom - vstRect->top);
}
effect->dispatcher(effect, effEditOpen, 0, 0, view, 0);
setLayout(hblParams);
}
void EditorWidget::handleResizeRequest(int width, int height)
{
setFixedSize(width, height);
}
+89
View File
@@ -0,0 +1,89 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "../headers/VSTPlugin.h"
AEffect *VSTPlugin::loadEffect()
{
AEffect *newEffect = NULL;
// Create a path to the bundle
CFStringRef pluginPathStringRef = CFStringCreateWithCString(
NULL, pluginPath.c_str(), kCFStringEncodingUTF8);
CFURLRef bundleUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
pluginPathStringRef,
kCFURLPOSIXPathStyle,
true);
if (bundleUrl == NULL) {
blog(LOG_WARNING,
"Couldn't make URL reference for VST plug-in");
return NULL;
}
// Open the bundle
bundle = CFBundleCreate(kCFAllocatorDefault, bundleUrl);
if (bundle == NULL) {
blog(LOG_WARNING, "Couldn't create VST bundle reference.");
CFRelease(pluginPathStringRef);
CFRelease(bundleUrl);
return NULL;
}
vstPluginMain mainEntryPoint = NULL;
mainEntryPoint = (vstPluginMain)CFBundleGetFunctionPointerForName(
bundle, CFSTR("VSTPluginMain"));
// VST plugins previous to the 2.4 SDK used main_macho for the
// entry point name.
if (mainEntryPoint == NULL) {
mainEntryPoint =
(vstPluginMain)CFBundleGetFunctionPointerForName(
bundle, CFSTR("main_macho"));
}
if (mainEntryPoint == NULL) {
blog(LOG_WARNING, "Couldn't get a pointer to plug-in's main()");
CFBundleUnloadExecutable(bundle);
CFRelease(bundle);
return NULL;
}
newEffect = mainEntryPoint(hostCallback_static);
if (newEffect == NULL) {
blog(LOG_WARNING, "VST Plug-in's main() returns null.");
CFBundleUnloadExecutable(bundle);
CFRelease(bundle);
return NULL;
}
newEffect->user = this;
// Clean up
CFRelease(pluginPathStringRef);
CFRelease(bundleUrl);
return newEffect;
}
void VSTPlugin::unloadLibrary()
{
if (bundle) {
CFBundleUnloadExecutable(bundle);
CFRelease(bundle);
}
}
+332
View File
@@ -0,0 +1,332 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "headers/VSTPlugin.h"
#include <QCryptographicHash>
#define OPEN_VST_SETTINGS "open_vst_settings"
#define CLOSE_VST_SETTINGS "close_vst_settings"
#define OPEN_WHEN_ACTIVE_VST_SETTINGS "open_when_active_vst_settings"
#define PLUG_IN_NAME obs_module_text("VstPlugin")
#define OPEN_VST_TEXT obs_module_text("OpenPluginInterface")
#define CLOSE_VST_TEXT obs_module_text("ClosePluginInterface")
#define OPEN_WHEN_ACTIVE_VST_TEXT obs_module_text("OpenInterfaceWhenActive")
OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("obs-vst", "en-US")
MODULE_EXPORT const char *obs_module_description(void)
{
return "VST 2.x Plug-in filter";
}
static bool open_editor_button_clicked(obs_properties_t *props,
obs_property_t *property, void *data)
{
VSTPlugin *vstPlugin = (VSTPlugin *)data;
QMetaObject::invokeMethod(vstPlugin, "openEditor");
obs_property_set_visible(obs_properties_get(props, OPEN_VST_SETTINGS),
false);
obs_property_set_visible(obs_properties_get(props, CLOSE_VST_SETTINGS),
true);
UNUSED_PARAMETER(props);
UNUSED_PARAMETER(property);
UNUSED_PARAMETER(data);
return true;
}
static bool close_editor_button_clicked(obs_properties_t *props,
obs_property_t *property, void *data)
{
VSTPlugin *vstPlugin = (VSTPlugin *)data;
QMetaObject::invokeMethod(vstPlugin, "closeEditor");
obs_property_set_visible(obs_properties_get(props, OPEN_VST_SETTINGS),
true);
obs_property_set_visible(obs_properties_get(props, CLOSE_VST_SETTINGS),
false);
UNUSED_PARAMETER(property);
return true;
}
std::string getFileMD5(const char *file)
{
QFile f(file);
if (f.open(QFile::ReadOnly)) {
QCryptographicHash hash(QCryptographicHash::Md5);
if (hash.addData(&f))
return std::string(hash.result().toHex());
}
return std::string();
}
static const char *vst_name(void *unused)
{
UNUSED_PARAMETER(unused);
return PLUG_IN_NAME;
}
static void vst_destroy(void *data)
{
VSTPlugin *vstPlugin = (VSTPlugin *)data;
QMetaObject::invokeMethod(vstPlugin, "closeEditor");
vstPlugin->deleteLater();
}
static void vst_update(void *data, obs_data_t *settings)
{
VSTPlugin *vstPlugin = (VSTPlugin *)data;
vstPlugin->openInterfaceWhenActive =
obs_data_get_bool(settings, OPEN_WHEN_ACTIVE_VST_SETTINGS);
const char *path = obs_data_get_string(settings, "plugin_path");
if (strcmp(path, "") == 0) {
vstPlugin->unloadEffect();
return;
}
vstPlugin->loadEffectFromPath(std::string(path));
std::string hash = getFileMD5(path);
const char *chunkHash = obs_data_get_string(settings, "chunk_hash");
const char *chunkData = obs_data_get_string(settings, "chunk_data");
bool chunkHashesMatch = chunkHash && strlen(chunkHash) > 0 &&
hash.compare(chunkHash) == 0;
if (chunkData && strlen(chunkData) > 0 &&
(chunkHashesMatch || !chunkHash || strlen(chunkHash) == 0)) {
vstPlugin->setChunk(std::string(chunkData));
}
}
static void *vst_create(obs_data_t *settings, obs_source_t *filter)
{
VSTPlugin *vstPlugin = new VSTPlugin(filter);
vst_update(vstPlugin, settings);
return vstPlugin;
}
static void vst_save(void *data, obs_data_t *settings)
{
VSTPlugin *vstPlugin = (VSTPlugin *)data;
obs_data_set_string(settings, "chunk_data",
vstPlugin->getChunk().c_str());
obs_data_set_string(
settings, "chunk_hash",
getFileMD5(vstPlugin->getEffectPath().c_str()).c_str());
}
static struct obs_audio_data *vst_filter_audio(void *data,
struct obs_audio_data *audio)
{
VSTPlugin *vstPlugin = (VSTPlugin *)data;
vstPlugin->process(audio);
/*
* OBS can only guarantee getting the filter source's parent and own name
* in this call, so we grab it and return the results for processing
* by the EditorWidget.
*/
vstPlugin->getSourceNames();
return audio;
}
static void fill_out_plugins(obs_property_t *list)
{
QStringList dir_list;
#ifdef __APPLE__
dir_list << "/Library/Audio/Plug-Ins/VST/"
<< "~/Library/Audio/Plug-ins/VST/";
#elif WIN32
#ifndef _WIN64
HANDLE hProcess = GetCurrentProcess();
BOOL isWow64;
IsWow64Process(hProcess, &isWow64);
if (!isWow64) {
#endif
dir_list << qEnvironmentVariable("ProgramFiles") +
"/Steinberg/VstPlugins/"
<< qEnvironmentVariable("CommonProgramFiles") +
"/Steinberg/Shared Components/"
<< qEnvironmentVariable("CommonProgramFiles") + "/VST2"
<< qEnvironmentVariable("CommonProgramFiles") +
"/Steinberg/VST2"
<< qEnvironmentVariable("CommonProgramFiles") +
"/VSTPlugins/"
<< qEnvironmentVariable("ProgramFiles") +
"/VSTPlugins/";
#ifndef _WIN64
} else {
dir_list << qEnvironmentVariable("ProgramFiles(x86)") +
"/Steinberg/VstPlugins/"
<< qEnvironmentVariable("CommonProgramFiles(x86)") +
"/Steinberg/Shared Components/"
<< qEnvironmentVariable("CommonProgramFiles(x86)") +
"/VST2"
<< qEnvironmentVariable("CommonProgramFiles(x86)") +
"/VSTPlugins/"
<< qEnvironmentVariable("ProgramFiles(x86)") +
"/VSTPlugins/";
}
#endif
#elif __linux__
// If the user has set the VST_PATH environmental
// variable, then use it. Else default to a list
// of common locations.
QString vstPathEnv(getenv("VST_PATH"));
if (!vstPathEnv.isNull()) {
dir_list.append(vstPathEnv.split(":"));
} else {
QString home(getenv("HOME"));
// Choose the most common locations
// clang-format off
dir_list << "/usr/lib/vst/"
<< "/usr/lib/lxvst/"
<< "/usr/lib/linux_vst/"
<< "/usr/lib64/vst/"
<< "/usr/lib64/lxvst/"
<< "/usr/lib64/linux_vst/"
<< "/usr/local/lib/vst/"
<< "/usr/local/lib/lxvst/"
<< "/usr/local/lib/linux_vst/"
<< "/usr/local/lib64/vst/"
<< "/usr/local/lib64/lxvst/"
<< "/usr/local/lib64/linux_vst/"
<< home + "/.vst/"
<< home + "/.lxvst/";
// clang-format on
}
#endif
QStringList filters;
#ifdef __APPLE__
filters << "*.vst";
#elif WIN32
filters << "*.dll";
#elif __linux__
filters << "*.so"
<< "*.o";
#endif
QStringList vst_list;
// Read all plugins into a list...
for (int a = 0; a < dir_list.size(); ++a) {
QDir search_dir(dir_list[a]);
search_dir.setNameFilters(filters);
QDirIterator it(search_dir, QDirIterator::Subdirectories);
while (it.hasNext()) {
QString path = it.next();
QString name = it.fileName();
#ifdef __APPLE__
name.remove(".vst", Qt::CaseInsensitive);
#elif WIN32
name.remove(".dll", Qt::CaseInsensitive);
#elif __linux__
name.remove(".so", Qt::CaseInsensitive);
name.remove(".o", Qt::CaseInsensitive);
#endif
name.append("=").append(path);
vst_list << name;
}
}
// Now sort list alphabetically (still case-sensitive though).
std::stable_sort(vst_list.begin(), vst_list.end(),
std::less<QString>());
// Now add said list to the plug-in list of OBS
obs_property_list_add_string(list, "{Please select a plug-in}",
nullptr);
for (int b = 0; b < vst_list.size(); ++b) {
QString vst_sorted = vst_list[b];
obs_property_list_add_string(
list,
vst_sorted.left(vst_sorted.indexOf('='))
.toStdString()
.c_str(),
vst_sorted.mid(vst_sorted.indexOf('=') + 1)
.toStdString()
.c_str());
}
}
static obs_properties_t *vst_properties(void *data)
{
VSTPlugin *vstPlugin = (VSTPlugin *)data;
obs_properties_t *props = obs_properties_create();
obs_property_t *list = obs_properties_add_list(props, "plugin_path",
PLUG_IN_NAME,
OBS_COMBO_TYPE_LIST,
OBS_COMBO_FORMAT_STRING);
fill_out_plugins(list);
obs_properties_add_button(props, OPEN_VST_SETTINGS, OPEN_VST_TEXT,
open_editor_button_clicked);
obs_properties_add_button(props, CLOSE_VST_SETTINGS, CLOSE_VST_TEXT,
close_editor_button_clicked);
if (vstPlugin->isEditorOpen()) {
obs_property_set_visible(
obs_properties_get(props, OPEN_VST_SETTINGS), false);
} else {
obs_property_set_visible(
obs_properties_get(props, CLOSE_VST_SETTINGS), false);
}
obs_properties_add_bool(props, OPEN_WHEN_ACTIVE_VST_SETTINGS,
OPEN_WHEN_ACTIVE_VST_TEXT);
return props;
}
bool obs_module_load(void)
{
struct obs_source_info vst_filter = {};
vst_filter.id = "vst_filter";
vst_filter.type = OBS_SOURCE_TYPE_FILTER;
vst_filter.output_flags = OBS_SOURCE_AUDIO;
vst_filter.get_name = vst_name;
vst_filter.create = vst_create;
vst_filter.destroy = vst_destroy;
vst_filter.update = vst_update;
vst_filter.filter_audio = vst_filter_audio;
vst_filter.get_properties = vst_properties;
vst_filter.save = vst_save;
obs_register_source(&vst_filter);
return true;
}
+3
View File
@@ -0,0 +1,3 @@
Language: Cpp
SortIncludes: false
DisableFormat: true
+382
View File
@@ -0,0 +1,382 @@
/*
* aeffectx.h - simple header to allow VeSTige compilation and eventually work
*
* Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#include <stdint.h>
#ifndef _AEFFECTX_H
#define _AEFFECTX_H
#define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \
( ( (int) b ) << 16 ) | \
( ( (int) c ) << 8 ) | \
( ( (int) d ) << 0 ) )
const int audioMasterAutomate = 0;
const int audioMasterVersion = 1;
const int audioMasterCurrentId = 2;
const int audioMasterIdle = 3;
const int audioMasterPinConnected = 4;
// unsupported? 5
const int audioMasterWantMidi = 6;
const int audioMasterGetTime = 7;
const int audioMasterProcessEvents = 8;
const int audioMasterSetTime = 9;
const int audioMasterTempoAt = 10;
const int audioMasterGetNumAutomatableParameters = 11;
const int audioMasterGetParameterQuantization = 12;
const int audioMasterIOChanged = 13;
const int audioMasterNeedIdle = 14;
const int audioMasterSizeWindow = 15;
const int audioMasterGetSampleRate = 16;
const int audioMasterGetBlockSize = 17;
const int audioMasterGetInputLatency = 18;
const int audioMasterGetOutputLatency = 19;
const int audioMasterGetPreviousPlug = 20;
const int audioMasterGetNextPlug = 21;
const int audioMasterWillReplaceOrAccumulate = 22;
const int audioMasterGetCurrentProcessLevel = 23;
const int audioMasterGetAutomationState = 24;
const int audioMasterOfflineStart = 25;
const int audioMasterOfflineRead = 26;
const int audioMasterOfflineWrite = 27;
const int audioMasterOfflineGetCurrentPass = 28;
const int audioMasterOfflineGetCurrentMetaPass = 29;
const int audioMasterSetOutputSampleRate = 30;
// unsupported? 31
const int audioMasterGetSpeakerArrangement = 31; // deprecated in 2.4?
const int audioMasterGetVendorString = 32;
const int audioMasterGetProductString = 33;
const int audioMasterGetVendorVersion = 34;
const int audioMasterVendorSpecific = 35;
const int audioMasterSetIcon = 36;
const int audioMasterCanDo = 37;
const int audioMasterGetLanguage = 38;
const int audioMasterOpenWindow = 39;
const int audioMasterCloseWindow = 40;
const int audioMasterGetDirectory = 41;
const int audioMasterUpdateDisplay = 42;
const int audioMasterBeginEdit = 43;
const int audioMasterEndEdit = 44;
const int audioMasterOpenFileSelector = 45;
const int audioMasterCloseFileSelector = 46; // currently unused
const int audioMasterEditFile = 47; // currently unused
const int audioMasterGetChunkFile = 48; // currently unused
const int audioMasterGetInputSpeakerArrangement = 49; // currently unused
const int effFlagsHasEditor = 1;
const int effFlagsCanReplacing = 1 << 4; // very likely
const int effFlagsProgramChunks = 1 << 5; // from Ardour
const int effFlagsIsSynth = 1 << 8; // currently unused
const int effOpen = 0;
const int effClose = 1; // currently unused
const int effSetProgram = 2; // currently unused
const int effGetProgram = 3; // currently unused
// The next one was gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
const int effSetProgramName = 4;
const int effGetProgramName = 5; // currently unused
// The next two were gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
const int effGetParamLabel = 6;
const int effGetParamDisplay = 7;
const int effGetParamName = 8; // currently unused
const int effSetSampleRate = 10;
const int effSetBlockSize = 11;
const int effMainsChanged = 12;
const int effEditGetRect = 13;
const int effEditOpen = 14;
const int effEditClose = 15;
const int effEditIdle = 19;
const int effEditTop = 20;
const int effIdentify = 22; // from http://www.asseca.org/vst-24-specs/efIdentify.html
const int effGetChunk = 23; // from Ardour
const int effSetChunk = 24; // from Ardour
const int effProcessEvents = 25;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efCanBeAutomated.html
const int effCanBeAutomated = 26;
// The next one was gleaned from http://www.kvraudio.com/forum/viewtopic.php?p=1905347
const int effGetProgramNameIndexed = 29;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efGetPlugCategory.html
const int effGetPlugCategory = 35;
const int effGetEffectName = 45;
const int effGetParameterProperties = 56; // missing
const int effGetVendorString = 47;
const int effGetProductString = 48;
const int effGetVendorVersion = 49;
const int effCanDo = 51; // currently unused
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efIdle.html
const int effIdle = 53;
const int effGetVstVersion = 58; // currently unused
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginSetProgram.html
const int effBeginSetProgram = 67;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efEndSetProgram.html
const int effEndSetProgram = 68;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efShellGetNextPlugin.html
const int effShellGetNextPlugin = 70;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginLoadBank.html
const int effBeginLoadBank = 75;
// The next one was gleaned from http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html
const int effBeginLoadProgram = 76;
// The next two were gleaned from http://www.kvraudio.com/forum/printview.php?t=143587&start=0
const int effStartProcess = 71;
const int effStopProcess = 72;
const int kEffectMagic = CCONST( 'V', 's', 't', 'P' );
const int kVstLangEnglish = 1;
const int kVstMidiType = 1;
const int kVstNanosValid = 1 << 8;
const int kVstPpqPosValid = 1 << 9;
const int kVstTempoValid = 1 << 10;
const int kVstBarsValid = 1 << 11;
const int kVstCyclePosValid = 1 << 12;
const int kVstTimeSigValid = 1 << 13;
// from Ardour
const int kVstSmpteValid = 1 << 14;
// from Ardour
const int kVstClockValid = 1 << 15;
const int kVstTransportPlaying = 1 << 1;
const int kVstTransportCycleActive = 1 << 2;
const int kVstTransportChanged = 1;
class RemoteVstPlugin;
class VstMidiEvent
{
public:
// 00
int type;
// 04
int byteSize;
// 08
int deltaFrames;
// 0c?
int flags;
// 10?
int noteLength;
// 14?
int noteOffset;
// 18
char midiData[4];
// 1c?
char detune;
// 1d?
char noteOffVelocity;
// 1e?
char reserved1;
// 1f?
char reserved2;
};
class VstEvent
{
char dump[sizeof( VstMidiEvent )];
};
class VstEvents
{
public:
// 00
int numEvents;
// 04
void *reserved;
// 08
VstEvent* events[1];
};
// Not finished, neither really used
class VstParameterProperties
{
public:
/*
float stepFloat;
char label[64];
int flags;
int minInteger;
int maxInteger;
int stepInteger;
char shortLabel[8];
int category;
char categoryLabel[24];
char empty[128];
*/
float stepFloat;
float smallStepFloat;
float largeStepFloat;
char label[64];
unsigned int flags;
unsigned int minInteger;
unsigned int maxInteger;
unsigned int stepInteger;
unsigned int largeStepInteger;
char shortLabel[8];
unsigned short displayIndex;
unsigned short category;
unsigned short numParametersInCategory;
unsigned short reserved;
char categoryLabel[24];
char future[16];
};
class AEffect
{
public:
// Never use virtual functions!!!
// 00-03
int magic;
// dispatcher 04-07
intptr_t (* dispatcher)( AEffect * , int , int , intptr_t, void * , float );
// process, quite sure 08-0b
void (* process)( AEffect * , float * * , float * * , int );
// setParameter 0c-0f
void (* setParameter)( AEffect * , int , float );
// getParameter 10-13
float (* getParameter)( AEffect * , int );
// programs 14-17
int numPrograms;
// Params 18-1b
int numParams;
// Input 1c-1f
int numInputs;
// Output 20-23
int numOutputs;
// flags 24-27
int flags;
// Fill somewhere 28-2b
void * ptr1;
void * ptr2;
int initialDelay;
// Zeroes 34-37 38-3b
int empty3a;
int empty3b;
// 1.0f 3c-3f
float unkown_float;
// An object? pointer 40-43
void *ptr3;
// Zeroes 44-47
void *user;
// Id 48-4b
int32_t uniqueID;
int32_t version;
// processReplacing 50-53
void (* processReplacing)( AEffect * , float * * , float * * , int );
};
typedef intptr_t (* audioMasterCallback)( AEffect * , int32_t, int32_t,
intptr_t, void * , float );
class VstTimeInfo
{
public:
// 00
double samplePos;
// 08
double sampleRate;
// 10
double nanoSeconds;
// 18
double ppqPos;
// 20?
double tempo;
// 28
double barStartPos;
// 30?
double cycleStartPos;
// 38?
double cycleEndPos;
// 40?
int timeSigNumerator;
// 44?
int timeSigDenominator;
// unconfirmed 48 4c 50
char empty3[4 + 4 + 4];
// 54
int flags;
};
// from http://www.asseca.org/vst-24-specs/efGetParameterProperties.html
enum VstParameterFlags
{
// parameter is a switch (on/off)
kVstParameterIsSwitch = 1 << 0,
// minInteger, maxInteger valid
kVstParameterUsesIntegerMinMax = 1 << 1,
// stepFloat, smallStepFloat, largeStepFloat valid
kVstParameterUsesFloatStep = 1 << 2,
// stepInteger, largeStepInteger valid
kVstParameterUsesIntStep = 1 << 3,
// displayIndex valid
kVstParameterSupportsDisplayIndex = 1 << 4,
// category, etc. valid
kVstParameterSupportsDisplayCategory = 1 << 5,
// set if parameter value can ramp up/down
kVstParameterCanRamp = 1 << 6
};
// from http://www.asseca.org/vst-24-specs/efBeginLoadProgram.html
struct VstPatchChunkInfo
{
int32_t version; // Format Version (should be 1)
int32_t pluginUniqueID; // UniqueID of the plug-in
int32_t pluginVersion; // Plug-in Version
int32_t numElements; // Number of Programs (Bank) or
// Parameters (Program)
char future[48]; // Reserved for future use
};
// from http://www.asseca.org/vst-24-specs/efGetPlugCategory.html
enum VstPlugCategory
{
kPlugCategUnknown = 0, // 0=Unknown, category not implemented
kPlugCategEffect, // 1=Simple Effect
kPlugCategSynth, // 2=VST Instrument (Synths, samplers,...)
kPlugCategAnalysis, // 3=Scope, Tuner, ...
kPlugCategMastering, // 4=Dynamics, ...
kPlugCategSpacializer, // 5=Panners, ...
kPlugCategRoomFx, // 6=Delays and Reverbs
kPlugSurroundFx, // 7=Dedicated surround processor
kPlugCategRestoration, // 8=Denoiser, ...
kPlugCategOfflineProcess, // 9=Offline Process
kPlugCategShell, // 10=Plug-in is container of other
// plug-ins @see effShellGetNextPlugin()
kPlugCategGenerator, // 11=ToneGenerator, ...
kPlugCategMaxCount // 12=Marker to count the categories
};
#endif
+77
View File
@@ -0,0 +1,77 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <QGridLayout>
#include "../headers/EditorWidget.h"
void EditorWidget::buildEffectContainer(AEffect *effect)
{
WNDCLASSEXW wcex{sizeof(wcex)};
wcex.lpfnWndProc = DefWindowProcW;
wcex.hInstance = GetModuleHandleW(nullptr);
wcex.lpszClassName = L"Minimal VST host - Guest VST Window Frame";
RegisterClassExW(&wcex);
const auto style = WS_CAPTION | WS_THICKFRAME | WS_OVERLAPPEDWINDOW;
windowHandle = CreateWindowW(wcex.lpszClassName, TEXT(""), style, 0, 0,
0, 0, nullptr, nullptr, nullptr, nullptr);
// set pointer to vst effect for window long
LONG_PTR wndPtr = (LONG_PTR)effect;
SetWindowLongPtr(windowHandle, -21 /*GWLP_USERDATA*/, wndPtr);
QWidget *widget = QWidget::createWindowContainer(
QWindow::fromWinId((WId)windowHandle), nullptr);
widget->move(0, 0);
QGridLayout *layout = new QGridLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
setLayout(layout);
layout->addWidget(widget);
effect->dispatcher(effect, effEditOpen, 0, 0, windowHandle, 0);
VstRect *vstRect = nullptr;
effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0);
if (vstRect) {
widget->resize(vstRect->right - vstRect->left,
vstRect->bottom - vstRect->top);
resize(vstRect->right - vstRect->left,
vstRect->bottom - vstRect->top);
} else {
widget->resize(300, 300);
}
}
void EditorWidget::handleResizeRequest(int, int)
{
// Some plugins can't resize automatically (like SPAN by Voxengo),
// so we must resize window manually
// get pointer to vst effect from window long
LONG_PTR wndPtr = (LONG_PTR)GetWindowLongPtrW(windowHandle,
-21 /*GWLP_USERDATA*/);
AEffect *effect = (AEffect *)(wndPtr);
VstRect *rec = nullptr;
effect->dispatcher(effect, effEditGetRect, 0, 0, &rec, 0);
if (rec) {
resize(rec->right - rec->left, rec->bottom - rec->top);
}
}
+91
View File
@@ -0,0 +1,91 @@
/*****************************************************************************
Copyright (C) 2016-2017 by Colin Edwards.
Additional Code Copyright (C) 2016-2017 by c3r1c3 <c3r1c3@nevermindonline.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "../headers/VSTPlugin.h"
#include "../headers/vst-plugin-callbacks.hpp"
#include <util/platform.h>
#include <windows.h>
AEffect *VSTPlugin::loadEffect()
{
AEffect *plugin = nullptr;
wchar_t *wpath;
os_utf8_to_wcs_ptr(pluginPath.c_str(), 0, &wpath);
dllHandle = LoadLibraryW(wpath);
bfree(wpath);
if (dllHandle == nullptr) {
DWORD errorCode = GetLastError();
// Display the error message and exit the process
if (errorCode == ERROR_BAD_EXE_FORMAT) {
blog(LOG_WARNING, "Could not open library, "
"wrong architecture.");
} else {
blog(LOG_WARNING,
"Failed trying to load VST from '%s'"
", error %d\n",
pluginPath.c_str(), GetLastError());
}
return nullptr;
}
vstPluginMain mainEntryPoint =
(vstPluginMain)GetProcAddress(dllHandle, "VSTPluginMain");
if (mainEntryPoint == nullptr) {
mainEntryPoint = (vstPluginMain)GetProcAddress(
dllHandle, "VstPluginMain()");
}
if (mainEntryPoint == nullptr) {
mainEntryPoint =
(vstPluginMain)GetProcAddress(dllHandle, "main");
}
if (mainEntryPoint == nullptr) {
blog(LOG_WARNING, "Couldn't get a pointer to plug-in's main()");
return nullptr;
}
// Instantiate the plug-in
try {
plugin = mainEntryPoint(hostCallback_static);
} catch (...) {
blog(LOG_WARNING, "VST plugin initialization failed");
return nullptr;
}
if (plugin == nullptr) {
blog(LOG_WARNING, "Couldn't create instance for '%s'",
pluginPath.c_str());
return nullptr;
}
plugin->user = this;
return plugin;
}
void VSTPlugin::unloadLibrary()
{
if (dllHandle) {
FreeLibrary(dllHandle);
dllHandle = nullptr;
}
}