Browse Source

Implement MIDI output for all formats

Needs testing, I did none :)
pull/61/head
falkTX 6 years ago
parent
commit
ffdfaa6174
8 changed files with 239 additions and 65 deletions
  1. +0
    -3
      distrho/DistrhoPlugin.hpp
  2. +22
    -2
      distrho/src/DistrhoPluginInternal.hpp
  3. +55
    -11
      distrho/src/DistrhoPluginJack.cpp
  4. +8
    -4
      distrho/src/DistrhoPluginLADSPA+DSSI.cpp
  5. +88
    -22
      distrho/src/DistrhoPluginLV2.cpp
  6. +2
    -2
      distrho/src/DistrhoPluginLV2export.cpp
  7. +47
    -9
      distrho/src/DistrhoPluginVST.cpp
  8. +17
    -12
      distrho/src/DistrhoUIInternal.hpp

+ 0
- 3
distrho/DistrhoPlugin.hpp View File

@@ -691,9 +691,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


+ 22
- 2
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,12 @@ struct Plugin::PrivateData {
} }
#endif #endif
} }

void writeMidiCallback(const MidiEvent& midiEvent)
{
if (writeMidiCallbackFunc != nullptr)
writeMidiCallbackFunc(callbacksPtr, midiEvent);
}
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -157,7 +174,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 +208,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()


+ 55
- 11
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)
{ {
@@ -201,6 +209,11 @@ public:
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 +343,10 @@ 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);
#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 +425,10 @@ protected:
#else #else
fPlugin.run(audioIns, audioOuts, nframes); fPlugin.run(audioIns, audioOuts, nframes);
#endif #endif

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
fPortMidiOutBuffer = nullptr;
#endif
} }


void jackShutdown() void jackShutdown()
@@ -440,6 +461,18 @@ 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

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


private: private:
@@ -457,6 +490,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 +512,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


+ 8
- 4
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
@@ -531,7 +535,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;




+ 88
- 22
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
@@ -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
@@ -610,17 +612,11 @@ public:
updateParameterOutputs(); updateParameterOutputs();


#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 +641,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 +650,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 +882,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 +918,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;
@@ -1016,6 +1050,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
}; };


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


+ 2
- 2
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;




+ 47
- 9
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
@@ -68,6 +68,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)
@@ -351,7 +357,8 @@ class PluginVst
{ {
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));
@@ -453,15 +460,15 @@ 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) if (hints & kParameterIsInteger)
{ {
DISTRHO_NAMESPACE::snprintf_iparam((char*)ptr, (int32_t)std::round(value), 24); DISTRHO_NAMESPACE::snprintf_iparam((char*)ptr, (int32_t)std::round(value), 24);
@@ -881,13 +888,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];


@@ -937,6 +944,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
@@ -1002,7 +1040,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)
{ {


+ 17
- 12
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;


Loading…
Cancel
Save