Browse Source

Initial work for VST3 compatible plugins, lots to do..

Signed-off-by: falkTX <falktx@falktx.com>
pull/292/head
falkTX 4 years ago
parent
commit
d7ba57dee1
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
7 changed files with 375 additions and 13 deletions
  1. +35
    -6
      Makefile.plugins.mk
  2. +2
    -0
      distrho/DistrhoPluginMain.cpp
  3. +2
    -0
      distrho/DistrhoUIMain.cpp
  4. +2
    -0
      distrho/src/DistrhoPluginInternal.hpp
  5. +333
    -0
      distrho/src/DistrhoPluginVST3.cpp
  6. +0
    -7
      distrho/src/travesty/factory.h
  7. +1
    -0
      examples/Parameters/Makefile

+ 35
- 6
Makefile.plugins.mk View File

@@ -52,6 +52,19 @@ endif
# backwards compat
BASE_FLAGS += -DHAVE_JACK

# ---------------------------------------------------------------------------------------------------------------------
# Set VST3 filename, see https://vst3sdk-doc.diatonic.jp/doc/vstinterfaces/vst3loc.html

ifeq ($(LINUX),true)
VST3_FILENAME = $(TARGET_PROCESSOR)-linux/$(NAME).so
endif
ifeq ($(MACOS),true)
VST3_FILENAME = MacOS/$(NAME)
endif
ifeq ($(WINDOWS),true)
VST3_FILENAME = $(TARGET_PROCESSOR)-win/$(NAME).vst3
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set files to build

@@ -72,7 +85,10 @@ dssi_ui = $(TARGET_DIR)/$(NAME)-dssi/$(NAME)_ui$(APP_EXT)
lv2 = $(TARGET_DIR)/$(NAME).lv2/$(NAME)$(LIB_EXT)
lv2_dsp = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_dsp$(LIB_EXT)
lv2_ui = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_ui$(LIB_EXT)
vst = $(TARGET_DIR)/$(NAME)-vst$(LIB_EXT)
vst2 = $(TARGET_DIR)/$(NAME)-vst$(LIB_EXT)
ifneq ($(VST3_FILENAME),)
vst3 = $(TARGET_DIR)/$(NAME).vst3/Contents/$(VST3_FILENAME)
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set plugin symbols to export
@@ -83,6 +99,7 @@ SYMBOLS_DSSI = -Wl,-exported_symbol,_ladspa_descriptor -Wl,-exported_symbol,_d
SYMBOLS_LV2 = -Wl,-exported_symbol,_lv2_descriptor -Wl,-exported_symbol,_lv2_generate_ttl
SYMBOLS_LV2UI = -Wl,-exported_symbol,_lv2ui_descriptor
SYMBOLS_VST2 = -Wl,-exported_symbol,_VSTPluginMain
SYMBOLS_VST3 = -Wl,-exported_symbol,_GetPluginFactory -Wl,-exported_symbol,_bundleEntry -Wl,-exported_symbol,_bundleExit
endif

# ---------------------------------------------------------------------------------------------------------------------
@@ -288,19 +305,29 @@ $(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB)
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_LV2UI) -o $@

# ---------------------------------------------------------------------------------------------------------------------
# VST
# VST2

vst: $(vst)
vst2 vst: $(vst2)

ifeq ($(HAVE_DGL),true)
$(vst): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST.cpp.o $(DGL_LIB)
$(vst2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o $(BUILD_DIR)/DistrhoUIMain_VST.cpp.o $(DGL_LIB)
else
$(vst): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o
$(vst2): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o
endif
-@mkdir -p $(shell dirname $@)
@echo "Creating VST plugin for $(NAME)"
@echo "Creating VST2 plugin for $(NAME)"
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_VST2) -o $@

# ---------------------------------------------------------------------------------------------------------------------
# VST3

vst3: $(vst3)

$(vst3): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.o
-@mkdir -p $(shell dirname $@)
@echo "Creating VST3 plugin for $(NAME)"
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_VST3) -o $@

# ---------------------------------------------------------------------------------------------------------------------

