Browse Source

Update DPF

tags/v1.2
falkTX 6 years ago
parent
commit
bb6fbd4580
21 changed files with 868 additions and 249 deletions
  1. +1
    -1
      dpf/dgl/Application.hpp
  2. +2
    -2
      dpf/dgl/src/Application.cpp
  3. +3
    -3
      dpf/dgl/src/NanoVG.cpp
  4. +4
    -4
      dpf/dgl/src/WidgetPrivateData.hpp
  5. +3
    -1
      dpf/dgl/src/Window.cpp
  6. +0
    -3
      dpf/dgl/src/pugl/pugl_osx.m
  7. +102
    -4
      dpf/distrho/DistrhoPlugin.hpp
  8. +2
    -1
      dpf/distrho/DistrhoUI.hpp
  9. +7
    -7
      dpf/distrho/src/DistrhoPlugin.cpp
  10. +55
    -6
      dpf/distrho/src/DistrhoPluginInternal.hpp
  11. +83
    -11
      dpf/distrho/src/DistrhoPluginJack.cpp
  12. +33
    -13
      dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp
  13. +105
    -35
      dpf/distrho/src/DistrhoPluginLV2.cpp
  14. +47
    -24
      dpf/distrho/src/DistrhoPluginLV2export.cpp
  15. +257
    -80
      dpf/distrho/src/DistrhoPluginVST.cpp
  16. +1
    -1
      dpf/distrho/src/DistrhoUI.cpp
  17. +14
    -3
      dpf/distrho/src/DistrhoUIDSSI.cpp
  18. +17
    -12
      dpf/distrho/src/DistrhoUIInternal.hpp
  19. +34
    -1
      dpf/distrho/src/DistrhoUILV2.cpp
  20. +92
    -31
      dpf/distrho/src/vestige/vestige.h
  21. +6
    -6
      dpf/utils/generate-ttl.sh

+ 1
- 1
dpf/dgl/Application.hpp View File

@@ -62,7 +62,7 @@ public:
idle() is called at regular intervals. idle() is called at regular intervals.
@note This function is meant for standalones only, *never* call this from plugins. @note This function is meant for standalones only, *never* call this from plugins.
*/ */
void exec();
void exec(int idleTime = 10);


/** /**
Quit the application. Quit the application.


+ 2
- 2
dpf/dgl/src/Application.cpp View File

@@ -44,12 +44,12 @@ void Application::idle()
} }
} }


void Application::exec()
void Application::exec(int idleTime)
{ {
for (; pData->doLoop;) for (; pData->doLoop;)
{ {
idle(); idle();
d_msleep(10);
d_msleep(idleTime);
} }
} }




+ 3
- 3
dpf/dgl/src/NanoVG.cpp View File

@@ -472,8 +472,8 @@ void NanoVG::skewY(float angle)
void NanoVG::scale(float x, float y) void NanoVG::scale(float x, float y)
{ {
if (fContext == nullptr) return; if (fContext == nullptr) return;
DISTRHO_SAFE_ASSERT_RETURN(x > 0.0f,);
DISTRHO_SAFE_ASSERT_RETURN(y > 0.0f,);
DISTRHO_SAFE_ASSERT_RETURN(d_isNotZero(x),);
DISTRHO_SAFE_ASSERT_RETURN(d_isNotZero(y),);


nvgScale(fContext, x, y); nvgScale(fContext, x, y);
} }
@@ -865,7 +865,7 @@ float NanoVG::textBounds(float x, float y, const char* string, const char* end,


float b[4]; float b[4];
const float ret = nvgTextBounds(fContext, x, y, string, end, b); const float ret = nvgTextBounds(fContext, x, y, string, end, b);
bounds = Rectangle<float>(b[0], b[1], b[2], b[3]);
bounds = Rectangle<float>(b[0], b[1], b[2] - b[0], b[3] - b[1]);
return ret; return ret;
} }




+ 4
- 4
dpf/dgl/src/WidgetPrivateData.hpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * 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 * or without fee is hereby granted, provided that the above copyright notice and this
@@ -63,9 +63,9 @@ struct Widget::PrivateData {
subWidgets.clear(); subWidgets.clear();
} }


void display(const uint width, const uint height)
void display(const uint width, const uint height, const bool renderingSubWidget)
{ {
if (skipDisplay || ! visible)
if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible)
return; return;


bool needsDisableScissor = false; bool needsDisableScissor = false;
@@ -123,7 +123,7 @@ struct Widget::PrivateData {
Widget* const widget(*it); Widget* const widget(*it);
DISTRHO_SAFE_ASSERT_CONTINUE(widget->pData != this); DISTRHO_SAFE_ASSERT_CONTINUE(widget->pData != this);


widget->pData->display(width, height);
widget->pData->display(width, height, true);
} }
} }




+ 3
- 1
dpf/dgl/src/Window.cpp View File

@@ -33,6 +33,8 @@
#if defined(DISTRHO_OS_WINDOWS) #if defined(DISTRHO_OS_WINDOWS)
# include "pugl/pugl_win.cpp" # include "pugl/pugl_win.cpp"
#elif defined(DISTRHO_OS_MAC) #elif defined(DISTRHO_OS_MAC)
# define PuglWindow DISTRHO_JOIN_MACRO(PuglWindow, DGL_NAMESPACE)
# define PuglOpenGLView DISTRHO_JOIN_MACRO(PuglOpenGLView, DGL_NAMESPACE)
# include "pugl/pugl_osx.m" # include "pugl/pugl_osx.m"
#else #else
# include <sys/types.h> # include <sys/types.h>
@@ -721,7 +723,7 @@ struct Window::PrivateData {
FOR_EACH_WIDGET(it) FOR_EACH_WIDGET(it)
{ {
Widget* const widget(*it); Widget* const widget(*it);
widget->pData->display(fWidth, fHeight);
widget->pData->display(fWidth, fHeight, false);
} }


fSelf->onDisplayAfter(); fSelf->onDisplayAfter();


+ 0
- 3
dpf/dgl/src/pugl/pugl_osx.m View File

@@ -24,9 +24,6 @@


#include "pugl_internal.h" #include "pugl_internal.h"


#define PuglWindow PuglWindow ## DGL_NAMESPACE
#define PuglOpenGLView PuglOpenGLView ## DGL_NAMESPACE

@interface PuglWindow : NSWindow @interface PuglWindow : NSWindow
{ {
@public @public


+ 102
- 4
dpf/distrho/DistrhoPlugin.hpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * 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 * or without fee is hereby granted, provided that the above copyright notice and this
@@ -89,6 +89,15 @@ static const uint32_t kParameterIsLogarithmic = 0x08;
*/ */
static const uint32_t kParameterIsOutput = 0x10; static const uint32_t kParameterIsOutput = 0x10;


/**
Parameter value is a trigger.@n
This means the value resets back to its default after each process/run call.@n
Cannot be used for output parameters.

@note Only officially supported under LV2. For other formats DPF simulates the behaviour.
*/
static const uint32_t kParameterIsTrigger = 0x20 | kParameterIsBoolean;

/** @} */ /** @} */


/* ------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------
@@ -274,6 +283,90 @@ struct ParameterRanges {
} }
}; };


/**
Parameter enumeration value.@n
A string representation of a plugin parameter value.@n
Used together can be used to give meaning to parameter values, working as an enumeration.
*/
struct ParameterEnumerationValue {
/**
Parameter value.
*/
float value;

/**
String representation of this value.
*/
String label;

/**
Default constructor, using 0.0 as value and empty label.
*/
ParameterEnumerationValue() noexcept
: value(0.0f),
label() {}

/**
Constructor using custom values.
*/
ParameterEnumerationValue(float v, const char* l) noexcept
: value(v),
label(l) {}
};

/**
Collection of parameter enumeration values.@n
Handy class to handle the lifetime and count of all enumeration values.
*/
struct ParameterEnumerationValues {
/**
Number of elements allocated in @values.
*/
uint8_t count;

/**
Wherever the host is to be restricted to only use enumeration values.

@note This mode is only a hint! Not all hosts and plugin formats support this mode.
*/
bool restrictedMode;

/**
Array of @ParameterEnumerationValue items.@n
This pointer must be null or have been allocated on the heap with `new`.
*/
const ParameterEnumerationValue* values;

/**
Default constructor, for zero enumeration values.
*/
ParameterEnumerationValues() noexcept
: count(0),
restrictedMode(false),
values() {}

/**
Constructor using custom values.@n
The pointer to @values must have been allocated on the heap with `new`.
*/
ParameterEnumerationValues(uint32_t c, bool r, const ParameterEnumerationValue* v) noexcept
: count(c),
restrictedMode(r),
values(v) {}

~ParameterEnumerationValues() noexcept
{
count = 0;
restrictedMode = false;

if (values != nullptr)
{
delete[] values;
values = nullptr;
}
}
};

