| @@ -55,6 +55,8 @@ private: | |||
| void _removeWindow(Window* const window); | |||
| void _oneShown(); | |||
| void _oneHidden(); | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(App) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -17,42 +17,9 @@ | |||
| #ifndef DGL_BASE_HPP_INCLUDED | |||
| #define DGL_BASE_HPP_INCLUDED | |||
| /* Compatibility with non-clang compilers */ | |||
| #ifndef __has_feature | |||
| # define __has_feature(x) 0 | |||
| #endif | |||
| #ifndef __has_extension | |||
| # define __has_extension __has_feature | |||
| #endif | |||
| /* Check OS */ | |||
| #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) | |||
| # define DGL_OS_WINDOWS 1 | |||
| #elif defined(__APPLE__) | |||
| # define DGL_OS_MAC 1 | |||
| #elif defined(__HAIKU__) | |||
| # define DGL_OS_HAIKU 1 | |||
| #elif defined(__linux__) || defined(__linux) | |||
| # define DGL_OS_LINUX 1 | |||
| #endif | |||
| #include "../distrho/extra/d_leakdetector.hpp" | |||
| /* Check for C++11 support */ | |||
| #if defined(HAVE_CPP11_SUPPORT) | |||
| # define PROPER_CPP11_SUPPORT | |||
| #elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) | |||
| # define PROPER_CPP11_SUPPORT | |||
| # if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407) || ! __has_extension(cxx_override_control) | |||
| # define override // gcc4.7+ only | |||
| # define final // gcc4.7+ only | |||
| # endif | |||
| #endif | |||
| #ifndef PROPER_CPP11_SUPPORT | |||
| # define noexcept throw() | |||
| # define override | |||
| # define final | |||
| # define nullptr (0) | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| /* Define namespace */ | |||
| #ifndef DGL_NAMESPACE | |||
| @@ -64,7 +31,7 @@ | |||
| #define USE_NAMESPACE_DGL using namespace DGL_NAMESPACE; | |||
| /* GL includes */ | |||
| #ifdef DGL_OS_MAC | |||
| #ifdef DISTRHO_OS_MAC | |||
| # include <OpenGL/gl.h> | |||
| #else | |||
| # include <GL/gl.h> | |||
| @@ -137,16 +104,6 @@ enum Modifier { | |||
| MODIFIER_SUPER = 1 << 3 /**< Mod4/Command/Windows key */ | |||
| }; | |||
| /* | |||
| * Cross-platform sleep function. | |||
| */ | |||
| void sleep(unsigned int secs); | |||
| /* | |||
| * Cross-platform msleep function. | |||
| */ | |||
| void msleep(unsigned int msecs); | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| @@ -197,6 +197,8 @@ private: | |||
| cairo_t* fContext; | |||
| cairo_surface_t* fSurface; | |||
| GLuint fTextureId; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CairoWidget) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -49,6 +49,8 @@ public: | |||
| private: | |||
| T fX, fY; | |||
| template<typename> friend class Rectangle; | |||
| DISTRHO_PREVENT_HEAP_ALLOCATION | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -78,6 +80,8 @@ public: | |||
| private: | |||
| T fWidth, fHeight; | |||
| template<typename> friend class Rectangle; | |||
| DISTRHO_PREVENT_HEAP_ALLOCATION | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -124,6 +128,8 @@ public: | |||
| private: | |||
| Point<T> fPos; | |||
| Size<T> fSize; | |||
| DISTRHO_PREVENT_HEAP_ALLOCATION | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -59,6 +59,8 @@ private: | |||
| GLenum fFormat; | |||
| GLenum fType; | |||
| GLuint fTextureId; | |||
| DISTRHO_PREVENT_HEAP_ALLOCATION | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -47,6 +47,8 @@ protected: | |||
| private: | |||
| Image fImgBackground; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageAboutWindow) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -55,6 +55,8 @@ private: | |||
| int fCurButton; | |||
| Callback* fCallback; | |||
| DISTRHO_LEAK_DETECTOR(ImageButton) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -83,6 +83,8 @@ private: | |||
| int fImgLayerCount; | |||
| Rectangle<int> fKnobArea; | |||
| GLuint fTextureId; | |||
| DISTRHO_LEAK_DETECTOR(ImageKnob) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -47,6 +47,7 @@ public: | |||
| void setEndPos(const Point<int>& endPos); | |||
| void setEndPos(int x, int y); | |||
| void setInverted(bool inverted); | |||
| void setRange(float min, float max); | |||
| void setStep(float step); | |||
| void setValue(float value, bool sendCallback = false); | |||
| @@ -67,6 +68,7 @@ private: | |||
| float fValueTmp; | |||
| bool fDragging; | |||
| bool fInverted; | |||
| int fStartedX; | |||
| int fStartedY; | |||
| @@ -77,6 +79,8 @@ private: | |||
| Rectangle<int> fSliderArea; | |||
| void _recheckArea(); | |||
| DISTRHO_LEAK_DETECTOR(ImageSlider) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -68,8 +68,10 @@ public: | |||
| } | |||
| protected: | |||
| App fApp; | |||
| App fApp; | |||
| Window fWindow; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(StandaloneWindow) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -97,6 +97,8 @@ private: | |||
| friend class CairoWidget; | |||
| friend class Window; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -77,6 +77,8 @@ private: | |||
| void _addWidget(Widget* const widget); | |||
| void _removeWidget(Widget* const widget); | |||
| void _idle(); | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -68,7 +68,7 @@ void App::exec() | |||
| while (pData->doLoop) | |||
| { | |||
| idle(); | |||
| msleep(10); | |||
| d_msleep(10); | |||
| } | |||
| } | |||
| @@ -31,6 +31,7 @@ ImageSlider::ImageSlider(Window& parent, const Image& image) | |||
| fValue(0.5f), | |||
| fValueTmp(fValue), | |||
| fDragging(false), | |||
| fInverted(false), | |||
| fStartedX(0), | |||
| fStartedY(0), | |||
| fCallback(nullptr) | |||
| @@ -47,6 +48,7 @@ ImageSlider::ImageSlider(Widget* widget, const Image& image) | |||
| fValue(0.5f), | |||
| fValueTmp(fValue), | |||
| fDragging(false), | |||
| fInverted(false), | |||
| fStartedX(0), | |||
| fStartedY(0), | |||
| fCallback(nullptr) | |||
| @@ -63,6 +65,7 @@ ImageSlider::ImageSlider(const ImageSlider& imageSlider) | |||
| fValue(imageSlider.fValue), | |||
| fValueTmp(fValue), | |||
| fDragging(false), | |||
| fInverted(imageSlider.fInverted), | |||
| fStartedX(0), | |||
| fStartedY(0), | |||
| fCallback(imageSlider.fCallback), | |||
| @@ -100,6 +103,15 @@ void ImageSlider::setEndPos(int x, int y) | |||
| setEndPos(Point<int>(x, y)); | |||
| } | |||
| void ImageSlider::setInverted(bool inverted) | |||
| { | |||
| if (fInverted == inverted) | |||
| return; | |||
| fInverted = inverted; | |||
| repaint(); | |||
| } | |||
| void ImageSlider::setRange(float min, float max) | |||
| { | |||
| if (fValue < min) | |||
| @@ -154,24 +166,33 @@ void ImageSlider::onDisplay() | |||
| #if 0 // DEBUG, paints slider area | |||
| glColor3f(0.4f, 0.5f, 0.1f); | |||
| glRecti(fSliderArea.getX(), fSliderArea.getY(), fSliderArea.getX()+fSliderArea.getWidth(), fSliderArea.getY()+fSliderArea.getHeight()); | |||
| glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | |||
| #endif | |||
| float normValue = (fValue - fMinimum) / (fMaximum - fMinimum); | |||
| int x, y; | |||
| if (fStartPos.getX() == fEndPos.getX()) | |||
| if (fStartPos.getY() == fEndPos.getY()) | |||
| { | |||
| x = fStartPos.getX(); | |||
| y = fEndPos.getY() - static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY())); | |||
| } | |||
| else if (fStartPos.getY() == fEndPos.getY()) | |||
| { | |||
| x = fEndPos.getX() - static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX())); | |||
| // horizontal | |||
| if (fInverted) | |||
| x = fEndPos.getX() - static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX())); | |||
| else | |||
| x = fStartPos.getX() + static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX())); | |||
| y = fStartPos.getY(); | |||
| } | |||
| else | |||
| return; | |||
| { | |||
| // vertical | |||
| x = fStartPos.getX(); | |||
| if (fInverted) | |||
| y = fEndPos.getY() - static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY())); | |||
| else | |||
| y = fStartPos.getY() + static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY())); | |||
| } | |||
| fImage.draw(x, y); | |||
| } | |||
| @@ -188,22 +209,23 @@ bool ImageSlider::onMouse(int button, bool press, int x, int y) | |||
| float vper; | |||
| if (fStartPos.getX() == fEndPos.getX()) | |||
| { | |||
| // vertical | |||
| vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight()); | |||
| } | |||
| else if (fStartPos.getY() == fEndPos.getY()) | |||
| if (fStartPos.getY() == fEndPos.getY()) | |||
| { | |||
| // horizontal | |||
| vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth()); | |||
| } | |||
| else | |||
| return false; | |||
| { | |||
| // vertical | |||
| vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight()); | |||
| } | |||
| float value; | |||
| value = fMaximum - vper * (fMaximum - fMinimum); | |||
| if (fInverted) | |||
| value = fMaximum - vper * (fMaximum - fMinimum); | |||
| else | |||
| value = fMinimum + vper * (fMaximum - fMinimum); | |||
| if (value < fMinimum) | |||
| { | |||
| @@ -250,7 +272,7 @@ bool ImageSlider::onMotion(int x, int y) | |||
| if (! fDragging) | |||
| return false; | |||
| bool horizontal = fStartPos.getY() == fEndPos.getY(); | |||
| const bool horizontal = fStartPos.getY() == fEndPos.getY(); | |||
| if ((horizontal && fSliderArea.containsX(x)) || (fSliderArea.containsY(y) && ! horizontal)) | |||
| { | |||
| @@ -269,7 +291,10 @@ bool ImageSlider::onMotion(int x, int y) | |||
| float value; | |||
| value = fMaximum - vper * (fMaximum - fMinimum); | |||
| if (fInverted) | |||
| value = fMaximum - vper * (fMaximum - fMinimum); | |||
| else | |||
| value = fMinimum + vper * (fMaximum - fMinimum); | |||
| if (value < fMinimum) | |||
| { | |||
| @@ -290,13 +315,19 @@ bool ImageSlider::onMotion(int x, int y) | |||
| setValue(value, true); | |||
| } | |||
| else if (y < fSliderArea.getY()) | |||
| else if (horizontal) | |||
| { | |||
| setValue(fMaximum, true); | |||
| if (x < fSliderArea.getX()) | |||
| setValue(fInverted ? fMaximum : fMinimum, true); | |||
| else | |||
| setValue(fInverted ? fMinimum : fMaximum, true); | |||
| } | |||
| else | |||
| { | |||
| setValue(fMinimum, true); | |||
| if (y < fSliderArea.getY()) | |||
| setValue(fInverted ? fMaximum : fMinimum, true); | |||
| else | |||
| setValue(fInverted ? fMinimum : fMaximum, true); | |||
| } | |||
| return true; | |||
| @@ -304,19 +335,21 @@ bool ImageSlider::onMotion(int x, int y) | |||
| void ImageSlider::_recheckArea() | |||
| { | |||
| if (fStartPos.getX() == fEndPos.getX()) | |||
| if (fStartPos.getY() == fEndPos.getY()) | |||
| { | |||
| // horizontal | |||
| fSliderArea = Rectangle<int>(fStartPos.getX(), | |||
| fStartPos.getY(), | |||
| fImage.getWidth(), | |||
| fEndPos.getY() + fImage.getHeight() - fStartPos.getY()); | |||
| fEndPos.getX() + fImage.getWidth() - fStartPos.getX(), | |||
| fImage.getHeight()); | |||
| } | |||
| else if (fStartPos.getY() == fEndPos.getY()) | |||
| else | |||
| { | |||
| // vertical | |||
| fSliderArea = Rectangle<int>(fStartPos.getX(), | |||
| fStartPos.getY(), | |||
| fEndPos.getX() + fImage.getWidth() - fStartPos.getX(), | |||
| fImage.getHeight()); | |||
| fImage.getWidth(), | |||
| fEndPos.getY() + fImage.getHeight() - fStartPos.getY()); | |||
| } | |||
| } | |||
| @@ -24,16 +24,16 @@ | |||
| #include "pugl/pugl.h" | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| # include "pugl/pugl_win.cpp" | |||
| #elif defined(DGL_OS_MAC) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| # include "pugl/pugl_osx_extended.h" | |||
| extern "C" { | |||
| struct PuglViewImpl { | |||
| int width; | |||
| int height; | |||
| };} | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| # include <sys/types.h> | |||
| # include <unistd.h> | |||
| extern "C" { | |||
| @@ -77,12 +77,12 @@ public: | |||
| fVisible(false), | |||
| fResizable(true), | |||
| fUsingEmbed(false), | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| hwnd(0) | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| xDisplay(nullptr), | |||
| xWindow(0) | |||
| #elif defined(DGL_OS_MAC) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| fNeedsIdle(true) | |||
| #else | |||
| _dummy('\0') | |||
| @@ -101,12 +101,12 @@ public: | |||
| fResizable(true), | |||
| fUsingEmbed(false), | |||
| fModal(parent.pData), | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| hwnd(0) | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| xDisplay(nullptr), | |||
| xWindow(0) | |||
| #elif defined(DGL_OS_MAC) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| fNeedsIdle(false) | |||
| #else | |||
| _dummy('\0') | |||
| @@ -115,7 +115,7 @@ public: | |||
| DBG("Creating window with parent..."); DBGF; | |||
| init(); | |||
| #ifdef DGL_OS_LINUX | |||
| #ifdef DISTRHO_OS_LINUX | |||
| const PuglInternals* const parentImpl(parent.pData->fView->impl); | |||
| XSetTransientForHint(xDisplay, xWindow, parentImpl->win); | |||
| @@ -130,12 +130,12 @@ public: | |||
| fVisible(parentId != 0), | |||
| fResizable(parentId == 0), | |||
| fUsingEmbed(parentId != 0), | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| hwnd(0) | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| xDisplay(nullptr), | |||
| xWindow(0) | |||
| #elif defined(DGL_OS_MAC) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| fNeedsIdle(false) | |||
| #else | |||
| _dummy('\0') | |||
| @@ -178,11 +178,11 @@ public: | |||
| puglSetReshapeFunc(fView, onReshapeCallback); | |||
| puglSetCloseFunc(fView, onCloseCallback); | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| PuglInternals* impl = fView->impl; | |||
| hwnd = impl->hwnd; | |||
| assert(hwnd != 0); | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| PuglInternals* impl = fView->impl; | |||
| xDisplay = impl->display; | |||
| xWindow = impl->win; | |||
| @@ -225,9 +225,9 @@ public: | |||
| fView = nullptr; | |||
| } | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| hwnd = 0; | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| xDisplay = nullptr; | |||
| xWindow = 0; | |||
| #endif | |||
| @@ -259,7 +259,7 @@ public: | |||
| for (; fVisible && fModal.enabled;) | |||
| { | |||
| idle(); | |||
| msleep(10); | |||
| d_msleep(10); | |||
| } | |||
| exec_fini(); | |||
| @@ -275,13 +275,13 @@ public: | |||
| void focus() | |||
| { | |||
| DBG("Window focus\n"); | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| SetForegroundWindow(hwnd); | |||
| SetActiveWindow(hwnd); | |||
| SetFocus(hwnd); | |||
| #elif defined(DGL_OS_MAC) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| puglImplFocus(fView); | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| XRaiseWindow(xDisplay, xWindow); | |||
| XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime); | |||
| XFlush(xDisplay); | |||
| @@ -321,16 +321,16 @@ public: | |||
| if (yesNo && fFirstInit) | |||
| setSize(static_cast<unsigned int>(fView->width), static_cast<unsigned int>(fView->height), true); | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| if (yesNo) | |||
| ShowWindow(hwnd, fFirstInit ? SW_SHOWNORMAL : SW_RESTORE); | |||
| else | |||
| ShowWindow(hwnd, SW_HIDE); | |||
| UpdateWindow(hwnd); | |||
| #elif defined(DGL_OS_MAC) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| puglImplSetVisible(fView, yesNo); | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| if (yesNo) | |||
| XMapRaised(xDisplay, xWindow); | |||
| else | |||
| @@ -414,7 +414,7 @@ public: | |||
| DBGp("Window setSize called %s, size %i %i\n", forced ? "(forced)" : "(not forced)", width, height); | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| int winFlags = WS_POPUPWINDOW | WS_CAPTION; | |||
| if (fResizable) | |||
| @@ -427,9 +427,9 @@ public: | |||
| if (! forced) | |||
| UpdateWindow(hwnd); | |||
| #elif defined(DGL_OS_MAC) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| puglImplSetSize(fView, width, height, forced); | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| XResizeWindow(xDisplay, xWindow, width, height); | |||
| if (! fResizable) | |||
| @@ -461,19 +461,19 @@ public: | |||
| { | |||
| DBGp("Window setTitle \"%s\"\n", title); | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| SetWindowTextA(hwnd, title); | |||
| #elif defined(DGL_OS_MAC) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| puglImplSetTitle(fView, title); | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| XStoreName(xDisplay, xWindow, title); | |||
| #endif | |||
| } | |||
| void setTransientWinId(const intptr_t winId) | |||
| { | |||
| #if defined(DGL_OS_LINUX) | |||
| XSetTransientForHint(xDisplay, xWindow, static_cast<::Window>(winId)); | |||
| #if defined(DISTRHO_OS_LINUX) | |||
| XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId)); | |||
| #else | |||
| return; | |||
| // unused | |||
| @@ -519,7 +519,7 @@ public: | |||
| { | |||
| puglProcessEvents(fView); | |||
| #ifdef DGL_OS_MAC | |||
| #ifdef DISTRHO_OS_MAC | |||
| if (fNeedsIdle) | |||
| puglImplIdle(fView); | |||
| #endif | |||
| @@ -544,7 +544,7 @@ public: | |||
| fModal.enabled = true; | |||
| fModal.parent->fModal.childFocus = this; | |||
| #ifdef DGL_OS_WINDOWS | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| // Center this window | |||
| PuglInternals* const parentImpl = fModal.parent->fView->impl; | |||
| @@ -741,12 +741,12 @@ private: | |||
| } | |||
| } fModal; | |||
| #if defined(DGL_OS_WINDOWS) | |||
| #if defined(DISTRHO_OS_WINDOWS) | |||
| HWND hwnd; | |||
| #elif defined(DGL_OS_LINUX) | |||
| #elif defined(DISTRHO_OS_LINUX) | |||
| Display* xDisplay; | |||
| ::Window xWindow; | |||
| #elif defined(DGL_OS_MAC) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| bool fNeedsIdle; | |||
| #else | |||
| char _dummy; | |||
| @@ -17,10 +17,17 @@ | |||
| #ifndef DISTRHO_PLUGIN_HPP_INCLUDED | |||
| #define DISTRHO_PLUGIN_HPP_INCLUDED | |||
| #include "DistrhoUtils.hpp" | |||
| #include "extra/d_string.hpp" | |||
| #include "src/DistrhoPluginChecks.h" | |||
| #include <cmath> | |||
| #ifdef PROPER_CPP11_SUPPORT | |||
| # include <cstdint> | |||
| #else | |||
| # include <stdint.h> | |||
| #endif | |||
| #ifndef M_PI | |||
| # define M_PI 3.14159265358979323846 | |||
| #endif | |||
| @@ -63,34 +70,74 @@ struct ParameterRanges { | |||
| max = 1.0f; | |||
| } | |||
| /*! | |||
| * Fix default value within range. | |||
| */ | |||
| void fixDefault() noexcept | |||
| { | |||
| fixValue(def); | |||
| } | |||
| /*! | |||
| * Fix a value within range. | |||
| */ | |||
| void fixValue(float& value) const noexcept | |||
| { | |||
| if (value < min) | |||
| if (value <= min) | |||
| value = min; | |||
| else if (value > max) | |||
| value = max; | |||
| } | |||
| /*! | |||
| * Get a fixed value within range. | |||
| */ | |||
| float getFixedValue(const float& value) const noexcept | |||
| { | |||
| if (value < min) | |||
| if (value <= min) | |||
| return min; | |||
| else if (value > max) | |||
| if (value >= max) | |||
| return max; | |||
| return value; | |||
| } | |||
| /*! | |||
| * Get a value normalized to 0.0<->1.0. | |||
| */ | |||
| float getNormalizedValue(const float& value) const noexcept | |||
| { | |||
| const float newValue((value - min) / (max - min)); | |||
| const float normValue((value - min) / (max - min)); | |||
| if (normValue <= 0.0f) | |||
| return 0.0f; | |||
| if (normValue >= 1.0f) | |||
| return 1.0f; | |||
| return normValue; | |||
| } | |||
| /*! | |||
| * Get a value normalized to 0.0<->1.0, fixed within range. | |||
| */ | |||
| float getFixedAndNormalizedValue(const float& value) const noexcept | |||
| { | |||
| if (value <= min) | |||
| return 0.0f; | |||
| if (value >= max) | |||
| return 1.0f; | |||
| const float normValue((value - min) / (max - min)); | |||
| if (newValue <= 0.0f) | |||
| if (normValue <= 0.0f) | |||
| return 0.0f; | |||
| if (newValue >= 1.0f) | |||
| if (normValue >= 1.0f) | |||
| return 1.0f; | |||
| return newValue; | |||
| return normValue; | |||
| } | |||
| /*! | |||
| * Get a proper value previously normalized to 0.0<->1.0. | |||
| */ | |||
| float getUnnormalizedValue(const float& value) const noexcept | |||
| { | |||
| return value * (max - min) + min; | |||
| @@ -107,7 +154,7 @@ struct Parameter { | |||
| d_string unit; | |||
| ParameterRanges ranges; | |||
| Parameter() | |||
| Parameter() noexcept | |||
| : hints(0x0) {} | |||
| void clear() noexcept | |||
| @@ -255,6 +302,8 @@ private: | |||
| struct PrivateData; | |||
| PrivateData* const pData; | |||
| friend class PluginExporter; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Plugin) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -17,7 +17,8 @@ | |||
| #ifndef DISTRHO_UI_HPP_INCLUDED | |||
| #define DISTRHO_UI_HPP_INCLUDED | |||
| #include "DistrhoUtils.hpp" | |||
| #include "extra/d_leakdetector.hpp" | |||
| #include "src/DistrhoPluginChecks.h" | |||
| #include "../dgl/Widget.hpp" | |||
| @@ -48,15 +49,15 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| // Host UI State | |||
| void d_uiResize(unsigned int width, unsigned int height); | |||
| void d_uiResize(uint width, uint height); | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Basic Information | |||
| virtual const char* d_getName() const noexcept { return DISTRHO_PLUGIN_NAME; } | |||
| virtual unsigned int d_getWidth() const noexcept = 0; | |||
| virtual unsigned int d_getHeight() const noexcept = 0; | |||
| virtual const char* d_getName() const noexcept { return DISTRHO_PLUGIN_NAME; } | |||
| virtual uint d_getWidth() const noexcept = 0; | |||
| virtual uint d_getHeight() const noexcept = 0; | |||
| // ------------------------------------------------------------------- | |||
| // DSP Callbacks | |||
| @@ -78,7 +79,7 @@ protected: | |||
| // ------------------------------------------------------------------- | |||
| // Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! | |||
| void* d_getPluginInstancePointer(); | |||
| void* d_getPluginInstancePointer() const noexcept; | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| @@ -87,6 +88,8 @@ private: | |||
| struct PrivateData; | |||
| PrivateData* const pData; | |||
| friend class UIExporter; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -19,7 +19,6 @@ | |||
| #include "src/DistrhoDefines.h" | |||
| #include <cassert> | |||
| #include <cstdarg> | |||
| #include <cstdio> | |||
| #include <cstdlib> | |||
| @@ -59,11 +58,14 @@ inline float | |||
| // misc functions | |||
| static inline | |||
| long d_cconst(int a, int b, int c, int d) noexcept | |||
| long d_cconst(const int a, const int b, const int c, const int d) noexcept | |||
| { | |||
| return (a << 24) | (b << 16) | (c << 8) | (d << 0); | |||
| } | |||
| static inline | |||
| void d_pass() noexcept {} | |||
| // ----------------------------------------------------------------------- | |||
| // string print functions | |||
| @@ -71,616 +73,97 @@ long d_cconst(int a, int b, int c, int d) noexcept | |||
| # define d_debug(...) | |||
| #else | |||
| static inline | |||
| void d_debug(const char* const fmt, ...) | |||
| void d_debug(const char* const fmt, ...) noexcept | |||
| { | |||
| va_list args; | |||
| va_start(args, fmt); | |||
| std::fprintf(stdout, "\x1b[30;1m"); | |||
| std::vfprintf(stdout, fmt, args); | |||
| std::fprintf(stdout, "\x1b[0m\n"); | |||
| va_end(args); | |||
| try { | |||
| ::va_list args; | |||
| ::va_start(args, fmt); | |||
| std::fprintf(stdout, "\x1b[30;1m"); | |||
| std::vfprintf(stdout, fmt, args); | |||
| std::fprintf(stdout, "\x1b[0m\n"); | |||
| ::va_end(args); | |||
| } catch (...) {} | |||
| } | |||
| #endif | |||
| static inline | |||
| void d_stdout(const char* const fmt, ...) | |||
| void d_stdout(const char* const fmt, ...) noexcept | |||
| { | |||
| va_list args; | |||
| va_start(args, fmt); | |||
| std::vfprintf(stdout, fmt, args); | |||
| std::fprintf(stdout, "\n"); | |||
| va_end(args); | |||
| try { | |||
| ::va_list args; | |||
| ::va_start(args, fmt); | |||
| std::vfprintf(stdout, fmt, args); | |||
| std::fprintf(stdout, "\n"); | |||
| ::va_end(args); | |||
| } catch (...) {} | |||
| } | |||
| static inline | |||
| void d_stderr(const char* const fmt, ...) | |||
| void d_stderr(const char* const fmt, ...) noexcept | |||
| { | |||
| va_list args; | |||
| va_start(args, fmt); | |||
| std::vfprintf(stderr, fmt, args); | |||
| std::fprintf(stderr, "\n"); | |||
| va_end(args); | |||
| try { | |||
| ::va_list args; | |||
| ::va_start(args, fmt); | |||
| std::vfprintf(stderr, fmt, args); | |||
| std::fprintf(stderr, "\n"); | |||
| ::va_end(args); | |||
| } catch (...) {} | |||
| } | |||
| static inline | |||
| void d_stderr2(const char* const fmt, ...) | |||
| void d_stderr2(const char* const fmt, ...) noexcept | |||
| { | |||
| va_list args; | |||
| va_start(args, fmt); | |||
| std::fprintf(stderr, "\x1b[31m"); | |||
| std::vfprintf(stderr, fmt, args); | |||
| std::fprintf(stderr, "\x1b[0m\n"); | |||
| va_end(args); | |||
| try { | |||
| ::va_list args; | |||
| ::va_start(args, fmt); | |||
| std::fprintf(stderr, "\x1b[31m"); | |||
| std::vfprintf(stderr, fmt, args); | |||
| std::fprintf(stderr, "\x1b[0m\n"); | |||
| ::va_end(args); | |||
| } catch (...) {} | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // d_*sleep | |||
| static inline | |||
| void d_sleep(unsigned int secs) | |||
| void d_safe_assert(const char* const assertion, const char* const file, const int line) noexcept | |||
| { | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| Sleep(secs * 1000); | |||
| #else | |||
| sleep(secs); | |||
| #endif | |||
| d_stderr2("assertion failure: \"%s\" in file %s, line %i", assertion, file, line); | |||
| } | |||
| static inline | |||
| void d_msleep(unsigned int msecs) | |||
| void d_safe_exception(const char* const exception, const char* const file, const int line) noexcept | |||
| { | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| Sleep(msecs); | |||
| #else | |||
| usleep(msecs * 1000); | |||
| #endif | |||
| d_stderr2("exception caught: \"%s\" in file %s, line %i", exception, file, line); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // d_string class | |||
| // d_*sleep | |||
| class d_string | |||
| static inline | |||
| void d_sleep(const uint secs) | |||
| { | |||
| public: | |||
| // ------------------------------------------------------------------- | |||
| // constructors (no explicit conversions allowed) | |||
| /* | |||
| * Empty string. | |||
| */ | |||
| explicit d_string() | |||
| { | |||
| _init(); | |||
| _dup(nullptr); | |||
| } | |||
| /* | |||
| * Simple character. | |||
| */ | |||
| explicit d_string(const char c) | |||
| { | |||
| char ch[2]; | |||
| ch[0] = c; | |||
| ch[1] = '\0'; | |||
| _init(); | |||
| _dup(ch); | |||
| } | |||
| /* | |||
| * Simple char string. | |||
| */ | |||
| explicit d_string(char* const strBuf) | |||
| { | |||
| _init(); | |||
| _dup(strBuf); | |||
| } | |||
| /* | |||
| * Simple const char string. | |||
| */ | |||
| explicit d_string(const char* const strBuf) | |||
| { | |||
| _init(); | |||
| _dup(strBuf); | |||
| } | |||
| /* | |||
| * Integer. | |||
| */ | |||
| explicit d_string(const int value) | |||
| { | |||
| char strBuf[0xff+1]; | |||
| std::memset(strBuf, 0, (0xff+1)*sizeof(char)); | |||
| std::snprintf(strBuf, 0xff, "%d", value); | |||
| _init(); | |||
| _dup(strBuf); | |||
| } | |||
| /* | |||
| * Unsigned integer, possibly in hexadecimal. | |||
| */ | |||
| explicit d_string(const unsigned int value, const bool hexadecimal = false) | |||
| { | |||
| char strBuf[0xff+1]; | |||
| std::memset(strBuf, 0, (0xff+1)*sizeof(char)); | |||
| std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value); | |||
| _init(); | |||
| _dup(strBuf); | |||
| } | |||
| /* | |||
| * Long integer. | |||
| */ | |||
| explicit d_string(const long int value) | |||
| { | |||
| char strBuf[0xff+1]; | |||
| std::memset(strBuf, 0, (0xff+1)*sizeof(char)); | |||
| std::snprintf(strBuf, 0xff, "%ld", value); | |||
| _init(); | |||
| _dup(strBuf); | |||
| } | |||
| /* | |||
| * Long unsigned integer, possibly hexadecimal. | |||
| */ | |||
| explicit d_string(const unsigned long int value, const bool hexadecimal = false) | |||
| { | |||
| char strBuf[0xff+1]; | |||
| std::memset(strBuf, 0, (0xff+1)*sizeof(char)); | |||
| std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value); | |||
| _init(); | |||
| _dup(strBuf); | |||
| } | |||
| /* | |||
| * Single-precision floating point number. | |||
| */ | |||
| explicit d_string(const float value) | |||
| { | |||
| char strBuf[0xff+1]; | |||
| std::memset(strBuf, 0, (0xff+1)*sizeof(char)); | |||
| std::snprintf(strBuf, 0xff, "%f", value); | |||
| _init(); | |||
| _dup(strBuf); | |||
| } | |||
| DISTRHO_SAFE_ASSERT_RETURN(secs > 0,); | |||
| /* | |||
| * Double-precision floating point number. | |||
| */ | |||
| explicit d_string(const double value) | |||
| { | |||
| char strBuf[0xff+1]; | |||
| std::memset(strBuf, 0, (0xff+1)*sizeof(char)); | |||
| std::snprintf(strBuf, 0xff, "%g", value); | |||
| _init(); | |||
| _dup(strBuf); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // non-explicit constructor | |||
| /* | |||
| * Create string from another string. | |||
| */ | |||
| d_string(const d_string& str) | |||
| { | |||
| _init(); | |||
| _dup(str.fBuffer); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // destructor | |||
| /* | |||
| * Destructor. | |||
| */ | |||
| ~d_string() | |||
| { | |||
| assert(fBuffer != nullptr); | |||
| delete[] fBuffer; | |||
| fBuffer = nullptr; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // public methods | |||
| /* | |||
| * Get length of the string. | |||
| */ | |||
| size_t length() const noexcept | |||
| { | |||
| return fBufferLen; | |||
| } | |||
| /* | |||
| * Check if the string is empty. | |||
| */ | |||
| bool isEmpty() const noexcept | |||
| { | |||
| return (fBufferLen == 0); | |||
| } | |||
| /* | |||
| * Check if the string is not empty. | |||
| */ | |||
| bool isNotEmpty() const noexcept | |||
| { | |||
| return (fBufferLen != 0); | |||
| } | |||
| /* | |||
| * Check if the string contains another string, optionally ignoring case. | |||
| */ | |||
| bool contains(const char* const strBuf, const bool ignoreCase = false) const | |||
| { | |||
| if (strBuf == nullptr) | |||
| return false; | |||
| if (ignoreCase) | |||
| { | |||
| #ifdef __USE_GNU | |||
| return (strcasestr(fBuffer, strBuf) != nullptr); | |||
| try { | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| ::Sleep(secs * 1000); | |||
| #else | |||
| d_string tmp1(fBuffer), tmp2(strBuf); | |||
| tmp1.toLower(); | |||
| tmp2.toLower(); | |||
| return (std::strstr((const char*)tmp1, (const char*)tmp2) != nullptr); | |||
| ::sleep(secs); | |||
| #endif | |||
| } | |||
| return (std::strstr(fBuffer, strBuf) != nullptr); | |||
| } | |||
| /* | |||
| * Overloaded function. | |||
| */ | |||
| bool contains(const d_string& str, const bool ignoreCase = false) const | |||
| { | |||
| return contains(str.fBuffer, ignoreCase); | |||
| } | |||
| /* | |||
| * Check if character at 'pos' is a digit. | |||
| */ | |||
| bool isDigit(const size_t pos) const noexcept | |||
| { | |||
| if (pos >= fBufferLen) | |||
| return false; | |||
| return (fBuffer[pos] >= '0' && fBuffer[pos] <= '9'); | |||
| } | |||
| /* | |||
| * Check if the string starts with the character 'c'. | |||
| */ | |||
| bool startsWith(const char c) const | |||
| { | |||
| if (c == '\0') | |||
| return false; | |||
| return (fBufferLen > 0 && fBuffer[0] == c); | |||
| } | |||
| /* | |||
| * Check if the string starts with the string 'prefix'. | |||
| */ | |||
| bool startsWith(const char* const prefix) const | |||
| { | |||
| if (prefix == nullptr) | |||
| return false; | |||
| const size_t prefixLen(std::strlen(prefix)); | |||
| if (fBufferLen < prefixLen) | |||
| return false; | |||
| return (std::strncmp(fBuffer + (fBufferLen-prefixLen), prefix, prefixLen) == 0); | |||
| } | |||
| /* | |||
| * Check if the string ends with the character 'c'. | |||
| */ | |||
| bool endsWith(const char c) const | |||
| { | |||
| if (c == '\0') | |||
| return false; | |||
| return (fBufferLen > 0 && fBuffer[fBufferLen] == c); | |||
| } | |||
| /* | |||
| * Check if the string ends with the string 'suffix'. | |||
| */ | |||
| bool endsWith(const char* const suffix) const | |||
| { | |||
| if (suffix == nullptr) | |||
| return false; | |||
| const size_t suffixLen(std::strlen(suffix)); | |||
| if (fBufferLen < suffixLen) | |||
| return false; | |||
| return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0); | |||
| } | |||
| /* | |||
| * Clear the string. | |||
| */ | |||
| void clear() noexcept | |||
| { | |||
| truncate(0); | |||
| } | |||
| /* | |||
| * Replace all occurrences of character 'before' with character 'after'. | |||
| */ | |||
| void replace(const char before, const char after) noexcept | |||
| { | |||
| if (before == '\0' || after == '\0') | |||
| return; | |||
| for (size_t i=0; i < fBufferLen; ++i) | |||
| { | |||
| if (fBuffer[i] == before) | |||
| fBuffer[i] = after; | |||
| else if (fBuffer[i] == '\0') | |||
| break; | |||
| } | |||
| } | |||
| /* | |||
| * Truncate the string to size 'n'. | |||
| */ | |||
| void truncate(const size_t n) noexcept | |||
| { | |||
| if (n >= fBufferLen) | |||
| return; | |||
| for (size_t i=n; i < fBufferLen; ++i) | |||
| fBuffer[i] = '\0'; | |||
| fBufferLen = n; | |||
| } | |||
| /* | |||
| * Convert all non-basic characters to '_'. | |||
| */ | |||
| void toBasic() noexcept | |||
| { | |||
| for (size_t i=0; i < fBufferLen; ++i) | |||
| { | |||
| if (fBuffer[i] >= '0' && fBuffer[i] <= '9') | |||
| continue; | |||
| if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z') | |||
| continue; | |||
| if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z') | |||
| continue; | |||
| if (fBuffer[i] == '_') | |||
| continue; | |||
| fBuffer[i] = '_'; | |||
| } | |||
| } | |||
| /* | |||
| * Convert to all ascii characters to lowercase. | |||
| */ | |||
| void toLower() noexcept | |||
| { | |||
| static const char kCharDiff('a' - 'A'); | |||
| for (size_t i=0; i < fBufferLen; ++i) | |||
| { | |||
| if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z') | |||
| fBuffer[i] += kCharDiff; | |||
| } | |||
| } | |||
| /* | |||
| * Convert to all ascii characters to uppercase. | |||
| */ | |||
| void toUpper() noexcept | |||
| { | |||
| static const char kCharDiff('a' - 'A'); | |||
| for (size_t i=0; i < fBufferLen; ++i) | |||
| { | |||
| if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z') | |||
| fBuffer[i] -= kCharDiff; | |||
| } | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // public operators | |||
| operator const char*() const noexcept | |||
| { | |||
| return fBuffer; | |||
| } | |||
| char& operator[](const size_t pos) const noexcept | |||
| { | |||
| return fBuffer[pos]; | |||
| } | |||
| bool operator==(const char* const strBuf) const | |||
| { | |||
| return (strBuf != nullptr && std::strcmp(fBuffer, strBuf) == 0); | |||
| } | |||
| bool operator==(const d_string& str) const | |||
| { | |||
| return operator==(str.fBuffer); | |||
| } | |||
| bool operator!=(const char* const strBuf) const | |||
| { | |||
| return !operator==(strBuf); | |||
| } | |||
| bool operator!=(const d_string& str) const | |||
| { | |||
| return !operator==(str.fBuffer); | |||
| } | |||
| d_string& operator=(const char* const strBuf) | |||
| { | |||
| _dup(strBuf); | |||
| return *this; | |||
| } | |||
| d_string& operator=(const d_string& str) | |||
| { | |||
| return operator=(str.fBuffer); | |||
| } | |||
| d_string& operator+=(const char* const strBuf) | |||
| { | |||
| if (strBuf == nullptr) | |||
| return *this; | |||
| const size_t newBufSize = fBufferLen + std::strlen(strBuf) + 1; | |||
| char newBuf[newBufSize]; | |||
| std::strcpy(newBuf, fBuffer); | |||
| std::strcat(newBuf, strBuf); | |||
| _dup(newBuf, newBufSize-1); | |||
| return *this; | |||
| } | |||
| d_string& operator+=(const d_string& str) | |||
| { | |||
| return operator+=(str.fBuffer); | |||
| } | |||
| d_string operator+(const char* const strBuf) | |||
| { | |||
| const size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1; | |||
| char newBuf[newBufSize]; | |||
| std::strcpy(newBuf, fBuffer); | |||
| if (strBuf != nullptr) | |||
| std::strcat(newBuf, strBuf); | |||
| return d_string(newBuf); | |||
| } | |||
| d_string operator+(const d_string& str) | |||
| { | |||
| return operator+(str.fBuffer); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| char* fBuffer; // the actual string buffer | |||
| size_t fBufferLen; // string length | |||
| bool fFirstInit; // true when first initiated | |||
| /* | |||
| * Shared init function. | |||
| * Called on all constructors. | |||
| */ | |||
| void _init() noexcept | |||
| { | |||
| fBuffer = nullptr; | |||
| fBufferLen = 0; | |||
| fFirstInit = true; | |||
| } | |||
| /* | |||
| * Helper function. | |||
| * Called whenever the string needs to be allocated. | |||
| * | |||
| * Notes: | |||
| * - Allocates string only if first initiated, or if 'strBuf' is not null and new string contents are different | |||
| * - If 'strBuf' is null 'size' must be 0 | |||
| */ | |||
| void _dup(const char* const strBuf, const size_t size = 0) | |||
| { | |||
| if (strBuf != nullptr) | |||
| { | |||
| // don't recreate string if contents match | |||
| if (fFirstInit || std::strcmp(fBuffer, strBuf) != 0) | |||
| { | |||
| if (! fFirstInit) | |||
| { | |||
| assert(fBuffer != nullptr); | |||
| delete[] fBuffer; | |||
| } | |||
| fBufferLen = (size > 0) ? size : std::strlen(strBuf); | |||
| fBuffer = new char[fBufferLen+1]; | |||
| std::strcpy(fBuffer, strBuf); | |||
| fBuffer[fBufferLen] = '\0'; | |||
| fFirstInit = false; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| assert(size == 0); | |||
| // don't recreate null string | |||
| if (fFirstInit || fBufferLen != 0) | |||
| { | |||
| if (! fFirstInit) | |||
| { | |||
| assert(fBuffer != nullptr); | |||
| delete[] fBuffer; | |||
| } | |||
| fBufferLen = 0; | |||
| fBuffer = new char[1]; | |||
| fBuffer[0] = '\0'; | |||
| fFirstInit = false; | |||
| } | |||
| } | |||
| } | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| static inline | |||
| d_string operator+(const d_string& strBefore, const char* const strBufAfter) | |||
| { | |||
| const char* const strBufBefore = (const char*)strBefore; | |||
| const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1; | |||
| char newBuf[newBufSize]; | |||
| std::strcpy(newBuf, strBufBefore); | |||
| std::strcat(newBuf, strBufAfter); | |||
| return d_string(newBuf); | |||
| } DISTRHO_SAFE_EXCEPTION("carla_sleep"); | |||
| } | |||
| static inline | |||
| d_string operator+(const char* const strBufBefore, const d_string& strAfter) | |||
| void d_msleep(const uint msecs) | |||
| { | |||
| const char* const strBufAfter = (const char*)strAfter; | |||
| const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1; | |||
| char newBuf[newBufSize]; | |||
| std::strcpy(newBuf, strBufBefore); | |||
| std::strcat(newBuf, strBufAfter); | |||
| DISTRHO_SAFE_ASSERT_RETURN(msecs > 0,); | |||
| return d_string(newBuf); | |||
| try { | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| ::Sleep(msecs); | |||
| #else | |||
| ::usleep(msecs * 1000); | |||
| #endif | |||
| } DISTRHO_SAFE_EXCEPTION("carla_msleep"); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -17,48 +17,6 @@ | |||
| #ifndef DISTRHO_DEFINES_H_INCLUDED | |||
| #define DISTRHO_DEFINES_H_INCLUDED | |||
| #include "DistrhoPluginInfo.h" | |||
| #ifndef DISTRHO_PLUGIN_NAME | |||
| # error DISTRHO_PLUGIN_NAME undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_HAS_UI | |||
| # error DISTRHO_PLUGIN_HAS_UI undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_IS_SYNTH | |||
| # error DISTRHO_PLUGIN_IS_SYNTH undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_NUM_INPUTS | |||
| # error DISTRHO_PLUGIN_NUM_INPUTS undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_NUM_OUTPUTS | |||
| # error DISTRHO_PLUGIN_NUM_OUTPUTS undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_WANT_LATENCY | |||
| # error DISTRHO_PLUGIN_WANT_LATENCY undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| # error DISTRHO_PLUGIN_WANT_PROGRAMS undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_WANT_STATE | |||
| # error DISTRHO_PLUGIN_WANT_STATE undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| # error DISTRHO_PLUGIN_WANT_TIMEPOS undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| # define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 | |||
| #endif | |||
| /* Compatibility with non-clang compilers */ | |||
| #ifndef __has_feature | |||
| # define __has_feature(x) 0 | |||
| @@ -108,6 +66,59 @@ | |||
| # define nullptr (0) | |||
| #endif | |||
| /* Define DISTRHO_SAFE_ASSERT* */ | |||
| #define DISTRHO_SAFE_ASSERT(cond) if (cond) d_pass(); else d_safe_assert(#cond, __FILE__, __LINE__); | |||
| #define DISTRHO_SAFE_ASSERT_BREAK(cond) if (cond) d_pass(); else { d_safe_assert(#cond, __FILE__, __LINE__); break; } | |||
| #define DISTRHO_SAFE_ASSERT_CONTINUE(cond) if (cond) d_pass(); else { d_safe_assert(#cond, __FILE__, __LINE__); continue; } | |||
| #define DISTRHO_SAFE_ASSERT_RETURN(cond, ret) if (cond) d_pass(); else { d_safe_assert(#cond, __FILE__, __LINE__); return ret; } | |||
| /* Define DISTRHO_SAFE_EXCEPTION */ | |||
| #define DISTRHO_SAFE_EXCEPTION(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); } | |||
| #define DISTRHO_SAFE_EXCEPTION_BREAK(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); break; } | |||
| #define DISTRHO_SAFE_EXCEPTION_CONTINUE(msg) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); continue; } | |||
| #define DISTRHO_SAFE_EXCEPTION_RETURN(msg, ret) catch(...) { d_safe_exception(msg, __FILE__, __LINE__); return ret; } | |||
| /* Define DISTRHO_DECLARE_NON_COPY_CLASS */ | |||
| #ifdef DISTRHO_PROPER_CPP11_SUPPORT | |||
| # define DISTRHO_DECLARE_NON_COPY_CLASS(ClassName) \ | |||
| private: \ | |||
| ClassName(ClassName&) = delete; \ | |||
| ClassName(const ClassName&) = delete; \ | |||
| ClassName& operator=(ClassName&) = delete ; \ | |||
| ClassName& operator=(const ClassName&) = delete; | |||
| #else | |||
| # define DISTRHO_DECLARE_NON_COPY_CLASS(ClassName) \ | |||
| private: \ | |||
| ClassName(ClassName&); \ | |||
| ClassName(const ClassName&); \ | |||
| ClassName& operator=(ClassName&); \ | |||
| ClassName& operator=(const ClassName&); | |||
| #endif | |||
| /* Define DISTRHO_DECLARE_NON_COPY_STRUCT */ | |||
| #ifdef DISTRHO_PROPER_CPP11_SUPPORT | |||
| # define DISTRHO_DECLARE_NON_COPY_STRUCT(StructName) \ | |||
| StructName(StructName&) = delete; \ | |||
| StructName(const StructName&) = delete; \ | |||
| StructName& operator=(StructName&) = delete; \ | |||
| StructName& operator=(const StructName&) = delete; | |||
| #else | |||
| # define DISTRHO_DECLARE_NON_COPY_STRUCT(StructName) | |||
| #endif | |||
| /* Define DISTRHO_PREVENT_HEAP_ALLOCATION */ | |||
| #ifdef DISTRHO_PROPER_CPP11_SUPPORT | |||
| # define DISTRHO_PREVENT_HEAP_ALLOCATION \ | |||
| private: \ | |||
| static void* operator new(size_t) = delete; \ | |||
| static void operator delete(void*) = delete; | |||
| #else | |||
| # define DISTRHO_PREVENT_HEAP_ALLOCATION \ | |||
| private: \ | |||
| static void* operator new(size_t); \ | |||
| static void operator delete(void*); | |||
| #endif | |||
| /* Define namespace */ | |||
| #ifndef DISTRHO_NO_NAMESPACE | |||
| # ifndef DISTRHO_NAMESPACE | |||
| @@ -122,6 +133,10 @@ | |||
| # define USE_NAMESPACE_DISTRHO | |||
| #endif | |||
| #define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI" | |||
| /* Useful typedefs */ | |||
| typedef unsigned char uchar; | |||
| typedef unsigned long int ulong; | |||
| typedef unsigned short int ushort; | |||
| typedef unsigned int uint; | |||
| #endif // DISTRHO_DEFINES_H_INCLUDED | |||
| @@ -110,7 +110,7 @@ protected: | |||
| // TODO | |||
| } | |||
| void handleUiResize(const unsigned int width, const unsigned int height) | |||
| void handleUiResize(const uint width, const uint height) | |||
| { | |||
| fUI.setSize(width, height); | |||
| } | |||
| @@ -154,7 +154,7 @@ private: | |||
| } | |||
| #endif | |||
| static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height) | |||
| static void uiResizeCallback(void* ptr, uint width, uint height) | |||
| { | |||
| handlePtr->handleUiResize(width, height); | |||
| } | |||
| @@ -77,11 +77,11 @@ struct Plugin::PrivateData { | |||
| bufferSize(d_lastBufferSize), | |||
| sampleRate(d_lastSampleRate) | |||
| { | |||
| assert(bufferSize != 0); | |||
| assert(sampleRate != 0.0); | |||
| DISTRHO_SAFE_ASSERT(bufferSize != 0); | |||
| DISTRHO_SAFE_ASSERT(sampleRate != 0.0); | |||
| } | |||
| ~PrivateData() | |||
| ~PrivateData() noexcept | |||
| { | |||
| if (parameters != nullptr) | |||
| { | |||
| @@ -117,10 +117,8 @@ public: | |||
| : fPlugin(createPlugin()), | |||
| fData((fPlugin != nullptr) ? fPlugin->pData : nullptr) | |||
| { | |||
| assert(fPlugin != nullptr); | |||
| if (fPlugin == nullptr) | |||
| return; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||
| for (uint32_t i=0, count=fData->parameterCount; i < count; ++i) | |||
| fPlugin->d_initParameter(i, fData->parameters[i]); | |||
| @@ -145,32 +143,44 @@ public: | |||
| const char* getName() const noexcept | |||
| { | |||
| return (fPlugin != nullptr) ? fPlugin->d_getName() : ""; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); | |||
| return fPlugin->d_getName(); | |||
| } | |||
| const char* getLabel() const noexcept | |||
| { | |||
| return (fPlugin != nullptr) ? fPlugin->d_getLabel() : ""; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); | |||
| return fPlugin->d_getLabel(); | |||
| } | |||
| const char* getMaker() const noexcept | |||
| { | |||
| return (fPlugin != nullptr) ? fPlugin->d_getMaker() : ""; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); | |||
| return fPlugin->d_getMaker(); | |||
| } | |||
| const char* getLicense() const noexcept | |||
| { | |||
| return (fPlugin != nullptr) ? fPlugin->d_getLicense() : ""; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, ""); | |||
| return fPlugin->d_getLicense(); | |||
| } | |||
| uint32_t getVersion() const noexcept | |||
| { | |||
| return (fPlugin != nullptr) ? fPlugin->d_getVersion() : 1000; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0); | |||
| return fPlugin->d_getVersion(); | |||
| } | |||
| long getUniqueId() const noexcept | |||
| { | |||
| return (fPlugin != nullptr) ? fPlugin->d_getUniqueId() : 0; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0); | |||
| return fPlugin->d_getUniqueId(); | |||
| } | |||
| void* getInstancePointer() const noexcept | |||
| @@ -183,19 +193,24 @@ public: | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| uint32_t getLatency() const noexcept | |||
| { | |||
| return (fData != nullptr) ? fData->latency : 0; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); | |||
| return fData->latency; | |||
| } | |||
| #endif | |||
| uint32_t getParameterCount() const noexcept | |||
| { | |||
| return (fData != nullptr) ? fData->parameterCount : 0; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); | |||
| return fData->parameterCount; | |||
| } | |||
| uint32_t getParameterHints(const uint32_t index) const noexcept | |||
| { | |||
| assert(index < fData->parameterCount); | |||
| return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].hints : 0x0; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0x0); | |||
| return fData->parameters[index].hints; | |||
| } | |||
| bool isParameterOutput(const uint32_t index) const noexcept | |||
| @@ -205,100 +220,117 @@ public: | |||
| const d_string& getParameterName(const uint32_t index) const noexcept | |||
| { | |||
| assert(index < fData->parameterCount); | |||
| return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].name : sFallbackString; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); | |||
| return fData->parameters[index].name; | |||
| } | |||
| const d_string& getParameterSymbol(const uint32_t index) const noexcept | |||
| { | |||
| assert(index < fData->parameterCount); | |||
| return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].symbol : sFallbackString; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); | |||
| return fData->parameters[index].symbol; | |||
| } | |||
| const d_string& getParameterUnit(const uint32_t index) const noexcept | |||
| { | |||
| assert(index < fData->parameterCount); | |||
| return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].unit : sFallbackString; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackString); | |||
| return fData->parameters[index].unit; | |||
| } | |||
| const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept | |||
| { | |||
| assert(index < fData->parameterCount); | |||
| return (fData != nullptr && index < fData->parameterCount) ? fData->parameters[index].ranges : sFallbackRanges; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackRanges); | |||
| return fData->parameters[index].ranges; | |||
| } | |||
| float getParameterValue(const uint32_t index) const noexcept | |||
| float getParameterValue(const uint32_t index) const | |||
| { | |||
| assert(index < fData->parameterCount); | |||
| return (fPlugin != nullptr && index < fData->parameterCount) ? fPlugin->d_getParameterValue(index) : 0.0f; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr, 0.0f); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, 0.0f); | |||
| return fPlugin->d_getParameterValue(index); | |||
| } | |||
| void setParameterValue(const uint32_t index, const float value) | |||
| { | |||
| assert(index < fData->parameterCount); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount,); | |||
| if (fPlugin != nullptr && index < fData->parameterCount) | |||
| fPlugin->d_setParameterValue(index, value); | |||
| fPlugin->d_setParameterValue(index, value); | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| uint32_t getProgramCount() const noexcept | |||
| { | |||
| return (fData != nullptr) ? fData->programCount : 0; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); | |||
| return fData->programCount; | |||
| } | |||
| const d_string& getProgramName(const uint32_t index) const noexcept | |||
| { | |||
| assert(index < fData->programCount); | |||
| return (fData != nullptr && index < fData->programCount) ? fData->programNames[index] : sFallbackString; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount, sFallbackString); | |||
| return fData->programNames[index]; | |||
| } | |||
| void setProgram(const uint32_t index) | |||
| { | |||
| assert(index < fData->programCount); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->programCount,); | |||
| if (fPlugin != nullptr && index < fData->programCount) | |||
| fPlugin->d_setProgram(index); | |||
| fPlugin->d_setProgram(index); | |||
| } | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| bool wantsStateKey(const char* const key) const noexcept | |||
| uint32_t getStateCount() const noexcept | |||
| { | |||
| for (uint32_t i=0; i < fData->stateCount; ++i) | |||
| { | |||
| if (fData->stateKeys[i] == key) | |||
| return true; | |||
| } | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); | |||
| return false; | |||
| return fData->stateCount; | |||
| } | |||
| uint32_t getStateCount() const noexcept | |||
| const d_string& getStateKey(const uint32_t index) const noexcept | |||
| { | |||
| return fData != nullptr ? fData->stateCount : 0; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); | |||
| return fData->stateKeys[index]; | |||
| } | |||
| const d_string& getStateKey(const uint32_t index) const noexcept | |||
| void setState(const char* const key, const char* const value) | |||
| { | |||
| assert(index < fData->stateCount); | |||
| return (fData != nullptr && index < fData->stateCount) ? fData->stateKeys[index] : sFallbackString; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); | |||
| DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,); | |||
| fPlugin->d_setState(key, value); | |||
| } | |||
| void setState(const char* const key, const char* const value) | |||
| bool wantStateKey(const char* const key) const noexcept | |||
| { | |||
| assert(key != nullptr && value != nullptr); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, false); | |||
| DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false); | |||
| if (fPlugin != nullptr && key != nullptr && value != nullptr) | |||
| fPlugin->d_setState(key, value); | |||
| for (uint32_t i=0; i < fData->stateCount; ++i) | |||
| { | |||
| if (fData->stateKeys[i] == key) | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| void setTimePos(const TimePos& timePos) | |||
| void setTimePos(const TimePos& timePos) noexcept | |||
| { | |||
| if (fData != nullptr) | |||
| std::memcpy(&fData->timePos, &timePos, sizeof(TimePos)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||
| std::memcpy(&fData->timePos, &timePos, sizeof(TimePos)); | |||
| } | |||
| #endif | |||
| @@ -306,44 +338,47 @@ public: | |||
| void activate() | |||
| { | |||
| if (fPlugin != nullptr) | |||
| fPlugin->d_activate(); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| fPlugin->d_activate(); | |||
| } | |||
| void deactivate() | |||
| { | |||
| if (fPlugin != nullptr) | |||
| fPlugin->d_deactivate(); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| fPlugin->d_deactivate(); | |||
| } | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| void run(float** const inputs, float** const outputs, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) | |||
| { | |||
| if (fPlugin != nullptr) | |||
| fPlugin->d_run(inputs, outputs, frames, midiEvents, midiEventCount); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| fPlugin->d_run(inputs, outputs, frames, midiEvents, midiEventCount); | |||
| } | |||
| #else | |||
| void run(float** const inputs, float** const outputs, const uint32_t frames) | |||
| { | |||
| if (fPlugin != nullptr) | |||
| fPlugin->d_run(inputs, outputs, frames); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| fPlugin->d_run(inputs, outputs, frames); | |||
| } | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| void setBufferSize(const uint32_t bufferSize, bool doCallback = false) | |||
| { | |||
| assert(bufferSize >= 2); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| DISTRHO_SAFE_ASSERT(bufferSize >= 2); | |||
| if (fData != nullptr) | |||
| { | |||
| if (doCallback && fData->bufferSize == bufferSize) | |||
| doCallback = false; | |||
| if (fData->bufferSize == bufferSize) | |||
| return; | |||
| fData->bufferSize = bufferSize; | |||
| } | |||
| fData->bufferSize = bufferSize; | |||
| if (fPlugin != nullptr && doCallback) | |||
| if (doCallback) | |||
| { | |||
| fPlugin->d_deactivate(); | |||
| fPlugin->d_bufferSizeChanged(bufferSize); | |||
| @@ -353,17 +388,16 @@ public: | |||
| void setSampleRate(const double sampleRate, bool doCallback = false) | |||
| { | |||
| assert(sampleRate > 0.0); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); | |||
| DISTRHO_SAFE_ASSERT(sampleRate > 0.0); | |||
| if (fData != nullptr) | |||
| { | |||
| if (doCallback && fData->sampleRate == sampleRate) | |||
| doCallback = false; | |||
| if (fData->sampleRate == sampleRate) | |||
| return; | |||
| fData->sampleRate = sampleRate; | |||
| } | |||
| fData->sampleRate = sampleRate; | |||
| if (fPlugin != nullptr && doCallback) | |||
| if (doCallback) | |||
| { | |||
| fPlugin->d_deactivate(); | |||
| fPlugin->d_sampleRateChanged(sampleRate); | |||
| @@ -373,7 +407,7 @@ public: | |||
| private: | |||
| // ------------------------------------------------------------------- | |||
| // private members accessed by DistrhoPlugin class | |||
| // private members accessed by DistrhoPlugin classes | |||
| Plugin* const fPlugin; | |||
| Plugin::PrivateData* const fData; | |||
| @@ -383,6 +417,9 @@ private: | |||
| static const d_string sFallbackString; | |||
| static const ParameterRanges sFallbackRanges; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter) | |||
| DISTRHO_PREVENT_HEAP_ALLOCATION | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -57,9 +57,8 @@ public: | |||
| fPortAudioOuts = nullptr; | |||
| #endif | |||
| if (const uint32_t count = fPlugin.getParameterCount()) | |||
| { | |||
| const uint32_t count(fPlugin.getParameterCount()); | |||
| fPortControls = new LADSPA_Data*[count]; | |||
| fLastControlValues = new LADSPA_Data[count]; | |||
| @@ -69,13 +68,18 @@ public: | |||
| fLastControlValues[i] = fPlugin.getParameterValue(i); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| fPortControls = nullptr; | |||
| fLastControlValues = nullptr; | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| fPortLatency = nullptr; | |||
| #endif | |||
| } | |||
| ~PluginLadspaDssi() | |||
| ~PluginLadspaDssi() noexcept | |||
| { | |||
| if (fPortControls != nullptr) | |||
| { | |||
| @@ -83,7 +87,7 @@ public: | |||
| fPortControls = nullptr; | |||
| } | |||
| if (fLastControlValues) | |||
| if (fLastControlValues != nullptr) | |||
| { | |||
| delete[] fLastControlValues; | |||
| fLastControlValues = nullptr; | |||
| @@ -104,12 +108,12 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| void ladspa_connect_port(const unsigned long port, LADSPA_Data* const dataLocation) | |||
| void ladspa_connect_port(const ulong port, LADSPA_Data* const dataLocation) noexcept | |||
| { | |||
| unsigned long index = 0; | |||
| ulong index = 0; | |||
| #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |||
| for (unsigned long i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||
| for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |||
| { | |||
| if (port == index++) | |||
| { | |||
| @@ -120,7 +124,7 @@ public: | |||
| #endif | |||
| #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||
| for (unsigned long i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||
| for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |||
| { | |||
| if (port == index++) | |||
| { | |||
| @@ -138,7 +142,7 @@ public: | |||
| } | |||
| #endif | |||
| for (unsigned long i=0, count=fPlugin.getParameterCount(); i < count; ++i) | |||
| for (ulong i=0, count=fPlugin.getParameterCount(); i < count; ++i) | |||
| { | |||
| if (port == index++) | |||
| { | |||
| @@ -151,14 +155,14 @@ public: | |||
| // ------------------------------------------------------------------- | |||
| #ifdef DISTRHO_PLUGIN_TARGET_DSSI | |||
| void ladspa_run(const unsigned long sampleCount) | |||
| void ladspa_run(const ulong sampleCount) | |||
| { | |||
| dssi_run_synth(sampleCount, nullptr, 0); | |||
| } | |||
| void dssi_run_synth(const unsigned long sampleCount, snd_seq_event_t* const events, const unsigned long eventCount) | |||
| void dssi_run_synth(const ulong sampleCount, snd_seq_event_t* const events, const ulong eventCount) | |||
| #else | |||
| void ladspa_run(const unsigned long sampleCount) | |||
| void ladspa_run(const ulong sampleCount) | |||
| #endif | |||
| { | |||
| // pre-roll | |||
| @@ -191,6 +195,7 @@ public: | |||
| { | |||
| const snd_seq_event_t& seqEvent(events[i]); | |||
| // FIXME | |||
| if (seqEvent.data.note.channel > 0xF || seqEvent.data.control.channel > 0xF) | |||
| continue; | |||
| @@ -264,8 +269,7 @@ public: | |||
| #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_IS_SYNTH | |||
| return; // unused | |||
| (void)events; | |||
| (void)eventCount; | |||
| (void)events; (void)eventCount; | |||
| #endif | |||
| } | |||
| @@ -286,7 +290,7 @@ public: | |||
| # endif | |||
| # if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| const DSSI_Program_Descriptor* dssi_get_program(const unsigned long index) | |||
| const DSSI_Program_Descriptor* dssi_get_program(const ulong index) | |||
| { | |||
| if (index >= fPlugin.getProgramCount()) | |||
| return nullptr; | |||
| @@ -300,12 +304,11 @@ public: | |||
| return &desc; | |||
| } | |||
| void dssi_select_program(const unsigned long bank, const unsigned long program) | |||
| void dssi_select_program(const ulong bank, const ulong program) | |||
| { | |||
| const unsigned long realProgram(bank * 128 + program); | |||
| const ulong realProgram(bank * 128 + program); | |||
| if (realProgram >= fPlugin.getProgramCount()) | |||
| return; | |||
| DISTRHO_SAFE_ASSERT_RETURN(realProgram < fPlugin.getProgramCount(),); | |||
| fPlugin.setProgram(realProgram); | |||
| @@ -372,7 +375,7 @@ private: | |||
| // ----------------------------------------------------------------------- | |||
| static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, unsigned long sampleRate) | |||
| static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, ulong sampleRate) | |||
| { | |||
| if (d_lastBufferSize == 0) | |||
| d_lastBufferSize = 2048; | |||
| @@ -383,7 +386,7 @@ static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, unsigned long | |||
| #define instancePtr ((PluginLadspaDssi*)instance) | |||
| static void ladspa_connect_port(LADSPA_Handle instance, unsigned long port, LADSPA_Data* dataLocation) | |||
| static void ladspa_connect_port(LADSPA_Handle instance, ulong port, LADSPA_Data* dataLocation) | |||
| { | |||
| instancePtr->ladspa_connect_port(port, dataLocation); | |||
| } | |||
| @@ -393,7 +396,7 @@ static void ladspa_activate(LADSPA_Handle instance) | |||
| instancePtr->ladspa_activate(); | |||
| } | |||
| static void ladspa_run(LADSPA_Handle instance, unsigned long sampleCount) | |||
| static void ladspa_run(LADSPA_Handle instance, ulong sampleCount) | |||
| { | |||
| instancePtr->ladspa_run(sampleCount); | |||
| } | |||
| @@ -417,19 +420,19 @@ static char* dssi_configure(LADSPA_Handle instance, const char* key, const char* | |||
| # endif | |||
| # if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| static const DSSI_Program_Descriptor* dssi_get_program(LADSPA_Handle instance, unsigned long index) | |||
| static const DSSI_Program_Descriptor* dssi_get_program(LADSPA_Handle instance, ulong index) | |||
| { | |||
| return instancePtr->dssi_get_program(index); | |||
| } | |||
| static void dssi_select_program(LADSPA_Handle instance, unsigned long bank, unsigned long program) | |||
| static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong program) | |||
| { | |||
| instancePtr->dssi_select_program(bank, program); | |||
| } | |||
| # endif | |||
| # if DISTRHO_PLUGIN_IS_SYNTH | |||
| static void dssi_run_synth(LADSPA_Handle instance, unsigned long sampleCount, snd_seq_event_t* events, unsigned long eventCount) | |||
| static void dssi_run_synth(LADSPA_Handle instance, ulong sampleCount, snd_seq_event_t* events, ulong eventCount) | |||
| { | |||
| instancePtr->dssi_run_synth(sampleCount, events, eventCount); | |||
| } | |||
| @@ -443,7 +446,7 @@ static void dssi_run_synth(LADSPA_Handle instance, unsigned long sampleCount, sn | |||
| static LADSPA_Descriptor sLadspaDescriptor = { | |||
| /* UniqueID */ 0, | |||
| /* Label */ nullptr, | |||
| /* Properties */ LADSPA_PROPERTY_REALTIME | LADSPA_PROPERTY_HARD_RT_CAPABLE, | |||
| /* Properties */ LADSPA_PROPERTY_HARD_RT_CAPABLE, | |||
| /* Name */ nullptr, | |||
| /* Maker */ nullptr, | |||
| /* Copyright */ nullptr, | |||
| @@ -506,8 +509,8 @@ public: | |||
| d_lastSampleRate = 0.0; | |||
| // Get port count, init | |||
| unsigned long port = 0; | |||
| unsigned long portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.getParameterCount(); | |||
| ulong port = 0; | |||
| ulong portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.getParameterCount(); | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| portCount += 1; | |||
| #endif | |||
| @@ -517,7 +520,7 @@ public: | |||
| // Set ports | |||
| #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |||
| for (unsigned long i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++port) | |||
| for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++port) | |||
| { | |||
| char portName[24] = { '\0' }; | |||
| std::sprintf(portName, "Audio Input %lu", i+1); | |||
| @@ -532,7 +535,7 @@ public: | |||
| #endif | |||
| #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |||
| for (unsigned long i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++port) | |||
| for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++port) | |||
| { | |||
| char portName[24] = { '\0' }; | |||
| std::sprintf(portName, "Audio Output %lu", i+1); | |||
| @@ -556,7 +559,7 @@ public: | |||
| ++port; | |||
| #endif | |||
| for (unsigned long i=0, count=plugin.getParameterCount(); i < count; ++i, ++port) | |||
| for (ulong i=0, count=plugin.getParameterCount(); i < count; ++i, ++port) | |||
| { | |||
| portNames[port] = strdup((const char*)plugin.getParameterName(i)); | |||
| portDescriptors[port] = LADSPA_PORT_CONTROL; | |||
| @@ -665,7 +668,7 @@ public: | |||
| if (sLadspaDescriptor.PortNames != nullptr) | |||
| { | |||
| for (unsigned long i=0; i < sLadspaDescriptor.PortCount; ++i) | |||
| for (ulong i=0; i < sLadspaDescriptor.PortCount; ++i) | |||
| { | |||
| if (sLadspaDescriptor.PortNames[i] != nullptr) | |||
| std::free((void*)sLadspaDescriptor.PortNames[i]); | |||
| @@ -684,7 +687,7 @@ static DescriptorInitializer sDescInit; | |||
| END_NAMESPACE_DISTRHO | |||
| DISTRHO_PLUGIN_EXPORT | |||
| const LADSPA_Descriptor* ladspa_descriptor(unsigned long index) | |||
| const LADSPA_Descriptor* ladspa_descriptor(ulong index) | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| return (index == 0) ? &sLadspaDescriptor : nullptr; | |||
| @@ -692,7 +695,7 @@ const LADSPA_Descriptor* ladspa_descriptor(unsigned long index) | |||
| #ifdef DISTRHO_PLUGIN_TARGET_DSSI | |||
| DISTRHO_PLUGIN_EXPORT | |||
| const DSSI_Descriptor* dssi_descriptor(unsigned long index) | |||
| const DSSI_Descriptor* dssi_descriptor(ulong index) | |||
| { | |||
| USE_NAMESPACE_DISTRHO | |||
| return (index == 0) ? &sDssiDescriptor : nullptr; | |||
| @@ -34,6 +34,7 @@ | |||
| #endif | |||
| #include <map> | |||
| #include <string> | |||
| #ifndef DISTRHO_PLUGIN_URI | |||
| # error DISTRHO_PLUGIN_URI undefined! | |||
| @@ -110,6 +111,20 @@ public: | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| fPortLatency = nullptr; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| if (const uint32_t count = fPlugin.getStateCount()) | |||
| { | |||
| fNeededUiSends = new bool[count]; | |||
| for (uint32_t i=0; i < count; ++i) | |||
| fNeededUiSends[i] = false; | |||
| } | |||
| else | |||
| { | |||
| fNeededUiSends = nullptr; | |||
| } | |||
| #endif | |||
| } | |||
| ~PluginLv2() | |||
| @@ -127,6 +142,12 @@ public: | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| if (fNeededUiSends != nullptr) | |||
| { | |||
| delete[] fNeededUiSends; | |||
| fNeededUiSends = nullptr; | |||
| } | |||
| fStateMap.clear(); | |||
| #endif | |||
| } | |||
| @@ -384,7 +405,18 @@ public: | |||
| if (event->body.type == fURIDs.distrhoState && fWorker != nullptr) | |||
| { | |||
| const void* const data((const void*)(event + 1)); | |||
| fWorker->schedule_work(fWorker->handle, event->body.size, data); | |||
| // check if this is our special message | |||
| if (std::strcmp((const char*)data, "__dpf_ui_data__") == 0) | |||
| { | |||
| for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | |||
| fNeededUiSends[i] = true; | |||
| } | |||
| else | |||
| // no, send to DSP as usual | |||
| { | |||
| fWorker->schedule_work(fWorker->handle, event->body.size, data); | |||
| } | |||
| continue; | |||
| } | |||
| @@ -404,10 +436,76 @@ public: | |||
| fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); | |||
| #endif | |||
| updateParameterOutputs(); | |||
| #if DISTRHO_LV2_USE_EVENTS_OUT | |||
| #endif | |||
| const uint32_t capacity = fPortEventsOut->atom.size; | |||
| updateParameterOutputs(); | |||
| bool needsInit = true; | |||
| uint32_t size, offset = 0; | |||
| LV2_Atom_Event* aev; | |||
| for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) | |||
| { | |||
| if (! fNeededUiSends[i]) | |||
| continue; | |||
| const d_string& key = fPlugin.getStateKey(i); | |||
| for (auto it = fStateMap.begin(), end = fStateMap.end(); it != end; ++it) | |||
| { | |||
| const d_string& curKey = it->first; | |||
| if (curKey != key) | |||
| continue; | |||
| const d_string& value = it->second; | |||
| // TODO - RT safe | |||
| d_stdout("Got msg (from DSP to UI via host):\n%s\n%s", (const char*)key, (const char*)value); | |||
| // join key and value | |||
| std::string tmpStr; | |||
| tmpStr += std::string(key); | |||
| tmpStr += std::string("\0", 1); | |||
| tmpStr += std::string(value); | |||
| // get msg size | |||
| const size_t msgSize(tmpStr.size()+1); | |||
| if (sizeof(LV2_Atom_Event) + msgSize > capacity - offset) | |||
| return; | |||
| if (needsInit) | |||
| { | |||
| fPortEventsOut->atom.size = 0; | |||
| fPortEventsOut->atom.type = fURIDs.atomSequence; | |||
| fPortEventsOut->body.unit = 0; | |||
| fPortEventsOut->body.pad = 0; | |||
| needsInit = false; | |||
| } | |||
| // reserve atom space | |||
| const size_t atomSize(lv2_atom_pad_size(sizeof(LV2_Atom) + msgSize)); | |||
| char atomBuf[atomSize]; | |||
| std::memset(atomBuf, 0, atomSize); | |||
| // put data | |||
| aev = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fPortEventsOut) + offset); | |||
| aev->time.frames = 0; | |||
| aev->body.type = fURIDs.distrhoState; | |||
| aev->body.size = msgSize; | |||
| std::memcpy(LV2_ATOM_BODY(&aev->body), tmpStr.data(), msgSize-1); | |||
| size = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize); | |||
| offset += size; | |||
| fPortEventsOut->atom.size += size; | |||
| fNeededUiSends[i] = false; | |||
| break; | |||
| } | |||
| } | |||
| #endif | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -538,6 +636,13 @@ public: | |||
| continue; | |||
| setState(key, value); | |||
| d_stdout("Got state msg:\n%s\n%s", (const char*)key, value); | |||
| #if DISTRHO_LV2_USE_EVENTS_OUT | |||
| // signal msg needed for UI | |||
| fNeededUiSends[i] = true; | |||
| #endif | |||
| } | |||
| return LV2_STATE_SUCCESS; | |||
| @@ -610,6 +715,7 @@ private: | |||
| LV2_URID atomFloat; | |||
| LV2_URID atomInt; | |||
| LV2_URID atomLong; | |||
| LV2_URID atomSequence; | |||
| LV2_URID atomString; | |||
| LV2_URID distrhoState; | |||
| LV2_URID midiEvent; | |||
| @@ -629,6 +735,7 @@ private: | |||
| atomFloat(uridMap->map(uridMap->handle, LV2_ATOM__Float)), | |||
| atomInt(uridMap->map(uridMap->handle, LV2_ATOM__Int)), | |||
| atomLong(uridMap->map(uridMap->handle, LV2_ATOM__Long)), | |||
| atomSequence(uridMap->map(uridMap->handle, LV2_ATOM__Sequence)), | |||
| atomString(uridMap->map(uridMap->handle, LV2_ATOM__String)), | |||
| distrhoState(uridMap->map(uridMap->handle, "urn:distrho:keyValueState")), | |||
| midiEvent(uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent)), | |||
| @@ -650,13 +757,14 @@ private: | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| StringMap fStateMap; | |||
| bool* fNeededUiSends; | |||
| void setState(const char* const key, const char* const newValue) | |||
| { | |||
| fPlugin.setState(key, newValue); | |||
| // check if we want to save this key | |||
| if (! fPlugin.wantsStateKey(key)) | |||
| if (! fPlugin.wantStateKey(key)) | |||
| return; | |||
| // check if key already exists | |||
| @@ -22,6 +22,7 @@ | |||
| #include "lv2/instance-access.h" | |||
| #include "lv2/midi.h" | |||
| #include "lv2/options.h" | |||
| #include "lv2/resize-port.h" | |||
| #include "lv2/state.h" | |||
| #include "lv2/time.h" | |||
| #include "lv2/ui.h" | |||
| @@ -37,6 +38,10 @@ | |||
| # error DISTRHO_PLUGIN_URI undefined! | |||
| #endif | |||
| #ifndef DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE | |||
| # define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048 | |||
| #endif | |||
| #define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) | |||
| #define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI) | |||
| @@ -130,6 +135,7 @@ void lv2_generate_ttl(const char* const basename) | |||
| pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n"; | |||
| pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n"; | |||
| pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; | |||
| pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n"; | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; | |||
| #endif | |||
| @@ -226,6 +232,7 @@ void lv2_generate_ttl(const char* const basename) | |||
| pluginString += " lv2:index " + d_string(portIndex) + " ;\n"; | |||
| pluginString += " lv2:name \"Events Input\" ;\n"; | |||
| pluginString += " lv2:symbol \"lv2_events_in\" ;\n"; | |||
| pluginString += " rsz:minimumSize " + d_string(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n"; | |||
| pluginString += " atom:bufferType atom:Sequence ;\n"; | |||
| # if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI) | |||
| pluginString += " atom:supports <" LV2_ATOM__String "> ;\n"; | |||
| @@ -247,6 +254,7 @@ void lv2_generate_ttl(const char* const basename) | |||
| pluginString += " lv2:index " + d_string(portIndex) + " ;\n"; | |||
| pluginString += " lv2:name \"Events Output\" ;\n"; | |||
| pluginString += " lv2:symbol \"lv2_events_out\" ;\n"; | |||
| pluginString += " rsz:minimumSize " + d_string(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n"; | |||
| pluginString += " atom:bufferType atom:Sequence ;\n"; | |||
| pluginString += " atom:supports <" LV2_ATOM__String "> ;\n"; | |||
| pluginString += " ] ;\n\n"; | |||
| @@ -215,7 +215,7 @@ protected: | |||
| #endif | |||
| } | |||
| void uiResize(const unsigned int width, const unsigned int height) | |||
| void uiResize(const uint width, const uint height) | |||
| { | |||
| fUI.setSize(width, height); | |||
| hostCallback(audioMasterSizeWindow, width, height, nullptr, 0.0f); | |||
| @@ -256,7 +256,7 @@ private: | |||
| handlePtr->sendNote(channel, note, velocity); | |||
| } | |||
| static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height) | |||
| static void uiResizeCallback(void* ptr, uint width, uint height) | |||
| { | |||
| handlePtr->uiResize(width, height); | |||
| } | |||
| @@ -753,7 +753,7 @@ private: | |||
| fPlugin.setState(newKey, newValue); | |||
| // check if we want to save this key | |||
| if (! fPlugin.wantsStateKey(newKey)) | |||
| if (! fPlugin.wantStateKey(newKey)) | |||
| return; | |||
| // check if key already exists | |||
| @@ -23,7 +23,7 @@ END_NAMESPACE_DGL | |||
| START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| // Static data | |||
| // Static data, see DistrhoUIInternal.hpp | |||
| double d_lastUiSampleRate = 0.0; | |||
| @@ -34,7 +34,7 @@ UI::UI() | |||
| : DGL::Widget(*DGL::dgl_lastUiParent), | |||
| pData(new PrivateData()) | |||
| { | |||
| assert(DGL::dgl_lastUiParent != nullptr); | |||
| DISTRHO_SAFE_ASSERT(DGL::dgl_lastUiParent != nullptr); | |||
| DGL::dgl_lastUiParent = nullptr; | |||
| } | |||
| @@ -79,7 +79,7 @@ void UI::d_sendNote(uint8_t channel, uint8_t note, uint8_t velocity) | |||
| // ----------------------------------------------------------------------- | |||
| // Host UI State | |||
| void UI::d_uiResize(unsigned int width, unsigned int height) | |||
| void UI::d_uiResize(uint width, uint height) | |||
| { | |||
| pData->uiResizeCallback(width, height); | |||
| } | |||
| @@ -88,7 +88,7 @@ void UI::d_uiResize(unsigned int width, unsigned int height) | |||
| // ----------------------------------------------------------------------- | |||
| // Direct DSP access | |||
| void* UI::d_getPluginInstancePointer() | |||
| void* UI::d_getPluginInstancePointer() const noexcept | |||
| { | |||
| return pData->dspPtr; | |||
| } | |||
| @@ -60,7 +60,7 @@ struct OscData { | |||
| lo_send(addr, targetPath, "if", index, value); | |||
| } | |||
| void send_midi(unsigned char data[4]) const | |||
| void send_midi(uchar data[4]) const | |||
| { | |||
| char targetPath[std::strlen(path)+6]; | |||
| std::strcpy(targetPath, path); | |||
| @@ -126,13 +126,13 @@ public: | |||
| } | |||
| #endif | |||
| void dssiui_control(unsigned long index, float value) | |||
| void dssiui_control(ulong index, float value) | |||
| { | |||
| fUI.parameterChanged(index, value); | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| void dssiui_program(unsigned long bank, unsigned long program) | |||
| void dssiui_program(ulong bank, ulong program) | |||
| { | |||
| fUI.programChanged(bank * 128 + program); | |||
| } | |||
| @@ -186,7 +186,7 @@ protected: | |||
| fOscData.send_midi(mdata); | |||
| } | |||
| void uiResize(const unsigned int width, const unsigned int height) | |||
| void uiResize(const uint width, const uint height) | |||
| { | |||
| fUI.setSize(width, height); | |||
| } | |||
| @@ -217,7 +217,7 @@ private: | |||
| uiPtr->sendNote(channel, note, velocity); | |||
| } | |||
| static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height) | |||
| static void uiResizeCallback(void* ptr, uint width, uint height) | |||
| { | |||
| uiPtr->uiResize(width, height); | |||
| } | |||
| @@ -36,7 +36,7 @@ typedef void (*editParamFunc) (void* ptr, uint32_t rindex, bool started); | |||
| typedef void (*setParamFunc) (void* ptr, uint32_t rindex, float value); | |||
| typedef void (*setStateFunc) (void* ptr, const char* key, const char* value); | |||
| typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8_t velo); | |||
| typedef void (*uiResizeFunc) (void* ptr, unsigned int width, unsigned int height); | |||
| typedef void (*uiResizeFunc) (void* ptr, uint width, uint height); | |||
| // ----------------------------------------------------------------------- | |||
| // UI private data | |||
| @@ -70,7 +70,7 @@ struct UI::PrivateData { | |||
| uiResizeCallbackFunc(nullptr), | |||
| ptr(nullptr) | |||
| { | |||
| assert(sampleRate != 0.0); | |||
| DISTRHO_SAFE_ASSERT(sampleRate != 0.0); | |||
| #if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2) | |||
| parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS; | |||
| @@ -78,6 +78,7 @@ struct UI::PrivateData { | |||
| parameterOffset += 1; | |||
| # endif | |||
| #endif | |||
| #ifdef DISTRHO_PLUGIN_TARGET_LV2 | |||
| # if (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE) | |||
| parameterOffset += 1; | |||
| @@ -112,7 +113,7 @@ struct UI::PrivateData { | |||
| sendNoteCallbackFunc(ptr, channel, note, velocity); | |||
| } | |||
| void uiResizeCallback(const unsigned int width, const unsigned int height) | |||
| void uiResizeCallback(const uint width, const uint height) | |||
| { | |||
| if (uiResizeCallbackFunc != nullptr) | |||
| uiResizeCallbackFunc(ptr, width, height); | |||
| @@ -126,16 +127,15 @@ class UIExporter | |||
| { | |||
| public: | |||
| UIExporter(void* const ptr, const intptr_t winId, | |||
| const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const uiResizeFunc uiResizeCall, void* const dspPtr = nullptr) | |||
| const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const uiResizeFunc uiResizeCall, | |||
| void* const dspPtr = nullptr) | |||
| : glApp(), | |||
| glWindow(glApp, winId), | |||
| fUi(createUI()), | |||
| fData((fUi != nullptr) ? fUi->pData : nullptr) | |||
| { | |||
| assert(fUi != nullptr); | |||
| if (fUi == nullptr) | |||
| return; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||
| fData->ptr = ptr; | |||
| fData->editParamCallbackFunc = editParamCall; | |||
| @@ -164,47 +164,60 @@ public: | |||
| const char* getName() const noexcept | |||
| { | |||
| return (fUi != nullptr) ? fUi->d_getName() : ""; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, ""); | |||
| return fUi->d_getName(); | |||
| } | |||
| unsigned int getWidth() const noexcept | |||
| uint getWidth() const noexcept | |||
| { | |||
| return (fUi != nullptr) ? fUi->d_getWidth() : 0; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, 0); | |||
| return fUi->d_getWidth(); | |||
| } | |||
| unsigned int getHeight() const noexcept | |||
| uint getHeight() const noexcept | |||
| { | |||
| return (fUi != nullptr) ? fUi->d_getHeight() : 0; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, 0); | |||
| return fUi->d_getHeight(); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| uint32_t getParameterOffset() const noexcept | |||
| { | |||
| return (fData != nullptr) ? fData->parameterOffset : 0; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); | |||
| return fData->parameterOffset; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| void parameterChanged(const uint32_t index, const float value) | |||
| { | |||
| if (fUi != nullptr) | |||
| fUi->d_parameterChanged(index, value); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); | |||
| fUi->d_parameterChanged(index, value); | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| void programChanged(const uint32_t index) | |||
| { | |||
| if (fUi != nullptr) | |||
| fUi->d_programChanged(index); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); | |||
| fUi->d_programChanged(index); | |||
| } | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| void stateChanged(const char* const key, const char* const value) | |||
| { | |||
| if (fUi != nullptr) | |||
| fUi->d_stateChanged(key, value); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); | |||
| DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,); | |||
| fUi->d_stateChanged(key, value); | |||
| } | |||
| #endif | |||
| @@ -212,9 +225,9 @@ public: | |||
| bool idle() | |||
| { | |||
| if (fUi != nullptr) | |||
| fUi->d_uiIdle(); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, false); | |||
| fUi->d_uiIdle(); | |||
| glApp.idle(); | |||
| return ! glApp.isQuiting(); | |||
| @@ -226,7 +239,7 @@ public: | |||
| glApp.quit(); | |||
| } | |||
| void setSize(const unsigned int width, const unsigned int height) | |||
| void setSize(const uint width, const uint height) | |||
| { | |||
| glWindow.setSize(width, height); | |||
| } | |||
| @@ -254,10 +267,13 @@ private: | |||
| DGL::Window glWindow; | |||
| // ------------------------------------------------------------------- | |||
| // private members accessed by DistrhoPlugin class | |||
| // private members accessed by DistrhoUI classes | |||
| UI* const fUi; | |||
| UI::PrivateData* const fData; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter) | |||
| DISTRHO_PREVENT_HEAP_ALLOCATION | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -40,9 +40,16 @@ public: | |||
| fUiResize(uiResz), | |||
| fUiTouch(uiTouch), | |||
| fController(controller), | |||
| fWriteFunction(writeFunc) | |||
| fWriteFunction(writeFunc), | |||
| fEventTransferURID(uridMap->map(uridMap->handle, LV2_ATOM__eventTransfer)), | |||
| fKeyValueURID(uridMap->map(uridMap->handle, "urn:distrho:keyValueState")) | |||
| { | |||
| fUiResize->ui_resize(fUiResize->handle, fUI.getWidth(), fUI.getHeight()); | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| // tell the DSP we're ready to receive msgs | |||
| setState("__dpf_ui_data__", ""); | |||
| #endif | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -61,10 +68,17 @@ public: | |||
| const float value(*(const float*)buffer); | |||
| fUI.parameterChanged(rindex-parameterOffset, value); | |||
| } | |||
| else | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| else if (format == fEventTransferURID) | |||
| { | |||
| //fUI.stateChanged(key, value); | |||
| const LV2_Atom* const atom((const LV2_Atom*)buffer); | |||
| const char* const stateKey((const char*)LV2_ATOM_BODY_CONST(atom)); | |||
| const char* const stateValue(stateKey+std::strlen(stateKey)+1); | |||
| d_stdout("Got MSG in UI from DSP ==> %s | %s", stateKey, stateValue); | |||
| fUI.stateChanged(stateKey, stateValue); | |||
| } | |||
| #endif | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -125,20 +139,20 @@ protected: | |||
| // set atom info | |||
| LV2_Atom* const atom((LV2_Atom*)atomBuf); | |||
| atom->size = msgSize; | |||
| atom->type = fUridMap->map(fUridMap->handle, "urn:distrho:keyValueState"); | |||
| atom->type = fKeyValueURID; | |||
| // set atom data | |||
| std::memcpy(atomBuf + sizeof(LV2_Atom), tmpStr.data(), msgSize-1); | |||
| // send to DSP side | |||
| fWriteFunction(fController, eventInPortIndex, atomSize, fUridMap->map(fUridMap->handle, LV2_ATOM__eventTransfer), atom); | |||
| fWriteFunction(fController, eventInPortIndex, atomSize, fEventTransferURID, atom); | |||
| } | |||
| void sendNote(const uint8_t /*channel*/, const uint8_t /*note*/, const uint8_t /*velocity*/) | |||
| { | |||
| } | |||
| void uiResize(const unsigned int width, const unsigned int height) | |||
| void uiResize(const uint width, const uint height) | |||
| { | |||
| fUI.setSize(width, height); | |||
| fUiResize->ui_resize(fUiResize->handle, width, height); | |||
| @@ -156,6 +170,10 @@ private: | |||
| const LV2UI_Controller fController; | |||
| const LV2UI_Write_Function fWriteFunction; | |||
| // Need to save this | |||
| const LV2_URID fEventTransferURID; | |||
| const LV2_URID fKeyValueURID; | |||
| // ------------------------------------------------------------------- | |||
| // Callbacks | |||
| @@ -181,7 +199,7 @@ private: | |||
| uiPtr->sendNote(channel, note, velocity); | |||
| } | |||
| static void uiResizeCallback(void* ptr, unsigned int width, unsigned int height) | |||
| static void uiResizeCallback(void* ptr, uint width, uint height) | |||
| { | |||
| uiPtr->uiResize(width, height); | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| Copyright 2008-2012 David Robillard <http://drobilla.net> | |||
| Copyright 2008-2013 David Robillard <http://drobilla.net> | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| @@ -48,6 +48,12 @@ | |||
| #include "atom-util.h" | |||
| #include "urid.h" | |||
| #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) | |||
| # define LV2_ATOM_FORGE_DEPRECATED __attribute__((__deprecated__)) | |||
| #else | |||
| # define LV2_ATOM_FORGE_DEPRECATED | |||
| #endif | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #else | |||
| @@ -89,7 +95,7 @@ typedef struct { | |||
| LV2_Atom_Forge_Frame* stack; | |||
| LV2_URID Blank; | |||
| LV2_URID Blank LV2_ATOM_FORGE_DEPRECATED; | |||
| LV2_URID Bool; | |||
| LV2_URID Chunk; | |||
| LV2_URID Double; | |||
| @@ -97,9 +103,10 @@ typedef struct { | |||
| LV2_URID Int; | |||
| LV2_URID Long; | |||
| LV2_URID Literal; | |||
| LV2_URID Object; | |||
| LV2_URID Path; | |||
| LV2_URID Property; | |||
| LV2_URID Resource; | |||
| LV2_URID Resource LV2_ATOM_FORGE_DEPRECATED; | |||
| LV2_URID Sequence; | |||
| LV2_URID String; | |||
| LV2_URID Tuple; | |||
| @@ -120,6 +127,13 @@ lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size); | |||
| static inline void | |||
| lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map) | |||
| { | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic push | |||
| # pragma clang diagnostic ignored "-Wdeprecated-declarations" | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic push | |||
| # pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |||
| #endif | |||
| lv2_atom_forge_set_buffer(forge, NULL, 0); | |||
| forge->Blank = map->map(map->handle, LV2_ATOM__Blank); | |||
| forge->Bool = map->map(map->handle, LV2_ATOM__Bool); | |||
| @@ -129,6 +143,7 @@ lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map) | |||
| forge->Int = map->map(map->handle, LV2_ATOM__Int); | |||
| forge->Long = map->map(map->handle, LV2_ATOM__Long); | |||
| forge->Literal = map->map(map->handle, LV2_ATOM__Literal); | |||
| forge->Object = map->map(map->handle, LV2_ATOM__Object); | |||
| forge->Path = map->map(map->handle, LV2_ATOM__Path); | |||
| forge->Property = map->map(map->handle, LV2_ATOM__Property); | |||
| forge->Resource = map->map(map->handle, LV2_ATOM__Resource); | |||
| @@ -138,6 +153,11 @@ lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map) | |||
| forge->URI = map->map(map->handle, LV2_ATOM__URI); | |||
| forge->URID = map->map(map->handle, LV2_ATOM__URID); | |||
| forge->Vector = map->map(map->handle, LV2_ATOM__Vector); | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic pop | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| } | |||
| static inline LV2_Atom* | |||
| @@ -184,8 +204,51 @@ lv2_atom_forge_pop(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) | |||
| static inline bool | |||
| lv2_atom_forge_top_is(LV2_Atom_Forge* forge, uint32_t type) | |||
| { | |||
| return forge->stack && | |||
| lv2_atom_forge_deref(forge, forge->stack->ref)->type == type; | |||
| return forge->stack && forge->stack->ref && | |||
| (lv2_atom_forge_deref(forge, forge->stack->ref)->type == type); | |||
| } | |||
| /** Return true iff @p type is an atom:Object. */ | |||
| static inline bool | |||
| lv2_atom_forge_is_object_type(const LV2_Atom_Forge* forge, uint32_t type) | |||
| { | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic push | |||
| # pragma clang diagnostic ignored "-Wdeprecated-declarations" | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic push | |||
| # pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |||
| #endif | |||
| return (type == forge->Object || | |||
| type == forge->Blank || | |||
| type == forge->Resource); | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic pop | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| } | |||
| /** Return true iff @p type is an atom:Object with a blank ID. */ | |||
| static inline bool | |||
| lv2_atom_forge_is_blank(const LV2_Atom_Forge* forge, | |||
| uint32_t type, | |||
| const LV2_Atom_Object_Body* body) | |||
| { | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic push | |||
| # pragma clang diagnostic ignored "-Wdeprecated-declarations" | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic push | |||
| # pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |||
| #endif | |||
| return (type == forge->Blank || | |||
| (type == forge->Object && body->id == 0)); | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic pop | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| } | |||
| /** | |||
| @@ -199,7 +262,7 @@ static inline void | |||
| lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size) | |||
| { | |||
| forge->buf = buf; | |||
| forge->size = size; | |||
| forge->size = (uint32_t)size; | |||
| forge->offset = 0; | |||
| forge->deref = NULL; | |||
| forge->sink = NULL; | |||
| @@ -253,7 +316,7 @@ lv2_atom_forge_raw(LV2_Atom_Forge* forge, const void* data, uint32_t size) | |||
| if (forge->sink) { | |||
| out = forge->sink(forge->handle, data, size); | |||
| } else { | |||
| out = (LV2_Atom_Forge_Ref)forge->buf + forge->offset; | |||
| out = (LV2_Atom_Forge_Ref)forge->buf + (LV2_Atom_Forge_Ref)forge->offset; | |||
| uint8_t* mem = forge->buf + forge->offset; | |||
| if (forge->offset + size > forge->size) { | |||
| return 0; | |||
| @@ -321,7 +384,8 @@ lv2_atom_forge_primitive(LV2_Atom_Forge* forge, const LV2_Atom* a) | |||
| if (lv2_atom_forge_top_is(forge, forge->Vector)) { | |||
| return lv2_atom_forge_raw(forge, LV2_ATOM_BODY_CONST(a), a->size); | |||
| } else { | |||
| return lv2_atom_forge_write(forge, a, sizeof(LV2_Atom) + a->size); | |||
| return lv2_atom_forge_write( | |||
| forge, a, (uint32_t)sizeof(LV2_Atom) + a->size); | |||
| } | |||
| } | |||
| @@ -503,7 +567,7 @@ lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) | |||
| } | |||
| /** | |||
| Write the header of an atom:Resource. | |||
| Write the header of an atom:Object. | |||
| The passed frame will be initialised to represent this object. To complete | |||
| the object, write a sequence of properties, then pop the frame with | |||
| @@ -514,12 +578,12 @@ lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) | |||
| LV2_URID eg_Cat = map("http://example.org/Cat"); | |||
| LV2_URID eg_name = map("http://example.org/name"); | |||
| // Write object header | |||
| // Start object with type eg_Cat and blank ID | |||
| LV2_Atom_Forge_Frame frame; | |||
| lv2_atom_forge_resource(forge, &frame, 1, eg_Cat); | |||
| lv2_atom_forge_object(forge, &frame, 0, eg_Cat); | |||
| // Write property: eg:name = "Hobbes" | |||
| lv2_atom_forge_property_head(forge, eg_name, 0); | |||
| // Append property eg:name = "Hobbes" | |||
| lv2_atom_forge_key(forge, eg_name); | |||
| lv2_atom_forge_string(forge, "Hobbes", strlen("Hobbes")); | |||
| // Finish object | |||
| @@ -527,39 +591,103 @@ lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) | |||
| @endcode | |||
| */ | |||
| static inline LV2_Atom_Forge_Ref | |||
| lv2_atom_forge_object(LV2_Atom_Forge* forge, | |||
| LV2_Atom_Forge_Frame* frame, | |||
| LV2_URID id, | |||
| LV2_URID otype) | |||
| { | |||
| const LV2_Atom_Object a = { | |||
| { (uint32_t)sizeof(LV2_Atom_Object_Body), forge->Object }, | |||
| { id, otype } | |||
| }; | |||
| return lv2_atom_forge_push( | |||
| forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); | |||
| } | |||
| /** | |||
| The same as lv2_atom_forge_object(), but for object:Resource. | |||
| This function is deprecated and should not be used in new code. | |||
| Use lv2_atom_forge_object() directly instead. | |||
| */ | |||
| LV2_ATOM_FORGE_DEPRECATED | |||
| static inline LV2_Atom_Forge_Ref | |||
| lv2_atom_forge_resource(LV2_Atom_Forge* forge, | |||
| LV2_Atom_Forge_Frame* frame, | |||
| LV2_URID id, | |||
| LV2_URID otype) | |||
| { | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic push | |||
| # pragma clang diagnostic ignored "-Wdeprecated-declarations" | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic push | |||
| # pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |||
| #endif | |||
| const LV2_Atom_Object a = { | |||
| { sizeof(LV2_Atom_Object) - sizeof(LV2_Atom), forge->Resource }, | |||
| { (uint32_t)sizeof(LV2_Atom_Object_Body), forge->Resource }, | |||
| { id, otype } | |||
| }; | |||
| LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); | |||
| return lv2_atom_forge_push(forge, frame, out); | |||
| return lv2_atom_forge_push( | |||
| forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic pop | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| } | |||
| /** | |||
| The same as lv2_atom_forge_resource(), but for object:Blank. | |||
| The same as lv2_atom_forge_object(), but for object:Blank. | |||
| This function is deprecated and should not be used in new code. | |||
| Use lv2_atom_forge_object() directly instead. | |||
| */ | |||
| LV2_ATOM_FORGE_DEPRECATED | |||
| static inline LV2_Atom_Forge_Ref | |||
| lv2_atom_forge_blank(LV2_Atom_Forge* forge, | |||
| LV2_Atom_Forge_Frame* frame, | |||
| uint32_t id, | |||
| LV2_URID otype) | |||
| { | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic push | |||
| # pragma clang diagnostic ignored "-Wdeprecated-declarations" | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic push | |||
| # pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |||
| #endif | |||
| const LV2_Atom_Object a = { | |||
| { sizeof(LV2_Atom_Object) - sizeof(LV2_Atom), forge->Blank }, | |||
| { (uint32_t)sizeof(LV2_Atom_Object_Body), forge->Blank }, | |||
| { id, otype } | |||
| }; | |||
| LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); | |||
| return lv2_atom_forge_push(forge, frame, out); | |||
| return lv2_atom_forge_push( | |||
| forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); | |||
| #if defined(__clang__) | |||
| # pragma clang diagnostic pop | |||
| #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| } | |||
| /** | |||
| Write a property key in an Object, to be followed by the value. | |||
| See lv2_atom_forge_object() documentation for an example. | |||
| */ | |||
| static inline LV2_Atom_Forge_Ref | |||
| lv2_atom_forge_key(LV2_Atom_Forge* forge, | |||
| LV2_URID key) | |||
| { | |||
| const LV2_Atom_Property_Body a = { key, 0, { 0, 0 } }; | |||
| return lv2_atom_forge_write(forge, &a, 2 * (uint32_t)sizeof(uint32_t)); | |||
| } | |||
| /** | |||
| Write the header for a property body (likely in an Object). | |||
| See lv2_atom_forge_resource() documentation for an example. | |||
| Write the header for a property body in an object, with context. | |||
| If you do not need the context, which is almost certainly the case, | |||
| use the simpler lv2_atom_forge_key() instead. | |||
| */ | |||
| static inline LV2_Atom_Forge_Ref | |||
| lv2_atom_forge_property_head(LV2_Atom_Forge* forge, | |||
| @@ -567,7 +695,7 @@ lv2_atom_forge_property_head(LV2_Atom_Forge* forge, | |||
| LV2_URID context) | |||
| { | |||
| const LV2_Atom_Property_Body a = { key, context, { 0, 0 } }; | |||
| return lv2_atom_forge_write(forge, &a, 2 * sizeof(uint32_t)); | |||
| return lv2_atom_forge_write(forge, &a, 2 * (uint32_t)sizeof(uint32_t)); | |||
| } | |||
| /** | |||
| @@ -579,11 +707,11 @@ lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge, | |||
| uint32_t unit) | |||
| { | |||
| const LV2_Atom_Sequence a = { | |||
| { sizeof(LV2_Atom_Sequence) - sizeof(LV2_Atom), forge->Sequence }, | |||
| { (uint32_t)sizeof(LV2_Atom_Sequence_Body), forge->Sequence }, | |||
| { unit, 0 } | |||
| }; | |||
| LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); | |||
| return lv2_atom_forge_push(forge, frame, out); | |||
| return lv2_atom_forge_push( | |||
| forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); | |||
| } | |||
| /** | |||
| @@ -1,7 +1,7 @@ | |||
| // lv2_atom_helpers.h | |||
| // | |||
| /**************************************************************************** | |||
| Copyright (C) 2005-2012, rncbc aka Rui Nuno Capela. All rights reserved. | |||
| Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved. | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| @@ -40,7 +40,7 @@ | |||
| #include <stdlib.h> | |||
| #include <assert.h> | |||
| #include "atom.h" | |||
| #include "atom-util.h" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| @@ -59,28 +59,18 @@ struct _LV2_Atom_Buffer | |||
| } LV2_Atom_Buffer; | |||
| // Pad a size to 64 bits (for LV2 atom:Sequence event sizes). | |||
| // | |||
| static inline | |||
| uint32_t lv2_atom_buffer_pad_size ( uint32_t size ) | |||
| { | |||
| return (size + 7) & (~7); | |||
| } | |||
| // Clear and initialize an existing LV2 atom:Sequenece buffer. | |||
| // | |||
| static inline | |||
| void lv2_atom_buffer_reset ( LV2_Atom_Buffer *buf, bool input ) | |||
| { | |||
| if (input) | |||
| if (input) { | |||
| buf->atoms.atom.size = sizeof(LV2_Atom_Sequence_Body); | |||
| else | |||
| buf->atoms.atom.type = buf->sequence_type; | |||
| } else { | |||
| buf->atoms.atom.size = buf->capacity; | |||
| buf->atoms.atom.type = buf->sequence_type; | |||
| buf->atoms.body.unit = 0; | |||
| buf->atoms.body.pad = 0; | |||
| buf->atoms.atom.type = buf->chunk_type; | |||
| } | |||
| } | |||
| @@ -88,12 +78,13 @@ void lv2_atom_buffer_reset ( LV2_Atom_Buffer *buf, bool input ) | |||
| // | |||
| static inline | |||
| LV2_Atom_Buffer *lv2_atom_buffer_new ( | |||
| uint32_t capacity, uint32_t sequence_type, bool input ) | |||
| uint32_t capacity, uint32_t chunk_type, uint32_t sequence_type, bool input ) | |||
| { | |||
| LV2_Atom_Buffer *buf = (LV2_Atom_Buffer *) | |||
| malloc(sizeof(LV2_Atom_Buffer) + sizeof(LV2_Atom_Sequence) + capacity); | |||
| buf->capacity = capacity; | |||
| buf->chunk_type = chunk_type; | |||
| buf->sequence_type = sequence_type; | |||
| lv2_atom_buffer_reset(buf, input); | |||
| @@ -116,7 +107,10 @@ void lv2_atom_buffer_free ( LV2_Atom_Buffer *buf ) | |||
| static inline | |||
| uint32_t lv2_atom_buffer_get_size ( LV2_Atom_Buffer *buf ) | |||
| { | |||
| return buf->atoms.atom.size - sizeof(LV2_Atom_Sequence_Body); | |||
| if (buf->atoms.atom.type == buf->sequence_type) | |||
| return buf->atoms.atom.size - uint32_t(sizeof(LV2_Atom_Sequence_Body)); | |||
| else | |||
| return 0; | |||
| } | |||
| @@ -160,7 +154,7 @@ bool lv2_atom_buffer_end ( | |||
| LV2_Atom_Buffer_Iterator *iter, LV2_Atom_Buffer *buf ) | |||
| { | |||
| iter->buf = buf; | |||
| iter->offset = lv2_atom_buffer_pad_size(lv2_atom_buffer_get_size(buf)); | |||
| iter->offset = lv2_atom_pad_size(lv2_atom_buffer_get_size(buf)); | |||
| return (iter->offset < buf->capacity - sizeof(LV2_Atom_Event)); | |||
| } | |||
| @@ -187,7 +181,7 @@ bool lv2_atom_buffer_increment ( LV2_Atom_Buffer_Iterator *iter ) | |||
| LV2_Atom_Sequence *atoms = &buf->atoms; | |||
| uint32_t size = ((LV2_Atom_Event *) ((char *) | |||
| LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + iter->offset))->body.size; | |||
| iter->offset += lv2_atom_buffer_pad_size(sizeof(LV2_Atom_Event) + size); | |||
| iter->offset += lv2_atom_pad_size(uint32_t(sizeof(LV2_Atom_Event)) + size); | |||
| return true; | |||
| } | |||
| @@ -239,7 +233,7 @@ bool lv2_atom_buffer_write ( | |||
| memcpy(LV2_ATOM_BODY(&ev->body), data, size); | |||
| size = lv2_atom_buffer_pad_size(sizeof(LV2_Atom_Event) + size); | |||
| size = lv2_atom_pad_size(uint32_t(sizeof(LV2_Atom_Event)) + size); | |||
| atoms->atom.size += size; | |||
| iter->offset += size; | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| Copyright 2008-2012 David Robillard <http://drobilla.net> | |||
| Copyright 2008-2013 David Robillard <http://drobilla.net> | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| @@ -41,14 +41,14 @@ extern "C" { | |||
| static inline uint32_t | |||
| lv2_atom_pad_size(uint32_t size) | |||
| { | |||
| return (size + 7) & (~7); | |||
| return (size + 7U) & (~7U); | |||
| } | |||
| /** Return the total size of @p atom, including the header. */ | |||
| static inline uint32_t | |||
| lv2_atom_total_size(const LV2_Atom* atom) | |||
| { | |||
| return sizeof(LV2_Atom) + atom->size; | |||
| return (uint32_t)sizeof(LV2_Atom) + atom->size; | |||
| } | |||
| /** Return true iff @p atom is null. */ | |||
| @@ -80,10 +80,10 @@ lv2_atom_sequence_begin(const LV2_Atom_Sequence_Body* body) | |||
| } | |||
| /** Get an iterator pointing to the end of a Sequence body. */ | |||
| static inline const LV2_Atom_Event* | |||
| lv2_atom_sequence_end(const LV2_Atom_Sequence_Body* body, uint32_t size) | |||
| static inline LV2_Atom_Event* | |||
| lv2_atom_sequence_end(LV2_Atom_Sequence_Body* body, uint32_t size) | |||
| { | |||
| return (const LV2_Atom_Event*)((const uint8_t*)body + lv2_atom_pad_size(size)); | |||
| return (LV2_Atom_Event*)((uint8_t*)body + lv2_atom_pad_size(size)); | |||
| } | |||
| /** Return true iff @p i has reached the end of @p body. */ | |||
| @@ -99,7 +99,6 @@ lv2_atom_sequence_is_end(const LV2_Atom_Sequence_Body* body, | |||
| static inline const LV2_Atom_Event* | |||
| lv2_atom_sequence_next(const LV2_Atom_Event* i) | |||
| { | |||
| if (!i) return NULL; | |||
| return (const LV2_Atom_Event*)((const uint8_t*)i | |||
| + sizeof(LV2_Atom_Event) | |||
| + lv2_atom_pad_size(i->body.size)); | |||
| @@ -128,6 +127,52 @@ lv2_atom_sequence_next(const LV2_Atom_Event* i) | |||
| !lv2_atom_sequence_is_end(body, size, (iter)); \ | |||
| (iter) = lv2_atom_sequence_next(iter)) | |||
| /** | |||
| @} | |||
| @name Sequence Utilities | |||
| @{ | |||
| */ | |||
| /** | |||
| Clear all events from @p sequence. | |||
| This simply resets the size field, the other fields are left untouched. | |||
| */ | |||
| static inline void | |||
| lv2_atom_sequence_clear(LV2_Atom_Sequence* seq) | |||
| { | |||
| seq->atom.size = sizeof(LV2_Atom_Sequence_Body); | |||
| } | |||
| /** | |||
| Append an event at the end of @p sequence. | |||
| @param seq Sequence to append to. | |||
| @param capacity Total capacity of the sequence atom | |||
| (e.g. as set by the host for sequence output ports). | |||
| @param event Event to write. | |||
| @return A pointer to the newly written event in @p seq, | |||
| or NULL on failure (insufficient space). | |||
| */ | |||
| static inline LV2_Atom_Event* | |||
| lv2_atom_sequence_append_event(LV2_Atom_Sequence* seq, | |||
| uint32_t capacity, | |||
| const LV2_Atom_Event* event) | |||
| { | |||
| const uint32_t total_size = (uint32_t)sizeof(*event) + event->body.size; | |||
| if (capacity - seq->atom.size < total_size) { | |||
| return NULL; | |||
| } | |||
| LV2_Atom_Event* e = lv2_atom_sequence_end(&seq->body, seq->atom.size); | |||
| memcpy(e, event, total_size); | |||
| seq->atom.size += lv2_atom_pad_size(total_size); | |||
| return e; | |||
| } | |||
| /** | |||
| @} | |||
| @name Tuple Iterator | |||
| @@ -143,7 +188,7 @@ lv2_atom_tuple_begin(const LV2_Atom_Tuple* tup) | |||
| /** Return true iff @p i has reached the end of @p body. */ | |||
| static inline bool | |||
| lv2_atom_tuple_is_end(const void* body, uint32_t size, LV2_Atom* i) | |||
| lv2_atom_tuple_is_end(const void* body, uint32_t size, const LV2_Atom* i) | |||
| { | |||
| return (const uint8_t*)i >= ((const uint8_t*)body + size); | |||
| } | |||
| @@ -169,13 +214,13 @@ lv2_atom_tuple_next(const LV2_Atom* i) | |||
| @endcode | |||
| */ | |||
| #define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \ | |||
| for (LV2_Atom* (iter) = lv2_atom_tuple_begin(tuple); \ | |||
| !lv2_atom_tuple_is_end(LV2_ATOM_BODY(tuple), (tuple)->size, (iter)); \ | |||
| for (const LV2_Atom* (iter) = lv2_atom_tuple_begin(tuple); \ | |||
| !lv2_atom_tuple_is_end(LV2_ATOM_BODY_CONST(tuple), (tuple)->size, (iter)); \ | |||
| (iter) = lv2_atom_tuple_next(iter)) | |||
| /** Like LV2_ATOM_TUPLE_FOREACH but for a headerless tuple body. */ | |||
| #define LV2_ATOM_TUPLE_BODY_FOREACH(body, size, iter) \ | |||
| for (LV2_Atom* (iter) = (LV2_Atom*)body; \ | |||
| for (const LV2_Atom* (iter) = (const LV2_Atom*)body; \ | |||
| !lv2_atom_tuple_is_end(body, size, (iter)); \ | |||
| (iter) = lv2_atom_tuple_next(iter)) | |||
| @@ -208,8 +253,8 @@ lv2_atom_object_next(const LV2_Atom_Property_Body* i) | |||
| const LV2_Atom* const value = (const LV2_Atom*)( | |||
| (const uint8_t*)i + 2 * sizeof(uint32_t)); | |||
| return (const LV2_Atom_Property_Body*)( | |||
| (const uint8_t*)i + lv2_atom_pad_size(sizeof(LV2_Atom_Property_Body) | |||
| + value->size)); | |||
| (const uint8_t*)i + lv2_atom_pad_size( | |||
| (uint32_t)sizeof(LV2_Atom_Property_Body) + value->size)); | |||
| } | |||
| /** | |||
| @@ -189,7 +189,7 @@ typedef struct { | |||
| /** The body of an atom:Object. May be cast to LV2_Atom. */ | |||
| typedef struct { | |||
| uint32_t id; /**< URID (atom:Resource) or blank ID (atom:Blank). */ | |||
| uint32_t id; /**< URID, or 0 for blank. */ | |||
| uint32_t otype; /**< Type URID (same as rdf:type, for fast dispatch). */ | |||
| /* Contents (a series of property bodies) follow here. */ | |||
| } LV2_Atom_Object_Body; | |||
| @@ -50,7 +50,7 @@ extern "C" { | |||
| static inline uint16_t | |||
| lv2_event_pad_size(uint16_t size) | |||
| { | |||
| return (size + 7) & (~7); | |||
| return (uint16_t)(size + 7U) & (uint16_t)(~7U); | |||
| } | |||
| @@ -60,7 +60,7 @@ lv2_event_pad_size(uint16_t size) | |||
| static inline void | |||
| lv2_event_buffer_reset(LV2_Event_Buffer* buf, | |||
| uint16_t stamp_type, | |||
| uint8_t *data) | |||
| uint8_t* data) | |||
| { | |||
| buf->data = data; | |||
| buf->header_size = sizeof(LV2_Event_Buffer); | |||
| @@ -130,7 +130,8 @@ lv2_event_increment(LV2_Event_Iterator* iter) | |||
| LV2_Event* const ev = (LV2_Event*)( | |||
| (uint8_t*)iter->buf->data + iter->offset); | |||
| iter->offset += lv2_event_pad_size(sizeof(LV2_Event) + ev->size); | |||
| iter->offset += lv2_event_pad_size( | |||
| (uint16_t)((uint16_t)sizeof(LV2_Event) + ev->size)); | |||
| return true; | |||
| } | |||
| @@ -190,7 +191,7 @@ lv2_event_write(LV2_Event_Iterator* iter, | |||
| memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size); | |||
| ++iter->buf->event_count; | |||
| size = lv2_event_pad_size(sizeof(LV2_Event) + size); | |||
| size = lv2_event_pad_size((uint16_t)(sizeof(LV2_Event) + size)); | |||
| iter->buf->size += size; | |||
| iter->offset += size; | |||
| @@ -208,11 +209,12 @@ lv2_event_reserve(LV2_Event_Iterator* iter, | |||
| uint16_t type, | |||
| uint16_t size) | |||
| { | |||
| if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size) | |||
| const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + size); | |||
| if (iter->buf->capacity - iter->buf->size < total_size) | |||
| return NULL; | |||
| LV2_Event* const ev = (LV2_Event*)((uint8_t*)iter->buf->data + | |||
| iter->offset); | |||
| LV2_Event* const ev = (LV2_Event*)( | |||
| (uint8_t*)iter->buf->data + iter->offset); | |||
| ev->frames = frames; | |||
| ev->subframes = subframes; | |||
| @@ -220,9 +222,9 @@ lv2_event_reserve(LV2_Event_Iterator* iter, | |||
| ev->size = size; | |||
| ++iter->buf->event_count; | |||
| size = lv2_event_pad_size(sizeof(LV2_Event) + size); | |||
| iter->buf->size += size; | |||
| iter->offset += size; | |||
| const uint16_t padded_size = lv2_event_pad_size(total_size); | |||
| iter->buf->size += padded_size; | |||
| iter->offset += padded_size; | |||
| return (uint8_t*)ev + sizeof(LV2_Event); | |||
| } | |||
| @@ -238,19 +240,20 @@ lv2_event_write_event(LV2_Event_Iterator* iter, | |||
| const LV2_Event* ev, | |||
| const uint8_t* data) | |||
| { | |||
| if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + ev->size) | |||
| const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + ev->size); | |||
| if (iter->buf->capacity - iter->buf->size < total_size) | |||
| return false; | |||
| LV2_Event* const write_ev = (LV2_Event*)( | |||
| (uint8_t*)iter->buf->data + iter->offset); | |||
| (uint8_t*)iter->buf->data + iter->offset); | |||
| *write_ev = *ev; | |||
| memcpy((uint8_t*)write_ev + sizeof(LV2_Event), data, ev->size); | |||
| ++iter->buf->event_count; | |||
| const uint16_t size = lv2_event_pad_size(sizeof(LV2_Event) + ev->size); | |||
| iter->buf->size += size; | |||
| iter->offset += size; | |||
| const uint16_t padded_size = lv2_event_pad_size(total_size); | |||
| iter->buf->size += padded_size; | |||
| iter->offset += padded_size; | |||
| return true; | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| Copyright 2012 David Robillard <http://drobilla.net> | |||
| Copyright 2012-2013 David Robillard <http://drobilla.net> | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| @@ -28,6 +28,7 @@ | |||
| #define LV2_ATOM_LOGGER_H | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #include "log.h" | |||
| @@ -50,7 +50,7 @@ inline double lv2midi_get_event(LV2_MIDIState* state, | |||
| } | |||
| *timestamp = *(double*)(state->midi->data + state->position); | |||
| *size = *(size_t*)(state->midi->data + state->position + sizeof(double)); | |||
| *size = (uint32_t)*(size_t*)(state->midi->data + state->position + sizeof(double)); | |||
| *data = state->midi->data + state->position + | |||
| sizeof(double) + sizeof(size_t); | |||
| return *timestamp; | |||
| @@ -64,10 +64,10 @@ inline double lv2midi_step(LV2_MIDIState* state) { | |||
| return state->frame_count; | |||
| } | |||
| state->position += sizeof(double); | |||
| state->position += (uint32_t)sizeof(double); | |||
| size_t size = *(size_t*)(state->midi->data + state->position); | |||
| state->position += sizeof(size_t); | |||
| state->position += size; | |||
| state->position += (uint32_t)sizeof(size_t); | |||
| state->position += (uint32_t)size; | |||
| return *(double*)(state->midi->data + state->position); | |||
| } | |||
| @@ -80,9 +80,9 @@ inline void lv2midi_put_event(LV2_MIDIState* state, | |||
| if (state->midi->size + sizeof(double) + sizeof(size_t) + size < state->midi->capacity) | |||
| { | |||
| *((double*)(state->midi->data + state->midi->size)) = timestamp; | |||
| state->midi->size += sizeof(double); | |||
| state->midi->size += (uint32_t)sizeof(double); | |||
| *((size_t*)(state->midi->data + state->midi->size)) = size; | |||
| state->midi->size += sizeof(size_t); | |||
| state->midi->size += (uint32_t)sizeof(size_t); | |||
| memcpy(state->midi->data + state->midi->size, data, size); | |||
| state->midi->size += size; | |||
| @@ -21,7 +21,7 @@ | |||
| /** | |||
| @file lv2.h | |||
| API for the LV2 specification <http://lv2plug.in/ns/lv2core>. | |||
| Revision: 6.5 | |||
| Revision: 12.0 | |||
| */ | |||
| #ifndef LV2_H_INCLUDED | |||
| @@ -109,6 +109,7 @@ | |||
| #define LV2_CORE__port LV2_CORE_PREFIX "port" | |||
| #define LV2_CORE__portProperty LV2_CORE_PREFIX "portProperty" | |||
| #define LV2_CORE__project LV2_CORE_PREFIX "project" | |||
| #define LV2_CORE__prototype LV2_CORE_PREFIX "prototype" | |||
| #define LV2_CORE__reportsLatency LV2_CORE_PREFIX "reportsLatency" | |||
| #define LV2_CORE__requiredFeature LV2_CORE_PREFIX "requiredFeature" | |||
| #define LV2_CORE__sampleRate LV2_CORE_PREFIX "sampleRate" | |||
| @@ -73,17 +73,19 @@ typedef struct _LV2_External_UI_Widget { | |||
| */ | |||
| typedef struct _LV2_External_UI_Host { | |||
| /** | |||
| * Callback that plugin UI will call | |||
| * when UI (GUI window) is closed by user. | |||
| * Callback that plugin UI will call when UI (GUI window) is closed by user. | |||
| * This callback will be called during execution of LV2_External_UI_Widget::run() | |||
| * (i.e. not from background thread). | |||
| * | |||
| * After this callback is called, UI is defunct. Host must call | |||
| * LV2UI_Descriptor::cleanup(). If host wants to make the UI visible | |||
| * again UI must be reinstantiated. | |||
| * After this callback is called, UI is defunct. Host must call LV2UI_Descriptor::cleanup(). | |||
| * If host wants to make the UI visible again, the UI must be reinstantiated. | |||
| * | |||
| * @note When using the depreated URI LV2_EXTERNAL_UI_DEPRECATED_URI, | |||
| * some hosts will not call LV2UI_Descriptor::cleanup() as they should, | |||
| * and may call show() again without re-initialization. | |||
| * | |||
| * @param controller Host context associated with plugin UI, as | |||
| * supplied to LV2UI_Descriptor::instantiate() | |||
| * supplied to LV2UI_Descriptor::instantiate(). | |||
| */ | |||
| void (*ui_closed)(LV2UI_Controller controller); | |||
| @@ -27,6 +27,9 @@ | |||
| /** max size of memory pool name, in chars, including terminating zero char */ | |||
| #define LV2_RTSAFE_MEMORY_POOL_NAME_MAX 128 | |||
| /** This extension used to be defined by a different URI */ | |||
| #define LV2_RTSAFE_MEMORY_POOL_DEPRECATED_URI "http://home.gna.org/lv2dynparam/rtmempool/v1" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #else | |||
| @@ -98,6 +101,17 @@ typedef struct _LV2_RtMemPool_Pool { | |||
| } LV2_RtMemPool_Pool; | |||
| /** | |||
| * Deprecated feature for backwards compatibility. | |||
| */ | |||
| typedef struct _LV2_RtMemPool_Pool_Deprecated { | |||
| unsigned char (*create)(const char*,size_t,size_t,size_t,LV2_RtMemPool_Handle*); | |||
| void (*destroy)(LV2_RtMemPool_Handle); | |||
| void* (*allocate_atomic)(LV2_RtMemPool_Handle); | |||
| void* (*allocate_sleepy)(LV2_RtMemPool_Handle); | |||
| void (*deallocate)(LV2_RtMemPool_Handle,void*); | |||
| } LV2_RtMemPool_Pool_Deprecated; | |||
| #ifdef __cplusplus | |||
| } /* extern "C" */ | |||
| #endif | |||
| @@ -19,8 +19,8 @@ | |||
| #include <stdint.h> | |||
| #include "lv2/lv2plug.in/ns/lv2core/lv2.h" | |||
| #include "lv2/lv2plug.in/ns/ext/urid/urid.h" | |||
| #include "lv2.h" | |||
| #include "urid.h" | |||
| #define LV2_MORPH_URI "http://lv2plug.in/ns/ext/morph" | |||
| #define LV2_MORPH_PREFIX LV2_MORPH_URI "#" | |||
| @@ -28,28 +28,29 @@ | |||
| #define LV2_PATCH_URI "http://lv2plug.in/ns/ext/patch" | |||
| #define LV2_PATCH_PREFIX LV2_PATCH_URI "#" | |||
| #define LV2_PATCH__Ack LV2_PATCH_PREFIX "Ack" | |||
| #define LV2_PATCH__Delete LV2_PATCH_PREFIX "Delete" | |||
| #define LV2_PATCH__Error LV2_PATCH_PREFIX "Error" | |||
| #define LV2_PATCH__Get LV2_PATCH_PREFIX "Get" | |||
| #define LV2_PATCH__Message LV2_PATCH_PREFIX "Message" | |||
| #define LV2_PATCH__Move LV2_PATCH_PREFIX "Move" | |||
| #define LV2_PATCH__Patch LV2_PATCH_PREFIX "Patch" | |||
| #define LV2_PATCH__Post LV2_PATCH_PREFIX "Post" | |||
| #define LV2_PATCH__Put LV2_PATCH_PREFIX "Put" | |||
| #define LV2_PATCH__Request LV2_PATCH_PREFIX "Request" | |||
| #define LV2_PATCH__Response LV2_PATCH_PREFIX "Response" | |||
| #define LV2_PATCH__Set LV2_PATCH_PREFIX "Set" | |||
| #define LV2_PATCH__add LV2_PATCH_PREFIX "add" | |||
| #define LV2_PATCH__body LV2_PATCH_PREFIX "body" | |||
| #define LV2_PATCH__destination LV2_PATCH_PREFIX "destination" | |||
| #define LV2_PATCH__property LV2_PATCH_PREFIX "property" | |||
| #define LV2_PATCH__readable LV2_PATCH_PREFIX "readable" | |||
| #define LV2_PATCH__remove LV2_PATCH_PREFIX "remove" | |||
| #define LV2_PATCH__request LV2_PATCH_PREFIX "request" | |||
| #define LV2_PATCH__subject LV2_PATCH_PREFIX "subject" | |||
| #define LV2_PATCH__value LV2_PATCH_PREFIX "value" | |||
| #define LV2_PATCH__wildcard LV2_PATCH_PREFIX "wildcard" | |||
| #define LV2_PATCH__writable LV2_PATCH_PREFIX "writable" | |||
| #define LV2_PATCH__Ack LV2_PATCH_PREFIX "Ack" | |||
| #define LV2_PATCH__Delete LV2_PATCH_PREFIX "Delete" | |||
| #define LV2_PATCH__Error LV2_PATCH_PREFIX "Error" | |||
| #define LV2_PATCH__Get LV2_PATCH_PREFIX "Get" | |||
| #define LV2_PATCH__Message LV2_PATCH_PREFIX "Message" | |||
| #define LV2_PATCH__Move LV2_PATCH_PREFIX "Move" | |||
| #define LV2_PATCH__Patch LV2_PATCH_PREFIX "Patch" | |||
| #define LV2_PATCH__Post LV2_PATCH_PREFIX "Post" | |||
| #define LV2_PATCH__Put LV2_PATCH_PREFIX "Put" | |||
| #define LV2_PATCH__Request LV2_PATCH_PREFIX "Request" | |||
| #define LV2_PATCH__Response LV2_PATCH_PREFIX "Response" | |||
| #define LV2_PATCH__Set LV2_PATCH_PREFIX "Set" | |||
| #define LV2_PATCH__add LV2_PATCH_PREFIX "add" | |||
| #define LV2_PATCH__body LV2_PATCH_PREFIX "body" | |||
| #define LV2_PATCH__destination LV2_PATCH_PREFIX "destination" | |||
| #define LV2_PATCH__property LV2_PATCH_PREFIX "property" | |||
| #define LV2_PATCH__readable LV2_PATCH_PREFIX "readable" | |||
| #define LV2_PATCH__remove LV2_PATCH_PREFIX "remove" | |||
| #define LV2_PATCH__request LV2_PATCH_PREFIX "request" | |||
| #define LV2_PATCH__subject LV2_PATCH_PREFIX "subject" | |||
| #define LV2_PATCH__sequenceNumber LV2_PATCH_PREFIX "sequenceNumber" | |||
| #define LV2_PATCH__value LV2_PATCH_PREFIX "value" | |||
| #define LV2_PATCH__wildcard LV2_PATCH_PREFIX "wildcard" | |||
| #define LV2_PATCH__writable LV2_PATCH_PREFIX "writable" | |||
| #endif /* LV2_PATCH_H */ | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| LV2 UI Extension | |||
| Copyright 2009-2012 David Robillard <d@drobilla.net> | |||
| Copyright 2009-2013 David Robillard <d@drobilla.net> | |||
| Copyright 2006-2011 Lars Luthman <lars.luthman@gmail.com> | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| @@ -51,8 +51,10 @@ | |||
| #define LV2_UI__portNotification LV2_UI_PREFIX "portNotification" | |||
| #define LV2_UI__portSubscribe LV2_UI_PREFIX "portSubscribe" | |||
| #define LV2_UI__resize LV2_UI_PREFIX "resize" | |||
| #define LV2_UI__showInterface LV2_UI_PREFIX "showInterface" | |||
| #define LV2_UI__touch LV2_UI_PREFIX "touch" | |||
| #define LV2_UI__ui LV2_UI_PREFIX "ui" | |||
| #define LV2_UI__updateRate LV2_UI_PREFIX "updateRate" | |||
| /** | |||
| The index returned by LV2_UI_Port_Port::port_index() for unknown ports. | |||
| @@ -260,7 +262,7 @@ typedef struct _LV2UI_Port_Map { | |||
| /** | |||
| Get the index for the port with the given @p symbol. | |||
| @return The index of the port, or LV2_UI_INVALID_PORT_INDEX if no such | |||
| @return The index of the port, or LV2UI_INVALID_PORT_INDEX if no such | |||
| port is found. | |||
| */ | |||
| uint32_t (*port_index)(LV2UI_Feature_Handle handle, const char* symbol); | |||
| @@ -339,7 +341,7 @@ typedef struct _LV2UI_Touch { | |||
| } LV2UI_Touch; | |||
| /** | |||
| UI Idle Feature (LV2_UI__idle) | |||
| UI Idle Feature (LV2_UI__idleInterface) | |||
| This feature is an addition to the UI API that provides a callback for the | |||
| host to call rapidly, e.g. to drive the idle callback of a toolkit. | |||
| @@ -356,6 +358,31 @@ typedef struct _LV2UI_Idle_Interface { | |||
| int (*idle)(LV2UI_Handle ui); | |||
| } LV2UI_Idle_Interface; | |||
| /** | |||
| UI Show Interface (LV2_UI__showInterface) | |||
| UIs can use this interface to provide show/hide methods to pop up a window, | |||
| which allows them to function in hosts unable to embed their widget type. | |||
| If used, LV2UI_Idle_Interface should also be used to drive the UI. The UI | |||
| should return non-zero from idle() when the window has been closed. | |||
| */ | |||
| typedef struct _LV2UI_Show_Interface { | |||
| /** | |||
| Show a window for this UI. | |||
| @return 0 on success, or anything else to stop being called. | |||
| */ | |||
| int (*show)(LV2UI_Handle ui); | |||
| /** | |||
| Hide the window for this UI. | |||
| @return 0 on success, or anything else to stop being called. | |||
| */ | |||
| int (*hide)(LV2UI_Handle ui); | |||
| } LV2UI_Show_Interface; | |||
| /** | |||
| Peak data for a slice of time, the update format for ui:peakProtocol. | |||
| */ | |||
| @@ -92,7 +92,7 @@ typedef struct { | |||
| } LV2_URI_Map_Feature; | |||
| #ifdef __cplusplus | |||
| } /* extern "C" */ | |||
| } /* extern "C" */ | |||
| #endif | |||
| #endif /* LV2_URI_MAP_H */ | |||
| @@ -123,7 +123,7 @@ typedef struct _LV2_URID_Unmap { | |||
| } LV2_URID_Unmap; | |||
| #ifdef __cplusplus | |||
| } /* extern "C" */ | |||
| } /* extern "C" */ | |||
| #endif | |||
| #endif /* LV2_URID_H */ | |||
| @@ -152,7 +152,7 @@ typedef struct _LV2_Worker_Schedule { | |||
| } LV2_Worker_Schedule; | |||
| #ifdef __cplusplus | |||
| } /* extern "C" */ | |||
| } /* extern "C" */ | |||
| #endif | |||
| #endif /* LV2_WORKER_H */ | |||
| @@ -42,6 +42,7 @@ DistrhoUI3BandEQ::DistrhoUI3BandEQ() | |||
| fSliderLow = new ImageSlider(this, sliderImage); | |||
| fSliderLow->setStartPos(sliderPosStart); | |||
| fSliderLow->setEndPos(sliderPosEnd); | |||
| fSliderLow->setInverted(true); | |||
| fSliderLow->setRange(-24.0f, 24.0f); | |||
| fSliderLow->setValue(0.0f); | |||
| fSliderLow->setCallback(this); | |||
| @@ -42,6 +42,7 @@ DistrhoUI3BandSplitter::DistrhoUI3BandSplitter() | |||
| fSliderLow = new ImageSlider(this, sliderImage); | |||
| fSliderLow->setStartPos(sliderPosStart); | |||
| fSliderLow->setEndPos(sliderPosEnd); | |||
| fSliderLow->setInverted(true); | |||
| fSliderLow->setRange(-24.0f, 24.0f); | |||
| fSliderLow->setValue(0.0f); | |||
| fSliderLow->setCallback(this); | |||
| @@ -110,9 +110,6 @@ public: | |||
| pthread_mutexattr_t atts; | |||
| pthread_mutexattr_init(&atts); | |||
| pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_RECURSIVE); | |||
| # ifndef CARLA_OS_ANDROID | |||
| pthread_mutexattr_setprotocol(&atts, PTHREAD_PRIO_INHERIT); | |||
| # endif | |||
| pthread_mutex_init(&fMutex, &atts); | |||
| pthread_mutexattr_destroy(&atts); | |||
| #endif | |||
| @@ -182,16 +179,16 @@ private: | |||
| // Helper class to lock&unlock a mutex during a function scope. | |||
| template <class Mutex> | |||
| class CarlaScopedLocker | |||
| class CarlaScopeLocker | |||
| { | |||
| public: | |||
| CarlaScopedLocker(const Mutex& mutex) noexcept | |||
| CarlaScopeLocker(const Mutex& mutex) noexcept | |||
| : fMutex(mutex) | |||
| { | |||
| fMutex.lock(); | |||
| } | |||
| ~CarlaScopedLocker() noexcept | |||
| ~CarlaScopeLocker() noexcept | |||
| { | |||
| fMutex.unlock(); | |||
| } | |||
| @@ -200,23 +197,23 @@ private: | |||
| const Mutex& fMutex; | |||
| CARLA_PREVENT_HEAP_ALLOCATION | |||
| CARLA_DECLARE_NON_COPY_CLASS(CarlaScopedLocker) | |||
| CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeLocker) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| // Helper class to unlock&lock a mutex during a function scope. | |||
| template <class Mutex> | |||
| class CarlaScopedUnlocker | |||
| class CarlaScopeUnlocker | |||
| { | |||
| public: | |||
| CarlaScopedUnlocker(const Mutex& mutex) noexcept | |||
| CarlaScopeUnlocker(const Mutex& mutex) noexcept | |||
| : fMutex(mutex) | |||
| { | |||
| fMutex.unlock(); | |||
| } | |||
| ~CarlaScopedUnlocker() noexcept | |||
| ~CarlaScopeUnlocker() noexcept | |||
| { | |||
| fMutex.lock(); | |||
| } | |||
| @@ -225,17 +222,17 @@ private: | |||
| const Mutex& fMutex; | |||
| CARLA_PREVENT_HEAP_ALLOCATION | |||
| CARLA_DECLARE_NON_COPY_CLASS(CarlaScopedUnlocker) | |||
| CARLA_DECLARE_NON_COPY_CLASS(CarlaScopeUnlocker) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| // Define types | |||
| typedef CarlaScopedLocker<CarlaMutex> CarlaMutexLocker; | |||
| typedef CarlaScopedLocker<CarlaRecursiveMutex> CarlaRecursiveMutexLocker; | |||
| typedef CarlaScopeLocker<CarlaMutex> CarlaMutexLocker; | |||
| typedef CarlaScopeLocker<CarlaRecursiveMutex> CarlaRecursiveMutexLocker; | |||
| typedef CarlaScopedUnlocker<CarlaMutex> CarlaMutexUnlocker; | |||
| typedef CarlaScopedUnlocker<CarlaRecursiveMutex> CarlaRecursiveMutexUnlocker; | |||
| typedef CarlaScopeUnlocker<CarlaMutex> CarlaMutexUnlocker; | |||
| typedef CarlaScopeUnlocker<CarlaRecursiveMutex> CarlaRecursiveMutexUnlocker; | |||
| // ----------------------------------------------------------------------- | |||