| @@ -691,9 +691,6 @@ public: | |||
| Write a MIDI output event.@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(). | |||
| @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; | |||
| #endif | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * 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 double d_lastSampleRate; | |||
| // ----------------------------------------------------------------------- | |||
| // DSP callbacks | |||
| typedef bool (*writeMidiFunc) (void* ptr, const MidiEvent& midiEvent); | |||
| // ----------------------------------------------------------------------- | |||
| // Plugin private data | |||
| @@ -65,6 +70,10 @@ struct Plugin::PrivateData { | |||
| TimePosition timePosition; | |||
| #endif | |||
| // Callbacks | |||
| void* callbacksPtr; | |||
| writeMidiFunc writeMidiCallbackFunc; | |||
| uint32_t bufferSize; | |||
| double sampleRate; | |||
| @@ -88,6 +97,8 @@ struct Plugin::PrivateData { | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| latency(0), | |||
| #endif | |||
| callbacksPtr(nullptr), | |||
| writeMidiCallbackFunc(nullptr), | |||
| bufferSize(d_lastBufferSize), | |||
| sampleRate(d_lastSampleRate) | |||
| { | |||
| @@ -149,6 +160,12 @@ struct Plugin::PrivateData { | |||
| } | |||
| #endif | |||
| } | |||
| void writeMidiCallback(const MidiEvent& midiEvent) | |||
| { | |||
| if (writeMidiCallbackFunc != nullptr) | |||
| writeMidiCallbackFunc(callbacksPtr, midiEvent); | |||
| } | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -157,7 +174,7 @@ struct Plugin::PrivateData { | |||
| class PluginExporter | |||
| { | |||
| public: | |||
| PluginExporter() | |||
| PluginExporter(void* const callbacksPtr, const writeMidiFunc writeMidiCall) | |||
| : fPlugin(createPlugin()), | |||
| fData((fPlugin != nullptr) ? fPlugin->pData : nullptr), | |||
| fIsActive(false) | |||
| @@ -191,6 +208,9 @@ public: | |||
| for (uint32_t i=0, count=fData->stateCount; i < count; ++i) | |||
| fPlugin->initState(i, fData->stateKeys[i], fData->stateDefValues[i]); | |||
| #endif | |||
| fData->callbacksPtr = callbacksPtr; | |||
| fData->writeMidiCallbackFunc = writeMidiCall; | |||
| } | |||
| ~PluginExporter() | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * 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 | |||
| static const setStateFunc setStateCallback = nullptr; | |||
| #endif | |||
| #if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| static const writeMidiFunc writeMidiCallback = nullptr; | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| @@ -91,7 +94,7 @@ class PluginJack | |||
| { | |||
| public: | |||
| PluginJack(jack_client_t* const client) | |||
| : fPlugin(), | |||
| : fPlugin(this, writeMidiCallback), | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, fPlugin.getInstancePointer()), | |||
| #endif | |||
| @@ -119,6 +122,11 @@ public: | |||
| 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 (fPlugin.getProgramCount() > 0) | |||
| { | |||
| @@ -201,6 +209,11 @@ public: | |||
| if (fClient == nullptr) | |||
| return; | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| jack_port_unregister(fClient, fPortMidiOut); | |||
| fPortMidiOut = nullptr; | |||
| #endif | |||
| jack_port_unregister(fClient, fPortEventsIn); | |||
| fPortEventsIn = nullptr; | |||
| @@ -330,6 +343,10 @@ protected: | |||
| 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 DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| @@ -408,6 +425,10 @@ protected: | |||
| #else | |||
| fPlugin.run(audioIns, audioOuts, nframes); | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| fPortMidiOutBuffer = nullptr; | |||
| #endif | |||
| } | |||
| void jackShutdown() | |||
| @@ -440,6 +461,18 @@ protected: | |||
| } | |||
| #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: | |||
| @@ -457,6 +490,10 @@ private: | |||
| jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; | |||
| #endif | |||
| jack_port_t* fPortEventsIn; | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| jack_port_t* fPortMidiOut; | |||
| void* fPortMidiOutBuffer; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| TimePosition fTimePosition; | |||
| #endif | |||
| @@ -475,51 +512,58 @@ private: | |||
| // ------------------------------------------------------------------- | |||
| // Callbacks | |||
| #define uiPtr ((PluginJack*)ptr) | |||
| #define thisPtr ((PluginJack*)ptr) | |||
| static int jackBufferSizeCallback(jack_nframes_t nframes, void* ptr) | |||
| { | |||
| uiPtr->jackBufferSize(nframes); | |||
| thisPtr->jackBufferSize(nframes); | |||
| return 0; | |||
| } | |||
| static int jackSampleRateCallback(jack_nframes_t nframes, void* ptr) | |||
| { | |||
| uiPtr->jackSampleRate(nframes); | |||
| thisPtr->jackSampleRate(nframes); | |||
| return 0; | |||
| } | |||
| static int jackProcessCallback(jack_nframes_t nframes, void* ptr) | |||
| { | |||
| uiPtr->jackProcess(nframes); | |||
| thisPtr->jackProcess(nframes); | |||
| return 0; | |||
| } | |||
| static void jackShutdownCallback(void* ptr) | |||
| { | |||
| uiPtr->jackShutdown(); | |||
| thisPtr->jackShutdown(); | |||
| } | |||
| static void setParameterValueCallback(void* ptr, uint32_t index, float value) | |||
| { | |||
| uiPtr->setParameterValue(index, value); | |||
| thisPtr->setParameterValue(index, value); | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| static void setStateCallback(void* ptr, const char* key, const char* value) | |||
| { | |||
| uiPtr->setState(key, value); | |||
| thisPtr->setState(key, value); | |||
| } | |||
| #endif | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| 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 | |||
| #undef uiPtr | |||
| #undef thisPtr | |||
| }; | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||
| @@ -22,9 +22,12 @@ | |||
| #ifdef DISTRHO_PLUGIN_TARGET_DSSI | |||
| # include "dssi/dssi.h" | |||
| # if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| # error DSSI does not support MIDI output | |||
| # endif | |||
| #else | |||
| # 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 | |||
| # endif | |||
| # if DISTRHO_PLUGIN_WANT_STATE | |||
| @@ -44,7 +47,8 @@ class PluginLadspaDssi | |||
| { | |||
| public: | |||
| PluginLadspaDssi() | |||
| : fPortControls(nullptr), | |||
| : fPlugin(nullptr, nullptr), | |||
| fPortControls(nullptr), | |||
| fLastControlValues(nullptr) | |||
| { | |||
| #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |||
| @@ -531,7 +535,7 @@ public: | |||
| // Create dummy plugin to get data from | |||
| d_lastBufferSize = 512; | |||
| d_lastSampleRate = 44100.0; | |||
| PluginExporter plugin; | |||
| PluginExporter plugin(nullptr, nullptr); | |||
| d_lastBufferSize = 0; | |||
| d_lastSampleRate = 0.0; | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * 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; | |||
| #if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| static const writeMidiFunc writeMidiCallback = nullptr; | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| class PluginLv2 | |||
| { | |||
| public: | |||
| 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 | |||
| fRunCount(0), | |||
| #endif | |||
| @@ -107,9 +112,6 @@ public: | |||
| #if DISTRHO_LV2_USE_EVENTS_IN | |||
| fPortEventsIn = nullptr; | |||
| #endif | |||
| #if DISTRHO_LV2_USE_EVENTS_OUT | |||
| fPortEventsOut = nullptr; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| fPortLatency = nullptr; | |||
| #endif | |||
| @@ -226,7 +228,7 @@ public: | |||
| #if DISTRHO_LV2_USE_EVENTS_OUT | |||
| if (port == index++) | |||
| { | |||
| fPortEventsOut = (LV2_Atom_Sequence*)dataLocation; | |||
| fEventsOutData.port = (LV2_Atom_Sequence*)dataLocation; | |||
| return; | |||
| } | |||
| #endif | |||
| @@ -610,17 +612,11 @@ public: | |||
| updateParameterOutputs(); | |||
| #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; | |||
| 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) | |||
| { | |||
| @@ -645,6 +641,7 @@ public: | |||
| break; | |||
| // reserve msg space | |||
| // FIXME create a large enough buffer beforehand | |||
| char msgBuf[msgSize]; | |||
| std::memset(msgBuf, 0, msgSize); | |||
| @@ -653,21 +650,23 @@ public: | |||
| std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()); | |||
| // 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->body.type = fURIDs.distrhoState; | |||
| aev->body.size = msgSize; | |||
| 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; | |||
| break; | |||
| } | |||
| } | |||
| #endif | |||
| #if DISTRHO_LV2_USE_EVENTS_OUT | |||
| fEventsOutData.endRun(); | |||
| #endif | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -883,9 +882,6 @@ private: | |||
| #if DISTRHO_LV2_USE_EVENTS_IN | |||
| LV2_Atom_Sequence* fPortEventsIn; | |||
| #endif | |||
| #if DISTRHO_LV2_USE_EVENTS_OUT | |||
| LV2_Atom_Sequence* fPortEventsOut; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| float* fPortLatency; | |||
| #endif | |||
| @@ -922,6 +918,44 @@ private: | |||
| } fLastPositionData; | |||
| #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 | |||
| struct URIDs { | |||
| LV2_URID atomBlank; | |||
| @@ -1016,6 +1050,38 @@ private: | |||
| *fPortLatency = fPlugin.getLatency(); | |||
| #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 | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * 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 | |||
| d_lastBufferSize = 512; | |||
| d_lastSampleRate = 44100.0; | |||
| PluginExporter plugin; | |||
| PluginExporter plugin(nullptr, nullptr); | |||
| d_lastBufferSize = 0; | |||
| d_lastSampleRate = 0.0; | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * 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; | |||
| 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) | |||
| @@ -351,7 +357,8 @@ class PluginVst | |||
| { | |||
| public: | |||
| PluginVst(const audioMasterCallback audioMaster, AEffect* const effect) | |||
| : fAudioMaster(audioMaster), | |||
| : fPlugin(this, writeMidiCallback), | |||
| fAudioMaster(audioMaster), | |||
| fEffect(effect) | |||
| { | |||
| std::memset(fProgramName, 0, sizeof(char)*(32+1)); | |||
| @@ -453,15 +460,15 @@ public: | |||
| { | |||
| const uint32_t hints = fPlugin.getParameterHints(index); | |||
| float value = fPlugin.getParameterValue(index); | |||
| if (hints & kParameterIsBoolean) | |||
| { | |||
| const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); | |||
| const float midRange = ranges.min + (ranges.max - ranges.min) / 2.0f; | |||
| value = value > midRange ? ranges.max : ranges.min; | |||
| } | |||
| if (hints & kParameterIsInteger) | |||
| { | |||
| DISTRHO_NAMESPACE::snprintf_iparam((char*)ptr, (int32_t)std::round(value), 24); | |||
| @@ -881,13 +888,13 @@ public: | |||
| friend class UIVst; | |||
| private: | |||
| // Plugin | |||
| PluginExporter fPlugin; | |||
| // VST stuff | |||
| const audioMasterCallback fAudioMaster; | |||
| AEffect* const fEffect; | |||
| // Plugin | |||
| PluginExporter fPlugin; | |||
| // Temporary data | |||
| char fProgramName[32+1]; | |||
| @@ -937,6 +944,37 @@ private: | |||
| } | |||
| #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 | |||
| // ------------------------------------------------------------------- | |||
| // 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 | |||
| static PluginExporter plugin; | |||
| static PluginExporter plugin(nullptr, nullptr); | |||
| if (doInternalInit) | |||
| { | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * 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 | |||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||
| @@ -61,12 +61,12 @@ struct UI::PrivateData { | |||
| #endif | |||
| // Callbacks | |||
| void* callbacksPtr; | |||
| editParamFunc editParamCallbackFunc; | |||
| setParamFunc setParamCallbackFunc; | |||
| setStateFunc setStateCallbackFunc; | |||
| sendNoteFunc sendNoteCallbackFunc; | |||
| setSizeFunc setSizeCallbackFunc; | |||
| void* ptr; | |||
| PrivateData() noexcept | |||
| : sampleRate(d_lastUiSampleRate), | |||
| @@ -74,12 +74,12 @@ struct UI::PrivateData { | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| dspPtr(d_lastUiDspPtr), | |||
| #endif | |||
| callbacksPtr(nullptr), | |||
| editParamCallbackFunc(nullptr), | |||
| setParamCallbackFunc(nullptr), | |||
| setStateCallbackFunc(nullptr), | |||
| sendNoteCallbackFunc(nullptr), | |||
| setSizeCallbackFunc(nullptr), | |||
| ptr(nullptr) | |||
| setSizeCallbackFunc(nullptr) | |||
| { | |||
| DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate)); | |||
| @@ -103,31 +103,31 @@ struct UI::PrivateData { | |||
| void editParamCallback(const uint32_t rindex, const bool started) | |||
| { | |||
| if (editParamCallbackFunc != nullptr) | |||
| editParamCallbackFunc(ptr, rindex, started); | |||
| editParamCallbackFunc(callbacksPtr, rindex, started); | |||
| } | |||
| void setParamCallback(const uint32_t rindex, const float value) | |||
| { | |||
| if (setParamCallbackFunc != nullptr) | |||
| setParamCallbackFunc(ptr, rindex, value); | |||
| setParamCallbackFunc(callbacksPtr, rindex, value); | |||
| } | |||
| void setStateCallback(const char* const key, const char* const value) | |||
| { | |||
| 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) | |||
| { | |||
| if (sendNoteCallbackFunc != nullptr) | |||
| sendNoteCallbackFunc(ptr, channel, note, velocity); | |||
| sendNoteCallbackFunc(callbacksPtr, channel, note, velocity); | |||
| } | |||
| void setSizeCallback(const uint width, const uint height) | |||
| { | |||
| 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 | |||
| { | |||
| 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, | |||
| const char* const bundlePath = nullptr) | |||
| #ifdef HAVE_DGL | |||
| @@ -238,7 +243,7 @@ public: | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||
| fData->ptr = ptr; | |||
| fData->callbacksPtr = callbacksPtr; | |||
| fData->editParamCallbackFunc = editParamCall; | |||
| fData->setParamCallbackFunc = setParamCall; | |||
| fData->setStateCallbackFunc = setStateCall; | |||