/** /**
Parameter. Parameter.
*/ */
@@ -312,6 +405,12 @@ struct Parameter {
*/ */
ParameterRanges ranges; ParameterRanges ranges;


/**
Enumeration values.@n
Can be used to give meaning to parameter values, working as an enumeration.
*/
ParameterEnumerationValues enumValues;

/** /**
Designation for this parameter. Designation for this parameter.
*/ */
@@ -334,6 +433,7 @@ struct Parameter {
symbol(), symbol(),
unit(), unit(),
ranges(), ranges(),
enumValues(),
designation(kParameterDesignationNull), designation(kParameterDesignationNull),
midiCC(0) {} midiCC(0) {}


@@ -346,6 +446,7 @@ struct Parameter {
symbol(s), symbol(s),
unit(u), unit(u),
ranges(def, min, max), ranges(def, min, max),
enumValues(),
designation(kParameterDesignationNull), designation(kParameterDesignationNull),
midiCC(0) {} midiCC(0) {}


@@ -593,9 +694,6 @@ public:
Write a MIDI output event.@n Write a MIDI output event.@n
This function must only be called during run().@n This function must only be called during run().@n
Returns false when the host buffer is full, in which case do not call this again until the next run(). Returns false when the host buffer is full, in which case do not call this again until the next run().
@note This function is not implemented yet!@n
It's here so that developers can prepare MIDI plugins in advance.@n
If you plan to use this, please report to DPF authors so it can be implemented.
*/ */
bool writeMidiEvent(const MidiEvent& midiEvent) noexcept; bool writeMidiEvent(const MidiEvent& midiEvent) noexcept;
#endif #endif


+ 2
- 1
dpf/distrho/DistrhoUI.hpp View File

@@ -90,10 +90,11 @@ public:
void setState(const char* key, const char* value); void setState(const char* key, const char* value);
#endif #endif


#if DISTRHO_PLUGIN_IS_SYNTH
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
/** /**
sendNote. sendNote.
@TODO Document this. @TODO Document this.
@note Work in progress. Implemented for DSSI and LV2 formats.
*/ */
void sendNote(uint8_t channel, uint8_t note, uint8_t velocity); void sendNote(uint8_t channel, uint8_t note, uint8_t velocity);
#endif #endif


+ 7
- 7
dpf/distrho/src/DistrhoPlugin.cpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * 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 * or without fee is hereby granted, provided that the above copyright notice and this
@@ -27,9 +27,10 @@ double d_lastSampleRate = 0.0;
/* ------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------
* Static fallback data, see DistrhoPluginInternal.hpp */ * Static fallback data, see DistrhoPluginInternal.hpp */


const String PluginExporter::sFallbackString;
const AudioPort PluginExporter::sFallbackAudioPort;
const ParameterRanges PluginExporter::sFallbackRanges;
const String PluginExporter::sFallbackString;
const AudioPort PluginExporter::sFallbackAudioPort;
const ParameterRanges PluginExporter::sFallbackRanges;
const ParameterEnumerationValues PluginExporter::sFallbackEnumValues;


/* ------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------
* Plugin */ * Plugin */
@@ -102,10 +103,9 @@ void Plugin::setLatency(uint32_t frames) noexcept
#endif #endif


#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
bool Plugin::writeMidiEvent(const MidiEvent& /*midiEvent*/) noexcept
bool Plugin::writeMidiEvent(const MidiEvent& midiEvent) noexcept
{ {
// TODO
return false;
return pData->writeMidiCallback(midiEvent);
} }
#endif #endif




+ 55
- 6
dpf/distrho/src/DistrhoPluginInternal.hpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * 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 * or without fee is hereby granted, provided that the above copyright notice and this
@@ -32,6 +32,11 @@ static const uint32_t kMaxMidiEvents = 512;
extern uint32_t d_lastBufferSize; extern uint32_t d_lastBufferSize;
extern double d_lastSampleRate; extern double d_lastSampleRate;


// -----------------------------------------------------------------------
// DSP callbacks

typedef bool (*writeMidiFunc) (void* ptr, const MidiEvent& midiEvent);

// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Plugin private data // Plugin private data


@@ -65,6 +70,10 @@ struct Plugin::PrivateData {
TimePosition timePosition; TimePosition timePosition;
#endif #endif


// Callbacks
void* callbacksPtr;
writeMidiFunc writeMidiCallbackFunc;

uint32_t bufferSize; uint32_t bufferSize;
double sampleRate; double sampleRate;


@@ -88,6 +97,8 @@ struct Plugin::PrivateData {
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
latency(0), latency(0),
#endif #endif
callbacksPtr(nullptr),
writeMidiCallbackFunc(nullptr),
bufferSize(d_lastBufferSize), bufferSize(d_lastBufferSize),
sampleRate(d_lastSampleRate) sampleRate(d_lastSampleRate)
{ {
@@ -149,6 +160,16 @@ struct Plugin::PrivateData {
} }
#endif #endif
} }

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
bool writeMidiCallback(const MidiEvent& midiEvent)
{
if (writeMidiCallbackFunc != nullptr)
return writeMidiCallbackFunc(callbacksPtr, midiEvent);

return false;
}
#endif
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -157,7 +178,7 @@ struct Plugin::PrivateData {
class PluginExporter class PluginExporter
{ {
public: public:
PluginExporter()
PluginExporter(void* const callbacksPtr, const writeMidiFunc writeMidiCall)
: fPlugin(createPlugin()), : fPlugin(createPlugin()),
fData((fPlugin != nullptr) ? fPlugin->pData : nullptr), fData((fPlugin != nullptr) ? fPlugin->pData : nullptr),
fIsActive(false) fIsActive(false)
@@ -191,6 +212,9 @@ public:
for (uint32_t i=0, count=fData->stateCount; i < count; ++i) for (uint32_t i=0, count=fData->stateCount; i < count; ++i)
fPlugin->initState(i, fData->stateKeys[i], fData->stateDefValues[i]); fPlugin->initState(i, fData->stateKeys[i], fData->stateDefValues[i]);
#endif #endif

fData->callbacksPtr = callbacksPtr;
fData->writeMidiCallbackFunc = writeMidiCall;
} }


~PluginExporter() ~PluginExporter()
@@ -322,9 +346,26 @@ public:
return fData->parameters[index].designation; return fData->parameters[index].designation;
} }


bool isParameterInput(const uint32_t index) const noexcept
{
return (getParameterHints(index) & kParameterIsOutput) == 0x0;
}

bool isParameterOutput(const uint32_t index) const noexcept bool isParameterOutput(const uint32_t index) const noexcept
{ {
return (getParameterHints(index) & kParameterIsOutput);
return (getParameterHints(index) & kParameterIsOutput) != 0x0;
}

bool isParameterOutputOrTrigger(const uint32_t index) const noexcept
{
const uint32_t hints = getParameterHints(index);

if (hints & kParameterIsOutput)
return true;
if ((hints & kParameterIsTrigger) == kParameterIsTrigger)
return true;

return false;
} }


const String& getParameterName(const uint32_t index) const noexcept const String& getParameterName(const uint32_t index) const noexcept
@@ -348,6 +389,13 @@ public:
return fData->parameters[index].unit; return fData->parameters[index].unit;
} }


const ParameterEnumerationValues& getParameterEnumValues(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackEnumValues);

return fData->parameters[index].enumValues;
}

const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept
{ {
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackRanges); DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackRanges);
@@ -601,9 +649,10 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Static fallback data, see DistrhoPlugin.cpp // Static fallback data, see DistrhoPlugin.cpp


static const String sFallbackString;
static const AudioPort sFallbackAudioPort;
static const ParameterRanges sFallbackRanges;
static const String sFallbackString;
static const AudioPort sFallbackAudioPort;
static const ParameterRanges sFallbackRanges;
static const ParameterEnumerationValues sFallbackEnumValues;


DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter) DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter)
DISTRHO_PREVENT_HEAP_ALLOCATION DISTRHO_PREVENT_HEAP_ALLOCATION


+ 83
- 11
dpf/distrho/src/DistrhoPluginJack.cpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@@ -42,6 +42,9 @@ START_NAMESPACE_DISTRHO
#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_STATE #if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_STATE
static const setStateFunc setStateCallback = nullptr; static const setStateFunc setStateCallback = nullptr;
#endif #endif
#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
static const writeMidiFunc writeMidiCallback = nullptr;
#endif


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


@@ -91,7 +94,7 @@ class PluginJack
{ {
public: public:
PluginJack(jack_client_t* const client) PluginJack(jack_client_t* const client)
: fPlugin(),
: fPlugin(this, writeMidiCallback),
#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, fPlugin.getInstancePointer()), fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, fPlugin.getInstancePointer()),
#endif #endif
@@ -119,6 +122,11 @@ public:


fPortEventsIn = jack_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); fPortEventsIn = jack_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);


#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
fPortMidiOut = jack_port_register(fClient, "midi-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
fPortMidiOutBuffer = nullptr;
#endif

#if DISTRHO_PLUGIN_WANT_PROGRAMS #if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fPlugin.getProgramCount() > 0) if (fPlugin.getProgramCount() > 0)
{ {
@@ -196,11 +204,24 @@ public:
fLastOutputValues = nullptr; fLastOutputValues = nullptr;
} }


#if DISTRHO_PLUGIN_HAS_UI
if (fParametersChanged != nullptr)
{
delete[] fParametersChanged;
fParametersChanged = nullptr;
}
#endif

fPlugin.deactivate(); fPlugin.deactivate();


if (fClient == nullptr) if (fClient == nullptr)
return; return;


#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
jack_port_unregister(fClient, fPortMidiOut);
fPortMidiOut = nullptr;
#endif

jack_port_unregister(fClient, fPortEventsIn); jack_port_unregister(fClient, fPortEventsIn);
fPortEventsIn = nullptr; fPortEventsIn = nullptr;


@@ -330,6 +351,11 @@ protected:


void* const midiBuf = jack_port_get_buffer(fPortEventsIn, nframes); void* const midiBuf = jack_port_get_buffer(fPortEventsIn, nframes);


#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
fPortMidiOutBuffer = jack_port_get_buffer(fPortMidiOut, nframes);
jack_midi_clear_buffer(fPortMidiOutBuffer);
#endif

if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf)) if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf))
{ {
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
@@ -408,6 +434,12 @@ protected:
#else #else
fPlugin.run(audioIns, audioOuts, nframes); fPlugin.run(audioIns, audioOuts, nframes);
#endif #endif

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
fPortMidiOutBuffer = nullptr;
#endif

updateParameterTriggers();
} }


void jackShutdown() void jackShutdown()
@@ -440,6 +472,35 @@ protected:
} }
#endif #endif


#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
bool writeMidi(const MidiEvent& midiEvent)
{
DISTRHO_SAFE_ASSERT_RETURN(fPortMidiOutBuffer != nullptr, false);

return jack_midi_event_write(fPortMidiOutBuffer,
midiEvent.frame,
midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data,
midiEvent.size) == 0;
}
#endif

