diff --git a/dpf/dgl/ImageWidgets.hpp b/dpf/dgl/ImageWidgets.hpp index aafe196..e5a2142 100644 --- a/dpf/dgl/ImageWidgets.hpp +++ b/dpf/dgl/ImageWidgets.hpp @@ -180,6 +180,7 @@ public: float getValue() const noexcept; void setValue(float value, bool sendCallback = false) noexcept; + void setDefault(float def) noexcept; void setStartPos(const Point& startPos) noexcept; void setStartPos(int x, int y) noexcept; @@ -203,7 +204,9 @@ private: float fMaximum; float fStep; float fValue; + float fValueDef; float fValueTmp; + bool fUsingDefault; bool fDragging; bool fInverted; diff --git a/dpf/dgl/Widget.hpp b/dpf/dgl/Widget.hpp index 74bf183..73d2d6e 100644 --- a/dpf/dgl/Widget.hpp +++ b/dpf/dgl/Widget.hpp @@ -24,9 +24,11 @@ // ----------------------------------------------------------------------- // Forward class names +#ifdef DISTRHO_DEFINES_H_INCLUDED START_NAMESPACE_DISTRHO class UI; END_NAMESPACE_DISTRHO +#endif START_NAMESPACE_DGL @@ -175,6 +177,22 @@ public: oldSize(0, 0) {} }; + /** + Widget position changed event. + @a pos The new absolute position of the widget. + @a oldPos The previous absolute position of the widget. + @see onPositionChanged + */ + struct PositionChangedEvent { + Point pos; + Point oldPos; + + /** Constuctor */ + PositionChangedEvent() noexcept + : pos(0, 0), + oldPos(0, 0) {} + }; + /** Constructor. */ @@ -362,6 +380,11 @@ protected: */ virtual void onResize(const ResizeEvent&); + /** + A function called when the widget's absolute position is changed. + */ + virtual void onPositionChanged(const PositionChangedEvent&); + private: struct PrivateData; PrivateData* const pData; @@ -373,7 +396,9 @@ private: friend class NanoWidget; friend class Window; friend class StandaloneWindow; +#ifdef DISTRHO_DEFINES_H_INCLUDED friend class DISTRHO_NAMESPACE::UI; +#endif DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget) }; diff --git a/dpf/dgl/Window.hpp b/dpf/dgl/Window.hpp index 90d255f..182ae97 100644 --- a/dpf/dgl/Window.hpp +++ b/dpf/dgl/Window.hpp @@ -19,9 +19,11 @@ #include "Geometry.hpp" +#ifdef DISTRHO_DEFINES_H_INCLUDED START_NAMESPACE_DISTRHO class UIExporter; END_NAMESPACE_DISTRHO +#endif START_NAMESPACE_DGL @@ -129,7 +131,9 @@ private: friend class Application; friend class Widget; friend class StandaloneWindow; +#ifdef DISTRHO_DEFINES_H_INCLUDED friend class DISTRHO_NAMESPACE::UIExporter; +#endif virtual void _addWidget(Widget* const widget); virtual void _removeWidget(Widget* const widget); diff --git a/dpf/dgl/src/ImageWidgets.cpp b/dpf/dgl/src/ImageWidgets.cpp index 9b4625c..12f952e 100644 --- a/dpf/dgl/src/ImageWidgets.cpp +++ b/dpf/dgl/src/ImageWidgets.cpp @@ -649,7 +649,9 @@ ImageSlider::ImageSlider(Window& parent, const Image& image) noexcept fMaximum(1.0f), fStep(0.0f), fValue(0.5f), + fValueDef(fValue), fValueTmp(fValue), + fUsingDefault(false), fDragging(false), fInverted(false), fValueIsSet(false), @@ -670,7 +672,9 @@ ImageSlider::ImageSlider(Widget* widget, const Image& image) noexcept fMaximum(1.0f), fStep(0.0f), fValue(0.5f), + fValueDef(fValue), fValueTmp(fValue), + fUsingDefault(false), fDragging(false), fInverted(false), fValueIsSet(false), @@ -743,6 +747,12 @@ void ImageSlider::setInverted(bool inverted) noexcept repaint(); } +void ImageSlider::setDefault(float value) noexcept +{ + fValueDef = value; + fUsingDefault = true; +} + void ImageSlider::setRange(float min, float max) noexcept { fMinimum = min; @@ -830,6 +840,13 @@ bool ImageSlider::onMouse(const MouseEvent& ev) if (! fSliderArea.contains(ev.pos)) return false; + if ((ev.mod & kModifierShift) != 0 && fUsingDefault) + { + setValue(fValueDef, true); + fValueTmp = fValue; + return true; + } + float vper; const int x = ev.pos.getX(); const int y = ev.pos.getY(); diff --git a/dpf/dgl/src/Widget.cpp b/dpf/dgl/src/Widget.cpp index b94d5dd..d200fb4 100644 --- a/dpf/dgl/src/Widget.cpp +++ b/dpf/dgl/src/Widget.cpp @@ -151,20 +151,12 @@ const Point& Widget::getAbsolutePos() const noexcept void Widget::setAbsoluteX(int x) noexcept { - if (pData->absolutePos.getX() == x) - return; - - pData->absolutePos.setX(x); - pData->parent.repaint(); + setAbsolutePos(Point(x, getAbsoluteY())); } void Widget::setAbsoluteY(int y) noexcept { - if (pData->absolutePos.getY() == y) - return; - - pData->absolutePos.setY(y); - pData->parent.repaint(); + setAbsolutePos(Point(getAbsoluteX(), y)); } void Widget::setAbsolutePos(int x, int y) noexcept @@ -177,7 +169,13 @@ void Widget::setAbsolutePos(const Point& pos) noexcept if (pData->absolutePos == pos) return; + PositionChangedEvent ev; + ev.oldPos = pData->absolutePos; + ev.pos = pos; + pData->absolutePos = pos; + onPositionChanged(ev); + pData->parent.repaint(); } @@ -245,6 +243,10 @@ void Widget::onResize(const ResizeEvent&) { } +void Widget::onPositionChanged(const PositionChangedEvent&) +{ +} + // ----------------------------------------------------------------------- END_NAMESPACE_DGL diff --git a/dpf/dgl/src/Window.cpp b/dpf/dgl/src/Window.cpp index c677d11..c03ee75 100644 --- a/dpf/dgl/src/Window.cpp +++ b/dpf/dgl/src/Window.cpp @@ -32,6 +32,8 @@ #if defined(DISTRHO_OS_WINDOWS) # include "pugl/pugl_win.cpp" +# undef max +# undef min #elif defined(DISTRHO_OS_MAC) # define PuglWindow DISTRHO_JOIN_MACRO(PuglWindow, DGL_NAMESPACE) # define PuglOpenGLView DISTRHO_JOIN_MACRO(PuglOpenGLView, DGL_NAMESPACE) @@ -573,7 +575,7 @@ struct Window::PrivateData { #if defined(DISTRHO_OS_WINDOWS) const int winFlags = WS_POPUPWINDOW | WS_CAPTION | (fResizable ? WS_SIZEBOX : 0x0); - RECT wr = { 0, 0, static_cast(width), static_cast(height) }; + RECT wr = { 0, 0, static_cast(width), static_cast(height) }; AdjustWindowRectEx(&wr, fUsingEmbed ? WS_CHILD : winFlags, FALSE, WS_EX_TOPMOST); SetWindowPos(hwnd, 0, 0, 0, wr.right-wr.left, wr.bottom-wr.top, diff --git a/dpf/dgl/src/pugl/pugl_win.cpp b/dpf/dgl/src/pugl/pugl_win.cpp index 67f4058..c87af85 100644 --- a/dpf/dgl/src/pugl/pugl_win.cpp +++ b/dpf/dgl/src/pugl/pugl_win.cpp @@ -111,7 +111,11 @@ puglCreateWindow(PuglView* view, const char* title) static int wc_count = 0; char classNameBuf[256]; std::srand((std::time(NULL))); +#ifdef __WINE__ + std::snprintf(classNameBuf, sizeof(classNameBuf), "%s_%d-%d", title, std::rand(), ++wc_count); +#else _snprintf(classNameBuf, sizeof(classNameBuf), "%s_%d-%d", title, std::rand(), ++wc_count); +#endif classNameBuf[sizeof(classNameBuf)-1] = '\0'; impl->wc.style = CS_OWNDC; diff --git a/dpf/distrho/src/DistrhoPluginCarla.cpp b/dpf/distrho/src/DistrhoPluginCarla.cpp index a0d5bb7..0bbb3a5 100644 --- a/dpf/distrho/src/DistrhoPluginCarla.cpp +++ b/dpf/distrho/src/DistrhoPluginCarla.cpp @@ -26,13 +26,14 @@ START_NAMESPACE_DISTRHO +#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +static const writeMidiFunc writeMidiCallback = nullptr; +#endif + #if DISTRHO_PLUGIN_HAS_UI // ----------------------------------------------------------------------- // Carla UI -#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT -static const writeMidiFunc writeMidiCallback = nullptr; -#endif #if ! DISTRHO_PLUGIN_WANT_STATE static const setStateFunc setStateCallback = nullptr; #endif diff --git a/dpf/distrho/src/DistrhoPluginVST.cpp b/dpf/distrho/src/DistrhoPluginVST.cpp index e787750..4553233 100644 --- a/dpf/distrho/src/DistrhoPluginVST.cpp +++ b/dpf/distrho/src/DistrhoPluginVST.cpp @@ -71,18 +71,21 @@ static const writeMidiFunc writeMidiCallback = nullptr; void strncpy(char* const dst, const char* const src, const size_t size) { - std::strncpy(dst, src, size-1); + DISTRHO_SAFE_ASSERT_RETURN(size > 0,); + std::memcpy(dst, src, std::min(std::strlen(src), size-1)); dst[size-1] = '\0'; } void snprintf_param(char* const dst, const float value, const size_t size) { + DISTRHO_SAFE_ASSERT_RETURN(size > 0,); std::snprintf(dst, size-1, "%f", value); dst[size-1] = '\0'; } void snprintf_iparam(char* const dst, const int32_t value, const size_t size) { + DISTRHO_SAFE_ASSERT_RETURN(size > 0,); std::snprintf(dst, size-1, "%d", value); dst[size-1] = '\0'; } diff --git a/plugins/Kars/DistrhoPluginKars.cpp b/plugins/Kars/DistrhoPluginKars.cpp index 1d2ce61..910a4dc 100644 --- a/plugins/Kars/DistrhoPluginKars.cpp +++ b/plugins/Kars/DistrhoPluginKars.cpp @@ -23,12 +23,14 @@ START_NAMESPACE_DISTRHO DistrhoPluginKars::DistrhoPluginKars() : Plugin(paramCount, 0, 0), // 0 programs, 0 states fSustain(false), + fRelease(0.01), + fVolume(75.0f), fSampleRate(getSampleRate()), fBlockStart(0) { for (int i=kMaxNotes; --i >= 0;) { - fNotes[i].index = i; + fNotes[i].voice = i; fNotes[i].setSampleRate(fSampleRate); } } @@ -38,15 +40,35 @@ DistrhoPluginKars::DistrhoPluginKars() void DistrhoPluginKars::initParameter(uint32_t index, Parameter& parameter) { - if (index != 0) - return; - - parameter.hints = kParameterIsAutomable|kParameterIsBoolean; - parameter.name = "Sustain"; - parameter.symbol = "sustain"; - parameter.ranges.def = 0.0f; - parameter.ranges.min = 0.0f; - parameter.ranges.max = 1.0f; + switch (index) + { + case paramSustain: + parameter.hints = kParameterIsAutomable|kParameterIsBoolean; + parameter.name = "Sustain"; + parameter.symbol = "sustain"; + parameter.ranges.def = 0.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 1.0f; + break; + case paramRelease: + parameter.hints = kParameterIsAutomable; + parameter.name = "Release"; + parameter.symbol = "release"; + parameter.unit = "s"; + parameter.ranges.def = 0.01f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 5.0f; + break; + case paramVolume: + parameter.hints = kParameterIsAutomable; + parameter.name = "Volume"; + parameter.symbol = "volume"; + parameter.unit = "%"; + parameter.ranges.def = 75.0f; + parameter.ranges.min = 0.0f; + parameter.ranges.max = 100.0f; + break; + } } // ----------------------------------------------------------------------- @@ -54,18 +76,30 @@ void DistrhoPluginKars::initParameter(uint32_t index, Parameter& parameter) float DistrhoPluginKars::getParameterValue(uint32_t index) const { - if (index != 0) - return 0.0f; + switch (index) + { + case paramSustain: return fSustain ? 1.0f : 0.0f; + case paramRelease: return fRelease; + case paramVolume: return fVolume; + } - return fSustain ? 1.0f : 0.0f; + return 0.0f; } void DistrhoPluginKars::setParameterValue(uint32_t index, float value) { - if (index != 0) - return; - - fSustain = value > 0.5f; + switch (index) + { + case paramSustain: + fSustain = value > 0.5f; + break; + case paramRelease: + fRelease = value; + break; + case paramVolume: + fVolume = value; + break; + } } // ----------------------------------------------------------------------- @@ -83,19 +117,112 @@ void DistrhoPluginKars::activate() } } +/** + Handy class to help keep audio buffer in sync with incoming MIDI events. + To use it, create a local variable (on the stack) and call nextEvent() until it returns false. + @code + for (AudioMidiSyncHelper amsh(outputs, frames, midiEvents, midiEventCount); amsh.nextEvent();) + { + float* const outL = amsh.outputs[0]; + float* const outR = amsh.outputs[1]; + + for (uint32_t i=0; i= midiEvents[curEventIndex].frame; ++curEventIndex) + for (uint32_t i=0; i MidiEvent::kDataSize) + if (amsh.midiEvents[i].size > MidiEvent::kDataSize) continue; - const uint8_t* data = midiEvents[curEventIndex].data; + const uint8_t* data = amsh.midiEvents[i].data; const uint8_t status = data[0] & 0xF0; switch (status) @@ -106,7 +233,7 @@ void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, con DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes if (velo > 0) { - fNotes[note].on = fBlockStart + midiEvents[curEventIndex].frame; + fNotes[note].on = fBlockStart + amsh.midiEvents[i].frame; fNotes[note].off = kNoteNull; fNotes[note].velocity = velo; break; @@ -115,35 +242,26 @@ void DistrhoPluginKars::run(const float**, float** outputs, uint32_t frames, con case 0x80: note = data[1]; DISTRHO_SAFE_ASSERT_BREAK(note < 128); // kMaxNotes - fNotes[note].off = fBlockStart + midiEvents[curEventIndex].frame; + fNotes[note].off = fBlockStart + amsh.midiEvents[i].frame; break; } } - if (curEventIndex < midiEventCount && midiEvents[curEventIndex].frame < frames) - count = midiEvents[curEventIndex].frame - pos; - else - count = frames - pos; - - std::memset(out+pos, 0, sizeof(float)*count); - //for (uint32_t i=0; i= 0;) { if (fNotes[i].on != kNoteNull) - addSamples(out, i, pos, count); + addSamples(out, i, amsh.frames); } - - pos += count; } fBlockStart += frames; } -void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t offset, uint32_t count) +void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t frames) { - const uint32_t start = fBlockStart + offset; + const uint32_t start = fBlockStart; Note& note(fNotes[voice]); @@ -162,7 +280,7 @@ void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t offset, uint3 float gain, sample; uint32_t index, size; - for (uint32_t i=0, s=start-note.on; i index) { @@ -198,7 +316,7 @@ void DistrhoPluginKars::addSamples(float* out, int voice, uint32_t offset, uint3 note.wavetable[index] = sample/2; } - out[offset+i] += gain * sample; + out[i] += gain * sample * (fVolume / 100.0f); } } diff --git a/plugins/Kars/DistrhoPluginKars.hpp b/plugins/Kars/DistrhoPluginKars.hpp index a2b428f..605cc6d 100644 --- a/plugins/Kars/DistrhoPluginKars.hpp +++ b/plugins/Kars/DistrhoPluginKars.hpp @@ -32,6 +32,8 @@ public: enum Parameters { paramSustain = 0, + paramRelease, + paramVolume, paramCount }; @@ -97,6 +99,8 @@ protected: private: bool fSustain; + float fRelease; + float fVolume; double fSampleRate; uint32_t fBlockStart; @@ -104,16 +108,16 @@ private: uint32_t on; uint32_t off; uint8_t velocity; - float index; - float size; - int sizei; - float* wavetable; + float voice; + float size; + int sizei; + float* wavetable; Note() noexcept : on(kNoteNull), off(kNoteNull), velocity(0), - index(0.0f), + voice(0.0f), size(0.0f), wavetable(nullptr) {} @@ -131,7 +135,7 @@ private: if (wavetable != nullptr) delete[] wavetable; - const float frequency = 440.0f * std::pow(2.0f, (index - 69.0f) / 12.0f); + const float frequency = 440.0f * std::pow(2.0f, (voice - 69.0f) / 12.0f); size = sampleRate / frequency; sizei = int(size)+1; wavetable = new float[sizei]; @@ -140,7 +144,7 @@ private: } fNotes[kMaxNotes]; - void addSamples(float* out, int voice, uint32_t offset, uint32_t count); + void addSamples(float* out, int voice, uint32_t frames); DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoPluginKars) }; diff --git a/plugins/ProM/Makefile b/plugins/ProM/Makefile index d43b437..0f0b24c 100644 --- a/plugins/ProM/Makefile +++ b/plugins/ProM/Makefile @@ -23,6 +23,12 @@ FILES_UI = \ include ../../dpf/Makefile.plugins.mk +# -------------------------------------------------------------- +# Extra flags + +BASE_FLAGS += $(shell pkg-config --cflags libprojectM) +LINK_FLAGS += $(shell pkg-config --libs libprojectM) -lpthread + # -------------------------------------------------------------- # Enable all possible plugin types