Signed-off-by: falkTX <falktx@falktx.com>tags/v1.5
| @@ -29,22 +29,17 @@ ifneq ($(WINDOWS),true) | |||
| ifneq (,$(findstring bsd,$(TARGET_MACHINE))) | |||
| BSD=true | |||
| endif | |||
| ifneq (,$(findstring haiku,$(TARGET_MACHINE))) | |||
| else ifneq (,$(findstring haiku,$(TARGET_MACHINE))) | |||
| HAIKU=true | |||
| endif | |||
| ifneq (,$(findstring linux,$(TARGET_MACHINE))) | |||
| else ifneq (,$(findstring linux,$(TARGET_MACHINE))) | |||
| LINUX=true | |||
| else ifneq (,$(findstring gnu,$(TARGET_MACHINE))) | |||
| HURD=true | |||
| endif | |||
| ifneq (,$(findstring apple,$(TARGET_MACHINE))) | |||
| else ifneq (,$(findstring apple,$(TARGET_MACHINE))) | |||
| MACOS=true | |||
| endif | |||
| ifneq (,$(findstring mingw,$(TARGET_MACHINE))) | |||
| else ifneq (,$(findstring mingw,$(TARGET_MACHINE))) | |||
| WINDOWS=true | |||
| endif | |||
| ifneq (,$(findstring windows,$(TARGET_MACHINE))) | |||
| else ifneq (,$(findstring windows,$(TARGET_MACHINE))) | |||
| WINDOWS=true | |||
| endif | |||
| @@ -112,12 +112,29 @@ endif | |||
| # Set plugin symbols to export | |||
| ifeq ($(MACOS),true) | |||
| SYMBOLS_LADSPA = -Wl,-exported_symbol,_ladspa_descriptor | |||
| SYMBOLS_DSSI = -Wl,-exported_symbol,_ladspa_descriptor -Wl,-exported_symbol,_dssi_descriptor | |||
| SYMBOLS_LV2 = -Wl,-exported_symbol,_lv2_descriptor -Wl,-exported_symbol,_lv2_generate_ttl | |||
| SYMBOLS_LV2UI = -Wl,-exported_symbol,_lv2ui_descriptor | |||
| SYMBOLS_VST2 = -Wl,-exported_symbol,_VSTPluginMain | |||
| SYMBOLS_VST3 = -Wl,-exported_symbol,_GetPluginFactory -Wl,-exported_symbol,_bundleEntry -Wl,-exported_symbol,_bundleExit | |||
| SYMBOLS_LADSPA = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/ladspa.exp | |||
| SYMBOLS_DSSI = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/dssi.exp | |||
| SYMBOLS_LV2DSP = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2-dsp.exp | |||
| SYMBOLS_LV2UI = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2-ui.exp | |||
| SYMBOLS_LV2 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2.exp | |||
| SYMBOLS_VST2 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/vst2.exp | |||
| SYMBOLS_VST3 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/vst3.exp | |||
| else ifeq ($(WINDOWS),true) | |||
| SYMBOLS_LADSPA = $(DPF_PATH)/utils/symbols/ladspa.def | |||
| SYMBOLS_DSSI = $(DPF_PATH)/utils/symbols/dssi.def | |||
| SYMBOLS_LV2DSP = $(DPF_PATH)/utils/symbols/lv2-dsp.def | |||
| SYMBOLS_LV2UI = $(DPF_PATH)/utils/symbols/lv2-ui.def | |||
| SYMBOLS_LV2 = $(DPF_PATH)/utils/symbols/lv2.def | |||
| SYMBOLS_VST2 = $(DPF_PATH)/utils/symbols/vst2.def | |||
| SYMBOLS_VST3 = $(DPF_PATH)/utils/symbols/vst3.def | |||
| else | |||
| SYMBOLS_LADSPA = -Wl,--version-script=$(DPF_PATH)/utils/symbols/ladspa.version | |||
| SYMBOLS_DSSI = -Wl,--version-script=$(DPF_PATH)/utils/symbols/dssi.version | |||
| SYMBOLS_LV2DSP = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2-dsp.version | |||
| SYMBOLS_LV2UI = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2-ui.version | |||
| SYMBOLS_LV2 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2.version | |||
| SYMBOLS_VST2 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/vst2.version | |||
| SYMBOLS_VST3 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/vst3.version | |||
| endif | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| @@ -337,12 +354,12 @@ $(lv2): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o | |||
| endif | |||
| -@mkdir -p $(shell dirname $@) | |||
| @echo "Creating LV2 plugin for $(NAME)" | |||
| $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_LV2) $(SYMBOLS_LV2UI) -o $@ | |||
| $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_LV2) -o $@ | |||
| $(lv2_dsp): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.o | |||
| -@mkdir -p $(shell dirname $@) | |||
| @echo "Creating LV2 plugin library for $(NAME)" | |||
| $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) $(SYMBOLS_LV2) -o $@ | |||
| $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(SHARED) $(SYMBOLS_LV2DSP) -o $@ | |||
| $(lv2_ui): $(OBJS_UI) $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.o $(DGL_LIB) | |||
| -@mkdir -p $(shell dirname $@) | |||
| @@ -206,6 +206,7 @@ function(dpf__build_ladspa NAME) | |||
| dpf__add_module("${NAME}-ladspa" ${_no_srcs}) | |||
| dpf__add_plugin_main("${NAME}-ladspa" "ladspa") | |||
| dpf__set_module_export_list("${NAME}-ladspa" "ladspa") | |||
| target_link_libraries("${NAME}-ladspa" PRIVATE "${NAME}-dsp") | |||
| set_target_properties("${NAME}-ladspa" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" | |||
| @@ -234,6 +235,7 @@ function(dpf__build_dssi NAME DGL_LIBRARY) | |||
| dpf__add_module("${NAME}-dssi" ${_no_srcs}) | |||
| dpf__add_plugin_main("${NAME}-dssi" "dssi") | |||
| dpf__set_module_export_list("${NAME}-dssi" "dssi") | |||
| target_link_libraries("${NAME}-dssi" PRIVATE "${NAME}-dsp") | |||
| set_target_properties("${NAME}-dssi" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" | |||
| @@ -264,6 +266,11 @@ function(dpf__build_lv2 NAME DGL_LIBRARY MONOLITHIC) | |||
| dpf__add_module("${NAME}-lv2" ${_no_srcs}) | |||
| dpf__add_plugin_main("${NAME}-lv2" "lv2") | |||
| if(DGL_LIBRARY AND MONOLITHIC) | |||
| dpf__set_module_export_list("${NAME}-lv2" "lv2") | |||
| else() | |||
| dpf__set_module_export_list("${NAME}-lv2" "lv2-dsp") | |||
| endif() | |||
| target_link_libraries("${NAME}-lv2" PRIVATE "${NAME}-dsp") | |||
| set_target_properties("${NAME}-lv2" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2/$<0:>" | |||
| @@ -280,6 +287,7 @@ function(dpf__build_lv2 NAME DGL_LIBRARY MONOLITHIC) | |||
| else() | |||
| dpf__add_module("${NAME}-lv2-ui" ${_no_srcs}) | |||
| dpf__add_ui_main("${NAME}-lv2-ui" "lv2" "${DGL_LIBRARY}") | |||
| dpf__set_module_export_list("${NAME}-lv2-ui" "lv2-ui") | |||
| target_link_libraries("${NAME}-lv2-ui" PRIVATE "${NAME}-ui") | |||
| set_target_properties("${NAME}-lv2-ui" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2/$<0:>" | |||
| @@ -311,6 +319,7 @@ function(dpf__build_vst2 NAME DGL_LIBRARY) | |||
| dpf__add_module("${NAME}-vst2" ${_no_srcs}) | |||
| dpf__add_plugin_main("${NAME}-vst2" "vst2") | |||
| dpf__add_ui_main("${NAME}-vst2" "vst2" "${DGL_LIBRARY}") | |||
| dpf__set_module_export_list("${NAME}-vst2" "vst2") | |||
| target_link_libraries("${NAME}-vst2" PRIVATE "${NAME}-dsp" "${NAME}-ui") | |||
| set_target_properties("${NAME}-vst2" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/$<0:>" | |||
| @@ -566,6 +575,24 @@ function(dpf__add_static_library NAME) | |||
| dpf__set_target_defaults("${NAME}") | |||
| endfunction() | |||
| # dpf__set_module_export_list | |||
| # ------------------------------------------------------------------------------ | |||
| # | |||
| # Applies a list of exported symbols to the module target. | |||
| # | |||
| function(dpf__set_module_export_list NAME EXPORTS) | |||
| if(WIN32) | |||
| target_sources("${NAME}" PRIVATE "${DPF_ROOT_DIR}/utils/symbols/${EXPORTS}.def") | |||
| elseif(APPLE) | |||
| set_property(TARGET "${NAME}" APPEND PROPERTY LINK_OPTIONS | |||
| "-Xlinker" "-exported_symbols_list" | |||
| "-Xlinker" "${DPF_ROOT_DIR}/utils/symbols/${EXPORTS}.exp") | |||
| else() | |||
| set_property(TARGET "${NAME}" APPEND PROPERTY LINK_OPTIONS | |||
| "-Xlinker" "--version-script=${DPF_ROOT_DIR}/utils/symbols/${EXPORTS}.version") | |||
| endif() | |||
| endfunction() | |||
| # dpf__set_target_defaults | |||
| # ------------------------------------------------------------------------------ | |||
| # | |||
| @@ -582,12 +582,26 @@ public: | |||
| NanoImage::Handle createImageFromMemory(uchar* data, uint dataSize, int imageFlags); | |||
| /** | |||
| Creates image from specified image data. | |||
| Creates image from specified raw format image data. | |||
| */ | |||
| NanoImage::Handle createImageFromRawMemory(uint w, uint h, const uchar* data, | |||
| ImageFlags imageFlags, ImageFormat format); | |||
| /** | |||
| Creates image from specified raw format image data. | |||
| Overloaded function for convenience. | |||
| @see ImageFlags | |||
| */ | |||
| NanoImage::Handle createImageFromRawMemory(uint w, uint h, const uchar* data, | |||
| int imageFlags, ImageFormat format); | |||
| /** | |||
| Creates image from specified RGBA image data. | |||
| */ | |||
| NanoImage::Handle createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags); | |||
| /** | |||
| Creates image from specified image data. | |||
| Creates image from specified RGBA image data. | |||
| Overloaded function for convenience. | |||
| @see ImageFlags | |||
| */ | |||
| @@ -382,6 +382,13 @@ public: | |||
| */ | |||
| void repaint(const Rectangle<uint>& rect) noexcept; | |||
| /** | |||
| Render this window's content into a picture file, specified by @a filename. | |||
| Window must be visible and on screen. | |||
| Written picture format is PPM. | |||
| */ | |||
| void renderToPicture(const char* filename); | |||
| /** | |||
| Run this window as a modal, blocking input events from the parent. | |||
| Only valid for windows that have been created with another window as parent (as passed in the constructor). | |||
| @@ -808,6 +808,13 @@ void TopLevelWidget::PrivateData::display() | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::renderToPicture(const char*, const GraphicsContext&, uint, uint) | |||
| { | |||
| notImplemented("Window::PrivateData::renderToPicture"); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept | |||
| { | |||
| GraphicsContext& context((GraphicsContext&)graphicsContext); | |||
| @@ -215,6 +215,7 @@ NanoImage& NanoImage::operator=(const Handle& handle) | |||
| fHandle.context = handle.context; | |||
| fHandle.imageId = handle.imageId; | |||
| _updateSize(); | |||
| return *this; | |||
| } | |||
| @@ -631,6 +632,45 @@ NanoImage::Handle NanoVG::createImageFromMemory(uchar* data, uint dataSize, int | |||
| return NanoImage::Handle(fContext, nvgCreateImageMem(fContext, imageFlags, data,static_cast<int>(dataSize))); | |||
| } | |||
| NanoImage::Handle NanoVG::createImageFromRawMemory(uint w, uint h, const uchar* data, | |||
| ImageFlags imageFlags, ImageFormat format) | |||
| { | |||
| return createImageFromRawMemory(w, h, data, static_cast<int>(imageFlags), format); | |||
| } | |||
| NanoImage::Handle NanoVG::createImageFromRawMemory(uint w, uint h, const uchar* data, | |||
| int imageFlags, ImageFormat format) | |||
| { | |||
| if (fContext == nullptr) return NanoImage::Handle(); | |||
| DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle()); | |||
| NVGtexture nvgformat; | |||
| switch (format) | |||
| { | |||
| case kImageFormatGrayscale: | |||
| nvgformat = NVG_TEXTURE_ALPHA; | |||
| break; | |||
| case kImageFormatBGR: | |||
| nvgformat = NVG_TEXTURE_BGR; | |||
| break; | |||
| case kImageFormatBGRA: | |||
| nvgformat = NVG_TEXTURE_BGRA; | |||
| break; | |||
| case kImageFormatRGB: | |||
| nvgformat = NVG_TEXTURE_RGB; | |||
| break; | |||
| case kImageFormatRGBA: | |||
| nvgformat = NVG_TEXTURE_RGBA; | |||
| break; | |||
| default: | |||
| return NanoImage::Handle(); | |||
| } | |||
| return NanoImage::Handle(fContext, nvgCreateImageRaw(fContext, | |||
| static_cast<int>(w), | |||
| static_cast<int>(h), imageFlags, nvgformat, data)); | |||
| } | |||
| NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags) | |||
| { | |||
| return createImageFromRGBA(w, h, data, static_cast<int>(imageFlags)); | |||
| @@ -646,12 +686,14 @@ NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, | |||
| static_cast<int>(h), imageFlags, data)); | |||
| } | |||
| NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, ImageFlags imageFlags, bool deleteTexture) | |||
| NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, | |||
| ImageFlags imageFlags, bool deleteTexture) | |||
| { | |||
| return createImageFromTextureHandle(textureId, w, h, static_cast<int>(imageFlags), deleteTexture); | |||
| } | |||
| NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, int imageFlags, bool deleteTexture) | |||
| NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, | |||
| int imageFlags, bool deleteTexture) | |||
| { | |||
| if (fContext == nullptr) return NanoImage::Handle(); | |||
| DISTRHO_SAFE_ASSERT_RETURN(textureId != 0, NanoImage::Handle()); | |||
| @@ -667,6 +667,36 @@ void TopLevelWidget::PrivateData::display() | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::renderToPicture(const char* const filename, | |||
| const GraphicsContext&, | |||
| const uint width, | |||
| const uint height) | |||
| { | |||
| FILE* const f = fopen(filename, "w"); | |||
| DISTRHO_SAFE_ASSERT_RETURN(f != nullptr,); | |||
| GLubyte* const pixels = new GLubyte[width * height * 3 * sizeof(GLubyte)]; | |||
| glFlush(); | |||
| glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); | |||
| fprintf(f, "P3\n%d %d\n255\n", width, height); | |||
| for (uint y = 0; y < height; y++) | |||
| { | |||
| for (uint i, x = 0; x < width; x++) | |||
| { | |||
| i = 3 * ((height - y - 1) * width + x); | |||
| fprintf(f, "%3d %3d %3d ", pixels[i], pixels[i+1], pixels[i+2]); | |||
| } | |||
| fprintf(f, "\n"); | |||
| } | |||
| delete[] pixels; | |||
| fclose(f); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept | |||
| { | |||
| return (const GraphicsContext&)graphicsContext; | |||
| @@ -231,6 +231,13 @@ void TopLevelWidget::PrivateData::display() | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::renderToPicture(const char*, const GraphicsContext&, uint, uint) | |||
| { | |||
| notImplemented("Window::PrivateData::renderToPicture"); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept | |||
| { | |||
| return (const GraphicsContext&)graphicsContext; | |||
| @@ -336,6 +336,11 @@ void Window::repaint(const Rectangle<uint>& rect) noexcept | |||
| puglPostRedisplayRect(pData->view, prect); | |||
| } | |||
| void Window::renderToPicture(const char* const filename) | |||
| { | |||
| pData->filenameToRenderInto = strdup(filename); | |||
| } | |||
| void Window::runAsModal(bool blockWait) | |||
| { | |||
| pData->runAsModal(blockWait); | |||
| @@ -95,6 +95,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s) | |||
| minHeight(0), | |||
| keepAspectRatio(false), | |||
| ignoreIdleCallbacks(false), | |||
| filenameToRenderInto(nullptr), | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| win32SelectedFile(nullptr), | |||
| #endif | |||
| @@ -120,6 +121,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c | |||
| minHeight(0), | |||
| keepAspectRatio(false), | |||
| ignoreIdleCallbacks(false), | |||
| filenameToRenderInto(nullptr), | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| win32SelectedFile(nullptr), | |||
| #endif | |||
| @@ -149,6 +151,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| minHeight(0), | |||
| keepAspectRatio(false), | |||
| ignoreIdleCallbacks(false), | |||
| filenameToRenderInto(nullptr), | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| win32SelectedFile(nullptr), | |||
| #endif | |||
| @@ -180,6 +183,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
| minHeight(0), | |||
| keepAspectRatio(false), | |||
| ignoreIdleCallbacks(false), | |||
| filenameToRenderInto(nullptr), | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| win32SelectedFile(nullptr), | |||
| #endif | |||
| @@ -195,6 +199,7 @@ Window::PrivateData::~PrivateData() | |||
| { | |||
| appData->idleCallbacks.remove(this); | |||
| appData->windows.remove(self); | |||
| std::free(filenameToRenderInto); | |||
| if (view == nullptr) | |||
| return; | |||
| @@ -743,6 +748,14 @@ void Window::PrivateData::onPuglExpose() | |||
| if (widget->isVisible()) | |||
| widget->pData->display(); | |||
| } | |||
| if (char* const filename = filenameToRenderInto) | |||
| { | |||
| const PuglRect rect = puglGetFrame(view); | |||
| filenameToRenderInto = nullptr; | |||
| renderToPicture(filename, getGraphicsContext(), static_cast<uint>(rect.width), static_cast<uint>(rect.height)); | |||
| std::free(filename); | |||
| } | |||
| #endif | |||
| } | |||
| @@ -77,6 +77,9 @@ struct Window::PrivateData : IdleCallback { | |||
| /** Whether to ignore idle callback requests, useful for temporary windows. */ | |||
| bool ignoreIdleCallbacks; | |||
| /** Render to a picture file when non-null, automatically free+unset after saving. */ | |||
| char* filenameToRenderInto; | |||
| #ifdef DISTRHO_OS_WINDOWS | |||
| /** Selected file for openFileBrowser on windows, stored for fake async operation. */ | |||
| const char* win32SelectedFile; | |||
| @@ -162,6 +165,8 @@ struct Window::PrivateData : IdleCallback { | |||
| # endif | |||
| #endif | |||
| static void renderToPicture(const char* filename, const GraphicsContext& context, uint width, uint height); | |||
| // modal handling | |||
| void startModal(); | |||
| void stopModal(); | |||
| @@ -817,9 +817,14 @@ int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int | |||
| return image; | |||
| } | |||
| int nvgCreateImageRaw(NVGcontext* ctx, int w, int h, int imageFlags, NVGtexture format, const unsigned char* data) | |||
| { | |||
| return ctx->params.renderCreateTexture(ctx->params.userPtr, format, w, h, imageFlags, data); | |||
| } | |||
| int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data) | |||
| { | |||
| return ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_RGBA, w, h, imageFlags, data); | |||
| return nvgCreateImageRaw(ctx, w, h, imageFlags, NVG_TEXTURE_RGBA, data); | |||
| } | |||
| void nvgUpdateImage(NVGcontext* ctx, int image, const unsigned char* data) | |||
| @@ -144,6 +144,14 @@ enum NVGimageFlags { | |||
| NVG_IMAGE_NEAREST = 1<<5, // Image interpolation is Nearest instead Linear | |||
| }; | |||
| enum NVGtexture { | |||
| NVG_TEXTURE_ALPHA, | |||
| NVG_TEXTURE_BGR, | |||
| NVG_TEXTURE_BGRA, | |||
| NVG_TEXTURE_RGB, | |||
| NVG_TEXTURE_RGBA, | |||
| }; | |||
| // Begin drawing a new frame | |||
| // Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame() | |||
| // nvgBeginFrame() defines the size of the window to render to in relation currently | |||
| @@ -375,6 +383,10 @@ int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags); | |||
| // Returns handle to the image. | |||
| int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int ndata); | |||
| // Creates image from specified image data and texture format. | |||
| // Returns handle to the image. | |||
| int nvgCreateImageRaw(NVGcontext* ctx, int w, int h, int imageFlags, NVGtexture format, const unsigned char* data); | |||
| // Creates image from specified image data. | |||
| // Returns handle to the image. | |||
| int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data); | |||
| @@ -627,11 +639,6 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa | |||
| // | |||
| // Internal Render API | |||
| // | |||
| enum NVGtexture { | |||
| NVG_TEXTURE_ALPHA = 0x01, | |||
| NVG_TEXTURE_RGBA = 0x02, | |||
| }; | |||
| struct NVGscissor { | |||
| float xform[6]; | |||
| float extent[2]; | |||
| @@ -761,9 +761,21 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im | |||
| } | |||
| #endif | |||
| if (type == NVG_TEXTURE_RGBA) | |||
| switch (type) | |||
| { | |||
| case NVG_TEXTURE_BGR: | |||
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, data); | |||
| break; | |||
| case NVG_TEXTURE_BGRA: | |||
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, data); | |||
| break; | |||
| case NVG_TEXTURE_RGB: | |||
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data); | |||
| break; | |||
| case NVG_TEXTURE_RGBA: | |||
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); | |||
| else | |||
| break; | |||
| default: | |||
| #if defined(NANOVG_GLES2) || defined (NANOVG_GL2) | |||
| glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | |||
| #elif defined(NANOVG_GLES3) | |||
| @@ -771,6 +783,8 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im | |||
| #else | |||
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data); | |||
| #endif | |||
| break; | |||
| } | |||
| if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { | |||
| if (imageFlags & NVG_IMAGE_NEAREST) { | |||
| @@ -845,22 +859,50 @@ static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w | |||
| glPixelStorei(GL_UNPACK_SKIP_ROWS, y); | |||
| #else | |||
| // No support for all of skip, need to update a whole row at a time. | |||
| if (tex->type == NVG_TEXTURE_RGBA) | |||
| switch (tex->type) | |||
| { | |||
| case NVG_TEXTURE_BGR: | |||
| data += y*tex->width*3; | |||
| break; | |||
| case NVG_TEXTURE_BGRA: | |||
| data += y*tex->width*4; | |||
| else | |||
| break; | |||
| case NVG_TEXTURE_RGB: | |||
| data += y*tex->width*3; | |||
| break; | |||
| case NVG_TEXTURE_RGBA: | |||
| data += y*tex->width*4; | |||
| break; | |||
| default: | |||
| data += y*tex->width; | |||
| break; | |||
| } | |||
| x = 0; | |||
| w = tex->width; | |||
| #endif | |||
| if (tex->type == NVG_TEXTURE_RGBA) | |||
| switch (tex->type) | |||
| { | |||
| case NVG_TEXTURE_BGR: | |||
| glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_BGR, GL_UNSIGNED_BYTE, data); | |||
| break; | |||
| case NVG_TEXTURE_BGRA: | |||
| glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_BGRA, GL_UNSIGNED_BYTE, data); | |||
| break; | |||
| case NVG_TEXTURE_RGB: | |||
| glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGB, GL_UNSIGNED_BYTE, data); | |||
| break; | |||
| case NVG_TEXTURE_RGBA: | |||
| glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data); | |||
| else | |||
| break; | |||
| default: | |||
| #if defined(NANOVG_GLES2) || defined(NANOVG_GL2) | |||
| glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | |||
| #else | |||
| glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data); | |||
| #endif | |||
| break; | |||
| } | |||
| glPixelStorei(GL_UNPACK_ALIGNMENT, 4); | |||
| #ifndef NANOVG_GLES2 | |||
| @@ -956,15 +998,31 @@ static int glnvg__convertPaint(GLNVGcontext* gl, GLNVGfragUniforms* frag, NVGpai | |||
| frag->type = NSVG_SHADER_FILLIMG; | |||
| #if NANOVG_GL_USE_UNIFORMBUFFER | |||
| if (tex->type == NVG_TEXTURE_RGBA) | |||
| switch (tex->type) | |||
| { | |||
| case NVG_TEXTURE_BGR: | |||
| case NVG_TEXTURE_BGRA: | |||
| case NVG_TEXTURE_RGB: | |||
| case NVG_TEXTURE_RGBA: | |||
| frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1; | |||
| else | |||
| break; | |||
| default: | |||
| frag->texType = 2; | |||
| break; | |||
| } | |||
| #else | |||
| if (tex->type == NVG_TEXTURE_RGBA) | |||
| switch (tex->type) | |||
| { | |||
| case NVG_TEXTURE_BGR: | |||
| case NVG_TEXTURE_BGRA: | |||
| case NVG_TEXTURE_RGB: | |||
| case NVG_TEXTURE_RGBA: | |||
| frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0.0f : 1.0f; | |||
| else | |||
| break; | |||
| default: | |||
| frag->texType = 2.0f; | |||
| break; | |||
| } | |||
| #endif | |||
| // printf("frag->texType = %d\n", frag->texType); | |||
| } else { | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2021 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 | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2021 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 | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2021 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 | |||
| @@ -44,11 +44,11 @@ START_NAMESPACE_DISTRHO | |||
| Some important notes when using this class: | |||
| 1. MidiEvent::frame retains its original value, but it is useless, do not use it. | |||
| 2. The class variables names are be the same as the default ones in the run function. | |||
| 2. The class variable names are the same as the default ones in the run function. | |||
| Keep that in mind and try to avoid typos. :) | |||
| */ | |||
| class AudioMidiSyncHelper { | |||
| public: | |||
| struct AudioMidiSyncHelper | |||
| { | |||
| /** Parameters from the run function, adjusted for event sync */ | |||
| float* outputs[DISTRHO_PLUGIN_NUM_OUTPUTS]; | |||
| uint32_t frames; | |||
| @@ -618,6 +618,36 @@ public: | |||
| return *this; | |||
| } | |||
| /* | |||
| * Create a new string where all non-basic characters are converted to '_'. | |||
| * @see toBasic() | |||
| */ | |||
| String asBasic() const noexcept | |||
| { | |||
| String s(*this); | |||
| return s.toBasic(); | |||
| } | |||
| /* | |||
| * Create a new string where all ascii characters are converted lowercase. | |||
| * @see toLower() | |||
| */ | |||
| String asLower() const noexcept | |||
| { | |||
| String s(*this); | |||
| return s.toLower(); | |||
| } | |||
| /* | |||
| * Create a new string where all ascii characters are converted to uppercase. | |||
| * @see toUpper() | |||
| */ | |||
| String asUpper() const noexcept | |||
| { | |||
| String s(*this); | |||
| return s.toUpper(); | |||
| } | |||
| /* | |||
| * Direct access to the string buffer (read-only). | |||
| */ | |||
| @@ -146,12 +146,11 @@ | |||
| // ----------------------------------------------------------------------- | |||
| // Enable full state if plugin exports presets | |||
| // FIXME | |||
| // #if DISTRHO_PLUGIN_WANT_PROGRAMS && DISTRHO_PLUGIN_WANT_STATE && ! DISTRHO_PLUGIN_WANT_FULL_STATE | |||
| // # warning Plugins with programs and state need to implement full state API | |||
| // # undef DISTRHO_PLUGIN_WANT_FULL_STATE | |||
| // # define DISTRHO_PLUGIN_WANT_FULL_STATE 1 | |||
| // #endif | |||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS && DISTRHO_PLUGIN_WANT_STATE && ! DISTRHO_PLUGIN_WANT_FULL_STATE | |||
| # warning Plugins with programs and state need to implement full state API too | |||
| # undef DISTRHO_PLUGIN_WANT_FULL_STATE | |||
| # define DISTRHO_PLUGIN_WANT_FULL_STATE 1 | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| // Disable UI if DGL or External UI is not available | |||
| @@ -332,6 +332,7 @@ void lv2_generate_ttl(const char* const basename) | |||
| pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n"; | |||
| pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n"; | |||
| pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; | |||
| pluginString += "@prefix midi: <" LV2_MIDI_PREFIX "> .\n"; | |||
| pluginString += "@prefix mod: <http://moddevices.com/ns/mod#> .\n"; | |||
| pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n"; | |||
| pluginString += "@prefix pg: <" LV2_PORT_GROUPS_PREFIX "> .\n"; | |||
| @@ -341,6 +342,7 @@ void lv2_generate_ttl(const char* const basename) | |||
| #if DISTRHO_LV2_USE_EVENTS_IN || DISTRHO_LV2_USE_EVENTS_OUT | |||
| pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n"; | |||
| #endif | |||
| pluginString += "@prefix spdx: <http://spdx.org/rdf/terms#> .\n"; | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n"; | |||
| #endif | |||
| @@ -368,11 +370,11 @@ void lv2_generate_ttl(const char* const basename) | |||
| // plugin | |||
| pluginString += "<" DISTRHO_PLUGIN_URI ">\n"; | |||
| #ifdef DISTRHO_PLUGIN_LV2_CATEGORY | |||
| pluginString += " a " DISTRHO_PLUGIN_LV2_CATEGORY ", lv2:Plugin ;\n"; | |||
| pluginString += " a " DISTRHO_PLUGIN_LV2_CATEGORY ", lv2:Plugin, doap:Project ;\n"; | |||
| #elif DISTRHO_PLUGIN_IS_SYNTH | |||
| pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n"; | |||
| pluginString += " a lv2:InstrumentPlugin, lv2:Plugin, doap:Project ;\n"; | |||
| #else | |||
| pluginString += " a lv2:Plugin ;\n"; | |||
| pluginString += " a lv2:Plugin, doap:Project ;\n"; | |||
| #endif | |||
| pluginString += "\n"; | |||
| @@ -594,10 +596,13 @@ void lv2_generate_ttl(const char* const basename) | |||
| pluginString += " rsz:minimumSize " + 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"; | |||
| pluginString += " atom:supports atom:String ;\n"; | |||
| # endif | |||
| # if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n"; | |||
| pluginString += " atom:supports midi:MidiEvent ;\n"; | |||
| # endif | |||
| # if DISTRHO_PLUGIN_WANT_STATEFILES | |||
| pluginString += " atom:supports <" LV2_PATCH__Message "> ;\n"; | |||
| # endif | |||
| # if DISTRHO_PLUGIN_WANT_TIMEPOS | |||
| pluginString += " atom:supports <" LV2_TIME__Position "> ;\n"; | |||
| @@ -615,10 +620,13 @@ void lv2_generate_ttl(const char* const basename) | |||
| pluginString += " rsz:minimumSize " + 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"; | |||
| pluginString += " atom:supports atom:String ;\n"; | |||
| # endif | |||
| # if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n"; | |||
| pluginString += " atom:supports midi:MidiEvent ;\n"; | |||
| # endif | |||
| # if DISTRHO_PLUGIN_WANT_STATEFILES | |||
| pluginString += " atom:supports <" LV2_PATCH__Message "> ;\n"; | |||
| # endif | |||
| pluginString += " ] ;\n\n"; | |||
| ++portIndex; | |||
| @@ -746,12 +754,22 @@ void lv2_generate_ttl(const char* const basename) | |||
| } | |||
| if (j+1 == enumValues.count) | |||
| pluginString += " ] ;\n\n"; | |||
| pluginString += " ] ;\n"; | |||
| else | |||
| pluginString += " ] ,\n"; | |||
| } | |||
| } | |||
| // MIDI CC binding | |||
| if (const uint8_t midiCC = plugin.getParameterMidiCC(i)) | |||
| { | |||
| char midiCCBuf[7]; | |||
| snprintf(midiCCBuf, sizeof(midiCCBuf), "B0%02x00", midiCC); | |||
| pluginString += " midi:binding \""; | |||
| pluginString += midiCCBuf; | |||
| pluginString += "\"^^midi:MidiEvent ;\n"; | |||
| } | |||
| // unit | |||
| const String& unit(plugin.getParameterUnit(i)); | |||
| @@ -814,7 +832,7 @@ void lv2_generate_ttl(const char* const basename) | |||
| } | |||
| // hints | |||
| const uint32_t hints(plugin.getParameterHints(i)); | |||
| const uint32_t hints = plugin.getParameterHints(i); | |||
| if (hints & kParameterIsBoolean) | |||
| { | |||
| @@ -832,8 +850,6 @@ void lv2_generate_ttl(const char* const basename) | |||
| pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n"; | |||
| } | |||
| // TODO midiCC | |||
| // group | |||
| const uint32_t groupId = plugin.getParameterGroupId(i); | |||
| @@ -895,13 +911,154 @@ void lv2_generate_ttl(const char* const basename) | |||
| { | |||
| const String license(plugin.getLicense()); | |||
| // TODO always convert to URL, do best-guess based on known licenses | |||
| // Using URL as license | |||
| if (license.contains("://")) | |||
| { | |||
| pluginString += " doap:license <" + license + "> ;\n\n"; | |||
| } | |||
| // String contaning quotes, use as-is | |||
| else if (license.contains('"')) | |||
| { | |||
| pluginString += " doap:license \"\"\"" + license + "\"\"\" ;\n\n"; | |||
| } | |||
| // Regular license string, convert to URL as much as we can | |||
| else | |||
| pluginString += " doap:license \"" + license + "\" ;\n\n"; | |||
| { | |||
| const String uplicense(license.asUpper()); | |||
| // for reference, see https://spdx.org/licenses/ | |||
| // common licenses | |||
| /**/ if (uplicense == "AGPL-1.0-ONLY" || | |||
| uplicense == "AGPL1" || | |||
| uplicense == "AGPLV1") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/AGPL-1.0-only.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "AGPL-1.0-OR-LATER" || | |||
| uplicense == "AGPL1+" || | |||
| uplicense == "AGPLV1+") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/AGPL-1.0-or-later.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "AGPL-3.0-ONLY" || | |||
| uplicense == "AGPL3" || | |||
| uplicense == "AGPLV3") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/AGPL-3.0-only.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "AGPL-3.0-OR-LATER" || | |||
| uplicense == "AGPL3+" || | |||
| uplicense == "AGPLV3+") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/AGPL-3.0-or-later.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "APACHE-2.0" || | |||
| uplicense == "APACHE2" || | |||
| uplicense == "APACHE-2") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/Apache-2.0.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "BSD-2-CLAUSE" || | |||
| uplicense == "BSD2" || | |||
| uplicense == "BSD-2") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/BSD-2-Clause.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "BSD-3-CLAUSE" || | |||
| uplicense == "BSD3" || | |||
| uplicense == "BSD-3") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/BSD-3-Clause.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "GPL-2.0-ONLY" || | |||
| uplicense == "GPL2" || | |||
| uplicense == "GPLV2") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/GPL-2.0-only.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "GPL-2.0-OR-LATER" || | |||
| uplicense == "GPL2+" || | |||
| uplicense == "GPLV2+" || | |||
| uplicense == "GPL V2+") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/GPL-2.0-or-later.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "GPL-3.0-ONLY" || | |||
| uplicense == "GPL3" || | |||
| uplicense == "GPLV3") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/GPL-3.0-only.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "GPL-3.0-OR-LATER" || | |||
| uplicense == "GPL3+" || | |||
| uplicense == "GPLV3+" || | |||
| uplicense == "GPL V3+") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/GPL-3.0-or-later.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "ISC") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/ISC.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "LGPL-2.0-ONLY" || | |||
| uplicense == "LGPL2" || | |||
| uplicense == "LGPLV2") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/LGPL-2.0-only.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "LGPL-2.0-OR-LATER" || | |||
| uplicense == "LGPL2+" || | |||
| uplicense == "LGPLV2+") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/LGPL-2.0-or-later.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "LGPL-2.1-ONLY" || | |||
| uplicense == "LGPL2.1" || | |||
| uplicense == "LGPLV2.1") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/LGPL-2.1-only.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "LGPL-2.1-OR-LATER" || | |||
| uplicense == "LGPL2.1+" || | |||
| uplicense == "LGPLV2.1+") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/LGPL-2.1-or-later.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "LGPL-3.0-ONLY" || | |||
| uplicense == "LGPL3" || | |||
| uplicense == "LGPLV3") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/LGPL-2.0-only.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "LGPL-3.0-OR-LATER" || | |||
| uplicense == "LGPL3+" || | |||
| uplicense == "LGPLV3+") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/LGPL-3.0-or-later.html> ;\n\n"; | |||
| } | |||
| else if (uplicense == "MIT") | |||
| { | |||
| pluginString += " doap:license <http://spdx.org/licenses/MIT.html> ;\n\n"; | |||
| } | |||
| // generic fallbacks | |||
| else if (uplicense.startsWith("GPL")) | |||
| { | |||
| pluginString += " doap:license <https://opensource.org/licenses/gpl-license> ;\n\n"; | |||
| } | |||
| else if (uplicense.startsWith("LGPL")) | |||
| { | |||
| pluginString += " doap:license <https://opensource.org/licenses/lgpl-license> ;\n\n"; | |||
| } | |||
| // unknown or not handled yet, log a warning | |||
| else | |||
| { | |||
| d_stderr("Unknown license string '%s'", license.buffer()); | |||
| pluginString += " doap:license \"" + license + "\" ;\n\n"; | |||
| } | |||
| } | |||
| } | |||
| // developer | |||
| @@ -1037,7 +1194,10 @@ void lv2_generate_ttl(const char* const basename) | |||
| presetsString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n"; | |||
| presetsString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n"; | |||
| # if DISTRHO_PLUGIN_WANT_STATE | |||
| presetsString += "@prefix owl: <http://www.w3.org/2002/07/owl#> .\n"; | |||
| presetsString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n"; | |||
| presetsString += "@prefix state: <" LV2_STATE_PREFIX "> .\n"; | |||
| presetsString += "@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n"; | |||
| # endif | |||
| presetsString += "\n"; | |||
| @@ -1045,8 +1205,13 @@ void lv2_generate_ttl(const char* const basename) | |||
| const uint32_t numPrograms = plugin.getProgramCount(); | |||
| # if DISTRHO_PLUGIN_WANT_FULL_STATE | |||
| const uint32_t numStates = plugin.getStateCount(); | |||
| const bool valid = numParameters != 0 || numStates != 0; | |||
| # else | |||
| const bool valid = numParameters != 0; | |||
| # endif | |||
| DISTRHO_CUSTOM_SAFE_ASSERT_RETURN("Programs require parameters or full state", valid, presetsFile.close()); | |||
| const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#"); | |||
| char strBuf[0xff+1]; | |||
| @@ -1054,6 +1219,22 @@ void lv2_generate_ttl(const char* const basename) | |||
| String presetString; | |||
| # if DISTRHO_PLUGIN_WANT_FULL_STATE | |||
| for (uint32_t i=0; i<numStates; ++i) | |||
| { | |||
| # if DISTRHO_PLUGIN_WANT_STATEFILES | |||
| if (plugin.isStateFile(i)) | |||
| continue; | |||
| # endif | |||
| presetString = "<" DISTRHO_PLUGIN_LV2_STATE_PREFIX + plugin.getStateKey(i) + ">\n"; | |||
| presetString += " a owl:DatatypeProperty ;\n"; | |||
| presetString += " rdfs:label \"Plugin state key-value string pair\" ;\n"; | |||
| presetString += " rdfs:domain state:State ;\n"; | |||
| presetString += " rdfs:range xsd:string .\n\n"; | |||
| presetsString += presetString; | |||
| } | |||
| # endif | |||
| for (uint32_t i=0; i<numPrograms; ++i) | |||
| { | |||
| std::snprintf(strBuf, 0xff, "%03i", i+1); | |||
| @@ -1062,17 +1243,6 @@ void lv2_generate_ttl(const char* const basename) | |||
| presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n"; | |||
| # if DISTRHO_PLUGIN_WANT_FULL_STATE | |||
| if (numParameters == 0 && numStates == 0) | |||
| #else | |||
| if (numParameters == 0) | |||
| #endif | |||
| { | |||
| presetString += " ."; | |||
| presetsString += presetString; | |||
| continue; | |||
| } | |||
| # if DISTRHO_PLUGIN_WANT_FULL_STATE | |||
| presetString += " state:state [\n"; | |||
| for (uint32_t j=0; j<numStates; ++j) | |||
| @@ -44,6 +44,7 @@ | |||
| #include <clocale> | |||
| #include <map> | |||
| #include <string> | |||
| #include <vector> | |||
| #if VESTIGE_HEADER | |||
| # include "vestige/vestige.h" | |||
| @@ -1635,6 +1636,20 @@ static void vst_processReplacingCallback(AEffect* effect, float** inputs, float* | |||
| #undef validPlugin | |||
| #undef vstObjectPtr | |||
| static struct Cleanup { | |||
| std::vector<AEffect*> effects; | |||
| ~Cleanup() | |||
| { | |||
| for (std::vector<AEffect*>::iterator it = effects.begin(), end = effects.end(); it != end; ++it) | |||
| { | |||
| AEffect* const effect = *it; | |||
| delete (VstObject*)effect->object; | |||
| delete effect; | |||
| } | |||
| } | |||
| } sCleanup; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -1714,12 +1729,13 @@ const AEffect* VSTPluginMain(audioMasterCallback audioMaster) | |||
| effect->processReplacing = vst_processReplacingCallback; | |||
| // pointers | |||
| VstObject* const obj(new VstObject()); | |||
| VstObject* const obj = new VstObject(); | |||
| obj->audioMaster = audioMaster; | |||
| obj->plugin = nullptr; | |||
| // done | |||
| effect->object = obj; | |||
| sCleanup.effects.push_back(effect); | |||
| return effect; | |||
| } | |||
| @@ -31,6 +31,7 @@ endif | |||
| ifeq ($(HAVE_OPENGL),true) | |||
| MANUAL_TESTS += Demo.opengl | |||
| MANUAL_TESTS += FileBrowserDialog | |||
| MANUAL_TESTS += NanoImage | |||
| MANUAL_TESTS += NanoSubWidgets | |||
| UNIT_TESTS += Window.opengl | |||
| endif | |||
| @@ -140,11 +141,15 @@ clean: | |||
| $(SILENT)$(CXX) $^ $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(VULKAN_LIBS) -o $@ | |||
| ../build/tests/FileBrowserDialog$(APP_EXT): ../build/tests/FileBrowserDialog.cpp.o ../build/libdgl-opengl.a | |||
| @echo "Linking Demo (OpenGL)" | |||
| @echo "Linking FileBrowserDialog (OpenGL)" | |||
| $(SILENT)$(CXX) $^ $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@ | |||
| ../build/tests/NanoImage$(APP_EXT): ../build/tests/NanoImage.cpp.o ../build/libdgl-opengl.a | |||
| @echo "Linking NanoImage (OpenGL)" | |||
| $(SILENT)$(CXX) $^ $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@ | |||
| ../build/tests/NanoSubWidgets$(APP_EXT): ../build/tests/NanoSubWidgets.cpp.o ../build/libdgl-opengl.a | |||
| @echo "Linking Demo (OpenGL)" | |||
| @echo "Linking NanoSubWidgets (OpenGL)" | |||
| $(SILENT)$(CXX) $^ $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@ | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| @@ -0,0 +1,229 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2021 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 "tests.hpp" | |||
| #include "dgl/NanoVG.hpp" | |||
| START_NAMESPACE_DGL | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| // Images | |||
| #include "images_res/CatPics.cpp" | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| class NanoImageExample : public NanoStandaloneWindow, | |||
| public IdleCallback | |||
| { | |||
| static const int kImg1y = 0; | |||
| static const int kImg2y = 500/2-CatPics::cat2Height/2; | |||
| static const int kImg3x = 400/3-CatPics::cat3Width/3; | |||
| static const int kImg1max = 500-CatPics::cat1Width; | |||
| static const int kImg2max = 500-CatPics::cat2Width; | |||
| static const int kImg3max = 400-CatPics::cat3Height; | |||
| static const int kImgFlags = IMAGE_GENERATE_MIPMAPS | IMAGE_REPEAT_X; | |||
| int imgTop1st, imgTop2nd, imgTop3rd; | |||
| int img1x, img2x, img3y; | |||
| bool img1rev, img2rev, img3rev; | |||
| NanoImage img1, img2, img3; | |||
| public: | |||
| NanoImageExample(Application& app) | |||
| : NanoStandaloneWindow(app), | |||
| imgTop1st(1), | |||
| imgTop2nd(2), | |||
| imgTop3rd(3), | |||
| img1x(0), | |||
| img2x(kImg2max), | |||
| img3y(kImg3max), | |||
| img1rev(false), | |||
| img2rev(true), | |||
| img3rev(true), | |||
| img1(createImageFromRawMemory(CatPics::cat1Width, CatPics::cat1Height, (uchar*)CatPics::cat1Data, kImgFlags, kImageFormatBGR)), | |||
| img2(createImageFromRawMemory(CatPics::cat2Width, CatPics::cat2Height, (uchar*)CatPics::cat2Data, kImgFlags, kImageFormatBGR)), | |||
| img3(createImageFromRawMemory(CatPics::cat3Width, CatPics::cat3Height, (uchar*)CatPics::cat3Data, kImgFlags, kImageFormatBGR)) | |||
| { | |||
| DISTRHO_SAFE_ASSERT(img1.isValid()); | |||
| DISTRHO_SAFE_ASSERT(img2.isValid()); | |||
| DISTRHO_SAFE_ASSERT(img3.isValid()); | |||
| DISTRHO_SAFE_ASSERT_UINT2(img1.getSize().getWidth() == CatPics::cat1Width, | |||
| img1.getSize().getWidth(), CatPics::cat1Width); | |||
| DISTRHO_SAFE_ASSERT_UINT2(img1.getSize().getHeight() == CatPics::cat1Height, | |||
| img1.getSize().getHeight(), CatPics::cat1Height); | |||
| DISTRHO_SAFE_ASSERT_UINT2(img2.getSize().getWidth() == CatPics::cat2Width, | |||
| img2.getSize().getWidth(), CatPics::cat2Width); | |||
| DISTRHO_SAFE_ASSERT_UINT2(img2.getSize().getHeight() == CatPics::cat2Height, | |||
| img2.getSize().getHeight(), CatPics::cat2Height); | |||
| DISTRHO_SAFE_ASSERT_UINT2(img3.getSize().getWidth() == CatPics::cat3Width, | |||
| img3.getSize().getWidth(), CatPics::cat3Width); | |||
| DISTRHO_SAFE_ASSERT_UINT2(img3.getSize().getHeight() == CatPics::cat3Height, | |||
| img3.getSize().getHeight(), CatPics::cat3Height); | |||
| setResizable(true); | |||
| setSize(500, 500); | |||
| // setGeometryConstraints(500, 500, false); | |||
| setTitle("NanoImage"); | |||
| done(); | |||
| addIdleCallback(this); | |||
| } | |||
| protected: | |||
| void onNanoDisplay() override | |||
| { | |||
| // bottom image | |||
| beginPath(); | |||
| fillPaint(setupImagePaint(imgTop3rd)); | |||
| fill(); | |||
| // middle image | |||
| beginPath(); | |||
| fillPaint(setupImagePaint(imgTop2nd)); | |||
| fill(); | |||
| // top image | |||
| beginPath(); | |||
| fillPaint(setupImagePaint(imgTop1st)); | |||
| fill(); | |||
| } | |||
| void idleCallback() noexcept override | |||
| { | |||
| if (img1rev) | |||
| { | |||
| img1x -= 2; | |||
| if (img1x <= -50) | |||
| { | |||
| img1rev = false; | |||
| setNewTopImg(1); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| img1x += 2; | |||
| if (img1x >= kImg1max+50) | |||
| { | |||
| img1rev = true; | |||
| setNewTopImg(1); | |||
| } | |||
| } | |||
| if (img2rev) | |||
| { | |||
| img2x -= 1; | |||
| if (img2x <= -50) | |||
| { | |||
| img2rev = false; | |||
| setNewTopImg(2); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| img2x += 4; | |||
| if (img2x >= kImg2max+50) | |||
| { | |||
| img2rev = true; | |||
| setNewTopImg(2); | |||
| } | |||
| } | |||
| if (img3rev) | |||
| { | |||
| img3y -= 3; | |||
| if (img3y <= -50) | |||
| { | |||
| img3rev = false; | |||
| setNewTopImg(3); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| img3y += 3; | |||
| if (img3y >= kImg3max+50) | |||
| { | |||
| img3rev = true; | |||
| setNewTopImg(3); | |||
| } | |||
| } | |||
| repaint(); | |||
| } | |||
| private: | |||
| Paint setupImagePaint(const int imgId) noexcept | |||
| { | |||
| switch (imgId) | |||
| { | |||
| case 1: | |||
| rect(img1x, kImg1y, CatPics::cat1Width, CatPics::cat1Height); | |||
| return imagePattern(img1x, kImg1y, CatPics::cat1Width, CatPics::cat1Height, 0, img1, 1.0f); | |||
| case 2: | |||
| rect(img2x, kImg2y, CatPics::cat2Width, CatPics::cat2Height); | |||
| return imagePattern(img2x, kImg2y, CatPics::cat2Width, CatPics::cat2Height, 0, img2, 1.0f); | |||
| case 3: | |||
| rect(kImg3x, img3y, CatPics::cat3Width, CatPics::cat3Height); | |||
| return imagePattern(kImg3x, img3y, CatPics::cat3Width, CatPics::cat3Height, 0, img3, 1.0f); | |||
| }; | |||
| return Paint(); | |||
| } | |||
| void setNewTopImg(const int imgId) noexcept | |||
| { | |||
| if (imgTop1st == imgId) | |||
| return; | |||
| if (imgTop2nd == imgId) | |||
| { | |||
| imgTop2nd = imgTop1st; | |||
| imgTop1st = imgId; | |||
| return; | |||
| } | |||
| imgTop3rd = imgTop2nd; | |||
| imgTop2nd = imgTop1st; | |||
| imgTop1st = imgId; | |||
| } | |||
| }; | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| int main() | |||
| { | |||
| USE_NAMESPACE_DGL; | |||
| Application app(true); | |||
| NanoImageExample win(app); | |||
| win.show(); | |||
| app.exec(); | |||
| return 0; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -9,19 +9,19 @@ ifeq ($(WINDOWS),true) | |||
| build: ../lv2_ttl_generator.exe | |||
| ../lv2_ttl_generator.exe: lv2_ttl_generator.c | |||
| $(CC) $< $(CFLAGS) -o $@ $(LDFLAGS) -static | |||
| $(CC) $< $(BUILD_C_FLAGS) -o $@ $(LINK_FLAGS) -static | |||
| touch ../lv2_ttl_generator | |||
| else # WINDOWS | |||
| ifneq ($(HAIKU),true) | |||
| LDFLAGS += -ldl | |||
| ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true) | |||
| LINK_FLAGS += -ldl | |||
| endif | |||
| build: ../lv2_ttl_generator | |||
| ../lv2_ttl_generator: lv2_ttl_generator.c | |||
| $(CC) $< $(CFLAGS) -o $@ $(LDFLAGS) | |||
| $(CC) $< $(BUILD_C_FLAGS) -o $@ $(LINK_FLAGS) | |||
| endif # WINDOWS | |||
| @@ -0,0 +1,3 @@ | |||
| EXPORTS | |||
| ladspa_descriptor | |||
| dssi_descriptor | |||
| @@ -0,0 +1,2 @@ | |||
| _ladspa_descriptor | |||
| _dssi_descriptor | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| global: ladspa_descriptor; dssi_descriptor; | |||
| local: *; | |||
| }; | |||
| @@ -0,0 +1,2 @@ | |||
| EXPORTS | |||
| ladspa_descriptor | |||
| @@ -0,0 +1 @@ | |||
| _ladspa_descriptor | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| global: ladspa_descriptor; | |||
| local: *; | |||
| }; | |||
| @@ -0,0 +1,3 @@ | |||
| EXPORTS | |||
| lv2_descriptor | |||
| lv2_generate_ttl | |||
| @@ -0,0 +1,2 @@ | |||
| _lv2_descriptor | |||
| _lv2_generate_ttl | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| global: lv2_descriptor; lv2_generate_ttl; | |||
| local: *; | |||
| }; | |||
| @@ -0,0 +1,2 @@ | |||
| EXPORTS | |||
| lv2ui_descriptor | |||
| @@ -0,0 +1 @@ | |||
| _lv2ui_descriptor | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| global: lv2ui_descriptor; | |||
| local: *; | |||
| }; | |||
| @@ -0,0 +1,4 @@ | |||
| EXPORTS | |||
| lv2_descriptor | |||
| lv2ui_descriptor | |||
| lv2_generate_ttl | |||
| @@ -0,0 +1,3 @@ | |||
| _lv2_descriptor | |||
| _lv2ui_descriptor | |||
| _lv2_generate_ttl | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| global: lv2_descriptor; lv2ui_descriptor; lv2_generate_ttl; | |||
| local: *; | |||
| }; | |||
| @@ -0,0 +1,3 @@ | |||
| EXPORTS | |||
| VSTPluginMain | |||
| main=VSTPluginMain | |||
| @@ -0,0 +1 @@ | |||
| _VSTPluginMain | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| global: VSTPluginMain; main; | |||
| local: *; | |||
| }; | |||
| @@ -0,0 +1,4 @@ | |||
| EXPORTS | |||
| GetPluginFactory | |||
| InitDll | |||
| ExitDll | |||
| @@ -0,0 +1,3 @@ | |||
| _GetPluginFactory | |||
| _bundleEntry | |||
| _bundleExit | |||
| @@ -0,0 +1,4 @@ | |||
| { | |||
| global: GetPluginFactory; ModuleEntry; ModuleExit; | |||
| local: *; | |||
| }; | |||
| @@ -0,0 +1,41 @@ | |||
| { | |||
| libdl is full of leaks | |||
| Memcheck:Leak | |||
| ... | |||
| fun:_dl_open | |||
| ... | |||
| } | |||
| { | |||
| libdl is full of leaks | |||
| Memcheck:Leak | |||
| ... | |||
| fun:_dl_close | |||
| ... | |||
| } | |||
| { | |||
| libdl is full of leaks | |||
| Memcheck:Leak | |||
| ... | |||
| fun:_dl_init | |||
| } | |||
| { | |||
| libdl is full of leaks | |||
| Memcheck:Leak | |||
| fun:calloc | |||
| fun:allocate_dtv | |||
| fun:_dl_allocate_tls | |||
| ... | |||
| } | |||
| { | |||
| libdl is full of leaks | |||
| Memcheck:Leak | |||
| ... | |||
| fun:call_init.part.0 | |||
| } | |||
| { | |||
| ignore XInitThreads | |||
| Memcheck:Leak | |||
| ... | |||
| fun:XInitThreads | |||
| ... | |||
| } | |||
| @@ -135,7 +135,6 @@ DistrhoPluginNekobi::DistrhoPluginNekobi() | |||
| fParams.decay = 75.0f; | |||
| fParams.accent = 25.0f; | |||
| fParams.volume = 75.0f; | |||
| fParams.bypass = false; | |||
| // Internal stuff | |||
| fSynth.waveform = 0.0f; | |||
| @@ -251,9 +250,6 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter) | |||
| parameter.ranges.max = 100.0f; | |||
| parameter.midiCC = 7; //Volume | |||
| break; | |||
| case paramBypass: | |||
| parameter.initDesignation(kParameterDesignationBypass); | |||
| break; | |||
| } | |||
| } | |||
| @@ -280,8 +276,6 @@ float DistrhoPluginNekobi::getParameterValue(uint32_t index) const | |||
| return fParams.accent; | |||
| case paramVolume: | |||
| return fParams.volume; | |||
| case paramBypass: | |||
| return fParams.bypass ? 1.0f : 0.0f; | |||
| } | |||
| return 0.0f; | |||
| @@ -331,14 +325,6 @@ void DistrhoPluginNekobi::setParameterValue(uint32_t index, float value) | |||
| fSynth.volume = value/100.0f; | |||
| DISTRHO_SAFE_ASSERT(fSynth.volume >= 0.0f && fSynth.volume <= 1.0f); | |||
| break; | |||
| case paramBypass: { | |||
| const bool bypass = (value > 0.5f); | |||
| if (fParams.bypass != bypass) | |||
| { | |||
| fParams.bypass = bypass; | |||
| nekobee_synth_all_voices_off(&fSynth); | |||
| } | |||
| } break; | |||
| } | |||
| } | |||
| @@ -374,10 +360,6 @@ void DistrhoPluginNekobi::run(const float**, float** outputs, uint32_t frames, c | |||
| return; | |||
| } | |||
| // ignore midi input if bypassed | |||
| if (fParams.bypass) | |||
| midiEventCount = 0; | |||
| while (framesDone < frames) | |||
| { | |||
| if (fSynth.nugget_remains == 0) | |||
| @@ -42,7 +42,6 @@ public: | |||
| paramDecay, | |||
| paramAccent, | |||
| paramVolume, | |||
| paramBypass, | |||
| paramCount | |||
| }; | |||
| @@ -118,7 +117,6 @@ private: | |||
| float decay; | |||
| float accent; | |||
| float volume; | |||
| bool bypass; | |||
| } fParams; | |||
| nekobee_synth_t fSynth; | |||
| @@ -96,6 +96,9 @@ DistrhoUIProM::DistrhoUIProM() | |||
| DistrhoUIProM::~DistrhoUIProM() | |||
| { | |||
| if (fPM == nullptr) | |||
| return; | |||
| if (DistrhoPluginProM* const dspPtr = (DistrhoPluginProM*)getPluginInstancePointer()) | |||
| { | |||
| const MutexLocker csm(dspPtr->fMutex); | |||
| @@ -74,8 +74,8 @@ void DistrhoPluginGLBars::initParameter(uint32_t index, Parameter& parameter) | |||
| parameter.name = "X"; | |||
| parameter.symbol = "x"; | |||
| parameter.unit = ""; | |||
| parameter.ranges.def = -4.0f; | |||
| parameter.ranges.min = 0.0f; | |||
| parameter.ranges.def = 0.0f; | |||
| parameter.ranges.min = -4.0f; | |||
| parameter.ranges.max = 4.0f; | |||
| break; | |||
| @@ -26,13 +26,17 @@ START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| DistrhoUIGLBars::DistrhoUIGLBars() | |||
| : UI(512, 512) | |||
| : UI(512, 512), | |||
| fInitialized(false) | |||
| { | |||
| setGeometryConstraints(256, 256, true); | |||
| } | |||
| DistrhoUIGLBars::~DistrhoUIGLBars() | |||
| { | |||
| if (! fInitialized) | |||
| return; | |||
| if (DistrhoPluginGLBars* const dspPtr = (DistrhoPluginGLBars*)getPluginInstancePointer()) | |||
| { | |||
| const MutexLocker csm(dspPtr->fMutex); | |||
| @@ -81,6 +85,8 @@ void DistrhoUIGLBars::uiIdle() | |||
| if (dspPtr->fState != nullptr) | |||
| return; | |||
| fInitialized = true; | |||
| const MutexLocker csm(dspPtr->fMutex); | |||
| dspPtr->fState = &fState; | |||
| } | |||
| @@ -53,6 +53,7 @@ protected: | |||
| bool onKeyboard(const KeyboardEvent&) override; | |||
| private: | |||
| bool fInitialized; | |||
| glBarsState fState; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoUIGLBars) | |||