// NOTE: no trigger support for JACK, simulate it here
void updateParameterTriggers()
{
float defValue;

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) != kParameterIsTrigger)
continue;

defValue = fPlugin.getParameterRanges(i).def;

if (d_isNotEqual(defValue, fPlugin.getParameterValue(i)))
fPlugin.setParameterValue(i, defValue);
}
}

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


private: private:
@@ -457,6 +518,10 @@ private:
jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
#endif #endif
jack_port_t* fPortEventsIn; jack_port_t* fPortEventsIn;
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
jack_port_t* fPortMidiOut;
void* fPortMidiOutBuffer;
#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS #if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePosition fTimePosition; TimePosition fTimePosition;
#endif #endif
@@ -475,51 +540,58 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Callbacks // Callbacks


#define uiPtr ((PluginJack*)ptr)
#define thisPtr ((PluginJack*)ptr)


static int jackBufferSizeCallback(jack_nframes_t nframes, void* ptr) static int jackBufferSizeCallback(jack_nframes_t nframes, void* ptr)
{ {
uiPtr->jackBufferSize(nframes);
thisPtr->jackBufferSize(nframes);
return 0; return 0;
} }


static int jackSampleRateCallback(jack_nframes_t nframes, void* ptr) static int jackSampleRateCallback(jack_nframes_t nframes, void* ptr)
{ {
uiPtr->jackSampleRate(nframes);
thisPtr->jackSampleRate(nframes);
return 0; return 0;
} }


static int jackProcessCallback(jack_nframes_t nframes, void* ptr) static int jackProcessCallback(jack_nframes_t nframes, void* ptr)
{ {
uiPtr->jackProcess(nframes);
thisPtr->jackProcess(nframes);
return 0; return 0;
} }


static void jackShutdownCallback(void* ptr) static void jackShutdownCallback(void* ptr)
{ {
uiPtr->jackShutdown();
thisPtr->jackShutdown();
} }


static void setParameterValueCallback(void* ptr, uint32_t index, float value) static void setParameterValueCallback(void* ptr, uint32_t index, float value)
{ {
uiPtr->setParameterValue(index, value);
thisPtr->setParameterValue(index, value);
} }


#if DISTRHO_PLUGIN_WANT_STATE #if DISTRHO_PLUGIN_WANT_STATE
static void setStateCallback(void* ptr, const char* key, const char* value) static void setStateCallback(void* ptr, const char* key, const char* value)
{ {
uiPtr->setState(key, value);
thisPtr->setState(key, value);
} }
#endif #endif


#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI
static void setSizeCallback(void* ptr, uint width, uint height) static void setSizeCallback(void* ptr, uint width, uint height)
{ {
uiPtr->setSize(width, height);
thisPtr->setSize(width, height);
}
#endif

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent)
{
return thisPtr->writeMidi(midiEvent);
} }
#endif #endif


#undef uiPtr
#undef thisPtr
}; };


END_NAMESPACE_DISTRHO END_NAMESPACE_DISTRHO


+ 33
- 13
dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * 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 * or without fee is hereby granted, provided that the above copyright notice and this
@@ -22,9 +22,12 @@


#ifdef DISTRHO_PLUGIN_TARGET_DSSI #ifdef DISTRHO_PLUGIN_TARGET_DSSI
# include "dssi/dssi.h" # include "dssi/dssi.h"
# if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
# error DSSI does not support MIDI output
# endif
#else #else
# include "ladspa/ladspa.h" # include "ladspa/ladspa.h"
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
# error Cannot use MIDI with LADSPA # error Cannot use MIDI with LADSPA
# endif # endif
# if DISTRHO_PLUGIN_WANT_STATE # if DISTRHO_PLUGIN_WANT_STATE
@@ -44,7 +47,8 @@ class PluginLadspaDssi
{ {
public: public:
PluginLadspaDssi() PluginLadspaDssi()
: fPortControls(nullptr),
: fPlugin(nullptr, nullptr),
fPortControls(nullptr),
fLastControlValues(nullptr) fLastControlValues(nullptr)
{ {
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 #if DISTRHO_PLUGIN_NUM_INPUTS > 0
@@ -171,7 +175,7 @@ public:
{ {
// pre-roll // pre-roll
if (sampleCount == 0) if (sampleCount == 0)
return updateParameterOutputs();
return updateParameterOutputsAndTriggers();


// Check for updated parameters // Check for updated parameters
float curValue; float curValue;
@@ -183,7 +187,7 @@ public:


curValue = *fPortControls[i]; curValue = *fPortControls[i];


if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i))
if (fPlugin.isParameterInput(i) && d_isNotEqual(fLastControlValues[i], curValue))
{ {
fLastControlValues[i] = curValue; fLastControlValues[i] = curValue;
fPlugin.setParameterValue(i, curValue); fPlugin.setParameterValue(i, curValue);
@@ -268,7 +272,7 @@ public:
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount);
#endif #endif


updateParameterOutputs();
updateParameterOutputsAndTriggers();


#if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT
return; // unused return; // unused
@@ -371,17 +375,33 @@ private:


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


void updateParameterOutputs()
void updateParameterOutputsAndTriggers()
{ {
float value;

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{ {
if (! fPlugin.isParameterOutput(i))
continue;
if (fPlugin.isParameterOutput(i))
{
value = fLastControlValues[i] = fPlugin.getParameterValue(i);


fLastControlValues[i] = fPlugin.getParameterValue(i);
if (fPortControls[i] != nullptr)
*fPortControls[i] = value;
}
else if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger)
{
// NOTE: no trigger support in LADSPA control ports, simulate it here
value = fPlugin.getParameterRanges(i).def;


if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
if (d_isEqual(value, fPlugin.getParameterValue(i)))
continue;

fLastControlValues[i] = value;
fPlugin.setParameterValue(i, value);

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


#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
@@ -531,7 +551,7 @@ public:
// Create dummy plugin to get data from // Create dummy plugin to get data from
d_lastBufferSize = 512; d_lastBufferSize = 512;
d_lastSampleRate = 44100.0; d_lastSampleRate = 44100.0;
PluginExporter plugin;
PluginExporter plugin(nullptr, nullptr);
d_lastBufferSize = 0; d_lastBufferSize = 0;
d_lastSampleRate = 0.0; d_lastSampleRate = 0.0;




+ 105
- 35
dpf/distrho/src/DistrhoPluginLV2.cpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * 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 * or without fee is hereby granted, provided that the above copyright notice and this
@@ -32,7 +32,7 @@
#include "lv2/lv2_programs.h" #include "lv2/lv2_programs.h"


#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
# include "libmodauth.h"
# include "libmodla.h"
#endif #endif


#ifdef noexcept #ifdef noexcept
@@ -56,13 +56,18 @@ START_NAMESPACE_DISTRHO


typedef std::map<const String, String> StringMap; typedef std::map<const String, String> StringMap;


#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
static const writeMidiFunc writeMidiCallback = nullptr;
#endif

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


class PluginLv2 class PluginLv2
{ {
public: public:
PluginLv2(const double sampleRate, const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker, const bool usingNominal) PluginLv2(const double sampleRate, const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker, const bool usingNominal)
: fUsingNominal(usingNominal),
: fPlugin(this, writeMidiCallback),
fUsingNominal(usingNominal),
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
fRunCount(0), fRunCount(0),
#endif #endif
@@ -107,9 +112,6 @@ public:
#if DISTRHO_LV2_USE_EVENTS_IN #if DISTRHO_LV2_USE_EVENTS_IN
fPortEventsIn = nullptr; fPortEventsIn = nullptr;
#endif #endif
#if DISTRHO_LV2_USE_EVENTS_OUT
fPortEventsOut = nullptr;
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
fPortLatency = nullptr; fPortLatency = nullptr;
#endif #endif
@@ -226,7 +228,7 @@ public:
#if DISTRHO_LV2_USE_EVENTS_OUT #if DISTRHO_LV2_USE_EVENTS_OUT
if (port == index++) if (port == index++)
{ {
fPortEventsOut = (LV2_Atom_Sequence*)dataLocation;
fEventsOutData.port = (LV2_Atom_Sequence*)dataLocation;
return; return;
} }
#endif #endif
@@ -517,14 +519,12 @@ public:


curValue = *fPortControls[i]; curValue = *fPortControls[i];


if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i))
if (fPlugin.isParameterInput(i) && d_isNotEqual(fLastControlValues[i], curValue))
{ {
fLastControlValues[i] = curValue; fLastControlValues[i] = curValue;


if (fPlugin.getParameterDesignation(i) == kParameterDesignationBypass) if (fPlugin.getParameterDesignation(i) == kParameterDesignationBypass)
{
curValue = 1.0f - curValue; curValue = 1.0f - curValue;
}


fPlugin.setParameterValue(i, curValue); fPlugin.setParameterValue(i, curValue);
} }
@@ -607,20 +607,14 @@ public:
#endif #endif
} }


updateParameterOutputs();
updateParameterOutputsAndTriggers();


#if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI
const uint32_t capacity = fPortEventsOut->atom.size;
fEventsOutData.initIfNeeded(fURIDs.atomSequence);


uint32_t size, offset = 0;
LV2_Atom_Event* aev; LV2_Atom_Event* aev;

fPortEventsOut->atom.size = sizeof(LV2_Atom_Sequence_Body);
fPortEventsOut->atom.type = fURIDs.atomSequence;
fPortEventsOut->body.unit = 0;
fPortEventsOut->body.pad = 0;

// TODO - MIDI Output
uint32_t offset = fEventsOutData.offset;
const uint32_t capacity = fEventsOutData.capacity;


for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
{ {
@@ -645,6 +639,7 @@ public:
break; break;


// reserve msg space // reserve msg space
// FIXME create a large enough buffer beforehand
char msgBuf[msgSize]; char msgBuf[msgSize];
std::memset(msgBuf, 0, msgSize); std::memset(msgBuf, 0, msgSize);


@@ -653,21 +648,23 @@ public:
std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()); std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length());


// put data // put data
aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fPortEventsOut) + offset);
aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + offset);
aev->time.frames = 0; aev->time.frames = 0;
aev->body.type = fURIDs.distrhoState; aev->body.type = fURIDs.distrhoState;
aev->body.size = msgSize; aev->body.size = msgSize;
std::memcpy(LV2_ATOM_BODY(&aev->body), msgBuf, msgSize-1); std::memcpy(LV2_ATOM_BODY(&aev->body), msgBuf, msgSize-1);


size = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize);
offset += size;
fPortEventsOut->atom.size += size;
fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize));


fNeededUiSends[i] = false; fNeededUiSends[i] = false;
break; break;
} }
} }
#endif #endif

