diff options
82 files changed, 3190 insertions, 1436 deletions
@@ -18,5 +18,7 @@ bin/ZaMultiCompX2 bin/ZamComp bin/ZamCompX2 bin/ZamEQ2 +bin/ZamGEQ31 +bin/ZamNoise bin/ZamSynth bin/ZamTube diff --git a/libs/dgl/App.hpp b/libs/dgl/App.hpp index 1afac9f..b6fce01 100644 --- a/libs/dgl/App.hpp +++ b/libs/dgl/App.hpp @@ -56,7 +56,8 @@ public: /** Run the application event-loop until all Windows are closed. - @idle() is called at regular intervals. + idle() is called at regular intervals. + @note: This function is meant for standalones only, *never* call this from plugins. */ void exec(); diff --git a/libs/dgl/Color.hpp b/libs/dgl/Color.hpp new file mode 100644 index 0000000..dbe2cd1 --- /dev/null +++ b/libs/dgl/Color.hpp @@ -0,0 +1,99 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_COLOR_HPP_INCLUDED +#define DGL_COLOR_HPP_INCLUDED + +#include "Base.hpp" + +struct NVGcolor; + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +// TODO: create color from "#333" and "#112233" like strings + +/** + A color made from red, green, blue and alpha floating-point values in [0..1] range. +*/ +struct Color { + /** + Direct access to the color values. + */ + union { + float rgba[4]; + struct { float red, green, blue, alpha; }; + }; + + /** + Create black color. + */ + Color() noexcept; + + /** + Create a color from red, green, blue and alpha numeric values. + Values must be in [0..255] range. + */ + Color(const int red, const int green, const int blue, const int alpha = 255) noexcept; + + /** + Create a color from red, green, blue and alpha floating-point values. + Values must in [0..1] range. + */ + Color(const float red, const float green, const float blue, const float alpha = 1.0f) noexcept; + + /** + Create a color by copying another color. + */ + Color(const Color& color) noexcept; + Color& operator=(const Color& color) noexcept; + + /** + Create a color by linearly interpolating two other colors. + */ + Color(const Color& color1, const Color& color2, const float u) noexcept; + + /** + Create a color specified by hue, saturation, lightness and alpha. + HSL values are all in [0..1] range, alpha in [0..255] range. + */ + static Color HSL(const float hue, const float saturation, const float lightness, const int alpha = 255); + + /** + Linearly interpolate this color against another. + */ + void interpolate(const Color& other, const float u) noexcept; + + /** + Check if this color matches another. + */ + bool operator==(const Color& color) noexcept; + bool operator!=(const Color& color) noexcept; + + /** + @internal + Needed for NanoVG compatibility. + */ + Color(const NVGcolor&) noexcept; + operator NVGcolor() const noexcept; +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_COLOR_HPP_INCLUDED diff --git a/libs/dgl/Geometry.hpp b/libs/dgl/Geometry.hpp index 1b0b22e..117c0a9 100644 --- a/libs/dgl/Geometry.hpp +++ b/libs/dgl/Geometry.hpp @@ -42,7 +42,7 @@ public: Point() noexcept; /** - Constructor using custom x and y values. + Constructor using custom X and Y values. */ Point(const T& x, const T& y) noexcept; @@ -91,6 +91,13 @@ public: */ void moveBy(const Point<T>& pos) noexcept; + /** + Return true if point is (0, 0). + */ + bool isZero() const noexcept; + + Point<T> operator+(const Point<T>& pos) noexcept; + Point<T> operator-(const Point<T>& pos) noexcept; Point<T>& operator=(const Point<T>& pos) noexcept; Point<T>& operator+=(const Point<T>& pos) noexcept; Point<T>& operator-=(const Point<T>& pos) noexcept; @@ -167,6 +174,18 @@ public: */ void shrinkBy(const T& divider) noexcept; + /** + Return true if size is null (0x0). + */ + bool isNull() const noexcept; + + /** + Return true if size is not null (0x0). + */ + bool isNotNull() const noexcept; + + Size<T> operator+(const Size<T>& size) noexcept; + Size<T> operator-(const Size<T>& size) noexcept; Size<T>& operator=(const Size<T>& size) noexcept; Size<T>& operator+=(const Size<T>& size) noexcept; Size<T>& operator-=(const Size<T>& size) noexcept; @@ -325,12 +344,12 @@ public: /** Constructor using custom X, Y and size values. */ - Circle(const T& x, const T& y, float size, int numSegments = 300); + Circle(const T& x, const T& y, const float size, const uint numSegments = 300); /** Constructor using custom position and size values. */ - Circle(const Point<T>& pos, float size, int numSegments = 300); + Circle(const Point<T>& pos, const float size, const uint numSegments = 300); /** Constructor using another Circle class values. @@ -379,20 +398,20 @@ public: /** Set size. - @note Must always be > 0.0f + @note Must always be > 0 */ - void setSize(float size) noexcept; + void setSize(const float size) noexcept; /** Get the current number of line segments that make this circle. */ - int getNumSegments() const noexcept; + uint getNumSegments() const noexcept; /** Set the number of line segments that will make this circle. @note Must always be >= 3 */ - void setNumSegments(int num); + void setNumSegments(const uint num); /** Draw this circle using the current OpenGL state. @@ -411,7 +430,7 @@ public: private: Point<T> fPos; float fSize; - int fNumSegments; + uint fNumSegments; // cached values float fTheta, fCos, fSin; @@ -594,6 +613,16 @@ public: void shrinkBy(const T& divider) noexcept; /** + Set rectangle using @a pos and @a size. + */ + void setRectangle(const Point<T>& pos, const Size<T>& size) noexcept; + + /** + Set rectangle. + */ + void setRectangle(const Rectangle<T>& rect) noexcept; + + /** Check if this rectangle contains the point defined by @a X and @a Y. */ bool contains(const T& x, const T& y) const noexcept; diff --git a/libs/dgl/Image.hpp b/libs/dgl/Image.hpp index cf8d1e5..ab0e648 100644 --- a/libs/dgl/Image.hpp +++ b/libs/dgl/Image.hpp @@ -45,15 +45,15 @@ public: /** Constructor using raw image data. - @note @a rawData must remain valid for the lifetime of this Image. + @note: @a rawData must remain valid for the lifetime of this Image. */ - Image(const char* rawData, int width, int height, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE); + Image(const char* const rawData, const uint width, const uint height, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE); /** Constructor using raw image data. - @note @a rawData must remain valid for the lifetime of this Image. + @note: @a rawData must remain valid for the lifetime of this Image. */ - Image(const char* rawData, const Size<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE); + Image(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE); /** Constructor using another image data. @@ -67,15 +67,15 @@ public: /** Load image data from memory. - @note @a rawData must remain valid for the lifetime of this Image. + @note: @a rawData must remain valid for the lifetime of this Image. */ - void loadFromMemory(const char* rawData, int width, int height, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; + void loadFromMemory(const char* const rawData, const uint width, const uint height, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE) noexcept; /** Load image data from memory. - @note @a rawData must remain valid for the lifetime of this Image. + @note: @a rawData must remain valid for the lifetime of this Image. */ - void loadFromMemory(const char* rawData, const Size<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; + void loadFromMemory(const char* const rawData, const Size<uint>& size, const GLenum format = GL_BGRA, const GLenum type = GL_UNSIGNED_BYTE) noexcept; /** Check if this image is valid. @@ -85,17 +85,17 @@ public: /** Get width. */ - int getWidth() const noexcept; + uint getWidth() const noexcept; /** Get height. */ - int getHeight() const noexcept; + uint getHeight() const noexcept; /** Get size. */ - const Size<int>& getSize() const noexcept; + const Size<uint>& getSize() const noexcept; /** Get the raw image data. @@ -120,7 +120,7 @@ public: /** Draw this image at (x, y) point. */ - void drawAt(int x, int y); + void drawAt(const int x, const int y); /** Draw this image at position @a pos. @@ -133,7 +133,7 @@ public: private: const char* fRawData; - Size<int> fSize; + Size<uint> fSize; GLenum fFormat; GLenum fType; GLuint fTextureId; diff --git a/libs/dgl/ImageAboutWindow.hpp b/libs/dgl/ImageAboutWindow.hpp index 3824064..5a72ea2 100644 --- a/libs/dgl/ImageAboutWindow.hpp +++ b/libs/dgl/ImageAboutWindow.hpp @@ -38,7 +38,7 @@ protected: void onDisplay() override; bool onKeyboard(const KeyboardEvent&) override; bool onMouse(const MouseEvent&) override; - void onReshape(int width, int height) override; + void onReshape(uint width, uint height) override; private: Image fImgBackground; diff --git a/libs/dgl/ImageButton.hpp b/libs/dgl/ImageButton.hpp index f022d9b..a400961 100644 --- a/libs/dgl/ImageButton.hpp +++ b/libs/dgl/ImageButton.hpp @@ -39,6 +39,7 @@ public: explicit ImageButton(Widget* widget, const Image& image) noexcept; explicit ImageButton(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept; explicit ImageButton(const ImageButton& imageButton) noexcept; + ImageButton& operator=(const ImageButton& imageButton) noexcept; void setCallback(Callback* callback) noexcept; diff --git a/libs/dgl/ImageKnob.hpp b/libs/dgl/ImageKnob.hpp index 3208763..3563824 100644 --- a/libs/dgl/ImageKnob.hpp +++ b/libs/dgl/ImageKnob.hpp @@ -44,6 +44,7 @@ public: explicit ImageKnob(Window& parent, const Image& image, Orientation orientation = Vertical, int id = 0) noexcept; explicit ImageKnob(Widget* widget, const Image& image, Orientation orientation = Vertical, int id = 0) noexcept; explicit ImageKnob(const ImageKnob& imageKnob); + ImageKnob& operator=(const ImageKnob& imageKnob); ~ImageKnob() override; int getId() const noexcept; diff --git a/libs/dgl/ImageSlider.hpp b/libs/dgl/ImageSlider.hpp index d53edde..613b25c 100644 --- a/libs/dgl/ImageSlider.hpp +++ b/libs/dgl/ImageSlider.hpp @@ -39,6 +39,7 @@ public: explicit ImageSlider(Window& parent, const Image& image, int id = 0) noexcept; explicit ImageSlider(Widget* widget, const Image& image, int id = 0) noexcept; explicit ImageSlider(const ImageSlider& imageSlider) noexcept; + ImageSlider& operator=(const ImageSlider& imageSlider) noexcept; int getId() const noexcept; void setId(int id) noexcept; diff --git a/libs/dgl/ImageSwitch.hpp b/libs/dgl/ImageSwitch.hpp index 7f301b7..bb963ac 100644 --- a/libs/dgl/ImageSwitch.hpp +++ b/libs/dgl/ImageSwitch.hpp @@ -37,6 +37,7 @@ public: explicit ImageSwitch(Window& parent, const Image& imageNormal, const Image& imageDown, int id = 0) noexcept; explicit ImageSwitch(Widget* widget, const Image& imageNormal, const Image& imageDown, int id = 0) noexcept; explicit ImageSwitch(const ImageSwitch& imageSwitch) noexcept; + ImageSwitch& operator=(const ImageSwitch& imageSwitch) noexcept; int getId() const noexcept; void setId(int id) noexcept; diff --git a/libs/dgl/NanoVG.hpp b/libs/dgl/NanoVG.hpp index 8d6642b..32d467d 100644 --- a/libs/dgl/NanoVG.hpp +++ b/libs/dgl/NanoVG.hpp @@ -17,9 +17,9 @@ #ifndef DGL_NANO_WIDGET_HPP_INCLUDED #define DGL_NANO_WIDGET_HPP_INCLUDED +#include "Color.hpp" #include "Widget.hpp" -struct NVGcolor; struct NVGcontext; struct NVGpaint; @@ -45,25 +45,28 @@ public: /** Get size. */ - Size<int> getSize() const; + Size<uint> getSize() const noexcept; /** Update image data. */ - void updateImage(const uchar* data); + void updateImage(const uchar* const data); protected: /** Constructors are protected. NanoImages must be created within a NanoVG or NanoWidget class. */ - NanoImage(NVGcontext* context, int imageId) noexcept; + NanoImage(NVGcontext* const context, const int imageId) noexcept; private: NVGcontext* fContext; int fImageId; + Size<uint> fSize; friend class NanoVG; + void _updateSize(); + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoImage) }; @@ -74,10 +77,7 @@ private: NanoVG class. This class exposes the NanoVG drawing API. - All calls should be wrapped in beginFrame() & endFrame(). - - @section Color utils - Colors in NanoVG are stored as uints in ABGR format. + All calls should be wrapped in beginFrame() and endFrame(). @section State Handling NanoVG contains state which represents how paths will be rendered. @@ -153,13 +153,13 @@ private: since aforementioned pixel snapping. While this may sound a little odd, the setup allows you to always render the - same way regardless of scaling. I.e. following works regardless of scaling: + same way regardless of scaling. i.e. following works regardless of scaling: @code const char* txt = "Text me up."; textBounds(vg, x,y, txt, NULL, bounds); beginPath(vg); - roundedRect(vg, bounds[0],bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]); + roundedRect(vg, bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]); fill(vg); @endcode @@ -182,7 +182,7 @@ public: enum Alpha { STRAIGHT_ALPHA, - PREMULTIPLIED_ALPHA, + PREMULTIPLIED_ALPHA }; enum LineCap { @@ -209,17 +209,6 @@ public: CW = 2 // Winding for holes }; - struct Color { - union { - float rgba[4]; - struct { float r,g,b,a; }; - }; - - Color() noexcept; - Color(const NVGcolor&) noexcept; - operator NVGcolor() const noexcept; - }; - struct Paint { float xform[6]; float extent[2]; @@ -231,6 +220,10 @@ public: PatternRepeat repeat; Paint() noexcept; + + /** + @internal + */ Paint(const NVGpaint&) noexcept; operator NVGpaint() const noexcept; }; @@ -260,7 +253,7 @@ public: /** Constructor using custom text atlas size. */ - NanoVG(int textAtlasWidth, int textAtlasHeight); + NanoVG(const int textAtlasWidth, const int textAtlasHeight); /** Destructor. @@ -280,12 +273,12 @@ public: Begin drawing a new frame. @param withAlha Controls if drawing the shapes to the render target should be done using straight or pre-multiplied alpha. */ - void beginFrame(int width, int height, float scaleFactor = 1.0f, Alpha alpha = PREMULTIPLIED_ALPHA); + void beginFrame(const uint width, const uint height, const float scaleFactor = 1.0f, const Alpha alpha = PREMULTIPLIED_ALPHA); /** Begin drawing a new frame inside a widget. */ - void beginFrame(Widget* widget); + void beginFrame(Widget* const widget); /** Ends drawing flushing remaining render state. @@ -293,46 +286,6 @@ public: void endFrame(); /* -------------------------------------------------------------------- - * Color utils */ - - /** - Returns a color value from red, green, blue values. Alpha will be set to 255 (1.0f). - */ - static Color RGB(uchar r, uchar g, uchar b); - - /** - Returns a color value from red, green, blue values. Alpha will be set to 1.0f. - */ - static Color RGBf(float r, float g, float b); - - /** - Returns a color value from red, green, blue and alpha values. - */ - static Color RGBA(uchar r, uchar g, uchar b, uchar a); - - /** - Returns a color value from red, green, blue and alpha values. - */ - static Color RGBAf(float r, float g, float b, float a); - - /** - Linearly interpolates from color c0 to c1, and returns resulting color value. - */ - static Color lerpRGBA(const Color& c0, const Color& c1, float u); - - /** - Returns color value specified by hue, saturation and lightness. - HSL values are all in range [0..1], alpha will be set to 255. - */ - static Color HSL(float h, float s, float l); - - /** - Returns color value specified by hue, saturation and lightness and alpha. - HSL values are all in range [0..1], alpha in range [0..255] - */ - static Color HSLA(float h, float s, float l, uchar a); - - /* -------------------------------------------------------------------- * State Handling */ /** @@ -360,6 +313,18 @@ public: void strokeColor(const Color& color); /** + Sets current stroke style to a solid color, made from red, green, blue and alpha numeric values. + Values must be in [0..255] range. + */ + void strokeColor(const int red, const int green, const int blue, const int alpha = 255); + + /** + Sets current stroke style to a solid color, made from red, green, blue and alpha numeric values. + Values must in [0..1] range. + */ + void strokeColor(const float red, const float green, const float blue, const float alpha = 1.0f); + + /** Sets current stroke style to a paint, which can be a one of the gradients or a pattern. */ void strokePaint(const Paint& paint); @@ -370,6 +335,18 @@ public: void fillColor(const Color& color); /** + Sets current fill style to a solid color, made from red, green, blue and alpha numeric values. + Values must be in [0..255] range. + */ + void fillColor(const int red, const int green, const int blue, const int alpha = 255); + + /** + Sets current fill style to a solid color, made from red, green, blue and alpha numeric values. + Values must in [0..1] range. + */ + void fillColor(const float red, const float green, const float blue, const float alpha = 1.0f); + + /** Sets current fill style to a paint, which can be a one of the gradients or a pattern. */ void fillPaint(const Paint& paint); @@ -457,7 +434,7 @@ public: static void transformIdentity(float dst[6]); /** - Sets the transform to translation matrix matrix. + Sets the transform to translation matrix */ static void transformTranslate(float dst[6], float tx, float ty); @@ -528,7 +505,7 @@ public: /** Creates image from specified image data. */ - NanoImage* createImageRGBA(int w, int h, const uchar* data); + NanoImage* createImageRGBA(uint w, uint h, const uchar* data); /* -------------------------------------------------------------------- * Paints */ @@ -760,6 +737,7 @@ public: private: NVGcontext* const fContext; + bool fInFrame; DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoVG) }; @@ -798,7 +776,7 @@ protected: private: /** Widget display function. - Implemented internally to wrap begin/endFrame() automaticaly. + Implemented internally to wrap begin/endFrame() automatically. */ void onDisplay() override { diff --git a/libs/dgl/StandaloneWindow.hpp b/libs/dgl/StandaloneWindow.hpp index 05a7185..b4087f9 100644 --- a/libs/dgl/StandaloneWindow.hpp +++ b/libs/dgl/StandaloneWindow.hpp @@ -41,7 +41,7 @@ public: } protected: - void onReshape(int width, int height) override + void onReshape(uint width, uint height) override { if (fWidget != nullptr) fWidget->setSize(width, height); diff --git a/libs/dgl/Widget.hpp b/libs/dgl/Widget.hpp index 74b4f80..86c42d4 100644 --- a/libs/dgl/Widget.hpp +++ b/libs/dgl/Widget.hpp @@ -52,8 +52,8 @@ class Widget public: /** Base event data. - @param mod The currently active modifiers. - @param time The timestamp (if any) of the currently-processing event. + @a mod The currently active modifiers. + @a time The timestamp (if any) of the currently-processing event. */ struct BaseEvent { Modifier mod; @@ -62,8 +62,8 @@ public: /** Keyboard event. - @param press True if the key was pressed, false if released. - @param key Unicode point of the key pressed. + @a press True if the key was pressed, false if released. + @a key Unicode point of the key pressed. @see onKeyboard */ struct KeyboardEvent : BaseEvent { @@ -73,8 +73,8 @@ public: /** Special keyboard event. - @param press True if the key was pressed, false if released. - @param key The key pressed. + @a press True if the key was pressed, false if released. + @a key The key pressed. @see onSpecial */ struct SpecialEvent : BaseEvent { @@ -84,9 +84,9 @@ public: /** Mouse event. - @param button The button number (1 = left, 2 = middle, 3 = right). - @param press True if the key was pressed, false if released. - @param pos The widget-relative coordinates of the pointer. + @a button The button number (1 = left, 2 = middle, 3 = right). + @a press True if the key was pressed, false if released. + @a pos The widget-relative coordinates of the pointer. @see onMouse */ struct MouseEvent : BaseEvent { @@ -97,7 +97,7 @@ public: /** Mouse motion event. - @param pos The widget-relative coordinates of the pointer. + @a pos The widget-relative coordinates of the pointer. @see onMotion */ struct MotionEvent : BaseEvent { @@ -106,8 +106,8 @@ public: /** Mouse scroll event. - @param pos The widget-relative coordinates of the pointer. - @param delta The scroll distance. + @a pos The widget-relative coordinates of the pointer. + @a delta The scroll distance. @see onScroll */ struct ScrollEvent : BaseEvent { @@ -117,13 +117,13 @@ public: /** Resize event. - @param size The new widget size. - @param oldSize The previous size, may be null. + @a size The new widget size. + @a oldSize The previous size, may be null. @see onResize */ struct ResizeEvent { - Size<int> size; - Size<int> oldSize; + Size<uint> size; + Size<uint> oldSize; }; /** @@ -162,37 +162,37 @@ public: /** Get width. */ - int getWidth() const noexcept; + uint getWidth() const noexcept; /** Get height. */ - int getHeight() const noexcept; + uint getHeight() const noexcept; /** Get size. */ - const Size<int>& getSize() const noexcept; + const Size<uint>& getSize() const noexcept; /** Set width. */ - virtual void setWidth(int width) noexcept; + virtual void setWidth(uint width) noexcept; /** Set height. */ - virtual void setHeight(int height) noexcept; + virtual void setHeight(uint height) noexcept; /** Set size using @a width and @a height values. */ - virtual void setSize(int width, int height) noexcept; + virtual void setSize(uint width, uint height) noexcept; /** Set size. */ - virtual void setSize(const Size<int>& size) noexcept; + virtual void setSize(const Size<uint>& size) noexcept; /** Get absolute X. @@ -241,7 +241,7 @@ public: Window& getParentWindow() const noexcept; /** - Check if this widget contains the point defined by @a X and @a Y. + Check if this widget contains the point defined by @a x and @a y. */ bool contains(int x, int y) const noexcept; @@ -306,7 +306,7 @@ protected: /** Tell the parent window this widget needs scaling. - When enabled, the widget viewport is scaled to match width&height. + When enabled, the widget viewport is scaled to match width and height. @note: This is an internal function; You do not need it under normal circumstances. */ @@ -317,7 +317,8 @@ private: bool fNeedsFullViewport; bool fNeedsScaling; bool fVisible; - Rectangle<int> fArea; + Point<int> fAbsolutePos; + Size<uint> fSize; friend class CairoWidget; friend class Window; diff --git a/libs/dgl/Window.hpp b/libs/dgl/Window.hpp index f52c141..89e91de 100644 --- a/libs/dgl/Window.hpp +++ b/libs/dgl/Window.hpp @@ -48,8 +48,8 @@ public: bool isResizable() const noexcept; void setResizable(bool yesNo); - int getWidth() const noexcept; - int getHeight() const noexcept; + uint getWidth() const noexcept; + uint getHeight() const noexcept; Size<uint> getSize() const noexcept; void setSize(uint width, uint height); void setSize(Size<uint> size); @@ -67,7 +67,7 @@ public: protected: virtual void onDisplayBefore(); virtual void onDisplayAfter(); - virtual void onReshape(int width, int height); + virtual void onReshape(uint width, uint height); virtual void onClose(); private: diff --git a/libs/dgl/ntk/NtkApp.hpp b/libs/dgl/ntk/NtkApp.hpp new file mode 100644 index 0000000..5dc7b2d --- /dev/null +++ b/libs/dgl/ntk/NtkApp.hpp @@ -0,0 +1,160 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_NTK_APP_HPP_INCLUDED +#define DGL_NTK_APP_HPP_INCLUDED + +#include "../Base.hpp" + +#ifdef override +# define override_defined +# undef override +#endif + +#include <list> +#include <FL/Fl.H> +#include <FL/Fl_Double_Window.H> +#include <FL/Fl_Shared_Image.H> +#include <FL/x.H> + +#ifdef override_defined +# define override +# undef override_defined +#endif + +START_NAMESPACE_DGL + +class NtkWindow; + +// ----------------------------------------------------------------------- + +/** + DGL compatible App class that uses NTK instead of OpenGL. + @see App + */ +class NtkApp +{ +public: + /** + Constructor. + */ + NtkApp() + : fIsRunning(true), + fWindows() + { + static bool initialized = false; + + if (! initialized) + { + initialized = true; + fl_register_images(); +#ifdef DISTRHO_OS_LINUX + fl_open_display(); +#endif + } + } + + /** + Destructor. + */ + ~NtkApp() + { + DISTRHO_SAFE_ASSERT(! fIsRunning); + + fWindows.clear(); + } + + /** + Idle function. + This calls the NTK event-loop once (and all idle callbacks). + */ + void idle() + { + Fl::check(); + Fl::flush(); + } + + /** + Run the application event-loop until all Windows are closed. + @note: This function is meant for standalones only, *never* call this from plugins. + */ + void exec() + { + fIsRunning = true; + Fl::run(); + fIsRunning = false; + } + + /** + Quit the application. + This stops the event-loop and closes all Windows. + */ + void quit() + { + fIsRunning = false; + + for (std::list<Fl_Double_Window*>::reverse_iterator rit = fWindows.rbegin(), rite = fWindows.rend(); rit != rite; ++rit) + { + Fl_Double_Window* const window(*rit); + window->hide(); + } + } + + /** + Check if the application is about to quit. + Returning true means there's no event-loop running at the moment. + */ + bool isQuiting() const noexcept + { + return !fIsRunning; + } + +private: + bool fIsRunning; + std::list<Fl_Double_Window*> fWindows; + + friend class NtkWindow; + + /** @internal used by NtkWindow. */ + void addWindow(Fl_Double_Window* const window) + { + DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,); + + if (fWindows.size() == 0) + fIsRunning = true; + + fWindows.push_back(window); + } + + /** @internal used by NtkWindow. */ + void removeWindow(Fl_Double_Window* const window) + { + DISTRHO_SAFE_ASSERT_RETURN(window != nullptr,); + + fWindows.remove(window); + + if (fWindows.size() == 0) + fIsRunning = false; + } + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NtkApp) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_NTK_APP_HPP_INCLUDED diff --git a/libs/dgl/ntk/NtkWidget.hpp b/libs/dgl/ntk/NtkWidget.hpp new file mode 100644 index 0000000..2247be3 --- /dev/null +++ b/libs/dgl/ntk/NtkWidget.hpp @@ -0,0 +1,202 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_NTK_WIDGET_HPP_INCLUDED +#define DGL_NTK_WIDGET_HPP_INCLUDED + +#include "NtkWindow.hpp" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +/** + DGL compatible Widget class that uses NTK instead of OpenGL. + @see Widget + */ +class NtkWidget : public Fl_Double_Window +{ +public: + /** + Constructor. + */ + explicit NtkWidget(NtkWindow& parent) + : Fl_Double_Window(100, 100), + fParent(parent) + { + fParent.add(this); + show(); + } + + /** + Destructor. + */ + ~NtkWidget() override + { + hide(); + fParent.remove(this); + } + + /** + Check if this widget is visible within its parent window. + Invisible widgets do not receive events except resize. + */ + bool isVisible() const + { + return visible(); + } + + /** + Set widget visible (or not) according to @a yesNo. + */ + void setVisible(bool yesNo) + { + if (yesNo) + show(); + else + hide(); + } + + /** + Get width. + */ + int getWidth() const + { + return w(); + } + + /** + Get height. + */ + int getHeight() const + { + return h(); + } + + /** + Set width. + */ + void setWidth(int width) + { + resize(x(), y(), width, h()); + } + + /** + Set height. + */ + void setHeight(int height) + { + resize(x(), y(), w(), height); + } + + /** + Set size using @a width and @a height values. + */ + void setSize(int width, int height) + { + resize(x(), y(), width, height); + } + + /** + Get absolute X. + */ + int getAbsoluteX() const + { + return x(); + } + + /** + Get absolute Y. + */ + int getAbsoluteY() const + { + return y(); + } + + /** + Set absolute X. + */ + void setAbsoluteX(int x) + { + resize(x, y(), w(), h()); + } + + /** + Set absolute Y. + */ + void setAbsoluteY(int y) + { + resize(x(), y, w(), h()); + } + + /** + Set absolute position using @a x and @a y values. + */ + void setAbsolutePos(int x, int y) + { + resize(x, y, w(), h()); + } + + /** + Get this widget's window application. + Same as calling getParentWindow().getApp(). + */ + NtkApp& getParentApp() const noexcept + { + return fParent.getApp(); + } + + /** + Get parent window, as passed in the constructor. + */ + NtkWindow& getParentWindow() const noexcept + { + return fParent; + } + + /** + Check if this widget contains the point defined by @a x and @a y. + */ + bool contains(int x, int y) const + { + return (x >= 0 && y >= 0 && x < w() && y < h()); + } + + /** + Tell this widget's window to repaint itself. + */ + void repaint() + { + redraw(); + } + +protected: + /** @internal used for DGL compatibility. */ + void setNeedsFullViewport(bool) noexcept {} + /** @internal used for DGL compatibility. */ + void setNeedsScaling(bool) noexcept {} + +private: + NtkWindow& fParent; + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NtkWidget) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_NTK_WIDGET_HPP_INCLUDED diff --git a/libs/dgl/ntk/NtkWindow.hpp b/libs/dgl/ntk/NtkWindow.hpp new file mode 100644 index 0000000..47e9f10 --- /dev/null +++ b/libs/dgl/ntk/NtkWindow.hpp @@ -0,0 +1,215 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DGL_NTK_WINDOW_HPP_INCLUDED +#define DGL_NTK_WINDOW_HPP_INCLUDED + +#include "NtkApp.hpp" + +START_NAMESPACE_DGL + +class NtkWidget; + +// ----------------------------------------------------------------------- + +class NtkWindow : public Fl_Double_Window +{ +public: + explicit NtkWindow(NtkApp& app) + : Fl_Double_Window(100, 100), + fApp(app), + fIsVisible(false), + fUsingEmbed(false), + fParent(nullptr) {} + + explicit NtkWindow(NtkApp& app, NtkWindow& parent) + : Fl_Double_Window(100, 100), + fApp(app), + fIsVisible(false), + fUsingEmbed(false), + fParent(&parent) {} + + explicit NtkWindow(NtkApp& app, intptr_t parentId) + : Fl_Double_Window(100, 100), + fApp(app), + fIsVisible(parentId != 0), + fUsingEmbed(parentId != 0), + fParent(nullptr) + { + if (fUsingEmbed) + { + fl_embed(this, (Window)parentId); + Fl_Double_Window::show(); + fApp.addWindow(this); + } + } + + ~NtkWindow() override + { + if (fUsingEmbed) + { + fApp.removeWindow(this); + Fl_Double_Window::hide(); + } + } + + void show() override + { + if (fUsingEmbed || fIsVisible) + return; + + Fl_Double_Window::show(); + fApp.addWindow(this); + fIsVisible = true; + + if (fParent != nullptr) + setTransientWinId((intptr_t)fl_xid(fParent)); + } + + void hide() override + { + if (fUsingEmbed || ! fIsVisible) + return; + + fIsVisible = false; + fApp.removeWindow(this); + Fl_Double_Window::hide(); + } + + void close() + { + hide(); + } + + bool isVisible() const + { + return visible(); + } + + void setVisible(bool yesNo) + { + if (yesNo) + show(); + else + hide(); + } + + bool isResizable() const + { + // TODO + return false; + } + + void setResizable(bool /*yesNo*/) + { + // TODO + } + + int getWidth() const noexcept + { + return w(); + } + + int getHeight() const noexcept + { + return h(); + } + + void setSize(uint width, uint height) + { + resize(x(), y(), width, height); + } + + void setTitle(const char* title) + { + label(title); + } + + void setTransientWinId(intptr_t winId) + { + DISTRHO_SAFE_ASSERT_RETURN(winId != 0,); + +#ifdef DISTRHO_OS_LINUX + DISTRHO_SAFE_ASSERT_RETURN(fl_display != nullptr,); + + const ::Window ourWindow(fl_xid(this)); + DISTRHO_SAFE_ASSERT_RETURN(ourWindow != 0,); + + XSetTransientForHint(fl_display, ourWindow, winId); +#endif + } + + NtkApp& getApp() const noexcept + { + return fApp; + } + + intptr_t getWindowId() const + { + return (intptr_t)fl_xid(this); + } + + void addIdleCallback(IdleCallback* const callback) + { + DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,); + + if (fIdleCallbacks.size() == 0) + Fl::add_idle(_idleHandler, this); + + fIdleCallbacks.push_back(callback); + } + + void removeIdleCallback(IdleCallback* const callback) + { + DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,); + + fIdleCallbacks.remove(callback); + + if (fIdleCallbacks.size() == 0) + Fl::remove_idle(_idleHandler, this); + } + +private: + NtkApp& fApp; + bool fIsVisible; + bool fUsingEmbed; + + // transient parent, may be null + NtkWindow* const fParent; + + std::list<IdleCallback*> fIdleCallbacks; + + friend class NtkWidget; + + static void _idleHandler(void* data) + { + NtkWindow* const self((NtkWindow*)data); + + for (std::list<IdleCallback*>::iterator it=self->fIdleCallbacks.begin(), ite=self->fIdleCallbacks.end(); it != ite; ++it) + { + IdleCallback* const idleCallback(*it); + idleCallback->idleCallback(); + } + } + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NtkWindow) +}; + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#endif // DGL_NTK_WINDOW_HPP_INCLUDED diff --git a/libs/dgl/src/App.cpp b/libs/dgl/src/App.cpp index 754e44e..b0467ca 100644 --- a/libs/dgl/src/App.cpp +++ b/libs/dgl/src/App.cpp @@ -22,9 +22,8 @@ START_NAMESPACE_DGL // ----------------------------------------------------------------------- App::App() - : pData(new PrivateData()) -{ -} + : pData(new PrivateData()), + leakDetector_App() {} App::~App() { diff --git a/libs/dgl/src/AppPrivateData.hpp b/libs/dgl/src/AppPrivateData.hpp index 05f7003..c668968 100644 --- a/libs/dgl/src/AppPrivateData.hpp +++ b/libs/dgl/src/AppPrivateData.hpp @@ -33,8 +33,10 @@ struct App::PrivateData { std::list<IdleCallback*> idleCallbacks; PrivateData() - : doLoop(false), - visibleWindows(0) {} + : doLoop(true), + visibleWindows(0), + windows(), + idleCallbacks() {} ~PrivateData() { @@ -58,6 +60,8 @@ struct App::PrivateData { if (--visibleWindows == 0) doLoop = false; } + + DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData) }; // ----------------------------------------------------------------------- diff --git a/libs/dgl/src/Color.cpp b/libs/dgl/src/Color.cpp new file mode 100644 index 0000000..46b7ad3 --- /dev/null +++ b/libs/dgl/src/Color.cpp @@ -0,0 +1,93 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../Color.hpp" + +#include "nanovg/nanovg.h" + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +Color::Color() noexcept + : red(1.0f), green(1.0f), blue(1.0f), alpha(1.0f) {} + +Color::Color(const int r, const int g, const int b, const int a) noexcept + : red(static_cast<float>(r)/255.0f), green(static_cast<float>(g)/255.0f), blue(static_cast<float>(b)/255.0f), alpha(static_cast<float>(a)/255.0f) {} + +Color::Color(const float r, const float g, const float b, const float a) noexcept + : red(r), green(g), blue(b), alpha(a) {} + +Color::Color(const Color& color) noexcept + : red(color.red), green(color.green), blue(color.blue), alpha(color.alpha) {} + +Color::Color(const Color& color1, const Color& color2, const float u) noexcept + : red(color1.red), green(color1.green), blue(color1.blue), alpha(color1.alpha) +{ + interpolate(color2, u); +} + +void Color::interpolate(const Color& other, const float u) noexcept +{ + const float u2 = (u < 0.0f) ? 0.0f : ((u > 1.0f) ? 1.0f : u); + const float oneMinusU = 1.0f - u; + + red = red * oneMinusU + other.red * u2; + green = green * oneMinusU + other.green * u2; + blue = blue * oneMinusU + other.blue * u2; + alpha = alpha * oneMinusU + other.alpha * u2; +} + +Color Color::HSL(const float hue, const float saturation, const float lightness, const int alpha) +{ + return nvgHSLA(hue, saturation, lightness, alpha); +} + +Color::Color(const NVGcolor& c) noexcept + : red(c.r), green(c.g), blue(c.b), alpha(c.a) {} + +Color::operator NVGcolor() const noexcept +{ + NVGcolor nc; + nc.r = red; + nc.g = green; + nc.b = blue; + nc.a = alpha; + return nc; +} + +Color& Color::operator=(const Color& color) noexcept +{ + red = color.red; + green = color.green; + blue = color.blue; + alpha = color.alpha; + return *this; +} + +bool Color::operator==(const Color& color) noexcept +{ + return (red == color.red && green == color.green && blue == color.blue && alpha == color.alpha); +} + +bool Color::operator!=(const Color& color) noexcept +{ + return (red != color.red || green != color.green || blue != color.blue || alpha != color.alpha); +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL diff --git a/libs/dgl/src/Geometry.cpp b/libs/dgl/src/Geometry.cpp index 3f90858..4dc7e43 100644 --- a/libs/dgl/src/Geometry.cpp +++ b/libs/dgl/src/Geometry.cpp @@ -16,10 +16,10 @@ #include "../Geometry.hpp" -#include <cmath> - START_NAMESPACE_DGL +static const float M_2PIf = 3.14159265358979323846f*2.0f; + // ----------------------------------------------------------------------- // Point @@ -79,15 +79,33 @@ void Point<T>::setPos(const Point<T>& pos) noexcept template<typename T> void Point<T>::moveBy(const T& x, const T& y) noexcept { - fX += x; - fY += y; + fX = static_cast<T>(fX+x); + fY = static_cast<T>(fY+y); } template<typename T> void Point<T>::moveBy(const Point<T>& pos) noexcept { - fX += pos.fX; - fY += pos.fY; + fX = static_cast<T>(fX+pos.fX); + fY = static_cast<T>(fY+pos.fY); +} + +template<typename T> +bool Point<T>::isZero() const noexcept +{ + return fX == 0 && fY == 0; +} + +template<typename T> +Point<T> Point<T>::operator+(const Point<T>& pos) noexcept +{ + return Point<T>(fX+pos.fX, fY+pos.fY); +} + +template<typename T> +Point<T> Point<T>::operator-(const Point<T>& pos) noexcept +{ + return Point<T>(fX-pos.fX, fY-pos.fY); } template<typename T> @@ -101,29 +119,29 @@ Point<T>& Point<T>::operator=(const Point<T>& pos) noexcept template<typename T> Point<T>& Point<T>::operator+=(const Point<T>& pos) noexcept { - fX += pos.fX; - fY += pos.fY; + fX = static_cast<T>(fX+pos.fX); + fY = static_cast<T>(fY+pos.fY); return *this; } template<typename T> Point<T>& Point<T>::operator-=(const Point<T>& pos) noexcept { - fX -= pos.fX; - fY -= pos.fY; + fX = static_cast<T>(fX-pos.fX); + fY = static_cast<T>(fY-pos.fY); return *this; } template<typename T> bool Point<T>::operator==(const Point<T>& pos) const noexcept { - return (fX == pos.fX && fY== pos.fY); + return (fX == pos.fX && fY == pos.fY); } template<typename T> bool Point<T>::operator!=(const Point<T>& pos) const noexcept { - return !operator==(pos); + return (fX != pos.fX || fY != pos.fY); } // ----------------------------------------------------------------------- @@ -185,15 +203,40 @@ void Size<T>::setSize(const Size<T>& size) noexcept template<typename T> void Size<T>::growBy(const T& multiplier) noexcept { - fWidth *= multiplier; - fHeight *= multiplier; + fWidth = static_cast<T>(fWidth*multiplier); + fHeight = static_cast<T>(fHeight*multiplier); } template<typename T> void Size<T>::shrinkBy(const T& divider) noexcept { - fWidth /= divider; - fHeight /= divider; + fWidth = static_cast<T>(fWidth/divider); + fHeight = static_cast<T>(fHeight/divider); +} + +template<typename T> +bool Size<T>::isNull() const noexcept +{ + return fWidth == 0 && fHeight == 0; +} + +template<typename T> +bool Size<T>::isNotNull() const noexcept +{ + return fWidth != 0 || fHeight != 0; +} + + +template<typename T> +Size<T> Size<T>::operator+(const Size<T>& size) noexcept +{ + return Size<T>(fWidth+size.fWidth, fHeight+size.fHeight); +} + +template<typename T> +Size<T> Size<T>::operator-(const Size<T>& size) noexcept +{ + return Size<T>(fWidth-size.fWidth, fHeight-size.fHeight); } template<typename T> @@ -207,32 +250,32 @@ Size<T>& Size<T>::operator=(const Size<T>& size) noexcept template<typename T> Size<T>& Size<T>::operator+=(const Size<T>& size) noexcept { - fWidth += size.fWidth; - fHeight += size.fHeight; + fWidth = static_cast<T>(fWidth+size.fWidth); + fHeight = static_cast<T>(fHeight+size.fHeight); return *this; } template<typename T> Size<T>& Size<T>::operator-=(const Size<T>& size) noexcept { - fWidth -= size.fWidth; - fHeight -= size.fHeight; + fWidth = static_cast<T>(fWidth-size.fWidth); + fHeight = static_cast<T>(fHeight-size.fHeight); return *this; } template<typename T> Size<T>& Size<T>::operator*=(const T& m) noexcept { - fWidth *= m; - fHeight *= m; + fWidth = static_cast<T>(fWidth*m); + fHeight = static_cast<T>(fHeight*m); return *this; } template<typename T> Size<T>& Size<T>::operator/=(const T& d) noexcept { - fWidth /= d; - fHeight /= d; + fWidth = static_cast<T>(fWidth/d); + fHeight = static_cast<T>(fHeight/d); return *this; } @@ -245,7 +288,7 @@ bool Size<T>::operator==(const Size<T>& size) const noexcept template<typename T> bool Size<T>::operator!=(const Size<T>& size) const noexcept { - return !operator==(size); + return (fWidth != size.fWidth || fHeight != size.fHeight); } // ----------------------------------------------------------------------- @@ -368,17 +411,15 @@ void Line<T>::setEndPos(const Point<T>& pos) noexcept template<typename T> void Line<T>::moveBy(const T& x, const T& y) noexcept { - fPosStart.fX += x; - fPosStart.fY += y; - fPosEnd.fX += x; - fPosEnd.fY += y; + fPosStart.moveBy(x, y); + fPosEnd.moveBy(x, y); } template<typename T> void Line<T>::moveBy(const Point<T>& pos) noexcept { - fPosStart += pos; - fPosEnd += pos; + fPosStart.moveBy(pos); + fPosEnd.moveBy(pos); } template<typename T> @@ -411,7 +452,7 @@ bool Line<T>::operator==(const Line<T>& line) const noexcept template<typename T> bool Line<T>::operator!=(const Line<T>& line) const noexcept { - return !operator==(line); + return (fPosStart != line.fPosStart || fPosEnd != line.fPosEnd); } // ----------------------------------------------------------------------- @@ -424,16 +465,14 @@ Circle<T>::Circle() noexcept fNumSegments(0), fTheta(0.0f), fCos(0.0f), - fSin(0.0f) -{ -} + fSin(0.0f) {} template<typename T> -Circle<T>::Circle(const T& x, const T& y, float size, int numSegments) +Circle<T>::Circle(const T& x, const T& y, const float size, const uint numSegments) : fPos(x, y), fSize(size), fNumSegments(numSegments >= 3 ? numSegments : 3), - fTheta(2.0f * M_PI / float(fNumSegments)), + fTheta(M_2PIf / static_cast<float>(fNumSegments)), fCos(std::cos(fTheta)), fSin(std::sin(fTheta)) { @@ -441,11 +480,11 @@ Circle<T>::Circle(const T& x, const T& y, float size, int numSegments) } template<typename T> -Circle<T>::Circle(const Point<T>& pos, float size, int numSegments) +Circle<T>::Circle(const Point<T>& pos, const float size, const uint numSegments) : fPos(pos), fSize(size), fNumSegments(numSegments >= 3 ? numSegments : 3), - fTheta(2.0f * M_PI / float(fNumSegments)), + fTheta(M_2PIf / static_cast<float>(fNumSegments)), fCos(std::cos(fTheta)), fSin(std::sin(fTheta)) { @@ -514,26 +553,30 @@ float Circle<T>::getSize() const noexcept } template<typename T> -void Circle<T>::setSize(float size) noexcept +void Circle<T>::setSize(const float size) noexcept { + DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,); + fSize = size; } template<typename T> -int Circle<T>::getNumSegments() const noexcept +uint Circle<T>::getNumSegments() const noexcept { return fNumSegments; } template<typename T> -void Circle<T>::setNumSegments(int num) +void Circle<T>::setNumSegments(const uint num) { + DISTRHO_SAFE_ASSERT_RETURN(num >= 3,); + if (fNumSegments == num) return; fNumSegments = num; - fTheta = 2.0f * M_PI / float(fNumSegments); + fTheta = M_2PIf / static_cast<float>(fNumSegments); fCos = std::cos(fTheta); fSin = std::sin(fTheta); } @@ -571,13 +614,13 @@ bool Circle<T>::operator==(const Circle<T>& cir) const noexcept template<typename T> bool Circle<T>::operator!=(const Circle<T>& cir) const noexcept { - return !operator==(cir); + return (fPos != cir.fPos || fSize != cir.fSize || fNumSegments != cir.fNumSegments); } template<typename T> void Circle<T>::_draw(const bool isOutline) { - if (fNumSegments == 0 && fSize > 0.0f) + if (fNumSegments < 3 || fSize <= 0.0f) return; float t, x = fSize, y = 0; @@ -653,7 +696,7 @@ bool Triangle<T>::operator==(const Triangle<T>& tri) const noexcept template<typename T> bool Triangle<T>::operator!=(const Triangle<T>& tri) const noexcept { - return !operator==(tri); + return (fPos1 != tri.fPos1 || fPos2 != tri.fPos2 || fPos3 != tri.fPos3); } template<typename T> @@ -767,14 +810,13 @@ void Rectangle<T>::setPos(const Point<T>& pos) noexcept template<typename T> void Rectangle<T>::moveBy(const T& x, const T& y) noexcept { - fPos.fX += x; - fPos.fY += y; + fPos.moveBy(x, y); } template<typename T> void Rectangle<T>::moveBy(const Point<T>& pos) noexcept { - fPos += pos; + fPos.moveBy(pos); } template<typename T> @@ -805,15 +847,27 @@ void Rectangle<T>::setSize(const Size<T>& size) noexcept template<typename T> void Rectangle<T>::growBy(const T& multiplier) noexcept { - fSize.fWidth *= multiplier; - fSize.fHeight *= multiplier; + fSize.growBy(multiplier); } template<typename T> void Rectangle<T>::shrinkBy(const T& divider) noexcept { - fSize.fWidth /= divider; - fSize.fHeight /= divider; + fSize.shrinkBy(divider); +} + +template<typename T> +void Rectangle<T>::setRectangle(const Point<T>& pos, const Size<T>& size) noexcept +{ + fPos = pos; + fSize = size; +} + +template<typename T> +void Rectangle<T>::setRectangle(const Rectangle<T>& rect) noexcept +{ + fPos = rect.fPos; + fSize = rect.fSize; } template<typename T> @@ -863,16 +917,14 @@ Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rect) noexcept template<typename T> Rectangle<T>& Rectangle<T>::operator*=(const T& m) noexcept { - fSize.fWidth *= m; - fSize.fHeight *= m; + fSize *= m; return *this; } template<typename T> Rectangle<T>& Rectangle<T>::operator/=(const T& d) noexcept { - fSize.fWidth /= d; - fSize.fHeight /= d; + fSize /= d; return *this; } @@ -885,7 +937,7 @@ bool Rectangle<T>::operator==(const Rectangle<T>& rect) const noexcept template<typename T> bool Rectangle<T>::operator!=(const Rectangle<T>& rect) const noexcept { - return !operator==(rect); + return (fPos != rect.fPos || fSize != rect.fSize); } template<typename T> @@ -958,4 +1010,3 @@ template class Rectangle<ushort>; // ----------------------------------------------------------------------- END_NAMESPACE_DGL - diff --git a/libs/dgl/src/Image.cpp b/libs/dgl/src/Image.cpp index 81b24dd..55ee0af 100644 --- a/libs/dgl/src/Image.cpp +++ b/libs/dgl/src/Image.cpp @@ -31,7 +31,7 @@ Image::Image() glGenTextures(1, &fTextureId); } -Image::Image(const char* rawData, int width, int height, GLenum format, GLenum type) +Image::Image(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type) : fRawData(rawData), fSize(width, height), fFormat(format), @@ -42,7 +42,7 @@ Image::Image(const char* rawData, int width, int height, GLenum format, GLenum t glGenTextures(1, &fTextureId); } -Image::Image(const char* rawData, const Size<int>& size, GLenum format, GLenum type) +Image::Image(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type) : fRawData(rawData), fSize(size), fFormat(format), @@ -73,12 +73,12 @@ Image::~Image() } } -void Image::loadFromMemory(const char* rawData, int width, int height, GLenum format, GLenum type) noexcept +void Image::loadFromMemory(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type) noexcept { - loadFromMemory(rawData, Size<int>(width, height), format, type); + loadFromMemory(rawData, Size<uint>(width, height), format, type); } -void Image::loadFromMemory(const char* rawData, const Size<int>& size, GLenum format, GLenum type) noexcept +void Image::loadFromMemory(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type) noexcept { fRawData = rawData; fSize = size; @@ -92,17 +92,17 @@ bool Image::isValid() const noexcept return (fRawData != nullptr && fSize.getWidth() > 0 && fSize.getHeight() > 0); } -int Image::getWidth() const noexcept +uint Image::getWidth() const noexcept { return fSize.getWidth(); } -int Image::getHeight() const noexcept +uint Image::getHeight() const noexcept { return fSize.getHeight(); } -const Size<int>& Image::getSize() const noexcept +const Size<uint>& Image::getSize() const noexcept { return fSize; } @@ -127,7 +127,7 @@ void Image::draw() drawAt(0, 0); } -void Image::drawAt(int x, int y) +void Image::drawAt(const int x, const int y) { drawAt(Point<int>(x, y)); } @@ -157,7 +157,7 @@ void Image::drawAt(const Point<int>& pos) fIsReady = true; } - Rectangle<int>(pos, fSize).draw(); + Rectangle<int>(pos, fSize.getWidth(), fSize.getHeight()).draw(); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); diff --git a/libs/dgl/src/ImageAboutWindow.cpp b/libs/dgl/src/ImageAboutWindow.cpp index 8d414d3..a12aa57 100644 --- a/libs/dgl/src/ImageAboutWindow.cpp +++ b/libs/dgl/src/ImageAboutWindow.cpp @@ -23,7 +23,8 @@ START_NAMESPACE_DGL ImageAboutWindow::ImageAboutWindow(Window& parent, const Image& image) : Window(parent.getApp(), parent), Widget((Window&)*this), - fImgBackground(image) + fImgBackground(image), + leakDetector_ImageAboutWindow() { Window::setResizable(false); Window::setSize(static_cast<uint>(image.getWidth()), static_cast<uint>(image.getHeight())); @@ -33,7 +34,8 @@ ImageAboutWindow::ImageAboutWindow(Window& parent, const Image& image) ImageAboutWindow::ImageAboutWindow(Widget* widget, const Image& image) : Window(widget->getParentApp(), widget->getParentWindow()), Widget((Window&)*this), - fImgBackground(image) + fImgBackground(image), + leakDetector_ImageAboutWindow() { Window::setResizable(false); Window::setSize(static_cast<uint>(image.getWidth()), static_cast<uint>(image.getHeight())); @@ -76,7 +78,7 @@ bool ImageAboutWindow::onMouse(const MouseEvent& ev) return false; } -void ImageAboutWindow::onReshape(int width, int height) +void ImageAboutWindow::onReshape(uint width, uint height) { Widget::setSize(width, height); Window::onReshape(width, height); diff --git a/libs/dgl/src/ImageButton.cpp b/libs/dgl/src/ImageButton.cpp index 29f27bd..3502170 100644 --- a/libs/dgl/src/ImageButton.cpp +++ b/libs/dgl/src/ImageButton.cpp @@ -27,9 +27,8 @@ ImageButton::ImageButton(Window& parent, const Image& image) noexcept fImageDown(image), fCurImage(&fImageNormal), fCurButton(-1), - fCallback(nullptr) -{ -} + fCallback(nullptr), + leakDetector_ImageButton() {} ImageButton::ImageButton(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept : Widget(parent), @@ -38,7 +37,8 @@ ImageButton::ImageButton(Window& parent, const Image& imageNormal, const Image& fImageDown(imageDown), fCurImage(&fImageNormal), fCurButton(-1), - fCallback(nullptr) + fCallback(nullptr), + leakDetector_ImageButton() { DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); @@ -52,9 +52,8 @@ ImageButton::ImageButton(Widget* widget, const Image& image) noexcept fImageDown(image), fCurImage(&fImageNormal), fCurButton(-1), - fCallback(nullptr) -{ -} + fCallback(nullptr), + leakDetector_ImageButton() {} ImageButton::ImageButton(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept : Widget(widget->getParentWindow()), @@ -63,7 +62,8 @@ ImageButton::ImageButton(Widget* widget, const Image& imageNormal, const Image& fImageDown(imageDown), fCurImage(&fImageNormal), fCurButton(-1), - fCallback(nullptr) + fCallback(nullptr), + leakDetector_ImageButton() { DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); @@ -77,11 +77,28 @@ ImageButton::ImageButton(const ImageButton& imageButton) noexcept fImageDown(imageButton.fImageDown), fCurImage(&fImageNormal), fCurButton(-1), - fCallback(imageButton.fCallback) + fCallback(imageButton.fCallback), + leakDetector_ImageButton() +{ + DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); + + setSize(fCurImage->getSize()); +} + +ImageButton& ImageButton::operator=(const ImageButton& imageButton) noexcept { + fImageNormal = imageButton.fImageNormal; + fImageHover = imageButton.fImageHover; + fImageDown = imageButton.fImageDown; + fCurImage = &fImageNormal; + fCurButton = -1; + fCallback = imageButton.fCallback; + DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); setSize(fCurImage->getSize()); + + return *this; } void ImageButton::setCallback(Callback* callback) noexcept diff --git a/libs/dgl/src/ImageKnob.cpp b/libs/dgl/src/ImageKnob.cpp index be34b58..0fc8c69 100644 --- a/libs/dgl/src/ImageKnob.cpp +++ b/libs/dgl/src/ImageKnob.cpp @@ -45,7 +45,8 @@ ImageKnob::ImageKnob(Window& parent, const Image& image, Orientation orientation fImgLayerCount(fIsImgVertical ? image.getHeight()/fImgLayerSize : image.getWidth()/fImgLayerSize), fKnobArea(0, 0, fImgLayerSize, fImgLayerSize), fTextureId(0), - fIsReady(false) + fIsReady(false), + leakDetector_ImageKnob() { glGenTextures(1, &fTextureId); setSize(fImgLayerSize, fImgLayerSize); @@ -74,7 +75,8 @@ ImageKnob::ImageKnob(Widget* widget, const Image& image, Orientation orientation fImgLayerCount(fIsImgVertical ? image.getHeight()/fImgLayerSize : image.getWidth()/fImgLayerSize), fKnobArea(0, 0, fImgLayerSize, fImgLayerSize), fTextureId(0), - fIsReady(false) + fIsReady(false), + leakDetector_ImageKnob() { glGenTextures(1, &fTextureId); setSize(fImgLayerSize, fImgLayerSize); @@ -103,12 +105,49 @@ ImageKnob::ImageKnob(const ImageKnob& imageKnob) fImgLayerCount(imageKnob.fImgLayerCount), fKnobArea(imageKnob.fKnobArea), fTextureId(0), - fIsReady(false) + fIsReady(false), + leakDetector_ImageKnob() { glGenTextures(1, &fTextureId); setSize(fImgLayerSize, fImgLayerSize); } +ImageKnob& ImageKnob::operator=(const ImageKnob& imageKnob) +{ + fImage = imageKnob.fImage; + fId = imageKnob.fId; + fMinimum = imageKnob.fMinimum; + fMaximum = imageKnob.fMaximum; + fStep = imageKnob.fStep; + fValue = imageKnob.fValue; + fValueDef = imageKnob.fValueDef; + fValueTmp = fValue; + fUsingDefault = imageKnob.fUsingDefault; + fUsingLog = imageKnob.fUsingLog; + fOrientation = imageKnob.fOrientation; + fRotationAngle = imageKnob.fRotationAngle; + fDragging = false; + fLastX = 0; + fLastY = 0; + fCallback = imageKnob.fCallback; + fIsImgVertical = imageKnob.fIsImgVertical; + fImgLayerSize = imageKnob.fImgLayerSize; + fImgLayerCount = imageKnob.fImgLayerCount; + fKnobArea = imageKnob.fKnobArea; + fIsReady = false; + + if (fTextureId != 0) + { + glDeleteTextures(1, &fTextureId); + fTextureId = 0; + } + + glGenTextures(1, &fTextureId); + setSize(fImgLayerSize, fImgLayerSize); + + return *this; +} + ImageKnob::~ImageKnob() { if (fTextureId != 0) @@ -329,7 +368,7 @@ bool ImageKnob::onMotion(const MotionEvent& ev) return false; bool doVal = false; - float d, value; + float d, value = 0.0f; if (fOrientation == ImageKnob::Horizontal) { diff --git a/libs/dgl/src/ImageSlider.cpp b/libs/dgl/src/ImageSlider.cpp index f6a9f49..b9ae84e 100644 --- a/libs/dgl/src/ImageSlider.cpp +++ b/libs/dgl/src/ImageSlider.cpp @@ -35,7 +35,11 @@ ImageSlider::ImageSlider(Window& parent, const Image& image, int id) noexcept fInverted(false), fStartedX(0), fStartedY(0), - fCallback(nullptr) + fCallback(nullptr), + fStartPos(), + fEndPos(), + fSliderArea(), + leakDetector_ImageSlider() { Widget::setNeedsFullViewport(true); } @@ -53,7 +57,11 @@ ImageSlider::ImageSlider(Widget* widget, const Image& image, int id) noexcept fInverted(false), fStartedX(0), fStartedY(0), - fCallback(nullptr) + fCallback(nullptr), + fStartPos(), + fEndPos(), + fSliderArea(), + leakDetector_ImageSlider() { Widget::setNeedsFullViewport(true); } @@ -74,11 +82,33 @@ ImageSlider::ImageSlider(const ImageSlider& imageSlider) noexcept fCallback(imageSlider.fCallback), fStartPos(imageSlider.fStartPos), fEndPos(imageSlider.fEndPos), - fSliderArea(imageSlider.fSliderArea) + fSliderArea(imageSlider.fSliderArea), + leakDetector_ImageSlider() { Widget::setNeedsFullViewport(true); } +ImageSlider& ImageSlider::operator=(const ImageSlider& imageSlider) noexcept +{ + fImage = imageSlider.fImage; + fId = imageSlider.fId; + fMinimum = imageSlider.fMinimum; + fMaximum = imageSlider.fMaximum; + fStep = imageSlider.fStep; + fValue = imageSlider.fValue; + fValueTmp = fValue; + fDragging = false; + fInverted = imageSlider.fInverted; + fStartedX = 0; + fStartedY = 0; + fCallback = imageSlider.fCallback; + fStartPos = imageSlider.fStartPos; + fEndPos = imageSlider.fEndPos; + fSliderArea = imageSlider.fSliderArea; + + return *this; +} + int ImageSlider::getId() const noexcept { return fId; diff --git a/libs/dgl/src/ImageSwitch.cpp b/libs/dgl/src/ImageSwitch.cpp index 41492b5..bd99786 100644 --- a/libs/dgl/src/ImageSwitch.cpp +++ b/libs/dgl/src/ImageSwitch.cpp @@ -26,7 +26,8 @@ ImageSwitch::ImageSwitch(Window& parent, const Image& imageNormal, const Image& fImageDown(imageDown), fIsDown(false), fId(id), - fCallback(nullptr) + fCallback(nullptr), + leakDetector_ImageSwitch() { DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize()); @@ -39,7 +40,8 @@ ImageSwitch::ImageSwitch(Widget* widget, const Image& imageNormal, const Image& fImageDown(imageDown), fIsDown(false), fId(id), - fCallback(nullptr) + fCallback(nullptr), + leakDetector_ImageSwitch() { DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize()); @@ -52,13 +54,29 @@ ImageSwitch::ImageSwitch(const ImageSwitch& imageSwitch) noexcept fImageDown(imageSwitch.fImageDown), fIsDown(imageSwitch.fIsDown), fId(imageSwitch.fId), - fCallback(imageSwitch.fCallback) + fCallback(imageSwitch.fCallback), + leakDetector_ImageSwitch() { DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize()); setSize(fImageNormal.getSize()); } +ImageSwitch& ImageSwitch::operator=(const ImageSwitch& imageSwitch) noexcept +{ + fImageNormal = imageSwitch.fImageNormal; + fImageDown = imageSwitch.fImageDown; + fIsDown = imageSwitch.fIsDown; + fId = imageSwitch.fId; + fCallback = imageSwitch.fCallback; + + DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize()); + + setSize(fImageNormal.getSize()); + + return *this; +} + int ImageSwitch::getId() const noexcept { return fId; diff --git a/libs/dgl/src/NanoVG.cpp b/libs/dgl/src/NanoVG.cpp index 78b6bc2..bb7b9f1 100644 --- a/libs/dgl/src/NanoVG.cpp +++ b/libs/dgl/src/NanoVG.cpp @@ -39,19 +39,7 @@ START_NAMESPACE_DGL // ----------------------------------------------------------------------- -// Conversions - -NanoVG::Color::Color() noexcept - : r(1.0f), g(1.0f), b(1.0f), a(1.0f) {} - -NanoVG::Color::Color(const NVGcolor& c) noexcept - : r(c.r), g(c.g), b(c.b), a(c.a) {} - -NanoVG::Color::operator NVGcolor() const noexcept -{ - NVGcolor nc = {{{ r, g, b, a }}}; - return nc; -} +// Paint NanoVG::Paint::Paint() noexcept : radius(0.0f), feather(0.0f), innerColor(), outerColor(), imageId(0), repeat(REPEAT_NONE) @@ -84,9 +72,13 @@ NanoVG::Paint::operator NVGpaint() const noexcept // ----------------------------------------------------------------------- // NanoImage -NanoImage::NanoImage(NVGcontext* context, int imageId) noexcept +NanoImage::NanoImage(NVGcontext* const context, const int imageId) noexcept : fContext(context), - fImageId(imageId) {} + fImageId(imageId), + fSize() +{ + _updateSize(); +} NanoImage::~NanoImage() { @@ -94,162 +86,194 @@ NanoImage::~NanoImage() nvgDeleteImage(fContext, fImageId); } -Size<int> NanoImage::getSize() const +Size<uint> NanoImage::getSize() const noexcept { - int w=0, h=0; + return fSize; +} - if (fContext != nullptr && fImageId != 0) - nvgImageSize(fContext, fImageId, &w, &h); +void NanoImage::updateImage(const uchar* const data) +{ + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr,); - return Size<int>(w, h); + if (fContext != nullptr && fImageId != 0) + { + nvgUpdateImage(fContext, fImageId, data); + _updateSize(); + } } -void NanoImage::updateImage(const uchar* data) +void NanoImage::_updateSize() { + int w=0, h=0; + if (fContext != nullptr && fImageId != 0) - nvgUpdateImage(fContext, fImageId, data); + { + nvgImageSize(fContext, fImageId, &w, &h); + + if (w < 0) w = 0; + if (h < 0) h = 0; + } + + fSize.setSize(w, h); } // ----------------------------------------------------------------------- // NanoVG NanoVG::NanoVG() - : fContext(nvgCreateGL(512, 512, NVG_ANTIALIAS)) + : fContext(nvgCreateGL(512, 512, NVG_ANTIALIAS)), + fInFrame(false) { DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr,); } -NanoVG::NanoVG(int textAtlasWidth, int textAtlasHeight) - : fContext(nvgCreateGL(textAtlasWidth, textAtlasHeight, NVG_ANTIALIAS)) +NanoVG::NanoVG(const int textAtlasWidth, const int textAtlasHeight) + : fContext(nvgCreateGL(textAtlasWidth, textAtlasHeight, NVG_ANTIALIAS)), + fInFrame(false) { DISTRHO_SAFE_ASSERT_RETURN(fContext != nullptr,); } NanoVG::~NanoVG() { - if (fContext == nullptr) - return; + DISTRHO_SAFE_ASSERT(! fInFrame); - nvgDeleteGL(fContext); + if (fContext != nullptr) + nvgDeleteGL(fContext); } // ----------------------------------------------------------------------- -void NanoVG::beginFrame(int width, int height, float scaleFactor, Alpha alpha) +void NanoVG::beginFrame(const uint width, const uint height, const float scaleFactor, const Alpha alpha) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(scaleFactor > 0.0f,); + DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,); + + fInFrame = true; nvgBeginFrame(fContext, width, height, scaleFactor, static_cast<NVGalpha>(alpha)); } -void NanoVG::beginFrame(Widget* widget) +void NanoVG::beginFrame(Widget* const widget) { + if (fContext == nullptr) return; DISTRHO_SAFE_ASSERT_RETURN(widget != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(! fInFrame,); Window& window(widget->getParentWindow()); + + fInFrame = true; nvgBeginFrame(fContext, window.getWidth(), window.getHeight(), 1.0f, NVG_PREMULTIPLIED_ALPHA); } void NanoVG::endFrame() { - nvgEndFrame(fContext); -} + DISTRHO_SAFE_ASSERT_RETURN(fInFrame,); -// ----------------------------------------------------------------------- -// Color utils + if (fContext != nullptr) + nvgEndFrame(fContext); -NanoVG::Color NanoVG::RGB(uchar r, uchar g, uchar b) -{ - return nvgRGB(r, g, b); + fInFrame = false; } -NanoVG::Color NanoVG::RGBf(float r, float g, float b) -{ - return nvgRGBf(r, g, b); -} +// ----------------------------------------------------------------------- +// State Handling -NanoVG::Color NanoVG::RGBA(uchar r, uchar g, uchar b, uchar a) +void NanoVG::save() { - return nvgRGBA(r, g, b, a); + if (fContext != nullptr) + nvgSave(fContext); } -NanoVG::Color NanoVG::RGBAf(float r, float g, float b, float a) +void NanoVG::restore() { - return nvgRGBAf(r, g, b, a); + if (fContext != nullptr) + nvgRestore(fContext); } -NanoVG::Color NanoVG::lerpRGBA(const Color& c0, const Color& c1, float u) +void NanoVG::reset() { - return nvgLerpRGBA(c0, c1, u); + if (fContext != nullptr) + nvgReset(fContext); } -NanoVG::Color NanoVG::HSL(float h, float s, float l) -{ - return nvgHSL(h, s, l); -} +// ----------------------------------------------------------------------- +// Render styles -NanoVG::Color NanoVG::HSLA(float h, float s, float l, uchar a) +void NanoVG::strokeColor(const Color& color) { - return nvgHSLA(h, s, l, a); + if (fContext != nullptr) + nvgStrokeColor(fContext, color); } -// ----------------------------------------------------------------------- -// State Handling - -void NanoVG::save() +void NanoVG::strokeColor(const int red, const int green, const int blue, const int alpha) { - nvgSave(fContext); + if (fContext != nullptr) + nvgStrokeColor(fContext, nvgRGBA(red, green, blue, alpha)); } -void NanoVG::restore() +void NanoVG::strokeColor(const float red, const float green, const float blue, const float alpha) { - nvgRestore(fContext); + if (fContext != nullptr) + nvgStrokeColor(fContext, nvgRGBAf(red, green, blue, alpha)); } -void NanoVG::reset() +void NanoVG::strokePaint(const Paint& paint) { - nvgReset(fContext); + if (fContext != nullptr) + nvgStrokePaint(fContext, paint); } -// ----------------------------------------------------------------------- -// Render styles - -void NanoVG::strokeColor(const Color& color) +void NanoVG::fillColor(const Color& color) { - nvgStrokeColor(fContext, color); + if (fContext != nullptr) + nvgFillColor(fContext, color); } -void NanoVG::strokePaint(const Paint& paint) +void NanoVG::fillColor(const int red, const int green, const int blue, const int alpha) { - nvgStrokePaint(fContext, paint); + if (fContext != nullptr) + nvgFillColor(fContext, nvgRGBA(red, green, blue, alpha)); } -void NanoVG::fillColor(const Color& color) +void NanoVG::fillColor(const float red, const float green, const float blue, const float alpha) { - nvgFillColor(fContext, color); + if (fContext != nullptr) + nvgFillColor(fContext, nvgRGBAf(red, green, blue, alpha)); } void NanoVG::fillPaint(const Paint& paint) { - nvgFillPaint(fContext, paint); + if (fContext != nullptr) + nvgFillPaint(fContext, paint); } void NanoVG::miterLimit(float limit) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(limit > 0.0f,); + nvgMiterLimit(fContext, limit); } void NanoVG::strokeWidth(float size) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,); + nvgStrokeWidth(fContext, size); } void NanoVG::lineCap(NanoVG::LineCap cap) { - nvgLineCap(fContext, cap); + if (fContext != nullptr) + nvgLineCap(fContext, cap); } void NanoVG::lineJoin(NanoVG::LineCap join) { - nvgLineJoin(fContext, join); + if (fContext != nullptr) + nvgLineJoin(fContext, join); } // ----------------------------------------------------------------------- @@ -257,42 +281,59 @@ void NanoVG::lineJoin(NanoVG::LineCap join) void NanoVG::resetTransform() { - nvgResetTransform(fContext); + if (fContext != nullptr) + nvgResetTransform(fContext); } void NanoVG::transform(float a, float b, float c, float d, float e, float f) { - nvgTransform(fContext, a, b, c, d, e, f); + if (fContext != nullptr) + nvgTransform(fContext, a, b, c, d, e, f); } void NanoVG::translate(float x, float y) { - nvgTranslate(fContext, x, y); + if (fContext != nullptr) + nvgTranslate(fContext, x, y); } void NanoVG::rotate(float angle) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,); + nvgRotate(fContext, angle); } void NanoVG::skewX(float angle) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,); + nvgSkewX(fContext, angle); } void NanoVG::skewY(float angle) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(angle > 0.0f,); + nvgSkewY(fContext, angle); } void NanoVG::scale(float x, float y) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(x > 0.0f,); + DISTRHO_SAFE_ASSERT_RETURN(y > 0.0f,); + nvgScale(fContext, x, y); } void NanoVG::currentTransform(float xform[6]) { - nvgCurrentTransform(fContext, xform); + if (fContext != nullptr) + nvgCurrentTransform(fContext, xform); } void NanoVG::transformIdentity(float dst[6]) @@ -360,46 +401,64 @@ float NanoVG::radToDeg(float rad) NanoImage* NanoVG::createImage(const char* filename) { + if (fContext == nullptr) return nullptr; + DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); + if (const int imageId = nvgCreateImage(fContext, filename)) return new NanoImage(fContext, imageId); + return nullptr; } NanoImage* NanoVG::createImageMem(uchar* data, int ndata) { + if (fContext == nullptr) return nullptr; + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, nullptr); + DISTRHO_SAFE_ASSERT_RETURN(ndata > 0, nullptr); + if (const int imageId = nvgCreateImageMem(fContext, data, ndata)) return new NanoImage(fContext, imageId); + return nullptr; } -NanoImage* NanoVG::createImageRGBA(int w, int h, const uchar* data) +NanoImage* NanoVG::createImageRGBA(uint w, uint h, const uchar* data) { + if (fContext == nullptr) return nullptr; + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, nullptr); + if (const int imageId = nvgCreateImageRGBA(fContext, w, h, data)) return new NanoImage(fContext, imageId); + return nullptr; } // ----------------------------------------------------------------------- // Paints -NanoVG::Paint NanoVG::linearGradient(float sx, float sy, float ex, float ey, const NanoVG::Color& icol, const NanoVG::Color& ocol) +NanoVG::Paint NanoVG::linearGradient(float sx, float sy, float ex, float ey, const Color& icol, const Color& ocol) { + if (fContext == nullptr) return Paint(); return nvgLinearGradient(fContext, sx, sy, ex, ey, icol, ocol); } -NanoVG::Paint NanoVG::boxGradient(float x, float y, float w, float h, float r, float f, const NanoVG::Color& icol, const NanoVG::Color& ocol) +NanoVG::Paint NanoVG::boxGradient(float x, float y, float w, float h, float r, float f, const Color& icol, const Color& ocol) { + if (fContext == nullptr) return Paint(); return nvgBoxGradient(fContext, x, y, w, h, r, f, icol, ocol); } -NanoVG::Paint NanoVG::radialGradient(float cx, float cy, float inr, float outr, const NanoVG::Color& icol, const NanoVG::Color& ocol) +NanoVG::Paint NanoVG::radialGradient(float cx, float cy, float inr, float outr, const Color& icol, const Color& ocol) { + if (fContext == nullptr) return Paint(); return nvgRadialGradient(fContext, cx, cy, inr, outr, icol, ocol); } NanoVG::Paint NanoVG::imagePattern(float ox, float oy, float ex, float ey, float angle, const NanoImage* image, NanoVG::PatternRepeat repeat) { + if (fContext == nullptr) return Paint(); DISTRHO_SAFE_ASSERT_RETURN(image != nullptr, Paint()); + return nvgImagePattern(fContext, ox, oy, ex, ey, angle, image->fImageId, repeat); } @@ -408,12 +467,14 @@ NanoVG::Paint NanoVG::imagePattern(float ox, float oy, float ex, float ey, float void NanoVG::scissor(float x, float y, float w, float h) { - nvgScissor(fContext, x, y, w, h); + if (fContext != nullptr) + nvgScissor(fContext, x, y, w, h); } void NanoVG::resetScissor() { - nvgResetScissor(fContext); + if (fContext != nullptr) + nvgResetScissor(fContext); } // ----------------------------------------------------------------------- @@ -421,72 +482,86 @@ void NanoVG::resetScissor() void NanoVG::beginPath() { - nvgBeginPath(fContext); + if (fContext != nullptr) + nvgBeginPath(fContext); } void NanoVG::moveTo(float x, float y) { - nvgMoveTo(fContext, x, y); + if (fContext != nullptr) + nvgMoveTo(fContext, x, y); } void NanoVG::lineTo(float x, float y) { - nvgLineTo(fContext, x, y); + if (fContext != nullptr) + nvgLineTo(fContext, x, y); } void NanoVG::bezierTo(float c1x, float c1y, float c2x, float c2y, float x, float y) { - nvgBezierTo(fContext, c1x, c1y, c2x, c2y, x, y); + if (fContext != nullptr) + nvgBezierTo(fContext, c1x, c1y, c2x, c2y, x, y); } void NanoVG::arcTo(float x1, float y1, float x2, float y2, float radius) { - nvgArcTo(fContext, x1, y1, x2, y2, radius); + if (fContext != nullptr) + nvgArcTo(fContext, x1, y1, x2, y2, radius); } void NanoVG::closePath() { - nvgClosePath(fContext); + if (fContext != nullptr) + nvgClosePath(fContext); } void NanoVG::pathWinding(NanoVG::Winding dir) { - nvgPathWinding(fContext, dir); + if (fContext != nullptr) + nvgPathWinding(fContext, dir); } void NanoVG::arc(float cx, float cy, float r, float a0, float a1, NanoVG::Winding dir) { - nvgArc(fContext, cx, cy, r, a0, a1, dir); + if (fContext != nullptr) + nvgArc(fContext, cx, cy, r, a0, a1, dir); } void NanoVG::rect(float x, float y, float w, float h) { - nvgRect(fContext, x, y, w, h); + if (fContext != nullptr) + nvgRect(fContext, x, y, w, h); } void NanoVG::roundedRect(float x, float y, float w, float h, float r) { - nvgRoundedRect(fContext, x, y, w, h, r); + if (fContext != nullptr) + nvgRoundedRect(fContext, x, y, w, h, r); } void NanoVG::ellipse(float cx, float cy, float rx, float ry) { - nvgEllipse(fContext, cx, cy, rx, ry); + if (fContext != nullptr) + nvgEllipse(fContext, cx, cy, rx, ry); } void NanoVG::circle(float cx, float cy, float r) { - nvgCircle(fContext, cx, cy, r); + if (fContext != nullptr) + nvgCircle(fContext, cx, cy, r); } void NanoVG::fill() { - nvgFill(fContext); + if (fContext != nullptr) + nvgFill(fContext); } void NanoVG::stroke() { - nvgStroke(fContext); + if (fContext != nullptr) + nvgStroke(fContext); } // ----------------------------------------------------------------------- @@ -494,71 +569,111 @@ void NanoVG::stroke() NanoVG::FontId NanoVG::createFont(const char* name, const char* filename) { + if (fContext == nullptr) return -1; + DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1); + DISTRHO_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', -1); + return nvgCreateFont(fContext, name, filename); } NanoVG::FontId NanoVG::createFontMem(const char* name, uchar* data, int ndata, bool freeData) { + if (fContext == nullptr) return -1; + DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1); + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, -1); + return nvgCreateFontMem(fContext, name, data, ndata, freeData); } NanoVG::FontId NanoVG::findFont(const char* name) { + if (fContext == nullptr) return -1; + DISTRHO_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', -1); + return nvgFindFont(fContext, name); } void NanoVG::fontSize(float size) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(size > 0.0f,); + nvgFontSize(fContext, size); } void NanoVG::fontBlur(float blur) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(blur >= 0.0f,); + nvgFontBlur(fContext, blur); } void NanoVG::textLetterSpacing(float spacing) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(spacing >= 0.0f,); + nvgTextLetterSpacing(fContext, spacing); } void NanoVG::textLineHeight(float lineHeight) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(lineHeight > 0.0f,); + nvgTextLineHeight(fContext, lineHeight); } void NanoVG::textAlign(NanoVG::Align align) { - nvgTextAlign(fContext, align); + if (fContext != nullptr) + nvgTextAlign(fContext, align); } void NanoVG::textAlign(int align) { - nvgTextAlign(fContext, align); + if (fContext != nullptr) + nvgTextAlign(fContext, align); } void NanoVG::fontFaceId(FontId font) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(font >= 0,); + nvgFontFaceId(fContext, font); } void NanoVG::fontFace(const char* font) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(font != nullptr && font[0] != '\0',); + nvgFontFace(fContext, font); } float NanoVG::text(float x, float y, const char* string, const char* end) { + if (fContext == nullptr) return 0.0f; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f); + return nvgText(fContext, x, y, string, end); } void NanoVG::textBox(float x, float y, float breakRowWidth, const char* string, const char* end) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',); + nvgTextBox(fContext, x, y, breakRowWidth, string, end); } float NanoVG::textBounds(float x, float y, const char* string, const char* end, Rectangle<float>& bounds) { + if (fContext == nullptr) return 0.0f; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0.0f); + float b[4]; const float ret = nvgTextBounds(fContext, x, y, string, end, b); bounds = Rectangle<float>(b[0], b[1], b[2], b[3]); @@ -567,22 +682,31 @@ float NanoVG::textBounds(float x, float y, const char* string, const char* end, void NanoVG::textBoxBounds(float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds) { + if (fContext == nullptr) return; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0',); + nvgTextBoxBounds(fContext, x, y, breakRowWidth, string, end, bounds); } int NanoVG::textGlyphPositions(float x, float y, const char* string, const char* end, NanoVG::GlyphPosition* positions, int maxPositions) { + if (fContext == nullptr) return 0; + DISTRHO_SAFE_ASSERT_RETURN(string != nullptr && string[0] != '\0', 0); + return nvgTextGlyphPositions(fContext, x, y, string, end, (NVGglyphPosition*)positions, maxPositions); } void NanoVG::textMetrics(float* ascender, float* descender, float* lineh) { - nvgTextMetrics(fContext, ascender, descender, lineh); + if (fContext != nullptr) + nvgTextMetrics(fContext, ascender, descender, lineh); } int NanoVG::textBreakLines(const char* string, const char* end, float breakRowWidth, NanoVG::TextRow* rows, int maxRows) { - return nvgTextBreakLines(fContext, string, end, breakRowWidth, (NVGtextRow*)rows, maxRows); + if (fContext != nullptr) + return nvgTextBreakLines(fContext, string, end, breakRowWidth, (NVGtextRow*)rows, maxRows); + return 0; } // ----------------------------------------------------------------------- diff --git a/libs/dgl/src/Widget.cpp b/libs/dgl/src/Widget.cpp index a494d1b..6013ea2 100644 --- a/libs/dgl/src/Widget.cpp +++ b/libs/dgl/src/Widget.cpp @@ -26,7 +26,10 @@ Widget::Widget(Window& parent) : fParent(parent), fNeedsFullViewport(false), fNeedsScaling(false), - fVisible(true) + fVisible(true), + fAbsolutePos(0, 0), + fSize(0, 0), + leakDetector_Widget() { fParent._addWidget(this); } @@ -60,66 +63,66 @@ void Widget::hide() setVisible(false); } -int Widget::getWidth() const noexcept +uint Widget::getWidth() const noexcept { - return fArea.getWidth(); + return fSize.getWidth(); } -int Widget::getHeight() const noexcept +uint Widget::getHeight() const noexcept { - return fArea.getHeight(); + return fSize.getHeight(); } -const Size<int>& Widget::getSize() const noexcept +const Size<uint>& Widget::getSize() const noexcept { - return fArea.getSize(); + return fSize; } -void Widget::setWidth(int width) noexcept +void Widget::setWidth(uint width) noexcept { - if (fArea.getWidth() == width) + if (fSize.getWidth() == width) return; ResizeEvent ev; - ev.oldSize = fArea.getSize(); - ev.size = Size<int>(width, fArea.getHeight()); + ev.oldSize = fSize; + ev.size = Size<uint>(width, fSize.getHeight()); - fArea.setWidth(width); + fSize.setWidth(width); onResize(ev); fParent.repaint(); } -void Widget::setHeight(int height) noexcept +void Widget::setHeight(uint height) noexcept { - if (fArea.getHeight() == height) + if (fSize.getHeight() == height) return; ResizeEvent ev; - ev.oldSize = fArea.getSize(); - ev.size = Size<int>(fArea.getWidth(), height); + ev.oldSize = fSize; + ev.size = Size<uint>(fSize.getWidth(), height); - fArea.setHeight(height); + fSize.setHeight(height); onResize(ev); fParent.repaint(); } -void Widget::setSize(int width, int height) noexcept +void Widget::setSize(uint width, uint height) noexcept { - setSize(Size<int>(width, height)); + setSize(Size<uint>(width, height)); } -void Widget::setSize(const Size<int>& size) noexcept +void Widget::setSize(const Size<uint>& size) noexcept { - if (fArea.getSize() == size) + if (fSize == size) return; ResizeEvent ev; - ev.oldSize = fArea.getSize(); - ev.size = size; + ev.oldSize = fSize; + ev.size = size; - fArea.setSize(size); + fSize = size; onResize(ev); fParent.repaint(); @@ -127,34 +130,34 @@ void Widget::setSize(const Size<int>& size) noexcept int Widget::getAbsoluteX() const noexcept { - return fArea.getX(); + return fAbsolutePos.getX(); } int Widget::getAbsoluteY() const noexcept { - return fArea.getY(); + return fAbsolutePos.getY(); } const Point<int>& Widget::getAbsolutePos() const noexcept { - return fArea.getPos(); + return fAbsolutePos; } void Widget::setAbsoluteX(int x) noexcept { - if (fArea.getX() == x) + if (fAbsolutePos.getX() == x) return; - fArea.setX(x); + fAbsolutePos.setX(x); fParent.repaint(); } void Widget::setAbsoluteY(int y) noexcept { - if (fArea.getY() == y) + if (fAbsolutePos.getY() == y) return; - fArea.setY(y); + fAbsolutePos.setY(y); fParent.repaint(); } @@ -165,10 +168,10 @@ void Widget::setAbsolutePos(int x, int y) noexcept void Widget::setAbsolutePos(const Point<int>& pos) noexcept { - if (fArea.getPos() == pos) + if (fAbsolutePos == pos) return; - fArea.setPos(pos); + fAbsolutePos = pos; fParent.repaint(); } @@ -184,7 +187,7 @@ Window& Widget::getParentWindow() const noexcept bool Widget::contains(int x, int y) const noexcept { - return (x >= 0 && y >= 0 && x < fArea.getWidth() && y < fArea.getHeight()); + return (x >= 0 && y >= 0 && static_cast<uint>(x) < fSize.getWidth() && static_cast<uint>(y) < fSize.getHeight()); } bool Widget::contains(const Point<int>& pos) const noexcept diff --git a/libs/dgl/src/Window.cpp b/libs/dgl/src/Window.cpp index f2c92e7..9d3c744 100644 --- a/libs/dgl/src/Window.cpp +++ b/libs/dgl/src/Window.cpp @@ -67,17 +67,19 @@ struct Window::PrivateData { fVisible(false), fResizable(true), fUsingEmbed(false), + fWidth(1), + fHeight(1), + fModal(), #if defined(DISTRHO_OS_WINDOWS) - hwnd(0) + hwnd(0), #elif defined(DISTRHO_OS_LINUX) xDisplay(nullptr), - xWindow(0) + xWindow(0), #elif defined(DISTRHO_OS_MAC) fNeedsIdle(true), - xWindow(nullptr) -#else - _dummy('\0') + xWindow(nullptr), #endif + leakDetector_PrivateData() { DBG("Creating window without parent..."); DBGF; init(); @@ -91,18 +93,19 @@ struct Window::PrivateData { fVisible(false), fResizable(true), fUsingEmbed(false), + fWidth(1), + fHeight(1), fModal(parent.pData), #if defined(DISTRHO_OS_WINDOWS) - hwnd(0) + hwnd(0), #elif defined(DISTRHO_OS_LINUX) xDisplay(nullptr), - xWindow(0) + xWindow(0), #elif defined(DISTRHO_OS_MAC) fNeedsIdle(false), - xWindow(nullptr) -#else - _dummy('\0') + xWindow(nullptr), #endif + leakDetector_PrivateData() { DBG("Creating window with parent..."); DBGF; init(); @@ -122,19 +125,21 @@ struct Window::PrivateData { fVisible(parentId != 0), fResizable(parentId == 0), fUsingEmbed(parentId != 0), + fWidth(1), + fHeight(1), + fModal(), #if defined(DISTRHO_OS_WINDOWS) - hwnd(0) + hwnd(0), #elif defined(DISTRHO_OS_LINUX) xDisplay(nullptr), - xWindow(0) + xWindow(0), #elif defined(DISTRHO_OS_MAC) fNeedsIdle(false), - xWindow(nullptr) -#else - _dummy('\0') + xWindow(nullptr), #endif + leakDetector_PrivateData() { - if (parentId != 0) + if (fUsingEmbed) { DBG("Creating embedded window..."); DBGF; puglInitWindowParent(fView, parentId); @@ -146,7 +151,7 @@ struct Window::PrivateData { init(); - if (parentId != 0) + if (fUsingEmbed) { DBG("NOTE: Embed window is always visible and non-resizable\n"); puglShowWindow(fView); @@ -164,6 +169,7 @@ struct Window::PrivateData { } puglInitResizable(fView, fResizable); + puglInitWindowSize(fView, fWidth, fHeight); puglSetHandle(fView, this); puglSetDisplayFunc(fView, onDisplayCallback); @@ -209,6 +215,12 @@ struct Window::PrivateData { //fOnModal = false; fWidgets.clear(); + if (fUsingEmbed) + { + puglHideWindow(fView); + fApp.pData->oneHidden(); + } + if (fSelf != nullptr) { fApp.pData->windows.remove(fSelf); @@ -238,6 +250,10 @@ struct Window::PrivateData { void close() { DBG("Window close\n"); + + if (fUsingEmbed) + return; + setVisible(false); if (! fFirstInit) @@ -351,7 +367,7 @@ struct Window::PrivateData { fVisible = yesNo; if (yesNo && fFirstInit) - setSize(static_cast<uint>(fView->width), static_cast<uint>(fView->height), true); + setSize(fWidth, fHeight, true); #if defined(DISTRHO_OS_WINDOWS) if (yesNo) @@ -405,7 +421,7 @@ struct Window::PrivateData { fResizable = yesNo; - setSize(static_cast<uint>(fView->width), static_cast<uint>(fView->height), true); + setSize(fWidth, fHeight, true); } // ------------------------------------------------------------------- @@ -418,14 +434,14 @@ struct Window::PrivateData { return; } - if (fView->width == static_cast<int>(width) && fView->height == static_cast<int>(height) && ! forced) + if (fWidth == width && fHeight == height && ! forced) { DBGp("Window setSize matches current size, ignoring request (%i %i)\n", width, height); return; } - fView->width = static_cast<int>(width); - fView->height = static_cast<int>(height); + fWidth = width; + fHeight = height; DBGp("Window setSize called %s, size %i %i\n", forced ? "(forced)" : "(not forced)", width, height); @@ -573,15 +589,15 @@ struct Window::PrivateData { // reset color glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - if (widget->fNeedsFullViewport || widget->fArea == Rectangle<int>(0, 0, fView->width, fView->height)) + if (widget->fNeedsFullViewport || (widget->fAbsolutePos.isZero() && widget->fSize == Size<uint>(fWidth, fHeight))) { // full viewport size - glViewport(0, 0, fView->width, fView->height); + glViewport(0, 0, fWidth, fHeight); } else if (! widget->fNeedsScaling) { // only set viewport pos - glViewport(widget->getAbsoluteX(), /*fView->height - widget->getHeight()*/ - widget->getAbsoluteY(), fView->width, fView->height); + glViewport(widget->getAbsoluteX(), /*fView->height - widget->getHeight()*/ - widget->getAbsoluteY(), fWidth, fHeight); // then cut the outer bounds glScissor(widget->getAbsoluteX(), fView->height - widget->getHeight() - widget->getAbsoluteY(), widget->getWidth(), widget->getHeight()); @@ -725,6 +741,12 @@ struct Window::PrivateData { { DBGp("PUGL: onReshape : %i %i\n", width, height); + if (width == 1 && height == 1) + return; + + fWidth = width; + fHeight = height; + fSelf->onReshape(width, height); FOR_EACH_WIDGET(it) @@ -761,6 +783,8 @@ struct Window::PrivateData { bool fVisible; bool fResizable; bool fUsingEmbed; + uint fWidth; + uint fHeight; std::list<Widget*> fWidgets; struct Modal { @@ -793,8 +817,6 @@ struct Window::PrivateData { #elif defined(DISTRHO_OS_MAC) bool fNeedsIdle; id xWindow; -#else - char _dummy; #endif // ------------------------------------------------------------------- @@ -843,6 +865,8 @@ struct Window::PrivateData { } #undef handlePtr + + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) }; // ----------------------------------------------------------------------- @@ -912,21 +936,19 @@ void Window::setResizable(bool yesNo) pData->setResizable(yesNo); } -int Window::getWidth() const noexcept +uint Window::getWidth() const noexcept { - return pData->fView->width; + return pData->fWidth; } -int Window::getHeight() const noexcept +uint Window::getHeight() const noexcept { - return pData->fView->height; + return pData->fHeight; } Size<uint> Window::getSize() const noexcept { - DISTRHO_SAFE_ASSERT_RETURN(pData->fView->width >= 0 && pData->fView->height >= 0, Size<uint>(0, 0)); - - return Size<uint>(pData->fView->width, pData->fView->height); + return Size<uint>(pData->fWidth, pData->fHeight); } void Window::setSize(uint width, uint height) @@ -1002,7 +1024,7 @@ void Window::onDisplayAfter() { } -void Window::onReshape(int width, int height) +void Window::onReshape(uint width, uint height) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/libs/distrho/DistrhoPlugin.hpp b/libs/distrho/DistrhoPlugin.hpp index a548314..817c266 100644 --- a/libs/distrho/DistrhoPlugin.hpp +++ b/libs/distrho/DistrhoPlugin.hpp @@ -22,7 +22,7 @@ #include <cmath> -#ifdef PROPER_CPP11_SUPPORT +#ifdef DISTRHO_PROPER_CPP11_SUPPORT # include <cstdint> #else # include <stdint.h> @@ -34,65 +34,116 @@ START_NAMESPACE_DISTRHO -// ----------------------------------------------------------------------- -// Parameter Hints +/* ------------------------------------------------------------------------------------------------------------ + * Parameter Hints */ -const uint32_t PARAMETER_IS_AUTOMABLE = 1 << 0; -const uint32_t PARAMETER_IS_BOOLEAN = 1 << 1; -const uint32_t PARAMETER_IS_INTEGER = 1 << 2; -const uint32_t PARAMETER_IS_LOGARITHMIC = 1 << 3; -const uint32_t PARAMETER_IS_OUTPUT = 1 << 4; +/** + @defgroup ParameterHints Parameter Hints -// ----------------------------------------------------------------------- -// Parameter Ranges + Various parameter hints. + @see Parameter::hints + @{ + */ + +/** + Parameter is automable (real-time safe). + @see Plugin::d_setParameterValue() + */ +static const uint32_t kParameterIsAutomable = 0x01; + +/** + Parameter value is boolean. + It's always at either minimum or maximum value. + */ +static const uint32_t kParameterIsBoolean = 0x02; + +/** + Parameter value is integer. + */ +static const uint32_t kParameterIsInteger = 0x04; + +/** + Parameter value is logarithmic. + */ +static const uint32_t kParameterIsLogarithmic = 0x08; +/** + Parameter is of output type. + When unset, parameter is assumed to be of input type. + + Parameter inputs are changed by the host and must not be changed by the plugin. + The only exception being when changing programs, see Plugin::d_setProgram(). + Outputs are changed by the plugin and never modified by the host. + */ +static const uint32_t kParameterIsOutput = 0x10; + +/** @} */ + +/* ------------------------------------------------------------------------------------------------------------ + * DPF Base structs */ + +/** + Parameter ranges. + This is used to set the default, minimum and maximum values of a parameter. + + By default a parameter has 0.0 as minimum, 1.0 as maximum and 0.0 as default. + When changing this struct values you must ensure maximum > minimum and default is within range. + */ struct ParameterRanges { + /** + Default value. + */ float def; + + /** + Minimum value. + */ float min; + + /** + Maximum value. + */ float max; + /** + Default constructor. + */ ParameterRanges() noexcept : def(0.0f), min(0.0f), max(1.0f) {} - ParameterRanges(float def, float min, float max) noexcept - { - this->def = def; - this->min = min; - this->max = max; - } - - void clear() noexcept - { - def = 0.0f; - min = 0.0f; - max = 1.0f; - } - - /*! - * Fix default value within range. - */ + /** + Constructor using custom values. + */ + ParameterRanges(const float df, const float mn, const float mx) noexcept + : def(df), + min(mn), + max(mx) {} + + /** + Fix the default value within range. + */ void fixDefault() noexcept { fixValue(def); } - /*! - * Fix a value within range. - */ + /** + 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 + /** + Get a fixed value within range. + */ + const float& getFixedValue(const float& value) const noexcept { if (value <= min) return min; @@ -101,9 +152,9 @@ struct ParameterRanges { return value; } - /*! - * Get a value normalized to 0.0<->1.0. - */ + /** + Get a value normalized to 0.0<->1.0. + */ float getNormalizedValue(const float& value) const noexcept { const float normValue((value - min) / (max - min)); @@ -115,9 +166,9 @@ struct ParameterRanges { return normValue; } - /*! - * Get a value normalized to 0.0<->1.0, fixed within range. - */ + /** + Get a value normalized to 0.0<->1.0, fixed within range. + */ float getFixedAndNormalizedValue(const float& value) const noexcept { if (value <= min) @@ -135,79 +186,175 @@ struct ParameterRanges { return normValue; } - /*! - * Get a proper value previously normalized to 0.0<->1.0. - */ + /** + Get a proper value previously normalized to 0.0<->1.0. + */ float getUnnormalizedValue(const float& value) const noexcept { + if (value <= 0.0f) + return min; + if (value >= 1.0f) + return max; + return value * (max - min) + min; } }; -// ----------------------------------------------------------------------- -// Parameter - +/** + Parameter. + */ struct Parameter { + /** + Hints describing this parameter. + @see ParameterHints + */ uint32_t hints; + + /** + The name of this parameter. + A parameter name can contain any character, but hosts might have a hard time with non-ascii ones. + The name doesn't have to be unique within a plugin instance, but it's recommended. + */ d_string name; + + /** + The symbol of this parameter. + A parameter symbol is a short restricted name used as a machine and human readable identifier. + The first character must be one of _, a-z or A-Z and subsequent characters can be from _, a-z, A-Z and 0-9. + @note: Parameter symbols MUST be unique within a plugin instance. + */ d_string symbol; + + /** + The unit of this parameter. + This means something like "dB", "kHz" and "ms". + Can be left blank if units do not apply to this parameter. + */ d_string unit; + + /** + Ranges of this parameter. + The ranges describe the default, minimum and maximum values. + */ ParameterRanges ranges; + /** + Default constructor for a null parameter. + */ Parameter() noexcept - : hints(0x0) {} - - void clear() noexcept - { - hints = 0x0; - name = ""; - symbol = ""; - unit = ""; - ranges.clear(); - } + : hints(0x0), + name(), + symbol(), + unit(), + ranges() {} }; -// ----------------------------------------------------------------------- -// MidiEvent - +/** + MIDI event. + */ struct MidiEvent { + /** + Size of internal data. + */ + static const uint32_t kDataSize = 4; + + /** + Time offset in frames. + */ uint32_t frame; - uint8_t size; - uint8_t buf[4]; - void clear() noexcept - { - frame = 0; - size = 0; - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - } + /** + Number of bytes used. + */ + uint32_t size; + + /** + MIDI data. + If size > kDataSize, dataExt is used (otherwise null). + */ + uint8_t data[kDataSize]; + const uint8_t* dataExt; }; -// ----------------------------------------------------------------------- -// TimePos +/** + Time position. + The @a playing and @a frame values are always valid. + BBT values are only valid when @a bbt.valid is true. -struct TimePos { + This struct is inspired by the JACK Transport API. + */ +struct TimePosition { + /** + Wherever the host transport is playing/rolling. + */ bool playing; + + /** + Current host transport position in frames. + */ uint64_t frame; - struct BeatBarTick { + /** + Bar-Beat-Tick time position. + */ + struct BarBeatTick { + /** + Wherever the host transport is using BBT. + If false you must not read from this struct. + */ bool valid; - int32_t bar; /*!< current bar */ - int32_t beat; /*!< current beat-within-bar */ - int32_t tick; /*!< current tick-within-beat */ + /** + Current bar. + Should always be > 0. + The first bar is bar '1'. + */ + int32_t bar; + + /** + Current beat within bar. + Should always be > 0 and <= @a beatsPerBar. + The first beat is beat '1'. + */ + int32_t beat; + + /** + Current tick within beat. + Should always be > 0 and <= @a ticksPerBeat. + The first tick is tick '0'. + */ + int32_t tick; + + /** + Number of ticks that have elapsed between frame 0 and the first beat of the current measure. + */ double barStartTick; - float beatsPerBar; /*!< time signature "numerator" */ - float beatType; /*!< time signature "denominator" */ + /** + Time signature "numerator". + */ + float beatsPerBar; + /** + Time signature "denominator". + */ + float beatType; + + /** + Number of ticks within a bar. + Usually a moderately large integer with many denominators, such as 1920.0. + */ double ticksPerBeat; + + /** + Number of beats per minute. + */ double beatsPerMinute; - BeatBarTick() noexcept + /** + Default constructor for a null BBT time position. + */ + BarBeatTick() noexcept : valid(false), bar(0), beat(0), @@ -219,84 +366,252 @@ struct TimePos { beatsPerMinute(0.0) {} } bbt; - TimePos() noexcept + /** + Default constructor for a time position. + */ + TimePosition() noexcept : playing(false), - frame(0) {} + frame(0), + bbt() {} }; -// ----------------------------------------------------------------------- -// Plugin +/* ------------------------------------------------------------------------------------------------------------ + * DPF Plugin */ + +/** + DPF Plugin class from where plugin instances are created. + + The public methods (Host state) are called from the plugin to get or set host information. + They can be called from a plugin instance at anytime unless stated otherwise. + All other methods are to be implemented by the plugin and will be called by the host. + + Shortly after a plugin instance is created, the various d_init* functions will be called by the host. + Host will call d_activate() before d_run(), and d_deactivate() before the plugin instance is destroyed. + The host may call deactivate right after activate and vice-versa, but never activate/deactivate consecutively. + There is no limit on how many times d_run() is called, only that activate/deactivate will be called in between. + + The buffer size and sample rate values will remain constant between activate and deactivate. + Buffer size is only a hint though, the host might call d_run() with a higher or lower number of frames. + + Some of this class functions are only available according to some macros. + + DISTRHO_PLUGIN_WANT_PROGRAMS activates program related features. + When enabled you need to implement d_initProgramName() and d_setProgram(). + DISTRHO_PLUGIN_WANT_STATE activates internal state features. + When enabled you need to implement d_initStateKey() and d_setState(). + + The process function d_run() changes wherever DISTRHO_PLUGIN_HAS_MIDI_INPUT is enabled or not. + When enabled it provides midi input events. + */ class Plugin { public: - Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount); + /** + Plugin class constructor. + You must set all parameter values to their defaults, matching ParameterRanges::def. + If you're using states you must also set them to their defaults by calling d_setState(). + */ + Plugin(const uint32_t parameterCount, const uint32_t programCount, const uint32_t stateCount); + + /** + Destructor. + */ virtual ~Plugin(); - // ------------------------------------------------------------------- - // Host state + /* -------------------------------------------------------------------------------------------------------- + * Host state */ + + /** + Get the current buffer size that will probably be used during processing, in frames. + This value will remain constant between activate and deactivate. + @note: This value is only a hint! + Hosts might call d_run() with a higher or lower number of frames. + @see d_bufferSizeChanged(uint32_t) + */ + uint32_t d_getBufferSize() const noexcept; + + /** + Get the current sample rate that will be used during processing. + This value will remain constant between activate and deactivate. + @see d_sampleRateChanged(double) + */ + double d_getSampleRate() const noexcept; - uint32_t d_getBufferSize() const noexcept; - double d_getSampleRate() const noexcept; #if DISTRHO_PLUGIN_WANT_TIMEPOS - const TimePos& d_getTimePos() const noexcept; + /** + Get the current host transport time position. + This function should only be called during d_run(). + You can call this during other times, but the returned position is not guaranteed to be in sync. + @note: TimePos is not supported in LADSPA and DSSI plugin formats. + */ + const TimePosition& d_getTimePosition() const noexcept; #endif + #if DISTRHO_PLUGIN_WANT_LATENCY - void d_setLatency(uint32_t frames) noexcept; + /** + Change the plugin audio output latency to @a frames. + This function should only be called in the constructor, d_activate() and d_run(). + */ + void d_setLatency(const uint32_t frames) noexcept; #endif -protected: - // ------------------------------------------------------------------- - // Information - - virtual const char* d_getName() const noexcept { return DISTRHO_PLUGIN_NAME; } - virtual const char* d_getLabel() const noexcept = 0; - virtual const char* d_getMaker() const noexcept = 0; - virtual const char* d_getLicense() const noexcept = 0; - virtual uint32_t d_getVersion() const noexcept = 0; - virtual long d_getUniqueId() const noexcept = 0; - - // ------------------------------------------------------------------- - // Init +#if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT + /** + Write a MIDI output event. + This function must only be called during d_run(). + Returns false when the host buffer is full, in which case do not call this again until the next d_run(). + */ + bool d_writeMidiEvent(const MidiEvent& midiEvent) noexcept; +#endif +protected: + /* -------------------------------------------------------------------------------------------------------- + * Information */ + + /** + Get the plugin name. + Returns DISTRHO_PLUGIN_NAME by default. + */ + virtual const char* d_getName() const { return DISTRHO_PLUGIN_NAME; } + + /** + Get the plugin label. + A plugin label follows the same rules as Parameter::symbol, with the exception that it can start with numbers. + */ + virtual const char* d_getLabel() const = 0; + + /** + Get the plugin author/maker. + */ + virtual const char* d_getMaker() const = 0; + + /** + Get the plugin license name (a single line of text). + */ + virtual const char* d_getLicense() const = 0; + + /** + Get the plugin version, in hexadecimal. + TODO format to be defined + */ + virtual uint32_t d_getVersion() const = 0; + + /** + Get the plugin unique Id. + This value is used by LADSPA, DSSI and VST plugin formats. + */ + virtual int64_t d_getUniqueId() const = 0; + + /* -------------------------------------------------------------------------------------------------------- + * Init */ + + /** + Initialize the parameter @a index. + This function will be called once, shortly after the plugin is created. + */ virtual void d_initParameter(uint32_t index, Parameter& parameter) = 0; + #if DISTRHO_PLUGIN_WANT_PROGRAMS + /** + Set the name of the program @a index. + This function will be called once, shortly after the plugin is created. + Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_PROGRAMS is enabled. + */ virtual void d_initProgramName(uint32_t index, d_string& programName) = 0; #endif + #if DISTRHO_PLUGIN_WANT_STATE - virtual void d_initStateKey(uint32_t index, d_string& stateKey) = 0; + /** + Set the state key and default value of @a index. + This function will be called once, shortly after the plugin is created. + Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled. + */ + virtual void d_initState(uint32_t index, d_string& stateKey, d_string& defaultStateValue) = 0; #endif - // ------------------------------------------------------------------- - // Internal data + /* -------------------------------------------------------------------------------------------------------- + * Internal data */ + /** + Get the current value of a parameter. + The host may call this function from any context, including realtime processing. + */ virtual float d_getParameterValue(uint32_t index) const = 0; - virtual void d_setParameterValue(uint32_t index, float value) = 0; + + /** + Change a parameter value. + The host may call this function from any context, including realtime processing. + When a parameter is marked as automable, you must ensure no non-realtime operations are called. + @note This function will only be called for parameter inputs. + */ + virtual void d_setParameterValue(uint32_t index, float value) = 0; + #if DISTRHO_PLUGIN_WANT_PROGRAMS - virtual void d_setProgram(uint32_t index) = 0; + /** + Change the currently used program to @a index. + The host may call this function from any context, including realtime processing. + Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_PROGRAMS is enabled. + */ + virtual void d_setProgram(uint32_t index) = 0; #endif + #if DISTRHO_PLUGIN_WANT_STATE - virtual void d_setState(const char* key, const char* value) = 0; + /** + Change an internal state @a key to @a value. + Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled. + */ + virtual void d_setState(const char* key, const char* value) = 0; #endif - // ------------------------------------------------------------------- - // Process + /* -------------------------------------------------------------------------------------------------------- + * Process */ + /** + Activate this plugin. + */ virtual void d_activate() {} + + /** + Deactivate this plugin. + */ virtual void d_deactivate() {} -#if DISTRHO_PLUGIN_IS_SYNTH - virtual void d_run(const float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) = 0; + +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT + /** + Run/process function for plugins with MIDI input. + @note: Some parameters might be null if there are no audio inputs/outputs or MIDI events. + */ + virtual void d_run(const float** inputs, float** outputs, uint32_t frames, + const MidiEvent* midiEvents, uint32_t midiEventCount) = 0; #else + /** + Run/process function for plugins without MIDI input. + @note: Some parameters might be null if there are no audio inputs or outputs. + */ virtual void d_run(const float** inputs, float** outputs, uint32_t frames) = 0; #endif - // ------------------------------------------------------------------- - // Callbacks (optional) + /* -------------------------------------------------------------------------------------------------------- + * Callbacks (optional) */ + /** + Optional callback to inform the plugin about a buffer size change. + This function will only be called when the plugin is deactivated. + @note: This value is only a hint! + Hosts might call d_run() with a higher or lower number of frames. + @see d_getBufferSize() + */ virtual void d_bufferSizeChanged(uint32_t newBufferSize); + + /** + Optional callback to inform the plugin about a sample rate change. + This function will only be called when the plugin is deactivated. + @see d_getSampleRate() + */ virtual void d_sampleRateChanged(double newSampleRate); - // ------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------- private: struct PrivateData; @@ -306,12 +621,15 @@ private: DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Plugin) }; -// ----------------------------------------------------------------------- -// Create plugin, entry point +/* ------------------------------------------------------------------------------------------------------------ + * Create plugin, entry point */ +/** + TODO. + */ extern Plugin* createPlugin(); -// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------------------------- END_NAMESPACE_DISTRHO diff --git a/libs/distrho/DistrhoUI.hpp b/libs/distrho/DistrhoUI.hpp index 98af2a0..b6b2402 100644 --- a/libs/distrho/DistrhoUI.hpp +++ b/libs/distrho/DistrhoUI.hpp @@ -20,77 +20,157 @@ #include "extra/d_leakdetector.hpp" #include "src/DistrhoPluginChecks.h" -#include "../dgl/Widget.hpp" - -#if DISTRHO_UI_USE_NANOVG +#if DISTRHO_UI_USE_NTK +# include "../dgl/ntk/NtkWidget.hpp" +typedef DGL::NtkWidget UIWidget; +#elif DISTRHO_UI_USE_NANOVG # include "../dgl/NanoVG.hpp" typedef DGL::NanoWidget UIWidget; -#else +# else +# include "../dgl/Widget.hpp" typedef DGL::Widget UIWidget; #endif START_NAMESPACE_DISTRHO -// ----------------------------------------------------------------------- -// UI +/* ------------------------------------------------------------------------------------------------------------ + * DPF UI */ + +/** + DPF UI class from where UI instances are created. + + TODO. + must call setSize during construction, + */ class UI : public UIWidget { public: + /** + UI class constructor. + The UI should be initialized to a default state that matches the plugin side. + */ UI(); + + /** + Destructor. + */ virtual ~UI(); - // ------------------------------------------------------------------- - // Host DSP State + /* -------------------------------------------------------------------------------------------------------- + * Host state */ + /** + Get the current sample rate used in plugin processing. + @see d_sampleRateChanged(double) + */ double d_getSampleRate() const noexcept; - void d_editParameter(uint32_t index, bool started); - void d_setParameterValue(uint32_t index, float value); + + /** + TODO: Document this. + */ + void d_editParameter(const uint32_t index, const bool started); + + /** + TODO: Document this. + */ + void d_setParameterValue(const uint32_t index, const float value); + #if DISTRHO_PLUGIN_WANT_STATE - void d_setState(const char* key, const char* value); + /** + TODO: Document this. + */ + void d_setState(const char* const key, const char* const value); #endif + #if DISTRHO_PLUGIN_IS_SYNTH - void d_sendNote(uint8_t channel, uint8_t note, uint8_t velocity); + /** + TODO: Document this. + */ + void d_sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity); #endif - // ------------------------------------------------------------------- - // Host UI State - - void d_setSize(uint width, uint height); - #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS - // ------------------------------------------------------------------- - // Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! + /* -------------------------------------------------------------------------------------------------------- + * Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! */ + /** + TODO: Document this. + */ void* d_getPluginInstancePointer() const noexcept; #endif protected: - // ------------------------------------------------------------------- - // Basic Information - - 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 + /* -------------------------------------------------------------------------------------------------------- + * DSP/Plugin Callbacks */ + /** + A parameter has changed on the plugin side. + This is called by the host to inform the UI about parameter changes. + */ virtual void d_parameterChanged(uint32_t index, float value) = 0; + #if DISTRHO_PLUGIN_WANT_PROGRAMS + /** + The current program has changed on the plugin side. + This is called by the host to inform the UI about program changes. + */ virtual void d_programChanged(uint32_t index) = 0; #endif + #if DISTRHO_PLUGIN_WANT_STATE + /** + A state has changed on the plugin side. + This is called by the host to inform the UI about state changes. + */ virtual void d_stateChanged(const char* key, const char* value) = 0; #endif - // ------------------------------------------------------------------- - // UI Callbacks (optional) + /* -------------------------------------------------------------------------------------------------------- + * DSP/Plugin Callbacks (optional) */ + + /** + Optional callback to inform the UI about a sample rate change on the plugin side. + @see d_getSampleRate() + */ + virtual void d_sampleRateChanged(double newSampleRate); + + /* -------------------------------------------------------------------------------------------------------- + * UI Callbacks (optional) */ + /** + TODO: Document this. + */ virtual void d_uiIdle() {} - virtual void d_uiReshape(int width, int height); - // ------------------------------------------------------------------- +#if ! DISTRHO_UI_USE_NTK + /** + OpenGL window reshape function, called when parent window is resized. + You can reimplement this function for a custom OpenGL state. + @see Window::onReshape(uint,uint) + */ + virtual void d_uiReshape(uint width, uint height); +#endif + + /* -------------------------------------------------------------------------------------------------------- + * UI Resize Handling, internal */ + +#if DISTRHO_UI_USE_NTK + /** + NTK widget resize function, called when the widget is resized. + This is overriden here so the host knows when the UI is resized by you. + */ + void resize(int x, int y, int w, int h) override; +#else + /** + OpenGL widget resize function, called when the widget is resized. + This is overriden here so the host knows when the UI is resized by you. + @see Widget::onResize(const ResizeEvent&) + */ + void onResize(const ResizeEvent& ev) override; +#endif + + // ------------------------------------------------------------------------------------------------------- private: struct PrivateData; @@ -99,21 +179,27 @@ private: friend class UIExporterWindow; // these should not be used + void position(int, int) noexcept {} void setAbsoluteX(int) const noexcept {} void setAbsoluteY(int) const noexcept {} void setAbsolutePos(int, int) const noexcept {} - void setAbsolutePos(const DGL::Point<int>&) const noexcept {} void setNeedsFullViewport(bool) const noexcept {} +#if ! DISTRHO_UI_USE_NTK + void setAbsolutePos(const DGL::Point<int>&) const noexcept {} +#endif DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI) }; -// ----------------------------------------------------------------------- -// Create UI, entry point +/* ------------------------------------------------------------------------------------------------------------ + * Create UI, entry point */ +/** + TODO. + */ extern UI* createUI(); -// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------------------------- END_NAMESPACE_DISTRHO diff --git a/libs/distrho/DistrhoUtils.hpp b/libs/distrho/DistrhoUtils.hpp index 76669d2..2dd4195 100644 --- a/libs/distrho/DistrhoUtils.hpp +++ b/libs/distrho/DistrhoUtils.hpp @@ -24,7 +24,7 @@ #include <cstdlib> #include <cstring> -#ifdef PROPER_CPP11_SUPPORT +#ifdef DISTRHO_PROPER_CPP11_SUPPORT # include <cstdint> #else # include <stdint.h> @@ -51,7 +51,7 @@ inline float // misc functions static inline -long d_cconst(const int a, const int b, const int c, const int d) noexcept +int64_t d_cconst(const int a, const int b, const int c, const int d) noexcept { return (a << 24) | (b << 16) | (c << 8) | (d << 0); } diff --git a/libs/distrho/extra/d_leakdetector.hpp b/libs/distrho/extra/d_leakdetector.hpp index ede4db9..2840c2d 100644 --- a/libs/distrho/extra/d_leakdetector.hpp +++ b/libs/distrho/extra/d_leakdetector.hpp @@ -19,6 +19,8 @@ #include "../DistrhoUtils.hpp" +START_NAMESPACE_DISTRHO + // ----------------------------------------------------------------------- // The following code was based from juce-core LeakDetector class // Copyright (C) 2013 Raw Material Software Ltd. @@ -45,10 +47,10 @@ }; \endcode */ -#define DISTRHO_LEAK_DETECTOR(ClassName) \ - friend class ::DistrhoLeakedObjectDetector<ClassName>; \ +#define DISTRHO_LEAK_DETECTOR(ClassName) \ + friend class DISTRHO_NAMESPACE::LeakedObjectDetector<ClassName>; \ static const char* getLeakedObjectClassName() noexcept { return #ClassName; } \ - ::DistrhoLeakedObjectDetector<ClassName> DISTRHO_JOIN_MACRO(leakDetector, __LINE__); + DISTRHO_NAMESPACE::LeakedObjectDetector<ClassName> DISTRHO_JOIN_MACRO(leakDetector_, ClassName); #define DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ClassName) \ DISTRHO_DECLARE_NON_COPY_CLASS(ClassName) \ @@ -67,14 +69,14 @@ class declaration. */ template<class OwnerClass> -class DistrhoLeakedObjectDetector +class LeakedObjectDetector { public: //============================================================================== - DistrhoLeakedObjectDetector() noexcept { ++(getCounter().numObjects); } - DistrhoLeakedObjectDetector(const DistrhoLeakedObjectDetector&) noexcept { ++(getCounter().numObjects); } + LeakedObjectDetector() noexcept { ++(getCounter().numObjects); } + LeakedObjectDetector(const LeakedObjectDetector&) noexcept { ++(getCounter().numObjects); } - ~DistrhoLeakedObjectDetector() noexcept + ~LeakedObjectDetector() noexcept { if (--(getCounter().numObjects) < 0) { @@ -99,9 +101,7 @@ private: { public: LeakCounter() noexcept - { - numObjects = 0; - } + : numObjects(0) {} ~LeakCounter() noexcept { @@ -136,4 +136,6 @@ private: // ----------------------------------------------------------------------- +END_NAMESPACE_DISTRHO + #endif // DISTRHO_LEAK_DETECTOR_HPP_INCLUDED diff --git a/libs/distrho/extra/d_mutex.hpp b/libs/distrho/extra/d_mutex.hpp index 8bbcb11..df704e0 100644 --- a/libs/distrho/extra/d_mutex.hpp +++ b/libs/distrho/extra/d_mutex.hpp @@ -26,6 +26,8 @@ #include <pthread.h> +START_NAMESPACE_DISTRHO + // ----------------------------------------------------------------------- // Mutex class @@ -223,4 +225,6 @@ typedef ScopedUnlocker<RecursiveMutex> RecursiveMutexUnlocker; // ----------------------------------------------------------------------- +END_NAMESPACE_DISTRHO + #endif // DISTRHO_MUTEX_HPP_INCLUDED diff --git a/libs/distrho/extra/d_scopedpointer.hpp b/libs/distrho/extra/d_scopedpointer.hpp index d7cc4eb..bde4e7b 100644 --- a/libs/distrho/extra/d_scopedpointer.hpp +++ b/libs/distrho/extra/d_scopedpointer.hpp @@ -21,6 +21,8 @@ #include <algorithm> +START_NAMESPACE_DISTRHO + // ----------------------------------------------------------------------- // The following code was based from juce-core ScopedPointer class // Copyright (C) 2013 Raw Material Software Ltd. @@ -180,7 +182,7 @@ public: { // Two ScopedPointers should never be able to refer to the same object - if // this happens, you must have done something dodgy! - DISTRHO_SAFE_ASSERT_RETURN(object != other.object && this != other.getAddress(),); + DISTRHO_SAFE_ASSERT_RETURN(object != other.object || this == other.getAddress() || object == nullptr,); std::swap(object, other.object); } @@ -240,4 +242,6 @@ bool operator!=(const ScopedPointer<ObjectType>& pointer1, ObjectType* const poi // ----------------------------------------------------------------------- +END_NAMESPACE_DISTRHO + #endif // DISTRHO_SCOPED_POINTER_HPP_INCLUDED diff --git a/libs/distrho/extra/d_string.hpp b/libs/distrho/extra/d_string.hpp index 3020d90..0420c42 100644 --- a/libs/distrho/extra/d_string.hpp +++ b/libs/distrho/extra/d_string.hpp @@ -19,6 +19,8 @@ #include "d_leakdetector.hpp" +START_NAMESPACE_DISTRHO + // ----------------------------------------------------------------------- // d_string class @@ -743,4 +745,6 @@ d_string operator+(const char* const strBufBefore, const d_string& strAfter) noe // ----------------------------------------------------------------------- +END_NAMESPACE_DISTRHO + #endif // DISTRHO_STRING_HPP_INCLUDED diff --git a/libs/distrho/src/DistrhoDefines.h b/libs/distrho/src/DistrhoDefines.h index 8e70e12..501fc28 100644 --- a/libs/distrho/src/DistrhoDefines.h +++ b/libs/distrho/src/DistrhoDefines.h @@ -48,16 +48,16 @@ /* Check for C++11 support */ #if defined(HAVE_CPP11_SUPPORT) -# define PROPER_CPP11_SUPPORT +# define DISTRHO_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) || (defined(__CLANG__) && ! __has_extension(cxx_override_control)) +# define DISTRHO_PROPER_CPP11_SUPPORT +# if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407 && ! defined(__clang__)) || (defined(__clang__) && ! __has_extension(cxx_override_control)) # define override // gcc4.7+ only # define final // gcc4.7+ only # endif #endif -#ifndef PROPER_CPP11_SUPPORT +#ifndef DISTRHO_PROPER_CPP11_SUPPORT # define noexcept throw() # define override # define final diff --git a/libs/distrho/src/DistrhoPlugin.cpp b/libs/distrho/src/DistrhoPlugin.cpp index f1b079b..9b301be 100644 --- a/libs/distrho/src/DistrhoPlugin.cpp +++ b/libs/distrho/src/DistrhoPlugin.cpp @@ -18,22 +18,22 @@ START_NAMESPACE_DISTRHO -// ----------------------------------------------------------------------- -// Static data, see DistrhoPluginInternal.hpp +/* ------------------------------------------------------------------------------------------------------------ + * Static data, see DistrhoPluginInternal.hpp */ uint32_t d_lastBufferSize = 0; double d_lastSampleRate = 0.0; -// ----------------------------------------------------------------------- -// Static fallback data, see DistrhoPluginInternal.hpp +/* ------------------------------------------------------------------------------------------------------------ + * Static fallback data, see DistrhoPluginInternal.hpp */ const d_string PluginExporter::sFallbackString; const ParameterRanges PluginExporter::sFallbackRanges; -// ----------------------------------------------------------------------- -// Plugin +/* ------------------------------------------------------------------------------------------------------------ + * Plugin */ -Plugin::Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount) +Plugin::Plugin(const uint32_t parameterCount, const uint32_t programCount, const uint32_t stateCount) : pData(new PrivateData()) { if (parameterCount > 0) @@ -42,21 +42,26 @@ Plugin::Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCou pData->parameters = new Parameter[parameterCount]; } +#if DISTRHO_PLUGIN_WANT_PROGRAMS if (programCount > 0) { -#if DISTRHO_PLUGIN_WANT_PROGRAMS pData->programCount = programCount; pData->programNames = new d_string[programCount]; -#endif } +#else + DISTRHO_SAFE_ASSERT(programCount == 0); +#endif +#if DISTRHO_PLUGIN_WANT_STATE if (stateCount > 0) { -#if DISTRHO_PLUGIN_WANT_STATE - pData->stateCount = stateCount; - pData->stateKeys = new d_string[stateCount]; -#endif + pData->stateCount = stateCount; + pData->stateKeys = new d_string[stateCount]; + pData->stateDefValues = new d_string[stateCount]; } +#else + DISTRHO_SAFE_ASSERT(stateCount == 0); +#endif } Plugin::~Plugin() @@ -64,8 +69,8 @@ Plugin::~Plugin() delete pData; } -// ----------------------------------------------------------------------- -// Host state +/* ------------------------------------------------------------------------------------------------------------ + * Host state */ uint32_t Plugin::d_getBufferSize() const noexcept { @@ -78,33 +83,33 @@ double Plugin::d_getSampleRate() const noexcept } #if DISTRHO_PLUGIN_WANT_TIMEPOS -const TimePos& Plugin::d_getTimePos() const noexcept +const TimePosition& Plugin::d_getTimePosition() const noexcept { - // timePos outside run() may not be valid - DISTRHO_SAFE_ASSERT(pData->isProcessing); - - return pData->timePos; + return pData->timePosition; } #endif #if DISTRHO_PLUGIN_WANT_LATENCY -void Plugin::d_setLatency(uint32_t frames) noexcept +void Plugin::d_setLatency(const uint32_t frames) noexcept { pData->latency = frames; } #endif -// ----------------------------------------------------------------------- -// Callbacks (optional) - -void Plugin::d_bufferSizeChanged(uint32_t) +#if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT +bool Plugin::d_writeMidiEvent(const MidiEvent& /*midiEvent*/) noexcept { + // TODO + return false; } +#endif -void Plugin::d_sampleRateChanged(double) -{ -} +/* ------------------------------------------------------------------------------------------------------------ + * Callbacks (optional) */ + +void Plugin::d_bufferSizeChanged(uint32_t) {} +void Plugin::d_sampleRateChanged(double) {} -// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------------------------- END_NAMESPACE_DISTRHO diff --git a/libs/distrho/src/DistrhoPluginCarla.cpp b/libs/distrho/src/DistrhoPluginCarla.cpp index 2e1b771..3ba0b11 100644 --- a/libs/distrho/src/DistrhoPluginCarla.cpp +++ b/libs/distrho/src/DistrhoPluginCarla.cpp @@ -214,15 +214,15 @@ protected: int nativeParamHints = ::PARAMETER_IS_ENABLED; const uint32_t paramHints = fPlugin.getParameterHints(index); - if (paramHints & PARAMETER_IS_AUTOMABLE) + if (paramHints & kParameterIsAutomable) nativeParamHints |= ::PARAMETER_IS_AUTOMABLE; - if (paramHints & PARAMETER_IS_BOOLEAN) + if (paramHints & kParameterIsBoolean) nativeParamHints |= ::PARAMETER_IS_BOOLEAN; - if (paramHints & PARAMETER_IS_INTEGER) + if (paramHints & kParameterIsInteger) nativeParamHints |= ::PARAMETER_IS_INTEGER; - if (paramHints & PARAMETER_IS_LOGARITHMIC) + if (paramHints & kParameterIsLogarithmic) nativeParamHints |= ::PARAMETER_IS_LOGARITHMIC; - if (paramHints & PARAMETER_IS_OUTPUT) + if (paramHints & kParameterIsOutput) nativeParamHints |= ::PARAMETER_IS_OUTPUT; param.hints = static_cast<NativeParameterHints>(nativeParamHints); diff --git a/libs/distrho/src/DistrhoPluginChecks.h b/libs/distrho/src/DistrhoPluginChecks.h index 3a06ee4..f556c06 100644 --- a/libs/distrho/src/DistrhoPluginChecks.h +++ b/libs/distrho/src/DistrhoPluginChecks.h @@ -19,6 +19,9 @@ #include "DistrhoPluginInfo.h" +// ----------------------------------------------------------------------- +// Check if all required macros are defined + #ifndef DISTRHO_PLUGIN_NAME # error DISTRHO_PLUGIN_NAME undefined! #endif @@ -55,18 +58,52 @@ # error DISTRHO_PLUGIN_WANT_TIMEPOS undefined! #endif -#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS -# define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 +// ----------------------------------------------------------------------- +// Test if synth has audio outputs + +#if DISTRHO_PLUGIN_IS_SYNTH && DISTRHO_PLUGIN_NUM_OUTPUTS == 0 +# error Synths need audio output to work! +#endif + +// ----------------------------------------------------------------------- +// Enable MIDI input if synth, test if midi-input disabled when synth + +#ifndef DISTRHO_PLUGIN_HAS_MIDI_INPUT +# define DISTRHO_PLUGIN_HAS_MIDI_INPUT DISTRHO_PLUGIN_IS_SYNTH +#elif DISTRHO_PLUGIN_IS_SYNTH && ! DISTRHO_PLUGIN_HAS_MIDI_INPUT +# error Synths need MIDI input to work! +#endif + +// ----------------------------------------------------------------------- +// Define optional macros if not done yet + +#ifndef DISTRHO_PLUGIN_HAS_MIDI_OUTPUT +# define DISTRHO_PLUGIN_HAS_MIDI_OUTPUT 0 #endif #ifndef DISTRHO_PLUGIN_IS_RT_SAFE -# define DISTRHO_PLUGIN_IS_RT_SAFE 1 +# define DISTRHO_PLUGIN_IS_RT_SAFE 0 +#endif + +#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS +# define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 #endif #ifndef DISTRHO_UI_USE_NANOVG # define DISTRHO_UI_USE_NANOVG 0 #endif -#define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI" +#ifndef DISTRHO_UI_USE_NTK +# define DISTRHO_UI_USE_NTK 0 +#endif + +// ----------------------------------------------------------------------- +// Define DISTRHO_UI_URI if needed + +#ifndef DISTRHO_UI_URI +# define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI" +#endif + +// ----------------------------------------------------------------------- #endif // DISTRHO_PLUGIN_CHECKS_H_INCLUDED diff --git a/libs/distrho/src/DistrhoPluginInternal.hpp b/libs/distrho/src/DistrhoPluginInternal.hpp index a604c23..7b4c04b 100644 --- a/libs/distrho/src/DistrhoPluginInternal.hpp +++ b/libs/distrho/src/DistrhoPluginInternal.hpp @@ -49,6 +49,7 @@ struct Plugin::PrivateData { #if DISTRHO_PLUGIN_WANT_STATE uint32_t stateCount; d_string* stateKeys; + d_string* stateDefValues; #endif #if DISTRHO_PLUGIN_WANT_LATENCY @@ -56,7 +57,7 @@ struct Plugin::PrivateData { #endif #if DISTRHO_PLUGIN_WANT_TIMEPOS - TimePos timePos; + TimePosition timePosition; #endif uint32_t bufferSize; @@ -73,6 +74,7 @@ struct Plugin::PrivateData { #if DISTRHO_PLUGIN_WANT_STATE stateCount(0), stateKeys(nullptr), + stateDefValues(nullptr), #endif #if DISTRHO_PLUGIN_WANT_LATENCY latency(0), @@ -106,6 +108,12 @@ struct Plugin::PrivateData { delete[] stateKeys; stateKeys = nullptr; } + + if (stateDefValues != nullptr) + { + delete[] stateDefValues; + stateDefValues = nullptr; + } #endif } }; @@ -118,7 +126,8 @@ class PluginExporter public: PluginExporter() : fPlugin(createPlugin()), - fData((fPlugin != nullptr) ? fPlugin->pData : nullptr) + fData((fPlugin != nullptr) ? fPlugin->pData : nullptr), + fIsActive(false) { DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); @@ -133,7 +142,7 @@ public: #if DISTRHO_PLUGIN_WANT_STATE for (uint32_t i=0, count=fData->stateCount; i < count; ++i) - fPlugin->d_initStateKey(i, fData->stateKeys[i]); + fPlugin->d_initState(i, fData->stateKeys[i], fData->stateDefValues[i]); #endif } @@ -218,7 +227,7 @@ public: bool isParameterOutput(const uint32_t index) const noexcept { - return (getParameterHints(index) & PARAMETER_IS_OUTPUT); + return (getParameterHints(index) & kParameterIsOutput); } const d_string& getParameterName(const uint32_t index) const noexcept @@ -304,6 +313,13 @@ public: return fData->stateKeys[index]; } + const d_string& getStateDefaultValue(const uint32_t index) const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->stateCount, sFallbackString); + + return fData->stateDefValues[index]; + } + void setState(const char* const key, const char* const value) { DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); @@ -329,11 +345,11 @@ public: #endif #if DISTRHO_PLUGIN_WANT_TIMEPOS - void setTimePos(const TimePos& timePos) noexcept + void setTimePosition(const TimePosition& timePosition) noexcept { DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); - std::memcpy(&fData->timePos, &timePos, sizeof(TimePos)); + std::memcpy(&fData->timePosition, &timePosition, sizeof(TimePosition)); } #endif @@ -343,6 +359,7 @@ public: { DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + fIsActive = true; fPlugin->d_activate(); } @@ -350,11 +367,13 @@ public: { DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); + fIsActive = false; fPlugin->d_deactivate(); } #if DISTRHO_PLUGIN_IS_SYNTH - void run(const float** const inputs, float** const outputs, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) + void run(const float** const inputs, float** const outputs, const uint32_t frames, + const MidiEvent* const midiEvents, const uint32_t midiEventCount) { DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); @@ -377,7 +396,19 @@ public: // ------------------------------------------------------------------- - void setBufferSize(const uint32_t bufferSize, bool doCallback = false) + uint32_t getBufferSize() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0); + return fData->bufferSize; + } + + double getSampleRate() const noexcept + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0.0); + return fData->sampleRate; + } + + void setBufferSize(const uint32_t bufferSize, const bool doCallback = false) { DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); @@ -390,13 +421,13 @@ public: if (doCallback) { - fPlugin->d_deactivate(); + if (fIsActive) fPlugin->d_deactivate(); fPlugin->d_bufferSizeChanged(bufferSize); - fPlugin->d_activate(); + if (fIsActive) fPlugin->d_activate(); } } - void setSampleRate(const double sampleRate, bool doCallback = false) + void setSampleRate(const double sampleRate, const bool doCallback = false) { DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fPlugin != nullptr,); @@ -409,9 +440,9 @@ public: if (doCallback) { - fPlugin->d_deactivate(); + if (fIsActive) fPlugin->d_deactivate(); fPlugin->d_sampleRateChanged(sampleRate); - fPlugin->d_activate(); + if (fIsActive) fPlugin->d_activate(); } } @@ -421,6 +452,7 @@ private: Plugin* const fPlugin; Plugin::PrivateData* const fData; + bool fIsActive; // ------------------------------------------------------------------- // Static fallback data, see DistrhoPlugin.cpp diff --git a/libs/distrho/src/DistrhoPluginJack.cpp b/libs/distrho/src/DistrhoPluginJack.cpp index 20b8a47..2de1165 100644 --- a/libs/distrho/src/DistrhoPluginJack.cpp +++ b/libs/distrho/src/DistrhoPluginJack.cpp @@ -105,9 +105,9 @@ public: jack_activate(fClient); if (const char* const name = jack_get_client_name(fClient)) - fUI.setTitle(name); + fUI.setWindowTitle(name); else - fUI.setTitle(DISTRHO_PLUGIN_NAME); + fUI.setWindowTitle(fPlugin.getName()); fUI.exec(this); } @@ -199,40 +199,37 @@ protected: #if DISTRHO_PLUGIN_WANT_TIMEPOS jack_position_t pos; - fTimePos.playing = (jack_transport_query(fClient, &pos) == JackTransportRolling); + fTimePosition.playing = (jack_transport_query(fClient, &pos) == JackTransportRolling); if (pos.unique_1 == pos.unique_2) { - if (pos.valid & JackTransportPosition) - fTimePos.frame = pos.frame; - else - fTimePos.frame = 0; + fTimePosition.frame = pos.frame; if (pos.valid & JackTransportBBT) { - fTimePos.bbt.valid = true; + fTimePosition.bbt.valid = true; - fTimePos.bbt.bar = pos.bar; - fTimePos.bbt.beat = pos.beat; - fTimePos.bbt.tick = pos.tick; - fTimePos.bbt.barStartTick = pos.bar_start_tick; + fTimePosition.bbt.bar = pos.bar; + fTimePosition.bbt.beat = pos.beat; + fTimePosition.bbt.tick = pos.tick; + fTimePosition.bbt.barStartTick = pos.bar_start_tick; - fTimePos.bbt.beatsPerBar = pos.beats_per_bar; - fTimePos.bbt.beatType = pos.beat_type; + fTimePosition.bbt.beatsPerBar = pos.beats_per_bar; + fTimePosition.bbt.beatType = pos.beat_type; - fTimePos.bbt.ticksPerBeat = pos.ticks_per_beat; - fTimePos.bbt.beatsPerMinute = pos.beats_per_minute; + fTimePosition.bbt.ticksPerBeat = pos.ticks_per_beat; + fTimePosition.bbt.beatsPerMinute = pos.beats_per_minute; } else - fTimePos.bbt.valid = false; + fTimePosition.bbt.valid = false; } else { - fTimePos.bbt.valid = false; - fTimePos.frame = 0; + fTimePosition.bbt.valid = false; + fTimePosition.frame = 0; } - fPlugin.setTimePos(fTimePos); + fPlugin.setTimePosition(fTimePosition); #endif #if DISTRHO_PLUGIN_IS_SYNTH @@ -249,14 +246,16 @@ protected: { if (jack_midi_event_get(&jevent, midiBuf, i) != 0) break; - if (jevent.size > 4) - continue; MidiEvent& midiEvent(midiEvents[midiEventCount++]); midiEvent.frame = jevent.time; midiEvent.size = jevent.size; - std::memcpy(midiEvent.buf, jevent.buffer, jevent.size); + + if (midiEvent.size > MidiEvent::kDataSize) + midiEvent.dataExt = jevent.buffer; + else + std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size); } fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount); @@ -293,7 +292,7 @@ protected: void setSize(const uint width, const uint height) { - fUI.setSize(width, height); + fUI.setWindowSize(width, height); } // ------------------------------------------------------------------- @@ -314,7 +313,7 @@ private: jack_port_t* fPortMidiIn; #endif #if DISTRHO_PLUGIN_WANT_TIMEPOS - TimePos fTimePos; + TimePosition fTimePosition; #endif // Temporary data @@ -374,6 +373,8 @@ END_NAMESPACE_DISTRHO int main() { + USE_NAMESPACE_DISTRHO; + jack_status_t status = jack_status_t(0x0); jack_client_t* client = jack_client_open(DISTRHO_PLUGIN_NAME, JackNoStartServer, &status); diff --git a/libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp b/libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp index 1194624..11a310d 100644 --- a/libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp +++ b/libs/distrho/src/DistrhoPluginLADSPA+DSSI.cpp @@ -16,12 +16,16 @@ #include "DistrhoPluginInternal.hpp" +#if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT +# error Cannot use MIDI Output with LADSPA or DSSI +#endif + #ifdef DISTRHO_PLUGIN_TARGET_DSSI # include "dssi/dssi.h" #else # include "ladspa/ladspa.h" -# if DISTRHO_PLUGIN_IS_SYNTH -# error Cannot build synth plugin with LADSPA +# if DISTRHO_PLUGIN_HAS_MIDI_INPUT +# error Cannot use MIDI with LADSPA # endif # if DISTRHO_PLUGIN_WANT_STATE # warning LADSPA cannot handle states @@ -186,7 +190,7 @@ public: } } -#if DISTRHO_PLUGIN_IS_SYNTH +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT // Get MIDI Events uint32_t midiEventCount = 0; MidiEvent midiEvents[eventCount]; @@ -203,58 +207,58 @@ public: { case SND_SEQ_EVENT_NOTEOFF: j = midiEventCount++; - midiEvents[j].frame = seqEvent.time.tick; - midiEvents[j].size = 3; - midiEvents[j].buf[0] = 0x80 + seqEvent.data.note.channel; - midiEvents[j].buf[1] = seqEvent.data.note.note; - midiEvents[j].buf[2] = 0; - midiEvents[j].buf[3] = 0; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0x80 + seqEvent.data.note.channel; + midiEvents[j].data[1] = seqEvent.data.note.note; + midiEvents[j].data[2] = 0; + midiEvents[j].data[3] = 0; break; case SND_SEQ_EVENT_NOTEON: j = midiEventCount++; - midiEvents[j].frame = seqEvent.time.tick; - midiEvents[j].size = 3; - midiEvents[j].buf[0] = 0x90 + seqEvent.data.note.channel; - midiEvents[j].buf[1] = seqEvent.data.note.note; - midiEvents[j].buf[2] = seqEvent.data.note.velocity; - midiEvents[j].buf[3] = 0; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0x90 + seqEvent.data.note.channel; + midiEvents[j].data[1] = seqEvent.data.note.note; + midiEvents[j].data[2] = seqEvent.data.note.velocity; + midiEvents[j].data[3] = 0; break; case SND_SEQ_EVENT_KEYPRESS: j = midiEventCount++; - midiEvents[j].frame = seqEvent.time.tick; - midiEvents[j].size = 3; - midiEvents[j].buf[0] = 0xA0 + seqEvent.data.note.channel; - midiEvents[j].buf[1] = seqEvent.data.note.note; - midiEvents[j].buf[2] = seqEvent.data.note.velocity; - midiEvents[j].buf[3] = 0; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0xA0 + seqEvent.data.note.channel; + midiEvents[j].data[1] = seqEvent.data.note.note; + midiEvents[j].data[2] = seqEvent.data.note.velocity; + midiEvents[j].data[3] = 0; break; case SND_SEQ_EVENT_CONTROLLER: j = midiEventCount++; - midiEvents[j].frame = seqEvent.time.tick; - midiEvents[j].size = 3; - midiEvents[j].buf[0] = 0xB0 + seqEvent.data.control.channel; - midiEvents[j].buf[1] = seqEvent.data.control.param; - midiEvents[j].buf[2] = seqEvent.data.control.value; - midiEvents[j].buf[3] = 0; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0xB0 + seqEvent.data.control.channel; + midiEvents[j].data[1] = seqEvent.data.control.param; + midiEvents[j].data[2] = seqEvent.data.control.value; + midiEvents[j].data[3] = 0; break; case SND_SEQ_EVENT_CHANPRESS: j = midiEventCount++; - midiEvents[j].frame = seqEvent.time.tick; - midiEvents[j].size = 2; - midiEvents[j].buf[0] = 0xD0 + seqEvent.data.control.channel; - midiEvents[j].buf[1] = seqEvent.data.control.value; - midiEvents[j].buf[2] = 0; - midiEvents[j].buf[3] = 0; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 2; + midiEvents[j].data[0] = 0xD0 + seqEvent.data.control.channel; + midiEvents[j].data[1] = seqEvent.data.control.value; + midiEvents[j].data[2] = 0; + midiEvents[j].data[3] = 0; break; #if 0 // TODO case SND_SEQ_EVENT_PITCHBEND: j = midiEventCount++; - midiEvents[j].frame = seqEvent.time.tick; - midiEvents[j].size = 3; - midiEvents[j].buf[0] = 0xE0 + seqEvent.data.control.channel; - midiEvents[j].buf[1] = 0; - midiEvents[j].buf[2] = 0; - midiEvents[j].buf[3] = 0; + midiEvents[j].frame = seqEvent.time.tick; + midiEvents[j].size = 3; + midiEvents[j].data[0] = 0xE0 + seqEvent.data.control.channel; + midiEvents[j].data[1] = 0; + midiEvents[j].data[2] = 0; + midiEvents[j].data[3] = 0; break; #endif } @@ -267,7 +271,7 @@ public: updateParameterOutputs(); -#if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_IS_SYNTH +#if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_HAS_MIDI_INPUT return; // unused (void)events; (void)eventCount; #endif @@ -431,7 +435,7 @@ static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong progra } # endif -# if DISTRHO_PLUGIN_IS_SYNTH +# if DISTRHO_PLUGIN_HAS_MIDI_INPUT static void dssi_run_synth(LADSPA_Handle instance, ulong sampleCount, snd_seq_event_t* events, ulong eventCount) { instancePtr->dssi_run_synth(sampleCount, events, eventCount); @@ -486,7 +490,7 @@ static DSSI_Descriptor sDssiDescriptor = { /* select_program */ nullptr, # endif /* get_midi_controller_for_port */ nullptr, -# if DISTRHO_PLUGIN_IS_SYNTH +# if DISTRHO_PLUGIN_HAS_MIDI_INPUT dssi_run_synth, # else /* run_synth */ nullptr, @@ -611,11 +615,11 @@ public: { const uint32_t hints(plugin.getParameterHints(i)); - if (hints & PARAMETER_IS_BOOLEAN) + if (hints & kParameterIsBoolean) portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED; - if (hints & PARAMETER_IS_INTEGER) + if (hints & kParameterIsInteger) portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER; - if (hints & PARAMETER_IS_LOGARITHMIC) + if (hints & kParameterIsLogarithmic) portRangeHints[port].HintDescriptor |= LADSPA_HINT_LOGARITHMIC; } } diff --git a/libs/distrho/src/DistrhoPluginLV2.cpp b/libs/distrho/src/DistrhoPluginLV2.cpp index 1a04e52..ba3c1c7 100644 --- a/libs/distrho/src/DistrhoPluginLV2.cpp +++ b/libs/distrho/src/DistrhoPluginLV2.cpp @@ -27,6 +27,7 @@ #include "lv2/time.h" #include "lv2/urid.h" #include "lv2/worker.h" +#include "lv2/lv2_kxstudio_properties.h" #include "lv2/lv2_programs.h" #ifdef noexcept @@ -34,37 +35,34 @@ #endif #include <map> -#include <string> #ifndef DISTRHO_PLUGIN_URI # error DISTRHO_PLUGIN_URI undefined! #endif -#if DISTRHO_PLUGIN_WANT_STATE -# warning LV2 State still TODO (working but needs final testing) -#endif #if DISTRHO_PLUGIN_WANT_TIMEPOS # warning LV2 TimePos still TODO #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) - -typedef std::map<d_string,d_string> StringMap; +#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_HAS_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) +#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_HAS_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) START_NAMESPACE_DISTRHO +typedef std::map<const d_string,d_string> StringMap; + // ----------------------------------------------------------------------- class PluginLv2 { public: - PluginLv2(const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker) + PluginLv2(const double sampleRate, const LV2_URID_Map* const uridMap, const LV2_Worker_Schedule* const worker) : fPortControls(nullptr), fLastControlValues(nullptr), + fSampleRate(sampleRate), #if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT # if DISTRHO_PLUGIN_WANT_TIMEPOS - fLastTimeSpeed(0.0f), + fLastTimeSpeed(0.0), # endif fURIDs(uridMap), #endif @@ -118,13 +116,31 @@ public: fNeededUiSends = new bool[count]; for (uint32_t i=0; i < count; ++i) + { fNeededUiSends[i] = false; + + const d_string& d_key(fPlugin.getStateKey(i)); + fStateMap[d_key] = fPlugin.getStateDefaultValue(i); + } } else { fNeededUiSends = nullptr; } #endif + +#if DISTRHO_PLUGIN_WANT_TIMEPOS + // hosts may not send all values, resulting on some invalid ones + fTimePosition.bbt.valid = false; + fTimePosition.bbt.bar = 1; + fTimePosition.bbt.beat = 1; + fTimePosition.bbt.tick = 0; + fTimePosition.bbt.barStartTick = 0; + fTimePosition.bbt.beatsPerBar = 4; + fTimePosition.bbt.beatType = 4; + fTimePosition.bbt.ticksPerBeat = 960.0; + fTimePosition.bbt.beatsPerMinute = 120.0; +#endif } ~PluginLv2() @@ -252,21 +268,18 @@ public: } #if DISTRHO_LV2_USE_EVENTS_IN -# if DISTRHO_PLUGIN_IS_SYNTH +# if DISTRHO_PLUGIN_HAS_MIDI_INPUT uint32_t midiEventCount = 0; # endif -# if DISTRHO_PLUGIN_WANT_TIMEPOS - bool needsFrameIncrement = true; -# endif LV2_ATOM_SEQUENCE_FOREACH(fPortEventsIn, event) { if (event == nullptr) break; -# if DISTRHO_PLUGIN_IS_SYNTH +# if DISTRHO_PLUGIN_HAS_MIDI_INPUT if (event->body.type == fURIDs.midiEvent) { - if (event->body.size > 4 || midiEventCount >= kMaxMidiEvents) + if (midiEventCount >= kMaxMidiEvents) continue; const uint8_t* const data((const uint8_t*)(event + 1)); @@ -276,18 +289,17 @@ public: midiEvent.frame = event->time.frames; midiEvent.size = event->body.size; - uint8_t i; - for (i=0; i < midiEvent.size; ++i) - midiEvent.buf[i] = data[i]; - for (; i < 4; ++i) - midiEvent.buf[i] = 0; + if (midiEvent.size > MidiEvent::kDataSize) + midiEvent.dataExt = data; + else + std::memcpy(midiEvent.data, data, midiEvent.size); ++midiEventCount; continue; } # endif # if DISTRHO_PLUGIN_WANT_TIMEPOS - if (event->body.type == fURIDs.atomBlank) + if (event->body.type == fURIDs.atomBlank || event->body.type == fURIDs.atomObject) { const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body); @@ -300,6 +312,7 @@ public: LV2_Atom* beatUnit = nullptr; LV2_Atom* beatsPerBar = nullptr; LV2_Atom* beatsPerMinute = nullptr; + LV2_Atom* ticksPerBeat = nullptr; LV2_Atom* frame = nullptr; LV2_Atom* speed = nullptr; @@ -310,94 +323,127 @@ public: fURIDs.timeBeatUnit, &beatUnit, fURIDs.timeBeatsPerBar, &beatsPerBar, fURIDs.timeBeatsPerMinute, &beatsPerMinute, + fURIDs.timeTicksPerBeat, &ticksPerBeat, fURIDs.timeFrame, &frame, fURIDs.timeSpeed, &speed, nullptr); - // TODO: - // - tick - // - barStartTick - // - ticksPerBeat - if (bar != nullptr) { - if (bar->type == fURIDs.atomDouble) - fTimePos.bbt.bar = ((LV2_Atom_Double*)bar)->body + 1.0f; + /**/ if (bar->type == fURIDs.atomDouble) + fTimePosition.bbt.bar = ((LV2_Atom_Double*)bar)->body + 1.0; else if (bar->type == fURIDs.atomFloat) - fTimePos.bbt.bar = ((LV2_Atom_Float*)bar)->body + 1.0f; + fTimePosition.bbt.bar = ((LV2_Atom_Float*)bar)->body + 1.0f; else if (bar->type == fURIDs.atomInt) - fTimePos.bbt.bar = ((LV2_Atom_Int*)bar)->body + 1; + fTimePosition.bbt.bar = ((LV2_Atom_Int*)bar)->body + 1; else if (bar->type == fURIDs.atomLong) - fTimePos.bbt.bar = ((LV2_Atom_Long*)bar)->body + 1; + fTimePosition.bbt.bar = ((LV2_Atom_Long*)bar)->body + 1; + else + d_stderr("Unknown lv2 bar value type"); } - /*if (barBeat != nullptr && barBeat->type == fURIDs.atomFloat) + if (ticksPerBeat != nullptr) { - }*/ + /**/ if (ticksPerBeat->type == fURIDs.atomDouble) + fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body; + else if (ticksPerBeat->type == fURIDs.atomFloat) + fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Float*)ticksPerBeat)->body; + else if (ticksPerBeat->type == fURIDs.atomInt) + fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Int*)ticksPerBeat)->body; + else if (ticksPerBeat->type == fURIDs.atomLong) + fTimePosition.bbt.ticksPerBeat = ((LV2_Atom_Long*)ticksPerBeat)->body; + else + d_stderr("Unknown lv2 ticksPerBeat value type"); + } - if (beat != nullptr) + if (barBeat != nullptr) { - if (beat->type == fURIDs.atomDouble) - fTimePos.bbt.beat = ((LV2_Atom_Double*)beat)->body + 1.0f; + double barBeatValue = 0.0; + + /**/ if (barBeat->type == fURIDs.atomDouble) + barBeatValue = ((LV2_Atom_Double*)barBeat)->body; + else if (barBeat->type == fURIDs.atomFloat) + barBeatValue = ((LV2_Atom_Float*)barBeat)->body; + else if (barBeat->type == fURIDs.atomInt) + barBeatValue = ((LV2_Atom_Int*)barBeat)->body; + else if (barBeat->type == fURIDs.atomLong) + barBeatValue = ((LV2_Atom_Long*)barBeat)->body; + else + d_stderr("Unknown lv2 barBeat value type"); + + const double rest = std::fmod(barBeatValue, 1.0); + fTimePosition.bbt.beat = barBeatValue-rest+1.0; + fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5; + } + // barBeat includes beat + else if (beat != nullptr) + { + /**/ if (beat->type == fURIDs.atomDouble) + fTimePosition.bbt.beat = ((LV2_Atom_Double*)beat)->body + 1.0; else if (beat->type == fURIDs.atomFloat) - fTimePos.bbt.beat = ((LV2_Atom_Float*)beat)->body + 1.0f; + fTimePosition.bbt.beat = ((LV2_Atom_Float*)beat)->body + 1.0f; else if (beat->type == fURIDs.atomInt) - fTimePos.bbt.beat = ((LV2_Atom_Int*)beat)->body + 1; + fTimePosition.bbt.beat = ((LV2_Atom_Int*)beat)->body + 1; else if (beat->type == fURIDs.atomLong) - fTimePos.bbt.beat = ((LV2_Atom_Long*)beat)->body + 1; + fTimePosition.bbt.beat = ((LV2_Atom_Long*)beat)->body + 1; + else + d_stderr("Unknown lv2 beat value type"); } if (beatUnit != nullptr) { - if (beatUnit->type == fURIDs.atomDouble) - fTimePos.bbt.beatType = ((LV2_Atom_Double*)beatUnit)->body; + /**/ if (beatUnit->type == fURIDs.atomDouble) + fTimePosition.bbt.beatType = ((LV2_Atom_Double*)beatUnit)->body; else if (beatUnit->type == fURIDs.atomFloat) - fTimePos.bbt.beatType = ((LV2_Atom_Float*)beatUnit)->body; + fTimePosition.bbt.beatType = ((LV2_Atom_Float*)beatUnit)->body; else if (beatUnit->type == fURIDs.atomInt) - fTimePos.bbt.beatType = ((LV2_Atom_Int*)beatUnit)->body; + fTimePosition.bbt.beatType = ((LV2_Atom_Int*)beatUnit)->body; else if (beatUnit->type == fURIDs.atomLong) - fTimePos.bbt.beatType = ((LV2_Atom_Long*)beatUnit)->body; + fTimePosition.bbt.beatType = ((LV2_Atom_Long*)beatUnit)->body; + else + d_stderr("Unknown lv2 beatUnit value type"); } if (beatsPerBar != nullptr) { - if (beatsPerBar->type == fURIDs.atomDouble) - fTimePos.bbt.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body; + /**/ if (beatsPerBar->type == fURIDs.atomDouble) + fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body; else if (beatsPerBar->type == fURIDs.atomFloat) - fTimePos.bbt.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body; + fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body; else if (beatsPerBar->type == fURIDs.atomInt) - fTimePos.bbt.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body; + fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body; else if (beatsPerBar->type == fURIDs.atomLong) - fTimePos.bbt.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body; + fTimePosition.bbt.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body; + else + d_stderr("Unknown lv2 beatsPerBar value type"); } if (beatsPerMinute != nullptr) { - if (beatsPerMinute->type == fURIDs.atomDouble) - fTimePos.bbt.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body; + /**/ if (beatsPerMinute->type == fURIDs.atomDouble) + fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body; else if (beatsPerMinute->type == fURIDs.atomFloat) - fTimePos.bbt.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body; + fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body; else if (beatsPerMinute->type == fURIDs.atomInt) - fTimePos.bbt.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body; + fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body; else if (beatsPerMinute->type == fURIDs.atomLong) - fTimePos.bbt.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body; + fTimePosition.bbt.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body; + else + d_stderr("Unknown lv2 beatsPerMinute value type"); } + fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*fTimePosition.bbt.beatsPerBar*(fTimePosition.bbt.bar-1); + if (frame != nullptr && frame->type == fURIDs.atomLong) - { - fTimePos.frame = ((LV2_Atom_Long*)frame)->body; - needsFrameIncrement = false; - } + fTimePosition.frame = ((LV2_Atom_Long*)frame)->body; if (speed != nullptr && speed->type == fURIDs.atomFloat) { fLastTimeSpeed = ((LV2_Atom_Float*)speed)->body; - fTimePos.playing = (fLastTimeSpeed == 1.0f); + fTimePosition.playing = (fLastTimeSpeed == 1.0); } - if ((! fTimePos.bbt.valid) && beatsPerMinute != nullptr && beatsPerBar != nullptr && beatUnit != nullptr) - fTimePos.bbt.valid = true; - + fTimePosition.bbt.valid = (beatsPerMinute != nullptr && beatsPerBar != nullptr && beatUnit != nullptr); continue; } # endif @@ -425,17 +471,52 @@ public: #endif # if DISTRHO_PLUGIN_WANT_TIMEPOS - if (needsFrameIncrement && fLastTimeSpeed != 0.0f) - fTimePos.frame += fLastTimeSpeed*sampleCount; - fPlugin.setTimePos(fTimePos); + fPlugin.setTimePosition(fTimePosition); # endif -#if DISTRHO_PLUGIN_IS_SYNTH +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, fMidiEvents, midiEventCount); #else fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); #endif +# if DISTRHO_PLUGIN_WANT_TIMEPOS + // update timePos for next callback + if (fLastTimeSpeed != 0.0) + { + const double newFrames = fLastTimeSpeed*sampleCount; + + fTimePosition.frame += newFrames; + + if (fTimePosition.bbt.valid) + { + const double samplesPerBeat = 60.0 / fTimePosition.bbt.beatsPerMinute * fSampleRate; + const double ticksPerSample = fTimePosition.bbt.ticksPerBeat / samplesPerBeat; + + double newTickPos = double(fTimePosition.bbt.tick) + ticksPerSample*newFrames; + double newBeatPos = double(fTimePosition.bbt.beat)-1.0; + double newBarPos = double(fTimePosition.bbt.bar)-1.0; + + for (; newTickPos >= fTimePosition.bbt.ticksPerBeat;) + { + ++newBeatPos; + newTickPos -= fTimePosition.bbt.ticksPerBeat; + } + + for (; newBeatPos >= fTimePosition.bbt.beatsPerBar;) + { + ++newBarPos; + newBeatPos -= fTimePosition.bbt.beatsPerBar; + } + + fTimePosition.bbt.bar = newBarPos+1.0; + fTimePosition.bbt.beat = newBeatPos+1.0; + fTimePosition.bbt.tick = newTickPos; + fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*fTimePosition.bbt.beatsPerBar*(fTimePosition.bbt.bar-1); + } + } +# endif + updateParameterOutputs(); #if DISTRHO_LV2_USE_EVENTS_OUT @@ -445,6 +526,10 @@ public: uint32_t size, offset = 0; LV2_Atom_Event* aev; +# if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT + // TODO +# endif +# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI) for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) { if (! fNeededUiSends[i]) @@ -452,29 +537,20 @@ public: const d_string& key = fPlugin.getStateKey(i); - for (auto it = fStateMap.begin(), end = fStateMap.end(); it != end; ++it) + for (StringMap::const_iterator cit=fStateMap.cbegin(), cite=fStateMap.cend(); cit != cite; ++cit) { - const d_string& curKey = it->first; + const d_string& curKey = cit->first; if (curKey != key) continue; - const d_string& value = it->second; + const d_string& value = cit->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); + // set msg size (key + value + separator + 2x null terminator) + const size_t msgSize(key.length()+value.length()+3); if (sizeof(LV2_Atom_Event) + msgSize > capacity - offset) - return; + break; if (needsInit) { @@ -485,17 +561,20 @@ public: 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); + // reserve msg space + char msgBuf[msgSize]; + std::memset(msgBuf, 0, msgSize); + + // write key and value in atom bufer + std::memcpy(msgBuf, key.buffer(), key.length()); + std::memcpy(msgBuf+(key.length()+1), value.buffer(), value.length()); // put data - aev = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, fPortEventsOut) + offset); + aev = (LV2_Atom_Event*)(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); + std::memcpy(LV2_ATOM_BODY(&aev->body), msgBuf, msgSize-1); size = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + msgSize); offset += size; @@ -505,6 +584,7 @@ public: break; } } +# endif #endif } @@ -526,12 +606,12 @@ public: { const int bufferSize(*(const int*)options[i].value); fPlugin.setBufferSize(bufferSize); - return LV2_OPTIONS_SUCCESS; + continue; } else { d_stderr("Host changed maxBlockLength but with wrong value type"); - return LV2_OPTIONS_ERR_BAD_VALUE; + continue; } } else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate)) @@ -539,18 +619,19 @@ public: if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Double)) { const double sampleRate(*(const double*)options[i].value); + fSampleRate = sampleRate; fPlugin.setSampleRate(sampleRate); - return LV2_OPTIONS_SUCCESS; + continue; } else { d_stderr("Host changed sampleRate but with wrong value type"); - return LV2_OPTIONS_ERR_BAD_VALUE; + continue; } } } - return LV2_OPTIONS_ERR_BAD_KEY; + return LV2_OPTIONS_SUCCESS; } // ------------------------------------------------------------------- @@ -596,16 +677,17 @@ public: // ------------------------------------------------------------------- #if DISTRHO_PLUGIN_WANT_STATE - LV2_State_Status lv2_save(const LV2_State_Store_Function store, const LV2_State_Handle handle, const uint32_t flags) + LV2_State_Status lv2_save(const LV2_State_Store_Function store, const LV2_State_Handle handle) { - //flags = LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE; - - for (auto it = fStateMap.begin(), end = fStateMap.end(); it != end; ++it) + for (StringMap::const_iterator cit=fStateMap.cbegin(), cite=fStateMap.cend(); cit != cite; ++cit) { - const d_string& key = it->first; - const d_string& value = it->second; + const d_string& key = cit->first; + const d_string& value = cit->second; + + const d_string urnKey("urn:distrho:" + key); - store(handle, fUridMap->map(fUridMap->handle, (const char*)key), (const char*)value, value.length()+1, fURIDs.atomString, flags); + // some hosts need +1 for the null terminator, even though the type is string + store(handle, fUridMap->map(fUridMap->handle, urnKey.buffer()), value.buffer(), value.length()+1, fURIDs.atomString, LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE); } return LV2_STATE_SUCCESS; @@ -613,32 +695,30 @@ public: LV2_State_Status lv2_restore(const LV2_State_Retrieve_Function retrieve, const LV2_State_Handle handle) { - size_t size = 0; - uint32_t type = 0; - uint32_t flags = LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE; + size_t size; + uint32_t type, flags; for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i) { - const d_string& key = fPlugin.getStateKey(i); + const d_string& key(fPlugin.getStateKey(i)); + const d_string urnKey("urn:distrho:" + key); - const void* data = retrieve(handle, fUridMap->map(fUridMap->handle, (const char*)key), &size, &type, &flags); + size = 0; + type = 0; + flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE; + const void* data = retrieve(handle, fUridMap->map(fUridMap->handle, urnKey.buffer()), &size, &type, &flags); - if (size == 0) - continue; - if (data == nullptr) - continue; - if (type != fURIDs.atomString) + if (data == nullptr || size == 0) continue; - const char* const value((const char*)data); + DISTRHO_SAFE_ASSERT_CONTINUE(type == fURIDs.atomString); - if (std::strlen(value) != size) - continue; + const char* const value((const char*)data); + const std::size_t length(std::strlen(value)); + DISTRHO_SAFE_ASSERT_CONTINUE(length == size || length+1 == size); 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; @@ -652,10 +732,10 @@ public: LV2_Worker_Status lv2_work(const void* const data) { - const char* const stateKey((const char*)data); - const char* const stateValue(stateKey+std::strlen(stateKey)+1); + const char* const key((const char*)data); + const char* const value(key+std::strlen(key)+1); - setState(stateKey, stateValue); + setState(key, value); return LV2_WORKER_SUCCESS; } @@ -699,18 +779,20 @@ private: // Temporary data float* fLastControlValues; -#if DISTRHO_PLUGIN_IS_SYNTH + double fSampleRate; +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT MidiEvent fMidiEvents[kMaxMidiEvents]; #endif #if DISTRHO_PLUGIN_WANT_TIMEPOS - TimePos fTimePos; - float fLastTimeSpeed; + TimePosition fTimePosition; + double fLastTimeSpeed; #endif // LV2 URIDs #if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT struct URIDs { LV2_URID atomBlank; + LV2_URID atomObject; LV2_URID atomDouble; LV2_URID atomFloat; LV2_URID atomInt; @@ -726,11 +808,13 @@ private: LV2_URID timeBeatUnit; LV2_URID timeBeatsPerBar; LV2_URID timeBeatsPerMinute; + LV2_URID timeTicksPerBeat; LV2_URID timeFrame; LV2_URID timeSpeed; URIDs(const LV2_URID_Map* const uridMap) : atomBlank(uridMap->map(uridMap->handle, LV2_ATOM__Blank)), + atomObject(uridMap->map(uridMap->handle, LV2_ATOM__Object)), atomDouble(uridMap->map(uridMap->handle, LV2_ATOM__Double)), atomFloat(uridMap->map(uridMap->handle, LV2_ATOM__Float)), atomInt(uridMap->map(uridMap->handle, LV2_ATOM__Int)), @@ -746,6 +830,7 @@ private: timeBeatUnit(uridMap->map(uridMap->handle, LV2_TIME__beatUnit)), timeBeatsPerBar(uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar)), timeBeatsPerMinute(uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute)), + timeTicksPerBeat(uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat)), timeFrame(uridMap->map(uridMap->handle, LV2_TIME__frame)), timeSpeed(uridMap->map(uridMap->handle, LV2_TIME__speed)) {} } fURIDs; @@ -768,9 +853,9 @@ private: return; // check if key already exists - for (auto it = fStateMap.begin(), end = fStateMap.end(); it != end; ++it) + for (StringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it) { - const d_string& d_key = it->first; + const d_string& d_key(it->first); if (d_key == key) { @@ -779,9 +864,7 @@ private: } } - // nope, add a new one then - d_string d_key(key); - fStateMap[d_key] = newValue; + d_stderr("Failed to find plugin state with key \"%s\"", key); } #endif @@ -866,7 +949,7 @@ static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, cons d_lastSampleRate = sampleRate; - return new PluginLv2(uridMap, worker); + return new PluginLv2(sampleRate, uridMap, worker); } #define instancePtr ((PluginLv2*)instance) @@ -925,9 +1008,9 @@ static void lv2_select_program(LV2_Handle instance, uint32_t bank, uint32_t prog // ----------------------------------------------------------------------- #if DISTRHO_PLUGIN_WANT_STATE -static LV2_State_Status lv2_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const*) +static LV2_State_Status lv2_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t, const LV2_Feature* const*) { - return instancePtr->lv2_save(store, handle, flags); + return instancePtr->lv2_save(store, handle); } static LV2_State_Status lv2_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t, const LV2_Feature* const*) diff --git a/libs/distrho/src/DistrhoPluginLV2export.cpp b/libs/distrho/src/DistrhoPluginLV2export.cpp index a5e6aed..fbc9340 100644 --- a/libs/distrho/src/DistrhoPluginLV2export.cpp +++ b/libs/distrho/src/DistrhoPluginLV2export.cpp @@ -22,6 +22,7 @@ #include "lv2/instance-access.h" #include "lv2/midi.h" #include "lv2/options.h" +#include "lv2/port-props.h" #include "lv2/resize-port.h" #include "lv2/state.h" #include "lv2/time.h" @@ -29,6 +30,7 @@ #include "lv2/units.h" #include "lv2/urid.h" #include "lv2/worker.h" +#include "lv2/lv2_kxstudio_properties.h" #include "lv2/lv2_programs.h" #include <fstream> @@ -42,8 +44,8 @@ # 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) +#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_HAS_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) +#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_HAS_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)) // ----------------------------------------------------------------------- @@ -248,13 +250,12 @@ void lv2_generate_ttl(const char* const basename) # if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI) pluginString += " atom:supports <" LV2_ATOM__String "> ;\n"; # endif +# if DISTRHO_PLUGIN_HAS_MIDI_INPUT + pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n"; +# endif # if DISTRHO_PLUGIN_WANT_TIMEPOS pluginString += " atom:supports <" LV2_TIME__Position "> ;\n"; # endif -# if DISTRHO_PLUGIN_IS_SYNTH - pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n"; -# endif - pluginString += " ] ;\n\n"; ++portIndex; #endif @@ -267,7 +268,12 @@ void lv2_generate_ttl(const char* const basename) pluginString += " lv2:symbol \"lv2_events_out\" ;\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"; +# endif +# if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT + pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n"; +# endif pluginString += " ] ;\n\n"; ++portIndex; #endif @@ -313,7 +319,7 @@ void lv2_generate_ttl(const char* const basename) { const ParameterRanges& ranges(plugin.getParameterRanges(i)); - if (plugin.getParameterHints(i) & PARAMETER_IS_INTEGER) + if (plugin.getParameterHints(i) & kParameterIsInteger) { pluginString += " lv2:default " + d_string(int(plugin.getParameterValue(i))) + " ;\n"; pluginString += " lv2:minimum " + d_string(int(ranges.min)) + " ;\n"; @@ -369,14 +375,17 @@ void lv2_generate_ttl(const char* const basename) { const uint32_t hints(plugin.getParameterHints(i)); - if (hints & PARAMETER_IS_BOOLEAN) + if (hints & kParameterIsBoolean) pluginString += " lv2:portProperty lv2:toggled ;\n"; - if (hints & PARAMETER_IS_INTEGER) + if (hints & kParameterIsInteger) pluginString += " lv2:portProperty lv2:integer ;\n"; - if (hints & PARAMETER_IS_LOGARITHMIC) - pluginString += " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> ;\n"; - if ((hints & PARAMETER_IS_AUTOMABLE) == 0 && ! plugin.isParameterOutput(i)) - pluginString += " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#expensive> ;\n"; + if (hints & kParameterIsLogarithmic) + pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n"; + if ((hints & kParameterIsAutomable) == 0 && ! plugin.isParameterOutput(i)) + { + pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n"; + pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n"; + } } if (i+1 == count) diff --git a/libs/distrho/src/DistrhoPluginVST.cpp b/libs/distrho/src/DistrhoPluginVST.cpp index 0747661..542c6e3 100644 --- a/libs/distrho/src/DistrhoPluginVST.cpp +++ b/libs/distrho/src/DistrhoPluginVST.cpp @@ -38,6 +38,7 @@ #ifdef VESTIGE_HEADER # include "vestige/aeffectx.h" #define effFlagsProgramChunks (1 << 5) +#define effSetProgramName 4 #define effGetParamLabel 6 #define effGetParamDisplay 7 #define effGetChunk 23 @@ -56,23 +57,22 @@ struct ERect { # include "vst/aeffectx.h" #endif -#if DISTRHO_PLUGIN_WANT_STATE -# warning VST State still TODO (working but needs final testing) -#endif -#if DISTRHO_PLUGIN_WANT_TIMEPOS -# warning VST TimePos still TODO (only basic BBT working) -#endif - -typedef std::map<d_string,d_string> StringMap; - START_NAMESPACE_DISTRHO +typedef std::map<const d_string,d_string> StringMap; + // ----------------------------------------------------------------------- void strncpy(char* const dst, const char* const src, const size_t size) { - std::strncpy(dst, src, size); - dst[size] = '\0'; + std::strncpy(dst, src, size-1); + dst[size-1] = '\0'; +} + +void snprintf_param(char* const dst, const float value, const size_t size) +{ + std::snprintf(dst, size-1, "%f", value); + dst[size-1] = '\0'; } #if DISTRHO_PLUGIN_HAS_UI @@ -83,8 +83,7 @@ class UiHelper public: UiHelper() : parameterChecks(nullptr), - parameterValues(nullptr), - nextProgram(-1) {} + parameterValues(nullptr) {} virtual ~UiHelper() { @@ -102,10 +101,9 @@ public: bool* parameterChecks; float* parameterValues; - int32_t nextProgram; #if DISTRHO_PLUGIN_WANT_STATE - virtual void setStateFromUi(const char* const newKey, const char* const newValue) = 0; + virtual void setStateFromUI(const char* const newKey, const char* const newValue) = 0; #endif }; @@ -127,14 +125,6 @@ public: void idle() { -#if DISTRHO_PLUGIN_WANT_PROGRAMS - if (fUiHelper->nextProgram != -1) - { - fUI.programChanged(fUiHelper->nextProgram); - fUiHelper->nextProgram = -1; - } -#endif - for (uint32_t i=0, count = fPlugin->getParameterCount(); i < count; ++i) { if (fUiHelper->parameterChecks[i]) @@ -157,6 +147,11 @@ public: return fUI.getHeight(); } + void setSampleRate(const double newSampleRate) + { + fUI.setSampleRate(newSampleRate, true); + } + // ------------------------------------------------------------------- // functions called from the plugin side, may block @@ -177,10 +172,7 @@ protected: void editParameter(const uint32_t index, const bool started) { - if (started) - hostCallback(audioMasterBeginEdit, index, 0, nullptr, 0.0f); - else - hostCallback(audioMasterEndEdit, index, 0, nullptr, 0.0f); + hostCallback(started ? audioMasterBeginEdit : audioMasterEndEdit, index, 0, nullptr, 0.0f); } void setParameterValue(const uint32_t index, const float realValue) @@ -195,7 +187,7 @@ protected: void setState(const char* const key, const char* const value) { #if DISTRHO_PLUGIN_WANT_STATE - fUiHelper->setStateFromUi(key, value); + fUiHelper->setStateFromUI(key, value); #else return; // unused (void)key; @@ -205,7 +197,7 @@ protected: void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) { -#if 0 //DISTRHO_PLUGIN_IS_SYNTH +#if 0 //DISTRHO_PLUGIN_HAS_MIDI_INPUT // TODO #else return; // unused @@ -217,7 +209,7 @@ protected: void setSize(const uint width, const uint height) { - fUI.setSize(width, height); + fUI.setWindowSize(width, height); hostCallback(audioMasterSizeWindow, width, height, nullptr, 0.0f); } @@ -278,16 +270,15 @@ public: : fAudioMaster(audioMaster), fEffect(effect) { -#if DISTRHO_PLUGIN_WANT_PROGRAMS - fCurProgram = -1; -#endif + std::memset(fProgramName, 0, sizeof(char)*(64+1)); + std::strcpy(fProgramName, "Default"); -#if DISTRHO_PLUGIN_IS_SYNTH +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT fMidiEventCount = 0; #endif #if DISTRHO_PLUGIN_HAS_UI - fVstUi = nullptr; + fVstUI = nullptr; fVstRect.top = 0; fVstRect.left = 0; fVstRect.bottom = 0; @@ -308,12 +299,18 @@ public: #if DISTRHO_PLUGIN_WANT_STATE fStateChunk = nullptr; + + for (uint32_t i=0, count=fPlugin.getStateCount(); i<count; ++i) + { + const d_string& d_key(fPlugin.getStateKey(i)); + fStateMap[d_key] = fPlugin.getStateDefaultValue(i); + } #endif } -#if DISTRHO_PLUGIN_WANT_STATE ~PluginVst() { +#if DISTRHO_PLUGIN_WANT_STATE if (fStateChunk != nullptr) { delete[] fStateChunk; @@ -321,60 +318,53 @@ public: } fStateMap.clear(); - } #endif + } intptr_t vst_dispatcher(const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt) { - int32_t ret = 0; - switch (opcode) { -#if DISTRHO_PLUGIN_WANT_PROGRAMS - case effSetProgram: - if (value >= 0 && value < static_cast<intptr_t>(fPlugin.getProgramCount())) - { - fCurProgram = value; - fPlugin.setProgram(fCurProgram); - -#if DISTRHO_PLUGIN_HAS_UI - if (fVstUi != nullptr) - setProgramFromPlugin(fCurProgram); -#endif + case effGetProgram: + return 0; - ret = 1; + case effSetProgramName: + if (char* const programName = (char*)ptr) + { + DISTRHO::strncpy(fProgramName, programName, 64); + return 1; } break; - case effGetProgram: - ret = fCurProgram; + case effGetProgramName: + if (char* const programName = (char*)ptr) + { + DISTRHO::strncpy(programName, fProgramName, 24); + return 1; + } break; - //case effSetProgramName: - // unsupported - // break; - - case effGetProgramName: - if (ptr != nullptr && fCurProgram >= 0 && fCurProgram < static_cast<int32_t>(fPlugin.getProgramCount())) + case effGetProgramNameIndexed: + if (char* const programName = (char*)ptr) { - DISTRHO::strncpy((char*)ptr, fPlugin.getProgramName(fCurProgram), 24); - ret = 1; + DISTRHO::strncpy(programName, fProgramName, 24); + return 1; } break; -#endif case effGetParamDisplay: if (ptr != nullptr && index < static_cast<int32_t>(fPlugin.getParameterCount())) { - char* buf = (char*)ptr; - std::snprintf((char*)ptr, 8, "%f", fPlugin.getParameterValue(index)); - buf[8] = '\0'; - ret = 1; + DISTRHO::snprintf_param((char*)ptr, fPlugin.getParameterValue(index), 24); + return 1; } break; case effSetSampleRate: fPlugin.setSampleRate(opt, true); + + if (fVstUI != nullptr) + fVstUI->setSampleRate(opt); break; case effSetBlockSize: @@ -385,7 +375,7 @@ public: if (value != 0) { fPlugin.activate(); -#if DISTRHO_PLUGIN_IS_SYNTH +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT fMidiEventCount = 0; #endif } @@ -397,76 +387,66 @@ public: #if DISTRHO_PLUGIN_HAS_UI case effEditGetRect: - if (fVstUi != nullptr) + if (fVstUI != nullptr) { - fVstRect.right = fVstUi->getWidth(); - fVstRect.bottom = fVstUi->getHeight(); + fVstRect.right = fVstUI->getWidth(); + fVstRect.bottom = fVstUI->getHeight(); } else { - d_lastUiSampleRate = fAudioMaster(fEffect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f); - UIExporter tmpUI(nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr); + d_lastUiSampleRate = fPlugin.getSampleRate(); + + UIExporter tmpUI(nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, fPlugin.getInstancePointer()); fVstRect.right = tmpUI.getWidth(); fVstRect.bottom = tmpUI.getHeight(); + tmpUI.quit(); } *(ERect**)ptr = &fVstRect; - ret = 1; - break; + return 1; case effEditOpen: - if (fVstUi == nullptr) + if (fVstUI == nullptr) { # if DISTRHO_OS_MAC && ! defined(__LP64__) if ((fEffect->dispatcher(fEffect, effCanDo, 0, 0, (void*)"hasCockosViewAsConfig", 0.0f) & 0xffff0000) != 0xbeef0000) return 0; # endif + d_lastUiSampleRate = fPlugin.getSampleRate(); - d_lastUiSampleRate = fAudioMaster(fEffect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f); + fVstUI = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr); - fVstUi = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr); +# if DISTRHO_PLUGIN_WANT_STATE + for (StringMap::const_iterator cit=fStateMap.cbegin(), cite=fStateMap.cend(); cit != cite; ++cit) + { + const d_string& key = cit->first; + const d_string& value = cit->second; -# if DISTRHO_PLUGIN_WANT_PROGRAMS - if (fCurProgram >= 0) - setProgramFromPlugin(fCurProgram); + fVstUI->setStateFromPlugin(key, value); + } # endif - for (uint32_t i=0, count = fPlugin.getParameterCount(); i < count; ++i) + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) setParameterValueFromPlugin(i, fPlugin.getParameterValue(i)); - fVstUi->idle(); - -#if DISTRHO_PLUGIN_WANT_STATE - if (fStateMap.size() > 0) - { - for (auto it = fStateMap.begin(), end = fStateMap.end(); it != end; ++it) - { - const d_string& key = it->first; - const d_string& value = it->second; - - fVstUi->setStateFromPlugin((const char*)key, (const char*)value); - } - - fVstUi->idle(); - } -#endif - ret = 1; + fVstUI->idle(); + return 1; } break; case effEditClose: - if (fVstUi != nullptr) + if (fVstUI != nullptr) { - delete fVstUi; - fVstUi = nullptr; - ret = 1; + delete fVstUI; + fVstUI = nullptr; + return 1; } break; + //case effIdle: case effEditIdle: - case effIdle: - if (fVstUi != nullptr) - fVstUi->idle(); + if (fVstUI != nullptr) + fVstUI->idle(); break; -#endif +#endif // DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_WANT_STATE case effGetChunk: @@ -474,88 +454,83 @@ public: return 0; if (fStateChunk != nullptr) + { delete[] fStateChunk; + fStateChunk = nullptr; + } - if (fStateMap.size() == 0) + if (fPlugin.getStateCount() == 0) { fStateChunk = new char[1]; fStateChunk[0] = '\0'; - ret = 1; + return 1; } else { - std::string tmpStr; + d_string chunkStr; - for (auto it = fStateMap.begin(), end = fStateMap.end(); it != end; ++it) + for (StringMap::const_iterator cit=fStateMap.cbegin(), cite=fStateMap.cend(); cit != cite; ++cit) { - const d_string& key = it->first; - const d_string& value = it->second; + const d_string& key = cit->first; + const d_string& value = cit->second; - tmpStr += (const char*)key; + // join key and value + d_string tmpStr; + tmpStr = key; tmpStr += "\xff"; - tmpStr += (const char*)value; + tmpStr += value; tmpStr += "\xff"; + + chunkStr += tmpStr; } - const size_t size(tmpStr.size()); - fStateChunk = new char[size]; - std::memcpy(fStateChunk, tmpStr.c_str(), size*sizeof(char)); + const std::size_t chunkSize(chunkStr.length()+1); - for (size_t i=0; i < size; ++i) + fStateChunk = new char[chunkSize]; + std::memcpy(fStateChunk, chunkStr.buffer(), chunkStr.length()); + fStateChunk[chunkSize] = '\0'; + + for (std::size_t i=0; i<chunkSize; ++i) { if (fStateChunk[i] == '\xff') fStateChunk[i] = '\0'; } - ret = size; + return chunkSize; } *(void**)ptr = fStateChunk; break; case effSetChunk: - if (value <= 0) + { + if (value <= 1 || ptr == nullptr) return 0; - if (value == 1) - return 1; - - if (const char* const state = (const char*)ptr) - { - const size_t stateSize = value; - const char* stateKey = state; - const char* stateValue = nullptr; - - for (size_t i=0; i < stateSize; ++i) - { - // find next null char - if (state[i] != '\0') - continue; - // found, set value - stateValue = &state[i+1]; - setStateFromUi(stateKey, stateValue); + const char* key = (const char*)ptr; + const char* value = nullptr; - if (fVstUi != nullptr) - fVstUi->setStateFromPlugin(stateKey, stateValue); + for (;;) + { + if (key[0] == '\0') + break; - // increment text position - i += std::strlen(stateValue) + 2; + value = key+(std::strlen(key)+1); - // check if end of data - if (i >= stateSize) - break; + setStateFromUI(key, value); - // get next key - stateKey = &state[i]; - } + if (fVstUI != nullptr) + fVstUI->setStateFromPlugin(key, value); - ret = 1; + // get next key + key = value+(std::strlen(value)+1); } - break; -#endif + return 1; + } +#endif // DISTRHO_PLUGIN_WANT_STATE -#if DISTRHO_PLUGIN_IS_SYNTH +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT case effProcessEvents: if (const VstEvents* const events = (const VstEvents*)ptr) { @@ -576,7 +551,7 @@ public: MidiEvent& midiEvent(fMidiEvents[fMidiEventCount++]); midiEvent.frame = vstMidiEvent->deltaFrames; midiEvent.size = 3; - std::memcpy(midiEvent.buf, vstMidiEvent->midiData, 3*sizeof(uint8_t)); + std::memcpy(midiEvent.data, vstMidiEvent->midiData, sizeof(uint8_t)*3); } } break; @@ -588,28 +563,32 @@ public: const uint32_t hints(fPlugin.getParameterHints(index)); // must be automable, and not output - if ((hints & PARAMETER_IS_AUTOMABLE) != 0 && (hints & PARAMETER_IS_OUTPUT) == 0) - ret = 1; + if ((hints & kParameterIsAutomable) != 0 && (hints & kParameterIsOutput) == 0) + return 1; } break; -#if (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS) case effCanDo: if (const char* const canDo = (const char*)ptr) { -# if DISTRHO_PLUGIN_IS_SYNTH +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT if (std::strcmp(canDo, "receiveVstEvents") == 0) return 1; if (std::strcmp(canDo, "receiveVstMidiEvent") == 0) return 1; -# endif -# if DISTRHO_PLUGIN_WANT_TIMEPOS +#endif +#if DISTRHO_PLUGIN_HAS_MIDI_OUTPUT + if (std::strcmp(canDo, "sendVstEvents") == 0) + return 1; + if (std::strcmp(canDo, "sendVstMidiEvent") == 0) + return 1; +#endif +#if DISTRHO_PLUGIN_WANT_TIMEPOS if (std::strcmp(canDo, "receiveVstTimeInfo") == 0) return 1; -# endif +#endif } break; -#endif //case effStartProcess: //case effStopProcess: @@ -617,7 +596,7 @@ public: // break; } - return ret; + return 0; } float vst_getParameter(const int32_t index) @@ -633,7 +612,7 @@ public: fPlugin.setParameterValue(index, realValue); #if DISTRHO_PLUGIN_HAS_UI - if (fVstUi != nullptr) + if (fVstUI != nullptr) setParameterValueFromPlugin(index, realValue); #endif } @@ -641,29 +620,50 @@ public: void vst_processReplacing(const float** const inputs, float** const outputs, const int32_t sampleFrames) { #if DISTRHO_PLUGIN_WANT_TIMEPOS - static const int kWantVstTimeFlags(kVstTransportPlaying|kVstTempoValid|kVstTimeSigValid); + static const int kWantVstTimeFlags(kVstTransportPlaying|kVstPpqPosValid|kVstTempoValid|kVstTimeSigValid); if (const VstTimeInfo* const vstTimeInfo = (const VstTimeInfo*)fAudioMaster(fEffect, audioMasterGetTime, 0, kWantVstTimeFlags, nullptr, 0.0f)) { - fTimePos.playing = (vstTimeInfo->flags & kVstTransportPlaying); - fTimePos.frame = vstTimeInfo->samplePos; - fTimePos.bbt.valid = ((vstTimeInfo->flags & kVstTempoValid) != 0 || (vstTimeInfo->flags & kVstTimeSigValid) != 0); + fTimePosition.frame = vstTimeInfo->samplePos; + fTimePosition.playing = (vstTimeInfo->flags & kVstTransportPlaying); + fTimePosition.bbt.valid = ((vstTimeInfo->flags & kVstTempoValid) != 0 || (vstTimeInfo->flags & kVstTimeSigValid) != 0); + + // ticksPerBeat is not possible with VST + fTimePosition.bbt.ticksPerBeat = 960.0; if (vstTimeInfo->flags & kVstTempoValid) + fTimePosition.bbt.beatsPerMinute = vstTimeInfo->tempo; + else + fTimePosition.bbt.beatsPerMinute = 120.0; + + if (vstTimeInfo->flags & (kVstPpqPosValid|kVstTimeSigValid)) { - fTimePos.bbt.beatsPerMinute = vstTimeInfo->tempo; + const int ppqPerBar = vstTimeInfo->timeSigNumerator * 4 / vstTimeInfo->timeSigDenominator; + const double barBeats = (std::fmod(vstTimeInfo->ppqPos, ppqPerBar) / ppqPerBar) * vstTimeInfo->timeSigDenominator; + const double rest = std::fmod(barBeats, 1.0); + + fTimePosition.bbt.bar = int(vstTimeInfo->ppqPos)/ppqPerBar + 1; + fTimePosition.bbt.beat = barBeats-rest+1; + fTimePosition.bbt.tick = rest*fTimePosition.bbt.ticksPerBeat+0.5; + fTimePosition.bbt.beatsPerBar = vstTimeInfo->timeSigNumerator; + fTimePosition.bbt.beatType = vstTimeInfo->timeSigDenominator; } - if (vstTimeInfo->flags & kVstTimeSigValid) + else { - fTimePos.bbt.beatsPerBar = vstTimeInfo->timeSigNumerator; - fTimePos.bbt.beatType = vstTimeInfo->timeSigDenominator; + fTimePosition.bbt.bar = 1; + fTimePosition.bbt.beat = 1; + fTimePosition.bbt.tick = 0; + fTimePosition.bbt.beatsPerBar = 4.0f; + fTimePosition.bbt.beatType = 4.0f; } - fPlugin.setTimePos(fTimePos); + fTimePosition.bbt.barStartTick = fTimePosition.bbt.ticksPerBeat*fTimePosition.bbt.beatsPerBar*(fTimePosition.bbt.bar-1); + + fPlugin.setTimePosition(fTimePosition); } #endif -#if DISTRHO_PLUGIN_IS_SYNTH +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT fPlugin.run(inputs, outputs, sampleFrames, fMidiEvents, fMidiEventCount); fMidiEventCount = 0; #else @@ -671,10 +671,10 @@ public: #endif #if DISTRHO_PLUGIN_HAS_UI - if (fVstUi == nullptr) + if (fVstUI == nullptr) return; - for (uint32_t i=0, count = fPlugin.getParameterCount(); i < count; ++i) + for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) { if (fPlugin.isParameterOutput(i)) setParameterValueFromPlugin(i, fPlugin.getParameterValue(i)); @@ -694,23 +694,21 @@ private: // Plugin PluginExporter fPlugin; -#if DISTRHO_PLUGIN_WANT_PROGRAMS - // Current state - int32_t fCurProgram; -#endif - // Temporary data -#if DISTRHO_PLUGIN_IS_SYNTH + char fProgramName[64+1]; + +#if DISTRHO_PLUGIN_HAS_MIDI_INPUT uint32_t fMidiEventCount; MidiEvent fMidiEvents[kMaxMidiEvents]; #endif + #if DISTRHO_PLUGIN_WANT_TIMEPOS - TimePos fTimePos; + TimePosition fTimePosition; #endif // UI stuff #if DISTRHO_PLUGIN_HAS_UI - UIVst* fVstUi; + UIVst* fVstUI; ERect fVstRect; #endif @@ -730,45 +728,31 @@ private: } #endif -#if DISTRHO_PLUGIN_WANT_PROGRAMS - void setProgramFromPlugin(const uint32_t index) - { -# if DISTRHO_PLUGIN_HAS_UI - // set previous parameters invalid - std::memset(parameterChecks, 0, sizeof(bool)*fPlugin.getParameterCount()); -# endif - - nextProgram = index; - } -#endif - #if DISTRHO_PLUGIN_WANT_STATE // ------------------------------------------------------------------- // functions called from the UI side, may block - void setStateFromUi(const char* const newKey, const char* const newValue) override + void setStateFromUI(const char* const key, const char* const newValue) override { - fPlugin.setState(newKey, newValue); + fPlugin.setState(key, newValue); // check if we want to save this key - if (! fPlugin.wantStateKey(newKey)) + if (! fPlugin.wantStateKey(key)) return; // check if key already exists - for (auto it = fStateMap.begin(), end = fStateMap.end(); it != end; ++it) + for (StringMap::iterator it=fStateMap.begin(), ite=fStateMap.end(); it != ite; ++it) { - const d_string& key = it->first; + const d_string& d_key(it->first); - if (key == newKey) + if (d_key == key) { it->second = newValue; return; } } - // nope, add a new one then - d_string d_key(newKey); - fStateMap[d_key] = newValue; + d_stderr("Failed to find plugin state with key \"%s\"", key); } #endif }; @@ -786,7 +770,7 @@ private: static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) { // first internal init - bool doInternalInit = (opcode == -1729 && index == 0xdead && value == 0xf00d); + const bool doInternalInit = (opcode == -1729 && index == 0xdead && value == 0xf00d); if (doInternalInit) { @@ -823,6 +807,13 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t #endif d_lastBufferSize = audioMaster(effect, audioMasterGetBlockSize, 0, 0, nullptr, 0.0f); d_lastSampleRate = audioMaster(effect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f); + + // some hosts are not ready at this point or return 0 buffersize/samplerate + if (d_lastBufferSize == 0) + d_lastBufferSize = 2048; + if (d_lastSampleRate <= 0.0) + d_lastSampleRate = 44100.0; + PluginVst* const plugin(new PluginVst(audioMaster, effect)); #ifdef VESTIGE_HEADER effect->ptr2 = plugin; @@ -861,21 +852,11 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t case effGetParamName: if (ptr != nullptr && index < static_cast<int32_t>(plugin.getParameterCount())) { - DISTRHO::strncpy((char*)ptr, plugin.getParameterName(index), 8); + DISTRHO::strncpy((char*)ptr, plugin.getParameterName(index), 16); return 1; } return 0; -#if DISTRHO_PLUGIN_WANT_PROGRAMS - case effGetProgramNameIndexed: - if (ptr != nullptr && index < static_cast<int32_t>(plugin.getProgramCount())) - { - DISTRHO::strncpy((char*)ptr, plugin.getProgramName(index), 24); - return 1; - } - return 0; -#endif - case effGetPlugCategory: #if DISTRHO_PLUGIN_IS_SYNTH return kPlugCategSynth; @@ -902,7 +883,7 @@ static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t case effGetProductString: if (ptr != nullptr) { - DISTRHO::strncpy((char*)ptr, plugin.getLabel(), 32); + DISTRHO::strncpy((char*)ptr, plugin.getLabel(), 64); return 1; } return 0; @@ -971,6 +952,7 @@ const AEffect* VSTPluginMain(audioMasterCallback audioMaster) // first internal init PluginExporter* plugin = nullptr; vst_dispatcherCallback(nullptr, -1729, 0xdead, 0xf00d, &plugin, 0.0f); + DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr); AEffect* const effect(new AEffect); std::memset(effect, 0, sizeof(AEffect)); @@ -985,11 +967,18 @@ const AEffect* VSTPluginMain(audioMasterCallback audioMaster) effect->version = plugin->getVersion(); #endif + // VST doesn't support parameter outputs, hide them + int numParams = 0; + + for (uint32_t i=0, count=plugin->getParameterCount(); i < count; ++i) + { + if (! plugin->isParameterOutput(i)) + ++numParams; + } + // plugin fields - effect->numParams = plugin->getParameterCount(); -#if DISTRHO_PLUGIN_WANT_PROGRAMS - effect->numPrograms = plugin->getProgramCount(); -#endif + effect->numParams = numParams; + effect->numPrograms = 1; effect->numInputs = DISTRHO_PLUGIN_NUM_INPUTS; effect->numOutputs = DISTRHO_PLUGIN_NUM_OUTPUTS; diff --git a/libs/distrho/src/DistrhoUI.cpp b/libs/distrho/src/DistrhoUI.cpp index c46425e..eda57b0 100644 --- a/libs/distrho/src/DistrhoUI.cpp +++ b/libs/distrho/src/DistrhoUI.cpp @@ -18,21 +18,21 @@ START_NAMESPACE_DISTRHO -// ----------------------------------------------------------------------- -// Static data, see DistrhoUIInternal.hpp +/* ------------------------------------------------------------------------------------------------------------ + * Static data, see DistrhoUIInternal.hpp */ -double d_lastUiSampleRate = 0.0; -void* d_lastUiDspPtr = nullptr; -Window* d_lastUiWindow = nullptr; +double d_lastUiSampleRate = 0.0; +void* d_lastUiDspPtr = nullptr; +UIWindow* d_lastUiWindow = nullptr; -// ----------------------------------------------------------------------- -// UI +/* ------------------------------------------------------------------------------------------------------------ + * UI */ UI::UI() : UIWidget(*d_lastUiWindow), pData(new PrivateData()) { - Widget::setNeedsFullViewport(true); + UIWidget::setNeedsFullViewport(true); } UI::~UI() @@ -40,49 +40,41 @@ UI::~UI() delete pData; } -// ----------------------------------------------------------------------- -// Host DSP State +/* ------------------------------------------------------------------------------------------------------------ + * Host state */ double UI::d_getSampleRate() const noexcept { return pData->sampleRate; } -void UI::d_editParameter(uint32_t index, bool started) +void UI::d_editParameter(const uint32_t index, const bool started) { pData->editParamCallback(index + pData->parameterOffset, started); } -void UI::d_setParameterValue(uint32_t index, float value) +void UI::d_setParameterValue(const uint32_t index, const float value) { pData->setParamCallback(index + pData->parameterOffset, value); } #if DISTRHO_PLUGIN_WANT_STATE -void UI::d_setState(const char* key, const char* value) +void UI::d_setState(const char* const key, const char* const value) { pData->setStateCallback(key, value); } #endif #if DISTRHO_PLUGIN_IS_SYNTH -void UI::d_sendNote(uint8_t channel, uint8_t note, uint8_t velocity) +void UI::d_sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) { pData->sendNoteCallback(channel, note, velocity); } #endif -// ----------------------------------------------------------------------- -// Host UI State - -void UI::d_setSize(uint width, uint height) -{ - pData->setSizeCallback(width, height); -} - #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS -// ----------------------------------------------------------------------- -// Direct DSP access +/* ------------------------------------------------------------------------------------------------------------ + * Direct DSP access */ void* UI::d_getPluginInstancePointer() const noexcept { @@ -90,10 +82,16 @@ void* UI::d_getPluginInstancePointer() const noexcept } #endif -// ----------------------------------------------------------------------- -// UI Callbacks (optional) +/* ------------------------------------------------------------------------------------------------------------ + * DSP/Plugin Callbacks (optional) */ -void UI::d_uiReshape(int width, int height) +void UI::d_sampleRateChanged(double) {} + +/* ------------------------------------------------------------------------------------------------------------ + * UI Callbacks (optional) */ + +#if ! DISTRHO_UI_USE_NTK +void UI::d_uiReshape(uint width, uint height) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -104,7 +102,24 @@ void UI::d_uiReshape(int width, int height) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } +#endif + +/* ------------------------------------------------------------------------------------------------------------ + * UI Resize Handling, internal */ + +#if DISTRHO_UI_USE_NTK +void UI::resize(int x, int y, int w, int h) +{ + UIWidget::resize(x, y, w, h); + pData->setSizeCallback(w, h); +} +#else +void UI::onResize(const ResizeEvent& ev) +{ + pData->setSizeCallback(ev.size.getWidth(), ev.size.getHeight()); +} +#endif -// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------------------------- END_NAMESPACE_DISTRHO diff --git a/libs/distrho/src/DistrhoUIDSSI.cpp b/libs/distrho/src/DistrhoUIDSSI.cpp index 4747035..0a3d6f9 100644 --- a/libs/distrho/src/DistrhoUIDSSI.cpp +++ b/libs/distrho/src/DistrhoUIDSSI.cpp @@ -97,7 +97,7 @@ public: fHostClosed(false), fOscData(oscData) { - fUI.setTitle(uiTitle); + fUI.setWindowTitle(uiTitle); } ~UIDssi() @@ -112,7 +112,7 @@ public: { fOscData.idle(); - if (! fUI.idle()) + if (fHostClosed || ! fUI.idle()) break; d_msleep(30); @@ -140,14 +140,19 @@ public: } #endif + void dssiui_samplerate(const double sampleRate) + { + fUI.setSampleRate(sampleRate, true); + } + void dssiui_show() { - fUI.setVisible(true); + fUI.setWindowVisible(true); } void dssiui_hide() { - fUI.setVisible(false); + fUI.setWindowVisible(false); } void dssiui_quit() @@ -190,7 +195,7 @@ protected: void setSize(const uint width, const uint height) { - fUI.setSize(width, height); + fUI.setWindowSize(width, height); } private: @@ -322,6 +327,9 @@ int osc_sample_rate_handler(const char*, const char*, lo_arg** argv, int, lo_mes d_lastUiSampleRate = sampleRate; + if (globalUI != nullptr) + globalUI->dssiui_samplerate(sampleRate); + return 0; } @@ -373,6 +381,9 @@ int main(int argc, char* argv[]) globalUI->dssiui_show(); globalUI->exec(); + delete globalUI; + globalUI = nullptr; + return 0; } diff --git a/libs/distrho/src/DistrhoUIInternal.hpp b/libs/distrho/src/DistrhoUIInternal.hpp index 15b65ca..e5b5376 100644 --- a/libs/distrho/src/DistrhoUIInternal.hpp +++ b/libs/distrho/src/DistrhoUIInternal.hpp @@ -19,21 +19,28 @@ #include "../DistrhoUI.hpp" -#include "../../dgl/App.hpp" -#include "../../dgl/Window.hpp" +#if DISTRHO_UI_USE_NTK +# include "../../dgl/ntk/NtkApp.hpp" +# include "../../dgl/ntk/NtkWindow.hpp" +typedef DGL::NtkApp App; +typedef DGL::NtkWindow UIWindow; +#else +# include "../../dgl/App.hpp" +# include "../../dgl/Window.hpp" +typedef DGL::App App; +typedef DGL::Window UIWindow; +#endif -using DGL::App; using DGL::IdleCallback; -using DGL::Window; START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------- // Static data, see DistrhoUI.cpp -extern double d_lastUiSampleRate; -extern void* d_lastUiDspPtr; -extern Window* d_lastUiWindow; +extern double d_lastUiSampleRate; +extern void* d_lastUiDspPtr; +extern UIWindow* d_lastUiWindow; // ----------------------------------------------------------------------- // UI callbacks @@ -130,7 +137,7 @@ struct UI::PrivateData { // Plugin Window, needed to take care of resize properly static inline -UI* createUiWrapper(void* const dspPtr, Window* const window) +UI* createUiWrapper(void* const dspPtr, UIWindow* const window) { d_lastUiDspPtr = dspPtr; d_lastUiWindow = window; @@ -140,28 +147,29 @@ UI* createUiWrapper(void* const dspPtr, Window* const window) return ret; } -class UIExporterWindow : public Window +class UIExporterWindow : public UIWindow { public: UIExporterWindow(App& app, const intptr_t winId, void* const dspPtr) - : Window(app, winId), - fUi(createUiWrapper(dspPtr, this)), + : UIWindow(app, winId), + fUI(createUiWrapper(dspPtr, this)), fIsReady(false) { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + // set window size setResizable(false); - setSize(fUi->d_getWidth(), fUi->d_getHeight()); + setSize(fUI->getWidth(), fUI->getHeight()); } ~UIExporterWindow() { - delete fUi; + delete fUI; } UI* getUI() const noexcept { - return fUi; + return fUI; } bool isReady() const noexcept @@ -169,19 +177,27 @@ public: return fIsReady; } -protected: - void onReshape(int width, int height) override +//protected: +#if DISTRHO_UI_USE_NTK + void resize(int x, int y, int width, int height) override { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); - + UIWindow::resize(x, y, width, height); fIsReady = true; + } +#else + void onReshape(uint width, uint height) override + { + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + + // custom window reshape + fUI->d_uiReshape(width, height); - fUi->setSize(width, height); - fUi->d_uiReshape(width, height); + fIsReady = true; } +#endif private: - UI* const fUi; + UI* const fUI; bool fIsReady; }; @@ -196,10 +212,11 @@ public: void* const dspPtr = nullptr) : glApp(), glWindow(glApp, winId, dspPtr), - fUi(glWindow.getUI()), - fData((fUi != nullptr) ? fUi->pData : nullptr) + fChangingSize(false), + fUI(glWindow.getUI()), + fData((fUI != nullptr) ? fUI->pData : nullptr) { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); fData->ptr = ptr; @@ -212,25 +229,19 @@ public: // ------------------------------------------------------------------- - const char* getName() const noexcept - { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, ""); - - return fUi->d_getName(); - } - uint getWidth() const noexcept { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, 0); - - return fUi->d_getWidth(); + return glWindow.getWidth(); } uint getHeight() const noexcept { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, 0); + return glWindow.getHeight(); + } - return fUi->d_getHeight(); + bool isVisible() const noexcept + { + return glWindow.isVisible(); } // ------------------------------------------------------------------- @@ -246,28 +257,28 @@ public: void parameterChanged(const uint32_t index, const float value) { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); - fUi->d_parameterChanged(index, value); + fUI->d_parameterChanged(index, value); } #if DISTRHO_PLUGIN_WANT_PROGRAMS void programChanged(const uint32_t index) { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); - fUi->d_programChanged(index); + fUI->d_programChanged(index); } #endif #if DISTRHO_PLUGIN_WANT_STATE void stateChanged(const char* const key, const char* const value) { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); + 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); + fUI->d_stateChanged(key, value); } #endif @@ -276,7 +287,7 @@ public: void exec(IdleCallback* const cb) { DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,); - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); glWindow.addIdleCallback(cb); glWindow.setVisible(true); @@ -286,24 +297,23 @@ public: void exec_idle() { if (glWindow.isReady()) - fUi->d_uiIdle(); + fUI->d_uiIdle(); + + fChangingSize = false; } bool idle() { - DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, false); + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false); glApp.idle(); if (glWindow.isReady()) - fUi->d_uiIdle(); + fUI->d_uiIdle(); - return ! glApp.isQuiting(); - } + fChangingSize = false; - bool isVisible() const noexcept - { - return glWindow.isVisible(); + return ! glApp.isQuiting(); } void quit() @@ -312,28 +322,57 @@ public: glApp.quit(); } - void setSize(const uint width, const uint height) + // ------------------------------------------------------------------- + + void setWindowSize(const uint width, const uint height, const bool updateUI = false) { + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + + if (fChangingSize) + return; + + fChangingSize = true; + + if (updateUI) + fUI->setSize(width, height); + glWindow.setSize(width, height); } - void setTitle(const char* const uiTitle) + void setWindowTitle(const char* const uiTitle) { glWindow.setTitle(uiTitle); } - void setTransientWinId(const intptr_t winId) + void setWindowTransientWinId(const intptr_t winId) { glWindow.setTransientWinId(winId); } - bool setVisible(const bool yesNo) + bool setWindowVisible(const bool yesNo) { glWindow.setVisible(yesNo); return ! glApp.isQuiting(); } + // ------------------------------------------------------------------- + + void setSampleRate(const double sampleRate, const bool doCallback = false) + { + DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); + DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); + DISTRHO_SAFE_ASSERT(sampleRate > 0.0); + + if (fData->sampleRate == sampleRate) + return; + + fData->sampleRate = sampleRate; + + if (doCallback) + fUI->d_sampleRateChanged(sampleRate); + } + private: // ------------------------------------------------------------------- // DGL Application and Window for this widget @@ -341,10 +380,13 @@ private: App glApp; UIExporterWindow glWindow; + // prevent recursion + bool fChangingSize; + // ------------------------------------------------------------------- // Widget and DistrhoUI data - UI* const fUi; + UI* const fUI; UI::PrivateData* const fData; DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter) diff --git a/libs/distrho/src/DistrhoUILV2.cpp b/libs/distrho/src/DistrhoUILV2.cpp index fbce23e..4de5346 100644 --- a/libs/distrho/src/DistrhoUILV2.cpp +++ b/libs/distrho/src/DistrhoUILV2.cpp @@ -16,6 +16,8 @@ #include "DistrhoUIInternal.hpp" +#include "../extra/d_string.hpp" + #include "lv2/atom.h" #include "lv2/atom-util.h" #include "lv2/data-access.h" @@ -23,10 +25,9 @@ #include "lv2/options.h" #include "lv2/ui.h" #include "lv2/urid.h" +#include "lv2/lv2_kxstudio_properties.h" #include "lv2/lv2_programs.h" -#include <string> - START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------- @@ -58,22 +59,25 @@ public: if (winId != 0) return; + // if winId != 0 then options must not be null + DISTRHO_SAFE_ASSERT_RETURN(options != nullptr,); + const LV2_URID uridWindowTitle(uridMap->map(uridMap->handle, LV2_UI__windowTitle)); - const LV2_URID uridFrontendWinId(uridMap->map(uridMap->handle, "http://kxstudio.sf.net/ns/carla/frontendWinId")); + const LV2_URID uridTransientWinId(uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TransientWindowId)); bool hasTitle = false; for (int i=0; options[i].key != 0; ++i) { - if (options[i].key == uridFrontendWinId) + if (options[i].key == uridTransientWinId) { if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Long)) { - if (const int64_t frontendWinId = *(const int64_t*)options[i].value) - fUI.setTransientWinId(static_cast<intptr_t>(frontendWinId)); + if (const int64_t transientWinId = *(const int64_t*)options[i].value) + fUI.setWindowTransientWinId(static_cast<intptr_t>(transientWinId)); } else - d_stderr("Host provides frontendWinId but has wrong value type"); + d_stderr("Host provides transientWinId but has wrong value type"); } else if (options[i].key == uridWindowTitle) { @@ -82,7 +86,7 @@ public: if (const char* const windowTitle = (const char*)options[i].value) { hasTitle = true; - fUI.setTitle(windowTitle); + fUI.setWindowTitle(windowTitle); } } else @@ -91,7 +95,7 @@ public: } if (! hasTitle) - fUI.setTitle(fUI.getName()); + fUI.setWindowTitle(DISTRHO_PLUGIN_NAME); } // ------------------------------------------------------------------- @@ -115,13 +119,12 @@ public: { const LV2_Atom* const atom((const LV2_Atom*)buffer); - // TODO - check atom type + DISTRHO_SAFE_ASSERT_RETURN(atom->type == fKeyValueURID,); - const char* const stateKey((const char*)LV2_ATOM_BODY_CONST(atom)); - const char* const stateValue(stateKey+std::strlen(stateKey)+1); + const char* const key = (const char*)LV2_ATOM_BODY_CONST(atom); + const char* const value = key+(std::strlen(key)+1); - d_stdout("Got MSG in UI from DSP ==> %s | %s", stateKey, stateValue); - fUI.stateChanged(stateKey, stateValue); + fUI.stateChanged(key, value); } #endif } @@ -138,12 +141,49 @@ public: int lv2ui_show() { - return fUI.setVisible(true) ? 0 : 1; + return fUI.setWindowVisible(true) ? 0 : 1; } int lv2ui_hide() { - return fUI.setVisible(false) ? 0 : 1; + return fUI.setWindowVisible(false) ? 0 : 1; + } + + int lv2ui_resize(uint width, uint height) + { + fUI.setWindowSize(width, height, true); + return 0; + } + + // ------------------------------------------------------------------- + + uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) + { + // currently unused + return LV2_OPTIONS_ERR_UNKNOWN; + } + + uint32_t lv2_set_options(const LV2_Options_Option* const options) + { + for (int i=0; options[i].key != 0; ++i) + { + if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate)) + { + if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Double)) + { + const double sampleRate(*(const double*)options[i].value); + fUI.setSampleRate(sampleRate); + continue; + } + else + { + d_stderr("Host changed sampleRate but with wrong value type"); + continue; + } + } + } + + return LV2_OPTIONS_SUCCESS; } // ------------------------------------------------------------------- @@ -168,25 +208,27 @@ protected: void setParameterValue(const uint32_t rindex, const float value) { - if (fWriteFunction != nullptr) - fWriteFunction(fController, rindex, sizeof(float), 0, &value); + DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,); + + fWriteFunction(fController, rindex, sizeof(float), 0, &value); } void setState(const char* const key, const char* const value) { - if (fWriteFunction == nullptr) - return; + DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,); const uint32_t eventInPortIndex(DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS); // join key and value - std::string tmpStr; - tmpStr += std::string(key); - tmpStr += std::string("\0", 1); - tmpStr += std::string(value); + d_string tmpStr; + tmpStr += key; + tmpStr += "\xff"; + tmpStr += value; - // get msg size - const size_t msgSize(tmpStr.size()+1); + tmpStr[std::strlen(key)] = '\0'; + + // set msg size (key + separator + value + null terminator) + const size_t msgSize(tmpStr.length()+1); // reserve atom space const size_t atomSize(lv2_atom_pad_size(sizeof(LV2_Atom) + msgSize)); @@ -199,7 +241,7 @@ protected: atom->type = fKeyValueURID; // set atom data - std::memcpy(atomBuf + sizeof(LV2_Atom), tmpStr.data(), msgSize-1); + std::memcpy(atomBuf + sizeof(LV2_Atom), tmpStr.buffer(), msgSize); // send to DSP side fWriteFunction(fController, eventInPortIndex, atomSize, fEventTransferURID, atom); @@ -211,7 +253,7 @@ protected: void setSize(const uint width, const uint height) { - fUI.setSize(width, height); + fUI.setWindowSize(width, height); if (fUiResize != nullptr && ! fWinIdWasNull) fUiResize->ui_resize(fUiResize->handle, width, height); @@ -313,9 +355,9 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, #endif } - if (options == nullptr) + if (options == nullptr && parentId == nullptr) { - d_stderr("Options feature missing, cannot continue!"); + d_stderr("Options feature missing (needed for show-interface), cannot continue!"); return nullptr; } @@ -338,10 +380,11 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, } if (const LV2_DirectAccess_Interface* const directAccess = (const LV2_DirectAccess_Interface*)extData->data_access(DISTRHO_DIRECT_ACCESS_URI)) - { instance = directAccess->get_instance_pointer(instance); - } else + instance = nullptr; + + if (instance == nullptr) { d_stderr("Failed to get direct access, cannot continue!"); return nullptr; @@ -352,23 +395,29 @@ static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, const intptr_t winId((intptr_t)parentId); - const LV2_URID uridSampleRate(uridMap->map(uridMap->handle, LV2_CORE__sampleRate)); - - for (int i=0; options[i].key != 0; ++i) + if (options != nullptr) { - if (options[i].key == uridSampleRate) + const LV2_URID uridSampleRate(uridMap->map(uridMap->handle, LV2_CORE__sampleRate)); + + for (int i=0; options[i].key != 0; ++i) { - if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Double)) - d_lastUiSampleRate = *(const double*)options[i].value; - else - d_stderr("Host provides sampleRate but has wrong value type"); + if (options[i].key == uridSampleRate) + { + if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Double)) + d_lastUiSampleRate = *(const double*)options[i].value; + else + d_stderr("Host provides sampleRate but has wrong value type"); - break; + break; + } } } if (d_lastUiSampleRate == 0.0) + { + d_stdout("WARNING: this host does not send sample-rate information for LV2 UIs, using 44100 as fallback (this could be wrong)"); d_lastUiSampleRate = 44100.0; + } return new UiLv2(winId, options, uridMap, uiResize, uiTouch, controller, writeFunction, instance); } @@ -402,6 +451,30 @@ static int lv2ui_hide(LV2UI_Handle ui) return uiPtr->lv2ui_hide(); } +static int lv2ui_resize(LV2UI_Handle ui, int width, int height) +{ + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, 1); + DISTRHO_SAFE_ASSERT_RETURN(width > 0, 1); + DISTRHO_SAFE_ASSERT_RETURN(height > 0, 1); + + return 1; // This needs more testing + //return uiPtr->lv2ui_resize(width, height); +} + +// ----------------------------------------------------------------------- + +static uint32_t lv2_get_options(LV2UI_Handle ui, LV2_Options_Option* options) +{ + return uiPtr->lv2_get_options(options); +} + +static uint32_t lv2_set_options(LV2UI_Handle ui, const LV2_Options_Option* options) +{ + return uiPtr->lv2_set_options(options); +} + +// ----------------------------------------------------------------------- + #if DISTRHO_PLUGIN_WANT_PROGRAMS static void lv2ui_select_program(LV2UI_Handle ui, uint32_t bank, uint32_t program) { @@ -413,13 +486,19 @@ static void lv2ui_select_program(LV2UI_Handle ui, uint32_t bank, uint32_t progra static const void* lv2ui_extension_data(const char* uri) { - static const LV2UI_Idle_Interface uiIdle = { lv2ui_idle }; - static const LV2UI_Show_Interface uiShow = { lv2ui_show, lv2ui_hide }; + static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options }; + static const LV2UI_Idle_Interface uiIdle = { lv2ui_idle }; + static const LV2UI_Show_Interface uiShow = { lv2ui_show, lv2ui_hide }; + static const LV2UI_Resize uiResz = { nullptr, lv2ui_resize }; + if (std::strcmp(uri, LV2_OPTIONS__interface) == 0) + return &options; if (std::strcmp(uri, LV2_UI__idleInterface) == 0) return &uiIdle; if (std::strcmp(uri, LV2_UI__showInterface) == 0) return &uiShow; + if (std::strcmp(uri, LV2_UI__resize) == 0) + return &uiResz; #if DISTRHO_PLUGIN_WANT_PROGRAMS static const LV2_Programs_UI_Interface uiPrograms = { lv2ui_select_program }; diff --git a/libs/distrho/src/lv2/lv2_kxstudio_properties.h b/libs/distrho/src/lv2/lv2_kxstudio_properties.h new file mode 100644 index 0000000..e8b42a6 --- /dev/null +++ b/libs/distrho/src/lv2/lv2_kxstudio_properties.h @@ -0,0 +1,33 @@ +/* + LV2 KXStudio Properties Extension + Copyright 2014 Filipe Coelho <falktx@falktx.com> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file lv2_kxstudio_properties.h + C header for the LV2 KXStudio Properties extension <http://kxstudio.sf.net/ns/lv2ext/props>. +*/ + +#ifndef LV2_KXSTUDIO_PROPERTIES_H +#define LV2_KXSTUDIO_PROPERTIES_H + +#define LV2_KXSTUDIO_PROPERTIES_URI "http://kxstudio.sf.net/ns/lv2ext/props" +#define LV2_KXSTUDIO_PROPERTIES_PREFIX LV2_KXSTUDIO_PROPERTIES_URI "#" + +#define LV2_KXSTUDIO_PROPERTIES__NonAutomable LV2_KXSTUDIO_PROPERTIES_PREFIX "NonAutomable" +#define LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat LV2_KXSTUDIO_PROPERTIES_PREFIX "TimePositionTicksPerBeat" +#define LV2_KXSTUDIO_PROPERTIES__TransientWindowId LV2_KXSTUDIO_PROPERTIES_PREFIX "TransientWindowId" + +#endif /* LV2_KXSTUDIO_PROPERTIES_H */ diff --git a/libs/distrho/src/vestige/aeffectx.h b/libs/distrho/src/vestige/aeffectx.h index 0cbde1a..23f84f2 100755..100644 --- a/libs/distrho/src/vestige/aeffectx.h +++ b/libs/distrho/src/vestige/aeffectx.h @@ -2,7 +2,7 @@ * aeffectx.h - simple header to allow VeSTige compilation and eventually work * * Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net> - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -113,12 +113,11 @@ #define kEffectMagic (CCONST( 'V', 's', 't', 'P' )) #define kVstLangEnglish 1 #define kVstMidiType 1 -#define kVstTempoValid (1 << 10) -#define kVstTransportPlaying (1 << 1) - struct RemoteVstPlugin; +#define kVstTransportPlaying (1 << 1) + #define kVstNanosValid (1 << 8) #define kVstPpqPosValid (1 << 9) #define kVstTempoValid (1 << 10) @@ -250,29 +249,26 @@ struct _AEffect typedef struct _AEffect AEffect; -struct _VstTimeInfo +typedef struct _VstTimeInfo { - // 00 - double samplePos; - // 08 - double sampleRate; - // unconfirmed 10 18 - char empty1[8 + 8]; - // 20? - double tempo; - // unconfirmed 28 30 38 - char empty2[8 + 8 + 8]; - // 40? - int timeSigNumerator; - // 44? - int timeSigDenominator; - // unconfirmed 48 4c 50 - char empty3[4 + 4 + 4]; - // 54 - int flags; -}; + /* info from online documentation of VST provided by Steinberg */ + + double samplePos; + double sampleRate; + double nanoSeconds; + double ppqPos; + double tempo; + double barStartPos; + double cycleStartPos; + double cycleEndPos; + int32_t timeSigNumerator; + int32_t timeSigDenominator; + int32_t smpteOffset; + int32_t smpteFrameRate; + int32_t samplesToNextClock; + int32_t flags; -typedef struct _VstTimeInfo VstTimeInfo; +} VstTimeInfo; typedef intptr_t (* audioMasterCallback) (AEffect *, int32_t, int32_t, intptr_t, void *, float); diff --git a/plugins/ZaMultiComp/ZaMultiCompPlugin.cpp b/plugins/ZaMultiComp/ZaMultiCompPlugin.cpp index 003c007..cf36218 100644 --- a/plugins/ZaMultiComp/ZaMultiCompPlugin.cpp +++ b/plugins/ZaMultiComp/ZaMultiCompPlugin.cpp @@ -36,7 +36,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) switch (index) { case paramAttack: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Attack"; parameter.symbol = "att"; parameter.unit = "ms"; @@ -45,7 +45,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 100.0f; break; case paramRelease: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Release"; parameter.symbol = "rel"; parameter.unit = "ms"; @@ -54,7 +54,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 500.0f; break; case paramKnee: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Knee"; parameter.symbol = "kn"; parameter.unit = "dB"; @@ -63,7 +63,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 9.0f; break; case paramRatio: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Ratio"; parameter.symbol = "rat"; parameter.unit = " "; @@ -72,7 +72,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramThresh: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Threshold"; parameter.symbol = "thr"; parameter.unit = "dB"; @@ -81,7 +81,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 0.0f; break; case paramMakeup1: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Makeup 1"; parameter.symbol = "mak1"; parameter.unit = "dB"; @@ -90,7 +90,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramMakeup2: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Makeup 2"; parameter.symbol = "mak2"; parameter.unit = "dB"; @@ -99,7 +99,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramMakeup3: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Makeup 3"; parameter.symbol = "mak3"; parameter.unit = "dB"; @@ -108,7 +108,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramGainR1: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Gain Reduction 1"; parameter.symbol = "gr1"; parameter.unit = "dB"; @@ -117,7 +117,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramGainR2: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Gain Reduction 2"; parameter.symbol = "gr2"; parameter.unit = "dB"; @@ -126,7 +126,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramGainR3: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Gain Reduction 3"; parameter.symbol = "gr3"; parameter.unit = "dB"; @@ -135,7 +135,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramXover1: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Crossover freq 1"; parameter.symbol = "xover1"; parameter.unit = "Hz"; @@ -144,7 +144,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1400.0f; break; case paramXover2: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Crossover freq 2"; parameter.symbol = "xover2"; parameter.unit = "Hz"; @@ -153,7 +153,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 14000.0f; break; case paramToggle1: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "ZamComp 1 ON"; parameter.symbol = "toggle1"; parameter.unit = " "; @@ -162,7 +162,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramToggle2: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "ZamComp 2 ON"; parameter.symbol = "toggle2"; parameter.unit = " "; @@ -171,7 +171,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramToggle3: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "ZamComp 3 ON"; parameter.symbol = "toggle3"; parameter.unit = " "; @@ -180,7 +180,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramListen1: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Listen 1"; parameter.symbol = "listen1"; parameter.unit = " "; @@ -189,7 +189,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramListen2: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Listen 2"; parameter.symbol = "listen2"; parameter.unit = " "; @@ -198,7 +198,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramListen3: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Listen 3"; parameter.symbol = "listen3"; parameter.unit = " "; @@ -207,7 +207,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramGlobalGain: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Master Trim"; parameter.symbol = "globalgain"; parameter.unit = "dB"; @@ -216,7 +216,7 @@ void ZaMultiCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramOutputLevel: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Output Level"; parameter.symbol = "outlevel"; parameter.unit = "dB"; diff --git a/plugins/ZaMultiComp/ZaMultiCompUI.cpp b/plugins/ZaMultiComp/ZaMultiCompUI.cpp index 70236af..65567b7 100644 --- a/plugins/ZaMultiComp/ZaMultiCompUI.cpp +++ b/plugins/ZaMultiComp/ZaMultiCompUI.cpp @@ -27,6 +27,8 @@ START_NAMESPACE_DISTRHO ZaMultiCompUI::ZaMultiCompUI() : UI() { + setSize(ZaMultiCompArtwork::zamulticompWidth, ZaMultiCompArtwork::zamulticompHeight); + // background fImgBackground = Image(ZaMultiCompArtwork::zamulticompData, ZaMultiCompArtwork::zamulticompWidth, ZaMultiCompArtwork::zamulticompHeight, GL_BGR); diff --git a/plugins/ZaMultiComp/ZaMultiCompUI.hpp b/plugins/ZaMultiComp/ZaMultiCompUI.hpp index 3d85b80..1ef3dc0 100644 --- a/plugins/ZaMultiComp/ZaMultiCompUI.hpp +++ b/plugins/ZaMultiComp/ZaMultiCompUI.hpp @@ -42,19 +42,6 @@ public: protected: // ------------------------------------------------------------------- - // Information - - uint d_getWidth() const noexcept override - { - return ZaMultiCompArtwork::zamulticompWidth; - } - - uint d_getHeight() const noexcept override - { - return ZaMultiCompArtwork::zamulticompHeight; - } - - // ------------------------------------------------------------------- // DSP Callbacks void d_parameterChanged(uint32_t index, float value) override; diff --git a/plugins/ZaMultiCompX2/ZaMultiCompX2Plugin.cpp b/plugins/ZaMultiCompX2/ZaMultiCompX2Plugin.cpp index f1c645b..da7b4f5 100644 --- a/plugins/ZaMultiCompX2/ZaMultiCompX2Plugin.cpp +++ b/plugins/ZaMultiCompX2/ZaMultiCompX2Plugin.cpp @@ -22,7 +22,7 @@ START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------- ZaMultiCompX2Plugin::ZaMultiCompX2Plugin() - : Plugin(paramCount, 1, 1) // 1 program, 1 state + : Plugin(paramCount, 1, 0) // 1 program, 0 state { // set default values d_setProgram(0); @@ -36,7 +36,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) switch (index) { case paramAttack: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Attack"; parameter.symbol = "att"; parameter.unit = "ms"; @@ -45,7 +45,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 100.0f; break; case paramRelease: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Release"; parameter.symbol = "rel"; parameter.unit = "ms"; @@ -54,7 +54,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 500.0f; break; case paramKnee: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Knee"; parameter.symbol = "kn"; parameter.unit = "dB"; @@ -63,7 +63,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 9.0f; break; case paramRatio: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Ratio"; parameter.symbol = "rat"; parameter.unit = " "; @@ -72,7 +72,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramThresh1: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Threshold 1"; parameter.symbol = "thr1"; parameter.unit = "dB"; @@ -81,7 +81,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 0.0f; break; case paramThresh2: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Threshold 2"; parameter.symbol = "thr2"; parameter.unit = "dB"; @@ -90,7 +90,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 0.0f; break; case paramThresh3: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Threshold 3"; parameter.symbol = "thr3"; parameter.unit = "dB"; @@ -99,7 +99,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 0.0f; break; case paramMakeup1: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Makeup 1"; parameter.symbol = "mak1"; parameter.unit = "dB"; @@ -108,7 +108,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramMakeup2: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Makeup 2"; parameter.symbol = "mak2"; parameter.unit = "dB"; @@ -117,7 +117,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramMakeup3: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Makeup 3"; parameter.symbol = "mak3"; parameter.unit = "dB"; @@ -126,7 +126,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramGainR1: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsAutomable | kParameterIsOutput; parameter.name = "Gain Reduction 1"; parameter.symbol = "gr1"; parameter.unit = "dB"; @@ -135,7 +135,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramGainR2: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsAutomable | kParameterIsOutput; parameter.name = "Gain Reduction 2"; parameter.symbol = "gr2"; parameter.unit = "dB"; @@ -144,7 +144,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramGainR3: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsAutomable | kParameterIsOutput; parameter.name = "Gain Reduction 3"; parameter.symbol = "gr3"; parameter.unit = "dB"; @@ -153,7 +153,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramXover1: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Crossover freq 1"; parameter.symbol = "xover1"; parameter.unit = "Hz"; @@ -162,7 +162,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20000.0f; break; case paramXover2: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Crossover freq 2"; parameter.symbol = "xover2"; parameter.unit = "Hz"; @@ -171,7 +171,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20000.0f; break; case paramToggle1: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "ZamComp 1 ON"; parameter.symbol = "toggle1"; parameter.unit = " "; @@ -180,7 +180,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramToggle2: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "ZamComp 2 ON"; parameter.symbol = "toggle2"; parameter.unit = " "; @@ -189,7 +189,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramToggle3: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "ZamComp 3 ON"; parameter.symbol = "toggle3"; parameter.unit = " "; @@ -198,7 +198,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramListen1: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Listen 1"; parameter.symbol = "listen1"; parameter.unit = " "; @@ -207,7 +207,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramListen2: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Listen 2"; parameter.symbol = "listen2"; parameter.unit = " "; @@ -216,7 +216,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramListen3: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Listen 3"; parameter.symbol = "listen3"; parameter.unit = " "; @@ -225,7 +225,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramGlobalGain: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Master Trim"; parameter.symbol = "globalgain"; parameter.unit = "dB"; @@ -234,7 +234,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramStereoDet: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Detection (MAX/avg)"; parameter.symbol = "stereodet"; parameter.unit = " "; @@ -243,7 +243,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramOutputLevelL: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Output Left"; parameter.symbol = "outl"; parameter.unit = "dB"; @@ -252,7 +252,7 @@ void ZaMultiCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramOutputLevelR: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Output Right"; parameter.symbol = "outr"; parameter.unit = "dB"; @@ -492,13 +492,13 @@ void ZaMultiCompX2Plugin::d_setProgram(uint32_t index) d_activate(); } -void ZaMultiCompX2Plugin::d_setState(const char* key, const char* value) +void ZaMultiCompX2Plugin::d_setState(const char*, const char*) { resetl = true; resetr = true; } -void ZaMultiCompX2Plugin::d_initStateKey(unsigned int key, d_string& val) +void ZaMultiCompX2Plugin::d_initState(unsigned int, d_string&, d_string&) { } diff --git a/plugins/ZaMultiCompX2/ZaMultiCompX2Plugin.hpp b/plugins/ZaMultiCompX2/ZaMultiCompX2Plugin.hpp index 20a5585..2ff8c7a 100644 --- a/plugins/ZaMultiCompX2/ZaMultiCompX2Plugin.hpp +++ b/plugins/ZaMultiCompX2/ZaMultiCompX2Plugin.hpp @@ -113,7 +113,7 @@ protected: void d_initParameter(uint32_t index, Parameter& parameter) ; void d_initProgramName(uint32_t index, d_string& programName) ; - void d_initStateKey(uint32_t, d_string&) override; + void d_initState(uint32_t, d_string&, d_string&) override; // ------------------------------------------------------------------- // Internal data diff --git a/plugins/ZaMultiCompX2/ZaMultiCompX2UI.cpp b/plugins/ZaMultiCompX2/ZaMultiCompX2UI.cpp index 53cc10e..245556d 100644 --- a/plugins/ZaMultiCompX2/ZaMultiCompX2UI.cpp +++ b/plugins/ZaMultiCompX2/ZaMultiCompX2UI.cpp @@ -27,6 +27,8 @@ START_NAMESPACE_DISTRHO ZaMultiCompX2UI::ZaMultiCompX2UI() : UI() { + setSize(ZaMultiCompX2Artwork::zamulticompx2Width, ZaMultiCompX2Artwork::zamulticompx2Height); + // background fImgBackground = Image(ZaMultiCompX2Artwork::zamulticompx2Data, ZaMultiCompX2Artwork::zamulticompx2Width, ZaMultiCompX2Artwork::zamulticompx2Height, GL_BGR); diff --git a/plugins/ZaMultiCompX2/ZaMultiCompX2UI.hpp b/plugins/ZaMultiCompX2/ZaMultiCompX2UI.hpp index 44dcb19..d9023f4 100644 --- a/plugins/ZaMultiCompX2/ZaMultiCompX2UI.hpp +++ b/plugins/ZaMultiCompX2/ZaMultiCompX2UI.hpp @@ -45,17 +45,6 @@ public: protected: // ------------------------------------------------------------------- - // Information - - uint d_getWidth() const noexcept override - { - return ZaMultiCompX2Artwork::zamulticompx2Width; - } - - uint d_getHeight() const noexcept override - { - return ZaMultiCompX2Artwork::zamulticompx2Height; - } void compcurve(float in, int k, float* x, float* y); void calc_compcurves(void); diff --git a/plugins/ZamAutoSat/DistrhoPluginInfo.h b/plugins/ZamAutoSat/DistrhoPluginInfo.h index d5c0cc7..efa7e32 100644 --- a/plugins/ZamAutoSat/DistrhoPluginInfo.h +++ b/plugins/ZamAutoSat/DistrhoPluginInfo.h @@ -27,7 +27,7 @@ #define DISTRHO_PLUGIN_NUM_OUTPUTS 1 #define DISTRHO_PLUGIN_WANT_LATENCY 0 -#define DISTRHO_PLUGIN_WANT_PROGRAMS 0 +#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 #define DISTRHO_PLUGIN_WANT_STATE 0 #define DISTRHO_PLUGIN_WANT_TIMEPOS 0 diff --git a/plugins/ZamAutoSat/ZamAutoSatUI.cpp b/plugins/ZamAutoSat/ZamAutoSatUI.cpp index b2dae8c..2857f11 100644 --- a/plugins/ZamAutoSat/ZamAutoSatUI.cpp +++ b/plugins/ZamAutoSat/ZamAutoSatUI.cpp @@ -24,6 +24,8 @@ START_NAMESPACE_DISTRHO ZamAutoSatUI::ZamAutoSatUI() : UI() { + setSize(ZamAutoSatArtwork::zamautosatWidth, ZamAutoSatArtwork::zamautosatHeight); + // background fImgBackground = Image(ZamAutoSatArtwork::zamautosatData, ZamAutoSatArtwork::zamautosatWidth, ZamAutoSatArtwork::zamautosatHeight, GL_BGR); diff --git a/plugins/ZamAutoSat/ZamAutoSatUI.hpp b/plugins/ZamAutoSat/ZamAutoSatUI.hpp index 4875382..59cefa7 100644 --- a/plugins/ZamAutoSat/ZamAutoSatUI.hpp +++ b/plugins/ZamAutoSat/ZamAutoSatUI.hpp @@ -39,19 +39,6 @@ public: protected: // ------------------------------------------------------------------- - // Information - - unsigned int d_getWidth() const noexcept override - { - return ZamAutoSatArtwork::zamautosatWidth; - } - - unsigned int d_getHeight() const noexcept override - { - return ZamAutoSatArtwork::zamautosatHeight; - } - - // ------------------------------------------------------------------- // DSP Callbacks void d_parameterChanged(uint32_t index, float value) override; diff --git a/plugins/ZamComp/ZamCompPlugin.cpp b/plugins/ZamComp/ZamCompPlugin.cpp index 0b13b5a..a7a1e1d 100644 --- a/plugins/ZamComp/ZamCompPlugin.cpp +++ b/plugins/ZamComp/ZamCompPlugin.cpp @@ -36,7 +36,7 @@ void ZamCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) switch (index) { case paramAttack: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Attack"; parameter.symbol = "att"; parameter.unit = "ms"; @@ -45,7 +45,7 @@ void ZamCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 200.0f; break; case paramRelease: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Release"; parameter.symbol = "rel"; parameter.unit = "ms"; @@ -54,7 +54,7 @@ void ZamCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 500.0f; break; case paramKnee: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Knee"; parameter.symbol = "kn"; parameter.unit = "dB"; @@ -63,7 +63,7 @@ void ZamCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 8.0f; break; case paramRatio: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Ratio"; parameter.symbol = "rat"; parameter.unit = " "; @@ -72,7 +72,7 @@ void ZamCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramThresh: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Threshold"; parameter.symbol = "thr"; parameter.unit = "dB"; @@ -81,7 +81,7 @@ void ZamCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 0.0f; break; case paramMakeup: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Makeup"; parameter.symbol = "mak"; parameter.unit = "dB"; @@ -90,7 +90,7 @@ void ZamCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramGainR: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Gain Reduction"; parameter.symbol = "gr"; parameter.unit = "dB"; @@ -99,7 +99,7 @@ void ZamCompPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 40.0f; break; case paramOutputLevel: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Output Level"; parameter.symbol = "outlevel"; parameter.unit = "dB"; diff --git a/plugins/ZamComp/ZamCompUI.cpp b/plugins/ZamComp/ZamCompUI.cpp index 48b4921..0be2e6c 100644 --- a/plugins/ZamComp/ZamCompUI.cpp +++ b/plugins/ZamComp/ZamCompUI.cpp @@ -25,6 +25,8 @@ START_NAMESPACE_DISTRHO ZamCompUI::ZamCompUI() : UI() { + setSize(ZamCompArtwork::zamcompWidth, ZamCompArtwork::zamcompHeight); + // background fImgBackground = Image(ZamCompArtwork::zamcompData, ZamCompArtwork::zamcompWidth, ZamCompArtwork::zamcompHeight, GL_BGR); diff --git a/plugins/ZamComp/ZamCompUI.hpp b/plugins/ZamComp/ZamCompUI.hpp index a9e7f75..8080d06 100644 --- a/plugins/ZamComp/ZamCompUI.hpp +++ b/plugins/ZamComp/ZamCompUI.hpp @@ -39,19 +39,6 @@ public: protected: // ------------------------------------------------------------------- - // Information - - uint d_getWidth() const noexcept override - { - return ZamCompArtwork::zamcompWidth; - } - - uint d_getHeight() const noexcept override - { - return ZamCompArtwork::zamcompHeight; - } - - // ------------------------------------------------------------------- // DSP Callbacks void d_parameterChanged(uint32_t index, float value) override; diff --git a/plugins/ZamCompX2/ZamCompX2Plugin.cpp b/plugins/ZamCompX2/ZamCompX2Plugin.cpp index 5165c98..03b8e5b 100644 --- a/plugins/ZamCompX2/ZamCompX2Plugin.cpp +++ b/plugins/ZamCompX2/ZamCompX2Plugin.cpp @@ -36,7 +36,7 @@ void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) switch (index) { case paramAttack: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Attack"; parameter.symbol = "att"; parameter.unit = "ms"; @@ -45,7 +45,7 @@ void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 100.0f; break; case paramRelease: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Release"; parameter.symbol = "rel"; parameter.unit = "ms"; @@ -54,7 +54,7 @@ void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 500.0f; break; case paramKnee: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Knee"; parameter.symbol = "kn"; parameter.unit = "dB"; @@ -63,7 +63,7 @@ void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 9.0f; break; case paramRatio: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Ratio"; parameter.symbol = "rat"; parameter.unit = " "; @@ -72,7 +72,7 @@ void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramThresh: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Threshold"; parameter.symbol = "thr"; parameter.unit = "dB"; @@ -81,7 +81,7 @@ void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 0.0f; break; case paramMakeup: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Makeup"; parameter.symbol = "mak"; parameter.unit = "dB"; @@ -90,7 +90,7 @@ void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramGainRed: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Gain Reduction"; parameter.symbol = "gr"; parameter.unit = "dB"; @@ -99,7 +99,7 @@ void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramStereo: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER; + parameter.hints = kParameterIsAutomable | kParameterIsInteger; parameter.name = "Stereolink"; parameter.symbol = "stereo"; parameter.unit = " "; @@ -108,7 +108,7 @@ void ZamCompX2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 2.0f; break; case paramOutputLevel: - parameter.hints = PARAMETER_IS_OUTPUT; + parameter.hints = kParameterIsOutput; parameter.name = "Output Level"; parameter.symbol = "outlevel"; parameter.unit = "dB"; diff --git a/plugins/ZamCompX2/ZamCompX2UI.cpp b/plugins/ZamCompX2/ZamCompX2UI.cpp index 017f2d7..36b7a7f 100644 --- a/plugins/ZamCompX2/ZamCompX2UI.cpp +++ b/plugins/ZamCompX2/ZamCompX2UI.cpp @@ -27,6 +27,8 @@ START_NAMESPACE_DISTRHO ZamCompX2UI::ZamCompX2UI() : UI() { + setSize(ZamCompX2Artwork::zamcompx2Width, ZamCompX2Artwork::zamcompx2Height); + // background fImgBackground = Image(ZamCompX2Artwork::zamcompx2Data, ZamCompX2Artwork::zamcompx2Width, ZamCompX2Artwork::zamcompx2Height, GL_BGR); diff --git a/plugins/ZamCompX2/ZamCompX2UI.hpp b/plugins/ZamCompX2/ZamCompX2UI.hpp index e9601a0..9eb1edb 100644 --- a/plugins/ZamCompX2/ZamCompX2UI.hpp +++ b/plugins/ZamCompX2/ZamCompX2UI.hpp @@ -42,19 +42,6 @@ public: protected: // ------------------------------------------------------------------- - // Information - - uint d_getWidth() const noexcept override - { - return ZamCompX2Artwork::zamcompx2Width; - } - - uint d_getHeight() const noexcept override - { - return ZamCompX2Artwork::zamcompx2Height; - } - - // ------------------------------------------------------------------- // DSP Callbacks void d_parameterChanged(uint32_t index, float value) override; diff --git a/plugins/ZamEQ2/ZamEQ2Plugin.cpp b/plugins/ZamEQ2/ZamEQ2Plugin.cpp index 74ad615..f150538 100644 --- a/plugins/ZamEQ2/ZamEQ2Plugin.cpp +++ b/plugins/ZamEQ2/ZamEQ2Plugin.cpp @@ -36,7 +36,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) switch (index) { case paramGain1: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Boost/Cut 1"; parameter.symbol = "boost1"; parameter.unit = "dB"; @@ -45,7 +45,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramQ1: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Bandwidth 1"; parameter.symbol = "bw1"; parameter.unit = " "; @@ -54,7 +54,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 6.0f; break; case paramFreq1: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Frequency 1"; parameter.symbol = "f1"; parameter.unit = "Hz"; @@ -63,7 +63,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 14000.0f; break; case paramGain2: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Boost/Cut 2"; parameter.symbol = "boost2"; parameter.unit = "dB"; @@ -72,7 +72,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramQ2: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Bandwidth 2"; parameter.symbol = "bw2"; parameter.unit = " "; @@ -81,7 +81,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 6.0f; break; case paramFreq2: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Frequency 2"; parameter.symbol = "f2"; parameter.unit = "Hz"; @@ -90,7 +90,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 14000.0f; break; case paramGainL: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Boost/Cut L"; parameter.symbol = "boostl"; parameter.unit = "dB"; @@ -99,7 +99,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramFreqL: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Frequency L"; parameter.symbol = "fl"; parameter.unit = "Hz"; @@ -108,7 +108,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 14000.0f; break; case paramGainH: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Boost/Cut H"; parameter.symbol = "boosth"; parameter.unit = "dB"; @@ -117,7 +117,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramFreqH: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_LOGARITHMIC; + parameter.hints = kParameterIsAutomable | kParameterIsLogarithmic; parameter.name = "Frequency H"; parameter.symbol = "fh"; parameter.unit = "Hz"; @@ -126,7 +126,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 14000.0f; break; case paramMaster: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Master Gain"; parameter.symbol = "master"; parameter.unit = "dB"; @@ -135,7 +135,7 @@ void ZamEQ2Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramTogglePeaks: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Peaks ON"; parameter.symbol = "peaks"; parameter.unit = " "; diff --git a/plugins/ZamEQ2/ZamEQ2UI.cpp b/plugins/ZamEQ2/ZamEQ2UI.cpp index 663ac7f..ba7f543 100644 --- a/plugins/ZamEQ2/ZamEQ2UI.cpp +++ b/plugins/ZamEQ2/ZamEQ2UI.cpp @@ -26,6 +26,8 @@ START_NAMESPACE_DISTRHO ZamEQ2UI::ZamEQ2UI() : UI() { + setSize(ZamEQ2Artwork::zameq2Width, ZamEQ2Artwork::zameq2Height); + // background fImgBackground = Image(ZamEQ2Artwork::zameq2Data, ZamEQ2Artwork::zameq2Width, ZamEQ2Artwork::zameq2Height, GL_BGR); diff --git a/plugins/ZamEQ2/ZamEQ2UI.hpp b/plugins/ZamEQ2/ZamEQ2UI.hpp index 6bb4100..0b4bb80 100644 --- a/plugins/ZamEQ2/ZamEQ2UI.hpp +++ b/plugins/ZamEQ2/ZamEQ2UI.hpp @@ -46,17 +46,6 @@ public: protected: // ------------------------------------------------------------------- - // Information - - uint d_getWidth() const noexcept override - { - return ZamEQ2Artwork::zameq2Width; - } - - uint d_getHeight() const noexcept override - { - return ZamEQ2Artwork::zameq2Height; - } inline double to_dB(double g) { diff --git a/plugins/ZamGEQ31/ZamGEQ31Plugin.cpp b/plugins/ZamGEQ31/ZamGEQ31Plugin.cpp index eb72bd7..58f5815 100644 --- a/plugins/ZamGEQ31/ZamGEQ31Plugin.cpp +++ b/plugins/ZamGEQ31/ZamGEQ31Plugin.cpp @@ -36,7 +36,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) switch (index) { case paramMaster: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Master Gain"; parameter.symbol = "master"; parameter.unit = "dB"; @@ -45,7 +45,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.f; break; case paramGain1: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "20Hz"; parameter.symbol = "band1"; parameter.unit = "dB"; @@ -54,7 +54,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain2: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "25Hz"; parameter.symbol = "band2"; parameter.unit = "dB"; @@ -63,7 +63,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain3: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "31.5Hz"; parameter.symbol = "band3"; parameter.unit = "dB"; @@ -72,7 +72,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain4: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "40Hz"; parameter.symbol = "band4"; parameter.unit = "dB"; @@ -81,7 +81,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain5: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "50Hz"; parameter.symbol = "band5"; parameter.unit = "dB"; @@ -90,7 +90,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain6: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "63Hz"; parameter.symbol = "band6"; parameter.unit = "dB"; @@ -99,7 +99,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain7: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "80Hz"; parameter.symbol = "band7"; parameter.unit = "dB"; @@ -108,7 +108,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain8: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "100Hz"; parameter.symbol = "band8"; parameter.unit = "dB"; @@ -117,7 +117,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain9: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "125Hz"; parameter.symbol = "band9"; parameter.unit = "dB"; @@ -126,7 +126,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain10: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "160Hz"; parameter.symbol = "band10"; parameter.unit = "dB"; @@ -135,7 +135,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain11: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "200Hz"; parameter.symbol = "band11"; parameter.unit = "dB"; @@ -144,7 +144,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain12: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "250Hz"; parameter.symbol = "band12"; parameter.unit = "dB"; @@ -153,7 +153,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain13: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "315Hz"; parameter.symbol = "band13"; parameter.unit = "dB"; @@ -162,7 +162,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain14: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "400Hz"; parameter.symbol = "band14"; parameter.unit = "dB"; @@ -171,7 +171,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain15: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "500Hz"; parameter.symbol = "band15"; parameter.unit = "dB"; @@ -180,7 +180,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain16: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "630Hz"; parameter.symbol = "band16"; parameter.unit = "dB"; @@ -189,7 +189,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain17: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "800Hz"; parameter.symbol = "band17"; parameter.unit = "dB"; @@ -198,7 +198,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain18: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "1000Hz"; parameter.symbol = "band18"; parameter.unit = "dB"; @@ -207,7 +207,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain19: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "1250Hz"; parameter.symbol = "band19"; parameter.unit = "dB"; @@ -216,7 +216,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain20: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "1600Hz"; parameter.symbol = "band20"; parameter.unit = "dB"; @@ -225,7 +225,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain21: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "2000Hz"; parameter.symbol = "band21"; parameter.unit = "dB"; @@ -234,7 +234,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain22: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "2500Hz"; parameter.symbol = "band22"; parameter.unit = "dB"; @@ -243,7 +243,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain23: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "3150Hz"; parameter.symbol = "band23"; parameter.unit = "dB"; @@ -252,7 +252,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain24: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "4000Hz"; parameter.symbol = "band24"; parameter.unit = "dB"; @@ -261,7 +261,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain25: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "5000Hz"; parameter.symbol = "band25"; parameter.unit = "dB"; @@ -270,7 +270,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain26: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "6300Hz"; parameter.symbol = "band26"; parameter.unit = "dB"; @@ -279,7 +279,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain27: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "8000Hz"; parameter.symbol = "band27"; parameter.unit = "dB"; @@ -288,7 +288,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain28: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "10kHz"; parameter.symbol = "band28"; parameter.unit = "dB"; @@ -297,7 +297,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain29: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "12.5kHz"; parameter.symbol = "band29"; parameter.unit = "dB"; @@ -306,7 +306,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain30: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "16kHz"; parameter.symbol = "band30"; parameter.unit = "dB"; @@ -315,7 +315,7 @@ void ZamGEQ31Plugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 12.0f; break; case paramGain31: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "20kHz"; parameter.symbol = "band31"; parameter.unit = "dB"; diff --git a/plugins/ZamGEQ31/ZamGEQ31UI.cpp b/plugins/ZamGEQ31/ZamGEQ31UI.cpp index e18ee59..5c98115 100644 --- a/plugins/ZamGEQ31/ZamGEQ31UI.cpp +++ b/plugins/ZamGEQ31/ZamGEQ31UI.cpp @@ -26,6 +26,8 @@ START_NAMESPACE_DISTRHO ZamGEQ31UI::ZamGEQ31UI() : UI() { + setSize(ZamGEQ31Artwork::zamgeq31Width, ZamGEQ31Artwork::zamgeq31Height); + // background fImgBackground = Image(ZamGEQ31Artwork::zamgeq31Data, ZamGEQ31Artwork::zamgeq31Width, ZamGEQ31Artwork::zamgeq31Height, GL_BGR); diff --git a/plugins/ZamGEQ31/ZamGEQ31UI.hpp b/plugins/ZamGEQ31/ZamGEQ31UI.hpp index 332be20..2e7ff98 100644 --- a/plugins/ZamGEQ31/ZamGEQ31UI.hpp +++ b/plugins/ZamGEQ31/ZamGEQ31UI.hpp @@ -43,17 +43,6 @@ public: protected: // ------------------------------------------------------------------- - // Information - - uint d_getWidth() const noexcept override - { - return ZamGEQ31Artwork::zamgeq31Width; - } - - uint d_getHeight() const noexcept override - { - return ZamGEQ31Artwork::zamgeq31Height; - } inline double to_dB(double g) { diff --git a/plugins/ZamNoise/ZamNoisePlugin.cpp b/plugins/ZamNoise/ZamNoisePlugin.cpp index 15053af..18a3dfb 100644 --- a/plugins/ZamNoise/ZamNoisePlugin.cpp +++ b/plugins/ZamNoise/ZamNoisePlugin.cpp @@ -49,7 +49,7 @@ void ZamNoisePlugin::d_initParameter(uint32_t index, Parameter& parameter) switch (index) { case paramNoiseToggle: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Noise Capture"; parameter.symbol = "noisecapture"; parameter.unit = ""; diff --git a/plugins/ZamNoise/ZamNoiseUI.cpp b/plugins/ZamNoise/ZamNoiseUI.cpp index 38e9e52..26a3ca9 100644 --- a/plugins/ZamNoise/ZamNoiseUI.cpp +++ b/plugins/ZamNoise/ZamNoiseUI.cpp @@ -25,6 +25,8 @@ START_NAMESPACE_DISTRHO ZamNoiseUI::ZamNoiseUI() : UI() { + setSize(ZamNoiseArtwork::zamnoiseWidth, ZamNoiseArtwork::zamnoiseHeight); + // background fImgBackground = Image(ZamNoiseArtwork::zamnoiseData, ZamNoiseArtwork::zamnoiseWidth, ZamNoiseArtwork::zamnoiseHeight, GL_BGR); diff --git a/plugins/ZamNoise/ZamNoiseUI.hpp b/plugins/ZamNoise/ZamNoiseUI.hpp index 2266985..b423f3b 100644 --- a/plugins/ZamNoise/ZamNoiseUI.hpp +++ b/plugins/ZamNoise/ZamNoiseUI.hpp @@ -42,19 +42,6 @@ public: protected: // ------------------------------------------------------------------- - // Information - - unsigned int d_getWidth() const noexcept override - { - return ZamNoiseArtwork::zamnoiseWidth; - } - - unsigned int d_getHeight() const noexcept override - { - return ZamNoiseArtwork::zamnoiseHeight; - } - - // ------------------------------------------------------------------- // DSP Callbacks void d_parameterChanged(uint32_t index, float value) override; diff --git a/plugins/ZamSynth/ZamSynthPlugin.cpp b/plugins/ZamSynth/ZamSynthPlugin.cpp index d8dcd6a..6addb0b 100644 --- a/plugins/ZamSynth/ZamSynthPlugin.cpp +++ b/plugins/ZamSynth/ZamSynthPlugin.cpp @@ -36,7 +36,7 @@ void ZamSynthPlugin::d_initParameter(uint32_t index, Parameter& parameter) switch (index) { case paramGain: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Gain"; parameter.symbol = "gain"; parameter.unit = "dB"; @@ -45,7 +45,7 @@ void ZamSynthPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramSpeed: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER; + parameter.hints = kParameterIsAutomable | kParameterIsInteger; parameter.name = "Speed"; parameter.symbol = "speed"; parameter.unit = " "; @@ -54,7 +54,7 @@ void ZamSynthPlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 20.0f; break; case paramGraph: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN; + parameter.hints = kParameterIsAutomable | kParameterIsBoolean; parameter.name = "Graph toggle"; parameter.symbol = "graph"; parameter.unit = " "; diff --git a/plugins/ZamTube/ZamTubePlugin.cpp b/plugins/ZamTube/ZamTubePlugin.cpp index 3134b89..b76e637 100644 --- a/plugins/ZamTube/ZamTubePlugin.cpp +++ b/plugins/ZamTube/ZamTubePlugin.cpp @@ -43,7 +43,7 @@ void ZamTubePlugin::d_initParameter(uint32_t index, Parameter& parameter) switch (index) { case paramTubedrive: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Tube Drive"; parameter.symbol = "tubedrive"; parameter.unit = " "; @@ -52,7 +52,7 @@ void ZamTubePlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 30.0f; break; case paramBass: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Bass"; parameter.symbol = "bass"; parameter.unit = " "; @@ -61,7 +61,7 @@ void ZamTubePlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramMiddle: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Mids"; parameter.symbol = "mids"; parameter.unit = " "; @@ -70,7 +70,7 @@ void ZamTubePlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramTreble: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Treble"; parameter.symbol = "treb"; parameter.unit = " "; @@ -79,7 +79,7 @@ void ZamTubePlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 1.0f; break; case paramToneStack: - parameter.hints = PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER; + parameter.hints = kParameterIsAutomable | kParameterIsInteger; parameter.name = "Tone Stack Model"; parameter.symbol = "tonestack"; parameter.unit = " "; @@ -88,7 +88,7 @@ void ZamTubePlugin::d_initParameter(uint32_t index, Parameter& parameter) parameter.ranges.max = 24.0f; break; case paramGain: - parameter.hints = PARAMETER_IS_AUTOMABLE; + parameter.hints = kParameterIsAutomable; parameter.name = "Output level"; parameter.symbol = "gain"; parameter.unit = " "; diff --git a/plugins/ZamTube/ZamTubeUI.cpp b/plugins/ZamTube/ZamTubeUI.cpp index e18c7ee..4b0da58 100644 --- a/plugins/ZamTube/ZamTubeUI.cpp +++ b/plugins/ZamTube/ZamTubeUI.cpp @@ -32,6 +32,8 @@ START_NAMESPACE_DISTRHO ZamTubeUI::ZamTubeUI() : UI() { + setSize(ZamTubeArtwork::zamtubeWidth, ZamTubeArtwork::zamtubeHeight); + // background fImgBackground = Image(ZamTubeArtwork::zamtubeData, ZamTubeArtwork::zamtubeWidth, ZamTubeArtwork::zamtubeHeight, GL_BGR); diff --git a/plugins/ZamTube/ZamTubeUI.hpp b/plugins/ZamTube/ZamTubeUI.hpp index b992eda..7eaff89 100644 --- a/plugins/ZamTube/ZamTubeUI.hpp +++ b/plugins/ZamTube/ZamTubeUI.hpp @@ -42,19 +42,6 @@ public: protected: // ------------------------------------------------------------------- - // Information - - uint d_getWidth() const noexcept override - { - return ZamTubeArtwork::zamtubeWidth; - } - - uint d_getHeight() const noexcept override - { - return ZamTubeArtwork::zamtubeHeight; - } - - // ------------------------------------------------------------------- // DSP Callbacks void d_parameterChanged(uint32_t index, float value) ; |