-include $(OBJS_DSP:%.o=%.d)
@@ -313,10 +340,12 @@ endif
-include $(BUILD_DIR)/DistrhoPluginMain_DSSI.cpp.d
-include $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.d
-include $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.d
-include $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.d

-include $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.d
-include $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.d
-include $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.d
-include $(BUILD_DIR)/DistrhoUIMain_VST.cpp.d
-include $(BUILD_DIR)/DistrhoUIMain_VST3.cpp.d

# ---------------------------------------------------------------------------------------------------------------------

+ 2
- 0
distrho/DistrhoPluginMain.cpp View File

@@ -27,6 +27,8 @@
# include "src/DistrhoPluginLV2export.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_VST)
# include "src/DistrhoPluginVST.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_VST3)
# include "src/DistrhoPluginVST3.cpp"
#else
# error unsupported format
#endif

+ 2
- 0
distrho/DistrhoUIMain.cpp View File

@@ -26,6 +26,8 @@
# include "src/DistrhoUILV2.cpp"
#elif defined(DISTRHO_PLUGIN_TARGET_VST)
// nothing
#elif defined(DISTRHO_PLUGIN_TARGET_VST3)
// nothing
#else
# error unsupported format
#endif

+ 2
- 0
distrho/src/DistrhoPluginInternal.hpp View File

@@ -814,7 +814,9 @@ private:
static const PortGroupWithId sFallbackPortGroup;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter)
#ifndef DISTRHO_PLUGIN_TARGET_VST3 /* there is no way around this for VST3 */
DISTRHO_PREVENT_HEAP_ALLOCATION
#endif
};

// -----------------------------------------------------------------------


+ 333
- 0
distrho/src/DistrhoPluginVST3.cpp View File

@@ -0,0 +1,333 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "DistrhoPluginInternal.hpp"
#include "../extra/ScopedPointer.hpp"

#include "travesty/audio_processor.h"
#include "travesty/component.h"
#include "travesty/edit_controller.h"
#include "travesty/factory.h"

START_NAMESPACE_DISTRHO

#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
static const writeMidiFunc writeMidiCallback = nullptr;
#endif

// custom v3_tuid compatible type
typedef uint32_t dpf_tuid[4];
static_assert(sizeof(v3_tuid) == sizeof(dpf_tuid), "uid size mismatch");

// custom uids, fully created during module init
static constexpr const uint32_t dpf_id_entry = d_cconst('D', 'P', 'F', ' ');
static constexpr const uint32_t dpf_id_clas = d_cconst('c', 'l', 'a', 's');
static constexpr const uint32_t dpf_id_comp = d_cconst('c', 'o', 'm', 'p');
static constexpr const uint32_t dpf_id_ctrl = d_cconst('c', 't', 'r', 'l');
static constexpr const uint32_t dpf_id_proc = d_cconst('p', 'r', 'o', 'c');
static constexpr const uint32_t dpf_id_view = d_cconst('v', 'i', 'e', 'w');

static dpf_tuid dpf_tuid_class = { dpf_id_entry, dpf_id_clas, 0, 0 };
static dpf_tuid dpf_tuid_component = { dpf_id_entry, dpf_id_comp, 0, 0 };
static dpf_tuid dpf_tuid_controller = { dpf_id_entry, dpf_id_ctrl, 0, 0 };
static dpf_tuid dpf_tuid_processor = { dpf_id_entry, dpf_id_proc, 0, 0 };
static dpf_tuid dpf_tuid_view = { dpf_id_entry, dpf_id_view, 0, 0 };

// -----------------------------------------------------------------------

void strncpy(char* const dst, const char* const src, const size_t size)
{
DISTRHO_SAFE_ASSERT_RETURN(size > 0,);

if (const size_t len = std::min(std::strlen(src), size-1U))
{
std::memcpy(dst, src, len);
dst[len] = '\0';
}
else
{
dst[0] = '\0';
}
}

// -----------------------------------------------------------------------

// v3_funknown, v3_plugin_base, v3_component

// audio_processor