#if DISTRHO_LV2_USE_EVENTS_OUT
fEventsOutData.endRun();
#endif
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -883,9 +880,6 @@ private:
#if DISTRHO_LV2_USE_EVENTS_IN #if DISTRHO_LV2_USE_EVENTS_IN
LV2_Atom_Sequence* fPortEventsIn; LV2_Atom_Sequence* fPortEventsIn;
#endif #endif
#if DISTRHO_LV2_USE_EVENTS_OUT
LV2_Atom_Sequence* fPortEventsOut;
#endif
#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
float* fPortLatency; float* fPortLatency;
#endif #endif
@@ -922,6 +916,44 @@ private:
} fLastPositionData; } fLastPositionData;
#endif #endif


#if DISTRHO_LV2_USE_EVENTS_OUT
struct Lv2EventsOutData {
uint32_t capacity, offset;
LV2_Atom_Sequence* port;

Lv2EventsOutData()
: capacity(0),
offset(0),
port(nullptr) {}

void initIfNeeded(const LV2_URID uridAtomSequence)
{
if (capacity != 0)
return;

capacity = port->atom.size;

port->atom.size = sizeof(LV2_Atom_Sequence_Body);
port->atom.type = uridAtomSequence;
port->body.unit = 0;
port->body.pad = 0;
}

void growBy(const uint32_t size)
{
offset += size;
port->atom.size += size;
}

void endRun()
{
capacity = 0;
offset = 0;
}

} fEventsOutData;
#endif

// LV2 URIDs // LV2 URIDs
struct URIDs { struct URIDs {
LV2_URID atomBlank; LV2_URID atomBlank;
@@ -998,17 +1030,23 @@ private:
} }
#endif #endif


void updateParameterOutputs()
void updateParameterOutputsAndTriggers()
{ {
float curValue;

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

fLastControlValues[i] = fPlugin.getParameterValue(i);
if (fPlugin.isParameterOutput(i))
{
curValue = fLastControlValues[i] = fPlugin.getParameterValue(i);


if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
if (fPortControls[i] != nullptr)
*fPortControls[i] = curValue;
}
else if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger)
{
// NOTE: host is responsible for auto-updating control port buffers
}
} }


#if DISTRHO_PLUGIN_WANT_LATENCY #if DISTRHO_PLUGIN_WANT_LATENCY
@@ -1016,6 +1054,38 @@ private:
*fPortLatency = fPlugin.getLatency(); *fPortLatency = fPlugin.getLatency();
#endif #endif
} }

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
bool writeMidi(const MidiEvent& midiEvent)
{
DISTRHO_SAFE_ASSERT_RETURN(fEventsOutData.port != nullptr, false);

fEventsOutData.initIfNeeded(fURIDs.atomSequence);

const uint32_t capacity = fEventsOutData.capacity;
const uint32_t offset = fEventsOutData.offset;

if (sizeof(LV2_Atom_Event) + midiEvent.size > capacity - offset)
return false;

LV2_Atom_Event* const aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fEventsOutData.port) + offset);
aev->time.frames = midiEvent.frame;
aev->body.type = fURIDs.midiEvent;
aev->body.size = midiEvent.size;
std::memcpy(LV2_ATOM_BODY(&aev->body),
midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data,
midiEvent.size);

fEventsOutData.growBy(lv2_atom_pad_size(sizeof(LV2_Atom_Event) + midiEvent.size));

return true;
}

static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent)
{
return ((PluginLv2*)ptr)->writeMidi(midiEvent);
}
#endif
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -1057,7 +1127,7 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons
#endif #endif


#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD #ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
mod_check_license(features, DISTRHO_PLUGIN_URI);
mod_license_check(features, DISTRHO_PLUGIN_URI);
#endif #endif


d_lastBufferSize = 0; d_lastBufferSize = 0;


+ 47
- 24
dpf/distrho/src/DistrhoPluginLV2export.cpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * 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 * or without fee is hereby granted, provided that the above copyright notice and this
@@ -80,7 +80,7 @@ void lv2_generate_ttl(const char* const basename)
// Dummy plugin to get data from // Dummy plugin to get data from
d_lastBufferSize = 512; d_lastBufferSize = 512;
d_lastSampleRate = 44100.0; d_lastSampleRate = 44100.0;
PluginExporter plugin;
PluginExporter plugin(nullptr, nullptr);
d_lastBufferSize = 0; d_lastBufferSize = 0;
d_lastSampleRate = 0.0; d_lastSampleRate = 0.0;


@@ -202,6 +202,7 @@ void lv2_generate_ttl(const char* const basename)
pluginString += "@prefix mod: <http://moddevices.com/ns/mod#> .\n"; pluginString += "@prefix mod: <http://moddevices.com/ns/mod#> .\n";
#endif #endif
pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n"; pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n";
pluginString += "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n";
pluginString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n"; pluginString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n"; pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n";
#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI
@@ -398,7 +399,7 @@ void lv2_generate_ttl(const char* const basename)
bool designated = false; bool designated = false;


// designation // designation
if (! plugin.isParameterOutput(i))
if (plugin.isParameterInput(i))
{ {
switch (plugin.getParameterDesignation(i)) switch (plugin.getParameterDesignation(i))
{ {
@@ -417,10 +418,10 @@ void lv2_generate_ttl(const char* const basename)
} }
} }


// name and symbol
if (! designated) if (! designated)
{ {
pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";
// name and symbol
pluginString += " lv2:name \"\"\"" + plugin.getParameterName(i) + "\"\"\" ;\n";


String symbol(plugin.getParameterSymbol(i)); String symbol(plugin.getParameterSymbol(i));


@@ -428,32 +429,53 @@ void lv2_generate_ttl(const char* const basename)
symbol = "lv2_port_" + String(portIndex-1); symbol = "lv2_port_" + String(portIndex-1);


pluginString += " lv2:symbol \"" + symbol + "\" ;\n"; pluginString += " lv2:symbol \"" + symbol + "\" ;\n";
}


// ranges
if (! designated)
{
// ranges
const ParameterRanges& ranges(plugin.getParameterRanges(i)); const ParameterRanges& ranges(plugin.getParameterRanges(i));


if (plugin.getParameterHints(i) & kParameterIsInteger) if (plugin.getParameterHints(i) & kParameterIsInteger)
{ {
if (! plugin.isParameterOutput(i))
if (plugin.isParameterInput(i))
pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n"; pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n";
pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n"; pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n";
pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n"; pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n";
} }
else else
{ {
if (! plugin.isParameterOutput(i))
if (plugin.isParameterInput(i))
pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n"; pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n";
pluginString += " lv2:minimum " + String(ranges.min) + " ;\n"; pluginString += " lv2:minimum " + String(ranges.min) + " ;\n";
pluginString += " lv2:maximum " + String(ranges.max) + " ;\n"; pluginString += " lv2:maximum " + String(ranges.max) + " ;\n";
} }
}


// unit
if (! designated)
{
// enumeration
const ParameterEnumerationValues& enumValues(plugin.getParameterEnumValues(i));

if (enumValues.count > 0)
{
if (enumValues.count >= 2 && enumValues.restrictedMode)
pluginString += " lv2:portProperty lv2:enumeration ;\n";

for (uint8_t j=0; j < enumValues.count; ++j)
{
const ParameterEnumerationValue& enumValue(enumValues.values[j]);

if (j == 0)
pluginString += " lv2:scalePoint [\n";
else
pluginString += " [\n";

pluginString += " rdfs:label \"\"\"" + enumValue.label + "\"\"\" ;\n";
pluginString += " rdf:value " + String(enumValue.value) + " ;\n";

if (j+1 == enumValues.count)
pluginString += " ] ;\n\n";
else
pluginString += " ] ,\n";
}
}

// unit
const String& unit(plugin.getParameterUnit(i)); const String& unit(plugin.getParameterUnit(i));


if (! unit.isEmpty()) if (! unit.isEmpty())
@@ -495,25 +517,26 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " ] ;\n"; pluginString += " ] ;\n";
} }
} }
}


// hints
if (! designated)
{
// hints
const uint32_t hints(plugin.getParameterHints(i)); const uint32_t hints(plugin.getParameterHints(i));


if (hints & kParameterIsBoolean) if (hints & kParameterIsBoolean)
{
if ((hints & kParameterIsTrigger) == kParameterIsTrigger)
pluginString += " lv2:portProperty <" LV2_PORT_PROPS__trigger "> ;\n";
pluginString += " lv2:portProperty lv2:toggled ;\n"; pluginString += " lv2:portProperty lv2:toggled ;\n";
}
if (hints & kParameterIsInteger) if (hints & kParameterIsInteger)
pluginString += " lv2:portProperty lv2:integer ;\n"; pluginString += " lv2:portProperty lv2:integer ;\n";
if (hints & kParameterIsLogarithmic) if (hints & kParameterIsLogarithmic)
pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n"; pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n";
if ((hints & kParameterIsAutomable) == 0 && ! plugin.isParameterOutput(i))
if ((hints & kParameterIsAutomable) == 0 && plugin.isParameterInput(i))
{ {
pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n"; pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n";
pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n"; pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n";
} }
}
} // ! designated


