Commit be86b227 authored by Benjamin Heisch's avatar Benjamin Heisch
Browse files

A lot of documentation and some small refractorings.

parent a62e9b0d
Pipeline #19324 failed with stages
in 2 minutes and 14 seconds
......@@ -3,6 +3,8 @@ find_package(TortureTester)
find_package(VST3)
set(__DIR_OF_XPLUG_CMAKE ${CMAKE_CURRENT_LIST_DIR})
###########################HELPER_FUNCTIONS##############################
# Getting a String of the current architecture(Which is Vst3-Naming compliant)
# The Architecture stirng will be written in the ARCHITECTURE_NAME Variable.
function(get_architecture)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows" OR ${CMAKE_SYSTEM_NAME} STREQUAL "MSYS")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
......@@ -32,54 +34,61 @@ endfunction(get_architecture)
###########################PACKAGE FUNCTIONS##############################
# Creates an LV2-PACKAGE
# TARGET - LV2 Target to create Package from.
# PATH - Path to directory, where to create the package witch PACKAGE_NAME in it. The Default, is the current workingdirectory.
# PACKAGE_NAME - Name of the Package To generate. Defaults to {TARGET_NAME}.lv2
function(create_lv2_package)
cmake_parse_arguments(CREATE_LV2_PACKAGE "" "TARGET;PATH;PACKAGE_NAME" "" ${ARGN} )
if(NOT CREATE_LV2_PACKAGE_PATH)
cmake_parse_arguments(CREATE_LV2_PACKAGE "" "TARGET;PATH;PACKAGE_NAME" "" ${ARGN} )
if(NOT CREATE_LV2_PACKAGE_PATH)
set(CREATE_LV2_PACKAGE_PATH "./")
endif(NOT CREATE_LV2_PACKAGE_PATH)
if(NOT CREATE_LV2_PACKAGE_PACKAGE_NAME)
endif(NOT CREATE_LV2_PACKAGE_PATH)
if(NOT CREATE_LV2_PACKAGE_PACKAGE_NAME)
set(CREATE_LV2_PACKAGE_PACKAGE_NAME ${TARGET}.lv2/)
endif(NOT CREATE_LV2_PACKAGE_PACKAGE_NAME)
endif(NOT CREATE_LV2_PACKAGE_PACKAGE_NAME)
set(LV2_PACKAGE_ROOT ${CREATE_LV2_PACKAGE_PATH}/${CREATE_LV2_PACKAGE_PACKAGE_NAME})
add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${LV2_PACKAGE_ROOT})
add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${TARGET}> ${LV2_PACKAGE_ROOT}/$<TARGET_FILE_NAME:${TARGET}>
set(LV2_PACKAGE_ROOT ${CREATE_LV2_PACKAGE_PATH}/${CREATE_LV2_PACKAGE_PACKAGE_NAME})
add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${LV2_PACKAGE_ROOT})
add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${TARGET}> ${LV2_PACKAGE_ROOT}/$<TARGET_FILE_NAME:${TARGET}>
COMMAND TTLGenerator ARGS $<TARGET_FILE:${TARGET}> BYPRODUCTS ${LV2_PACKAGE_ROOT}/manifest.ttl
${LV2_PACKAGE_ROOT}/${TARGET}.ttl WORKING_DIRECTORY ${LV2_PACKAGE_ROOT})
endfunction(create_lv2_package)
# Creates an VST3-PACKAGE
# TARGET - VST3 Target to create Package from.
# PATH - Path to directory, where to create the package witch PACKAGE_NAME in it. The Default, is the current workingdirectory.
# PACKAGE_NAME - Name of the Package To generate. Defaults to {TARGET_NAME}.vst3
function(create_vst3_package)
cmake_parse_arguments(CREATE_VST3_PACKAGE "" "TARGET;PATH;PACKAGE_NAME" "" ${ARGN} )
if(NOT CREATE_VST3_PACKAGE_PATH)
cmake_parse_arguments(CREATE_VST3_PACKAGE "" "TARGET;PATH;PACKAGE_NAME" "" ${ARGN} )
if(NOT CREATE_VST3_PACKAGE_PATH)
set(CREATE_VST3_PACKAGE_PATH "./")
endif(NOT CREATE_VST3_PACKAGE_PATH)
if(NOT CREATE_VST3_PACKAGE_PACKAGE_NAME)
set(CREATE_VST3_PACKAGE_PACKAGE_NAME ${TARGET})
endif(NOT CREATE_VST3_PACKAGE_PACKAGE_NAME)
set(VST3_PACKAGE_ROOT ${CREATE_VST3_PACKAGE_PATH}/${CREATE_VST3_PACKAGE_PACKAGE_NAME})
get_architecture()
set_target_properties(${TARGET} PROPERTIES PREFIX "")
add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${VST3_PACKAGE_ROOT}
endif(NOT CREATE_VST3_PACKAGE_PATH)
if(NOT CREATE_VST3_PACKAGE_PACKAGE_NAME)
set(CREATE_VST3_PACKAGE_PACKAGE_NAME ${TARGET}.vst3)
endif(NOT CREATE_VST3_PACKAGE_PACKAGE_NAME)
set(VST3_PACKAGE_ROOT ${CREATE_VST3_PACKAGE_PATH}/${CREATE_VST3_PACKAGE_PACKAGE_NAME})
get_architecture()
set_target_properties(${TARGET} PROPERTIES PREFIX "")
add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${VST3_PACKAGE_ROOT}
COMMAND ${CMAKE_COMMAND} -E make_directory ${VST3_PACKAGE_ROOT}/Contents/Resources
COMMAND ${CMAKE_COMMAND} -E make_directory ${VST3_PACKAGE_ROOT}/Contents/${ARCHITECTURE_NAME}
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${TARGET}> ${VST3_PACKAGE_ROOT}/Contents/${ARCHITECTURE_NAME}/$<TARGET_FILE_NAME:${TARGET}>
COMMAND ${CMAKE_COMMAND} -E copy ${__DIR_OF_XPLUG_CMAKE}/speaker.ico ${VST3_PACKAGE_ROOT}/Plugin.ico)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows" OR ${CMAKE_SYSTEM_NAME} STREQUAL "MSYS")
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows" OR ${CMAKE_SYSTEM_NAME} STREQUAL "MSYS")
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated_desktop.ini CONTENT "[.ShellClassInfo]\nIconResource=Plugin.ico,0")
set(WINDOWS_EXTRA_DIR "/${ARCHITECTURE_NAME}/")
add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/generated_desktop.ini ${VST3_PACKAGE_ROOT}/desktop.ini
COMMAND attrib +s +r +h ${VST3_PACKAGE_ROOT}/desktop.ini
COMMAND attrib +r +h ${VST3_PACKAGE_ROOT}/Plugin.ico
COMMAND ${CMAKE_COMMAND} -E rename ${VST3_PACKAGE_ROOT}/Contents/${ARCHITECTURE_NAME}/$<TARGET_FILE_NAME:${TARGET}> ${VST3_PACKAGE_ROOT}/Contents/${ARCHITECTURE_NAME}/${TARGET}.vst3 )
endif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows" OR ${CMAKE_SYSTEM_NAME} STREQUAL "MSYS")
endif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows" OR ${CMAKE_SYSTEM_NAME} STREQUAL "MSYS")
endfunction(create_vst3_package)
################################TEST FUNCTIONS##########################
# Run pluginval tests with given TARGET. pluginval must be available as target or be installed.
# Run all available VST2 Tests, which are installed on the current System.
function(run_vst2_test TARGET)
if(TARGET pluginval)
add_test(NAME ${TARGET}_pluginval_vst2_test COMMAND pluginval " \" --validate-in-process --validate $<TARGET_FILE:${TARGET}> --strictness-level 10 \"" )
......@@ -89,7 +98,7 @@ function(run_vst2_test TARGET)
add_test(NAME ${TARGET}_xvalidate_vst2_test COMMAND XValidate -vst2 -l 10 -p $<TARGET_FILE:${TARGET}> )
endfunction(run_vst2_test TARGET)
# Run pluginval tests with given TARGET. pluginval must be available as target or be installed.
# Run all available VST3 Tests, which are installed on the current System.
function(run_vst3_test TARGET)
create_vst3_package(TARGET ${TARGET} PATH ${CMAKE_CURRENT_BINARY_DIR}/temp/ PACKAGE_NAME ${TARGET}.vst3)
if(TARGET pluginval)
......@@ -107,23 +116,20 @@ function(run_vst3_test TARGET)
add_test(NAME ${TARGET}_xvalidate_vst3_test COMMAND XValidate -vst3 -l 10 -p $<TARGET_FILE:${TARGET}> )
endfunction(run_vst3_test TARGET)
# Run all available LADSPA Tests, which are installed on the current System.
function(run_ladspa_tests TARGET)
if(TARGET TortureTester)
add_test(NAME ${TARGET}_torture_ladspa_test COMMAND $<TARGET_FILE:TortureTester> --evil --denormals --ladspa --plugin $<TARGET_FILE:${TARGET}>)
endif(TARGET TortureTester)
add_test(NAME ${TARGET}_xvalidate_ladspa_test COMMAND XValidate -ladspa -l 10 -p $<TARGET_FILE:${TARGET}> )
endfunction(run_ladspa_tests TARGET)
# Run all available LV2 Tests, which are installed on the current System.
function(run_lv2_tests TARGET)
create_lv2_package(TARGET ${TARGET} PATH ${CMAKE_CURRENT_BINARY_DIR}/temp/ PACKAGE_NAME ${TARGET}.lv2)
set(LV2_TEMP_PACKAGE ${CMAKE_CURRENT_BINARY_DIR}/temp/${TARGET}.lv2/)
if(TARGET TortureTester)
add_test(NAME ${TARGET}_torture_lv2_test COMMAND $<TARGET_FILE:TortureTester> --evil --lv2 --plugin ${LV2_TEMP_PACKAGE}/$<TARGET_FILE_NAME:${TARGET}> )
endif(TARGET TortureTester)
add_test(NAME ${TARGET}_xvalidate_lv2_test COMMAND XValidate -lv2 -l 10 -p ${LV2_TEMP_PACKAGE}/$<TARGET_FILE_NAME:${TARGET}> )
endfunction(run_lv2_tests TARGET)
/*
Copyright 2007-2019 David Robillard <http://drobilla.net>
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.
THIS 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 "lilv.h"
#include <lv2/atom/atom.h>
......
/**
* @file Exampleplugin, to show the use of an easy Start with LazyPlugin. Easy Midi Messaging Concepts are explained here.
*/
#include <base/PluginBases.hpp>
#include <base/Ports.hpp>
#include <tools/PortHandling.hpp>
using namespace XPlug;
/**
* @brief MidiForwarder Example class, which has 1 Midi Input and 2 Midi
* Outputs. The Midi in signal is forwarded to the 2 Midi Outputs
*/
class MidiForwarder : public LazyPlugin
{
public:
/**
* @brief Standard constructor, which creates on instantiation the needed
* Ports and Informations.
*/
MidiForwarder()
{
// Adding the needed in and output ports in our portcomponent
this->portComponent->addPort(
std::make_shared<QueueMidiPort>("MidiIn", PortDirection::Input));
this->portComponent->addPort(
std::make_shared<QueueMidiPort>("MidiOut", PortDirection::Output));
this->portComponent->addPort(
std::make_shared<QueueMidiPort>("MidiOut2", PortDirection::Output));
// Detect the needed Features for this Plugin(exspecially MIDI support)
this->featureComponent->detectFeatures(this->getPortComponent());
// Overwrite some default information
this->infoComponent->pluginName = "MidiForwarder";
this->infoComponent->creatorName = "Benjamin Heisch";
this->infoComponent->pluginUri =
......@@ -22,9 +38,11 @@ public:
// Geerbt über IPlugin
virtual void processAudio() override
{
// Get the needed ports, to operate on from the portcomponent.
auto in0 = getPortAt<IMidiPort>(this, 0, PortDirection::Input);
auto out0 = getPortAt<IMidiPort>(this, 0, PortDirection::Output);
auto out1 = getPortAt<IMidiPort>(this, 1, PortDirection::Output);
// Forward all Messages from the Inputs to the output.
while (!in0->empty()) {
auto midiMsg = in0->get();
auto midiMsg2 = midiMsg;
......@@ -36,6 +54,5 @@ public:
virtual void deinit() override {}
virtual void activate() override {}
virtual void deactivate() override {}
// virtual PluginInfo* getPluginInfo() override;
};
REGISTER_PLUGIN(MidiForwarder);
......@@ -2,19 +2,33 @@
#include <base/Ports.hpp>
#include <tools/PortHandling.hpp>
using namespace XPlug;
/**
* @brief VolumePlguin class, which forwards audiodata and just changes the
* Volume. For an easy start its derived from LazyPlugin, to start easily.
*/
class VolumePlugin : public LazyPlugin
{
protected:
// Define an Input and an Outputport. (To optimize accesstime, not like in
// MidiForwarder)
std::shared_ptr<IAudioPort> in0 =
std::make_shared<MonoPort>("In0", PortDirection::Input);
std::shared_ptr<IAudioPort> out0 =
std::make_shared<MonoPort>("Out0", PortDirection::Output);
public:
/**
* @brief Constructor, which adding the local defined Ports, to the
* PortComponent. Its also changed the needed Plugininformation.
*/
VolumePlugin()
{
// Adding the local ports to the portcomponent, so the plugininfrastructure
// can process it.
this->portComponent->addPort(in0);
this->portComponent->addPort(out0);
// Changing the Information about the Plugin, because the default Values
// are... not enough ;)
this->infoComponent->pluginName = "VolumePlugin";
this->infoComponent->creatorName = "Benjamin Heisch";
this->infoComponent->pluginUri =
......@@ -24,10 +38,11 @@ public:
// Geerbt über IPlugin
virtual void processAudio() override
{
// auto in0 = getPortAt<IAudioPort>(this, 0,PortDirection::Input);
// auto out0 = getPortAt<IAudioPort>(this, 0, PortDirection::Output);
// Simple loop over the Dat and process.
// Currently no Volumechanging is used, but it will be added later, when the
// Framework supports Parameter, so the Volume can be adjustet.
for (size_t i = 0; i < in0->size(); i++) {
for (size_t s = 0; s < in0->getSampleSize(); s++) {
for (size_t s = 0; s < in0->getSampleCount(); s++) {
if (in0->at(i)->getData() != nullptr &&
out0->at(i)->getData() != nullptr)
out0->at(i)->getData()[s] = in0->at(i)->getData()[s];
......@@ -38,6 +53,10 @@ public:
virtual void deinit() override {}
virtual void activate() override {}
virtual void deactivate() override {}
// virtual PluginInfo* getPluginInfo() override;
};
// Its very important to Register a Plugin in the GlobalData object, which is
// accessed through the GlobalData() Function.
// The easiest way ist to just use this REGISTER_PLUGIN macro. But use it in
// your sourcefile, because a static variable will be declared. And that just
// works in Sourcefiles.
REGISTER_PLUGIN(VolumePlugin);
#ifndef EXAMPLE_PLUGIN_HPP
#define EXAMPLE_PLUGIN_HPP
#include <base/LazyPlugin.hpp>
using namespace XPlug;
class VolumePlugin : public LazyPlugin
{
public:
VolumePlugin();
// Geerbt ber IPlugin
virtual void processAudio() override;
virtual void init() override;
virtual void deinit() override;
virtual void activate() override;
virtual void deactivate() override;
// virtual PluginInfo* getInfoComponent() override;
};
#endif //! EXAMPLE_PLUGIN_HPP
\ No newline at end of file
/**
* @file Implementation file for the LADSPA Format. The needed API functions are
* defined here. Also the access to the Plugin is implemented here.
*/
#include "ladspa.h"
#include <cstring>
#include <interfaces/IPlugin.hpp>
......@@ -7,8 +11,6 @@
using namespace XPlug;
static std::vector<LADSPA_Descriptor*> ladspaDescriptorArray;
struct LADSPAHandleDataType
{
IPlugin* plug;
......@@ -17,23 +19,37 @@ struct LADSPAHandleDataType
extern "C"
{
/**
* @brief entrypoint for the LADSPA-Format. In this Function an
* LADSPA_Descriptor is created, which maps all needed Functioncalls to
* functionality of the inernal API. Due to the Support of multiple Plugins,
* multiple Plugins can be registered here.
* @param index INdex of a Plugin in the current Binary to load.
* @return if no Plugin is available, a nullptr is returned otherwhise an
* Instance which maps the internal API to the LADSPA-Format is returned.
*/
const LADSPA_Descriptor* ladspa_descriptor(unsigned long index)
{
if (index >= GlobalData().getNumberOfRegisteredPlugins())
if (index >=
GlobalData().getNumberOfRegisteredPlugins()) // index is obvously out of
// range, so return 0.
return nullptr;
PluginPtr plug = GlobalData().getPlugin(index);
auto desc = new LADSPA_Descriptor();
// add the needed Implementation data to the LADSPA_Descriptor
desc->ImplementationData =
new LADSPAHandleDataType{ GlobalData().getPlugin(index).get(), desc };
/******************* INSTANTIATION**********************/
desc->instantiate = [](const LADSPA_Descriptor* descriptor,
unsigned long) -> LADSPA_Handle {
// because the ImplementationData and the LADSPA_Handle are the Same, we
// can return the ImplementationData here. But we the pluginreference in
// this Function, so we pass that and all other needed Data over the
// ImplementationData.
auto data =
static_cast<LADSPAHandleDataType*>(descriptor->ImplementationData);
data->plug->init();
return data;
// return NULL;
};
desc->activate = [](LADSPA_Handle instance) {
auto data = static_cast<LADSPAHandleDataType*>(instance);
......@@ -45,7 +61,9 @@ extern "C"
};
desc->cleanup = [](LADSPA_Handle instance) {
auto data = static_cast<LADSPAHandleDataType*>(instance);
data->plug->deinit();
data->plug
->deinit(); // is needed here, because its the opposite to instantiate.
// free everything.
for (size_t i = 0; i < data->desc->PortCount; i++) {
delete[] data->desc->PortNames[i];
}
......@@ -54,9 +72,9 @@ extern "C"
delete data->desc;
delete data;
};
// LADSPA_PROPERTY_HARD_RT_CAPABLE and other stuff, not supported yet.
desc->Properties = 0;
desc->Properties =
0; // LADSPA_PROPERTY_HARD_RT_CAPABLE and other stuff, not supported yet.
/*********************PORT HANDLING*********************/
desc->PortCount =
static_cast<unsigned long>(getAudioChannelCount(plug.get()));
......@@ -64,8 +82,8 @@ extern "C"
unsigned long portIndex,
LADSPA_Data* DataLocation) {
auto data = static_cast<LADSPAHandleDataType*>(instance);
if (portIndex <
getAudioChannelCount(data->plug)) { // portIndex is in or outputPort
// portIndex is in or outputPort
if (portIndex < getAudioChannelCount(data->plug)) {
getAudioChannelFromIndex(data->plug, portIndex)->feed(DataLocation);
} else {
// Not SUpported yet
......@@ -73,13 +91,18 @@ extern "C"
};
// TODO: When adding Parameter, the have to be mapped to ports here.
int curIndex = 0;
// Ugly allocations, but they are needed... Its just for compatiblity with
// c.
char** portNamesCArray = new char*[desc->PortCount * sizeof(const char*)];
auto portDescripors =
new LADSPA_PortDescriptor[desc->PortCount *
sizeof(LADSPA_PortDescriptor)];
auto rangeHints =
new LADSPA_PortRangeHint[desc->PortCount * sizeof(LADSPA_PortDescriptor)];
int curIndex = 0;
// Iterate through all Audioports and try to allocate Portname, rangehints.
// Still needed for c compatibility. If someone has an more elegant and more
// c++ Way, pls make a commit!
iteratePorts<IAudioPort>(
plug.get(),
[&portNamesCArray, &portDescripors, &rangeHints, &curIndex](IAudioPort* p,
......@@ -112,9 +135,11 @@ extern "C"
desc->run = [](LADSPA_Handle instance, unsigned long SampleCount) {
auto data = static_cast<LADSPAHandleDataType*>(instance);
// Set current Samplesize/Count on everyrun, because she can be different.
// Maybe add some optimizations here.
iteratePorts<IAudioPort>(data->plug,
[SampleCount](IAudioPort* p, size_t) {
p->setSampleSize(SampleCount);
p->setSampleCount(SampleCount);
return false;
});
data->plug->processAudio();
......
......@@ -3,6 +3,9 @@
#include "tools/LibLoading.hpp"
#include <vector>
using namespace XPlug;
/**
* @brief LADSPA Test Suite for XValidate/system_tests
*/
class LADSPATestSuite : public FormatTestSuiteBase
{
public:
......@@ -30,6 +33,7 @@ public:
LoadFunc<LADSPA_Descriptor_Function>(lib, "ladspa_descriptor");
size_t index = 0;
const LADSPA_Descriptor* desc = nullptr;
// All things loaded. Than Run normal execution of Plugin.
while (desc = ladspa_descriptor_fnc(index++), desc != nullptr) {
auto handle = desc->instantiate(desc, sampleRate);
desc->activate(handle);
......
/**
* @file TtlGenerator helper application, to genereate LV2 ttl files.
*/
#include "lv2_ttl_generation.hpp"
#include <fstream>
#include <interfaces/IPlugin.hpp>
......@@ -7,12 +10,11 @@
#include <tools/StringTools.hpp>
using namespace XPlug;
/********FUNCTION VARIABLES*********/
std::string (*getTTLFromPluginPtr)(IPlugin*) = nullptr;
std::string (*getManifestFromMultpleInfosPtr)(std::vector<TTLPluginInfo>) =
nullptr;
std::vector<TTLPluginInfo> (*getPluginInfosPtr)(const std::string&) = nullptr;
void
writeOutBundle(std::vector<TTLPluginInfo> infoArray,
const std::string& fileOutDir = "./")
......
/**
* @file Implementation file for the LV2 Format. The needed API functions are
* defined here. Also the access to the Plugin is implemented here.
*/
#include "GlobalData.hpp"
#include <interfaces/IPlugin.hpp>
#include <lv2/atom/atom.h>
......@@ -11,6 +16,10 @@
#include <vector>
using namespace XPlug;
/**
* @brief Handle, wich is used, to create an possibility to write and read Midi
* more easily.
*/
struct MidiHandle
{
LV2_Atom_Sequence* midiDataLocation;
......@@ -19,7 +28,7 @@ struct MidiHandle
};
/**
* @brief Treats the MidiHandle, at it would be an input. (Put MidiMsg in Pipe)
* @param in
* @param in Input MidiHandle.
*/
inline void
handleInput(MidiHandle* in)
......@@ -35,17 +44,19 @@ handleInput(MidiHandle* in)
}
}
// Struct for a 3 byte MIDI event, used for writing notes
/**
* @brief Struct for a 3 byte MIDI event, used for writing notes
*/
typedef struct
{
LV2_Atom_Event event;
// MidiMessage msg;
uint8_t msg[3];
} MIDINoteEvent;
/**
* @brief Treats the MidiHandle, at it would be an output. (fetches things from
* the Pipe to the output)
* @param in
* @param out Output Midihandle.
*/
inline void
handleOutput(MidiHandle* out)
......@@ -70,12 +81,17 @@ handleOutput(MidiHandle* out)
}
}
/**
* @brief LV2Handle, wich is used to pass Data arount, between LV2-API function
* calls.
*/
struct LV2HandleDataType
{
IPlugin* plug;
const LV2_Descriptor* lv2Desc;
LV2_URID_Map* map;
std::vector<MidiHandle> midiHandles;
IPlugin* plug; // Reference to current Plugin
const LV2_Descriptor* lv2Desc; // Reference to LV2 Descripor
LV2_URID_Map* map; // URID Map to map ids.
std::vector<MidiHandle>
midiHandles; // Midihandles, to use when writing to output.
};
inline bool
......@@ -88,32 +104,32 @@ supportsMidi(IPlugin* plug, IPort* port)
}
/**
The `lv2_descriptor()` function is the entry point to the plugin library. The
host will load symbols the library and call this function repeatedly with
increasing indices to find all the plugins defined in the library. The
descriptorIndex is not an indentifier, the URI of the returned descriptor is
used to determine the identify of the plugin.
This method is in the ``discovery'' threading class, so no other functions
or methods in this plugin library will be called concurrently with it.
*/
* @brief Map, which maps URIs form plugins to ids, to match the internal API
* structure.
*/
static std::unordered_map<std::string, uint32_t> URI_INDEX_MAP;
extern "C"
{
/**
* @brief Implementation of the lv2_descriptor entrypoint.
* @param index index of a Plugin to load(compatible with lv2)
* @return nullptr if index is invalid or an Pointer to the LV2_Descriptor for
* the Plugin.
*/
const LV2_Descriptor* lv2_descriptor(uint32_t index)
{
// return nullptr, if out of range.
if (index >= GlobalData().getNumberOfRegisteredPlugins())
return NULL;
return nullptr;
PluginPtr plug = GlobalData().getPlugin(index);
auto desc = new LV2_Descriptor();
// get the identifaction URI for the Plugin.
desc->URI = plug->getInfoComponent()->getPluginURI().data();
URI_INDEX_MAP[std::string(plug->getInfoComponent()->getPluginURI())] =
index;
// LV2_Descriptor desc = lv2DescriptorArray.at(lv2DescriptorArray.size() -
// 1);
desc->activate = [](LV2_Handle instance) {
auto data = static_cast<LV2HandleDataType*>(instance);
data->plug->activate();
......@@ -136,11 +152,11 @@ extern "C"
if (midiPort != nullptr) {
if (supportsMidi(data->plug, midiPort)) {
if (data->midiHandles.capacity() <
getNumberOfPorts<IMidiPort>(
data->plug,
PortDirection::All)) // Resize if vector is not big enough
getNumberOfPorts<IMidiPort>(data->plug, PortDirection::All))
// Resize if vector is not big enough
data->midiHandles.resize(getNumberOfPorts<IMidiPort>(
data->plug, PortDirection::All));
// Allocate for every MIDI Port an Midihandle
data->midiHandles[midiPortIndex] =
MidiHandle{ (LV2_Atom_Sequence*)DataLocation,
midiPort,
......@@ -156,43 +172,27 @@ extern "C"
midiPortIndex++;
return false;
});
/* auto midiPort =
dynamic_cast<IMidiPort*>(data->plug->getPortComponent()->at(IPort)); if
(midiPort != nullptr && (
(data->plug->getFeatureComponent()->supportsFeature(Feature::MidiInput)&&midiPort->getDirection()==PortDirection::Input
) ||
(data->plug->getFeatureComponent()->supportsFeature(Feature::MidiOutput)
&& midiPort->getDirection() == PortDirection::Output)
)) {
data->midiHandles.push_back( MidiHandle{
(LV2_Atom_Sequence*)DataLocation,
midiPort,
data->map->map(data->map->handle, LV2_MIDI__MidiEvent)
});
}
else {
getAudioChannelFromIndex(data->plug,
IPort)->feed((float*)DataLocation);
}*/
// midiData->body.
};
desc->instantiate = [](const LV2_Descriptor* descriptor,
double,
const char*,
const LV2_Feature* const* features) -> LV2_Handle {
// map an uri to an id, to use it with the internal API
auto descriptorIndex = URI_INDEX_MAP[std::string(descriptor->URI)];
GlobalData().getPlugin(descriptorIndex)->init();
auto lv2Handle = new LV2HandleDataType{
GlobalData().getPlugin(descriptorIndex).get(), descriptor, nullptr, {}
};
// Get The URID_Map feature, which is needed to use with midi.
for (int i = 0; features[i]; ++i) {
if (!strcmp(features[i]->URI, LV2_URID__map)) {
lv2Handle->map = (LV2_URID_Map*)features[i]->data;
break;
}
}
// When the map feature is not present, we cant instantiate... Maybe skip
// this, if its not absolutly neccessary.