Debug Chorus and Delay.

This commit is contained in:
Robin Davies
2022-03-17 23:08:09 -04:00
parent 4f6f504e2e
commit 80d0712614
5 changed files with 292 additions and 101 deletions
+54 -3
View File
@@ -25,7 +25,7 @@ import createStyles from '@mui/styles/createStyles';
import withStyles from '@mui/styles/withStyles'; import withStyles from '@mui/styles/withStyles';
import IControlViewFactory from './IControlViewFactory'; import IControlViewFactory from './IControlViewFactory';
import { PiPedalModelFactory, PiPedalModel } from "./PiPedalModel"; import { PiPedalModelFactory, PiPedalModel,MonitorPortHandle } from "./PiPedalModel";
import { PedalBoardItem } from './PedalBoard'; import { PedalBoardItem } from './PedalBoard';
import PluginControlView, { ControlGroup,ControlViewCustomization } from './PluginControlView'; import PluginControlView, { ControlGroup,ControlViewCustomization } from './PluginControlView';
import ToobFrequencyResponseView from './ToobFrequencyResponseView'; import ToobFrequencyResponseView from './ToobFrequencyResponseView';
@@ -41,7 +41,7 @@ interface ToobMLProps extends WithStyles<typeof styles> {
} }
interface ToobMLState { interface ToobMLState {
gainEnabled: boolean;
} }
const ToobMLView = const ToobMLView =
@@ -50,22 +50,73 @@ const ToobMLView =
implements ControlViewCustomization implements ControlViewCustomization
{ {
model: PiPedalModel; model: PiPedalModel;
gainRef: React.RefObject<HTMLDivElement>;
customizationId: number = 1; customizationId: number = 1;
constructor(props: ToobMLProps) { constructor(props: ToobMLProps) {
super(props); super(props);
this.model = PiPedalModelFactory.getInstance(); this.model = PiPedalModelFactory.getInstance();
this.gainRef = React.createRef();
this.state = { this.state = {
gainEnabled: true
} }
} }
subscribedId?: number = undefined;
monitorPortHandle?: MonitorPortHandle = undefined;
removeGainEnabledSubscription()
{
if (this.monitorPortHandle)
{
this.model.unmonitorPort(this.monitorPortHandle);
this.monitorPortHandle = undefined;
}
}
addGainEnabledSubscription(instanceId: number)
{
this.removeGainEnabledSubscription();
this.monitorPortHandle = this.model.monitorPort(instanceId,"gainEnabled",0.1,
(value: number) => {
if (this.gainRef.current)
{
this.gainRef.current.style.opacity = value !== 0.0? "1.0": "0.4";
}
this.setState({gainEnabled: value !== 0.0 });
});
}
componentDidUpdate()
{
if (this.props.instanceId !== this.subscribedId)
{
this.removeGainEnabledSubscription();
this.addGainEnabledSubscription(this.props.instanceId);
}
}
componentDidMount()
{
this.addGainEnabledSubscription(this.props.instanceId);
}
componentWillUnmount()
{
this.removeGainEnabledSubscription();
}
ModifyControls(controls: (React.ReactNode| ControlGroup)[]): (React.ReactNode| ControlGroup)[] ModifyControls(controls: (React.ReactNode| ControlGroup)[]): (React.ReactNode| ControlGroup)[]
{ {
let group = controls[1] as ControlGroup; let group = controls[4] as ControlGroup;
group.controls.splice(0,0, group.controls.splice(0,0,
( <ToobFrequencyResponseView instanceId={this.props.instanceId} minDb={-20} maxDb={20} />) ( <ToobFrequencyResponseView instanceId={this.props.instanceId} minDb={-20} maxDb={20} />)
); );
let gainControl: React.ReactElement = controls[3] as React.ReactElement;
if (gainControl)
{
controls[3] = (<div ref={this.gainRef}> { gainControl} </div>);
}
return controls; return controls;
} }
render() { render() {
+1
View File
@@ -102,6 +102,7 @@ add_custom_command(
set (PIPEDAL_SOURCES set (PIPEDAL_SOURCES
StdOutCapture.hpp StdOutCapture.cpp
Ipv6Helpers.cpp Ipv6Helpers.hpp Ipv6Helpers.cpp Ipv6Helpers.hpp
PluginPreset.cpp PluginPreset.hpp PluginPreset.cpp PluginPreset.hpp
CpuGovernor.cpp CpuGovernor.hpp CpuGovernor.cpp CpuGovernor.hpp
+30 -33
View File
@@ -41,10 +41,10 @@
#include "lv2/lv2plug.in/ns/ext/port-groups/port-groups.h" #include "lv2/lv2plug.in/ns/ext/port-groups/port-groups.h"
#include <fstream> #include <fstream>
#include "PiPedalException.hpp" #include "PiPedalException.hpp"
#include "StdOutCapture.hpp"
#include "Locale.hpp" #include "Locale.hpp"
using namespace pipedal; using namespace pipedal;
#define MAP_CHECK() \ #define MAP_CHECK() \
@@ -85,8 +85,8 @@ namespace pipedal
static const char *LV2_MIDI_EVENT = "http://lv2plug.in/ns/ext/midi#MidiEvent"; static const char *LV2_MIDI_EVENT = "http://lv2plug.in/ns/ext/midi#MidiEvent";
static const char *LV2_DESIGNATION = "http://lv2plug.in/ns/lv2core#Designation"; static const char *LV2_DESIGNATION = "http://lv2plug.in/ns/lv2core#Designation";
class Lv2Host::Urids
class Lv2Host::Urids { {
public: public:
Urids(MapFeature &mapFeature) Urids(MapFeature &mapFeature)
{ {
@@ -96,8 +96,6 @@ namespace pipedal
}; };
} }
void Lv2Host::LilvUris::Initialize(LilvWorld *pWorld) void Lv2Host::LilvUris::Initialize(LilvWorld *pWorld)
{ {
rdfsComment = lilv_new_uri(pWorld, Lv2Host::RDFS_COMMENT_URI); rdfsComment = lilv_new_uri(pWorld, Lv2Host::RDFS_COMMENT_URI);
@@ -124,9 +122,6 @@ void Lv2Host::LilvUris::Initialize(LilvWorld*pWorld)
time_speed = lilv_new_uri(pWorld, LV2_TIME__speed); time_speed = lilv_new_uri(pWorld, LV2_TIME__speed);
appliesTo = lilv_new_uri(pWorld, LV2_CORE__appliesTo); appliesTo = lilv_new_uri(pWorld, LV2_CORE__appliesTo);
} }
void Lv2Host::LilvUris::Free() void Lv2Host::LilvUris::Free()
@@ -385,6 +380,7 @@ void Lv2Host::LoadPluginClassesFromLilv()
void Lv2Host::Load(const char *lv2Path) void Lv2Host::Load(const char *lv2Path)
{ {
this->plugins_.clear(); this->plugins_.clear();
this->ui_plugins_.clear(); this->ui_plugins_.clear();
if (!classesLoaded) if (!classesLoaded)
@@ -395,16 +391,20 @@ void Lv2Host::Load(const char *lv2Path)
free_world(); free_world();
setenv("LV2_PATH", lv2Path, true); setenv("LV2_PATH", lv2Path, true);
StdOutCapture stdoutCapture; // captures lilv messages written to STDOUT.
pWorld = lilv_world_new(); pWorld = lilv_world_new();
{
lilv_world_load_all(pWorld); lilv_world_load_all(pWorld);
}
lilvUris.Initialize(pWorld); lilvUris.Initialize(pWorld);
const LilvPlugins *plugins = lilv_world_get_all_plugins(pWorld); const LilvPlugins *plugins = lilv_world_get_all_plugins(pWorld);
LoadPluginClassesFromLilv(); LoadPluginClassesFromLilv();
LILV_FOREACH(plugins, iPlugin, plugins) LILV_FOREACH(plugins, iPlugin, plugins)
{ {
const LilvPlugin *lilvPlugin = lilv_plugins_get(plugins, iPlugin); const LilvPlugin *lilvPlugin = lilv_plugins_get(plugins, iPlugin);
@@ -441,6 +441,12 @@ void Lv2Host::Load(const char *lv2Path)
this->plugins_.push_back(pluginInfo); this->plugins_.push_back(pluginInfo);
} }
} }
auto messages = stdoutCapture.GetOutputLines();
for (const std::string & s: messages)
{
Lv2Log::info("lilv: " + s);
}
const auto &collation = std::use_facet<std::collate<char>>(std::locale()); const auto &collation = std::use_facet<std::collate<char>>(std::locale());
auto compare = [&collation]( auto compare = [&collation](
@@ -485,7 +491,8 @@ void Lv2Host::Load(const char *lv2Path)
} }
} }
} }
}; }
;
class NodesAutoFree class NodesAutoFree
{ {
@@ -628,9 +635,7 @@ Lv2PluginInfo::Lv2PluginInfo(Lv2Host *lv2Host, const LilvPlugin *pPlugin)
std::sort(ports_.begin(), ports_.end(), ports_sort_compare); std::sort(ports_.begin(), ports_.end(), ports_sort_compare);
this->is_valid_ = isValid; this->is_valid_ = isValid;
} }
std::vector<std::string> supportedFeatures = { std::vector<std::string> supportedFeatures = {
@@ -780,7 +785,6 @@ Lv2PortInfo::Lv2PortInfo(Lv2Host *host, const LilvPlugin *plugin, const LilvPort
NodeAutoFree unitsValueUri = lilv_port_get(plugin, pPort, host->lilvUris.unitsUri); NodeAutoFree unitsValueUri = lilv_port_get(plugin, pPort, host->lilvUris.unitsUri);
this->units_ = UriToUnits(nodeAsString(unitsValueUri)); this->units_ = UriToUnits(nodeAsString(unitsValueUri));
NodeAutoFree bufferType = lilv_port_get(plugin, pPort, host->lilvUris.bufferType_uri); NodeAutoFree bufferType = lilv_port_get(plugin, pPort, host->lilvUris.bufferType_uri);
this->buffer_type_ = ""; this->buffer_type_ = "";
@@ -929,7 +933,6 @@ std::shared_ptr<Lv2PluginInfo> Lv2Host::GetPluginInfo(const std::string &uri) co
return nullptr; return nullptr;
} }
Lv2PedalBoard *Lv2Host::CreateLv2PedalBoard(const PedalBoard &pedalBoard) Lv2PedalBoard *Lv2Host::CreateLv2PedalBoard(const PedalBoard &pedalBoard)
{ {
Lv2PedalBoard *pPedalBoard = new Lv2PedalBoard(); Lv2PedalBoard *pPedalBoard = new Lv2PedalBoard();
@@ -945,8 +948,8 @@ Lv2PedalBoard *Lv2Host::CreateLv2PedalBoard(const PedalBoard &pedalBoard)
} }
} }
struct StateCallbackData
struct StateCallbackData { {
Lv2Host *pHost; Lv2Host *pHost;
std::vector<ControlValue> *pResult; std::vector<ControlValue> *pResult;
}; };
@@ -966,11 +969,8 @@ void Lv2Host::fn_LilvSetPortValueFunc(const char* port_symbol,
throw PiPedalStateException("Preset format not supported."); throw PiPedalStateException("Preset format not supported.");
} }
pResult->push_back(ControlValue(port_symbol, *(float *)value)); pResult->push_back(ControlValue(port_symbol, *(float *)value));
} }
std::vector<ControlValue> Lv2Host::LoadFactoryPluginPreset( std::vector<ControlValue> Lv2Host::LoadFactoryPluginPreset(
PedalBoardItem *pedalBoardItem, const std::string &presetUri) PedalBoardItem *pedalBoardItem, const std::string &presetUri)
{ {
@@ -989,9 +989,9 @@ std::vector<ControlValue> Lv2Host::LoadFactoryPluginPreset(
throw PiPedalStateException("No such plugin."); throw PiPedalStateException("No such plugin.");
} }
LilvNodes *presets = lilv_plugin_get_related(plugin, lilvUris.pset_Preset); LilvNodes *presets = lilv_plugin_get_related(plugin, lilvUris.pset_Preset);
LILV_FOREACH(nodes, i, presets) { LILV_FOREACH(nodes, i, presets)
{
const LilvNode *preset = lilv_nodes_get(presets, i); const LilvNode *preset = lilv_nodes_get(presets, i);
lilv_world_load_resource(pWorld, preset); lilv_world_load_resource(pWorld, preset);
@@ -1001,7 +1001,6 @@ std::vector<ControlValue> Lv2Host::LoadFactoryPluginPreset(
/*********************************/ /*********************************/
// NodeAutoFree uriNode = lilv_new_uri(pWorld, presetUri.c_str()); // NodeAutoFree 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);
@@ -1011,7 +1010,6 @@ std::vector<ControlValue> Lv2Host::LoadFactoryPluginPreset(
throw PiPedalStateException("Preset not found."); throw PiPedalStateException("Preset not found.");
} }
StateCallbackData cbData; StateCallbackData cbData;
cbData.pHost = this; cbData.pHost = this;
cbData.pResult = &result; cbData.pResult = &result;
@@ -1023,14 +1021,14 @@ std::vector<ControlValue> Lv2Host::LoadFactoryPluginPreset(
/*********************************/ /*********************************/
} }
} }
lilv_nodes_free(presets); lilv_nodes_free(presets);
return result; return result;
} }
struct PresetCallbackState { struct PresetCallbackState
{
Lv2Host *pHost; Lv2Host *pHost;
std::map<std::string, float> *values; std::map<std::string, float> *values;
bool failed = false; bool failed = false;
@@ -1044,7 +1042,9 @@ void Lv2Host::PortValueCallback(const char*symbol,void*user_data,const void* val
if (type == pHost->urids->atom_Float) if (type == pHost->urids->atom_Float)
{ {
(*pState->values)[symbol] = *static_cast<const float *>(value); (*pState->values)[symbol] = *static_cast<const float *>(value);
} else { }
else
{
pState->failed = true; pState->failed = true;
} }
} }
@@ -1066,7 +1066,8 @@ PluginPresets Lv2Host::GetFactoryPluginPresets(const std::string &pluginUri)
result.pluginUri_ = pluginUri; result.pluginUri_ = pluginUri;
LilvNodes *presets = lilv_plugin_get_related(plugin, lilvUris.pset_Preset); LilvNodes *presets = lilv_plugin_get_related(plugin, lilvUris.pset_Preset);
LILV_FOREACH(nodes, i, presets) { LILV_FOREACH(nodes, i, presets)
{
const LilvNode *preset = lilv_nodes_get(presets, i); const LilvNode *preset = lilv_nodes_get(presets, i);
lilv_world_load_resource(pWorld, preset); lilv_world_load_resource(pWorld, preset);
@@ -1087,15 +1088,14 @@ PluginPresets Lv2Host::GetFactoryPluginPresets(const std::string &pluginUri)
} }
lilv_nodes_free(presets); lilv_nodes_free(presets);
return result; return result;
} }
Lv2Effect *Lv2Host::CreateEffect(const PedalBoardItem &pedalBoardItem) Lv2Effect *Lv2Host::CreateEffect(const PedalBoardItem &pedalBoardItem)
{ {
auto info = this->GetPluginInfo(pedalBoardItem.uri()); auto info = this->GetPluginInfo(pedalBoardItem.uri());
if (!info) return nullptr; if (!info)
return nullptr;
return new Lv2Effect(this, info, pedalBoardItem); return new Lv2Effect(this, info, pedalBoardItem);
} }
@@ -1112,8 +1112,6 @@ Lv2PortGroup::Lv2PortGroup(Lv2Host *lv2Host, const std::string &groupUri)
name_ = nodeAsString(nameNode); name_ = nodeAsString(nameNode);
} }
#define MAP_REF(class, name) \ #define MAP_REF(class, name) \
json_map::reference(#name, &class ::name##_) json_map::reference(#name, &class ::name##_)
@@ -1246,4 +1244,3 @@ json_map::storage_type<Lv2PluginUiPortGroup> Lv2PluginUiPortGroup::jmap{{
MAP_REF(Lv2PluginUiPortGroup, symbol), MAP_REF(Lv2PluginUiPortGroup, symbol),
MAP_REF(Lv2PluginUiPortGroup, name), MAP_REF(Lv2PluginUiPortGroup, name),
}}; }};
+100
View File
@@ -0,0 +1,100 @@
// Copyright (c) 2022 Robin Davies
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "StdOutCapture.hpp"
#include <cstdio>
#include <unistd.h>
#include <fcntl.h>
#include <filesystem>
#include <sstream>
#include <fstream>
#include <sys/stat.h>
#ifdef __WIN32__
#define dup _dup
#define dup2 _dup2
#endif
using namespace pipedal;
constexpr int STDOUT_HANDLE = 2;
StdOutCapture::StdOutCapture()
{
this->tempFileName = std::tmpnam(nullptr);
int redirectHandle = open(tempFileName.c_str(),O_CREAT | O_WRONLY | O_TRUNC);
this->oldStdout = dup(STDOUT_HANDLE);
dup2(redirectHandle,STDOUT_HANDLE);
close(redirectHandle);
}
StdOutCapture::~StdOutCapture()
{
EndCapture();
if (tempFileName.length() != 0)
{
remove(tempFileName.c_str());
}
}
void StdOutCapture::EndCapture()
{
if (this->oldStdout != -1)
{
dup2(this->oldStdout,STDOUT_HANDLE);
close(this->oldStdout);
this->oldStdout = -1;
chmod(this->tempFileName.c_str(),0644);
}
}
std::vector<std::string> StdOutCapture::GetOutputLines() {
EndCapture();
std::vector<std::string> result;
std::ifstream f(this->tempFileName);
if (f.is_open())
{
char buffer[1024];
std::string line;
while (true)
{
if (f.eof())
{
break;
}
std::getline(f,line);
if (f.fail()) break;
if (line.length() != 0)
{
result.push_back(line);
}
}
}
return result;
}
+42
View File
@@ -0,0 +1,42 @@
// Copyright (c) 2022 Robin Davies
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
#include <string>
namespace pipedal {
class StdOutCapture {
public:
StdOutCapture();
~StdOutCapture();
void EndCapture();
std::vector<std::string> GetOutputLines();
private:
std::string tempFileName;
int oldStdout = -1;
};
} // namespace