Browse Source

Massive work for DISTRHO exports on LV2 and VST, it's close...

tags/1.9.4
falkTX 11 years ago
parent
commit
478def9c32
23 changed files with 1239 additions and 1200 deletions
  1. +1
    -1
      source/modules/carla_native/3bandeq/DistrhoPlugin3BandEQ.cpp
  2. +1
    -1
      source/modules/carla_native/3bandeq/DistrhoPlugin3BandEQ.hpp
  3. +0
    -2
      source/modules/carla_native/3bandeq/DistrhoPluginInfo.h
  4. +3
    -1
      source/modules/carla_native/3bandeq/DistrhoUI3BandEQ.cpp
  5. +8
    -2
      source/modules/carla_native/3bandeq/DistrhoUI3BandEQ.hpp
  6. +8
    -31
      source/modules/distrho/DistrhoPlugin.hpp
  7. +5
    -6
      source/modules/distrho/DistrhoUI.hpp
  8. +145
    -68
      source/modules/distrho/DistrhoUtils.hpp
  9. +0
    -6
      source/modules/distrho/src/DistrhoDefines.h
  10. +5
    -5
      source/modules/distrho/src/DistrhoPlugin.cpp
  11. +65
    -67
      source/modules/distrho/src/DistrhoPluginInternal.hpp
  12. +116
    -101
      source/modules/distrho/src/DistrhoPluginLADSPA+DSSI.cpp
  13. +224
    -180
      source/modules/distrho/src/DistrhoPluginLV2.cpp
  14. +78
    -80
      source/modules/distrho/src/DistrhoPluginLV2export.cpp
  15. +167
    -226
      source/modules/distrho/src/DistrhoPluginVST.cpp
  16. +12
    -4
      source/modules/distrho/src/DistrhoUI.cpp
  17. +27
    -185
      source/modules/distrho/src/DistrhoUIDSSI.cpp
  18. +0
    -35
      source/modules/distrho/src/DistrhoUIExternal.cpp
  19. +65
    -103
      source/modules/distrho/src/DistrhoUIInternal.hpp
  20. +301
    -0
      source/modules/distrho/src/DistrhoUILV2.cpp
  21. +0
    -43
      source/modules/distrho/src/DistrhoUIOpenGL.cpp
  22. +0
    -50
      source/modules/distrho/src/DistrhoUIQt.cpp
  23. +8
    -3
      source/tests/Makefile

+ 1
- 1
source/modules/carla_native/3bandeq/DistrhoPlugin3BandEQ.cpp View File