if (i+1 == count) if (i+1 == count)
pluginString += " ] ;\n\n"; pluginString += " ] ;\n\n";
@@ -537,7 +560,7 @@ void lv2_generate_ttl(const char* const basename)
#endif #endif


// name // name
pluginString += " doap:name \"" + String(plugin.getName()) + "\" ;\n";
pluginString += " doap:name \"\"\"" + String(plugin.getName()) + "\"\"\" ;\n";


// license // license
{ {
@@ -546,7 +569,7 @@ void lv2_generate_ttl(const char* const basename)
if (license.contains("://")) if (license.contains("://"))
pluginString += " doap:license <" + license + "> ;\n\n"; pluginString += " doap:license <" + license + "> ;\n\n";
else else
pluginString += " doap:license \"" + license + "\" ;\n\n";
pluginString += " doap:license \"\"\"" + license + "\"\"\" ;\n\n";
} }


// developer // developer
@@ -554,7 +577,7 @@ void lv2_generate_ttl(const char* const basename)
const String homepage(plugin.getHomePage()); const String homepage(plugin.getHomePage());


pluginString += " doap:maintainer [\n"; pluginString += " doap:maintainer [\n";
pluginString += " foaf:name \"" + String(plugin.getMaker()) + "\" ;\n";
pluginString += " foaf:name \"\"\"" + String(plugin.getMaker()) + "\"\"\" ;\n";


if (homepage.isNotEmpty()) if (homepage.isNotEmpty())
pluginString += " foaf:homepage <" + homepage + "> ;\n"; pluginString += " foaf:homepage <" + homepage + "> ;\n";


+ 257
- 80
dpf/distrho/src/DistrhoPluginVST.cpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * 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 * or without fee is hereby granted, provided that the above copyright notice and this
@@ -37,11 +37,12 @@
#define VESTIGE_HEADER #define VESTIGE_HEADER
#define VST_FORCE_DEPRECATED 0 #define VST_FORCE_DEPRECATED 0


#include <clocale>
#include <map> #include <map>
#include <string> #include <string>


#ifdef VESTIGE_HEADER #ifdef VESTIGE_HEADER
# include "vestige/aeffectx.h"
# include "vestige/vestige.h"
#define effFlagsProgramChunks (1 << 5) #define effFlagsProgramChunks (1 << 5)
#define effSetProgramName 4 #define effSetProgramName 4
#define effGetParamLabel 6 #define effGetParamLabel 6
@@ -51,11 +52,8 @@
#define effCanBeAutomated 26 #define effCanBeAutomated 26
#define effGetProgramNameIndexed 29 #define effGetProgramNameIndexed 29
#define effGetPlugCategory 35 #define effGetPlugCategory 35
#define effIdle 53
#define effEditKeyDown 59 #define effEditKeyDown 59
#define effEditKeyUp 60 #define effEditKeyUp 60
#define kPlugCategEffect 1
#define kPlugCategSynth 2
#define kVstVersion 2400 #define kVstVersion 2400
struct ERect { struct ERect {
int16_t top, left, bottom, right; int16_t top, left, bottom, right;
@@ -68,6 +66,12 @@ START_NAMESPACE_DISTRHO


typedef std::map<const String, String> StringMap; typedef std::map<const String, String> StringMap;


static const int kVstMidiEventSize = static_cast<int>(sizeof(VstMidiEvent));

#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
static const writeMidiFunc writeMidiCallback = nullptr;
#endif

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


void strncpy(char* const dst, const char* const src, const size_t size) void strncpy(char* const dst, const char* const src, const size_t size)
@@ -88,17 +92,42 @@ void snprintf_iparam(char* const dst, const int32_t value, const size_t size)
dst[size-1] = '\0'; dst[size-1] = '\0';
} }


#if DISTRHO_PLUGIN_HAS_UI
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------


class UiHelper
class ScopedSafeLocale {
public:
ScopedSafeLocale() noexcept
: locale(::strdup(::setlocale(LC_NUMERIC, nullptr)))
{
::setlocale(LC_NUMERIC, "C");
}

~ScopedSafeLocale() noexcept
{
if (locale != nullptr)
{
::setlocale(LC_NUMERIC, locale);
std::free(locale);
}
}

private:
char* const locale;

DISTRHO_DECLARE_NON_COPY_CLASS(ScopedSafeLocale)
DISTRHO_PREVENT_HEAP_ALLOCATION
};

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

class ParameterCheckHelper
{ {
public: public:
UiHelper()
ParameterCheckHelper()
: parameterChecks(nullptr), : parameterChecks(nullptr),
parameterValues(nullptr) {} parameterValues(nullptr) {}


virtual ~UiHelper()
virtual ~ParameterCheckHelper()
{ {
if (parameterChecks != nullptr) if (parameterChecks != nullptr)
{ {
@@ -112,20 +141,21 @@ public:
} }
} }


bool* parameterChecks;
float* parameterValues;
bool* parameterChecks;
float* parameterValues;


# if DISTRHO_PLUGIN_WANT_STATE
#if DISTRHO_PLUGIN_WANT_STATE
virtual void setStateFromUI(const char* const newKey, const char* const newValue) = 0; virtual void setStateFromUI(const char* const newKey, const char* const newValue) = 0;
# endif
#endif
}; };


#if DISTRHO_PLUGIN_HAS_UI
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------


class UIVst class UIVst
{ {
public: public:
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, UiHelper* const uiHelper, PluginExporter* const plugin, const intptr_t winId)
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, ParameterCheckHelper* const uiHelper, PluginExporter* const plugin, const intptr_t winId)
: fAudioMaster(audioMaster), : fAudioMaster(audioMaster),
fEffect(effect), fEffect(effect),
fUiHelper(uiHelper), fUiHelper(uiHelper),
@@ -300,7 +330,7 @@ private:
// Vst stuff // Vst stuff
const audioMasterCallback fAudioMaster; const audioMasterCallback fAudioMaster;
AEffect* const fEffect; AEffect* const fEffect;
UiHelper* const fUiHelper;
ParameterCheckHelper* const fUiHelper;
PluginExporter* const fPlugin; PluginExporter* const fPlugin;


// Plugin UI // Plugin UI
@@ -343,15 +373,12 @@ private:


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


#if DISTRHO_PLUGIN_HAS_UI
class PluginVst : public UiHelper
#else
class PluginVst
#endif
class PluginVst : public ParameterCheckHelper
{ {
public: public:
PluginVst(const audioMasterCallback audioMaster, AEffect* const effect) PluginVst(const audioMasterCallback audioMaster, AEffect* const effect)
: fAudioMaster(audioMaster),
: fPlugin(this, writeMidiCallback),
fAudioMaster(audioMaster),
fEffect(effect) fEffect(effect)
{ {
std::memset(fProgramName, 0, sizeof(char)*(32+1)); std::memset(fProgramName, 0, sizeof(char)*(32+1));
@@ -376,14 +403,14 @@ public:
for (uint32_t i=0; i < paramCount; ++i) for (uint32_t i=0; i < paramCount; ++i)
{ {
parameterChecks[i] = false; parameterChecks[i] = false;
parameterValues[i] = 0.0f;
parameterValues[i] = NAN;
} }
} }
# if DISTRHO_OS_MAC # if DISTRHO_OS_MAC
# ifdef __LP64__ # ifdef __LP64__
fUsingNsView = true; fUsingNsView = true;
# else # else
# warning 32bit VST UIs on OSX only work if the host supports "hasCockosViewAsConfig"
# warning 32bit VST UIs on OSX only work if the host supports "hasCockosViewAsConfig"
fUsingNsView = false; fUsingNsView = false;
# endif # endif
# endif // DISTRHO_OS_MAC # endif // DISTRHO_OS_MAC
@@ -453,24 +480,35 @@ public:
{ {
const uint32_t hints = fPlugin.getParameterHints(index); const uint32_t hints = fPlugin.getParameterHints(index);
float value = fPlugin.getParameterValue(index); float value = fPlugin.getParameterValue(index);
if (hints & kParameterIsBoolean) if (hints & kParameterIsBoolean)
{ {
const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); const ParameterRanges& ranges(fPlugin.getParameterRanges(index));
const float midRange = ranges.min + (ranges.max - ranges.min) / 2.0f; const float midRange = ranges.min + (ranges.max - ranges.min) / 2.0f;
value = value > midRange ? ranges.max : ranges.min; value = value > midRange ? ranges.max : ranges.min;
} }
if (hints & kParameterIsInteger)
else if (hints & kParameterIsInteger)
{ {
DISTRHO_NAMESPACE::snprintf_iparam((char*)ptr, (int32_t)std::round(value), 24);
value = std::round(value);
} }
else

const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(index));

for (uint8_t i = 0; i < enumValues.count; ++i)
{ {
DISTRHO_NAMESPACE::snprintf_param((char*)ptr, value, 24);
if (d_isNotEqual(value, enumValues.values[i].value))
continue;

DISTRHO_NAMESPACE::strncpy((char*)ptr, enumValues.values[i].label.buffer(), 24);
return 1;
} }


if (hints & kParameterIsInteger)
DISTRHO_NAMESPACE::snprintf_iparam((char*)ptr, (int32_t)value, 24);
else
DISTRHO_NAMESPACE::snprintf_param((char*)ptr, value, 24);

return 1; return 1;
} }
break; break;
@@ -607,6 +645,7 @@ public:


#if DISTRHO_PLUGIN_WANT_STATE #if DISTRHO_PLUGIN_WANT_STATE
case effGetChunk: case effGetChunk:
{
if (ptr == nullptr) if (ptr == nullptr)
return 0; return 0;


@@ -616,7 +655,9 @@ public:
fStateChunk = nullptr; fStateChunk = nullptr;
} }


