Signed-off-by: falkTX <falktx@falktx.com>tags/v1.5
| @@ -22,7 +22,7 @@ | |||
| # add_subdirectory(DPF) | |||
| # | |||
| # dpf_add_plugin(MyPlugin | |||
| # TARGETS lv2 vst2 | |||
| # TARGETS lv2 vst2 vst3 | |||
| # UI_TYPE opengl | |||
| # FILES_DSP | |||
| # src/MyPlugin.cpp | |||
| @@ -71,7 +71,7 @@ include(CMakeParseArguments) | |||
| # | |||
| # `TARGETS` <tgt1>...<tgtN> | |||
| # a list of one of more of the following target types: | |||
| # `jack`, `ladspa`, `dssi`, `lv2`, `vst2` | |||
| # `jack`, `ladspa`, `dssi`, `lv2`, `vst2`, `vst3` | |||
| # | |||
| # `UI_TYPE` <type> | |||
| # the user interface type: `opengl` (default), `cairo` | |||
| @@ -153,6 +153,8 @@ function(dpf_add_plugin NAME) | |||
| dpf__build_lv2("${NAME}" "${_dgl_library}" "${_dpf_plugin_MONOLITHIC}") | |||
| elseif(_target STREQUAL "vst2") | |||
| dpf__build_vst2("${NAME}" "${_dgl_library}") | |||
| elseif(_target STREQUAL "vst3") | |||
| dpf__build_vst3("${NAME}" "${_dgl_library}") | |||
| else() | |||
| message(FATAL_ERROR "Unrecognized target type for plugin: ${_target}") | |||
| endif() | |||
| @@ -199,7 +201,7 @@ endfunction() | |||
| # dpf__build_ladspa | |||
| # ------------------------------------------------------------------------------ | |||
| # | |||
| # Add build rules for a DSSI plugin. | |||
| # Add build rules for a LADSPA plugin. | |||
| # | |||
| function(dpf__build_ladspa NAME) | |||
| dpf__create_dummy_source_list(_no_srcs) | |||
| @@ -259,7 +261,7 @@ endfunction() | |||
| # dpf__build_lv2 | |||
| # ------------------------------------------------------------------------------ | |||
| # | |||
| # Add build rules for a LV2 plugin. | |||
| # Add build rules for an LV2 plugin. | |||
| # | |||
| function(dpf__build_lv2 NAME DGL_LIBRARY MONOLITHIC) | |||
| dpf__create_dummy_source_list(_no_srcs) | |||
| @@ -339,6 +341,95 @@ function(dpf__build_vst2 NAME DGL_LIBRARY) | |||
| endif() | |||
| endfunction() | |||
| # dpf__determine_vst3_package_architecture | |||
| # ------------------------------------------------------------------------------ | |||
| # | |||
| # Determines the package architecture for a VST3 plugin target. | |||
| # | |||
| function(dpf__determine_vst3_package_architecture OUTPUT_VARIABLE) | |||
| # if set by variable, override the detection | |||
| if(DPF_VST3_ARCHITECTURE) | |||
| set("${OUTPUT_VARIABLE}" "${DPF_VST3_ARCHITECTURE}" PARENT_SCOPE) | |||
| return() | |||
| endif() | |||
| # not used on Apple, which supports universal binary | |||
| if(APPLE) | |||
| set("${OUTPUT_VARIABLE}" "universal" PARENT_SCOPE) | |||
| return() | |||
| endif() | |||
| # identify the target processor (special case of MSVC, problematic sometimes) | |||
| if(MSVC) | |||
| set(vst3_system_arch "${MSVC_CXX_ARCHITECTURE_ID}") | |||
| else() | |||
| set(vst3_system_arch "${CMAKE_SYSTEM_PROCESSOR}") | |||
| endif() | |||
| # transform the processor name to a format that VST3 recognizes | |||
| if(vst3_system_arch MATCHES "^(x86_64|amd64|AMD64|x64|X64)$") | |||
| set(vst3_package_arch "x86_64") | |||
| elseif(vst3_system_arch MATCHES "^(i.86|x86|X86)$") | |||
| if(WIN32) | |||
| set(vst3_package_arch "x86") | |||
| else() | |||
| set(vst3_package_arch "i386") | |||
| endif() | |||
| elseif(vst3_system_arch MATCHES "^(armv[3-8][a-z]*)$") | |||
| set(vst3_package_arch "${vst3_system_arch}") | |||
| elseif(vst3_system_arch MATCHES "^(aarch64)$") | |||
| set(vst3_package_arch "aarch64") | |||
| else() | |||
| message(FATAL_ERROR "We don't know this architecture for VST3: ${vst3_system_arch}.") | |||
| endif() | |||
| # TODO: the detections for Windows arm/arm64 when supported | |||
| set("${OUTPUT_VARIABLE}" "${vst3_package_arch}" PARENT_SCOPE) | |||
| endfunction() | |||
| # dpf__build_vst3 | |||
| # ------------------------------------------------------------------------------ | |||
| # | |||
| # Add build rules for a VST3 plugin. | |||
| # | |||
| function(dpf__build_vst3 NAME DGL_LIBRARY) | |||
| dpf__determine_vst3_package_architecture(vst3_arch) | |||
| dpf__create_dummy_source_list(_no_srcs) | |||
| dpf__add_module("${NAME}-vst3" ${_no_srcs}) | |||
| dpf__add_plugin_main("${NAME}-vst3" "vst3") | |||
| dpf__add_ui_main("${NAME}-vst3" "vst3" "${DGL_LIBRARY}") | |||
| dpf__set_module_export_list("${NAME}-vst3" "vst3") | |||
| target_link_libraries("${NAME}-vst3" PRIVATE "${NAME}-dsp" "${NAME}-ui") | |||
| set_target_properties("${NAME}-vst3" PROPERTIES | |||
| ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/obj/vst3/$<0:>" | |||
| OUTPUT_NAME "${NAME}" | |||
| PREFIX "") | |||
| if(APPLE) | |||
| set_target_properties("${NAME}-vst3" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/MacOS/$<0:>" | |||
| SUFFIX "") | |||
| elseif(WIN32) | |||
| set_target_properties("${NAME}-vst3" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/${vst3_arch}-win/$<0:>") | |||
| else() | |||
| set_target_properties("${NAME}-vst3" PROPERTIES | |||
| LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/${vst3_arch}-linux/$<0:>") | |||
| endif() | |||
| if(APPLE) | |||
| # Uses the same macOS bundle template as VST2 | |||
| set(INFO_PLIST_PROJECT_NAME "${NAME}") | |||
| configure_file("${DPF_ROOT_DIR}/utils/plugin.vst/Contents/Info.plist" | |||
| "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents/Info.plist" @ONLY) | |||
| file(COPY "${DPF_ROOT_DIR}/utils/plugin.vst/Contents/PkgInfo" | |||
| DESTINATION "${PROJECT_BINARY_DIR}/bin/${NAME}.vst3/Contents") | |||
| endif() | |||
| endfunction() | |||
| # dpf__add_dgl_cairo | |||
| # ------------------------------------------------------------------------------ | |||
| # | |||
| @@ -1 +0,0 @@ | |||
| pugl-upstream/include/ | |||
| @@ -310,9 +310,9 @@ ScopedUTF16String::ScopedUTF16String(const char* const s) noexcept | |||
| : str(nullptr) | |||
| { | |||
| const size_t len = strlen(s); | |||
| str = (int16_t*)malloc(sizeof(int16_t) * len); | |||
| str = (int16_t*)malloc(sizeof(int16_t) * (len + 1)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(str != nullptr,); | |||
| strncpy_utf16(str, s, len); | |||
| strncpy_utf16(str, s, len + 1); | |||
| } | |||
| ScopedUTF16String::~ScopedUTF16String() noexcept | |||
| @@ -1402,11 +1402,11 @@ public: | |||
| v3_result getParameterInfo(int32_t rindex, v3_param_info* const info) const noexcept | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(rindex >= 0, V3_INVALID_ARG); | |||
| std::memset(info, 0, sizeof(v3_param_info)); | |||
| #if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| if (rindex == 0) | |||
| { | |||
| std::memset(info, 0, sizeof(v3_param_info)); | |||
| info->param_id = rindex; | |||
| info->flags = V3_PARAM_CAN_AUTOMATE | V3_PARAM_IS_LIST | V3_PARAM_PROGRAM_CHANGE; | |||
| info->step_count = fProgramCountMinusOne; | |||
| @@ -1417,10 +1417,12 @@ public: | |||
| --rindex; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| if (rindex <= 130*16) | |||
| if (rindex < 130*16) | |||
| { | |||
| std::memset(info, 0, sizeof(v3_param_info)); | |||
| info->param_id = rindex; | |||
| # if DISTRHO_PLUGIN_WANT_PROGRAMS | |||
| ++info->param_id; | |||
| # endif | |||
| info->flags = V3_PARAM_CAN_AUTOMATE | V3_PARAM_IS_HIDDEN; | |||
| info->step_count = 127; | |||
| char ccstr[24]; | |||
| @@ -1465,7 +1467,6 @@ public: | |||
| if ((hints & kParameterIsInteger) && ranges.max - ranges.min > 1) | |||
| step_count = ranges.max - ranges.min - 1; | |||
| std::memset(info, 0, sizeof(v3_param_info)); | |||
| info->param_id = index + fParameterOffset; | |||
| info->flags = flags; | |||
| info->step_count = step_count; | |||
| @@ -1493,7 +1494,7 @@ public: | |||
| --rindex; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| if (rindex <= 130*16) | |||
| if (rindex < 130*16) | |||
| { | |||
| snprintf_f32_utf16(output, std::round(normalised * 127), 128); | |||
| return V3_OK; | |||
| @@ -1519,7 +1520,7 @@ public: | |||
| --rindex; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| if (rindex <= 130*16) | |||
| if (rindex < 130*16) | |||
| { | |||
| // TODO | |||
| return V3_NOT_IMPLEMENTED; | |||
| @@ -1542,7 +1543,7 @@ public: | |||
| --rindex; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| if (rindex <= 130*16) | |||
| if (rindex < 130*16) | |||
| return std::round(normalised * 127); | |||
| rindex -= 130*16; | |||
| #endif | |||
| @@ -1561,7 +1562,7 @@ public: | |||
| --rindex; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| if (rindex <= 130*16) | |||
| if (rindex < 130*16) | |||
| return std::max(0.0, std::min(1.0, plain / 127)); | |||
| rindex -= 130*16; | |||
| #endif | |||
| @@ -1580,7 +1581,7 @@ public: | |||
| --rindex; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| if (rindex <= 130*16) | |||
| if (rindex < 130*16) | |||
| { | |||
| // TODO | |||
| return 0.0; | |||
| @@ -1625,7 +1626,7 @@ public: | |||
| --rindex; | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| if (rindex <= 130*16) | |||
| if (rindex < 130*16) | |||
| { | |||
| // TODO | |||
| fChangedParameterValues[rindex] = true; | |||
| @@ -1775,7 +1776,7 @@ public: | |||
| --rindex; | |||
| # endif | |||
| # if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| if (rindex <= 130*16) | |||
| if (rindex < 130*16) | |||
| continue; | |||
| rindex -= 130*16; | |||
| # endif | |||
| @@ -1835,26 +1836,42 @@ public: | |||
| # if DISTRHO_PLUGIN_WANT_STATE | |||
| if (std::strcmp(msgid, "state-set") == 0) | |||
| { | |||
| int16_t* key16; | |||
| int16_t* value16; | |||
| uint32_t keySize, valueSize; | |||
| int64_t keyLength = -1; | |||
| int64_t valueLength = -1; | |||
| v3_result res; | |||
| res = v3_cpp_obj(attrs)->get_binary(attrs, "key", (const void**)&key16, &keySize); | |||
| res = v3_cpp_obj(attrs)->get_int(attrs, "key:length", &keyLength); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(keyLength >= 0, keyLength, V3_INTERNAL_ERR); | |||
| res = v3_cpp_obj(attrs)->get_int(attrs, "value:length", &valueLength); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(valueLength >= 0, valueLength, V3_INTERNAL_ERR); | |||
| int16_t* const key16 = (int16_t*)std::malloc(sizeof(int16_t)*(keyLength + 1)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(key16 != nullptr, V3_NOMEM); | |||
| int16_t* const value16 = (int16_t*)std::malloc(sizeof(int16_t)*(valueLength + 1)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(value16 != nullptr, V3_NOMEM); | |||
| res = v3_cpp_obj(attrs)->get_string(attrs, "key", key16, sizeof(int16_t)*keyLength); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); | |||
| res = v3_cpp_obj(attrs)->get_binary(attrs, "value", (const void**)&value16, &valueSize); | |||
| res = v3_cpp_obj(attrs)->get_string(attrs, "value", value16, sizeof(int16_t)*valueLength); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); | |||
| // do cheap inline conversion | |||
| char* const key = (char*)key16; | |||
| char* const value = (char*)value16; | |||
| for (uint32_t i=0; i<keySize/sizeof(int16_t); ++i) | |||
| for (int64_t i=0; i<keyLength; ++i) | |||
| key[i] = key16[i]; | |||
| for (uint32_t i=0; i<valueSize/sizeof(int16_t); ++i) | |||
| for (int64_t i=0; i<valueLength; ++i) | |||
| value[i] = value16[i]; | |||
| key[keyLength] = '\0'; | |||
| value[valueLength] = '\0'; | |||
| fPlugin.setState(key, value); | |||
| // save this key as needed | |||
| @@ -1867,6 +1884,8 @@ public: | |||
| if (dkey == key) | |||
| { | |||
| it->second = value; | |||
| std::free(key16); | |||
| std::free(value16); | |||
| return V3_OK; | |||
| } | |||
| } | |||
| @@ -1874,6 +1893,8 @@ public: | |||
| d_stderr("Failed to find plugin state with key \"%s\"", key); | |||
| } | |||
| std::free(key16); | |||
| std::free(value16); | |||
| return V3_OK; | |||
| } | |||
| # endif | |||
| @@ -2042,6 +2063,8 @@ private: | |||
| DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); | |||
| v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 2); | |||
| v3_cpp_obj(attrlist)->set_int(attrlist, "key:length", std::strlen(key)); | |||
| v3_cpp_obj(attrlist)->set_int(attrlist, "value:length", std::strlen(value)); | |||
| v3_cpp_obj(attrlist)->set_string(attrlist, "key", ScopedUTF16String(key)); | |||
| v3_cpp_obj(attrlist)->set_string(attrlist, "value", ScopedUTF16String(value)); | |||
| v3_cpp_obj(fConnection)->notify(fConnection, message); | |||
| @@ -3085,6 +3108,10 @@ struct dpf_component : v3_component_cpp { | |||
| hostContextFromFactory(h), | |||
| hostContextFromInitialize(nullptr) | |||
| { | |||
| // make sure context is valid through this component lifetime | |||
| if (hostContextFromFactory != nullptr) | |||
| v3_cpp_obj_ref(hostContextFromFactory); | |||
| // v3_funknown, everything custom | |||
| query_interface = query_interface_component; | |||
| ref = ref_component; | |||
| @@ -3541,6 +3568,10 @@ struct dpf_factory : v3_plugin_factory_cpp { | |||
| ~dpf_factory() | |||
| { | |||
| // unref old context if there is one | |||
| if (hostContext != nullptr) | |||
| v3_cpp_obj_unref(hostContext); | |||
| if (gComponentGarbage.size() == 0) | |||
| return; | |||
| @@ -3696,7 +3727,18 @@ struct dpf_factory : v3_plugin_factory_cpp { | |||
| { | |||
| d_stdout("dpf_factory::set_host_context => %p %p", self, context); | |||
| dpf_factory* const factory = *static_cast<dpf_factory**>(self); | |||
| // unref old context if there is one | |||
| if (factory->hostContext != nullptr) | |||
| v3_cpp_obj_unref(factory->hostContext); | |||
| // store new context | |||
| factory->hostContext = context; | |||
| // make sure the object keeps being valid for a while | |||
| if (context != nullptr) | |||
| v3_cpp_obj_ref(context); | |||
| return V3_OK; | |||
| } | |||
| @@ -299,27 +299,46 @@ public: | |||
| #if DISTRHO_PLUGIN_WANT_STATE | |||
| if (std::strcmp(msgid, "state-set") == 0) | |||
| { | |||
| int16_t* key16; | |||
| int16_t* value16; | |||
| uint32_t keySize, valueSize; | |||
| int64_t keyLength = -1; | |||
| int64_t valueLength = -1; | |||
| v3_result res; | |||
| res = v3_cpp_obj(attrs)->get_binary(attrs, "key", (const void**)&key16, &keySize); | |||
| res = v3_cpp_obj(attrs)->get_int(attrs, "key:length", &keyLength); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(keyLength >= 0, keyLength, V3_INTERNAL_ERR); | |||
| res = v3_cpp_obj(attrs)->get_binary(attrs, "value", (const void**)&value16, &valueSize); | |||
| res = v3_cpp_obj(attrs)->get_int(attrs, "value:length", &valueLength); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(valueLength >= 0, valueLength, V3_INTERNAL_ERR); | |||
| int16_t* const key16 = (int16_t*)std::malloc(sizeof(int16_t)*(keyLength + 1)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(key16 != nullptr, V3_NOMEM); | |||
| int16_t* const value16 = (int16_t*)std::malloc(sizeof(int16_t)*(valueLength + 1)); | |||
| DISTRHO_SAFE_ASSERT_RETURN(value16 != nullptr, V3_NOMEM); | |||
| res = v3_cpp_obj(attrs)->get_string(attrs, "key", key16, sizeof(int16_t)*keyLength); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); | |||
| res = v3_cpp_obj(attrs)->get_string(attrs, "value", value16, sizeof(int16_t)*valueLength); | |||
| DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res); | |||
| // do cheap inline conversion | |||
| char* const key = (char*)key16; | |||
| char* const value = (char*)value16; | |||
| for (uint32_t i=0; i<keySize/sizeof(int16_t); ++i) | |||
| for (int64_t i=0; i<keyLength; ++i) | |||
| key[i] = key16[i]; | |||
| for (uint32_t i=0; i<valueSize/sizeof(int16_t); ++i) | |||
| for (int64_t i=0; i<valueLength; ++i) | |||
| value[i] = value16[i]; | |||
| key[keyLength] = '\0'; | |||
| value[valueLength] = '\0'; | |||
| fUI.stateChanged(key, value); | |||
| std::free(key16); | |||
| std::free(value16); | |||
| return V3_OK; | |||
| } | |||
| #endif | |||
| @@ -549,6 +568,8 @@ private: | |||
| DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,); | |||
| v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1); | |||
| v3_cpp_obj(attrlist)->set_int(attrlist, "key:length", std::strlen(key)); | |||
| v3_cpp_obj(attrlist)->set_int(attrlist, "value:length", std::strlen(value)); | |||
| v3_cpp_obj(attrlist)->set_string(attrlist, "key", ScopedUTF16String(key)); | |||
| v3_cpp_obj(attrlist)->set_string(attrlist, "value", ScopedUTF16String(value)); | |||
| v3_cpp_obj(fConnection)->notify(fConnection, message); | |||
| @@ -103,12 +103,13 @@ protected: | |||
| void onDisplay() override | |||
| { | |||
| const GraphicsContext& context(getGraphicsContext()); | |||
| const double scaleFactor = getWindow().getScaleFactor(); | |||
| const int iconSize = bgIcon.getWidth(); | |||
| Color(0.027f, 0.027f, 0.027f).setFor(context); | |||
| Rectangle<uint>(0, 0, getSize()).draw(context); | |||
| bgIcon.setY(curPage*iconSize + curPage*3); | |||
| bgIcon.setY(curPage * iconSize + curPage * 3 * scaleFactor); | |||
| Color(0.129f, 0.129f, 0.129f).setFor(context); | |||
| bgIcon.draw(context); | |||
| @@ -118,7 +119,8 @@ protected: | |||
| if (curHover != curPage && curHover != -1) | |||
| { | |||
| Rectangle<int> rHover(1, curHover*iconSize + curHover*3, iconSize-2, iconSize-2); | |||
| Rectangle<int> rHover(1 * scaleFactor, curHover * iconSize + curHover * 3 * scaleFactor, | |||
| iconSize - 2 * scaleFactor, iconSize - 2 * scaleFactor); | |||
| Color(0.071f, 0.071f, 0.071f).setFor(context); | |||
| rHover.draw(context); | |||
| @@ -146,13 +148,13 @@ protected: | |||
| // draw some text | |||
| nvg.beginFrame(this); | |||
| nvg.fontSize(23.0f); | |||
| nvg.fontSize(23.0f * scaleFactor); | |||
| nvg.textAlign(NanoVG::ALIGN_LEFT|NanoVG::ALIGN_TOP); | |||
| //nvg.textLineHeight(20.0f); | |||
| nvg.fillColor(220,220,220,220); | |||
| nvg.textBox(10, 420, iconSize, "Haha,", nullptr); | |||
| nvg.textBox(15, 440, iconSize, "Look!", nullptr); | |||
| nvg.textBox(10 * scaleFactor, 420 * scaleFactor, iconSize, "Haha,", nullptr); | |||
| nvg.textBox(15 * scaleFactor, 440 * scaleFactor, iconSize, "Look!", nullptr); | |||
| nvg.endFrame(); | |||
| #endif | |||
| @@ -226,9 +228,10 @@ protected: | |||
| { | |||
| const uint width = ev.size.getWidth(); | |||
| const uint height = ev.size.getHeight(); | |||
| const double scaleFactor = getWindow().getScaleFactor(); | |||
| bgIcon.setWidth(width-4); | |||
| bgIcon.setHeight(width-4); | |||
| bgIcon.setWidth(width - 4 * scaleFactor); | |||
| bgIcon.setHeight(width - 4 * scaleFactor); | |||
| lineSep.setStartPos(width, 0); | |||
| lineSep.setEndPos(width, height); | |||
| @@ -420,30 +423,31 @@ public: | |||
| curWidget(nullptr) | |||
| { | |||
| const ScopedGraphicsContext sgc(*this); | |||
| const double scaleFactor = getScaleFactor(); | |||
| wColor = new ExampleColorSubWidget(this); | |||
| wColor->hide(); | |||
| wColor->setAbsoluteX(kSidebarWidth); | |||
| wColor->setAbsoluteX(kSidebarWidth * scaleFactor); | |||
| wImages = new ExampleImagesSubWidget(this); | |||
| wImages->hide(); | |||
| wImages->setAbsoluteX(kSidebarWidth); | |||
| wImages->setAbsoluteX(kSidebarWidth * scaleFactor); | |||
| wRects = new ExampleRectanglesSubWidget(this); | |||
| wRects->hide(); | |||
| wRects->setAbsoluteX(kSidebarWidth); | |||
| wRects->setAbsoluteX(kSidebarWidth * scaleFactor); | |||
| wShapes = new ExampleShapesSubWidget(this); | |||
| wShapes->hide(); | |||
| wShapes->setAbsoluteX(kSidebarWidth); | |||
| wShapes->setAbsoluteX(kSidebarWidth * scaleFactor); | |||
| #ifdef DGL_OPENGL | |||
| wText = new ExampleTextSubWidget(this), | |||
| wText->hide(); | |||
| wText->setAbsoluteX(kSidebarWidth); | |||
| wText->setAbsoluteX(kSidebarWidth * scaleFactor); | |||
| #endif | |||
| wLeft = new LeftSideWidget(this, this), | |||
| wLeft->setAbsolutePos(2, 2); | |||
| wLeft->setAbsolutePos(2 * scaleFactor, 2 * scaleFactor); | |||
| resizer = new ResizeHandle(this); | |||
| @@ -493,10 +497,12 @@ protected: | |||
| { | |||
| StandaloneWindow::onReshape(width, height); | |||
| if (width < kSidebarWidth) | |||
| const double scaleFactor = getScaleFactor(); | |||
| if (width < kSidebarWidth * scaleFactor) | |||
| return; | |||
| Size<uint> size(width-kSidebarWidth, height); | |||
| const Size<uint> size(width - kSidebarWidth * scaleFactor, height); | |||
| wColor->setSize(size); | |||
| wImages->setSize(size); | |||
| wRects->setSize(size); | |||
| @@ -504,7 +510,7 @@ protected: | |||
| #ifdef DGL_OPENGL | |||
| wText->setSize(size); | |||
| #endif | |||
| wLeft->setSize(kSidebarWidth-4, height-4); | |||
| wLeft->setSize((kSidebarWidth - 4) * scaleFactor, (height - 4) * scaleFactor); | |||
| } | |||
| private: | |||
| @@ -528,8 +534,9 @@ template <class ExampleWidgetStandaloneWindow> | |||
| void createAndShowExampleWidgetStandaloneWindow(Application& app) | |||
| { | |||
| ExampleWidgetStandaloneWindow swin(app); | |||
| const double scaleFactor = swin.getScaleFactor(); | |||
| swin.setResizable(true); | |||
| swin.setSize(600, 500); | |||
| swin.setSize(600 * scaleFactor, 500 * scaleFactor); | |||
| swin.setTitle(ExampleWidgetStandaloneWindow::kExampleWidgetName); | |||
| swin.show(); | |||
| app.exec(); | |||
| @@ -38,21 +38,26 @@ public: | |||
| loadSharedResources(); | |||
| #endif | |||
| setResizable(true); | |||
| setSize(500, 200); | |||
| setGeometryConstraints(500, 200, true); | |||
| setTitle("FileBrowserDialog"); | |||
| const double scaleFactor = getScaleFactor(); | |||
| setGeometryConstraints(500 * scaleFactor, 200 * scaleFactor, true); | |||
| setSize(500 * scaleFactor, 200 * scaleFactor); | |||
| done(); | |||
| } | |||
| protected: | |||
| void onNanoDisplay() override | |||
| { | |||
| const double scaleFactor = getScaleFactor(); | |||
| // Selected file | |||
| beginPath(); | |||
| fontSize(14); | |||
| fontSize(14 * scaleFactor); | |||
| textAlign(ALIGN_LEFT | ALIGN_MIDDLE); | |||
| fillColor(255, 255, 255, 255); | |||
| text(20, getHeight()/2, selectedFile, NULL); | |||
| text(20 * scaleFactor, getHeight()/2, selectedFile, NULL); | |||
| closePath(); | |||
| // Button background | |||
| @@ -66,7 +71,7 @@ protected: | |||
| // Button label | |||
| beginPath(); | |||
| fontSize(14); | |||
| fontSize(14 * scaleFactor); | |||
| Rectangle<float> buttonTextBounds; | |||
| textBounds(0, 0, "Press me", NULL, buttonTextBounds); | |||
| textAlign(ALIGN_CENTER | ALIGN_MIDDLE); | |||
| @@ -138,8 +143,12 @@ protected: | |||
| { | |||
| const uint width = ev.size.getWidth(); | |||
| const uint height = ev.size.getHeight(); | |||
| const double scaleFactor = getScaleFactor(); | |||
| buttonBounds = Rectangle<uint>(width - 120, height/2 - 20, 100, 40); | |||
| buttonBounds = Rectangle<uint>(width - 120 * scaleFactor, | |||
| height/2 - 20 * scaleFactor, | |||
| 100 * scaleFactor, | |||
| 40 * scaleFactor); | |||
| } | |||
| void onFocus(const bool focus, CrossingMode) override | |||
| @@ -85,7 +85,7 @@ public: | |||
| setResizable(true); | |||
| setSize(500, 500); | |||
| // setGeometryConstraints(500, 500, false); | |||
| setGeometryConstraints(500, 500, false, true); | |||
| setTitle("NanoImage"); | |||
| done(); | |||
| @@ -42,23 +42,28 @@ public: | |||
| // StandaloneWindow | |||
| explicit ExampleTextWidget(Application& app); | |||
| // helper | |||
| double getScaleFactor(); | |||
| protected: | |||
| void onNanoDisplay() override | |||
| { | |||
| const int width = BaseWidget::getWidth(); | |||
| const int height = BaseWidget::getHeight(); | |||
| const double scaleFactor = getScaleFactor(); | |||
| NanoVG::fontSize(40.0f); | |||
| NanoVG::fontSize(40.0f * scaleFactor); | |||
| NanoVG::textAlign(NanoVG::Align(NanoVG::ALIGN_CENTER|NanoVG::ALIGN_MIDDLE)); | |||
| NanoVG::textLineHeight(20.0f); | |||
| NanoVG::textLineHeight(20.0f * scaleFactor); | |||
| NanoVG::beginPath(); | |||
| NanoVG::fillColor(220,220,220,255); | |||
| NanoVG::roundedRect(10, height/4+10, width-20, height/2-20, 3); | |||
| NanoVG::roundedRect(10 * scaleFactor, height/4 + 10 * scaleFactor, | |||
| width - 20 * scaleFactor, height/2 - 20 * scaleFactor, 3 * scaleFactor); | |||
| NanoVG::fill(); | |||
| NanoVG::fillColor(0,150,0,220); | |||
| NanoVG::textBox(10, height/2, width-20, "Hello World!", nullptr); | |||
| NanoVG::textBox(10 * scaleFactor, height/2, width - 20 * scaleFactor, "Hello World!", nullptr); | |||
| } | |||
| }; | |||
| @@ -71,6 +76,12 @@ ExampleTextWidget<NanoSubWidget>::ExampleTextWidget(Widget* const parent) | |||
| setSize(500, 300); | |||
| } | |||
| template<> inline | |||
| double ExampleTextWidget<NanoSubWidget>::getScaleFactor() | |||
| { | |||
| return getWindow().getScaleFactor(); | |||
| } | |||
| // TopLevelWidget | |||
| template<> inline | |||
| ExampleTextWidget<NanoTopLevelWidget>::ExampleTextWidget(Window& windowToMapTo) | |||
| @@ -80,6 +91,12 @@ ExampleTextWidget<NanoTopLevelWidget>::ExampleTextWidget(Window& windowToMapTo) | |||
| setSize(500, 300); | |||
| } | |||
| template<> inline | |||
| double ExampleTextWidget<NanoTopLevelWidget>::getScaleFactor() | |||
| { | |||
| return NanoTopLevelWidget::getScaleFactor(); | |||
| } | |||
| // StandaloneWindow | |||
| template<> inline | |||
| ExampleTextWidget<NanoStandaloneWindow>::ExampleTextWidget(Application& app) | |||
| @@ -90,6 +107,12 @@ ExampleTextWidget<NanoStandaloneWindow>::ExampleTextWidget(Application& app) | |||
| done(); | |||
| } | |||
| template<> inline | |||
| double ExampleTextWidget<NanoStandaloneWindow>::getScaleFactor() | |||
| { | |||
| return Window::getScaleFactor(); | |||
| } | |||
| template class ExampleTextWidget<NanoSubWidget>; | |||
| template class ExampleTextWidget<NanoTopLevelWidget>; | |||
| template class ExampleTextWidget<NanoStandaloneWindow>; | |||
| @@ -29,6 +29,7 @@ | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||
| #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:ReverbPlugin" | |||
| #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:ReverbPlugin" | |||
| #define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Reverb" | |||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED | |||
| @@ -29,6 +29,7 @@ include ../../dpf/Makefile.plugins.mk | |||
| TARGETS += jack | |||
| TARGETS += ladspa | |||
| TARGETS += lv2_sep | |||
| TARGETS += vst2 | |||
| TARGETS += vst3 | |||
| @@ -38,12 +39,6 @@ TARGETS += dssi | |||
| endif | |||
| endif | |||
| ifeq ($(HAVE_DGL),true) | |||
| TARGETS += lv2_sep | |||
| else | |||
| TARGETS += lv2_dsp | |||
| endif | |||
| all: $(TARGETS) | |||
| # -------------------------------------------------------------- | |||
| @@ -14,7 +14,6 @@ | |||
| * For a full copy of the license see the LICENSE file. | |||
| */ | |||
| #include "libprojectM/projectM-opengl.h" | |||
| #include "libprojectM/projectM.hpp" | |||
| #include "DistrhoPluginProM.hpp" | |||
| @@ -69,6 +68,12 @@ static String getCurrentExecutableDataDir() | |||
| } | |||
| else | |||
| # endif | |||
| if (datadir.endsWith("/x86_64-linux")) | |||
| { | |||
| datadir.truncate(datadir.rfind('/')); | |||
| datadir += "/Resources"; | |||
| } | |||
| else | |||
| #endif | |||
| { | |||
| datadir += "/resources"; | |||
| @@ -166,9 +171,6 @@ void DistrhoUIProM::onDisplay() | |||
| return; | |||
| fPM->renderFrame(); | |||
| // turn off shaders at the end of the drawing cycle, so other things can draw properly | |||
| glUseProgram(0); | |||
| } | |||
| static projectMKeycode dgl2pmkey(const DGL_NAMESPACE::Key key) noexcept | |||
| @@ -251,33 +253,6 @@ bool DistrhoUIProM::onKeyboard(const KeyboardEvent& ev) | |||
| if (fPM == nullptr) | |||
| return false; | |||
| #if 0 | |||
| if (ev.press && (ev.key == '1' || ev.key == '+' || ev.key == '-')) | |||
| { | |||
| if (ev.key == '1') | |||
| { | |||
| if (getWidth() != 512 || getHeight() != 512) | |||
| setSize(512, 512); | |||
| } | |||
| else if (ev.key == '+') | |||
| { | |||
| /**/ if (getWidth() < 1100 && getHeight() < 1100) | |||
| setSize(getWidth()+100, getHeight()+100); | |||
| else if (getWidth() != 1100 || getHeight() != 1100) | |||
| setSize(1100, 1100); | |||
| } | |||
| else if (ev.key == '-') | |||
| { | |||
| /**/ if (getWidth() >= 200 && getHeight() >= 200) | |||
| setSize(getWidth()-100, getHeight()-100); | |||
| else if (getWidth() != 100 || getHeight() != 100) | |||
| setSize(100, 100); | |||
| } | |||
| return true; | |||
| } | |||
| #endif | |||
| // special handling for text | |||
| if (fPM->isTextInputActive(true) && !ev.press) | |||
| { | |||
| @@ -357,20 +332,6 @@ bool DistrhoUIProM::onKeyboard(const KeyboardEvent& ev) | |||
| return true; | |||
| } | |||
| bool DistrhoUIProM::onSpecial(const SpecialEvent& ev) | |||
| { | |||
| if (fPM == nullptr) | |||
| return false; | |||
| const projectMKeycode pmKey = dgl2pmkey(ev.key); | |||
| if (pmKey == PROJECTM_K_NONE) | |||
| return false; | |||
| fPM->default_key_handler(ev.press ? PROJECTM_KEYUP : PROJECTM_KEYDOWN, pmKey); | |||
| return true; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| @@ -49,7 +49,6 @@ protected: | |||
| void onDisplay() override; | |||
| bool onKeyboard(const KeyboardEvent&) override; | |||
| bool onSpecial(const SpecialEvent&) override; | |||
| private: | |||
| ScopedPointer<projectM> fPM; | |||
| @@ -195,9 +195,7 @@ LINK_FLAGS += -lpthread | |||
| # -------------------------------------------------------------- | |||
| # Enable all possible plugin types | |||
| TARGETS += lv2 | |||
| TARGETS += vst2 | |||
| TARGETS += vst3 | |||
| TARGETS = lv2 vst2 vst3 | |||
| all: $(TARGETS) | |||
| @@ -56,6 +56,11 @@ protected: | |||
| const GraphicsContext& context(getGraphicsContext()); | |||
| const double lineWidth = 1.0 * getScaleFactor(); | |||
| #ifdef DGL_OPENGL | |||
| glUseProgram(0); | |||
| glMatrixMode(GL_MODELVIEW); | |||
| #endif | |||
| // draw white lines, 1px wide | |||
| Color(1.0f, 1.0f, 1.0f).setFor(context); | |||
| l1.draw(context, lineWidth); | |||
| @@ -30,6 +30,7 @@ | |||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 1 | |||
| #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | |||
| #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:AnalyserPlugin" | |||
| #define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Analyzer" | |||
| #define DISTRHO_UI_USER_RESIZABLE 1 | |||
| enum Parameters { | |||
| @@ -3,7 +3,7 @@ | |||
| * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies | |||
| * Copyright (C) 2000 Christian Zander <phoenix@minion.de> | |||
| * Copyright (C) 2015 Nedko Arnaudov | |||
| * Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2016-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -27,9 +27,14 @@ START_NAMESPACE_DISTRHO | |||
| DistrhoUIGLBars::DistrhoUIGLBars() | |||
| : UI(512, 512), | |||
| fInitialized(false) | |||
| fInitialized(false), | |||
| fResizeHandle(this) | |||
| { | |||
| setGeometryConstraints(256, 256, true); | |||
| // no need to show resize handle if window is user-resizable | |||
| if (isResizable()) | |||
| fResizeHandle.hide(); | |||
| } | |||
| DistrhoUIGLBars::~DistrhoUIGLBars() | |||
| @@ -100,36 +105,6 @@ void DistrhoUIGLBars::onDisplay() | |||
| fState.Render(); | |||
| } | |||
| bool DistrhoUIGLBars::onKeyboard(const KeyboardEvent& ev) | |||
| { | |||
| if (ev.press && (ev.key == '1' || ev.key == '+' || ev.key == '-')) | |||
| { | |||
| if (ev.key == '1') | |||
| { | |||
| if (getWidth() != 512 || getHeight() != 512) | |||
| setSize(512, 512); | |||
| } | |||
| else if (ev.key == '+') | |||
| { | |||
| /**/ if (getWidth() < 1100 && getHeight() < 1100) | |||
| setSize(std::min(getWidth()+100, 1100U), std::min(getHeight()+100, 1100U)); | |||
| else if (getWidth() != 1100 || getHeight() != 1100) | |||
| setSize(1100, 1100); | |||
| } | |||
| else if (ev.key == '-') | |||
| { | |||
| /**/ if (getWidth() > 100 && getHeight() > 100) | |||
| setSize(std::max(getWidth()-100, 100U), std::max(getHeight()-100, 100U)); | |||
| else if (getWidth() != 100 || getHeight() != 100) | |||
| setSize(100, 100); | |||
| } | |||
| return true; | |||
| } | |||
| return true; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| UI* createUI() | |||
| @@ -3,7 +3,7 @@ | |||
| * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies | |||
| * Copyright (C) 2000 Christian Zander <phoenix@minion.de> | |||
| * Copyright (C) 2015 Nedko Arnaudov | |||
| * Copyright (C) 2016-2019 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2016-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -24,6 +24,7 @@ | |||
| #include "DistrhoUI.hpp" | |||
| #include "glBars.hpp" | |||
| #include "ResizeHandle.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| @@ -50,11 +51,11 @@ protected: | |||
| // Widget Callbacks | |||
| void onDisplay() override; | |||
| bool onKeyboard(const KeyboardEvent&) override; | |||
| private: | |||
| bool fInitialized; | |||
| glBarsState fState; | |||
| ResizeHandle fResizeHandle; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DistrhoUIGLBars) | |||
| }; | |||
| @@ -31,10 +31,7 @@ LINK_FLAGS += -lpthread | |||
| # -------------------------------------------------------------- | |||
| # Enable all possible plugin types | |||
| TARGETS += jack | |||
| TARGETS += lv2 | |||
| TARGETS += vst2 | |||
| TARGETS += vst3 | |||
| TARGETS = jack lv2 vst2 vst3 | |||
| all: $(TARGETS) | |||