@@ -224,7 +224,7 @@ void DistrhoPlugin3BandEQ::d_deactivate()
tmp1LP = tmp2LP = tmp1HP = tmp2HP = 0.0f;
}
void DistrhoPlugin3BandEQ::d_run(float** inputs, float** outputs, uint32_t frames, const MidiEvent*, uint32_t)
void DistrhoPlugin3BandEQ::d_run(float** inputs, float** outputs, uint32_t frames)
{
float* in1 = inputs[0];
float* in2 = inputs[1];


+ 1
- 1
source/modules/carla_native/3bandeq/DistrhoPlugin3BandEQ.hpp View File

@@ -88,7 +88,7 @@ protected:
void d_activate() override;
void d_deactivate() override;
void d_run(float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) override;
void d_run(float** inputs, float** outputs, uint32_t frames) override;
// -------------------------------------------------------------------


+ 0
- 2
source/modules/carla_native/3bandeq/DistrhoPluginInfo.h View File

@@ -32,6 +32,4 @@

#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/plugins/3BandEQ"

#define DISTRHO_UI_OPENGL

#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED

+ 3
- 1
source/modules/carla_native/3bandeq/DistrhoUI3BandEQ.cpp View File

@@ -16,12 +16,14 @@

#include "DistrhoUI3BandEQ.hpp"

using DGL::Point;

START_NAMESPACE_DISTRHO

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

DistrhoUI3BandEQ::DistrhoUI3BandEQ()
: OpenGLUI(),
: UI(),
fAboutWindow(this)
{
// background


+ 8
- 2
source/modules/carla_native/3bandeq/DistrhoUI3BandEQ.hpp View File

@@ -17,7 +17,7 @@
#ifndef DISTRHO_UI_3BANDEQ_HPP_INCLUDED
#define DISTRHO_UI_3BANDEQ_HPP_INCLUDED

#include "DistrhoUIOpenGL.hpp"
#include "DistrhoUI.hpp"

#include "dgl/ImageAboutWindow.hpp"
#include "dgl/ImageButton.hpp"
@@ -27,11 +27,17 @@
#include "DistrhoArtwork3BandEQ.hpp"
#include "DistrhoPlugin3BandEQ.hpp"

using DGL::Image;
using DGL::ImageAboutWindow;
using DGL::ImageButton;
using DGL::ImageKnob;
using DGL::ImageSlider;

START_NAMESPACE_DISTRHO

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

class DistrhoUI3BandEQ : public OpenGLUI,
class DistrhoUI3BandEQ : public UI,
public ImageButton::Callback,
public ImageKnob::Callback,
public ImageSlider::Callback


+ 8
- 31
source/modules/distrho/DistrhoPlugin.hpp View File

@@ -37,46 +37,24 @@ struct ParameterRanges {
float def;
float min;
float max;
float step;
float stepSmall;
float stepLarge;

ParameterRanges() noexcept
: def(0.0f),
min(0.0f),
max(1.0f),
step(0.001f),
stepSmall(0.00001f),
stepLarge(0.01f) {}
max(1.0f) {}

ParameterRanges(float def, float min, float max) noexcept
: step(0.001f),
stepSmall(0.00001f),
stepLarge(0.01f)
{
this->def = def;
this->min = min;
this->max = max;
}

ParameterRanges(float def, float min, float max, float step, float stepSmall, float stepLarge) noexcept
{
this->def = def;
this->min = min;
this->max = max;
this->step = step;
this->stepSmall = stepSmall;
this->stepLarge = stepLarge;
}

void clear() noexcept
{
def = 0.0f;
min = 0.0f;
max = 1.0f;
step = 0.001f;
stepSmall = 0.00001f;
stepLarge = 0.01f;
}

void fixValue(float& value) const noexcept
@@ -141,22 +119,17 @@ struct Parameter {

struct MidiEvent {
uint32_t frame;
uint8_t buf[4];
uint8_t size;

MidiEvent() noexcept
{
clear();
}
uint8_t buf[4];

void clear() noexcept
{
frame = 0;
size = 0;
buf[0] = 0;
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
size = 0;
}
};

@@ -234,7 +207,11 @@ protected:

virtual void d_activate() {}
virtual void d_deactivate() {}
#if DISTRHO_PLUGIN_IS_SYNTH
virtual void d_run(float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) = 0;
#else
virtual void d_run(float** inputs, float** outputs, uint32_t frames) = 0;
#endif

// -------------------------------------------------------------------
// Callbacks (optional)
@@ -247,7 +224,7 @@ protected:
private:
struct PrivateData;
PrivateData* const pData;
friend class PluginInternal;
friend class PluginExporter;
};

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


+ 5
- 6
source/modules/distrho/DistrhoUI.hpp View File

@@ -19,12 +19,14 @@

#include "DistrhoUtils.hpp"

#include "dgl/Widget.hpp"

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// UI

class UI
class UI : public DGL::Widget
{
public:
UI();
@@ -40,7 +42,7 @@ public:
void d_setState(const char* key, const char* value);
#endif
#if DISTRHO_PLUGIN_IS_SYNTH
void d_sendNote(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity);
void d_sendNote(uint8_t channel, uint8_t note, uint8_t velocity);
#endif

// -------------------------------------------------------------------
@@ -66,9 +68,6 @@ protected:
#if DISTRHO_PLUGIN_WANT_STATE
virtual void d_stateChanged(const char* key, const char* value) = 0;
#endif
#if DISTRHO_PLUGIN_IS_SYNTH
virtual void d_noteReceived(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) = 0;
#endif

// -------------------------------------------------------------------
// UI Callbacks (optional)
@@ -80,7 +79,7 @@ protected:
private:
struct PrivateData;
PrivateData* const pData;
friend class UIInternal;
friend class UIExporter;
};

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


+ 145
- 68
source/modules/distrho/DistrhoUtils.hpp View File

@@ -141,24 +141,49 @@ public:
// -------------------------------------------------------------------
// constructors (no explicit conversions allowed)

/*
* Empty string.
*/
explicit d_string()
{
_init();
_dup(nullptr);
}

/*
* Simple character.
*/
explicit d_string(const char c)
{
char ch[2];
ch[0] = c;
ch[1] = '\0';

_init();
_dup(ch);
}

/*
* Simple char string.
*/
explicit d_string(char* const strBuf)
{
_init();
_dup(strBuf);
}

/*
* Simple const char string.
*/
explicit d_string(const char* const strBuf)
{
_init();
_dup(strBuf);
}

/*
* Integer.
*/
explicit d_string(const int value)
{
char strBuf[0xff+1];
@@ -169,6 +194,9 @@ public:
_dup(strBuf);
}

/*
* Unsigned integer, possibly in hexadecimal.
*/
explicit d_string(const unsigned int value, const bool hexadecimal = false)
{
char strBuf[0xff+1];
@@ -179,6 +207,9 @@ public:
_dup(strBuf);
}

/*
* Long integer.
*/
explicit d_string(const long int value)
{
char strBuf[0xff+1];
@@ -189,6 +220,9 @@ public:
_dup(strBuf);
}

/*
* Long unsigned integer, possibly hexadecimal.
*/
explicit d_string(const unsigned long int value, const bool hexadecimal = false)
{
char strBuf[0xff+1];
@@ -199,6 +233,9 @@ public:
_dup(strBuf);
}

/*
* Single-precision floating point number.
*/
explicit d_string(const float value)
{
char strBuf[0xff+1];
@@ -209,6 +246,9 @@ public:
_dup(strBuf);
}

/*
* Double-precision floating point number.
*/
explicit d_string(const double value)
{
char strBuf[0xff+1];
@@ -222,6 +262,9 @@ public:
// -------------------------------------------------------------------
// non-explicit constructor

/*
* Create string from another string.
*/
d_string(const d_string& str)
{
_init();
@@ -231,6 +274,9 @@ public:
// -------------------------------------------------------------------
// destructor

/*
* Destructor.
*/
~d_string()
{
assert(fBuffer != nullptr);
@@ -242,52 +288,64 @@ public:
// -------------------------------------------------------------------
// public methods

/*
* Get length of the string.
*/
size_t length() const noexcept
{
return fBufferLen;
}

/*
* Check if the string is empty.
*/
bool isEmpty() const noexcept
{
return (fBufferLen == 0);
}

/*
* Check if the string is not empty.
*/
bool isNotEmpty() const noexcept
{
return (fBufferLen != 0);
}

#ifdef __USE_GNU
/*
* Check if the string contains another string, optionally ignoring case.
*/
bool contains(const char* const strBuf, const bool ignoreCase = false) const
{
if (strBuf == nullptr)
return false;

if (ignoreCase)
{
#ifdef __USE_GNU
return (strcasestr(fBuffer, strBuf) != nullptr);
else
return (std::strstr(fBuffer, strBuf) != nullptr);
}

bool contains(const d_string& str, const bool ignoreCase = false) const
{
return contains(str.fBuffer, ignoreCase);
}
#else
bool contains(const char* const strBuf) const
{
if (strBuf == nullptr)
return false;
d_string tmp1(fBuffer), tmp2(strBuf);
tmp1.toLower();
tmp2.toLower();
return (std::strstr((const char*)tmp1, (const char*)tmp2) != nullptr);
#endif
}

return (std::strstr(fBuffer, strBuf) != nullptr);
}

bool contains(const d_string& str) const
/*
* Overloaded function.
*/
bool contains(const d_string& str, const bool ignoreCase = false) const
{
return contains(str.fBuffer);
return contains(str.fBuffer, ignoreCase);
}
#endif

/*
* Check if character at 'pos' is a digit.
*/
bool isDigit(const size_t pos) const noexcept
{
if (pos >= fBufferLen)
@@ -296,6 +354,20 @@ public:
return (fBuffer[pos] >= '0' && fBuffer[pos] <= '9');
}

/*
* Check if the string starts with the character 'c'.
*/
bool startsWith(const char c) const
{
if (c == '\0')
return false;

return (fBufferLen > 0 && fBuffer[0] == c);
}

/*
* Check if the string starts with the string 'prefix'.
*/
bool startsWith(const char* const prefix) const
{
if (prefix == nullptr)
@@ -309,6 +381,20 @@ public:
return (std::strncmp(fBuffer + (fBufferLen-prefixLen), prefix, prefixLen) == 0);
}

/*
* Check if the string ends with the character 'c'.
*/
bool endsWith(const char c) const
{
if (c == '\0')
return false;

return (fBufferLen > 0 && fBuffer[fBufferLen] == c);
}

/*
* Check if the string ends with the string 'suffix'.
*/
bool endsWith(const char* const suffix) const
{
if (suffix == nullptr)
@@ -322,56 +408,20 @@ public:
return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
}

/*
* Clear the string.
*/
void clear() noexcept
{
truncate(0);
}

size_t find(const char c) const noexcept
{
for (size_t i=0; i < fBufferLen; ++i)
{
if (fBuffer[i] == c)
return i;
}

return 0;
}

size_t rfind(const char c) const noexcept
{
for (size_t i=fBufferLen; i > 0; --i)
{
if (fBuffer[i-1] == c)
return i-1;
}

return 0;
}

size_t rfind(const char* const strBuf) const
{
if (strBuf == nullptr || strBuf[0] == '\0')
return fBufferLen;

size_t ret = fBufferLen+1;
const char* tmpBuf = fBuffer;

for (size_t i=0; i < fBufferLen; ++i)
{
if (std::strstr(tmpBuf, strBuf) == nullptr)
break;

--ret;
++tmpBuf;
}

return (ret > fBufferLen) ? fBufferLen : fBufferLen-ret;
}

/*
* Replace all occurrences of character 'before' with character 'after'.
*/
void replace(const char before, const char after) noexcept
{
if (after == '\0')
if (before == '\0' || after == '\0')
return;

for (size_t i=0; i < fBufferLen; ++i)
@@ -383,6 +433,9 @@ public:
}
}

/*
* Truncate the string to size 'n'.
*/
void truncate(const size_t n) noexcept
{
if (n >= fBufferLen)
@@ -394,6 +447,9 @@ public:
fBufferLen = n;
}

/*
* Convert all non-basic characters to '_'.
*/
void toBasic() noexcept
{
for (size_t i=0; i < fBufferLen; ++i)
@@ -411,6 +467,9 @@ public:
}
}

/*
* Convert to all ascii characters to lowercase.
*/
void toLower() noexcept
{
static const char kCharDiff('a' - 'A');
@@ -422,6 +481,9 @@ public:
}
}

/*
* Convert to all ascii characters to uppercase.
*/
void toUpper() noexcept
{
static const char kCharDiff('a' - 'A');
@@ -480,7 +542,10 @@ public:

d_string& operator+=(const char* const strBuf)
{
const size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
if (strBuf == nullptr)
return *this;

const size_t newBufSize = fBufferLen + std::strlen(strBuf) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, fBuffer);
@@ -502,7 +567,9 @@ public:
char newBuf[newBufSize];

std::strcpy(newBuf, fBuffer);
std::strcat(newBuf, strBuf);

if (strBuf != nullptr)
std::strcat(newBuf, strBuf);

return d_string(newBuf);
}
@@ -515,10 +582,14 @@ public:
// -------------------------------------------------------------------

private:
char* fBuffer;
size_t fBufferLen;
bool fFirstInit;

char* fBuffer; // the actual string buffer
size_t fBufferLen; // string length
bool fFirstInit; // true when first initiated

/*
* Shared init function.
* Called on all constructors.
*/
void _init() noexcept
{
fBuffer = nullptr;
@@ -526,8 +597,14 @@ private:
fFirstInit = true;
}

// allocate string strBuf if not null
// size > 0 only if strBuf is valid
/*
* Helper function.
* Called whenever the string needs to be allocated.
*
* Notes:
* - Allocates string only if first initiated, or if 'strBuf' is not null and new string contents are different
* - If 'strBuf' is null 'size' must be 0
*/
void _dup(const char* const strBuf, const size_t size = 0)
{
if (strBuf != nullptr)
@@ -580,7 +657,7 @@ static inline
d_string operator+(const d_string& strBefore, const char* const strBufAfter)
{
const char* const strBufBefore = (const char*)strBefore;
const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, strBufBefore);


+ 0
- 6
source/modules/distrho/src/DistrhoDefines.h View File

@@ -55,12 +55,6 @@
# error DISTRHO_PLUGIN_WANT_TIMEPOS undefined!
#endif

#if DISTRHO_PLUGIN_HAS_UI
# if ! (defined(DISTRHO_UI_EXTERNAL) || defined(DISTRHO_UI_OPENGL) || defined(DISTRHO_UI_QT))
# error DISTRHO_PLUGIN_HAS_UI is defined but not its type; please define one of DISTRHO_UI_EXTERNAL, DISTRHO_UI_OPENGL or DISTRHO_UI_QT
# endif
#endif

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# define DISTRHO_PLUGIN_EXPORT extern "C" __declspec (dllexport)
# define DISTRHO_OS_WINDOWS 1


+ 5
- 5
source/modules/distrho/src/DistrhoPlugin.cpp View File

@@ -19,16 +19,16 @@
START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// Static data
// Static data, see DistrhoPluginInternal.hpp

uint32_t d_lastBufferSize = 0;
double d_lastSampleRate = 0.0;

// -----------------------------------------------------------------------
// Static, fallback data
// Static fallback data, see DistrhoPluginInternal.hpp

const d_string PluginInternal::sFallbackString;
const ParameterRanges PluginInternal::sFallbackRanges;
const d_string PluginExporter::sFallbackString;
const ParameterRanges PluginExporter::sFallbackRanges;

// -----------------------------------------------------------------------
// Plugin
@@ -92,7 +92,7 @@ void Plugin::d_setLatency(uint32_t frames) noexcept
#endif

// -----------------------------------------------------------------------
// Callbacks
// Callbacks (optional)

void Plugin::d_bufferSizeChanged(uint32_t)
{


+ 65
- 67
source/modules/distrho/src/DistrhoPluginInternal.hpp View File

@@ -22,16 +22,20 @@
START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// Maxmimum values

#define MAX_MIDI_EVENTS 512
static const uint32_t kMaxMidiEvents = 512;

// -----------------------------------------------------------------------
// Static data, see DistrhoPlugin.cpp

extern uint32_t d_lastBufferSize;
extern double d_lastSampleRate;

struct Plugin::PrivateData {
uint32_t bufferSize;
double sampleRate;
// -----------------------------------------------------------------------
// Plugin private data

struct Plugin::PrivateData {
uint32_t parameterCount;
Parameter* parameters;

@@ -53,12 +57,11 @@ struct Plugin::PrivateData {
TimePos timePos;
#endif

char _d; // dummy
uint32_t bufferSize;
double sampleRate;

PrivateData()
: bufferSize(d_lastBufferSize),
sampleRate(d_lastSampleRate),
parameterCount(0),
PrivateData() noexcept
: parameterCount(0),
parameters(nullptr),
#if DISTRHO_PLUGIN_WANT_PROGRAMS
programCount(0),
@@ -71,7 +74,8 @@ struct Plugin::PrivateData {
#if DISTRHO_PLUGIN_WANT_LATENCY
latency(0),
#endif
_d(0)
bufferSize(d_lastBufferSize),
sampleRate(d_lastSampleRate)
{
assert(bufferSize != 0);
assert(sampleRate != 0.0);
@@ -104,11 +108,12 @@ struct Plugin::PrivateData {
};

// -----------------------------------------------------------------------
// Plugin exporter class

class PluginInternal
class PluginExporter
{
public:
PluginInternal()
PluginExporter()
: fPlugin(createPlugin()),
fData((fPlugin != nullptr) ? fPlugin->pData : nullptr)
{
@@ -131,131 +136,121 @@ public:
#endif
}

~PluginInternal()
~PluginExporter()
{
if (fPlugin != nullptr)
delete fPlugin;
delete fPlugin;
}

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

const char* getName() const
const char* getName() const noexcept
{
assert(fPlugin != nullptr);
return (fPlugin != nullptr) ? fPlugin->d_getName() : "";
}

const char* getLabel() const
const char* getLabel() const noexcept
{
assert(fPlugin != nullptr);
return (fPlugin != nullptr) ? fPlugin->d_getLabel() : "";
}

const char* getMaker() const
const char* getMaker() const noexcept
{
assert(fPlugin != nullptr);
return (fPlugin != nullptr) ? fPlugin->d_getMaker() : "";
}

const char* getLicense() const
const char* getLicense() const noexcept
{
assert(fPlugin != nullptr);
return (fPlugin != nullptr) ? fPlugin->d_getLicense() : "";
}

uint32_t getVersion() const
uint32_t getVersion() const noexcept
{
assert(fPlugin != nullptr);
return (fPlugin != nullptr) ? fPlugin->d_getVersion() : 1000;
}

long getUniqueId() const
long getUniqueId() const noexcept
{
assert(fPlugin != nullptr);
return (fPlugin != nullptr) ? fPlugin->d_getUniqueId() : 0;
}

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

#if DISTRHO_PLUGIN_WANT_LATENCY
uint32_t getLatency() const
uint32_t getLatency() const noexcept
{
assert(fData != nullptr);
return (fData != nullptr) ? fData->getLatency : 0;
return (fData != nullptr) ? fData->latency : 0;
}
#endif

uint32_t getParameterCount() const
uint32_t getParameterCount() const noexcept
{
assert(fData != nullptr);
return (fData != nullptr) ? fData->parameterCount : 0;
}

uint32_t getParameterHints(const uint32_t index) const
uint32_t getParameterHints(const uint32_t index) const noexcept
{
assert(fData != nullptr && index < fData->parameterCount);
assert(index < fData->parameterCount);
return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].hints : 0x0;
}

bool isParameterIsOutput(const uint32_t index) const
bool isParameterOutput(const uint32_t index) const noexcept
{
return (getParameterHints(index) & PARAMETER_IS_OUTPUT);
}

const d_string& getParameterName(const uint32_t index) const
const d_string& getParameterName(const uint32_t index) const noexcept
{
assert(fData != nullptr && index < fData->parameterCount);
assert(index < fData->parameterCount);
return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].name : sFallbackString;
}

const d_string& getParameterSymbol(const uint32_t index) const
const d_string& getParameterSymbol(const uint32_t index) const noexcept
{
assert(fData != nullptr && index < fData->parameterCount);
assert(index < fData->parameterCount);
return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].symbol : sFallbackString;
}

const d_string& getParameterUnit(const uint32_t index) const
const d_string& getParameterUnit(const uint32_t index) const noexcept
{
assert(fData != nullptr && index < fData->parameterCount);
assert(index < fData->parameterCount);
return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].unit : sFallbackString;
}

const ParameterRanges& getParameterRanges(const uint32_t index) const
const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept
{
assert(fData != nullptr && index < fData->parameterCount);
assert(index < fData->parameterCount);
return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].ranges : sFallbackRanges;
}

float getParameterValue(const uint32_t index) const
float getParameterValue(const uint32_t index) const noexcept
{
assert(fPlugin != nullptr && index < fData->parameterCount);
assert(index < fData->parameterCount);
return (fPlugin != nullptr && index < fData->parameterCount) ? fPlugin->d_getParameterValue(index) : 0.0f;
}

void setParameterValue(const uint32_t index, const float value)
{
assert(fPlugin != nullptr && index < fData->parameterCount);
assert(index < fData->parameterCount);

if (fPlugin != nullptr && index < fData->parameterCount)
fPlugin->d_setParameterValue(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
uint32_t getProgramCount() const
uint32_t getProgramCount() const noexcept
{
assert(fData != nullptr);
return (fData != nullptr) ? fData->programCount : 0;
}

const d_string& getProgramName(const uint32_t index) const
const d_string& getProgramName(const uint32_t index) const noexcept
{
assert(fData != nullptr && index < fData->programCount);
assert(index < fData->programCount);
return (fData != nullptr && index < fData->programCount) ? fData->programNames[index] : sFallbackString;
}

void setProgram(const uint32_t index)
{
assert(fPlugin != nullptr && index < fData->programCount);
assert(index < fData->programCount);

if (fPlugin != nullptr && index < fData->programCount)
fPlugin->d_setProgram(index);
@@ -263,21 +258,20 @@ public:
#endif

#if DISTRHO_PLUGIN_WANT_STATE
uint32_t getStateCount() const
uint32_t getStateCount() const noexcept
{
assert(fData != nullptr);
return fData != nullptr ? fData->stateCount : 0;
}

const d_string& getStateKey(const uint32_t index) const
const d_string& getStateKey(const uint32_t index) const noexcept
{
assert(fData != nullptr && index < fData->stateCount);
assert(index < fData->stateCount);
return (fData != nullptr && index < fData->stateCount) ? fData->stateKeys[index] : sFallbackString;
}

void setState(const char* const key, const char* const value)
{
assert(fPlugin != nullptr && key != nullptr && value != nullptr);
assert(key != nullptr && value != nullptr);

if (fPlugin != nullptr && key != nullptr && value != nullptr)
fPlugin->d_setState(key, value);
@@ -288,33 +282,34 @@ public:

void activate()
{
assert(fPlugin != nullptr);

if (fPlugin != nullptr)
fPlugin->d_activate();
}

void deactivate()
{
assert(fPlugin != nullptr);

if (fPlugin != nullptr)
fPlugin->d_deactivate();
}

#if DISTRHO_PLUGIN_IS_SYNTH
void run(float** const inputs, float** const outputs, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount)
{
assert(fPlugin != nullptr);

if (fPlugin != nullptr)
fPlugin->d_run(inputs, outputs, frames, midiEvents, midiEventCount);
}

#else
void run(float** const inputs, float** const outputs, const uint32_t frames)
{
if (fPlugin != nullptr)
fPlugin->d_run(inputs, outputs, frames);
}
#endif
// -------------------------------------------------------------------

void setBufferSize(const uint32_t bufferSize, bool doCallback = false)
{
assert(fData != nullptr && fPlugin != nullptr && bufferSize >= 2);
assert(bufferSize >= 2);

if (fData != nullptr)
{
@@ -334,7 +329,7 @@ public:

void setSampleRate(const double sampleRate, bool doCallback = false)
{
assert(fData != nullptr && fPlugin != nullptr && sampleRate > 0.0);
assert(sampleRate > 0.0);

if (fData != nullptr)
{
@@ -352,13 +347,16 @@ public:
}
}

private:
// -------------------------------------------------------------------
// private members accessed by DistrhoPlugin class

protected:
Plugin* const fPlugin;
Plugin::PrivateData* const fData;

private:
// -------------------------------------------------------------------
// Static fallback data, see DistrhoPlugin.cpp

static const d_string sFallbackString;
static const ParameterRanges sFallbackRanges;
};


+ 116
- 101
source/modules/distrho/src/DistrhoPluginLADSPA+DSSI.cpp View File

@@ -32,8 +32,6 @@
# warning LADSPA/DSSI does not support TimePos
#endif

typedef LADSPA_Data* LADSPA_DataPtr;

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
@@ -54,8 +52,8 @@ public:
{
const uint32_t count(fPlugin.getParameterCount());

fPortControls = new LADSPA_DataPtr[count];;
fLastControlValues = new LADSPA_Data[count];;
fPortControls = new LADSPA_Data*[count];
fLastControlValues = new LADSPA_Data[count];

for (uint32_t i=0; i < count; ++i)
{
@@ -86,7 +84,19 @@ public:

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

void ladspa_connect_port(const unsigned long port, const LADSPA_DataPtr dataLocation)
void ladspa_activate()
{
fPlugin.activate();
}

void ladspa_deactivate()
{
fPlugin.deactivate();
}

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

void ladspa_connect_port(const unsigned long port, LADSPA_Data* const dataLocation)
{
unsigned long index = 0;

@@ -129,91 +139,31 @@ public:
// -------------------------------------------------------------------

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
# if DISTRHO_PLUGIN_WANT_STATE
char* dssi_configure(const char* const key, const char* const value)
{
if (strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, strlen(DSSI_RESERVED_CONFIGURE_PREFIX) == 0))
return nullptr;
if (strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, strlen(DSSI_GLOBAL_CONFIGURE_PREFIX) == 0))
return nullptr;

fPlugin.setState(key, value);
return nullptr;
}
# endif

# if DISTRHO_PLUGIN_WANT_PROGRAMS
const DSSI_Program_Descriptor* dssi_get_program(const unsigned long index)
{
if (index >= fPlugin.getProgramCount())
return nullptr;

static DSSI_Program_Descriptor desc;

desc.Bank = index / 128;
desc.Program = index % 128;
desc.Name = fPlugin.getProgramName(index);

return &desc;
}

void dssi_select_program(const unsigned long bank, const unsigned long program)
{
const unsigned long realProgram(bank * 128 + program);

if (realProgram >= fPlugin.getProgramCount())
return;

fPlugin.setProgram(realProgram);

// Update parameters
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (fPlugin.isParameterIsOutput(i))
continue;

fLastControlValues[i] = fPlugin.getParameterValue(i);

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
}
}
# endif
#endif

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

void ladspa_activate()
{
fPlugin.activate();
}

void ladspa_deactivate()
{
fPlugin.deactivate();
}

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
void ladspa_run(const unsigned long bufferSize)
void ladspa_run(const unsigned long sampleCount)
{
dssi_run_synth(bufferSize, nullptr, 0);
dssi_run_synth(sampleCount, nullptr, 0);
}

void dssi_run_synth(const unsigned long bufferSize, snd_seq_event_t* const events, const unsigned long eventCount)
void dssi_run_synth(const unsigned long sampleCount, snd_seq_event_t* const events, const unsigned long eventCount)
#else
void ladspa_run(const unsigned long bufferSize)
void ladspa_run(const unsigned long sampleCount)
#endif
{
// pre-roll
if (sampleCount == 0)
return updateParameterOutputs();

// Check for updated parameters
float curValue;

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
assert(fPortControls[i] != nullptr);
if (fPortControls[i] == nullptr)
continue;

curValue = *fPortControls[i];

if (fLastControlValues[i] != curValue && ! fPlugin.isParameterIsOutput(i))
if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i))
{
fLastControlValues[i] = curValue;
fPlugin.setParameterValue(i, curValue);
@@ -225,94 +175,157 @@ public:
uint32_t midiEventCount = 0;
MidiEvent midiEvents[eventCount];

for (uint32_t i=0, j; i < eventCount && midiEventCount < MAX_MIDI_EVENTS; ++i)
for (uint32_t i=0, j; i < eventCount; ++i)
{
const snd_seq_event_t& seqEvent(events[i]);

if (seqEvent.data.note.channel > 0xF)
if (seqEvent.data.note.channel > 0xF || seqEvent.data.control.channel > 0xF)
continue;

switch (seqEvent.type)
{
case SND_SEQ_EVENT_NOTEON:
case SND_SEQ_EVENT_NOTEOFF:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].buf[0] = 0x90 + seqEvent.data.note.channel;
midiEvents[j].size = 3;
midiEvents[j].buf[0] = 0x80 + seqEvent.data.note.channel;
midiEvents[j].buf[1] = seqEvent.data.note.note;
midiEvents[j].buf[2] = seqEvent.data.note.velocity;
midiEvents[j].buf[2] = 0;
midiEvents[j].buf[3] = 0;
midiEvents[j].size = 3;
break;
case SND_SEQ_EVENT_NOTEOFF:
case SND_SEQ_EVENT_NOTEON:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].buf[0] = 0x80 + seqEvent.data.note.channel;
midiEvents[j].size = 3;
midiEvents[j].buf[0] = 0x90 + seqEvent.data.note.channel;
midiEvents[j].buf[1] = seqEvent.data.note.note;
midiEvents[j].buf[2] = 0;
midiEvents[j].buf[2] = seqEvent.data.note.velocity;
midiEvents[j].buf[3] = 0;
midiEvents[j].size = 3;
break;
case SND_SEQ_EVENT_KEYPRESS:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].buf[0] = 0xA0 + seqEvent.data.note.channel;
midiEvents[j].buf[1] = seqEvent.data.note.note;
midiEvents[j].buf[2] = seqEvent.data.note.velocity;
midiEvents[j].buf[3] = 0;
midiEvents[j].size = 3;
break;
case SND_SEQ_EVENT_CONTROLLER:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].buf[0] = 0xB0 + seqEvent.data.control.channel;
midiEvents[j].buf[1] = seqEvent.data.control.param;
midiEvents[j].buf[2] = seqEvent.data.control.value;
midiEvents[j].buf[3] = 0;
midiEvents[j].size = 3;
break;
case SND_SEQ_EVENT_CHANPRESS:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 2;
midiEvents[j].buf[0] = 0xD0 + seqEvent.data.control.channel;
midiEvents[j].buf[1] = seqEvent.data.control.value;
midiEvents[j].buf[2] = 0;
midiEvents[j].buf[3] = 0;
midiEvents[j].size = 2;
break;
#if 0 // TODO
case SND_SEQ_EVENT_PITCHBEND:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].buf[0] = 0xE0 + seqEvent.data.control.channel;
midiEvents[j].buf[1] = 0;
midiEvents[j].buf[2] = 0;
midiEvents[j].buf[3] = 0;
midiEvents[j].size = 3;
break;
#endif
}
}

fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, midiEvents, midiEventCount);
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, midiEvents, midiEventCount);
#else
fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, nullptr, 0);
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount);
#endif

updateParameterOutputs();

#if ! DISTRHO_PLUGIN_IS_SYNTH
return; // unused
(void)events;
(void)eventCount;
#endif
}

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

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
# if DISTRHO_PLUGIN_WANT_STATE
char* dssi_configure(const char* const key, const char* const value)
{
if (std::strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, std::strlen(DSSI_RESERVED_CONFIGURE_PREFIX) == 0))
return nullptr;
if (std::strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, std::strlen(DSSI_GLOBAL_CONFIGURE_PREFIX) == 0))
return nullptr;

