Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ examples: dgl
$(MAKE) all -C examples/Meters
$(MAKE) all -C examples/MidiThrough
$(MAKE) all -C examples/Parameters
$(MAKE) all -C examples/SendNote
$(MAKE) all -C examples/States

ifeq ($(HAVE_CAIRO),true)
Expand Down Expand Up @@ -58,6 +59,7 @@ clean:
$(MAKE) clean -C examples/Meters
$(MAKE) clean -C examples/MidiThrough
$(MAKE) clean -C examples/Parameters
$(MAKE) clean -C examples/SendNote
$(MAKE) clean -C examples/States
$(MAKE) clean -C utils/lv2-ttl-generator
ifneq ($(MACOS_OR_WINDOWS),true)
Expand Down
8 changes: 6 additions & 2 deletions Makefile.plugins.mk
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ DGL_FLAGS += -DDGL_EXTERNAL
HAVE_DGL = true
endif

ifneq ($(UI_TYPE),none)
THREAD_LIBS += -lpthread
endif

DGL_LIBS += $(DGL_SYSTEM_LIBS)

ifneq ($(HAVE_DGL),true)
Expand Down Expand Up @@ -171,7 +175,7 @@ $(jack): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o
endif
-@mkdir -p $(shell dirname $@)
@echo "Creating JACK standalone for $(NAME)"
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(shell $(PKG_CONFIG) --libs jack) -o $@
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(THREAD_LIBS) $(shell $(PKG_CONFIG) --libs jack) -o $@

# ---------------------------------------------------------------------------------------------------------------------
# LADSPA
Expand Down Expand Up @@ -234,7 +238,7 @@ $(vst): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_VST.cpp.o
endif
-@mkdir -p $(shell dirname $@)
@echo "Creating VST plugin for $(NAME)"
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) -o $@
$(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(THREAD_LIBS) $(SHARED) -o $@

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

Expand Down
100 changes: 100 additions & 0 deletions distrho/src/DistrhoPluginInternal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

#include "../DistrhoPlugin.hpp"

#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT
# include "extra/Mutex.hpp"
#endif

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
Expand Down Expand Up @@ -672,6 +676,102 @@ class PluginExporter
DISTRHO_PREVENT_HEAP_ALLOCATION
};

#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT
// -----------------------------------------------------------------------
// Midi queue class

/**
Single-consumer, single-producer FIFO queue of short MIDI messages, intended
for UI-to-DSP messaging in case of VST or similar plugin formats.
The access is guarded by mutex, using try-lock on the receiving side.
*/
class SimpleMidiQueue
{
public:
SimpleMidiQueue()
: fMidiStorage(nullptr),
fMidiCount(0),
fWriterIndex(0)
{
fMidiStorage = new ShortMessage[kMidiStorageCapacity];
}

virtual ~SimpleMidiQueue()
{
delete[] fMidiStorage;
fMidiStorage = nullptr;
}

void clear()
{
const MutexLocker locker(fMutex);
fMidiCount = 0;
}

void send(const uint8_t midiData[3])
{
const MutexLocker locker(fMutex);

uint32_t count = fMidiCount;
if (count == kMidiStorageCapacity)
return;

uint32_t index = fWriterIndex;
ShortMessage &msg = fMidiStorage[index];
std::memcpy(msg.data, midiData, 3);

fMidiCount = count + 1;
fWriterIndex = (index + 1) % kMidiStorageCapacity;
}

uint32_t receive(MidiEvent* events, uint32_t eventCount)
{
if (fMidiCount == 0)
return eventCount;

const MutexTryLocker locker(fMutex);
if (locker.wasNotLocked())
return eventCount;

// preserve the ordering of frame times according to messages before us
uint32_t frame = 0;
if (eventCount > 0)
frame = events[eventCount - 1].frame;

uint32_t countAvailable = fMidiCount;
uint32_t readerIndex = (fWriterIndex + kMidiStorageCapacity - countAvailable) % kMidiStorageCapacity;
for (; countAvailable > 0 && eventCount < kMaxMidiEvents; --countAvailable)
{
ShortMessage msg = fMidiStorage[readerIndex];
MidiEvent &event = events[eventCount++];
event.frame = frame;
event.size = 3;
std::memcpy(event.data, msg.data, sizeof(uint8_t)*3);
readerIndex = (readerIndex + 1) % kMaxMidiEvents;
}

fMidiCount = countAvailable;
return eventCount;
}

protected:
enum
{
kMidiStorageCapacity = 256,
};

struct ShortMessage
{
uint8_t data[3];
};

ShortMessage* fMidiStorage;
volatile uint32_t fMidiCount;
uint32_t fWriterIndex;
Mutex fMutex;
};
#endif

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