if (fPlugin.getStateCount() == 0)
const uint32_t paramCount = fPlugin.getParameterCount();

if (fPlugin.getStateCount() == 0 && paramCount == 0)
{ {
fStateChunk = new char[1]; fStateChunk = new char[1];
fStateChunk[0] = '\0'; fStateChunk[0] = '\0';
@@ -650,6 +691,30 @@ public:
chunkStr += tmpStr; chunkStr += tmpStr;
} }


if (paramCount != 0)
{
// add another separator
chunkStr += "\xff";

// temporarily set locale to "C" while converting floats
const ScopedSafeLocale ssl;

for (uint32_t i=0; i<paramCount; ++i)
{
if (fPlugin.isParameterOutputOrTrigger(i))
continue;

// join key and value
String tmpStr;
tmpStr = fPlugin.getParameterSymbol(i);
tmpStr += "\xff";
tmpStr += String(fPlugin.getParameterValue(i));
tmpStr += "\xff";

chunkStr += tmpStr;
}
}

const std::size_t chunkSize(chunkStr.length()+1); const std::size_t chunkSize(chunkStr.length()+1);


fStateChunk = new char[chunkSize]; fStateChunk = new char[chunkSize];
@@ -667,21 +732,27 @@ public:


*(void**)ptr = fStateChunk; *(void**)ptr = fStateChunk;
return ret; return ret;
}


case effSetChunk: case effSetChunk:
{ {
if (value <= 1 || ptr == nullptr) if (value <= 1 || ptr == nullptr)
return 0; return 0;


const size_t chunkSize = static_cast<size_t>(value);

const char* key = (const char*)ptr; const char* key = (const char*)ptr;
const char* value = nullptr; const char* value = nullptr;
size_t size, bytesRead = 0;


for (;;)
while (bytesRead < chunkSize)
{ {
if (key[0] == '\0') if (key[0] == '\0')
break; break;


value = key+(std::strlen(key)+1);
size = std::strlen(key)+1;
value = key + size;
bytesRead += size;


setStateFromUI(key, value); setStateFromUI(key, value);


@@ -691,7 +762,52 @@ public:
# endif # endif


// get next key // get next key
key = value+(std::strlen(value)+1);
size = std::strlen(value)+1;
key = value + size;
bytesRead += size;
}

const uint32_t paramCount = fPlugin.getParameterCount();

if (bytesRead+4 < chunkSize && paramCount != 0)
{
++key;
float fvalue;

// temporarily set locale to "C" while converting floats
const ScopedSafeLocale ssl;

while (bytesRead < chunkSize)
{
if (key[0] == '\0')
break;

size = std::strlen(key)+1;
value = key + size;
bytesRead += size;

// find parameter with this symbol, and set its value
for (uint32_t i=0; i<paramCount; ++i)
{
if (fPlugin.isParameterOutputOrTrigger(i))
continue;
if (fPlugin.getParameterSymbol(i) != key)
continue;

fvalue = std::atof(value);
fPlugin.setParameterValue(i, fvalue);
# if DISTRHO_PLUGIN_HAS_UI
if (fVstUI != nullptr)
setParameterValueFromPlugin(i, fvalue);
# endif
break;
}

// get next key
size = std::strlen(value)+1;
key = value + size;
bytesRead += size;
}
} }


return 1; return 1;
@@ -805,7 +921,10 @@ public:
void vst_processReplacing(const float** const inputs, float** const outputs, const int32_t sampleFrames) void vst_processReplacing(const float** const inputs, float** const outputs, const int32_t sampleFrames)
{ {
if (sampleFrames <= 0) if (sampleFrames <= 0)
{
updateParameterOutputsAndTriggers();
return; return;
}


if (! fPlugin.isActive()) if (! fPlugin.isActive())
{ {
@@ -864,16 +983,7 @@ public:
fPlugin.run(inputs, outputs, sampleFrames); fPlugin.run(inputs, outputs, sampleFrames);
#endif #endif


#if DISTRHO_PLUGIN_HAS_UI
if (fVstUI == nullptr)
return;

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (fPlugin.isParameterOutput(i))
setParameterValueFromPlugin(i, fPlugin.getParameterValue(i));
}
#endif
updateParameterOutputsAndTriggers();
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -881,13 +991,13 @@ public:
friend class UIVst; friend class UIVst;


private: private:
// Plugin
PluginExporter fPlugin;

// VST stuff // VST stuff
const audioMasterCallback fAudioMaster; const audioMasterCallback fAudioMaster;
AEffect* const fEffect; AEffect* const fEffect;


// Plugin
PluginExporter fPlugin;

// Temporary data // Temporary data
char fProgramName[32+1]; char fProgramName[32+1];


@@ -929,6 +1039,56 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// functions called from the plugin side, RT no block // functions called from the plugin side, RT no block


void updateParameterOutputsAndTriggers()
{
float curValue;

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (fPlugin.isParameterOutput(i))
{
// NOTE: no output parameter support in VST, simulate it here
curValue = fPlugin.getParameterValue(i);

if (d_isEqual(curValue, parameterValues[i]))
continue;

#if DISTRHO_PLUGIN_HAS_UI
if (fVstUI != nullptr)
setParameterValueFromPlugin(i, curValue);
else
#endif
parameterValues[i] = curValue;

#ifndef DPF_VST_SHOW_PARAMETER_OUTPUTS
// skip automating parameter outputs from plugin if we disable them on VST
continue;
#endif
}
else if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger)
{
// NOTE: no trigger support in VST parameters, simulate it here
curValue = fPlugin.getParameterValue(i);

if (d_isEqual(curValue, fPlugin.getParameterRanges(i).def))
continue;

#if DISTRHO_PLUGIN_HAS_UI
if (fVstUI != nullptr)
setParameterValueFromPlugin(i, curValue);
#endif
fPlugin.setParameterValue(i, curValue);
}
else
{
continue;
}

const ParameterRanges& ranges(fPlugin.getParameterRanges(i));
hostCallback(audioMasterAutomate, i, 0, nullptr, ranges.getNormalizedValue(curValue));
}
}

#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI
void setParameterValueFromPlugin(const uint32_t index, const float realValue) void setParameterValueFromPlugin(const uint32_t index, const float realValue)
{ {
@@ -937,6 +1097,37 @@ private:
} }
#endif #endif


#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
bool writeMidi(const MidiEvent& midiEvent)
{
if (midiEvent.size > 4)
return true;

VstEvents vstEvents;
std::memset(&vstEvents, 0, sizeof(VstEvents));

VstMidiEvent vstMidiEvent;
std::memset(&vstMidiEvent, 0, sizeof(VstMidiEvent));

vstEvents.numEvents = 1;
vstEvents.events[0] = (VstEvent*)&vstMidiEvent;

vstMidiEvent.type = kVstMidiType;
vstMidiEvent.byteSize = kVstMidiEventSize;
vstMidiEvent.deltaFrames = midiEvent.frame;

for (uint8_t i=0; i<midiEvent.size; ++i)
vstMidiEvent.midiData[i] = midiEvent.data[i];

return hostCallback(audioMasterProcessEvents, 0, 0, &vstEvents) == 1;
}

static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent)
{
return ((PluginVst*)ptr)->writeMidi(midiEvent);
}
#endif

#if DISTRHO_PLUGIN_WANT_STATE #if DISTRHO_PLUGIN_WANT_STATE
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// functions called from the UI side, may block // functions called from the UI side, may block
@@ -977,17 +1168,10 @@ struct VstObject {
PluginVst* plugin; PluginVst* plugin;
}; };


#ifdef VESTIGE_HEADER
# define validObject effect != nullptr && effect->ptr3 != nullptr
# define validPlugin effect != nullptr && effect->ptr3 != nullptr && ((VstObject*)effect->ptr3)->plugin != nullptr
# define vstObjectPtr (VstObject*)effect->ptr3
#else
# define validObject effect != nullptr && effect->object != nullptr
# define validPlugin effect != nullptr && effect->object != nullptr && ((VstObject*)effect->object)->plugin != nullptr
# define vstObjectPtr (VstObject*)effect->object
#endif

#define pluginPtr (vstObjectPtr)->plugin
#define validObject effect != nullptr && effect->object != nullptr
#define validPlugin effect != nullptr && effect->object != nullptr && ((VstObject*)effect->object)->plugin != nullptr
#define vstObjectPtr (VstObject*)effect->object
#define pluginPtr (vstObjectPtr)->plugin


static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
{ {
@@ -1002,7 +1186,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
} }


// Create dummy plugin to get data from // Create dummy plugin to get data from
static PluginExporter plugin;
static PluginExporter plugin(nullptr, nullptr);


if (doInternalInit) if (doInternalInit)
{ {
@@ -1055,11 +1239,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
/* This code invalidates the object created in VSTPluginMain /* This code invalidates the object created in VSTPluginMain
* Probably not safe against all hosts */ * Probably not safe against all hosts */
obj->audioMaster = nullptr; obj->audioMaster = nullptr;
# ifdef VESTIGE_HEADER
effect->ptr3 = nullptr;
# else
vstObjectPtr = nullptr;
# endif
effect->object = nullptr;
delete obj; delete obj;
#endif #endif


@@ -1083,14 +1263,14 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
return 1; return 1;
} }
return 0; return 0;
case effGetParameterProperties: case effGetParameterProperties:
if (ptr != nullptr && index < static_cast<int32_t>(plugin.getParameterCount())) if (ptr != nullptr && index < static_cast<int32_t>(plugin.getParameterCount()))
{ {
if (VstParameterProperties* const properties = (VstParameterProperties*)ptr) if (VstParameterProperties* const properties = (VstParameterProperties*)ptr)
{ {
memset(properties, 0, sizeof(VstParameterProperties)); memset(properties, 0, sizeof(VstParameterProperties));
const uint32_t hints = plugin.getParameterHints(index); const uint32_t hints = plugin.getParameterHints(index);


if (hints & kParameterIsOutput) if (hints & kParameterIsOutput)
@@ -1100,7 +1280,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
{ {
properties->flags |= kVstParameterIsSwitch; properties->flags |= kVstParameterIsSwitch;
} }
if (hints & kParameterIsInteger) if (hints & kParameterIsInteger)
{ {
properties->flags |= kVstParameterUsesIntegerMinMax; properties->flags |= kVstParameterUsesIntegerMinMax;
@@ -1119,7 +1299,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t
} }
} }
return 0; return 0;
case effGetPlugCategory: case effGetPlugCategory:
#if DISTRHO_PLUGIN_IS_SYNTH #if DISTRHO_PLUGIN_IS_SYNTH
return kPlugCategSynth; return kPlugCategSynth;
@@ -1226,20 +1406,18 @@ const AEffect* VSTPluginMain(audioMasterCallback audioMaster)
// vst fields // vst fields
effect->magic = kEffectMagic; effect->magic = kEffectMagic;
effect->uniqueID = plugin->getUniqueId(); effect->uniqueID = plugin->getUniqueId();
#ifdef VESTIGE_HEADER
int32_t* const version = (int32_t*)&effect->unknown1;
*version = plugin->getVersion();
#else
effect->version = plugin->getVersion();
#endif
effect->version = plugin->getVersion();


// VST doesn't support parameter outputs, hide them
// VST doesn't support parameter outputs. we can fake them, but it is a hack. Disabled by default.
#ifdef DPF_VST_SHOW_PARAMETER_OUTPUTS
const int numParams = plugin->getParameterCount();
#else
int numParams = 0; int numParams = 0;
bool outputsReached = false; bool outputsReached = false;


for (uint32_t i=0, count=plugin->getParameterCount(); i < count; ++i) for (uint32_t i=0, count=plugin->getParameterCount(); i < count; ++i)
{ {
if (! plugin->isParameterOutput(i))
if (plugin->isParameterInput(i))
{ {
// parameter outputs must be all at the end // parameter outputs must be all at the end
DISTRHO_SAFE_ASSERT_BREAK(! outputsReached); DISTRHO_SAFE_ASSERT_BREAK(! outputsReached);
@@ -1248,6 +1426,7 @@ const AEffect* VSTPluginMain(audioMasterCallback audioMaster)
} }
outputsReached = true; outputsReached = true;
} }
#endif


// plugin fields // plugin fields
effect->numParams = numParams; effect->numParams = numParams;
@@ -1278,11 +1457,9 @@ const AEffect* VSTPluginMain(audioMasterCallback audioMaster)
VstObject* const obj(new VstObject()); VstObject* const obj(new VstObject());
obj->audioMaster = audioMaster; obj->audioMaster = audioMaster;
obj->plugin = nullptr; obj->plugin = nullptr;
#ifdef VESTIGE_HEADER
effect->ptr3 = obj;
#else

// done
effect->object = obj; effect->object = obj;
#endif


return effect; return effect;
} }


+ 1
- 1
dpf/distrho/src/DistrhoUI.cpp View File

@@ -82,7 +82,7 @@ void UI::setState(const char* key, const char* value)
} }
#endif #endif