fPlugin.setState(key, value);
return nullptr;
}
# endif

# if DISTRHO_PLUGIN_WANT_PROGRAMS
const DSSI_Program_Descriptor* dssi_get_program(const unsigned long index)
{
if (index >= fPlugin.getProgramCount())
return nullptr;

static DSSI_Program_Descriptor desc;

desc.Bank = index / 128;
desc.Program = index % 128;
desc.Name = fPlugin.getProgramName(index);

return &desc;
}

void dssi_select_program(const unsigned long bank, const unsigned long program)
{
const unsigned long realProgram(bank * 128 + program);

if (realProgram >= fPlugin.getProgramCount())
return;

fPlugin.setProgram(realProgram);

// Update control inputs
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (fPlugin.isParameterOutput(i))
continue;

fLastControlValues[i] = fPlugin.getParameterValue(i);

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
}
}
# endif
#endif

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

private:
PluginInternal fPlugin;
PluginExporter fPlugin;

LADSPA_DataPtr fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
LADSPA_DataPtr fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
LADSPA_DataPtr* fPortControls;
// LADSPA ports
LADSPA_Data* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
LADSPA_Data* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
LADSPA_Data** fPortControls;
#if DISTRHO_PLUGIN_WANT_LATENCY
LADSPA_DataPtr fPortLatency;
LADSPA_Data* fPortLatency;
#endif

// Temporary data
LADSPA_Data* fLastControlValues;

// -------------------------------------------------------------------
@@ -321,7 +334,7 @@ private:
{
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (! fPlugin.isParameterIsOutput(i))
if (! fPlugin.isParameterOutput(i))
continue;

fLastControlValues[i] = fPlugin.getParameterValue(i);
@@ -332,7 +345,7 @@ private:

#if DISTRHO_PLUGIN_WANT_LATENCY
if (fPortLatency != nullptr)
*fPortLatency = fPlugin.latency();
*fPortLatency = fPlugin.getLatency();
#endif
}
};
@@ -468,7 +481,7 @@ public:
// Create dummy plugin to get data from
d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
PluginInternal plugin;
PluginExporter plugin;
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;

@@ -524,7 +537,7 @@ public:
portNames[port] = strdup((const char*)plugin.getParameterName(i));
portDescriptors[port] = LADSPA_PORT_CONTROL;

if (plugin.isParameterIsOutput(i))
if (plugin.isParameterOutput(i))
portDescriptors[port] |= LADSPA_PORT_OUTPUT;
else
portDescriptors[port] |= LADSPA_PORT_INPUT;
@@ -661,3 +674,5 @@ const DSSI_Descriptor* dssi_descriptor(unsigned long index)
return (index == 0) ? &sDssiDescriptor : nullptr;
}
#endif

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

+ 224
- 180
source/modules/distrho/src/DistrhoPluginLV2.cpp View File

@@ -16,17 +16,20 @@

#include "DistrhoPluginInternal.hpp"

#include "lv2/lv2.h"
#include "lv2/atom.h"
#include "lv2/atom-util.h"
#include "lv2/buf-size.h"
#include "lv2/midi.h"
#include "lv2/options.h"
#include "lv2/programs.h"
#include "lv2/state.h"
#include "lv2/time.h"
#include "lv2/urid.h"
#include "lv2/worker.h"
#include "lv2/lv2_programs.h"

// #include "lv2/atom-util.h"
// #include "lv2/midi.h"
#ifdef noexcept
# undef noexcept
#endif

#include <map>

@@ -34,9 +37,6 @@
# error DISTRHO_PLUGIN_URI undefined!
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
# warning LV2 Synth still TODO
#endif
#if DISTRHO_PLUGIN_WANT_STATE
# warning LV2 State still TODO
#endif
@@ -44,10 +44,9 @@
# warning LV2 TimePos still TODO
#endif

#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_TIMEPOS)
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_STATE)
#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)

typedef float* floatptr;
typedef std::map<d_string,d_string> StringMap;

START_NAMESPACE_DISTRHO
@@ -60,6 +59,9 @@ public:
PluginLv2(const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker)
: fPortControls(nullptr),
fLastControlValues(nullptr),
#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT
fURIDs(uridMap),
#endif
fUridMap(uridMap),
fWorker(worker)
{
@@ -70,15 +72,15 @@ public:
fPortAudioOuts[i] = nullptr;

{
const uint32_t count(fPlugin.parameterCount());
const uint32_t count(fPlugin.getParameterCount());

fPortControls = new floatptr[count];;
fLastControlValues = new float[count];;
fPortControls = new float*[count];
fLastControlValues = new float[count];

for (uint32_t i=0; i < count; ++i)
{
fPortControls[i] = nullptr;
fLastControlValues[i] = fPlugin.parameterValue(i);
fLastControlValues[i] = fPlugin.getParameterValue(i);
}
}

@@ -91,36 +93,6 @@ public:
#if DISTRHO_PLUGIN_WANT_LATENCY
fPortLatency = nullptr;
#endif

// #if DISTRHO_LV2_USE_EVENTS
// uridIdAtomString = 0;
// # if DISTRHO_PLUGIN_IS_SYNTH
// uridIdMidiEvent = 0;
// # endif
// # if DISTRHO_PLUGIN_WANT_STATE

// # endif
//
// for (uint32_t i=0; features[i]; i++)
// {
// if (strcmp(features[i]->URI, LV2_URID__map) == 0)
// {
// uridMap = (LV2_URID_Map*)features[i]->data;
//
// uridIdAtomString = uridMap->map(uridMap->handle, LV2_ATOM__String);
// # if DISTRHO_PLUGIN_IS_SYNTH
// uridIdMidiEvent = uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent);
// # endif
// # if DISTRHO_PLUGIN_WANT_STATE
// uridIdPatchMessage = uridMap->map(uridMap->handle, LV2_PATCH__Message);
// # endif
// }
// else if (strcmp(features[i]->URI, LV2_WORKER__schedule) == 0)
// {
// workerSchedule = (LV2_Worker_Schedule*)features[i]->data;
// }
// }
// #endif
}

~PluginLv2()
@@ -137,11 +109,13 @@ public:
fLastControlValues = nullptr;
}

// #if DISTRHO_PLUGIN_WANT_STATE
// stateMap.clear();
// #endif
#if DISTRHO_PLUGIN_WANT_STATE
fStateMap.clear();
#endif
}

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

void lv2_activate()
{
fPlugin.activate();
@@ -152,6 +126,8 @@ public:
fPlugin.deactivate();
}

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

void lv2_connect_port(const uint32_t port, void* const dataLocation)
{
uint32_t index = 0;
@@ -160,7 +136,7 @@ public:
{
if (port == index++)
{
fPortAudioIns[i] = (floatptr)dataLocation;
fPortAudioIns[i] = (float*)dataLocation;
return;
}
}
@@ -169,7 +145,7 @@ public:
{
if (port == index++)
{
fPortAudioOuts[i] = (floatptr)dataLocation;
fPortAudioOuts[i] = (float*)dataLocation;
return;
}
}
@@ -193,77 +169,86 @@ public:
#if DISTRHO_PLUGIN_WANT_LATENCY
if (port == index++)
{
fPortLatency = (floatptr)dataLocation;
fPortLatency = (float*)dataLocation;
return;
}
#endif

for (uint32_t i=0, count=fPlugin.parameterCount(); i < count; ++i)
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (port == index++)
{
fPortControls[i] = (floatptr)dataLocation;
fPortControls[i] = (float*)dataLocation;
return;
}
}
}

void lv2_run(const uint32_t bufferSize)
// -------------------------------------------------------------------

void lv2_run(const uint32_t sampleCount)
{
if (bufferSize == 0)
{
updateParameterOutputs();
return;
}
// pre-roll
if (sampleCount == 0)
return updateParameterOutputs();

// Check for updated parameters
float curValue;

for (uint32_t i=0, count=fPlugin.parameterCount(); i < count; ++i)
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
assert(fPortControls[i] != nullptr);
if (fPortControls[i] == nullptr)
continue;

curValue = *fPortControls[i];

if (fLastControlValues[i] != curValue && ! fPlugin.parameterIsOutput(i))
if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i))
{
fLastControlValues[i] = curValue;
fPlugin.setParameterValue(i, curValue);
}
}

#if DISTRHO_PLUGIN_IS_SYNTH
// Get Events, xxx
#if DISTRHO_LV2_USE_EVENTS_IN
# if DISTRHO_PLUGIN_IS_SYNTH
uint32_t midiEventCount = 0;

#if DISTRHO_LV2_USE_EVENTS
LV2_ATOM_SEQUENCE_FOREACH(portEventsIn, iter)
# endif
LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event)
{
const LV2_Atom_Event* event = /*(const LV2_Atom_Event*)*/iter;

if (! event)
continue;
if (event == nullptr)
break;

# if DISTRHO_PLUGIN_IS_SYNTH
if (event->body.type == uridIdMidiEvent)
if (event->body.type == fURIDs.midiEvent)
{
if (event->time.frames >= bufferSize || midiEventCount >= MAX_MIDI_EVENTS)
break;

if (event->body.size > 3)
if (event->body.size > 4 || midiEventCount >= kMaxMidiEvents)
continue;

const uint8_t* data = (const uint8_t*)(event + 1);
const uint8_t* data((const uint8_t*)(event + 1));

MidiEvent& midiEvent(fMidiEvents[midiEventCount]);

midiEvent.frame = event->time.frames;
midiEvent.size = event->body.size;

midiEvents[midiEventCount].frame = event->time.frames;
memcpy(midiEvents[midiEventCount].buffer, data, event->body.size);
uint8_t i;
for (i=0; i < midiEvent.size; ++i)
midiEvent.buf[i] = data[i];
for (; i < 4; ++i)
midiEvent.buf[i] = 0;

midiEventCount += 1;
++midiEventCount;
continue;
}
# endif
# if DISTRHO_PLUGIN_WANT_STATE
if (event->body.type == uridIdPatchMessage)
# if DISTRHO_PLUGIN_WANT_TIMEPOS
if (event->body.type == fURIDs.timePosition)
{
// TODO
}
# endif
# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
//if (event->body.type == fURIDs.midiEvent)
{
// TODO
//if (workerSchedule)
@@ -273,18 +258,38 @@ public:
}
#endif

fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, midiEventCount, midiEvents);
#if DISTRHO_PLUGIN_IS_SYNTH
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount);
#else
fPlugin.run(fPortAudioIns, fPortAudioOuts, bufferSize, 0, nullptr);
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount);
#endif

