Lv2 core implementation

Implementation of the Lv2 core, except for CV ports. No features or
extensions are supported yet.

You can now generate sound using Lv2 instruments (restricted to non-piano)
or effects.

For an explenation about the new classes, see Lv2Manager.h
This commit is contained in:
Johannes Lorenz
2020-05-24 12:50:50 +02:00
parent 7aef23d209
commit 2a66e83f53
39 changed files with 3536 additions and 3 deletions

View File

@@ -71,6 +71,7 @@ private:
ch_cnt_t m_controlCount;
bool m_noLink;
BoolModel m_stereoLinkModel;
//! control vector for each processor
QVector<control_list_t> m_controls;

View File

@@ -0,0 +1,9 @@
IF(LMMS_HAVE_LV2)
INCLUDE_DIRECTORIES(${LV2_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${LILV_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${SUIL_INCLUDE_DIRS})
INCLUDE(BuildPlugin)
BUILD_PLUGIN(lv2effect Lv2Effect.cpp Lv2FxControls.cpp Lv2FxControlDialog.cpp Lv2Effect.h Lv2FxControls.h Lv2FxControlDialog.h
MOCFILES Lv2Effect.h Lv2FxControls.h Lv2FxControlDialog.h
EMBEDDED_RESOURCES logo.png)
ENDIF(LMMS_HAVE_LV2)

View File

@@ -0,0 +1,111 @@
/*
* Lv2Effect.cpp - implementation of LV2 effect
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* 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 "Lv2Effect.h"
#include <QDebug>
#include <lv2.h>
#include "Lv2SubPluginFeatures.h"
#include "embed.h"
#include "plugin_export.h"
Plugin::Descriptor PLUGIN_EXPORT lv2effect_plugin_descriptor =
{
STRINGIFY(PLUGIN_NAME),
"LV2",
QT_TRANSLATE_NOOP("pluginBrowser",
"plugin for using arbitrary LV2-effects inside LMMS."),
"Johannes Lorenz <jlsf2013$$$users.sourceforge.net, $$$=@>",
0x0100,
Plugin::Effect,
new PluginPixmapLoader("logo"),
nullptr,
new Lv2SubPluginFeatures(Plugin::Effect)
};
Lv2Effect::Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key *key) :
Effect(&lv2effect_plugin_descriptor, parent, key),
m_controls(this, key->attributes["uri"]),
m_tmpOutputSmps(Engine::mixer()->framesPerPeriod())
{
}
bool Lv2Effect::processAudioBuffer(sampleFrame *buf, const fpp_t frames)
{
if (!isEnabled() || !isRunning()) { return false; }
Q_ASSERT(frames <= static_cast<fpp_t>(m_tmpOutputSmps.size()));
m_controls.copyBuffersFromLmms(buf, frames);
m_controls.copyModelsFromLmms();
// m_pluginMutex.lock();
m_controls.run(frames);
// m_pluginMutex.unlock();
m_controls.copyBuffersToLmms(m_tmpOutputSmps.data(), frames);
double outSum = .0;
bool corrupt = wetLevel() < 0; // #3261 - if w < 0, bash w := 0, d := 1
const float d = corrupt ? 1 : dryLevel();
const float w = corrupt ? 0 : wetLevel();
for(fpp_t f = 0; f < frames; ++f)
{
buf[f][0] = d * buf[f][0] + w * m_tmpOutputSmps[f][0];
buf[f][1] = d * buf[f][1] + w * m_tmpOutputSmps[f][1];
double l = static_cast<double>(buf[f][0]);
double r = static_cast<double>(buf[f][1]);
outSum += l*l + r*r;
}
checkGate(outSum / frames);
return isRunning();
}
extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin *lmms_plugin_main(Model *_parent, void *_data)
{
using KeyType = Plugin::Descriptor::SubPluginFeatures::Key;
Lv2Effect* eff = new Lv2Effect(_parent, static_cast<const KeyType*>(_data));
if (!eff->isValid()) { delete eff; eff = nullptr; }
return eff;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Lv2Effect.h - implementation of LV2 effect
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* 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.
*
*/
#ifndef LV2_EFFECT_H
#define LV2_EFFECT_H
#include "Effect.h"
#include "Lv2FxControls.h"
class Lv2Effect : public Effect
{
Q_OBJECT
public:
/*
initialization
*/
Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key* _key);
//! Must be checked after ctor or reload
bool isValid() const { return m_controls.isValid(); }
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
EffectControls* controls() override { return &m_controls; }
Lv2FxControls* lv2Controls() { return &m_controls; }
const Lv2FxControls* lv2Controls() const { return &m_controls; }
private:
Lv2FxControls m_controls;
std::vector<sampleFrame> m_tmpOutputSmps;
};
#endif // LMMS_HAVE_LV2

View File

@@ -0,0 +1,72 @@
/*
* Lv2FxControlDialog.cpp - Lv2FxControlDialog implementation
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* 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 "Lv2FxControlDialog.h"
#include <QDebug>
#include <QPushButton>
#include <lv2.h>
#include "Lv2Effect.h"
#include "Lv2FxControls.h"
Lv2FxControlDialog::Lv2FxControlDialog(Lv2FxControls *controls) :
EffectControlDialog(controls),
Lv2ViewBase(this, controls)
{
if (m_reloadPluginButton) {
connect(m_reloadPluginButton, &QPushButton::clicked,
this, [this](){ lv2Controls()->reloadPlugin(); });
}
if (m_toggleUIButton) {
connect(m_toggleUIButton, &QPushButton::toggled,
this, [this](){ toggleUI(); });
}
if (m_helpButton) {
connect(m_helpButton, &QPushButton::toggled,
this, [this](bool visible){ toggleHelp(visible); });
}
// for Effects, modelChanged only goes to the top EffectView
// we need to call it manually
modelChanged();
}
Lv2FxControls *Lv2FxControlDialog::lv2Controls()
{
return static_cast<Lv2FxControls *>(m_effectControls);
}
void Lv2FxControlDialog::modelChanged()
{
Lv2ViewBase::modelChanged(lv2Controls());
}

View File

@@ -0,0 +1,47 @@
/*
* Lv2FxControlDialog.h - Lv2FxControlDialog implementation
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* 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.
*
*/
#ifndef LV2_FX_CONTROL_DIALOG_H
#define LV2_FX_CONTROL_DIALOG_H
#include "EffectControlDialog.h"
#include "Lv2ViewBase.h"
class Lv2FxControls;
class Lv2FxControlDialog : public EffectControlDialog, public Lv2ViewBase
{
Q_OBJECT
public:
Lv2FxControlDialog(Lv2FxControls *controls);
private:
Lv2FxControls *lv2Controls();
void modelChanged() override;
};
#endif

View File

@@ -0,0 +1,104 @@
/*
* Lv2FxControls.cpp - Lv2FxControls implementation
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* 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 "Lv2FxControls.h"
#include <QDomElement>
#include "Engine.h"
#include "Lv2Effect.h"
#include "Lv2FxControlDialog.h"
#include "Lv2Proc.h"
Lv2FxControls::Lv2FxControls(class Lv2Effect *effect, const QString& uri) :
EffectControls(effect),
Lv2ControlBase(this, uri)
{
if (isValid())
{
connect(Engine::mixer(), &Mixer::sampleRateChanged,
this, [this](){Lv2ControlBase::reloadPlugin();});
}
}
void Lv2FxControls::saveSettings(QDomDocument &doc, QDomElement &that)
{
Lv2ControlBase::saveSettings(doc, that);
}
void Lv2FxControls::loadSettings(const QDomElement &that)
{
Lv2ControlBase::loadSettings(that);
}
int Lv2FxControls::controlCount()
{
return static_cast<int>(Lv2ControlBase::controlCount());
}
EffectControlDialog *Lv2FxControls::createView()
{
return new Lv2FxControlDialog(this);
}
void Lv2FxControls::changeControl() // TODO: what is that?
{
// engine::getSong()->setModified();
}
DataFile::Types Lv2FxControls::settingsType()
{
return DataFile::EffectSettings;
}
void Lv2FxControls::setNameFromFile(const QString &name)
{
effect()->setDisplayName(name);
}

View File

@@ -0,0 +1,61 @@
/*
* Lv2FxControls.h - Lv2FxControls implementation
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* 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.
*
*/
#ifndef LV2_FX_CONTROLS_H
#define LV2_FX_CONTROLS_H
#include "EffectControls.h"
#include "Lv2ControlBase.h"
class Lv2Effect;
class Lv2FxControls : public EffectControls, public Lv2ControlBase
{
Q_OBJECT
public:
Lv2FxControls(Lv2Effect *effect, const QString &uri);
void saveSettings(QDomDocument &_doc, QDomElement &_parent) override;
void loadSettings(const QDomElement &that) override;
inline QString nodeName() const override
{
return Lv2ControlBase::nodeName();
}
int controlCount() override;
EffectControlDialog *createView() override;
private slots:
void changeControl();
private:
DataFile::Types settingsType() override;
void setNameFromFile(const QString &name) override;
friend class Lv2FxControlDialog;
friend class Lv2Effect;
};
#endif

BIN
plugins/Lv2Effect/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

View File

@@ -0,0 +1,7 @@
IF(LMMS_HAVE_LV2)
INCLUDE_DIRECTORIES(${LV2_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${LILV_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${SUIL_INCLUDE_DIRS})
INCLUDE(BuildPlugin)
BUILD_PLUGIN(lv2instrument Lv2Instrument.cpp Lv2Instrument.h MOCFILES Lv2Instrument.h EMBEDDED_RESOURCES logo.png)
ENDIF(LMMS_HAVE_LV2)

View File

@@ -0,0 +1,303 @@
/*
* Lv2Instrument.cpp - implementation of LV2 instrument
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* 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 "Lv2Instrument.h"
#include <QDebug>
#include <QDragEnterEvent>
#include "Engine.h"
#include "InstrumentPlayHandle.h"
#include "InstrumentTrack.h"
#include "Lv2SubPluginFeatures.h"
#include "Mixer.h"
#include "StringPairDrag.h"
#include "embed.h"
#include "plugin_export.h"
Plugin::Descriptor PLUGIN_EXPORT lv2instrument_plugin_descriptor =
{
STRINGIFY(PLUGIN_NAME),
"LV2",
QT_TRANSLATE_NOOP("pluginBrowser",
"plugin for using arbitrary LV2 instruments inside LMMS."),
"Johannes Lorenz <jlsf2013$$$users.sourceforge.net, $$$=@>",
0x0100,
Plugin::Instrument,
new PluginPixmapLoader("logo"),
nullptr,
new Lv2SubPluginFeatures(Plugin::Instrument)
};
/*
Lv2Instrument
*/
Lv2Instrument::Lv2Instrument(InstrumentTrack *instrumentTrackArg,
Descriptor::SubPluginFeatures::Key *key) :
Instrument(instrumentTrackArg, &lv2instrument_plugin_descriptor, key),
Lv2ControlBase(this, key->attributes["uri"])
{
if (Lv2ControlBase::isValid())
{
#ifdef LV2_INSTRUMENT_USE_MIDI
for (int i = 0; i < NumKeys; ++i) { m_runningNotes[i] = 0; }
#endif
connect(instrumentTrack()->pitchRangeModel(), SIGNAL(dataChanged()),
this, SLOT(updatePitchRange()), Qt::DirectConnection);
connect(Engine::mixer(), &Mixer::sampleRateChanged,
this, [this](){Lv2ControlBase::reloadPlugin();});
// now we need a play-handle which cares for calling play()
InstrumentPlayHandle *iph =
new InstrumentPlayHandle(this, instrumentTrackArg);
Engine::mixer()->addPlayHandle(iph);
}
}
Lv2Instrument::~Lv2Instrument()
{
Engine::mixer()->removePlayHandlesOfTypes(instrumentTrack(),
PlayHandle::TypeNotePlayHandle |
PlayHandle::TypeInstrumentPlayHandle);
}
bool Lv2Instrument::isValid() const { return Lv2ControlBase::isValid(); }
void Lv2Instrument::saveSettings(QDomDocument &doc, QDomElement &that)
{
Lv2ControlBase::saveSettings(doc, that);
}
void Lv2Instrument::loadSettings(const QDomElement &that)
{
Lv2ControlBase::loadSettings(that);
}
void Lv2Instrument::loadFile(const QString &file)
{
Lv2ControlBase::loadFile(file);
}
#ifdef LV2_INSTRUMENT_USE_MIDI
bool Lv2Instrument::handleMidiEvent(
const MidiEvent &event, const MidiTime &time, f_cnt_t offset)
{
// this function can be called from GUI threads while the plugin is running,
// so this requires caching, e.g. in ringbuffers
(void)time;
(void)offset;
(void)event;
return true;
}
#endif
// not yet working
#ifndef LV2_INSTRUMENT_USE_MIDI
void Lv2Instrument::playNote(NotePlayHandle *nph, sampleFrame *)
{
}
#endif
void Lv2Instrument::play(sampleFrame *buf)
{
copyModelsFromLmms();
fpp_t fpp = Engine::mixer()->framesPerPeriod();
run(fpp);
copyBuffersToLmms(buf, fpp);
instrumentTrack()->processAudioBuffer(buf, fpp, nullptr);
}
PluginView *Lv2Instrument::instantiateView(QWidget *parent)
{
return new Lv2InsView(this, parent);
}
void Lv2Instrument::updatePitchRange()
{
qDebug() << "Lmms: Cannot update pitch range for lv2 plugin:"
"not implemented yet";
}
QString Lv2Instrument::nodeName() const
{
return Lv2ControlBase::nodeName();
}
DataFile::Types Lv2Instrument::settingsType()
{
return DataFile::InstrumentTrackSettings;
}
void Lv2Instrument::setNameFromFile(const QString &name)
{
instrumentTrack()->setName(name);
}
/*
Lv2InsView
*/
Lv2InsView::Lv2InsView(Lv2Instrument *_instrument, QWidget *_parent) :
InstrumentView(_instrument, _parent),
Lv2ViewBase(this, _instrument)
{
setAutoFillBackground(true);
if (m_reloadPluginButton) {
connect(m_reloadPluginButton, &QPushButton::clicked,
this, [this](){ castModel<Lv2Instrument>()->reloadPlugin();} );
}
if (m_toggleUIButton) {
connect(m_toggleUIButton, &QPushButton::toggled,
this, [this](){ toggleUI(); });
}
if (m_helpButton) {
connect(m_helpButton, &QPushButton::toggled,
this, [this](bool visible){ toggleHelp(visible); });
}
}
void Lv2InsView::dragEnterEvent(QDragEnterEvent *_dee)
{
void (QDragEnterEvent::*reaction)(void) = &QDragEnterEvent::ignore;
if (_dee->mimeData()->hasFormat(StringPairDrag::mimeType()))
{
const QString txt =
_dee->mimeData()->data(StringPairDrag::mimeType());
if (txt.section(':', 0, 0) == "pluginpresetfile") {
reaction = &QDragEnterEvent::acceptProposedAction;
}
}
(_dee->*reaction)();
}
void Lv2InsView::dropEvent(QDropEvent *_de)
{
const QString type = StringPairDrag::decodeKey(_de);
const QString value = StringPairDrag::decodeValue(_de);
if (type == "pluginpresetfile")
{
castModel<Lv2Instrument>()->loadFile(value);
_de->accept();
return;
}
_de->ignore();
}
void Lv2InsView::toggleUI()
{
}
void Lv2InsView::modelChanged()
{
Lv2ViewBase::modelChanged(castModel<Lv2Instrument>());
}
extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin *lmms_plugin_main(Model *_parent, void *_data)
{
using KeyType = Plugin::Descriptor::SubPluginFeatures::Key;
Lv2Instrument* ins = new Lv2Instrument(
static_cast<InstrumentTrack*>(_parent),
static_cast<KeyType*>(_data ));
if (!ins->isValid()) { delete ins; ins = nullptr; }
return ins;
}
}

View File

@@ -0,0 +1,123 @@
/*
* Lv2Instrument.h - implementation of LV2 instrument
*
* Copyright (c) 2018-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* 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.
*
*/
#ifndef LV2_INSTRUMENT_H
#define LV2_INSTRUMENT_H
#include <QString>
#include "Instrument.h"
#include "InstrumentView.h"
#include "Note.h"
#include "Lv2ControlBase.h"
#include "Lv2ViewBase.h"
// whether to use MIDI vs playHandle
// currently only MIDI works
#define LV2_INSTRUMENT_USE_MIDI
class QPushButton;
class Lv2Instrument : public Instrument, public Lv2ControlBase
{
Q_OBJECT
public:
/*
initialization
*/
Lv2Instrument(InstrumentTrack *instrumentTrackArg,
Descriptor::SubPluginFeatures::Key* key);
~Lv2Instrument() override;
//! Must be checked after ctor or reload
bool isValid() const;
/*
load/save
*/
void saveSettings(QDomDocument &doc, QDomElement &that) override;
void loadSettings(const QDomElement &that) override;
void loadFile(const QString &file) override;
/*
realtime funcs
*/
bool hasNoteInput() const override { return false; /* not supported yet */ }
#ifdef LV2_INSTRUMENT_USE_MIDI
bool handleMidiEvent(const MidiEvent &event,
const MidiTime &time = MidiTime(), f_cnt_t offset = 0) override;
#else
void playNote(NotePlayHandle *nph, sampleFrame *) override;
#endif
void play(sampleFrame *buf) override;
/*
misc
*/
Flags flags() const override
{
#ifdef LV2_INSTRUMENT_USE_MIDI
return IsSingleStreamed | IsMidiBased;
#else
return IsSingleStreamed;
#endif
}
PluginView *instantiateView(QWidget *parent) override;
private slots:
void updatePitchRange();
private:
QString nodeName() const override;
DataFile::Types settingsType() override;
void setNameFromFile(const QString &name) override;
#ifdef LV2_INSTRUMENT_USE_MIDI
int m_runningNotes[NumKeys];
#endif
friend class Lv2InsView;
};
class Lv2InsView : public InstrumentView, public Lv2ViewBase
{
Q_OBJECT
public:
Lv2InsView(Lv2Instrument *_instrument, QWidget *_parent);
protected:
void dragEnterEvent(QDragEnterEvent *_dee) override;
void dropEvent(QDropEvent *_de) override;
private slots:
void reloadPlugin();
void toggleUI();
private:
void modelChanged() override;
};
#endif // LV2_INSTRUMENT_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B