class PluginVst3
{
public:
PluginVst3()
: fPlugin(this, writeMidiCallback)
{
}

private:
// Plugin
PluginExporter fPlugin;

// VST3 stuff
// TODO

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
bool writeMidi(const MidiEvent& midiEvent)
{
// TODO
return true;
}

static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent)
{
return ((PluginVst*)ptr)->writeMidi(midiEvent);
}
#endif

};

// -----------------------------------------------------------------------
// WIP this whole section still TODO

struct ControllerComponent;
struct ProcessorComponent;

struct ComponentAdapter : v3_funknown, v3_plugin_base
{
// needs atomic refcount, starts at 1

ComponentAdapter()
{
static const uint8_t* kSupportedFactories[] = {
v3_funknown_iid,
v3_plugin_base_iid,
/*
v3_component_iid,
v3_edit_controller_iid,
v3_audio_processor_iid
*/
};

// ------------------------------------------------------------------------------------------------------------
// v3_funknown

query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result
{
d_stdout("ComponentAdapter::query_interface %p %p %p", self, iid, iface);

*iface = NULL;
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE);

for (const uint8_t* factory_iid : kSupportedFactories)
{
if (v3_tuid_match(factory_iid, iid))
{
*iface = self;
return V3_OK;
}
}

return V3_NO_INTERFACE;
};

// TODO use atomic counter
ref = []V3_API(void*) -> uint32_t { return 1; };
unref = []V3_API(void*) -> uint32_t { return 0; };
}
};

struct ControllerComponent : ComponentAdapter
{
};

struct ProcessorComponent : ComponentAdapter
{
};

// --------------------------------------------------------------------------------------------------------------------
// Dummy plugin to get data from

static ScopedPointer<PluginExporter> gPluginInfo;

static void gPluginInit()
{
if (gPluginInfo != nullptr)
return;

d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
gPluginInfo = new PluginExporter(nullptr, nullptr);
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;

dpf_tuid_class[3] = dpf_tuid_component[3] = dpf_tuid_controller[3]
= dpf_tuid_processor[3] = dpf_tuid_view[3] = gPluginInfo->getUniqueId();
}

// --------------------------------------------------------------------------------------------------------------------
// dpf_factory

struct v3_plugin_factory_cpp : v3_funknown, v3_plugin_factory {
v3_plugin_factory_2 v2;
v3_plugin_factory_3 v3;
};

struct dpf_factory : v3_plugin_factory_cpp {
dpf_factory()
{
static const uint8_t* kSupportedFactories[] = {
v3_funknown_iid,
v3_plugin_factory_iid,
v3_plugin_factory_2_iid
};

// ------------------------------------------------------------------------------------------------------------
// v3_funknown

query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result
{
*iface = NULL;
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE);

for (const uint8_t* factory_iid : kSupportedFactories)
{
if (v3_tuid_match(factory_iid, iid))
{
*iface = self;
return V3_OK;
}
}

return V3_NO_INTERFACE;
};

// we only support 1 plugin per binary, so don't have to care here
ref = []V3_API(void*) -> uint32_t { return 1; };
unref = []V3_API(void*) -> uint32_t { return 0; };

// ------------------------------------------------------------------------------------------------------------
// v3_plugin_factory

get_factory_info = []V3_API(void*, struct v3_factory_info* const info) -> v3_result
{
DISTRHO_NAMESPACE::strncpy(info->vendor, gPluginInfo->getMaker(), sizeof(info->vendor));
DISTRHO_NAMESPACE::strncpy(info->url, gPluginInfo->getHomePage(), sizeof(info->url));
DISTRHO_NAMESPACE::strncpy(info->email, "", sizeof(info->email)); // TODO
return V3_OK;
};

num_classes = []V3_API(void*) -> int32_t
{
return 1;
};

get_class_info = []V3_API(void*, int32_t /*idx*/, struct v3_class_info* const info) -> v3_result
{
memcpy(info->class_id, dpf_tuid_class, sizeof(v3_tuid));
info->cardinality = 0x7FFFFFFF;
DISTRHO_NAMESPACE::strncpy(info->category, "Audio Module Class", sizeof(info->category));
DISTRHO_NAMESPACE::strncpy(info->name, gPluginInfo->getName(), sizeof(info->name));
return V3_OK;
};

create_instance = []V3_API(void* self, const v3_tuid class_id, const v3_tuid iid, void** instance) -> v3_result
{
d_stdout("%s %i %p %p %p %p", __PRETTY_FUNCTION__, __LINE__, self, class_id, iid, instance);
DISTRHO_SAFE_ASSERT_RETURN(v3_tuid_match(class_id, *(v3_tuid*)&dpf_tuid_class) &&
v3_tuid_match(iid, v3_component_iid), V3_NO_INTERFACE);

*instance = nullptr; // new ComponentAdapter();
return V3_INTERNAL_ERR;
};

// ------------------------------------------------------------------------------------------------------------
// v3_plugin_factory_2

v2.get_class_info_2 = []V3_API(void*, int32_t /*idx*/, struct v3_class_info_2 *info) -> v3_result
{
// get_class_info
memcpy(info->class_id, dpf_tuid_class, sizeof(v3_tuid));
info->cardinality = 0x7FFFFFFF;
DISTRHO_NAMESPACE::strncpy(info->category, "Audio Module Class", sizeof(info->category));
DISTRHO_NAMESPACE::strncpy(info->name, gPluginInfo->getName(), sizeof(info->name));
// get_class_info_2
info->class_flags = 0;
DISTRHO_NAMESPACE::strncpy(info->sub_categories, "", sizeof(info->sub_categories)); // TODO
DISTRHO_NAMESPACE::strncpy(info->vendor, gPluginInfo->getMaker(), sizeof(info->vendor));
DISTRHO_NAMESPACE::strncpy(info->version, "", sizeof(info->version)); // TODO
DISTRHO_NAMESPACE::strncpy(info->sdk_version, "Travesty", sizeof(info->sdk_version)); // TESTING use "VST 3.7" ?
return V3_OK;
};
}
};