#if DISTRHO_LV2_USE_EVENTS_OUT
LV2_ATOM_SEQUENCE_FOREACH(fPortEventsOut, event)
{
if (event == nullptr)
break;

# if DISTRHO_PLUGIN_WANT_STATE
if (event->body.type == fURIDs.midiEvent)
{
// TODO
//if (workerSchedule)
// workerSchedule->schedule_work(workerSchedule->handle, event->body.size, )
}
# endif
}
#endif

updateParameterOutputs();
}

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

uint32_t lv2_get_options(LV2_Options_Option* const /*options*/)
{
// currently unused
return LV2_OPTIONS_SUCCESS;
return LV2_OPTIONS_ERR_UNKNOWN;
}

uint32_t lv2_set_options(const LV2_Options_Option* const options)
@@ -297,9 +302,13 @@ public:
{
const int bufferSize(*(const int*)options[i].value);
fPlugin.setBufferSize(bufferSize);
return LV2_OPTIONS_SUCCESS;
}
else
{
d_stderr("Host changed maxBlockLength but with wrong value type");
return LV2_OPTIONS_ERR_BAD_VALUE;
}
}
else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate))
{
@@ -307,26 +316,32 @@ public:
{
const double sampleRate(*(const double*)options[i].value);
fPlugin.setSampleRate(sampleRate);
return LV2_OPTIONS_SUCCESS;
}
else
{
d_stderr("Host changed sampleRate but with wrong value type");
return LV2_OPTIONS_ERR_BAD_VALUE;
}
}
}

return LV2_OPTIONS_SUCCESS;
return LV2_OPTIONS_ERR_BAD_KEY;
}

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

#if DISTRHO_PLUGIN_WANT_PROGRAMS
const LV2_Program_Descriptor* lv2_get_program(const uint32_t index)
{
if (index >= fPlugin.programCount())
if (index >= fPlugin.getProgramCount())
return nullptr;

static LV2_Program_Descriptor desc;

desc.bank = index / 128;
desc.program = index % 128;
desc.name = fPlugin.programName(index);
desc.name = fPlugin.getProgramName(index);

return &desc;
}
@@ -335,64 +350,68 @@ public:
{
const uint32_t realProgram(bank * 128 + program);

if (realProgram >= fPlugin.programCount())
if (realProgram >= fPlugin.getProgramCount())
return;

fPlugin.setProgram(realProgram);

// Update parameters
for (uint32_t i=0, count=fPlugin.parameterCount(); i < count; ++i)
// Update control inputs
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (! fPlugin.parameterIsOutput(i))
{
fLastControlValues[i] = fPlugin.parameterValue(i);
if (fPlugin.isParameterOutput(i))
continue;

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
}
fLastControlValues[i] = fPlugin.getParameterValue(i);

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
}
}
#endif

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

#if DISTRHO_PLUGIN_WANT_STATE
LV2_State_Status lv2_save(LV2_State_Store_Function store, LV2_State_Handle handle, const uint32_t flags, const LV2_Feature* const* /*features*/)
LV2_State_Status lv2_save(LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* /*features*/)
{
// flags = LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE;
flags = LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE;

// for (auto i = stateMap.begin(); i != stateMap.end(); i++)
// {
// const d_string& key = i->first;
// const d_string& value = i->second;
//
// store(handle, uridMap->map(uridMap->handle, (const char*)key), (const char*)value, value.length(), uridIdAtomString, flags);
// }
for (auto it = fStateMap.begin(), end = fStateMap.end(); it != end; ++it)
{
const d_string& key = it->first;
const d_string& value = it->second;
store(handle, fUridMap->map(fUridMap->handle, (const char*)key), (const char*)value, value.length()+1, fURIDs.atomString, flags);
}

return LV2_STATE_SUCCESS;
}

LV2_State_Status lv2_restore(LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, const uint32_t flags, const LV2_Feature* const* /*features*/)
LV2_State_Status lv2_restore(LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* /*features*/)
{
// size_t size;
// uint32_t type;
// for (uint32_t i=0; i < plugin.stateCount(); i++)
// {
// const d_string& key = plugin.stateKey(i);
//
// const void* data = retrieve(handle, uridMap->map(uridMap->handle, (const char*)key), &size, &type, &flags);
//
// if (size == 0 || ! data)
// continue;
// if (type != uridIdAtomString)
// continue;
//
// const char* value = (const char*)data;
// setState(key, value);
// }
size_t size;
uint32_t type;
for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
{
const d_string& key = fPlugin.getStateKey(i);
const void* data = retrieve(handle, fUridMap->map(fUridMap->handle, (const char*)key), &size, &type, &flags);
if (size == 0 || data == nullptr)
continue;
if (type != fURIDs.atomString)
continue;
//const char* value = (const char*)data;
//setState(key, value);
}

return LV2_STATE_SUCCESS;
}

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

LV2_Worker_Status lv2_work(LV2_Worker_Respond_Function /*respond*/, LV2_Worker_Respond_Handle /*handle*/, const uint32_t /*size*/, const void* /*data*/)
{
// TODO
@@ -406,13 +425,15 @@ public:
}
#endif

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

private:
PluginInternal fPlugin;
PluginExporter fPlugin;

// LV2 ports
floatptr fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
floatptr fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
floatptr* fPortControls;
float* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
float* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
float** fPortControls;
#if DISTRHO_LV2_USE_EVENTS_IN
LV2_Atom_Sequence* fPortEventsIn;
#endif
@@ -420,75 +441,74 @@ private:
LV2_Atom_Sequence* fPortEventsOut;
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY
floatptr fPortLatency;
float* fPortLatency;
#endif

// Temporary data
float* fLastControlValues;
#if DISTRHO_PLUGIN_IS_SYNTH
MidiEvent fMidiEvents[kMaxMidiEvents];
#endif

// #if DISTRHO_PLUGIN_IS_SYNTH
// MidiEvent fMidiEvents[MAX_MIDI_EVENTS];
// #endif
// LV2 URIDs
#if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT
struct URIDs {
LV2_URID atomString;
LV2_URID midiEvent;
LV2_URID timePosition;

URIDs(const LV2_URID_Map* const uridMap)
: atomString(uridMap->map(uridMap->handle, LV2_ATOM__String)),
midiEvent(uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent)),
timePosition(uridMap->map(uridMap->handle, LV2_TIME__Position)) {}
} fURIDs;
#endif

// Feature data
// LV2 features
const LV2_URID_Map* const fUridMap;
const LV2_Worker_Schedule* const fWorker;

// xxx
// #if DISTRHO_LV2_USE_EVENTS
//
// // URIDs
// LV2_URID_Map* uridMap;
// LV2_URID uridIdAtomString;
// # if DISTRHO_PLUGIN_IS_SYNTH
// LV2_URID uridIdMidiEvent;
// # endif
// # if DISTRHO_PLUGIN_WANT_STATE
// LV2_URID uridIdPatchMessage;
// LV2_Worker_Schedule* workerSchedule;
// # endif
// #endif

// #if DISTRHO_PLUGIN_WANT_STATE
// stringMap stateMap;
//
// void setState(const char* newKey, const char* newValue)
// {
// plugin.setState(newKey, newValue);
//
// // check if key already exists
// for (auto i = stateMap.begin(); i != stateMap.end(); i++)
// {
// const d_string& key = i->first;
//
// if (key == newKey)
// {
// i->second = newValue;
// return;
// }
// }
//
// // add a new one then
// stateMap[newKey] = newValue;
// }
// #endif
#if DISTRHO_PLUGIN_WANT_STATE
StringMap fStateMap;

void updateParameterOutputs()
void setState(const char* const newKey, const char* const newValue)
{
for (uint32_t i=0, count=fPlugin.parameterCount(); i < count; ++i)
fPlugin.setState(newKey, newValue);

// check if key already exists
for (auto it = fStateMap.begin(), end = fStateMap.end(); it != end; ++it)
{
if (fPlugin.parameterIsOutput(i))
{
fLastControlValues[i] = fPlugin.parameterValue(i);
const d_string& key = it->first;

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
if (key == newKey)
{
it->second = newValue;
return;
}
}

// add a new one then
d_string d_key(newKey);
fStateMap[d_key] = newValue;
}
#endif

void updateParameterOutputs()
{
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (! fPlugin.isParameterOutput(i))
continue;

fLastControlValues[i] = fPlugin.getParameterValue(i);

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
}

#if DISTRHO_PLUGIN_WANT_LATENCY
if (fPortLatency != nullptr)
*fPortLatency = fPlugin.latency();
*fPortLatency = fPlugin.getLatency();
#endif
}
};
@@ -511,12 +531,26 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons
worker = (const LV2_Worker_Schedule*)features[i]->data;
}

if (options == nullptr)
{
d_stderr("Options feature missing, cannot continue!");
return nullptr;
}

if (uridMap == nullptr)
{
d_stderr("URID Map feature missing, cannot continue!");
return nullptr;
}

#if DISTRHO_PLUGIN_WANT_STATE
if (worker == nullptr)
{
d_stderr("Worker feature missing, cannot continue!");
return nullptr;
}
#endif

for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
@@ -531,7 +565,7 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons
}

if (d_lastBufferSize == 0)
d_lastBufferSize = 512;
d_lastBufferSize = 2048;

d_lastSampleRate = sampleRate;

@@ -565,6 +599,8 @@ static void lv2_cleanup(LV2_Handle instance)
delete instancePtr;
}

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

