Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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: 7 additions & 1 deletion Makefile.plugins.mk
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ DGL_FLAGS += -DDGL_EXTERNAL
HAVE_DGL = true
endif

ifneq ($(UI_TYPE),none)
ifneq ($(WINDOWS),true)
VST_LIBS += -lpthread
endif
endif

DGL_LIBS += $(DGL_SYSTEM_LIBS)

ifneq ($(HAVE_DGL),true)
Expand Down Expand Up @@ -234,7 +240,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) $(VST_LIBS) $(SHARED) -o $@

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

Expand Down
127 changes: 122 additions & 5 deletions distrho/src/DistrhoPluginVST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@

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

#ifndef __cdecl
Expand Down Expand Up @@ -155,13 +158,116 @@ class ParameterCheckHelper
#endif
};

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

class MidiSendFromEditorHelper
{
public:
MidiSendFromEditorHelper()
: fMidiStorage(nullptr),
fMidiCount(0),
fWriterIndex(0)
{
fMidiStorage = new ShortMessage[kMidiStorageCapacity];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why isn't this part of the class variables but allocated on the constructor?
do we pointer swap at some point? if not, there is no reason to allocate things twice

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on purpose, to avoid a large block in the middle of object layout.
I'm pretty sure it's a recommended practice regarding caching, especially that this buffer is not going to be touched very regularly.

}

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

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

void sendEditorMidi(const uint8_t midiData[3])
{
MutexLocker locker(fMutex);
Comment thread
jpcima marked this conversation as resolved.
Outdated

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 receiveEditorMidi(MidiEvent *events, uint32_t eventCount)
{
if (fMidiCount == 0)
return eventCount;

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

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

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 +424,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 +448,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 +491,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 +652,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 +1131,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
32 changes: 32 additions & 0 deletions examples/SendNote/DistrhoPluginInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED
#define DISTRHO_PLUGIN_INFO_H_INCLUDED

#define DISTRHO_PLUGIN_BRAND "DISTRHO"
#define DISTRHO_PLUGIN_NAME "SendNote"
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/SendNote"

#define DISTRHO_PLUGIN_HAS_UI 1
#define DISTRHO_PLUGIN_HAS_EMBED_UI 1
#define DISTRHO_PLUGIN_IS_RT_SAFE 1
#define DISTRHO_PLUGIN_NUM_INPUTS 0
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0

#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED
46 changes: 46 additions & 0 deletions examples/SendNote/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/make -f
# Makefile for DISTRHO Plugins #
# ---------------------------- #
# Created by falkTX
#

# --------------------------------------------------------------
# Project name, used for binaries

NAME = d_sendNote

# --------------------------------------------------------------
# Files to build

FILES_DSP = \
SendNoteExamplePlugin.cpp


FILES_UI = \
SendNoteExampleUI.cpp

# --------------------------------------------------------------
# Do some magic

include ../../Makefile.plugins.mk

# --------------------------------------------------------------
# Enable all possible plugin types

ifeq ($(HAVE_JACK),true)
ifeq ($(HAVE_OPENGL),true)
TARGETS += jack
endif
endif

ifeq ($(HAVE_OPENGL),true)
TARGETS += lv2_sep
else
TARGETS += lv2_dsp
endif

TARGETS += vst

all: $(TARGETS)

# --------------------------------------------------------------
6 changes: 6 additions & 0 deletions examples/SendNote/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# SendNote example

This example will show how to send MIDI notes in DPF based UIs.<br/>

The UI presents a row of MIDI keys which transmit note events to a synthesizer.

Loading