Toob Flanger, Stereo Reverb, bug fixes

- support state in factory presets.
- Use uncompressed json for settings files.
- Set current plugin preset name to last loaded plugin preset.
- Append plugins after  start node,  before end node fixed.
- Correctly release web socket when web app goes idle.
- Fit and finish issues.
This commit is contained in:
Robin Davies
2023-06-07 04:57:13 -04:00
parent 9dcbf3d00b
commit a3dca9fa5c
133 changed files with 2715 additions and 998 deletions
+203 -189
View File
@@ -30,10 +30,10 @@
#include "Lv2Pedalboard.hpp"
#include "OptionsFeature.hpp"
#include "JackConfiguration.hpp"
#include "lv2/urid.lv2/urid.h"
#include "lv2/ui.lv2/ui.h"
#include "lv2.h"
#include "lv2/atom.lv2/atom.h"
#include "lv2/urid/urid.h"
#include "lv2/ui/ui.h"
//#include "lv2.h"
#include "lv2/atom/atom.h"
#include "lv2/time/time.h"
#include "lv2/state/state.h"
#include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h"
@@ -71,20 +71,23 @@ namespace pipedal
static const char *LV2_MIDI_PLUGIN = "http://lv2plug.in/ns/lv2core#MIDIPlugin";
class PluginHost::Urids
{
public:
Urids(MapFeature &mapFeature)
{
atom_Float = mapFeature.GetUrid(LV2_ATOM__Float);
atom__Float = mapFeature.GetUrid(LV2_ATOM__Float);
atom__Double = mapFeature.GetUrid(LV2_ATOM__Double);
atom_Int = mapFeature.GetUrid(LV2_ATOM__Int);
ui__portNotification = mapFeature.GetUrid(LV2_UI__portNotification);
ui__plugin = mapFeature.GetUrid(LV2_UI__plugin);
ui__protocol = mapFeature.GetUrid(LV2_UI__protocol);
ui__floatProtocol = mapFeature.GetUrid(LV2_UI__protocol);
ui__peakProtocol = mapFeature.GetUrid(LV2_UI__peakProtocol);
}
LV2_URID atom_Float;
LV2_URID atom__Float;
LV2_URID atom__Double;
LV2_URID atom_Int;
LV2_URID ui__portNotification;
LV2_URID ui__plugin;
LV2_URID ui__protocol;
@@ -103,33 +106,33 @@ void PluginHost::SetConfiguration(const PiPedalConfiguration &configuration)
void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
{
rdfs__Comment = lilv_new_uri(pWorld, PluginHost::RDFS__comment);
rdfs__range = lilv_new_uri(pWorld,PluginHost::RDFS__range);
rdfs__range = lilv_new_uri(pWorld, PluginHost::RDFS__range);
port_logarithmic = lilv_new_uri(pWorld, LV2_PORT_PROPS__logarithmic);
port__display_priority = lilv_new_uri(pWorld, LV2_PORT_PROPS__displayPriority);
port_range_steps = lilv_new_uri(pWorld, LV2_PORT_PROPS__rangeSteps);
integer_property_uri = lilv_new_uri(pWorld, LV2_CORE__integer);
enumeration_property_uri = lilv_new_uri(pWorld, LV2_CORE__enumeration);
core__toggled = lilv_new_uri(pWorld, LV2_CORE__toggled);
core__connectionOptional = lilv_new_uri(pWorld,LV2_CORE__connectionOptional);
core__connectionOptional = lilv_new_uri(pWorld, LV2_CORE__connectionOptional);
portprops__not_on_gui_property_uri = lilv_new_uri(pWorld, LV2_PORT_PROPS__notOnGUI);
midi__event = lilv_new_uri(pWorld, LV2_MIDI__MidiEvent);
core__designation = lilv_new_uri(pWorld, LV2_CORE__designation);
portgroups__group = lilv_new_uri(pWorld, LV2_PORT_GROUPS__group);
units__unit = lilv_new_uri(pWorld, LV2_UNITS__unit);
invada_units__unit = lilv_new_uri(pWorld, "http://lv2plug.in/ns/extension/units#unit"); // a typo in invada plugin ttl files.
invada_units__unit = lilv_new_uri(pWorld, "http://lv2plug.in/ns/extension/units#unit"); // a typo in invada plugin ttl files.
invada_portprops__logarithmic = lilv_new_uri(pWorld, "http://lv2plug.in/ns/dev/extportinfo#logarithmic"); // a typo in invada plugin ttl files.
atom__bufferType = lilv_new_uri(pWorld, LV2_ATOM__bufferType);
atom__Path = lilv_new_uri(pWorld, LV2_ATOM__Path);
presets__preset = lilv_new_uri(pWorld, LV2_PRESETS__Preset);
state__state = lilv_new_uri(pWorld,LV2_STATE__state);
rdfs__label = lilv_new_uri(pWorld, LILV_NS_RDFS "label");
lv2core__symbol = lilv_new_uri(pWorld, LV2_CORE__symbol);
lv2core__name = lilv_new_uri(pWorld, LV2_CORE__name);
lv2core__index = lilv_new_uri(pWorld, LV2_CORE__index);
lv2core__Parameter = lilv_new_uri(pWorld,LV2_CORE_PREFIX "Parameter");
lv2core__Parameter = lilv_new_uri(pWorld, LV2_CORE_PREFIX "Parameter");
pipedalUI__ui = lilv_new_uri(pWorld, PIPEDAL_UI__ui);
pipedalUI__fileProperties = lilv_new_uri(pWorld, PIPEDAL_UI__fileProperties);
@@ -142,16 +145,14 @@ void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
pipedalUI__outputPorts = lilv_new_uri(pWorld, PIPEDAL_UI__outputPorts);
pipedalUI__text = lilv_new_uri(pWorld, PIPEDAL_UI__text);
ui__portNotification = lilv_new_uri(pWorld, LV2_UI__portNotification);
ui__plugin = lilv_new_uri(pWorld, LV2_UI__plugin);
ui__protocol = lilv_new_uri(pWorld, LV2_UI__protocol);
ui__floatProtocol = lilv_new_uri(pWorld, LV2_UI__protocol);
ui__peakProtocol = lilv_new_uri(pWorld, LV2_UI__peakProtocol);
ui__portIndex = lilv_new_uri(pWorld,LV2_UI__portIndex);
lv2__symbol = lilv_new_uri(pWorld,LV2_CORE__symbol);
ui__portIndex = lilv_new_uri(pWorld, LV2_UI__portIndex);
lv2__symbol = lilv_new_uri(pWorld, LV2_CORE__symbol);
lv2__port = lilv_new_uri(pWorld, LV2_CORE__port);
// ui:portNotification
// [
@@ -170,11 +171,10 @@ void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
appliesTo = lilv_new_uri(pWorld, LV2_CORE__appliesTo);
patch__writable = lilv_new_uri(pWorld,LV2_PATCH__writable);
patch__readable = lilv_new_uri(pWorld,LV2_PATCH__readable);
patch__writable = lilv_new_uri(pWorld, LV2_PATCH__writable);
patch__readable = lilv_new_uri(pWorld, LV2_PATCH__readable);
dc__format = lilv_new_uri(pWorld, "http://purl.org/dc/terms/format");
}
void PluginHost::LilvUris::Free()
@@ -355,14 +355,14 @@ void PluginHost::LoadPluginClassesFromLilv()
if (lv2Class && lv2Class->parent_uri().size() != 0)
{
std::shared_ptr<Lv2PluginClass> parentClass = GetPluginClass(lv2Class->parent_uri());
if (parentClass)
{
Lv2PluginClass *ccClass = const_cast<Lv2PluginClass *>(lv2Class.get());
ccClass->set_parent(parentClass);
Lv2PluginClass *ccParentClass = parentClass.get();
ccParentClass->add_child(lv2Class);
}
std::shared_ptr<Lv2PluginClass> parentClass = GetPluginClass(lv2Class->parent_uri());
if (parentClass)
{
Lv2PluginClass *ccClass = const_cast<Lv2PluginClass *>(lv2Class.get());
ccClass->set_parent(parentClass);
Lv2PluginClass *ccParentClass = parentClass.get();
ccParentClass->add_child(lv2Class);
}
}
}
}
@@ -405,30 +405,30 @@ void PluginHost::Load(const char *lv2Path)
if (pluginInfo->hasCvPorts())
{
Lv2Log::debug("Plugin %s (%s) skipped. (Has CV ports).", pluginInfo->name().c_str(), pluginInfo->uri().c_str());
Lv2Log::debug("Plugin %s (%s) skipped. (Has CV ports).", pluginInfo->name().c_str(), pluginInfo->uri().c_str());
}
#if !SUPPORT_MIDI
else if (pluginInfo->plugin_class() == LV2_MIDI_PLUGIN)
{
Lv2Log::debug("Plugin %s (%s) skipped. (MIDI Plugin).", pluginInfo->name().c_str(), pluginInfo->uri().c_str());
Lv2Log::debug("Plugin %s (%s) skipped. (MIDI Plugin).", pluginInfo->name().c_str(), pluginInfo->uri().c_str());
}
#endif
else if (!pluginInfo->is_valid())
{
auto &ports = pluginInfo->ports();
for (int i = 0; i < ports.size(); ++i)
auto &ports = pluginInfo->ports();
for (int i = 0; i < ports.size(); ++i)
{
auto &port = ports[i];
if (!port->is_valid())
{
auto &port = ports[i];
if (!port->is_valid())
{
Lv2Log::debug("Plugin port %s:%s is invalid.", pluginInfo->name().c_str(), port->name().c_str());
}
Lv2Log::debug("Plugin port %s:%s is invalid.", pluginInfo->name().c_str(), port->name().c_str());
}
Lv2Log::debug("Plugin %s (%s) skipped. Not valid.", pluginInfo->name().c_str(), pluginInfo->uri().c_str());
}
Lv2Log::debug("Plugin %s (%s) skipped. Not valid.", pluginInfo->name().c_str(), pluginInfo->uri().c_str());
}
else
{
this->plugins_.push_back(pluginInfo);
this->plugins_.push_back(pluginInfo);
}
}
auto messages = stdoutCapture.GetOutputLines();
@@ -457,28 +457,28 @@ void PluginHost::Load(const char *lv2Path)
if (plugin->is_valid())
{
#if SUPPORT_MIDI
if (info.audio_inputs() == 0 && !info.has_midi_input())
{
Lv2Log::debug("Plugin %s (%s) skipped. No inputs.", plugin->name().c_str(), plugin->uri().c_str());
}
else if (info.audio_outputs() == 0 && !info.has_midi_output())
{
Lv2Log::debug("Plugin %s (%s) skipped. No audio outputs.", plugin->name().c_str(), plugin->uri().c_str());
}
if (info.audio_inputs() == 0 && !info.has_midi_input())
{
Lv2Log::debug("Plugin %s (%s) skipped. No inputs.", plugin->name().c_str(), plugin->uri().c_str());
}
else if (info.audio_outputs() == 0 && !info.has_midi_output())
{
Lv2Log::debug("Plugin %s (%s) skipped. No audio outputs.", plugin->name().c_str(), plugin->uri().c_str());
}
#else
if (info.audio_inputs() == 0)
{
Lv2Log::debug("Plugin %s (%s) skipped. No audio inputs.", plugin->name().c_str(), plugin->uri().c_str());
}
else if (info.audio_outputs() == 0)
{
Lv2Log::debug("Plugin %s (%s) skipped. No audio outputs.", plugin->name().c_str(), plugin->uri().c_str());
}
if (info.audio_inputs() == 0)
{
Lv2Log::debug("Plugin %s (%s) skipped. No audio inputs.", plugin->name().c_str(), plugin->uri().c_str());
}
else if (info.audio_outputs() == 0)
{
Lv2Log::debug("Plugin %s (%s) skipped. No audio outputs.", plugin->name().c_str(), plugin->uri().c_str());
}
#endif
else
{
ui_plugins_.push_back(std::move(info));
}
else
{
ui_plugins_.push_back(std::move(info));
}
}
}
@@ -493,8 +493,8 @@ void PluginHost::Load(const char *lv2Path)
const auto &vst3PluginList = this->vst3Host->getPluginList();
for (const auto &vst3Plugin : vst3PluginList)
{
// copy not move!
ui_plugins_.push_back(vst3Plugin->pluginInfo_);
// copy not move!
ui_plugins_.push_back(vst3Plugin->pluginInfo_);
}
auto ui_compare = [&collation](
Lv2PluginUiInfo &left,
@@ -511,7 +511,6 @@ void PluginHost::Load(const char *lv2Path)
#endif
};
static std::vector<std::string> nodeAsStringArray(const LilvNodes *nodes)
{
std::vector<std::string> result;
@@ -523,12 +522,10 @@ static std::vector<std::string> nodeAsStringArray(const LilvNodes *nodes)
}
const char *PluginHost::RDFS__comment = "http://www.w3.org/2000/01/rdf-schema#"
"comment";
"comment";
const char *PluginHost::RDFS__range = "http://www.w3.org/2000/01/rdf-schema#"
"range";
"range";
LilvNode *PluginHost::get_comment(const std::string &uri)
{
@@ -554,20 +551,20 @@ bool Lv2PluginInfo::HasFactoryPresets(PluginHost *lv2Host, const LilvPlugin *plu
return result;
}
std::shared_ptr<PiPedalUI> Lv2PluginInfo::FindWritablePathProperties(PluginHost *lv2Host,const LilvPlugin*pPlugin)
std::shared_ptr<PiPedalUI> Lv2PluginInfo::FindWritablePathProperties(PluginHost *lv2Host, const LilvPlugin *pPlugin)
{
// example:
// example:
// <http://github.com/mikeoliphant/neural-amp-modeler-lv2#model>
// a lv2:Parameter;
// rdfs:label "Model";
// rdfs:range atom:Path.
// ...
// patch:writable <http://github.com/mikeoliphant/neural-amp-modeler-lv2#model>;
// ...
// patch:writable <http://github.com/mikeoliphant/neural-amp-modeler-lv2#model>;
LilvWorld* pWorld = lv2Host->getWorld();
LilvWorld *pWorld = lv2Host->getWorld();
AutoLilvNode pluginUri = lilv_plugin_get_uri(pPlugin);
AutoLilvNodes patchWritables = lilv_world_find_nodes(pWorld,pluginUri,lv2Host->lilvUris.patch__writable,nullptr);
AutoLilvNodes patchWritables = lilv_world_find_nodes(pWorld, pluginUri, lv2Host->lilvUris.patch__writable, nullptr);
std::vector<UiFileProperty::ptr> fileProperties;
@@ -576,13 +573,13 @@ std::shared_ptr<PiPedalUI> Lv2PluginInfo::FindWritablePathProperties(PluginHost
AutoLilvNode propertyUri = lilv_nodes_get(patchWritables, iNode);
if (propertyUri)
{
// isA lv2:Parameter?
if (lilv_world_ask(pWorld,propertyUri,lv2Host->lilvUris.isA,lv2Host->lilvUris.lv2core__Parameter))
// isA lv2:Parameter?
if (lilv_world_ask(pWorld, propertyUri, lv2Host->lilvUris.isA, lv2Host->lilvUris.lv2core__Parameter))
{
// rfs:range atom:Path?
if (lilv_world_ask(pWorld,propertyUri,lv2Host->lilvUris.rdfs__range,lv2Host->lilvUris.atom__Path))
if (lilv_world_ask(pWorld, propertyUri, lv2Host->lilvUris.rdfs__range, lv2Host->lilvUris.atom__Path))
{
AutoLilvNode label = lilv_world_get(pWorld,propertyUri,lv2Host->lilvUris.rdfs__label,nullptr);
AutoLilvNode label = lilv_world_get(pWorld, propertyUri, lv2Host->lilvUris.rdfs__label, nullptr);
std::string strLabel = label.AsString();
if (strLabel.length() != 0)
{
@@ -591,33 +588,25 @@ std::shared_ptr<PiPedalUI> Lv2PluginInfo::FindWritablePathProperties(PluginHost
std::string lv2DirectoryName = path.filename().string();
// we have a valid path property!
auto fileProperty =
std::make_shared<UiFileProperty>(
strLabel, propertyUri.AsUri(), lv2DirectoryName);
auto fileProperty =
std::make_shared<UiFileProperty>(
strLabel,propertyUri.AsUri(),lv2DirectoryName);
AutoLilvNodes dc_types = lilv_world_find_nodes(pWorld,propertyUri,lv2Host->lilvUris.dc__format,nullptr);
AutoLilvNodes dc_types = lilv_world_find_nodes(pWorld, propertyUri, lv2Host->lilvUris.dc__format, nullptr);
LILV_FOREACH(nodes, i, dc_types)
{
AutoLilvNode dc_type = lilv_nodes_get(dc_types,i);
AutoLilvNode dc_type = lilv_nodes_get(dc_types, i);
std::string fileType = dc_type.AsString();
std::string label = "";
fileProperty->fileTypes().push_back(UiFileType(label,fileType));
fileProperty->fileTypes().push_back(UiFileType(label, fileType));
}
fileProperties.push_back(
fileProperty
);
fileProperty);
}
}
}
}
}
if (fileProperties.size() != 0)
{
@@ -625,7 +614,6 @@ std::shared_ptr<PiPedalUI> Lv2PluginInfo::FindWritablePathProperties(PluginHost
}
return std::shared_ptr<PiPedalUI>();
}
Lv2PluginInfo::Lv2PluginInfo(PluginHost *lv2Host, LilvWorld *pWorld, const LilvPlugin *pPlugin)
@@ -685,15 +673,15 @@ Lv2PluginInfo::Lv2PluginInfo(PluginHost *lv2Host, LilvWorld *pWorld, const LilvP
std::shared_ptr<Lv2PortInfo> portInfo = std::make_shared<Lv2PortInfo>(lv2Host, pPlugin, pPort);
if (!portInfo->is_valid())
{
isValid = false;
isValid = false;
}
const auto &portGroup = portInfo->port_group();
if (portGroup.size() != 0)
{
if (std::find(portGroups.begin(), portGroups.end(), portGroup) == portGroups.end())
{
portGroups.push_back(portGroup);
}
if (std::find(portGroups.begin(), portGroups.end(), portGroup) == portGroups.end())
{
portGroups.push_back(portGroup);
}
}
ports_.push_back(std::move(portInfo));
}
@@ -707,8 +695,8 @@ Lv2PluginInfo::Lv2PluginInfo(PluginHost *lv2Host, LilvWorld *pWorld, const LilvP
{
if (!this->IsSupportedFeature(this->required_features_[i]))
{
Lv2Log::debug("%s (%s) requires feature %s.", this->name_.c_str(), this->uri_.c_str(), this->required_features_[i].c_str());
isValid = false;
Lv2Log::debug("%s (%s) requires feature %s.", this->name_.c_str(), this->uri_.c_str(), this->required_features_[i].c_str());
isValid = false;
}
}
@@ -724,9 +712,11 @@ Lv2PluginInfo::Lv2PluginInfo(PluginHost *lv2Host, LilvWorld *pWorld, const LilvP
if (pipedalUINode)
{
this->piPedalUI_ = std::make_shared<PiPedalUI>(lv2Host, pipedalUINode, std::filesystem::path(bundlePath));
} else {
// look for
this->piPedalUI_ = FindWritablePathProperties(lv2Host,pPlugin);
}
else
{
// look for
this->piPedalUI_ = FindWritablePathProperties(lv2Host, pPlugin);
}
int nInputs = 0;
@@ -788,7 +778,7 @@ bool Lv2PluginInfo::IsSupportedFeature(const std::string &feature) const
for (int i = 0; i < supportedFeatures.size(); ++i)
{
if (supportedFeatures[i] == feature)
return true;
return true;
}
return false;
}
@@ -864,7 +854,7 @@ Lv2PortInfo::Lv2PortInfo(PluginHost *host, const LilvPlugin *plugin, const LilvP
auto priority_node = lilv_nodes_get_first(priority_nodes);
if (priority_node)
{
this->display_priority_ = lilv_node_as_int(priority_node);
this->display_priority_ = lilv_node_as_int(priority_node);
}
}
@@ -875,7 +865,7 @@ Lv2PortInfo::Lv2PortInfo(PluginHost *host, const LilvPlugin *plugin, const LilvP
auto range_steps_node = lilv_nodes_get_first(range_steps_nodes);
if (range_steps_node)
{
this->range_steps_ = lilv_node_as_int(range_steps_node);
this->range_steps_ = lilv_node_as_int(range_steps_node);
}
}
this->integer_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris.integer_property_uri);
@@ -884,7 +874,7 @@ Lv2PortInfo::Lv2PortInfo(PluginHost *host, const LilvPlugin *plugin, const LilvP
this->toggled_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris.core__toggled);
this->not_on_gui_ = lilv_port_has_property(plugin, pPort, host->lilvUris.portprops__not_on_gui_property_uri);
this->connection_optional_ = lilv_port_has_property(plugin,pPort,host->lilvUris.core__connectionOptional);
this->connection_optional_ = lilv_port_has_property(plugin, pPort, host->lilvUris.core__connectionOptional);
LilvScalePoints *pScalePoints = lilv_port_get_scale_points(plugin, pPort);
LILV_FOREACH(scale_points, iSP, pScalePoints)
@@ -921,23 +911,26 @@ Lv2PortInfo::Lv2PortInfo(PluginHost *host, const LilvPlugin *plugin, const LilvP
if (unitsValueUri)
{
this->units_ = UriToUnits(nodeAsString(unitsValueUri));
} else {
}
else
{
// invada plugins use the wrong URI.
AutoLilvNode invadaUnitsValueUri = lilv_port_get(plugin, pPort, host->lilvUris.invada_units__unit);
if (invadaUnitsValueUri)
{
std::string uri = nodeAsString(invadaUnitsValueUri);
static const char*INCORRECT_URI = "http://lv2plug.in/ns/extension/units#";
static const char*CORRECT_URI = "http://lv2plug.in/ns/extensions/units#";
static const char *INCORRECT_URI = "http://lv2plug.in/ns/extension/units#";
static const char *CORRECT_URI = "http://lv2plug.in/ns/extensions/units#";
if (uri.starts_with(INCORRECT_URI))
{
uri = uri.replace(0,strlen(INCORRECT_URI),CORRECT_URI);
uri = uri.replace(0, strlen(INCORRECT_URI), CORRECT_URI);
}
this->units_ = UriToUnits(uri);
} else {
}
else
{
this->units(Units::none);
}
}
AutoLilvNode commentNode = lilv_port_get(plugin, pPort, host->lilvUris.rdfs__Comment);
@@ -963,9 +956,9 @@ Lv2PluginClasses PluginHost::GetPluginPortClass(const LilvPlugin *lilvPlugin, co
{
LILV_FOREACH(nodes, iNode, nodes)
{
const LilvNode *node = lilv_nodes_get(nodes, iNode);
std::string classUri = nodeAsString(node);
result.push_back(classUri);
const LilvNode *node = lilv_nodes_get(nodes, iNode);
std::string classUri = nodeAsString(node);
result.push_back(classUri);
}
}
return Lv2PluginClasses(result);
@@ -994,7 +987,7 @@ bool Lv2PluginClasses::is_a(PluginHost *lv2Plugins, const char *classUri) const
{
if (lv2Plugins->is_a(classUri_, i))
{
return true;
return true;
}
}
return false;
@@ -1038,39 +1031,39 @@ Lv2PluginUiInfo::Lv2PluginUiInfo(PluginHost *pHost, const Lv2PluginInfo *plugin)
}
for (auto port : plugin->ports())
{
if (port->is_input())
{
if (port->is_control_port())
if (port->is_control_port())
{
controls_.push_back(Lv2PluginUiPort(plugin, port.get()));
}
else if (port->is_atom_port())
{
if (port->supports_midi())
{
controls_.push_back(Lv2PluginUiPort(plugin, port.get()));
}
else if (port->is_atom_port())
{
if (port->supports_midi())
{
has_midi_input_ = true;
}
}
else if (port->is_audio_port())
{
++audio_inputs_;
has_midi_input_ = true;
}
}
else if (port->is_audio_port())
{
++audio_inputs_;
}
}
else if (port->is_output())
{
if (port->is_control_port())
{
controls_.push_back(Lv2PluginUiPort(plugin, port.get()));
}
else if (port->is_atom_port() && port->supports_midi())
{
this->has_midi_output_ = true;
}
else if (port->is_audio_port())
{
++audio_outputs_;
}
if (port->is_control_port())
{
controls_.push_back(Lv2PluginUiPort(plugin, port.get()));
}
else if (port->is_atom_port() && port->supports_midi())
{
this->has_midi_output_ = true;
}
else if (port->is_audio_port())
{
++audio_outputs_;
}
}
}
for (auto &portGroup : plugin->port_groups())
@@ -1097,7 +1090,7 @@ std::shared_ptr<Lv2PluginInfo> PluginHost::GetPluginInfo(const std::string &uri)
{
if ((*i)->uri() == uri)
{
return (*i);
return (*i);
}
}
return nullptr;
@@ -1108,7 +1101,7 @@ Lv2Pedalboard *PluginHost::CreateLv2Pedalboard(Pedalboard &pedalboard, Lv2Pedalb
Lv2Pedalboard *pPedalboard = new Lv2Pedalboard();
try
{
pPedalboard->Prepare(this, pedalboard,errorMessages);
pPedalboard->Prepare(this, pedalboard, errorMessages);
return pPedalboard;
}
catch (const std::exception &e)
@@ -1134,7 +1127,7 @@ void PluginHost::fn_LilvSetPortValueFunc(const char *port_symbol,
PluginHost *pHost = pData->pHost;
std::vector<ControlValue> *pResult = pData->pResult;
LV2_URID valueType = (LV2_URID)type;
if (valueType != pHost->urids->atom_Float)
if (valueType != pHost->urids->atom__Float)
{
throw PiPedalStateException("Preset format not supported.");
}
@@ -1169,27 +1162,27 @@ std::vector<ControlValue> PluginHost::LoadFactoryPluginPreset(
if (presetUri == thisPresetUri)
{
/*********************************/
/*********************************/
// AutoLilvNode uriNode = lilv_new_uri(pWorld, presetUri.c_str());
// AutoLilvNode uriNode = lilv_new_uri(pWorld, presetUri.c_str());
auto lilvState = lilv_state_new_from_world(pWorld, GetLv2UridMap(), preset);
auto lilvState = lilv_state_new_from_world(pWorld, GetLv2UridMap(), preset);
if (lilvState == nullptr)
{
throw PiPedalStateException("Preset not found.");
}
if (lilvState == nullptr)
{
throw PiPedalStateException("Preset not found.");
}
StateCallbackData cbData;
cbData.pHost = this;
cbData.pResult = &result;
auto n = lilv_state_get_num_properties(lilvState);
lilv_state_emit_port_values(lilvState, fn_LilvSetPortValueFunc, &cbData);
StateCallbackData cbData;
cbData.pHost = this;
cbData.pResult = &result;
auto n = lilv_state_get_num_properties(lilvState);
lilv_state_emit_port_values(lilvState, fn_LilvSetPortValueFunc, &cbData);
lilv_state_free(lilvState);
break;
lilv_state_free(lilvState);
break;
/*********************************/
/*********************************/
}
}
lilv_nodes_free(presets);
@@ -1209,11 +1202,17 @@ void PluginHost::PortValueCallback(const char *symbol, void *user_data, const vo
PresetCallbackState *pState = static_cast<PresetCallbackState *>(user_data);
PluginHost *pHost = pState->pHost;
if (type == pHost->urids->atom_Float)
if (type == pHost->urids->atom__Double)
{
(*pState->values)[symbol] = (float)(*static_cast<const double *>(value));
} else if (type == pHost->urids->atom__Float)
{
(*pState->values)[symbol] = *static_cast<const float *>(value);
}
else
else if (type == pHost->urids->atom_Int)
{
(*pState->values)[symbol] = *static_cast<const int32_t *>(value);
} else
{
pState->failed = true;
}
@@ -1244,16 +1243,30 @@ PluginPresets PluginHost::GetFactoryPluginPresets(const std::string &pluginUri)
LilvState *state = lilv_state_new_from_world(pWorld, this->mapFeature.GetMap(), preset);
if (state != nullptr)
{
std::string label = lilv_state_get_label(state);
const char *t = this->mapFeature.UridToString(14);
const char *tLabel = lilv_state_get_label(state);
if (tLabel != nullptr)
{
std::string strLabel = tLabel;
std::map<std::string, float> controlValues;
PresetCallbackState cbData{this, &controlValues, false};
lilv_state_emit_port_values(state, PortValueCallback, (void *)&cbData);
int numProperties = lilv_state_get_num_properties(state);
// can't handle std:state part of preset.
if (numProperties == 0)
{
if (!cbData.failed)
{
result.presets_.push_back(PluginPreset(result.nextInstanceId_++, strLabel, controlValues, Lv2PluginState()));
}
} else {
result.presets_.push_back(PluginPreset::MakeLilvPreset(result.nextInstanceId_++, strLabel, controlValues, lilv_node_as_uri(preset)));
}
lilv_state_free(state);
if (!cbData.failed)
{
result.presets_.push_back(PluginPreset(result.nextInstanceId_++, label, controlValues,Lv2PluginState()));
}
}
}
}
lilv_nodes_free(presets);
@@ -1267,13 +1280,13 @@ IEffect *PluginHost::CreateEffect(PedalboardItem &pedalboardItem)
#if ENABLE_VST3
try
{
Vst3Effect::Ptr vst3Plugin = this->vst3Host->CreatePlugin(pedalboardItem, this);
return vst3Plugin.release();
Vst3Effect::Ptr vst3Plugin = this->vst3Host->CreatePlugin(pedalboardItem, this);
return vst3Plugin.release();
}
catch (const std::exception &e)
{
Lv2Log::error(std::string("Failed to create VST3 plugin: ") + e.what());
throw;
Lv2Log::error(std::string("Failed to create VST3 plugin: ") + e.what());
throw;
}
#else
Lv2Log::error(std::string("VST3 support not enabled at compile time."));
@@ -1285,7 +1298,7 @@ IEffect *PluginHost::CreateEffect(PedalboardItem &pedalboardItem)
{
auto info = this->GetPluginInfo(pedalboardItem.uri());
if (!info)
return nullptr;
return nullptr;
return new Lv2Effect(this, info, pedalboardItem);
}
@@ -1443,20 +1456,21 @@ json_map::storage_type<Lv2PluginUiPort> Lv2PluginUiPort::jmap{{
json_map::storage_type<Lv2PluginUiInfo>
Lv2PluginUiInfo::jmap{
{json_map::reference("uri", &Lv2PluginUiInfo::uri_),
json_map::reference("name", &Lv2PluginUiInfo::name_),
json_map::enum_reference("plugin_type", &Lv2PluginUiInfo::plugin_type_, get_plugin_type_enum_converter()),
json_map::reference("plugin_display_type", &Lv2PluginUiInfo::plugin_display_type_),
json_map::reference("author_name", &Lv2PluginUiInfo::author_name_),
json_map::reference("author_homepage", &Lv2PluginUiInfo::author_homepage_),
json_map::reference("audio_inputs", &Lv2PluginUiInfo::audio_inputs_),
json_map::reference("audio_outputs", &Lv2PluginUiInfo::audio_outputs_),
json_map::reference("description", &Lv2PluginUiInfo::description_),
json_map::reference("has_midi_input", &Lv2PluginUiInfo::has_midi_input_),
json_map::reference("has_midi_output", &Lv2PluginUiInfo::has_midi_output_),
json_map::reference("controls", &Lv2PluginUiInfo::controls_),
json_map::reference("port_groups", &Lv2PluginUiInfo::port_groups_),
json_map::reference("is_vst3", &Lv2PluginUiInfo::is_vst3_),
json_map::reference("fileProperties", &Lv2PluginUiInfo::fileProperties_),
json_map::reference("uiPortNotifications", &Lv2PluginUiInfo::uiPortNotifications_),
}};
{
json_map::reference("uri", &Lv2PluginUiInfo::uri_),
json_map::reference("name", &Lv2PluginUiInfo::name_),
json_map::enum_reference("plugin_type", &Lv2PluginUiInfo::plugin_type_, get_plugin_type_enum_converter()),
json_map::reference("plugin_display_type", &Lv2PluginUiInfo::plugin_display_type_),
json_map::reference("author_name", &Lv2PluginUiInfo::author_name_),
json_map::reference("author_homepage", &Lv2PluginUiInfo::author_homepage_),
json_map::reference("audio_inputs", &Lv2PluginUiInfo::audio_inputs_),
json_map::reference("audio_outputs", &Lv2PluginUiInfo::audio_outputs_),
json_map::reference("description", &Lv2PluginUiInfo::description_),
json_map::reference("has_midi_input", &Lv2PluginUiInfo::has_midi_input_),
json_map::reference("has_midi_output", &Lv2PluginUiInfo::has_midi_output_),
json_map::reference("controls", &Lv2PluginUiInfo::controls_),
json_map::reference("port_groups", &Lv2PluginUiInfo::port_groups_),
json_map::reference("is_vst3", &Lv2PluginUiInfo::is_vst3_),
json_map::reference("fileProperties", &Lv2PluginUiInfo::fileProperties_),
json_map::reference("uiPortNotifications", &Lv2PluginUiInfo::uiPortNotifications_),
}};