static uint32_t lv2_get_options(LV2_Handle instance, LV2_Options_Option* options)
{
return instancePtr->lv2_get_options(options);
@@ -575,6 +611,8 @@ static uint32_t lv2_set_options(LV2_Handle instance, const LV2_Options_Option* o
return instancePtr->lv2_set_options(options);
}

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

#if DISTRHO_PLUGIN_WANT_PROGRAMS
static const LV2_Program_Descriptor* lv2_get_program(LV2_Handle instance, uint32_t index)
{
@@ -587,6 +625,8 @@ static void lv2_select_program(LV2_Handle instance, uint32_t bank, uint32_t prog
}
#endif

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

#if DISTRHO_PLUGIN_WANT_STATE
static LV2_State_Status lv2_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features)
{
@@ -609,6 +649,8 @@ LV2_Worker_Status lv2_work_response(LV2_Handle instance, uint32_t size, const vo
}
#endif

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

static const void* lv2_extension_data(const char* uri)
{
static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options };
@@ -640,7 +682,7 @@ static const void* lv2_extension_data(const char* uri)

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

static LV2_Descriptor sLv2Descriptor = {
static const LV2_Descriptor sLv2Descriptor = {
DISTRHO_PLUGIN_URI,
lv2_instantiate,
lv2_connect_port,
@@ -661,3 +703,5 @@ const LV2_Descriptor* lv2_descriptor(uint32_t index)
USE_NAMESPACE_DISTRHO
return (index == 0) ? &sLv2Descriptor : nullptr;
}

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

+ 78
- 80
source/modules/distrho/src/DistrhoPluginLV2export.cpp View File

@@ -16,18 +16,17 @@

#include "DistrhoPluginInternal.hpp"

#include "lv2/lv2.h"
#include "lv2/atom.h"
#include "lv2/buf-size.h"
// #include "lv2/midi.h"
#include "lv2/midi.h"
#include "lv2/options.h"
#include "lv2/programs.h"
// #include "lv2/state.h"
#include "lv2/state.h"
#include "lv2/time.h"
// #include "lv2/ui.h"
#include "lv2/urid.h"
#include "lv2/ui.h"
#include "lv2/units.h"
// #include "lv2/worker.h"
#include "lv2/urid.h"
#include "lv2/worker.h"
#include "lv2/lv2_programs.h"

#include <fstream>
#include <iostream>
@@ -36,20 +35,8 @@
# error DISTRHO_PLUGIN_URI undefined!
#endif

// TODO: UI
#undef DISTRHO_PLUGIN_HAS_UI

#undef DISTRHO_PLUGIN_WANT_LATENCY
#undef DISTRHO_PLUGIN_WANT_PROGRAMS
#undef DISTRHO_PLUGIN_WANT_STATE
#undef DISTRHO_PLUGIN_WANT_TIMEPOS
#define DISTRHO_PLUGIN_WANT_LATENCY 1
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1
#define DISTRHO_PLUGIN_WANT_STATE 1
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1

#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_TIMEPOS)
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_STATE)
#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)

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

@@ -61,7 +48,7 @@ void lv2_generate_ttl(const char* const basename)
// Dummy plugin to get data from
d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
PluginInternal plugin;
PluginExporter plugin;
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;

@@ -99,14 +86,18 @@ void lv2_generate_ttl(const char* const basename)
# else
manifestString += " a ui:X11UI ;\n";
# endif
manifestString += " ui:binary <" + pluginLabel + "_ui." DISTRHO_DLL_EXTENSION "> .\n";
// # if DISTRHO_LV2_USE_EVENTS
// manifestString += " lv2:optionalFeature <" LV2_URID__map "> ,\n";
// manifestString += " ui:noUserResize .\n";
// # else
// manifestString += " lv2:optionalFeature ui:noUserResize .\n";
// # endif
manifestString += "\n";
manifestString += " ui:binary <" + pluginLabel + "_ui." DISTRHO_DLL_EXTENSION "> ;\n";
#if DISTRHO_PLUGIN_WANT_PROGRAMS
manifestString += " lv2:extensionData ui:idleInterface ,\n";
manifestString += " <" LV2_PROGRAMS__Interface "> ;\n";
#else
manifestString += " lv2:extensionData ui:idleInterface ;\n";
#endif
manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
manifestString += " ui:touch ;\n";
manifestString += " lv2:requiredFeature ui:resize ,\n";
manifestString += " <" LV2_OPTIONS__options "> ,\n";
manifestString += " <" LV2_URID__map "> .\n";
#endif

manifestFile << manifestString << std::endl;
@@ -121,6 +112,8 @@ void lv2_generate_ttl(const char* const basename)
std::fstream pluginFile(pluginTTL, std::ios::out);

d_string pluginString;

// header
#if DISTRHO_LV2_USE_EVENTS_IN
pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
#endif
@@ -133,6 +126,7 @@ void lv2_generate_ttl(const char* const basename)
pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n";
pluginString += "\n";

// plugin
pluginString += "<" DISTRHO_PLUGIN_URI ">\n";
#if DISTRHO_PLUGIN_IS_SYNTH
pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n";
@@ -141,35 +135,31 @@ void lv2_generate_ttl(const char* const basename)
#endif
pluginString += "\n";

#if (DISTRHO_PLUGIN_WANT_STATE || DISTRHO_PLUGIN_WANT_PROGRAMS)
pluginString += " lv2:extensionData <" LV2_OPTIONS__interface "> ,\n";
# if DISTRHO_PLUGIN_WANT_STATE
pluginString += " <" LV2_STATE__interface "> ,\n";
pluginString += " <" LV2_WORKER__interface "> \n";
# if DISTRHO_PLUGIN_WANT_PROGRAMS
pluginString += ",\n";
# else
pluginString += ";\n";
# endif
# endif
# if DISTRHO_PLUGIN_WANT_PROGRAMS
pluginString += " <" LV2_PROGRAMS__Interface "> ;\n";
# endif
// extensionData
pluginString += " lv2:extensionData <" LV2_OPTIONS__interface "> ";
#if DISTRHO_PLUGIN_WANT_STATE
pluginString += ",\n <" LV2_OPTIONS__interface "> ";
pluginString += ",\n <" LV2_WORKER__interface "> ";
#endif
pluginString += "\n";
#if DISTRHO_PLUGIN_WANT_PROGRAMS
pluginString += ",\n <" LV2_PROGRAMS__Interface "> ";
#endif
pluginString += ";\n\n";

#if DISTRHO_PLUGIN_WANT_STATE
// optionalFeatures
pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n";
pluginString += " <" LV2_WORKER__schedule "> ;\n";
#else
pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ;\n";
#endif
pluginString += " <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
pluginString += "\n";

pluginString += " lv2:requiredFeature <" LV2_BUF_SIZE__boundedBlockLength "> ,\n";
pluginString += " <" LV2_URID__map "> ;\n";
pluginString += "\n";
// requiredFeatures
pluginString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ";
pluginString += ",\n <" LV2_URID__map "> ";
#if DISTRHO_PLUGIN_WANT_STATE
pluginString += ",\n <" LV2_WORKER__schedule "> ";
#endif
pluginString += ";\n\n";

// UI
#if DISTRHO_PLUGIN_HAS_UI
pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n";
pluginString += "\n";
@@ -178,7 +168,7 @@ void lv2_generate_ttl(const char* const basename)
{
uint32_t portIndex = 0;

for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
{
if (i == 0)
pluginString += " lv2:port [\n";
@@ -186,7 +176,7 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " [\n";

pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";
pluginString += " lv2:index " + d_string(portIndex++) + " ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:symbol \"lv2_audio_in_" + d_string(i+1) + "\" ;\n";
pluginString += " lv2:name \"Audio Input " + d_string(i+1) + "\" ;\n";

@@ -196,7 +186,7 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " ] ,\n";
}

for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
{
if (i == 0)
pluginString += " lv2:port [\n";
@@ -204,7 +194,7 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " [\n";

pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";
pluginString += " lv2:index " + d_string(portIndex++) + " ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:symbol \"lv2_audio_out_" + d_string(i+1) + "\" ;\n";
pluginString += " lv2:name \"Audio Output " + d_string(i+1) + "\" ;\n";

@@ -217,19 +207,22 @@ void lv2_generate_ttl(const char* const basename)
#if DISTRHO_LV2_USE_EVENTS_IN
pluginString += " lv2:port [\n";
pluginString += " a lv2:InputPort, atom:AtomPort ;\n";
pluginString += " lv2:index " + d_string(portIndex++) + " ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:name \"Events Input\" ;\n";
pluginString += " lv2:symbol \"lv2_events_in\" ;\n";
pluginString += " atom:bufferType atom:Sequence ;\n";
# if (DISTRHO_PLUGIN_IS_SYNTH && DISTRHO_PLUGIN_WANT_TIMEPOS) // TODO
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ,\n";
pluginString += " <" LV2_TIME__Position "> ;\n";
# elif DISTRHO_PLUGIN_IS_SYNTH
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
# else
# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
# endif
# if DISTRHO_PLUGIN_WANT_TIMEPOS
pluginString += " atom:supports <" LV2_TIME__Position "> ;\n";
# endif
# if DISTRHO_PLUGIN_IS_SYNTH
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
# endif

pluginString += " ] ;\n";
++portIndex;
#endif

#if DISTRHO_LV2_USE_EVENTS_OUT
@@ -239,38 +232,41 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " lv2:name \"Events Output\" ;\n";
pluginString += " lv2:symbol \"lv2_events_out\" ;\n";
pluginString += " atom:bufferType atom:Sequence ;\n";
pluginString += " atom:supports <something_here> ;\n"; // TODO
pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
pluginString += " ] ;\n";
++portIndex;
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
pluginString += " lv2:port [\n";
pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
pluginString += " lv2:index " + d_string(portIndex++) + " ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:name \"Latency\" ;\n";
pluginString += " lv2:symbol \"lv2_latency\" ;\n";
pluginString += " lv2:designation lv2:latency ;\n";
pluginString += " lv2:portProperty lv2:reportsLatency ;\n";
pluginString += " ] ;\n";
++portIndex;
#endif

for (uint32_t i=0; i < plugin.parameterCount(); ++i)
for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i, ++portIndex)
{
if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";

if (plugin.parameterIsOutput(i))
if (plugin.isParameterOutput(i))
pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
else
pluginString += " a lv2:InputPort, lv2:ControlPort ;\n";

pluginString += " lv2:index " + d_string(portIndex++) + " ;\n";
pluginString += " lv2:name \"" + plugin.parameterName(i) + "\" ;\n";
pluginString += " lv2:index " + d_string(portIndex) + " ;\n";
pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";

// symbol
{
d_string symbol(plugin.parameterSymbol(i));
d_string symbol(plugin.getParameterSymbol(i));

if (symbol.isEmpty())
symbol = "lv2_port_" + d_string(portIndex-1);
@@ -280,17 +276,17 @@ void lv2_generate_ttl(const char* const basename)

// ranges
{
const ParameterRanges& ranges(plugin.parameterRanges(i));
const ParameterRanges& ranges(plugin.getParameterRanges(i));

if (plugin.parameterHints(i) & PARAMETER_IS_INTEGER)
if (plugin.getParameterHints(i) & PARAMETER_IS_INTEGER)
{
pluginString += " lv2:default " + d_string(int(plugin.parameterValue(i))) + " ;\n";
pluginString += " lv2:default " + d_string(int(plugin.getParameterValue(i))) + " ;\n";
pluginString += " lv2:minimum " + d_string(int(ranges.min)) + " ;\n";
pluginString += " lv2:maximum " + d_string(int(ranges.max)) + " ;\n";
}
else
{
pluginString += " lv2:default " + d_string(plugin.parameterValue(i)) + " ;\n";
pluginString += " lv2:default " + d_string(plugin.getParameterValue(i)) + " ;\n";
pluginString += " lv2:minimum " + d_string(ranges.min) + " ;\n";
pluginString += " lv2:maximum " + d_string(ranges.max) + " ;\n";
}
@@ -298,7 +294,7 @@ void lv2_generate_ttl(const char* const basename)

// unit
{
const d_string& unit(plugin.parameterUnit(i));
const d_string& unit(plugin.getParameterUnit(i));

if (! unit.isEmpty())
{
@@ -332,7 +328,7 @@ void lv2_generate_ttl(const char* const basename)

// hints
{
const uint32_t hints(plugin.parameterHints(i));
const uint32_t hints(plugin.getParameterHints(i));

if (hints & PARAMETER_IS_BOOLEAN)
pluginString += " lv2:portProperty lv2:toggled ;\n";
@@ -340,17 +336,19 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " lv2:portProperty lv2:integer ;\n";
if (hints & PARAMETER_IS_LOGARITHMIC)
pluginString += " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ;\n";
if ((hints & PARAMETER_IS_AUTOMABLE) == 0 && ! plugin.isParameterOutput(i))
pluginString += " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#expensive> ;\n";
}

if (i+1 == plugin.parameterCount())
if (i+1 == count)
pluginString += " ] ;\n\n";
else
pluginString += " ] ,\n";
}
}

pluginString += " doap:name \"" + d_string(plugin.name()) + "\" ;\n";
pluginString += " doap:maintainer [ foaf:name \"" + d_string(plugin.maker()) + "\" ] .\n";
pluginString += " doap:name \"" + d_string(plugin.getName()) + "\" ;\n";
pluginString += " doap:maintainer [ foaf:name \"" + d_string(plugin.getMaker()) + "\" ] .\n";

pluginFile << pluginString << std::endl;
pluginFile.close();


+ 167
- 226
source/modules/distrho/src/DistrhoPluginVST.cpp View File

@@ -18,9 +18,6 @@

#if DISTRHO_PLUGIN_HAS_UI
# include "DistrhoUIInternal.hpp"
# ifdef DISTRHO_UI_QT
# include <QtGui/QApplication>
# endif
#endif

#ifndef __cdecl
@@ -40,62 +37,27 @@ START_NAMESPACE_DISTRHO

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

#if DISTRHO_PLUGIN_HAS_UI

# ifdef DISTRHO_UI_QT
class QStaticScopedAppInit
void strncpy(char* const dst, const char* const src, const size_t size)
{
public:
QStaticScopedAppInit()
: fApp(nullptr),
fInitiated(false) {}

void initIfNeeded()
{
if (fInitiated)
return;

fInitiated = true;

if (QApplication* app = qApp)
{
fApp = app;
}
else
{
static int qargc = 0;
static char* qargv[] = { nullptr };
fApp = new QApplication(qargc, qargv, true);
fApp->setQuitOnLastWindowClosed(false);
}
}

void idle()
{
initIfNeeded();
fApp->processEvents();
}

private:
QApplication* fApp;
bool fInitiated;
};
std::strncpy(dst, src, size);
dst[size] = '\0';
}

static QStaticScopedAppInit sApp;
# endif
// -----------------------------------------------------------------------

#if DISTRHO_PLUGIN_HAS_UI
class UIVst
{
public:
UIVst(audioMasterCallback audioMaster, AEffect* effect, PluginInternal* plugin, intptr_t winId)
: kAudioMaster(audioMaster),
kEffect(effect),
kPlugin(plugin),
fUi(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback),
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, PluginExporter* const plugin, const intptr_t winId)
: fAudioMaster(audioMaster),
fEffect(effect),
fPlugin(plugin),
fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback),
fParameterChecks(nullptr),
fParameterValues(nullptr)
{
const uint32_t paramCount(plugin->parameterCount());
const uint32_t paramCount(plugin->getParameterCount());

if (paramCount > 0)
{
@@ -112,10 +74,6 @@ public:
#if DISTRHO_PLUGIN_WANT_PROGRAMS
fNextProgram = -1;
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
fMidiEventCount = 0;
#endif
}

~UIVst()
@@ -140,54 +98,49 @@ public:
#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fNextProgram != -1)
{
fUi.programChanged(fNextProgram);
fUI.programChanged(fNextProgram);
fNextProgram = -1;
}
#endif

for (uint32_t i=0, count = kPlugin->parameterCount(); i < count; ++i)
for (uint32_t i=0, count = fPlugin->getParameterCount(); i < count; ++i)
{
if (fParameterChecks[i])
{
fParameterChecks[i] = false;

fUi.parameterChanged(i, fParameterValues[i]);
fUI.parameterChanged(i, fParameterValues[i]);
}
}

#if DISTRHO_PLUGIN_IS_SYNTH
// TODO - notes
#endif

fUi.idle();
fUI.idle();
}

int16_t getWidth() const
int16_t getWidth() const noexcept
{
return fUi.width();
return fUI.getWidth();
}

int16_t getHeight() const
int16_t getHeight() const noexcept
{
return fUi.height();
return fUI.getHeight();
}

// -------------------------------------------------------------------
// functions called from the plugin side, RT no block

void setParameterValueFromPlugin(uint32_t index, float perValue)
void setParameterValueFromPlugin(const uint32_t index, const float perValue)
{
fParameterChecks[index] = true;
fParameterValues[index] = perValue;
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void setProgramFromPlugin(uint32_t index)
void setProgramFromPlugin(const uint32_t index)
{
fNextProgram = index;

// set previous parameters invalid
for (uint32_t i=0, count = kPlugin->parameterCount(); i < count; ++i)
for (uint32_t i=0, count = fPlugin->getParameterCount(); i < count; ++i)
fParameterChecks[i] = false;
}
#endif
@@ -195,12 +148,12 @@ public:
// -------------------------------------------------------------------

protected:
intptr_t hostCallback(int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
intptr_t hostCallback(const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
{
return kAudioMaster(kEffect, opcode, index, value, ptr, opt);
return fAudioMaster(fEffect, opcode, index, value, ptr, opt);
}

void editParameter(uint32_t index, bool started)
void editParameter(const uint32_t index, const bool started)
{
if (started)
hostCallback(audioMasterBeginEdit, index, 0, nullptr, 0.0f);
@@ -208,61 +161,59 @@ protected:
hostCallback(audioMasterEndEdit, index, 0, nullptr, 0.0f);
}

void setParameterValue(uint32_t index, float realValue)
void setParameterValue(const uint32_t index, const float realValue)
{
const ParameterRanges& ranges(kPlugin->parameterRanges(index));
const float perValue(ranges.normalizedValue(realValue));
const ParameterRanges& ranges(fPlugin->getParameterRanges(index));
const float perValue(ranges.getNormalizedValue(realValue));

kPlugin->setParameterValue(index, realValue);
fPlugin->setParameterValue(index, realValue);
hostCallback(audioMasterAutomate, index, 0, nullptr, perValue);
}

void setState(const char* key, const char* value)
void setState(const char* const key, const char* const value)
{
#if DISTRHO_PLUGIN_WANT_STATE
kPlugin->setState(key, value);
fPlugin->setState(key, value);
#else
return; // unused
(void)key;
(void)value;
#endif
}

void sendNote(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{
#if DISTRHO_PLUGIN_IS_SYNTH
// TODO
#endif
return;

// unused
(void)onOff;
#else
return; // unused
(void)channel;
(void)note;
(void)velocity;
#endif
}

void uiResize(unsigned int width, unsigned int height)
void uiResize(const unsigned int width, const unsigned int height)
{
fUI.setSize(width, height);
hostCallback(audioMasterSizeWindow, width, height, nullptr, 0.0f);
}

private:
// Vst stuff
audioMasterCallback const kAudioMaster;
AEffect* const kEffect;
PluginInternal* const kPlugin;
const audioMasterCallback fAudioMaster;
AEffect* const fEffect;
PluginExporter* const fPlugin;

// Plugin UI
UIInternal fUi;
UIExporter fUI;

// Temporary data
bool* fParameterChecks;
float* fParameterValues;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
int32_t fNextProgram;
#endif
#if DISTRHO_PLUGIN_IS_SYNTH
uint32_t fMidiEventCount;
MidiEvent fMidiEvents[MAX_MIDI_EVENTS];
#endif

// -------------------------------------------------------------------
// Callbacks
@@ -284,9 +235,9 @@ private:
handlePtr->setState(key, value);
}

static void sendNoteCallback(void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
{
handlePtr->sendNote(onOff, channel, note, velocity);
handlePtr->sendNote(channel, note, velocity);
}

static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height)
@@ -303,18 +254,10 @@ private:
class PluginVst
{
public:
PluginVst(audioMasterCallback audioMaster, AEffect* effect)
: kAudioMaster(audioMaster),
kEffect(effect)
PluginVst(const audioMasterCallback audioMaster, AEffect* const effect)
: fAudioMaster(audioMaster),
fEffect(effect)
{
#if DISTRHO_PLUGIN_HAS_UI
fVstUi = nullptr;
fVstRect.top = 0;
fVstRect.left = 0;
fVstRect.bottom = 0;
fVstRect.right = 0;
#endif

#if DISTRHO_PLUGIN_WANT_PROGRAMS
fCurProgram = -1;
#endif
@@ -322,13 +265,17 @@ public:
#if DISTRHO_PLUGIN_IS_SYNTH
fMidiEventCount = 0;
#endif
}

~PluginVst()
{
#if DISTRHO_PLUGIN_HAS_UI
fVstUi = nullptr;
fVstRect.top = 0;
fVstRect.left = 0;
fVstRect.bottom = 0;
fVstRect.right = 0;
#endif
}

intptr_t vst_dispatcher(int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
intptr_t vst_dispatcher(const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
{
int32_t ret = 0;

@@ -336,7 +283,7 @@ public:
{
#if DISTRHO_PLUGIN_WANT_PROGRAMS
case effSetProgram:
if (value >= 0 && value < static_cast<intptr_t>(fPlugin.programCount()))
if (value >= 0 && value < static_cast<intptr_t>(fPlugin.getProgramCount()))
{
fCurProgram = value;
fPlugin.setProgram(fCurProgram);
@@ -359,21 +306,19 @@ public:
break;

case effGetProgramName:
if (ptr != nullptr && fCurProgram >= 0 && fCurProgram < static_cast<int32_t>(fPlugin.programCount()))
if (ptr != nullptr && fCurProgram >= 0 && fCurProgram < static_cast<int32_t>(fPlugin.getProgramCount()))
{
char* buf = (char*)ptr;
std::strncpy(buf, fPlugin.programName(fCurProgram), kVstMaxProgNameLen);
buf[kVstMaxProgNameLen] = '\0';
DISTRHO::strncpy((char*)ptr, fPlugin.getProgramName(fCurProgram), kVstMaxProgNameLen);
ret = 1;
}
break;
#endif

case effGetParamDisplay:
if (ptr != nullptr && index < static_cast<int32_t>(fPlugin.parameterCount()))
if (ptr != nullptr && index < static_cast<int32_t>(fPlugin.getParameterCount()))
{
char* buf = (char*)ptr;
std::snprintf((char*)ptr, kVstMaxParamStrLen, "%f", fPlugin.parameterValue(index));
std::snprintf((char*)ptr, kVstMaxParamStrLen, "%f", fPlugin.getParameterValue(index));
buf[kVstMaxParamStrLen] = '\0';
ret = 1;
}
@@ -396,14 +341,40 @@ public:

#if DISTRHO_PLUGIN_HAS_UI
case effEditGetRect:
createUiIfNeeded(0);
if (fVstUi != nullptr)
{
fVstRect.right = fVstUi->getWidth();
fVstRect.bottom = fVstUi->getHeight();
}
else
{
d_lastUiSampleRate = fAudioMaster(fEffect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f);
UIExporter tmpUI(nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr);
fVstRect.right = tmpUI.getWidth();
fVstRect.bottom = tmpUI.getHeight();
}
*(ERect**)ptr = &fVstRect;
ret = 1;
break;

case effEditOpen:
createUiIfNeeded((intptr_t)ptr); // FIXME - use FromVstPtr<>
ret = 1;
if (fVstUi == nullptr)
{
d_lastUiSampleRate = fAudioMaster(fEffect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f);

fVstUi = new UIVst(fAudioMaster, fEffect, &fPlugin, (intptr_t)ptr);

# if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fCurProgram >= 0)
fVstUi->setProgramFromPlugin(fCurProgram);
# endif
for (uint32_t i=0, count = fPlugin.getParameterCount(); i < count; ++i)
fVstUi->setParameterValueFromPlugin(i, fPlugin.getParameterValue(i));

fVstUi->idle();

ret = 1;
}
break;

case effEditClose:
@@ -411,9 +382,6 @@ public:
{
delete fVstUi;
fVstUi = nullptr;
# ifdef DISTRHO_UI_QT4
sApp.idle();
# endif
ret = 1;
}
break;
@@ -421,9 +389,6 @@ public:
case effEditIdle:
if (fVstUi != nullptr)
fVstUi->idle();
# ifdef DISTRHO_UI_QT4
sApp.idle();
# endif
break;
#endif

@@ -445,9 +410,9 @@ public:
#endif

case effCanBeAutomated:
if (index < static_cast<int32_t>(fPlugin.parameterCount()))
if (index < static_cast<int32_t>(fPlugin.getParameterCount()))
{
uint32_t hints = fPlugin.parameterHints(index);
const uint32_t hints(fPlugin.getParameterHints(index));

// must be automable, and not output
if ((hints & PARAMETER_IS_AUTOMABLE) != 0 && (hints & PARAMETER_IS_OUTPUT) == 0)
@@ -457,8 +422,14 @@ public:

case effCanDo:
#if DISTRHO_PLUGIN_IS_SYNTH
if (const char* const canDo = (const char*)ptr)
{
if (std::strcmp(canDo, "receiveVstEvents") == 0)
ret = 1;
else if (std::strcmp(canDo, "receiveVstMidiEvent") == 0)
ret = 1;
}
#endif
// TODO
break;

case effStartProcess:
@@ -469,16 +440,16 @@ public:
return ret;
}

float vst_getParameter(int32_t index)
float vst_getParameter(const int32_t index)
{
const ParameterRanges& ranges(fPlugin.parameterRanges(index));
return ranges.normalizedValue(fPlugin.parameterValue(index));
const ParameterRanges& ranges(fPlugin.getParameterRanges(index));
return ranges.getNormalizedValue(fPlugin.getParameterValue(index));
}

void vst_setParameter(int32_t index, float value)
void vst_setParameter(const int32_t index, const float value)
{
const ParameterRanges& ranges(fPlugin.parameterRanges(index));
const float realValue(ranges.unnormalizedValue(value));
const ParameterRanges& ranges(fPlugin.getParameterRanges(index));
const float realValue(ranges.getUnnormalizedValue(value));
fPlugin.setParameterValue(index, realValue);

#if DISTRHO_PLUGIN_HAS_UI
@@ -487,14 +458,12 @@ public:
#endif
}

void vst_processReplacing(float** inputs, float** outputs, int32_t sampleFrames)
void vst_processReplacing(float** const inputs, float** const outputs, const int32_t sampleFrames)
{
#if DISTRHO_PLUGIN_IS_SYNTH
fPlugin.run(inputs, outputs, sampleFrames, fMidiEventCount, fMidiEvents);

// TODO - send notes to UI
#else
fPlugin.run(inputs, outputs, sampleFrames, 0, nullptr);
fPlugin.run(inputs, outputs, sampleFrames);
#endif
}

@@ -502,68 +471,35 @@ public:

private:
// VST stuff
audioMasterCallback const kAudioMaster;
AEffect* const kEffect;
const audioMasterCallback fAudioMaster;
AEffect* const fEffect;

// Plugin
PluginInternal fPlugin;

#if DISTRHO_PLUGIN_HAS_UI
// UI
UIVst* fVstUi;
ERect fVstRect;
#endif
PluginExporter fPlugin;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
int32_t fCurProgram;
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
uint32_t fMidiEventCount;
MidiEvent fMidiEvents[MAX_MIDI_EVENTS];
MidiEvent fMidiEvents[kMaxMidiEvents];
#endif

#if DISTRHO_PLUGIN_HAS_UI
void createUiIfNeeded(intptr_t ptr)
{
if (fVstUi != nullptr)
return;

d_lastUiSampleRate = kAudioMaster(kEffect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f);

if (ptr == 0)
{
// fake temporary window, just to set ui size
UIVst tmpUi(kAudioMaster, kEffect, &fPlugin, ptr);
fVstRect.right = tmpUi.getWidth();
fVstRect.bottom = tmpUi.getHeight();
}
else
{
// real parented ui
fVstUi = new UIVst(kAudioMaster, kEffect, &fPlugin, ptr);
fVstRect.right = fVstUi->getWidth();
fVstRect.bottom = fVstUi->getHeight();

# if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fCurProgram >= 0)
fVstUi->setProgramFromPlugin(fCurProgram);
# endif

for (uint32_t i=0, count = fPlugin.parameterCount(); i < count; ++i)
fVstUi->setParameterValueFromPlugin(i, fPlugin.parameterValue(i));
}
}
UIVst* fVstUi;
ERect fVstRect;
#endif
};

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

#define handlePtr ((PluginVst*)effect->object)
#define handlePtr ((PluginVst*)effect->resvd2)

static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
{
// first internal init
bool doInternalInit = (opcode == -1 && index == 0xdead && value == 0xf00d);
bool doInternalInit = (opcode == -1729 && index == 0xdead && value == 0xf00d);

if (doInternalInit)
{
@@ -573,7 +509,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
}

// Create dummy plugin to get data from
static PluginInternal plugin;
static PluginExporter plugin;

if (doInternalInit)
{
@@ -581,7 +517,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;

*(PluginInternal**)ptr = &plugin;
*(PluginExporter**)ptr = &plugin;
return 0;
}

@@ -589,47 +525,49 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
switch (opcode)
{
case effOpen:
if (effect != nullptr && effect->object == nullptr)
if (effect != nullptr && effect->object != nullptr /*&& dynamic_cast<audioMasterCallback>(effect->object)*/)
{
audioMasterCallback audioMaster = (audioMasterCallback)effect->user;
audioMasterCallback audioMaster = (audioMasterCallback)effect->object;
d_lastBufferSize = audioMaster(effect, audioMasterGetBlockSize, 0, 0, nullptr, 0.0f);
d_lastSampleRate = audioMaster(effect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f);
effect->object = new PluginVst(audioMaster, effect);
PluginVst* const plugin(new PluginVst(audioMaster, effect));
effect->resvd2 = (intptr_t)plugin;
return 1;
}
return 0;

case effClose:
if (effect != nullptr && effect->object != nullptr)
if (effect != nullptr && effect->resvd2 != 0)
{
delete (PluginVst*)effect->object;
delete (PluginVst*)effect->resvd2;
effect->object = nullptr;
effect->resvd2 = 0;
delete effect;
return 1;
}
return 0;

case effGetParamLabel: // FIXME - proper close buf/ptr
if (ptr != nullptr && index < static_cast<int32_t>(plugin.parameterCount()))
case effGetParamLabel:
if (ptr != nullptr && index < static_cast<int32_t>(plugin.getParameterCount()))
{
std::strncpy((char*)ptr, plugin.parameterUnit(index), kVstMaxParamStrLen);
DISTRHO::strncpy((char*)ptr, plugin.getParameterUnit(index), kVstMaxParamStrLen);
return 1;
}
return 0;

case effGetParamName:
if (ptr != nullptr && index < static_cast<int32_t>(plugin.parameterCount()))
if (ptr != nullptr && index < static_cast<int32_t>(plugin.getParameterCount()))
{
std::strncpy((char*)ptr, plugin.parameterName(index), kVstMaxParamStrLen);
DISTRHO::strncpy((char*)ptr, plugin.getParameterName(index), kVstMaxParamStrLen);
return 1;
}
return 0;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
case effGetProgramNameIndexed:
if (ptr != nullptr && index < static_cast<int32_t>(plugin.parameterCount()))
if (ptr != nullptr && index < static_cast<int32_t>(plugin.getProgramCount()))
{
std::strncpy((char*)ptr, plugin.programName(index), kVstMaxProgNameLen);
DISTRHO::strncpy((char*)ptr, plugin.getProgramName(index), kVstMaxProgNameLen);
return 1;
}
return 0;
@@ -639,13 +577,13 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
#if DISTRHO_PLUGIN_IS_SYNTH
return kPlugCategSynth;
#else
return kPlugCategUnknown;
return kPlugCategEffect;
#endif

case effGetEffectName:
if (ptr != nullptr)
{
std::strncpy((char*)ptr, plugin.name(), kVstMaxProductStrLen);
DISTRHO::strncpy((char*)ptr, plugin.getName(), kVstMaxProductStrLen);
return 1;
}
return 0;
@@ -653,7 +591,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
case effGetVendorString:
if (ptr != nullptr)
{
std::strncpy((char*)ptr, plugin.maker(), kVstMaxVendorStrLen);
DISTRHO::strncpy((char*)ptr, plugin.getMaker(), kVstMaxVendorStrLen);
return 1;
}
return 0;
@@ -661,20 +599,20 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
case effGetProductString:
if (ptr != nullptr)
{
std::strncpy((char*)ptr, plugin.label(), kVstMaxEffectNameLen);
DISTRHO::strncpy((char*)ptr, plugin.getLabel(), kVstMaxEffectNameLen);
return 1;
}
return 0;

case effGetVendorVersion:
return plugin.version();
return plugin.getVersion();

case effGetVstVersion:
return kVstVersion;
};

// handle object opcodes
if (effect != nullptr && effect->object != nullptr)
// handle advanced opcodes
if (effect != nullptr && effect->resvd2 != 0)
return handlePtr->vst_dispatcher(opcode, index, value, ptr, opt);

return 0;
@@ -682,26 +620,26 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t

static float vst_getParameterCallback(AEffect* effect, int32_t index)
{
if (effect != nullptr && effect->object != nullptr)
if (effect != nullptr && effect->resvd2 != 0)
return handlePtr->vst_getParameter(index);
return 0.0f;
}

static void vst_setParameterCallback(AEffect* effect, int32_t index, float value)
{
if (effect != nullptr && effect->object != nullptr)
if (effect != nullptr && effect->resvd2 != 0)
handlePtr->vst_setParameter(index, value);
}

static void vst_processCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames)
{
if (effect != nullptr && effect->object != nullptr)
if (effect != nullptr && effect->resvd2 != 0)
handlePtr->vst_processReplacing(inputs, outputs, sampleFrames);
}

static void vst_processReplacingCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames)
{
if (effect != nullptr && effect->object != nullptr)
if (effect != nullptr && effect->resvd2 != 0)
handlePtr->vst_processReplacing(inputs, outputs, sampleFrames);
}

@@ -720,35 +658,31 @@ const AEffect* VSTPluginMain(audioMasterCallback audioMaster)
if (audioMaster(nullptr, audioMasterVersion, 0, 0, nullptr, 0.0f) == 0)
return nullptr;

PluginInternal* plugin = nullptr;
vst_dispatcherCallback(nullptr, -1, 0xdead, 0xf00d, &plugin, 0.0f);
// first internal init
PluginExporter* plugin = nullptr;
vst_dispatcherCallback(nullptr, -1729, 0xdead, 0xf00d, &plugin, 0.0f);

AEffect* effect = new AEffect;
memset(effect, 0, sizeof(AEffect));
AEffect* const effect(new AEffect);
std::memset(effect, 0, sizeof(AEffect));

// vst fields
effect->magic = kEffectMagic;
effect->uniqueID = plugin->uniqueId();
effect->version = plugin->version();
effect->uniqueID = plugin->getUniqueId();
effect->version = plugin->getVersion();

// plugin fields
effect->numParams = plugin->parameterCount();
effect->numParams = plugin->getParameterCount();
#if DISTRHO_PLUGIN_WANT_PROGRAMS
effect->numPrograms = plugin->programCount();
effect->numPrograms = plugin->getProgramCount();
#endif
effect->numInputs = DISTRHO_PLUGIN_NUM_INPUTS;
effect->numOutputs = DISTRHO_PLUGIN_NUM_OUTPUTS;

// static calls
effect->dispatcher = vst_dispatcherCallback;
effect->process = vst_processCallback;
effect->getParameter = vst_getParameterCallback;
effect->setParameter = vst_setParameterCallback;
effect->processReplacing = vst_processReplacingCallback;
effect->processDoubleReplacing = nullptr;

// plugin flags
effect->flags |= effFlagsCanReplacing;
#if DISTRHO_PLUGIN_IS_SYNTH
effect->flags |= effFlagsIsSynth;
#endif
#if DISTRHO_PLUGIN_HAS_UI
effect->flags |= effFlagsHasEditor;
#endif
@@ -756,9 +690,16 @@ const AEffect* VSTPluginMain(audioMasterCallback audioMaster)
effect->flags |= effFlagsProgramChunks;
#endif

// static calls
effect->dispatcher = vst_dispatcherCallback;
effect->process = vst_processCallback;
effect->getParameter = vst_getParameterCallback;
effect->setParameter = vst_setParameterCallback;
effect->processReplacing = vst_processReplacingCallback;
effect->processDoubleReplacing = nullptr;

// pointers
effect->object = nullptr;
effect->user = (void*)audioMaster;
effect->object = (void*)audioMaster;

return effect;
}

+ 12
- 4
source/modules/distrho/src/DistrhoUI.cpp View File

@@ -16,6 +16,10 @@

#include "DistrhoUIInternal.hpp"

START_NAMESPACE_DGL
extern Window* dgl_lastUiParent;
END_NAMESPACE_DGL

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
@@ -27,8 +31,12 @@ double d_lastUiSampleRate = 0.0;
// UI

UI::UI()
: pData(new PrivateData())
: DGL::Widget(*DGL::dgl_lastUiParent),
pData(new PrivateData())
{
assert(DGL::dgl_lastUiParent != nullptr);

DGL::dgl_lastUiParent = nullptr;
}

UI::~UI()
@@ -46,7 +54,7 @@ double UI::d_getSampleRate() const noexcept

void UI::d_editParameter(uint32_t index, bool started)
{
pData->editParamCallback(index, started);
pData->editParamCallback(index + pData->parameterOffset, started);
}

void UI::d_setParameterValue(uint32_t index, float value)
@@ -62,9 +70,9 @@ void UI::d_setState(const char* key, const char* value)
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
void UI::d_sendNote(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
void UI::d_sendNote(uint8_t channel, uint8_t note, uint8_t velocity)
{
pData->sendNoteCallback(onOff, channel, note, velocity);
pData->sendNoteCallback(channel, note, velocity);
}
#endif



+ 27
- 185
source/modules/distrho/src/DistrhoUIDSSI.cpp View File

@@ -16,20 +16,11 @@

#include "DistrhoUIInternal.hpp"

#ifdef DISTRHO_UI_EXTERNAL
# error DSSI always uses external UI, no wrapper needed!
#endif
#include "dgl/App.hpp"
#include "dgl/Window.hpp"

#include <lo/lo.h>

#ifdef DISTRHO_UI_QT
# include <QtGui/QApplication>
# include <QtGui/QMainWindow>
#else
# include "dgl/App.hpp"
# include "dgl/Window.hpp"
#endif

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
@@ -95,78 +86,34 @@ struct OscData {

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

#ifdef DISTRHO_UI_QT
class UIDssi : public QMainWindow
#else
class UIDssi
#endif
{
public:
UIDssi(const OscData& oscData, const char* const uiTitle)
#ifdef DISTRHO_UI_QT
: QMainWindow(nullptr),
fUI(this, 0, nullptr, setParameterCallback, setStateCallback, uiSendNoteCallback, uiResizeCallback),
: fUI(this, 0, nullptr, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback),
fHostClosed(false),
qtTimer(0),
#else
: fUI(this, 0, nullptr, setParameterCallback, setStateCallback, uiSendNoteCallback, uiResizeCallback),
fHostClosed(false),
glApp(fUI.getApp()),
glWindow(fUI.getWindow()),
#endif
fOscData(oscData)
{
#ifdef DISTRHO_UI_QT
QtUI* const qtUI(fUI.getQt4Ui());

setCentralWidget(qtUI);
setWindowTitle(uiTitle);

if (qtUI->d_resizable())
{
adjustSize();
}
else
{
setFixedSize(qtUI->width(), qtUI->height());
# ifdef DISTRHO_OS_WINDOWS
setWindowFlags(windowFlags()|Qt::MSWindowsFixedSizeDialogHint);
# endif
}
#else
glWindow.setTitle(uiTitle);
#endif
fUI.setTitle(uiTitle);
}

~UIDssi()
{
#ifdef DISTRHO_UI_QT
if (qtTimer != 0)
{
killTimer(qtTimer);
qtTimer = 0;
}
#endif

if (fOscData.server != nullptr && ! fHostClosed)
fOscData.send_exiting();
}

void exec()
{
#ifdef DISTRHO_UI_QT
assert(qtTimer == 0);

qtTimer = startTimer(50);
qApp->exec();
#else
while (! glApp.isQuiting())
for (;;)
{
fOscData.idle();
fUI.idle();
msleep(50);

if (! fUI.idle())
break;

d_msleep(50);
}
#endif
}

// -------------------------------------------------------------------
@@ -190,70 +137,26 @@ public:
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
void dssiui_midi(uint8_t data[4])
{
uint8_t status = data[1] & 0xF0;
uint8_t channel = data[1] & 0x0F;

// fix bad note-off
if (status == 0x90 && data[3] == 0)
status -= 0x10;

if (status == 0x80)
{
uint8_t note = data[2];
fUI.noteReceived(false, channel, note, 0);
}
else if (status == 0x90)
{
uint8_t note = data[2];
uint8_t velo = data[3];
fUI.noteReceived(true, channel, note, velo);
}
}
#endif

void dssiui_show()
{
#ifdef DISTRHO_UI_QT
show();
#else
glWindow.show();
#endif
fUI.setVisible(true);
}

void dssiui_hide()
{
#ifdef DISTRHO_UI_QT
hide();
#else
glWindow.hide();
#endif
fUI.setVisible(false);
}

void dssiui_quit()
{
fHostClosed = true;

#ifdef DISTRHO_UI_QT
if (qtTimer != 0)
{
killTimer(qtTimer);
qtTimer = 0;
}
close();
qApp->quit();
#else
glWindow.close();
glApp.quit();
#endif
fUI.quit();
}

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

protected:
void setParameterValue(uint32_t rindex, float value)
void setParameterValue(const uint32_t rindex, const float value)
{
if (fOscData.server == nullptr)
return;
@@ -261,7 +164,7 @@ protected:
fOscData.send_control(rindex, value);
}

void setState(const char* key, const char* value)
void setState(const char* const key, const char* const value)
{
if (fOscData.server == nullptr)
return;
@@ -269,7 +172,7 @@ protected:
fOscData.send_configure(key, value);
}

void uiSendNote(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{
if (fOscData.server == nullptr)
return;
@@ -277,47 +180,20 @@ protected:
return;

uint8_t mdata[4] = { 0, channel, note, velocity };
mdata[1] += onOff ? 0x90 : 0x80;
mdata[1] += (velocity != 0) ? 0x90 : 0x80;

fOscData.send_midi(mdata);
}

void uiResize(unsigned int width, unsigned int height)
{
#ifdef DISTRHO_UI_QT
setFixedSize(width, height);
#else
glWindow.setSize(width, height);
#endif
}

#ifdef DISTRHO_UI_QT
void timerEvent(QTimerEvent* event)
void uiResize(const unsigned int width, const unsigned int height)
{
if (event->timerId() == uiTimer)
{
fOscData.idle();
fUI.idle();
}

QMainWindow::timerEvent(event);
fUI.setSize(width, height);
}
#endif

private:
// Plugin UI
UIInternal fUI;
UIExporter fUI;
bool fHostClosed;

#ifdef DISTRHO_UI_QT
// Qt4 stuff
int qtTimer;
#else
// OpenGL stuff
App& glApp;
Window& glWindow;
#endif

const OscData& fOscData;

// -------------------------------------------------------------------
@@ -335,9 +211,9 @@ private:
uiPtr->setState(key, value);
}

static void uiSendNoteCallback(void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
{
uiPtr->uiSendNote(onOff, channel, note, velocity);
uiPtr->sendNote(channel, note, velocity);
}

static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height)
@@ -431,19 +307,6 @@ int osc_program_handler(const char*, const char*, lo_arg** argv, int, lo_message
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
int osc_midi_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
d_debug("osc_midi_handler()");

initUiIfNeeded();

globalUI->dssiui_midi(argv[0]->m);

return 0;
}
#endif

int osc_sample_rate_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const int32_t sampleRate = argv[0]->i;
@@ -470,7 +333,7 @@ int osc_hide_handler(const char*, const char*, lo_arg**, int, lo_message, void*)
d_debug("osc_hide_handler()");

if (globalUI != nullptr)
globalUI->dssiui_hide();
globalUI->dssiui_hide();

return 0;
}
@@ -481,10 +344,6 @@ int osc_quit_handler(const char*, const char*, lo_arg**, int, lo_message, void*)

if (globalUI != nullptr)
globalUI->dssiui_quit();
#ifdef DISTRHO_UI_QT
else if (QApplication* app = qApp)
app->quit();
#endif

return 0;
}
@@ -500,9 +359,6 @@ int main(int argc, char* argv[])
// dummy test mode
if (argc == 1)
{
#ifdef DISTRHO_UI_QT
QApplication app(argc, argv, true);
#endif
gUiTitle = "DSSI UI Test";

initUiIfNeeded();
@@ -518,10 +374,6 @@ int main(int argc, char* argv[])
return 1;
}

#ifdef DISTRHO_UI_QT
QApplication app(argc, argv, true);
#endif

const char* oscUrl = argv[1];
const char* uiTitle = argv[4];

@@ -561,13 +413,6 @@ int main(int argc, char* argv[])
lo_server_add_method(oscServer, oscPathProgram, "ii", osc_program_handler, nullptr);
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
char oscPathMidi[oscPathSize+6];
strcpy(oscPathMidi, oscPath);
strcat(oscPathMidi, "/midi");
lo_server_add_method(oscServer, oscPathMidi, "m", osc_midi_handler, nullptr);
#endif

char oscPathSampleRate[oscPathSize+13];
strcpy(oscPathSampleRate, oscPath);
strcat(oscPathSampleRate, "/sample-rate");
@@ -628,9 +473,6 @@ int main(int argc, char* argv[])
lo_server_del_method(oscServer, oscPathControl, "if");
#if DISTRHO_PLUGIN_WANT_PROGRAMS
lo_server_del_method(oscServer, oscPathProgram, "ii");
#endif
#if DISTRHO_PLUGIN_IS_SYNTH
lo_server_del_method(oscServer, oscPathMidi, "m");
#endif
lo_server_del_method(oscServer, oscPathSampleRate, "i");
lo_server_del_method(oscServer, oscPathShow, "");
@@ -638,10 +480,10 @@ int main(int argc, char* argv[])
lo_server_del_method(oscServer, oscPathQuit, "");
lo_server_del_method(oscServer, nullptr, nullptr);

free(oscServerPath);
free(oscHost);
free(oscPort);
free(oscPath);
std::free(oscServerPath);
std::free(oscHost);
std::free(oscPort);
std::free(oscPath);

lo_address_free(oscAddr);
lo_server_free(oscServer);


+ 0
- 35
source/modules/distrho/src/DistrhoUIExternal.cpp View File

@@ -1,35 +0,0 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 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 "DistrhoUIInternal.hpp"

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// External UI

ExternalUI::ExternalUI()
: UI()
{
}

ExternalUI::~ExternalUI()
{
}

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

END_NAMESPACE_DISTRHO

+ 65
- 103
source/modules/distrho/src/DistrhoUIInternal.hpp View File

@@ -19,33 +19,28 @@

#include "../DistrhoUI.hpp"

#if defined(DISTRHO_UI_EXTERNAL)
# include "../DistrhoUIExternal.hpp"
#elif defined(DISTRHO_UI_OPENGL)
# include "../DistrhoUIOpenGL.hpp"
# include "../dgl/App.hpp"
# include "../dgl/Window.hpp"
#elif defined(DISTRHO_UI_QT)
# include "../DistrhoUIQt.hpp"
#else
# error Invalid UI type
#endif

#include <cassert>
#include "../dgl/App.hpp"
#include "../dgl/Window.hpp"
#include <lo/lo_osc_types.h>

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// Static data, see DistrhoUI.cpp

extern double d_lastUiSampleRate;

typedef void (*editParamFunc) (void* ptr, uint32_t index, bool started);
typedef void (*setParamFunc) (void* ptr, uint32_t index, float value);
// -----------------------------------------------------------------------
// UI callbacks

typedef void (*editParamFunc) (void* ptr, uint32_t rindex, bool started);
typedef void (*setParamFunc) (void* ptr, uint32_t rindex, float value);
typedef void (*setStateFunc) (void* ptr, const char* key, const char* value);
typedef void (*sendNoteFunc) (void* ptr, bool onOff, uint8_t channel, uint8_t note, uint8_t velo);
typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8_t velo);
typedef void (*uiResizeFunc) (void* ptr, unsigned int width, unsigned int height);

extern double d_lastUiSampleRate;

// -----------------------------------------------------------------------
// UI private data

struct UI::PrivateData {
// DSP
@@ -60,7 +55,7 @@ struct UI::PrivateData {
uiResizeFunc uiResizeCallbackFunc;
void* ptr;

PrivateData()
PrivateData() noexcept
: sampleRate(d_lastUiSampleRate),
parameterOffset(0),
editParamCallbackFunc(nullptr),
@@ -77,34 +72,42 @@ struct UI::PrivateData {
# if DISTRHO_PLUGIN_WANT_LATENCY
parameterOffset += 1;
# endif
#endif
#ifdef DISTRHO_PLUGIN_TARGET_LV2
# if (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE)
parameterOffset += 1;
# if DISTRHO_PLUGIN_WANT_STATE
parameterOffset += 1;
# endif
# endif
#endif
}

void editParamCallback(uint32_t index, bool started)
void editParamCallback(const uint32_t rindex, const bool started)
{
if (editParamCallbackFunc != nullptr)
editParamCallbackFunc(ptr, index, started);
editParamCallbackFunc(ptr, rindex, started);
}

void setParamCallback(uint32_t rindex, float value)
void setParamCallback(const uint32_t rindex, const float value)
{
if (setParamCallbackFunc != nullptr)
setParamCallbackFunc(ptr, rindex, value);
}

void setStateCallback(const char* key, const char* value)
void setStateCallback(const char* const key, const char* const value)
{
if (setStateCallbackFunc != nullptr)
setStateCallbackFunc(ptr, key, value);
}

void sendNoteCallback(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
void sendNoteCallback(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{
if (sendNoteCallbackFunc != nullptr)
sendNoteCallbackFunc(ptr, onOff, channel, note, velocity);
sendNoteCallbackFunc(ptr, channel, note, velocity);
}

void uiResizeCallback(unsigned int width, unsigned int height)
void uiResizeCallback(const unsigned int width, const unsigned int height)
{
if (uiResizeCallbackFunc != nullptr)
uiResizeCallbackFunc(ptr, width, height);
@@ -112,18 +115,16 @@ struct UI::PrivateData {
};

// -----------------------------------------------------------------------
// UI exporter class

class UIInternal
class UIExporter
{
public:
UIInternal(void* ptr, intptr_t winId, editParamFunc editParamCall, setParamFunc setParamCall, setStateFunc setStateCall, sendNoteFunc sendNoteCall, uiResizeFunc uiResizeCall)
#ifdef DISTRHO_UI_OPENGL
UIExporter(void* const ptr, const intptr_t winId,
const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const uiResizeFunc uiResizeCall)
: glApp(),
glWindow(glApp, winId),
fUi(createUI()),
#else
: fUi(createUI()),
#endif
fData((fUi != nullptr) ? fUi->pData : nullptr)
{
assert(fUi != nullptr);
@@ -138,145 +139,106 @@ public:
fData->sendNoteCallbackFunc = sendNoteCall;
fData->uiResizeCallbackFunc = uiResizeCall;

#ifdef DISTRHO_UI_OPENGL
glWindow.setSize(fUi->d_getWidth(), fUi->d_getHeight());
glWindow.setResizable(false);
#else
assert(winId == 0);
return;

// unused
(void)winId;
#endif
}

~UIInternal()
~UIExporter()
{
if (fUi != nullptr)
delete fUi;
delete fUi;
}

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

const char* getName() const
const char* getName() const noexcept
{
assert(fUi != nullptr);
return (fUi != nullptr) ? fUi->d_getName() : "";
}

unsigned int getWidth() const
unsigned int getWidth() const noexcept
{
assert(fUi != nullptr);
return (fUi != nullptr) ? fUi->d_getWidth() : 0;
}

unsigned int getHeight() const
unsigned int getHeight() const noexcept
{
assert(fUi != nullptr);
return (fUi != nullptr) ? fUi->d_getHeight() : 0;
}

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

void parameterChanged(uint32_t index, float value)
uint32_t getParameterOffset() const noexcept
{
assert(fUi != nullptr);
return (fData != nullptr) ? fData->parameterOffset : 0;
}

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

void parameterChanged(const uint32_t index, const float value)
{
if (fUi != nullptr)
fUi->d_parameterChanged(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void programChanged(uint32_t index)
void programChanged(const uint32_t index)
{
assert(fUi != nullptr);

if (fUi != nullptr)
fUi->d_programChanged(index);
}
#endif

#if DISTRHO_PLUGIN_WANT_STATE
void stateChanged(const char* key, const char* value)
void stateChanged(const char* const key, const char* const value)
{
assert(fUi != nullptr);

if (fUi != nullptr)
fUi->d_stateChanged(key, value);
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
void noteReceived(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity)
{
assert(fUi != nullptr);

if (fUi != nullptr)
fUi->d_noteReceived(onOff, channel, note, velocity);
}
#endif

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

void idle()
bool idle()
{
assert(fUi != nullptr);

if (fUi != nullptr)
fUi->d_uiIdle();

#ifdef DISTRHO_UI_OPENGL
glApp.idle();
#endif
}

#if defined(DISTRHO_UI_EXTERNAL)
const char* getExternalFilename() const
{
return ((ExternalUI*)fUi)->d_getExternalFilename();
}
#elif defined(DISTRHO_UI_OPENGL)
DGL::App& getApp()
{
return glApp;
return ! glApp.isQuiting();
}

DGL::Window& getWindow()
void quit()
{
return glWindow;
glWindow.close();
glApp.quit();
}

/*intptr_t getWindowId() const
void setSize(const unsigned int width, const unsigned int height)
{
return glWindow.getWindowId();
}*/
glWindow.setSize(width, height);
}

/*void fixWindowSize()
void setTitle(const char* const uiTitle)
{
assert(fUi != nullptr);
glWindow.setSize(fUi->d_getWidth(), fUi->d_getHeight());
}*/
#elif defined(DISTRHO_UI_QT)
/*QtUI* getQtUI() const
{
return (QtUI*)fUi;
}*/
glWindow.setTitle(uiTitle);
}

bool isResizable() const
void setVisible(const bool yesNo)
{
return ((QtUI*)fUi)->d_isResizable();
glWindow.setVisible(yesNo);
}
#endif

private:
// -------------------------------------------------------------------
// DGL Application and Window for this plugin

#ifdef DISTRHO_UI_OPENGL
private:
DGL::App glApp;
DGL::Window glWindow;
#endif

protected:
// -------------------------------------------------------------------
// private members accessed by DistrhoPlugin class

UI* const fUi;
UI::PrivateData* const fData;
};


+ 301
- 0
source/modules/distrho/src/DistrhoUILV2.cpp View File

@@ -0,0 +1,301 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 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 "DistrhoUIInternal.hpp"

#include "lv2/atom.h"
#include "lv2/options.h"
#include "lv2/ui.h"
#include "lv2/urid.h"
#include "lv2/lv2_programs.h"

START_NAMESPACE_DISTRHO

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

class UiLv2
{
public:
UiLv2(const intptr_t winId, const LV2_URID_Map* const uridMap, const LV2UI_Resize* const uiResz, const LV2UI_Touch* uiTouch, const LV2UI_Controller controller, const LV2UI_Write_Function writeFunc)
: fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, uiResizeCallback),
fUridMap(uridMap),
fUiResize(uiResz),
fUiTouch(uiTouch),
fController(controller),
fWriteFunction(writeFunc)
{
fUiResize->ui_resize(fUiResize->handle, fUI.getWidth(), fUI.getHeight());
}

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

void lv2ui_port_event(const uint32_t rindex, const uint32_t bufferSize, const uint32_t format, const void* const buffer)
{
if (format == 0)
{
const uint32_t parameterOffset(fUI.getParameterOffset());

if (rindex < parameterOffset)
return;
if (bufferSize != sizeof(float))
return;

const float value(*(const float*)buffer);
fUI.parameterChanged(rindex-parameterOffset, value);

d_stderr("port changed %i, %i, %f", rindex, parameterOffset, value);
}
else
{
//fUI.stateChanged(key, value);
}
}

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

int lv2ui_idle()
{
fUI.idle();
return 0;
}

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

void lv2ui_select_program(const uint32_t bank, const uint32_t program)
{
const uint32_t realProgram(bank * 128 + program);

fUI.programChanged(realProgram);
}

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

protected:
void editParameterValue(const uint32_t rindex, const bool started)
{
if (fUiTouch != nullptr && fUiTouch->touch != nullptr)
fUiTouch->touch(fUiTouch->handle, rindex, started);
}

void setParameterValue(const uint32_t rindex, const float value)
{
if (fWriteFunction != nullptr)
fWriteFunction(fController, rindex, sizeof(float), 0, &value);
}

void setState(const char* const /*key*/, const char* const /*value*/)
{
}

void sendNote(const uint8_t /*channel*/, const uint8_t /*note*/, const uint8_t /*velocity*/)
{
}

void uiResize(const unsigned int width, const unsigned int height)
{
fUI.setSize(width, height);
fUiResize->ui_resize(fUiResize->handle, width, height);
}

private:
UIExporter fUI;

// LV2 features
const LV2_URID_Map* const fUridMap;
const LV2UI_Resize* const fUiResize;
const LV2UI_Touch* const fUiTouch;

// LV2 UI stuff
const LV2UI_Controller fController;
const LV2UI_Write_Function fWriteFunction;

// -------------------------------------------------------------------
// Callbacks

#define uiPtr ((UiLv2*)ptr)

static void editParameterCallback(void* ptr, uint32_t rindex, bool started)
{
uiPtr->editParameterValue(rindex, started);
}

static void setParameterCallback(void* ptr, uint32_t rindex, float value)
{
uiPtr->setParameterValue(rindex, value);
}

static void setStateCallback(void* ptr, const char* key, const char* value)
{
uiPtr->setState(key, value);
}

static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
{
uiPtr->sendNote(channel, note, velocity);
}

static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height)
{
uiPtr->uiResize(width, height);
}

#undef uiPtr
};

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

static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, const char*, LV2UI_Write_Function writeFunction, LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features)
{
if (uri == nullptr || std::strcmp(uri, DISTRHO_PLUGIN_URI) != 0)
{
d_stderr("Invalid plugin URI");
return nullptr;
}

const LV2_Options_Option* options = nullptr;
const LV2_URID_Map* uridMap = nullptr;
const LV2UI_Resize* uiResize = nullptr;
const LV2UI_Touch* uiTouch = nullptr;
void* parentId = nullptr;

for (int i=0; features[i] != nullptr; ++i)
{
if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
options = (const LV2_Options_Option*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
uridMap = (const LV2_URID_Map*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_UI__resize) == 0)
uiResize = (const LV2UI_Resize*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_UI__parent) == 0)
parentId = features[i]->data;
}

if (options == nullptr)
{
d_stderr("Options feature missing, cannot continue!");
return nullptr;
}

if (uridMap == nullptr)
{
d_stderr("URID Map feature missing, cannot continue!");
return nullptr;
}

if (uiResize == nullptr)
{
d_stderr("UI Resize feature missing, cannot continue!");
return nullptr;
}

if (parentId == nullptr)
{
d_stderr("Parent Window Id missing, cannot continue!");
return nullptr;
}

*widget = parentId;

const intptr_t winId(*((intptr_t*)&parentId));

for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == uridMap->map(uridMap->handle, LV2_CORE__sampleRate))
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Double))
d_lastUiSampleRate = *(const double*)options[i].value;
else
d_stderr("Host provides sampleRate but has wrong value type");

break;
}
}

if (d_lastUiSampleRate == 0.0)
d_lastUiSampleRate = 44100.0;

return new UiLv2(winId, uridMap, uiResize, uiTouch, controller, writeFunction);
}

#define uiPtr ((UiLv2*)ui)

static void lv2ui_cleanup(LV2UI_Handle ui)
{
delete uiPtr;
}

static void lv2ui_port_event(LV2UI_Handle ui, uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
{
uiPtr->lv2ui_port_event(portIndex, bufferSize, format, buffer);
}

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

static int lv2ui_idle(LV2UI_Handle ui)
{
return uiPtr->lv2ui_idle();
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
static void lv2ui_select_program(LV2UI_Handle ui, uint32_t bank, uint32_t program)
{
uiPtr->lv2ui_select_program(bank, program);
}
#endif

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

static const void* lv2ui_extension_data(const char* uri)
{
static const LV2UI_Idle_Interface uiIdle = { lv2ui_idle };

if (std::strcmp(uri, LV2_UI__idleInterface) == 0)
return &uiIdle;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
static const LV2_Programs_UI_Interface uiPrograms = { lv2ui_select_program };

if (std::strcmp(uri, LV2_PROGRAMS__UIInterface) == 0)
return &uiPrograms;
#endif

return nullptr;
}

#undef instancePtr

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

static const LV2UI_Descriptor sLv2UiDescriptor = {
DISTRHO_UI_URI,
lv2ui_instantiate,
lv2ui_cleanup,
lv2ui_port_event,
lv2ui_extension_data
};

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

END_NAMESPACE_DISTRHO

DISTRHO_PLUGIN_EXPORT
const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index)
{
USE_NAMESPACE_DISTRHO
return (index == 0) ? &sLv2UiDescriptor : nullptr;
}

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

+ 0
- 43
source/modules/distrho/src/DistrhoUIOpenGL.cpp View File

@@ -1,43 +0,0 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 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 "DistrhoUIInternal.hpp"

START_NAMESPACE_DGL
extern Window* dgl_lastUiParent;
END_NAMESPACE_DGL

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// OpenGL UI

OpenGLUI::OpenGLUI()
: UI(),
Widget(*DGL::dgl_lastUiParent)
{
assert(DGL::dgl_lastUiParent != nullptr);

DGL::dgl_lastUiParent = nullptr;
}

OpenGLUI::~OpenGLUI()
{
}

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

END_NAMESPACE_DISTRHO

+ 0
- 50
source/modules/distrho/src/DistrhoUIQt.cpp View File

@@ -1,50 +0,0 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-2013 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 "DistrhoUIInternal.hpp"

#include <QtGui/QResizeEvent>

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// Qt UI

QtUI::QtUI()
: UI(),
QWidget(nullptr)
{
}

QtUI::~QtUI()
{
}

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

void QtUI::setSize(unsigned int width, unsigned int height)
{
if (d_isResizable())
resize(width, height);
else
setFixedSize(width, height);

d_uiResize(width, height);
}

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

END_NAMESPACE_DISTRHO

+ 8
- 3
source/tests/Makefile View File

@@ -8,9 +8,7 @@ include ../Makefile.mk

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

BUILD_CXX_FLAGS += -I../backend -I../includes -I../modules -I../modules/distrho -I../utils
BUILD_CXX_FLAGS += -DWANT_NATIVE -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST -DWANT_AU -DWANT_CSOUND -DWANT_FLUIDSYNTH -DWANT_LINUXSAMPLER
BUILD_CXX_FLAGS += -DWANT_OPENGL -DWANT_AUDIOFILE -DWANT_MIDIFILE -DWANT_ZYNADDSUBFX -DWANT_ZYNADDSUBFX_UI
BUILD_CXX_FLAGS += -I. -I../backend -I../includes -I../modules -I../modules/distrho -I../utils
BUILD_CXX_FLAGS += -std=c++11 -Wzero-as-null-pointer-constant
BUILD_CXX_FLAGS += -isystem /opt/kxstudio/include
# BUILD_CXX_FLAGS += -isystem /usr/include/qt5
@@ -58,6 +56,13 @@ CarlaString: CarlaString.cpp ../utils/CarlaString.hpp
$(CXX) $< $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@
# valgrind ./CarlaString

DISTRHO: DISTRHO.cpp ../modules/distrho/*.hpp ../modules/distrho/src/*.cpp
$(CXX) $< ../modules/dgl.a $(BUILD_CXX_FLAGS) -I../modules/distrho $(LINK_FLAGS) $(DGL_LIBS) $(shell pkg-config --libs liblo) -o $@
./DISTRHO

DISTRHO.so: DISTRHO.cpp ../modules/distrho/*.hpp ../modules/distrho/src/*.cpp
$(CXX) $< ../modules/dgl.a $(BUILD_CXX_FLAGS) -I../modules/distrho -DSHARED_DLL $(LINK_FLAGS) $(DGL_LIBS) -shared -Wl,--no-undefined -o $@

DGL: DGL.cpp ../modules/distrho/dgl/src/Window.cpp
$(CXX) $< $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) -o $@
# ./DGL


Loading…
Cancel
Save