DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit 087afb6134acaedf270d10fc482e2df50b7d43e3
parent c8e754caafefa8cb736386cbd0a813856d21f7c8
Author: falkTX <falktx@gmail.com>
Date:   Fri, 22 Aug 2014 02:57:01 +0100

Several fixes to LV2 time code; Misc changes

Diffstat:
Mdistrho/src/DistrhoPluginJack.cpp | 5+----
Mdistrho/src/DistrhoPluginLV2.cpp | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Mdistrho/src/DistrhoPluginVST.cpp | 46++++++++++++++++++++++++++--------------------
Mdistrho/src/DistrhoUILV2.cpp | 54++++++++++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 177 insertions(+), 58 deletions(-)

diff --git a/distrho/src/DistrhoPluginJack.cpp b/distrho/src/DistrhoPluginJack.cpp @@ -203,10 +203,7 @@ protected: if (pos.unique_1 == pos.unique_2) { - if (pos.valid & JackTransportPosition) - fTimePosition.frame = pos.frame; - else - fTimePosition.frame = 0; + fTimePosition.frame = pos.frame; if (pos.valid & JackTransportBBT) { diff --git a/distrho/src/DistrhoPluginLV2.cpp b/distrho/src/DistrhoPluginLV2.cpp @@ -55,12 +55,13 @@ typedef std::map<const d_string,d_string> StringMap; class PluginLv2 { public: - PluginLv2(const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker) + PluginLv2(const double sampleRate, const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker) : fPortControls(nullptr), fLastControlValues(nullptr), + fSampleRate(sampleRate), #if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT # if DISTRHO_PLUGIN_WANT_TIMEPOS - fLastTimeSpeed(0.0f), + fLastTimeSpeed(0.0), # endif fURIDs(uridMap), #endif @@ -256,9 +257,6 @@ public: # if DISTRHO_PLUGIN_HAS_MIDI_INPUT uint32_t midiEventCount = 0; # endif -# if DISTRHO_PLUGIN_WANT_TIMEPOS - bool needsFrameIncrement = true; -# endif LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event) { if (event == nullptr) @@ -287,7 +285,7 @@ public: } # endif # if DISTRHO_PLUGIN_WANT_TIMEPOS - if (event->body.type == fURIDs.atomBlank) + if (event->body.type == fURIDs.atomBlank || event->body.type == fURIDs.atomObject) { const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body); @@ -314,42 +312,71 @@ public: fURIDs.timeSpeed, &speed, nullptr); - // TODO: - // - tick - // - barStartTick - // - ticksPerBeat + // Not possible with LV2: + // -> barStartTick + // -> ticksPerBeat + fTimePosition.bbt.barStartTick = 0.0; + fTimePosition.bbt.ticksPerBeat = 960.0; if (bar != nullptr) { - if (bar->type == fURIDs.atomDouble) - fTimePosition.bbt.bar = ((LV2_Atom_Double*)bar)->body + 1.0f; + /**/ if (bar->type == fURIDs.atomDouble) + fTimePosition.bbt.bar = ((LV2_Atom_Double*)bar)->body + 1.0; else if (bar->type == fURIDs.atomFloat) fTimePosition.bbt.bar = ((LV2_Atom_Float*)bar)->body + 1.0f; else if (bar->type == fURIDs.atomInt) fTimePosition.bbt.bar = ((LV2_Atom_Int*)bar)->body + 1; else if (bar->type == fURIDs.atomLong) fTimePosition.bbt.bar = ((LV2_Atom_Long*)bar)->body + 1; + else + d_stderr("Unknown lv2 bar value type"); } - /*if (barBeat != nullptr && barBeat->type == fURIDs.atomFloat) + if (barBeat != nullptr) { - }*/ - - if (beat != nullptr) + double barBeatValue = 0.0; + + /**/ if (barBeat->type == fURIDs.atomDouble) + barBeatValue = ((LV2_Atom_Double*)barBeat)->body + 1.0; + else if (barBeat->type == fURIDs.atomFloat) + barBeatValue = ((LV2_Atom_Float*)barBeat)->body + 1.0f; + else if (barBeat->type == fURIDs.atomInt) + barBeatValue = ((LV2_Atom_Int*)barBeat)->body + 1; + else if (barBeat->type == fURIDs.atomLong) + barBeatValue = ((LV2_Atom_Long*)barBeat)->body + 1; + else + d_stderr("Unknown lv2 barBeat value type"); + + if (barBeatValue != 0.0) + { + const double beat = std::floor(barBeatValue); + fTimePosition.bbt.beat = beat; + fTimePosition.bbt.tick = (barBeatValue-beat)*fTimePosition.bbt.ticksPerBeat; + } + else + { + fTimePosition.bbt.beat = 0; + fTimePosition.bbt.tick = 0; + } + } + // barBeat includes beat + else if (beat != nullptr) { - if (beat->type == fURIDs.atomDouble) - fTimePosition.bbt.beat = ((LV2_Atom_Double*)beat)->body + 1.0f; + /**/ if (beat->type == fURIDs.atomDouble) + fTimePosition.bbt.beat = ((LV2_Atom_Double*)beat)->body + 1.0; else if (beat->type == fURIDs.atomFloat) fTimePosition.bbt.beat = ((LV2_Atom_Float*)beat)->body + 1.0f; else if (beat->type == fURIDs.atomInt) fTimePosition.bbt.beat = ((LV2_Atom_Int*)beat)->body + 1; else if (beat->type == fURIDs.atomLong) fTimePosition.bbt.beat = ((LV2_Atom_Long*)beat)->body + 1; + else + d_stderr("Unknown lv2 beat value type"); } if (beatUnit != nullptr) { - if (beatUnit->type == fURIDs.atomDouble) + /**/ if (beatUnit->type == fURIDs.atomDouble) fTimePosition.bbt.beatType = ((LV2_Atom_Double*)beatUnit)->body; else if (beatUnit->type == fURIDs.atomFloat) fTimePosition.bbt.beatType = ((LV2_Atom_Float*)beatUnit)->body; @@ -357,11 +384,13 @@ public: fTimePosition.bbt.beatType = ((LV2_Atom_Int*)beatUnit)->body; else if (beatUnit->type == fURIDs.atomLong) fTimePosition.bbt.beatType = ((LV2_Atom_Long*)beatUnit)->body; + else + d_stderr("Unknown lv2 beatUnit value type"); } if (beatsPerBar != nullptr) { - if (beatsPerBar->type == fURIDs.atomDouble) + /**/ if (beatsPerBar->type == fURIDs.atomDouble) fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body; else if (beatsPerBar->type == fURIDs.atomFloat) fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body; @@ -369,11 +398,13 @@ public: fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body; else if (beatsPerBar->type == fURIDs.atomLong) fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body; + else + d_stderr("Unknown lv2 beatsPerBar value type"); } if (beatsPerMinute != nullptr) { - if (beatsPerMinute->type == fURIDs.atomDouble) + /**/ if (beatsPerMinute->type == fURIDs.atomDouble) fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body; else if (beatsPerMinute->type == fURIDs.atomFloat) fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body; @@ -381,23 +412,20 @@ public: fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body; else if (beatsPerMinute->type == fURIDs.atomLong) fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body; + else + d_stderr("Unknown lv2 beatsPerMinute value type"); } if (frame != nullptr && frame->type == fURIDs.atomLong) - { fTimePosition.frame = ((LV2_Atom_Long*)frame)->body; - needsFrameIncrement = false; - } if (speed != nullptr && speed->type == fURIDs.atomFloat) { fLastTimeSpeed = ((LV2_Atom_Float*)speed)->body; - fTimePosition.playing = (fLastTimeSpeed == 1.0f); + fTimePosition.playing = (fLastTimeSpeed == 1.0); } - if ((! fTimePosition.bbt.valid) && beatsPerMinute != nullptr && beatsPerBar != nullptr && beatUnit != nullptr) - fTimePosition.bbt.valid = true; - + fTimePosition.bbt.valid = (beatsPerMinute != nullptr && beatsPerBar != nullptr && beatUnit != nullptr); continue; } # endif @@ -425,8 +453,6 @@ public: #endif # if DISTRHO_PLUGIN_WANT_TIMEPOS - if (needsFrameIncrement && fLastTimeSpeed != 0.0f) - fTimePosition.frame += fLastTimeSpeed*sampleCount; fPlugin.setTimePosition(fTimePosition); # endif @@ -436,6 +462,42 @@ public: fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); #endif +# if DISTRHO_PLUGIN_WANT_TIMEPOS + // update timePos for next callback + if (fLastTimeSpeed != 0.0) + { + const double newFrames = fLastTimeSpeed*sampleCount; + + fTimePosition.frame += newFrames; + + if (fTimePosition.bbt.valid) + { + const double samplesPerBeat = 60.0 / fTimePosition.bbt.beatsPerMinute * fSampleRate; + const double ticksPerSample = fTimePosition.bbt.ticksPerBeat / samplesPerBeat; + + double newTickPos = double(fTimePosition.bbt.tick) + ticksPerSample*newFrames; + double newBeatPos = double(fTimePosition.bbt.beat)-1.0; + double newBarPos = double(fTimePosition.bbt.bar)-1.0; + + for (; newTickPos >= fTimePosition.bbt.ticksPerBeat;) + { + ++newBeatPos; + newTickPos -= fTimePosition.bbt.ticksPerBeat; + } + + for (; newBeatPos >= fTimePosition.bbt.beatsPerBar;) + { + ++newBarPos; + newBeatPos -= fTimePosition.bbt.beatsPerBar; + } + + fTimePosition.bbt.bar = newBarPos+1.0; + fTimePosition.bbt.beat = newBeatPos+1.0; + fTimePosition.bbt.tick = newTickPos; + } + } +# endif + updateParameterOutputs(); #if DISTRHO_LV2_USE_EVENTS_OUT @@ -538,6 +600,7 @@ public: if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Double)) { const double sampleRate(*(const double*)options[i].value); + fSampleRate = sampleRate; fPlugin.setSampleRate(sampleRate); continue; } @@ -697,18 +760,20 @@ private: // Temporary data float* fLastControlValues; + double fSampleRate; #if DISTRHO_PLUGIN_HAS_MIDI_INPUT MidiEvent fMidiEvents[kMaxMidiEvents]; #endif #if DISTRHO_PLUGIN_WANT_TIMEPOS TimePosition fTimePosition; - float fLastTimeSpeed; + double fLastTimeSpeed; #endif // LV2 URIDs #if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT struct URIDs { LV2_URID atomBlank; + LV2_URID atomObject; LV2_URID atomDouble; LV2_URID atomFloat; LV2_URID atomInt; @@ -729,6 +794,7 @@ private: URIDs(const LV2_URID_Map* const uridMap) : atomBlank(uridMap->map(uridMap->handle, LV2_ATOM__Blank)), + atomObject(uridMap->map(uridMap->handle, LV2_ATOM__Object)), atomDouble(uridMap->map(uridMap->handle, LV2_ATOM__Double)), atomFloat(uridMap->map(uridMap->handle, LV2_ATOM__Float)), atomInt(uridMap->map(uridMap->handle, LV2_ATOM__Int)), @@ -862,7 +928,7 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons d_lastSampleRate = sampleRate; - return new PluginLv2(uridMap, worker); + return new PluginLv2(sampleRate, uridMap, worker); } #define instancePtr ((PluginLv2*)instance) diff --git a/distrho/src/DistrhoPluginVST.cpp b/distrho/src/DistrhoPluginVST.cpp @@ -16,8 +16,6 @@ #include "DistrhoPluginInternal.hpp" -#define DISTRHO_PLUGIN_HAS_UI 1 - #if DISTRHO_PLUGIN_HAS_UI # include "DistrhoUIInternal.hpp" #endif @@ -153,6 +151,11 @@ public: return fUI.getHeight(); } + void setSampleRate(const double newSampleRate) + { + fUI.setSampleRate(newSampleRate, true); + } + // ------------------------------------------------------------------- // functions called from the plugin side, may block @@ -279,7 +282,7 @@ public: #endif #if DISTRHO_PLUGIN_HAS_UI - fVstUi = nullptr; + fVstUI = nullptr; fVstRect.top = 0; fVstRect.left = 0; fVstRect.bottom = 0; @@ -363,6 +366,9 @@ public: case effSetSampleRate: fPlugin.setSampleRate(opt, true); + + if (fVstUI != nullptr) + fVstUI->setSampleRate(opt); break; case effSetBlockSize: @@ -385,10 +391,10 @@ public: #if DISTRHO_PLUGIN_HAS_UI case effEditGetRect: - if (fVstUi != nullptr) + if (fVstUI != nullptr) { - fVstRect.right = fVstUi->getWidth(); - fVstRect.bottom = fVstUi->getHeight(); + fVstRect.right = fVstUI->getWidth(); + fVstRect.bottom = fVstUI->getHeight(); } else { @@ -403,7 +409,7 @@ public: return 1; case effEditOpen: - if (fVstUi == nullptr) + if (fVstUI == nullptr) { # if DISTRHO_OS_MAC && ! defined(__LP64__) if ((fEffect->dispatcher(fEffect, effCanDo, 0, 0, (void*)"hasCockosViewAsConfig", 0.0f) & 0xffff0000) != 0xbeef0000) @@ -411,7 +417,7 @@ public: # endif d_lastUiSampleRate = fPlugin.getSampleRate(); - fVstUi = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr); + fVstUI = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr); # if DISTRHO_PLUGIN_WANT_STATE for (StringMap::const_iterator cit=fStateMap.cbegin(), cite=fStateMap.cend(); cit != cite; ++cit) @@ -419,30 +425,30 @@ public: const d_string& key = cit->first; const d_string& value = cit->second; - fVstUi->setStateFromPlugin(key, value); + fVstUI->setStateFromPlugin(key, value); } # endif for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) setParameterValueFromPlugin(i, fPlugin.getParameterValue(i)); - fVstUi->idle(); + fVstUI->idle(); return 1; } break; case effEditClose: - if (fVstUi != nullptr) + if (fVstUI != nullptr) { - delete fVstUi; - fVstUi = nullptr; + delete fVstUI; + fVstUI = nullptr; return 1; } break; //case effIdle: case effEditIdle: - if (fVstUi != nullptr) - fVstUi->idle(); + if (fVstUI != nullptr) + fVstUI->idle(); break; #endif // DISTRHO_PLUGIN_HAS_UI @@ -517,8 +523,8 @@ public: setStateFromUI(key, value); - if (fVstUi != nullptr) - fVstUi->setStateFromPlugin(key, value); + if (fVstUI != nullptr) + fVstUI->setStateFromPlugin(key, value); // get next key key = value+(std::strlen(value)+1); @@ -610,7 +616,7 @@ public: fPlugin.setParameterValue(index, realValue); #if DISTRHO_PLUGIN_HAS_UI - if (fVstUi != nullptr) + if (fVstUI != nullptr) setParameterValueFromPlugin(index, realValue); #endif } @@ -648,7 +654,7 @@ public: #endif #if DISTRHO_PLUGIN_HAS_UI - if (fVstUi == nullptr) + if (fVstUI == nullptr) return; for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) @@ -685,7 +691,7 @@ private: // UI stuff #if DISTRHO_PLUGIN_HAS_UI - UIVst* fVstUi; + UIVst* fVstUI; ERect fVstRect; #endif diff --git a/distrho/src/DistrhoUILV2.cpp b/distrho/src/DistrhoUILV2.cpp @@ -27,6 +27,8 @@ #include "lv2/urid.h" #include "lv2/lv2_programs.h" +// TODO - UI setSampleRate changes + START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------- @@ -147,6 +149,37 @@ public: // ------------------------------------------------------------------- + uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) + { + // currently unused + return LV2_OPTIONS_ERR_UNKNOWN; + } + + uint32_t lv2_set_options(const LV2_Options_Option* const options) + { + for (int i=0; options[i].key != 0; ++i) + { + if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate)) + { + if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Double)) + { + const double sampleRate(*(const double*)options[i].value); + fUI.setSampleRate(sampleRate); + continue; + } + else + { + d_stderr("Host changed sampleRate but with wrong value type"); + continue; + } + } + } + + return LV2_OPTIONS_SUCCESS; + } + + // ------------------------------------------------------------------- + #if DISTRHO_PLUGIN_WANT_PROGRAMS void lv2ui_select_program(const uint32_t bank, const uint32_t program) { @@ -403,6 +436,20 @@ static int lv2ui_hide(LV2UI_Handle ui) return uiPtr->lv2ui_hide(); } +// ----------------------------------------------------------------------- + +static uint32_t lv2_get_options(LV2UI_Handle ui, LV2_Options_Option* options) +{ + return uiPtr->lv2_get_options(options); +} + +static uint32_t lv2_set_options(LV2UI_Handle ui, const LV2_Options_Option* options) +{ + return uiPtr->lv2_set_options(options); +} + +// ----------------------------------------------------------------------- + #if DISTRHO_PLUGIN_WANT_PROGRAMS static void lv2ui_select_program(LV2UI_Handle ui, uint32_t bank, uint32_t program) { @@ -414,9 +461,12 @@ static void lv2ui_select_program(LV2UI_Handle ui, uint32_t bank, uint32_t progra static const void* lv2ui_extension_data(const char* uri) { - static const LV2UI_Idle_Interface uiIdle = { lv2ui_idle }; - static const LV2UI_Show_Interface uiShow = { lv2ui_show, lv2ui_hide }; + static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; + static const LV2UI_Idle_Interface uiIdle = { lv2ui_idle }; + static const LV2UI_Show_Interface uiShow = { lv2ui_show, lv2ui_hide }; + if (std::strcmp(uri, LV2_OPTIONS__interface) == 0) + return &options; if (std::strcmp(uri, LV2_UI__idleInterface) == 0) return &uiIdle; if (std::strcmp(uri, LV2_UI__showInterface) == 0)