#if DISTRHO_PLUGIN_IS_SYNTH
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity) void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity)
{ {
pData->sendNoteCallback(channel, note, velocity); pData->sendNoteCallback(channel, note, velocity);


+ 14
- 3
dpf/distrho/src/DistrhoUIDSSI.cpp View File

@@ -26,6 +26,10 @@


START_NAMESPACE_DISTRHO START_NAMESPACE_DISTRHO


#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT
static const sendNoteFunc sendNoteCallback = nullptr;
#endif

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


struct OscData { struct OscData {
@@ -180,6 +184,7 @@ protected:
fOscData.send_configure(key, value); fOscData.send_configure(key, value);
} }


#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{ {
if (fOscData.server == nullptr) if (fOscData.server == nullptr)
@@ -187,11 +192,15 @@ protected:
if (channel > 0xF) if (channel > 0xF)
return; return;


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

uint8_t mdata[4] = {
0,
channel + (velocity != 0 ? 0x90 : 0x80),
note,
velocity
};
fOscData.send_midi(mdata); fOscData.send_midi(mdata);
} }
#endif


void setSize(const uint width, const uint height) void setSize(const uint width, const uint height)
{ {
@@ -219,10 +228,12 @@ private:
uiPtr->setState(key, value); uiPtr->setState(key, value);
} }


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


static void setSizeCallback(void* ptr, uint width, uint height) static void setSizeCallback(void* ptr, uint width, uint height)
{ {


+ 17
- 12
dpf/distrho/src/DistrhoUIInternal.hpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * 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 * or without fee is hereby granted, provided that the above copyright notice and this
@@ -61,12 +61,12 @@ struct UI::PrivateData {
#endif #endif


// Callbacks // Callbacks
void* callbacksPtr;
editParamFunc editParamCallbackFunc; editParamFunc editParamCallbackFunc;
setParamFunc setParamCallbackFunc; setParamFunc setParamCallbackFunc;
setStateFunc setStateCallbackFunc; setStateFunc setStateCallbackFunc;
sendNoteFunc sendNoteCallbackFunc; sendNoteFunc sendNoteCallbackFunc;
setSizeFunc setSizeCallbackFunc; setSizeFunc setSizeCallbackFunc;
void* ptr;


PrivateData() noexcept PrivateData() noexcept
: sampleRate(d_lastUiSampleRate), : sampleRate(d_lastUiSampleRate),
@@ -74,12 +74,12 @@ struct UI::PrivateData {
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
dspPtr(d_lastUiDspPtr), dspPtr(d_lastUiDspPtr),
#endif #endif
callbacksPtr(nullptr),
editParamCallbackFunc(nullptr), editParamCallbackFunc(nullptr),
setParamCallbackFunc(nullptr), setParamCallbackFunc(nullptr),
setStateCallbackFunc(nullptr), setStateCallbackFunc(nullptr),
sendNoteCallbackFunc(nullptr), sendNoteCallbackFunc(nullptr),
setSizeCallbackFunc(nullptr),
ptr(nullptr)
setSizeCallbackFunc(nullptr)
{ {
DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate)); DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate));


@@ -103,31 +103,31 @@ struct UI::PrivateData {
void editParamCallback(const uint32_t rindex, const bool started) void editParamCallback(const uint32_t rindex, const bool started)
{ {
if (editParamCallbackFunc != nullptr) if (editParamCallbackFunc != nullptr)
editParamCallbackFunc(ptr, rindex, started);
editParamCallbackFunc(callbacksPtr, rindex, started);
} }


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


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


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


void setSizeCallback(const uint width, const uint height) void setSizeCallback(const uint width, const uint height)
{ {
if (setSizeCallbackFunc != nullptr) if (setSizeCallbackFunc != nullptr)
setSizeCallbackFunc(ptr, width, height);
setSizeCallbackFunc(callbacksPtr, width, height);
} }
}; };


@@ -221,8 +221,13 @@ UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const char* const
class UIExporter class UIExporter
{ {
public: public:
UIExporter(void* const ptr, const intptr_t winId,
const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const setSizeFunc setSizeCall,
UIExporter(void* const callbacksPtr,
const intptr_t winId,
const editParamFunc editParamCall,
const setParamFunc setParamCall,
const setStateFunc setStateCall,
const sendNoteFunc sendNoteCall,
const setSizeFunc setSizeCall,
void* const dspPtr = nullptr, void* const dspPtr = nullptr,
const char* const bundlePath = nullptr) const char* const bundlePath = nullptr)
#ifdef HAVE_DGL #ifdef HAVE_DGL
@@ -238,7 +243,7 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);


fData->ptr = ptr;
fData->callbacksPtr = callbacksPtr;
fData->editParamCallbackFunc = editParamCall; fData->editParamCallbackFunc = editParamCall;
fData->setParamCallbackFunc = setParamCall; fData->setParamCallbackFunc = setParamCall;
fData->setStateCallbackFunc = setStateCall; fData->setStateCallbackFunc = setStateCall;


+ 34
- 1
dpf/distrho/src/DistrhoUILV2.cpp View File

@@ -22,6 +22,7 @@
#include "lv2/atom-util.h" #include "lv2/atom-util.h"
#include "lv2/data-access.h" #include "lv2/data-access.h"
#include "lv2/instance-access.h" #include "lv2/instance-access.h"
#include "lv2/midi.h"
#include "lv2/options.h" #include "lv2/options.h"
#include "lv2/parameters.h" #include "lv2/parameters.h"
#include "lv2/ui.h" #include "lv2/ui.h"
@@ -35,6 +36,15 @@


START_NAMESPACE_DISTRHO START_NAMESPACE_DISTRHO


typedef struct _LV2_Atom_MidiEvent {
LV2_Atom atom; /**< Atom header. */
uint8_t data[3]; /**< MIDI data (body). */
} LV2_Atom_MidiEvent;

#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT
static const sendNoteFunc sendNoteCallback = nullptr;
#endif

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


class UiLv2 class UiLv2
@@ -51,6 +61,7 @@ public:
fController(controller), fController(controller),
fWriteFunction(writeFunc), fWriteFunction(writeFunc),
fEventTransferURID(uridMap->map(uridMap->handle, LV2_ATOM__eventTransfer)), fEventTransferURID(uridMap->map(uridMap->handle, LV2_ATOM__eventTransfer)),
fMidiEventURID(uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent)),
fKeyValueURID(uridMap->map(uridMap->handle, DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")), fKeyValueURID(uridMap->map(uridMap->handle, DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")),
fWinIdWasNull(winId == 0) fWinIdWasNull(winId == 0)
{ {
@@ -256,9 +267,28 @@ protected:
fWriteFunction(fController, eventInPortIndex, atomSize, fEventTransferURID, atom); fWriteFunction(fController, eventInPortIndex, atomSize, fEventTransferURID, atom);
} }


void sendNote(const uint8_t /*channel*/, const uint8_t /*note*/, const uint8_t /*velocity*/)
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{ {
DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,);

if (channel > 0xF)
return;

const uint32_t eventInPortIndex(DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS);

LV2_Atom_MidiEvent atomMidiEvent;
atomMidiEvent.atom.size = 3;
atomMidiEvent.atom.type = fMidiEventURID;

atomMidiEvent.data[0] = channel + (velocity != 0 ? 0x90 : 0x80);
atomMidiEvent.data[1] = note;
atomMidiEvent.data[2] = velocity;

// send to DSP side
fWriteFunction(fController, eventInPortIndex, sizeof(LV2_Atom_MidiEvent), fEventTransferURID, &atomMidiEvent);
} }
#endif