static const dpf_factory dpf_factory;

END_NAMESPACE_DISTRHO

// --------------------------------------------------------------------------------------------------------------------
// VST3 entry point

DISTRHO_PLUGIN_EXPORT
const void* GetPluginFactory(void);

const void* GetPluginFactory(void)
{
static const struct v3_plugin_factory_2* const factory = (v3_plugin_factory_2*)&dpf_factory;
return &factory;
}

// --------------------------------------------------------------------------------------------------------------------
// OS specific module load

#ifdef DISTRHO_OS_MAC
DISTRHO_PLUGIN_EXPORT bool bundleEntry(CFBundleRef);
DISTRHO_PLUGIN_EXPORT bool bundleExit(void);
bool bundleEntry(CFBundleRef)
{
gPluginInit();
return true;
}
bool bundleExit(void)
{
gPluginInfo = nullptr;
return true;
}
#else
# ifdef DISTRHO_OS_WINDOWS
# define ENTRYFNNAME InitDll
# define EXITFNNAME ExitDll
# else
# define ENTRYFNNAME ModuleEntry
# define EXITFNNAME ModuleExit
# endif
DISTRHO_PLUGIN_EXPORT bool ENTRYFNNAME(void*);
DISTRHO_PLUGIN_EXPORT bool EXITFNNAME(void);
bool ENTRYFNNAME(void*)
{
gPluginInit();
return true;
}
bool EXITFNNAME(void)
{
gPluginInfo = nullptr;
return true;
}
# undef ENTRYFNNAME
# undef EXITFNNAME
#endif

// --------------------------------------------------------------------------------------------------------------------

+ 0
- 7
distrho/src/travesty/factory.h View File

@@ -113,10 +113,3 @@ struct v3_plugin_factory_3 {

static const v3_tuid v3_plugin_factory_3_iid =
V3_ID(0x4555A2AB, 0xC1234E57, 0x9B122910, 0x36878931);

#ifdef __cplusplus
struct v3_plugin_factory_cpp : v3_funknown, v3_plugin_factory {
v3_plugin_factory_2 v2;
v3_plugin_factory_3 v3;
};
#endif

+ 1
- 0
examples/Parameters/Makefile View File

@@ -46,6 +46,7 @@ TARGETS += lv2_dsp
endif

TARGETS += vst
TARGETS += vst3

all: $(TARGETS)



Loading…
Cancel
Save