END_NAMESPACE_DISTRHO
Expand Down
66 changes: 46 additions & 20 deletions distrho/src/DistrhoPluginJack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class PluginJack
PluginJack(jack_client_t* const client)
: fPlugin(this, writeMidiCallback),
#if DISTRHO_PLUGIN_HAS_UI
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, getDesktopScaleFactor(), fPlugin.getInstancePointer()),
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, sendNoteCallback, setSizeCallback, getDesktopScaleFactor(), fPlugin.getInstancePointer()),
#endif
fClient(client)
{
Expand Down Expand Up @@ -356,12 +356,13 @@ class PluginJack
jack_midi_clear_buffer(fPortMidiOutBuffer);
#endif

if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf))
{
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
uint32_t midiEventCount = 0;
MidiEvent midiEvents[eventCount];
uint32_t midiEventCount = 0;
MidiEvent midiEvents[kMaxMidiEvents];
#endif

if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf))
{
jack_midi_event_t jevent;

for (uint32_t i=0; i < eventCount; ++i)
Expand Down Expand Up @@ -410,27 +411,26 @@ class PluginJack
#endif

#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
MidiEvent& midiEvent(midiEvents[midiEventCount++]);
if (midiEventCount < kMaxMidiEvents)
{
MidiEvent& midiEvent(midiEvents[midiEventCount++]);

midiEvent.frame = jevent.time;
midiEvent.size = jevent.size;
midiEvent.frame = jevent.time;
midiEvent.size = jevent.size;

if (midiEvent.size > MidiEvent::kDataSize)
midiEvent.dataExt = jevent.buffer;
else
std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size);
if (midiEvent.size > MidiEvent::kDataSize)
midiEvent.dataExt = jevent.buffer;
else
std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size);
}
#endif
}

#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount);
#endif
}
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
else
{
fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0);
}
# if DISTRHO_PLUGIN_HAS_UI
midiEventCount = fMidiQueue.receive(midiEvents, midiEventCount);
# endif
fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount);
#else
fPlugin.run(audioIns, audioOuts, nframes);
#endif
Expand Down Expand Up @@ -466,6 +466,17 @@ class PluginJack
#endif

#if DISTRHO_PLUGIN_HAS_UI
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{
uint8_t midiData[3];
midiData[0] = 0x90 | channel;
midiData[1] = note;
midiData[2] = velocity;
fMidiQueue.send(midiData);
}
# endif

void setSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);
Expand Down Expand Up @@ -535,6 +546,9 @@ class PluginJack
# if DISTRHO_PLUGIN_WANT_PROGRAMS
int fProgramChanged;
# endif
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
SimpleMidiQueue fMidiQueue;
# endif
#endif

// -------------------------------------------------------------------
Expand Down Expand Up @@ -578,6 +592,18 @@ class PluginJack
#endif

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

static void setSizeCallback(void* ptr, uint width, uint height)
{
thisPtr->setSize(width, height);
Expand Down
62 changes: 57 additions & 5 deletions distrho/src/DistrhoPluginVST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,54 @@ class ParameterCheckHelper
#endif
};

#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT
// -----------------------------------------------------------------------

class MidiSendFromEditorHelper
{
public:
virtual ~MidiSendFromEditorHelper() {}

void clearEditorMidi()
{
fQueue.clear();
}

void sendEditorMidi(const uint8_t midiData[3])
{
fQueue.send(midiData);
}

uint32_t receiveEditorMidi(MidiEvent* events, uint32_t eventCount)
{
return fQueue.receive(events, eventCount);
}

private:
SimpleMidiQueue fQueue;
};
#endif

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

class UIHelperVst : public ParameterCheckHelper
#if DISTRHO_PLUGIN_HAS_UI && DISTRHO_PLUGIN_WANT_MIDI_INPUT
, public MidiSendFromEditorHelper
#endif
{
public:
virtual ~UIHelperVst()
{
}
};

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

class UIVst
{
public:
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, ParameterCheckHelper* const uiHelper, PluginExporter* const plugin, const intptr_t winId, const float scaleFactor)
UIVst(const audioMasterCallback audioMaster, AEffect* const effect, UIHelperVst* const uiHelper, PluginExporter* const plugin, const intptr_t winId, const float scaleFactor)
: fAudioMaster(audioMaster),
fEffect(effect),
fUiHelper(uiHelper),
Expand Down Expand Up @@ -318,8 +359,12 @@ class UIVst

void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{
# if 0 //DISTRHO_PLUGIN_WANT_MIDI_INPUT
// TODO
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
uint8_t midiData[3];
midiData[0] = 0x90 | channel;
midiData[1] = note;
midiData[2] = velocity;
fUiHelper->sendEditorMidi(midiData);
# else
return; // unused
(void)channel;
Expand All @@ -338,7 +383,7 @@ class UIVst
// Vst stuff
const audioMasterCallback fAudioMaster;
AEffect* const fEffect;
ParameterCheckHelper* const fUiHelper;
UIHelperVst* const fUiHelper;
PluginExporter* const fPlugin;

// Plugin UI
Expand Down Expand Up @@ -381,7 +426,7 @@ class UIVst

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

class PluginVst : public ParameterCheckHelper
class PluginVst : public UIHelperVst
{
public:
PluginVst(const audioMasterCallback audioMaster, AEffect* const effect)
Expand Down Expand Up @@ -542,6 +587,10 @@ class PluginVst : public ParameterCheckHelper
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
fMidiEventCount = 0;

#if DISTRHO_PLUGIN_HAS_UI
clearEditorMidi();
#endif

// tell host we want MIDI events
hostCallback(audioMasterWantMidi);
#endif
Expand Down Expand Up @@ -1017,6 +1066,9 @@ class PluginVst : public ParameterCheckHelper
#endif

#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
#if DISTRHO_PLUGIN_HAS_UI
fMidiEventCount = receiveEditorMidi(fMidiEvents, fMidiEventCount);
#endif
fPlugin.run(inputs, outputs, sampleFrames, fMidiEvents, fMidiEventCount);
fMidiEventCount = 0;
#else
Expand Down
Loading