void setSize(const uint width, const uint height) void setSize(const uint width, const uint height)
{ {
@@ -282,6 +312,7 @@ private:


// Need to save this // Need to save this
const LV2_URID fEventTransferURID; const LV2_URID fEventTransferURID;
const LV2_URID fMidiEventURID;
const LV2_URID fKeyValueURID; const LV2_URID fKeyValueURID;


// using ui:showInterface if true // using ui:showInterface if true
@@ -307,10 +338,12 @@ private:
uiPtr->setState(key, value); uiPtr->setState(key, value);
} }


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


static void setSizeCallback(void* ptr, uint width, uint height) static void setSizeCallback(void* ptr, uint width, uint height)
{ {


dpf/distrho/src/vestige/aeffectx.h → dpf/distrho/src/vestige/vestige.h View File

@@ -1,9 +1,18 @@
/* /*
* aeffectx.h - simple header to allow VeSTige compilation and eventually work
* IMPORTANT: The author of DPF has no connection with the
* author of the VeSTige VST-compatibility header, has had no
* involvement in its creation.
*
* The VeSTige header is included in this package in the good-faith
* belief that it has been cleanly and legally reverse engineered
* without reference to the official VST SDK and without its
* developer(s) having agreed to the VST SDK license agreement.
*/

/*
* simple header to allow VeSTige compilation and eventually work
* *
* Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net> * Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public * modify it under the terms of the GNU General Public
@@ -22,8 +31,8 @@
* *
*/ */
#include <stdint.h> #include <stdint.h>
#ifndef _AEFFECTX_H
#define _AEFFECTX_H
#ifndef _VESTIGE_H
#define _VESTIGE_H


#define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \ #define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \
( ( (int) b ) << 16 ) | \ ( ( (int) b ) << 16 ) | \
@@ -87,11 +96,11 @@
#define effFlagsIsSynth (1 << 8) // currently unused #define effFlagsIsSynth (1 << 8) // currently unused


#define effOpen 0 #define effOpen 0
#define effClose 1 // currently unused
#define effSetProgram 2 // currently unused
#define effGetProgram 3 // currently unused
#define effGetProgramName 5 // currently unused
#define effGetParamName 8 // currently unused
#define effClose 1
#define effSetProgram 2
#define effGetProgram 3
#define effGetProgramName 5
#define effGetParamName 8
#define effSetSampleRate 10 #define effSetSampleRate 10
#define effSetBlockSize 11 #define effSetBlockSize 11
#define effMainsChanged 12 #define effMainsChanged 12
@@ -101,22 +110,42 @@
#define effEditIdle 19 #define effEditIdle 19
#define effEditTop 20 #define effEditTop 20
#define effProcessEvents 25 #define effProcessEvents 25
#define effGetPlugCategory 35
#define effGetEffectName 45 #define effGetEffectName 45
#define effGetVendorString 47 #define effGetVendorString 47
#define effGetProductString 48 #define effGetProductString 48
#define effGetVendorVersion 49 #define effGetVendorVersion 49
#define effCanDo 51 // currently unused
/* from http://asseca.com/vst-24-specs/efGetParameterProperties.html */
#define effCanDo 51
#define effIdle 53
#define effGetParameterProperties 56 #define effGetParameterProperties 56
#define effGetVstVersion 58 // currently unused
#define effGetVstVersion 58
#define effShellGetNextPlugin 70
#define effStartProcess 71
#define effStopProcess 72

#define effBeginSetProgram 67
#define effEndSetProgram 68

#ifdef WORDS_BIGENDIAN
// "VstP"
#define kEffectMagic 0x50747356
#else
// "PtsV"
#define kEffectMagic 0x56737450
#endif


#define kEffectMagic (CCONST( 'V', 's', 't', 'P' ))
#define kVstLangEnglish 1 #define kVstLangEnglish 1
#define kVstMidiType 1 #define kVstMidiType 1


struct RemoteVstPlugin; struct RemoteVstPlugin;


#define kVstTransportChanged 1
#define kVstTransportPlaying (1 << 1) #define kVstTransportPlaying (1 << 1)
#define kVstTransportCycleActive (1 << 2)
#define kVstTransportRecording (1 << 3)

#define kVstAutomationWriting (1 << 6)
#define kVstAutomationReading (1 << 7)


#define kVstNanosValid (1 << 8) #define kVstNanosValid (1 << 8)
#define kVstPpqPosValid (1 << 9) #define kVstPpqPosValid (1 << 9)
@@ -174,26 +203,57 @@ struct _VstEvents
VstEvent * events[2]; VstEvent * events[2];
}; };


enum Vestige2StringConstants
{
VestigeMaxNameLen = 64,
VestigeMaxLabelLen = 64,
VestigeMaxShortLabelLen = 8,
VestigeMaxCategLabelLen = 24,
VestigeMaxFileNameLen = 100
};


enum VstPlugCategory
{
kPlugCategUnknown = 0,
kPlugCategEffect,
kPlugCategSynth,
kPlugCategAnalysis,
kPlugCategMastering,
kPlugCategSpacializer,
kPlugCategRoomFx,
kPlugSurroundFx,
kPlugCategRestoration,
kPlugCategOfflineProcess,
kPlugCategShell,
kPlugCategGenerator,
kPlugCategMaxCount
};

typedef struct _VstEvents VstEvents; typedef struct _VstEvents VstEvents;


/* this struct taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */
struct _VstParameterProperties struct _VstParameterProperties
{ {
float stepFloat;
float smallStepFloat;
float largeStepFloat;
char label[64];
int32_t flags;
int32_t minInteger;
int32_t maxInteger;
int32_t stepInteger;
int32_t largeStepInteger;
char shortLabel[8];
float stepFloat; /* float step */
float smallStepFloat; /* small float step */
float largeStepFloat; /* large float step */
char label[VestigeMaxLabelLen]; /* parameter label */
int32_t flags; /* @see VstParameterFlags */
int32_t minInteger; /* integer minimum */
int32_t maxInteger; /* integer maximum */
int32_t stepInteger; /* integer step */
int32_t largeStepInteger; /* large integer step */
char shortLabel[VestigeMaxShortLabelLen]; /* short label, recommended: 6 + delimiter */
int16_t displayIndex; /* index where this parameter should be displayed (starting with 0) */
int16_t category; /* 0: no category, else group index + 1 */
int16_t numParametersInCategory; /* number of parameters in category */
int16_t reserved; /* zero */
char categoryLabel[VestigeMaxCategLabelLen]; /* category label, e.g. "Osc 1" */
char future[16]; /* reserved for future use */
}; };


typedef struct _VstParameterProperties VstParameterProperties; typedef struct _VstParameterProperties VstParameterProperties;


/* this enum taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */
enum VstParameterFlags enum VstParameterFlags
{ {
kVstParameterIsSwitch = 1 << 0, /* parameter is a switch (on/off) */ kVstParameterIsSwitch = 1 << 0, /* parameter is a switch (on/off) */
@@ -231,18 +291,19 @@ struct _AEffect
// Fill somewhere 28-2b // Fill somewhere 28-2b
void *ptr1; void *ptr1;
void *ptr2; void *ptr2;
// Zeroes 2c-2f 30-33 34-37 38-3b
char empty3[4 + 4 + 4];
int initialDelay;
// Zeroes 30-33 34-37 38-3b
char empty2[4 + 4];
// 1.0f 3c-3f // 1.0f 3c-3f
float unkown_float; float unkown_float;
// An object? pointer 40-43 // An object? pointer 40-43
void *ptr3;
void *object;
// Zeroes 44-47 // Zeroes 44-47
void *user; void *user;
// Id 48-4b // Id 48-4b
int32_t uniqueID; int32_t uniqueID;
// Don't know 4c-4f
char unknown1[4];
// plugin version 4c-4f
int32_t version;
// processReplacing 50-53 // processReplacing 50-53
void (* processReplacing) (struct _AEffect *, float **, float **, int); void (* processReplacing) (struct _AEffect *, float **, float **, int);
}; };

+ 6
- 6
dpf/utils/generate-ttl.sh View File

@@ -9,13 +9,13 @@ else
exit exit
fi fi


PWD=`dirname $0`
PWD="$(dirname "$0")"


if [ -f $PWD/lv2_ttl_generator.exe ]; then
GEN=$PWD/lv2_ttl_generator.exe
if [ -f "$PWD/lv2_ttl_generator.exe" ]; then
GEN="$PWD/lv2_ttl_generator.exe"
EXT=dll EXT=dll
else else
GEN=$PWD/lv2_ttl_generator
GEN="$PWD/lv2_ttl_generator"
if [ -d /Library/Audio ]; then if [ -d /Library/Audio ]; then
EXT=dylib EXT=dylib
else else
@@ -27,7 +27,7 @@ FOLDERS=`find . -type d -name \*.lv2`


for i in $FOLDERS; do for i in $FOLDERS; do
cd $i cd $i
FILE=`ls *.$EXT | sort | head -n 1`
$GEN ./$FILE
FILE="$(ls *.$EXT | sort | head -n 1)"
"$GEN" "./$FILE"
cd .. cd ..
done done

Loading…
Cancel
Save