JUCE breaking changes ===================== develop ======= Change ------ Functions on AudioPluginInstance that can add parameters have been made private. Possible Issues --------------- Code implementing custom plugin formats may stop building if it calls these functions. Workaround ---------- When implementing custom plugin formats, ensure that the plugin parameters derive from AudioPluginInstance::HostedParameter and then use addHostedParameter, addHostedParameterGroup or setHostedParameterTree to add the parameters to the plugin instance. Rationale --------- In a plugin host, it is very important to be able to uniquely identify parameters across different versions of the same plugin. To make this possible, we needed to introduce a way of retrieving a unique ID for each parameter, which is now possible using the HostedParameter class. However, we also needed to enforce that all AudioPluginInstances can only have parameters which are of the type HostedParameter, which required hiding the old functions. Version 6.1.0 ============= Change ------ juce::gl::loadFunctions() no longer loads extension functions. Possible Issues --------------- Code that depended on extension functions being loaded automatically may cease to function correctly. Workaround ---------- Extension functions can now be loaded using juce::gl::loadExtensions(). Rationale --------- There are a great number of extension functions, and on some systems these can be slow to load (i.e. a second or so). Projects that do not require these extension functions should not have to pay for this unnecessary overhead. Now, only core functions will be loaded by default, and extensions can be loaded explicitly in projects that require such functionality. Change ------ Thread::setPriority() will no longer set a realtime scheduling policy for all threads with non-zero priorities on POSIX systems. Possible Issues --------------- Threads that implicitly relied on using a realtime policy will no longer request a realtime policy if their priority is 7 or lower. Workaround ---------- For threads that require a realtime policy on POSIX systems, request a priority of 8 or higher by calling Thread::setPriority() or Thread::setCurrentThreadPriority(). Rationale --------- By default, new Thread instances have a priority of 5. Previously, non-zero priorities corresponded to realtime scheduling policies, meaning that new Threads would use the realtime scheduling policy unless they explicitly requested a priority of 0. However, most threads do not and should not require realtime scheduling. Setting a realtime policy on all newly-created threads may degrade performance, as multiple realtime threads will end up fighting for limited resources. Change ------ The JUCE_GLSL_VERSION preprocessor definition has been removed. Possible Issues --------------- Code which used this definition will no longer compile. Workaround ---------- Use OpenGLHelpers::getGLSLVersionString to retrieve a version string which is consistent with the capabilities of the current OpenGL context. Rationale --------- A compile-time version string is not very useful, as OpenGL versions and capabilities can change at runtime. Replacing this macro with a function allows querying the capabilities of the current context at runtime. Change ------ The minimum support CMake version is now 3.15. Possible Issues --------------- It will no longer be possible to configure JUCE projects with CMake versions between 3.12 and 3.14 inclusive. Workaround ---------- No workaround is available. Rationale --------- Moving to 3.15 allows us to use target_link_directories and target_link_options, which were introduced in 3.13, which in turn allows us to provide support for bundled precompiled libraries in modules. Plugins already required CMake 3.15, so this change just brings other target types in line with the requirements for plugins. Change ------ The default value of JUCE_MODAL_LOOPS_PERMITTED has been changed from 1 to 0. Possible Issues --------------- With JUCE_MODAL_LOOPS_PERMITTED set to 0 code that previously relied upon modal loops will need to be rewritten to use asynchronous versions of the modal functions. There is no non-modal alternative to AlterWindow::showNativeDialogBox and the previously modal behaviour of the MultiDocumentPanel destructor has changed. Workaround ---------- Set JUCE_MODAL_LOOPS_PERMITTED back to 1. Rationale --------- Modal operations are a frequent source of problems, particularly when used in plug-ins. On Android modal loops are not possible, so people wanting to target Android often have an unwelcome surprise when then have to rewrite what they assumed to be platform independent code. Changing the default addresses these problems. Change ------ The minimum supported C++ standard is now C++14 and the oldest supported compilers on macOS and Linux are now Xcode 9.2, GCC 5.0 and Clang 3.4. Possible Issues --------------- Older compilers will no longer be able to compile JUCE. People using Xcode 8.5 on OS X 10.11 will need to update the operating system to OS X 10.12 to be able to use Xcode 9.2. Workaround ---------- No workaround is available. Rationale --------- This compiler upgrade will allow the use of C++14 within the framework. Change ------ Platform GL headers are no longer included in juce_opengl.h Possible Issues --------------- Projects depending on symbols declared in these headers may fail to build. Workaround ---------- The old platform-supplied headers have been replaced with a new juce_gl.h header which is generated using the XML registry files supplied by Khronos. This custom header declares GL symbols in the juce::gl namespace. If your code only needs to be JUCE-compatible, you can explicitly qualify each name with `juce::gl::`. If you need your code to build with different extension-loader libraries (GLEW, GL3W etc.) you can make all GL symbols visible without additional qualification with `using namespace juce::gl`. Rationale --------- Using our own GL headers allows us to generate platform-independent headers which include symbols for all specified OpenGL versions and extensions. Note that although the function signatures exist, they may not resolve to a function at runtime. If your code uses commands from an extension or recent GL version, you should check each function pointer against `nullptr` before attempting to use it. To avoid repeatedly checking, you could query a subset of functions after calling gl::loadFunctions() and cache the results. Supplying custom GL headers also allows us to use C++ techniques (namespaces, references), making the headers safer than the platform-defined headers. Platform headers are generally written in C, and export a significant portion of their symbols as preprocessor definitions. Change ------ The functions `getComponentAsyncLayerBackedViewDisabled` and `setComponentAsyncLayerBackedViewDisabled` were moved into the juce namespace. Possible Issues --------------- Code that declares these functions may fail to link. Workaround ---------- Move declarations of these functions into the juce namespace. Rationale --------- Although the names of these functions are unlikely to collide with functions from other libraries, we can make such collisions much more unlikely by keeping JUCE code in the juce namespace. Change ------ The `juce_blocks_basics` module was removed. Possible Issues --------------- Projects depending on `juce_blocks_basics` will not build. Workaround ---------- The BLOCKS API is now located in a separate repository: https://github.com/WeAreROLI/roli_blocks_basics Projects which used to depend on `juce_blocks_basics` can use `roli_blocks_basics` instead. Rationale --------- ROLI is no longer involved with the development of JUCE. Therefore, development on the BLOCKS API has been moved out of the JUCE repository, and to a new repository managed by ROLI. Change ------ The live build functionality of the Projucer has been removed. Possible Issues --------------- You will no longer be able to use live build in the Projucer. Workaround ---------- None. Rationale --------- Keeping the live build compatible with the latest compilers on all our supported platforms is a very substantial maintenance burden, but very few people are using this feature of the Projucer. Removing the live build will simplify the code and our release process. Change ------ `Component::createFocusTraverser()` has been renamed to `Component::createKeyboardFocusTraverser()` and now returns a `std::unique_ptr` instead of a raw pointer. `Component::createFocusTraverser()` is a new method for controlling basic focus traversal and not keyboard focus traversal. Possible Issues --------------- Derived Components that override the old method will no longer compile. Workaround ---------- Override the new method. Be careful to override `createKeyboardFocusTraverser()` and not `createFocusTraverser()` to ensure that the behaviour is the same. Rationale --------- The ownership of this method is now clearer as the previous code relied on the caller deleting the object. The name has changed to accomodate the new `Component::createFocusTraverser()` method that returns an object for determining basic focus traversal, of which keyboard focus is generally a subset. Change ------ PluginDescription::uid has been deprecated and replaced with a new 'uniqueId' data member. Possible Issues --------------- Code using the old data member will need to be updated in order to compile. Workaround ---------- Code that used to use 'uid' to identify plugins should switch to using 'uniqueId', with some caveats - see "Rationale" for details. Rationale --------- The 'uniqueId' member has the benefit of being consistent for a given VST3 across Windows, macOS, and Linux. However, the value of the uniqueId may differ from the value of the old uid on some platforms. The value of the old 'uid' member can now be found in the 'deprecatedUid' member, which should allow clients to implement logic such as checking a saved uid against the new uniqueId, and falling back to the deprecatedUid. This should allow hosts to gracefully upgrade from the old uid values to the new values. Version 6.0.8 ============= Change ------ Calling AudioProcessorEditor::setResizeLimits() will no longer implicitly add a ResizableCornerComponent to the editor if it has not already been set as resizable. Possible Issues --------------- Code which previously relied on calling this method to set up the corner resizer will no longer work. Workaround ---------- Explicitly call AudioProcessorEditor::setResizable() with the second argument set to true to enable the corner resizer. Rationale --------- The previous behaviour was undocumented and potentially confusing. There is now a single method to control the behaviour of the editor's corner resizer to avoid any ambiguity. Change ------ The implementations of `getValue` and `setValue` in `AUInstanceParameter` now properly take the ranges of discrete parameters into account. Possible Issues --------------- This issue affects JUCE Audio Unit hosts. Automation data previously saved for a discrete parameter with a non-zero minimum value may not set the parameter to the same values as previous JUCE versions. Note that previously, `getValue` on a hosted discrete parameter may have returned out-of-range values, and `setValue` may have only mapped to a portion of the parameter range. As a result, automation recorded for affected parameters was likely already behaving unexpectedly. Workaround ---------- There is no workaround. Rationale --------- The old behaviour was incorrect, and was causing issues in plugin validators and other hosts. Hosts expect `getValue` to return a normalised parameter value. If this function returns an out-of-range value (including Inf and NaN) this is likely to break assumptions made by the host, leading to crashes, corrupted project data, or other defects. Change ------ AudioProcessorListener::audioProcessorChanged gained a new parameter describing the nature of any change. Possible Issues --------------- Code using the old function signature will not build until updated to use the new signature. Workaround ---------- Listeners should add the new parameter to any overrides of audioProcessorChanged. Rationale --------- The new function signature means that wrappers can be smarter about the requests that they make to hosts whenever some aspect of the processor changes. In particular, plugin wrappers can now distinguish between changes to latency, parameter attributes, and the current program. This means that hosts will no longer assume parameters have changed when `setLatencySamples` is called. Change ------ CharacterFunctions::readDoubleValue now returns values consistent with other C++ number parsing libraries. Parsing values smaller than the minimum number respresentable in a double will return (+/-)0.0 and parsing values larger than the maximum number respresentable in a double will return (+/-)inf. Possible Issues --------------- Code reading very large or very small numbers may receive values of 0.0 and inf rather than nan. Workaround ---------- Where you may be using std::isnan to check the validity of the result you can instead use std::isfinite. Rationale --------- The new behaviour is consistent with other string parsing libraries. Version 6.0.6 ============= Change ------ The name of `OperatingSystemType::MacOSX_11_0` was changed to `OperatingSystemType::MacOS_11`. Possible Issues --------------- Code using the old name will not build until it is updated to use the new name. Workaround ---------- Update code using the old name to use the new name instead. Rationale --------- Newer versions of macOS have dropped the "X" naming. Minor version updates are also less significant now than they were for the X-series. Change ------ Xcode projects generated using the Projucer will now use the "New Build System" instead of the "Legacy Build System" by default. Possible Issues --------------- Xcode 10.0 - 10.2 has some known issues when using the new build system such as JUCE modules not rebuilding correctly when modified, issue and file navigation not working, and breakpoints not being reliably set or hit. Workaround ---------- If you are using an affected version of Xcode then you can enable the "Use Legacy Build System" setting in the Projucer Xcode exporter to go back to the previous behaviour. Rationale --------- The legacy build system has issues building arm64 binaries for Apple silicon and will eventually be removed altogether. Version 6.0.5 ============= Change ------ New pure virtual methods accepting `PopupMenu::Options` arguments have been added to `PopupMenu::LookAndFeelMethods`. Possible Issues --------------- Classes derived from `PopupMenu::LookAndFeelMethods`, such as custom LookAndFeel classes, will not compile unless these pure virtual methods are implemented. Workaround ---------- The old LookAndFeel methods still exist, so if the new Options parameter is not useful in your application, your implementation of `PopupMenu::LookAndFeelMethods` can simply forward to the old methods. For example, your implementation of `drawPopupMenuBackgroundWithOptions` can internally call your existing `drawPopupMenuBackground` implementation. Rationale --------- Allowing the LookAndFeelMethods to access the popup menu's options allows for more flexible styling. For example, a theme may wish to query the menu's target component or parent for colours to use. Change ------ A typo in the JUCEUtils CMake script that caused the wrong manufacturer code to be set in the compile definitions for a plugin was fixed. Possible Issues --------------- The manufacturer code for plugins built under CMake with this version of JUCE will differ from the manufacturer code that was generated previously. Workaround ---------- If you have released plugins that used the old, incorrect manufacturer code and wish to continue using this code for backwards compatibility, add the following to your `juce_add_plugin` call: USE_LEGACY_COMPATIBILITY_PLUGIN_CODE TRUE In most cases, this should not be necessary, and we recommend using the fixed behaviour. Rationale --------- This change ensures that the manufacturer codes used by CMake projects match the codes that would be generated by the Projucer, improving compatibility when transitioning from the Projucer to CMake. Version 6.0.2 ============= Change ------ The JUCE_WASAPI_EXCLUSIVE flag has been removed from juce_audio_devices and all available WASAPI audio device modes (shared, shared low latency and exclusive) are available by default when JUCE_WASAPI is enabled. The AudioIODeviceType::createAudioIODeviceType_WASAPI() method which takes a single boolean argument has also been deprecated in favour of a new method which takes a WASAPIDeviceMode enum. Possible Issues --------------- Code that relied on the JUCE_WASAPI_EXCLUSIVE flag to disable WASAPI exclusive mode will no longer work. Workaround ---------- Override the AudioDeviceManager::createAudioDeviceTypes() method to omit the WASAPI exclusive mode device if you do not want it to be available. Rationale --------- JUCE now supports shared low latency WASAPI audio devices via the AudioClient3 interface and instead of adding an additional compile time config flag to enable this functionality, which adds complexity to the build process when not using the Projucer, JUCE makes all WASAPI device modes available by default. Change ------ The fields representing Mac OS X 10.4 to 10.6 inclusive have been removed from the `OperatingSystemType` enum. Possible Issues --------------- Code that uses these fields will fail to build. Workaround ---------- Remove references to these fields from user code. Rationale --------- JUCE is not supported on Mac OS X versions lower than 10.7, so it is a given that `getOperatingSystemType` will always return an OS version greater than or equal to 10.7. Code that changes behaviours depending on the OS version can assume that this version is at least 10.7. Change ------ The JUCE_DISABLE_COREGRAPHICS_FONT_SMOOTHING flag in juce_graphics is no longer used on iOS. Possible Issues --------------- Projects with this flag enabled may render differently on iOS. Workaround ---------- There is no workaround. Rationale --------- When using a cached image to render Components with `setBufferedToImage (true)` the result now matches the default behaviour on iOS where fonts are not smoothed. Change ------ Space, return and escape key events on the native macOS menu bar are no longer passed to the currently focused JUCE Component. Possible Issues --------------- Code relying on receiving these keyboard events will no longer work. Workaround ---------- There is no workaround. Rationale --------- It should be possible for users with a keyboard or assistive device to navigate the menu, invoking the currently highlighted menu item with the space or return key and dismissing the menu with the escape key. These key events should not be passed to the application and doing so interferes with the accessibility of JUCE apps. Only passing these events to the native macOS menu means that JUCE apps behave as expected for users. Version 6.0.0 ============= Change ------ The Convolution class interface was changed: - `loadImpulseResponse` member functions now take `enum class` parameters instead of `bool`. - `copyAndLoadImpulseResponseFromBlock` and `copyAndLoadImpulseResponseFromBuffer` were replaced by a new `loadImpulseResponse` overload. Possible Issues --------------- Code using the old interface will no longer compile, and will need to be updated. Workaround ---------- Code that was previously loading impulse responses from binary data or from files can substitute old `bool` parameters with the newer `enum class` equivalents. Code that was previously passing buffers or blocks will need reworking so that the Convolution instance can take ownership of the buffer containing the impulse response. Rationale --------- The newer `enum class` parameters make user code much more readable, e.g. `loadImpulseResponse (file, Stereo::yes, Trim::yes, 0, Normalise::yes)` rather than `loadImpulseResponse (file, true, true, 0, true);`. By taking ownership of the passed buffer, the Convolution can avoid preallocating a large internal buffer, reducing memory usage when short impulse responses are used. Changing the ownership semantics of the buffer also makes it easier for users to avoid copies/allocations on the audio thread, and gives more flexibility to the implementation to run initialisation tasks on a background thread. Change ------ All references to ROLI Ltd. (ROLI) have been changed to Raw Material Software Limited. Possible Issues --------------- Exising projects, particularly Android, may need to be resaved by the Projucer and have the old build artifacts deleted before they will build. Workaround ---------- In Android projects any explicit mention of paths with the from "com.roli.*" should be changed to the form "com.rmsl.*". Rationale --------- This change reflects the change in ownership from ROLI to RMSL. Change ------ The Windows DPI handling in the VST wrapper and hosting code has been refactored to be more stable. Possible Issues --------------- The new code uses a top-level AffineTransform to scale the JUCE editor window instead of native methods. Therefore any AudioProcessorEditors which have their own AffineTransform applied will no longer work correctly. Workaround ---------- If you are using an AffineTransform to scale the entire plug-in window then consider putting the component you want to transform in a child of the editor and transform that instead. Alternatively, if you don't need a separate scale factor for each plug-in instance you can use Desktop::setGlobalScaleFactor(). Rationale --------- The old code had some bugs when using OpenGL and when moving between monitors with different scale factors. The new code should fix these and DPI-aware plug-ins will scale correctly. Change ------ Relative Xcode subproject paths specified in the Projucer are now relative to the build directory rather than the project directory. Possible Issues --------------- After being re-saved in the Projucer existing Xcode projects will fail to find any subprojects specified using a relative path. Workaround ---------- Update the subproject path in the Projucer. Rationale --------- Most other Xcode specific paths are specified reltive to the build directory. This change brings the Xcode subproject path in line with the rest of the configuration. Version 5.4.6 ============= Change ------ AudioProcessorValueTreeState::getRawParameterValue now returns a std::atomic* instead of a float*. Possible Issues --------------- Existing code which explicitly mentions the type of the returned value, or interacts with the dereferenced float in ways unsupported by the std::atomic wrapper, will fail to compile. Certain evaluation-reordering compiler optimisations may no longer be possible. Workaround ---------- Update your code to deal with a std::atomic* instead of a float*. Rationale --------- Returning a std::atomic* allows the JUCE framework to have much stronger guarantees about thread safety. Change ------ Removed a workaround from the ASIOAudioIODevice::getOutputLatencyInSamples() and ASIOAudioIODevice::getInputLatencyInSamples() methods which was adding an arbitrary amount to the reported latencies to compensate for dodgy, old drivers. Possible Issues --------------- Code which relied on these altered values may now behave differently. Workaround ---------- Update your code to deal with the new, correct values reported from the drivers directly. Rationale --------- JUCE will now return the latency values as reported by the drivers without adding anything to them. The workaround was for old drivers and the current drivers should report the correct values without the need for the workaround. Change ------ The default behaviour of the AU and AUv3 plug-in wrappers is now to call get/setStateInformation instead of get/setProgramStateInformation. Possible Issues --------------- AudioProcessor subclasses which have overridden the default implementations of get/setProgramStateInformation (which simply call through to get/setStateInformation) may be unable to load previously saved state; state previously saved via a call to getProgramStateInformation will be presented to setStateInformation. Workaround ---------- Enable the JUCE_AU_WRAPPERS_SAVE_PROGRAM_STATES configuration option in the juce_audio_plugin_client module to preserve backwards compatibility if required. Rationale --------- When using overridden get/setProgramStateInformation methods the previous behaviour of the AU and AUv3 wrappers does not correctly save and restore state. Version 5.4.5 ============= Change ------ The alignment of text rendered on macOS using CoreGraphics may have shifted slightly, depending on the font you have used. The default macOS font has shifted downwards. Possible Issues --------------- Meticulously aligned text components of a GUI may now be misaligned. Workaround ---------- Use a custom LookAndFeel to change the location where text is drawn, or use a different font that matches the previous alignment of your original font. Rationale --------- This was an unintentional change resulting from moving away from a deprecated macOS text API. The new alignment is consistent with other rendering engines (web browsers and text editors) and the software renderer. Change ------ The JUCEApplicationBase::backButtonPressed() method now returns a bool to indicate whether the back event was handled or not. Possible Issues --------------- Applications which override this method will fail to compile. Workaround ---------- You will need to update your code to return a bool indicating whether the back event was handled or not. Rationale --------- The back button behaviour on Android was previously broken as it would not do anything. The new code will correctly call finish() on the Activity when the back button is pressed but this method now allows the user to override this to implement their own custom navigation behaviour by returning true to indicate that it has been handled. Change ------ The AudioBlock class has been refactored and some of the method names have changed. Additionally the `const` behaviour now mirrors that of `std::span`, with the `const`-ness of the contained data decoupled from the `const`-ness of the container. Possible Issues --------------- Code using the old method names or violating `const`-correctness will fail to compile. Workaround ---------- You will need to update your code to use the new method names and select an appropriate `const`-ness for the AudioBlock and the data it references. Rationale --------- The names of some of the methods in the AudioBlock class were ambiguous, particularly when chaining methods involving references to other blocks. The interaction between the `const`-ness of the AudioBlock and the `const`-ness of the referenced data was also ambiguous and has now been standardised to the same behaviour as other non-owning data views like `std::span`. Version 5.4.4 ============= Change ------ The Visual Studio 2013 exporter has been removed from the Projucer and we will no longer maintain backwards compatibility with Visual Studio 2013 in JUCE. Possible Issues --------------- It is no longer possible to create Visual Studio 2013 projects from the Projucer or compile JUCE-based software using Visual Studio 2013. Workaround ---------- If you are using Visual Studio 2013 to build your projects you will need to update to a more modern version of Visual Studio. Rationale --------- Of all the platforms JUCE supports Visual Studio 2013 was holding us back the most in terms of C++ features we would like to use more broadly across the codebase. It is still possible to target older versions of Windows with more modern versions of Visual Studio. Until recently the AAX SDK was distributed as a Visual Studio 2013 project, but this is now provided as a Visual Studio 2017 project. Change ------ JUCE is moving towards using C++11 pointer container types instead of passing raw pointers as arguments and return values. Possible Issues --------------- You will need to change your code to pass std::unique_ptr into and out of various functions across JUCE's API. Workaround ---------- None Rationale --------- Indicating ownership through the transfer of smart pointer types has been part of mainstream C++ for a long time and this change enforces memory safety by default in most situations. Change ------ SystemTrayIconComponent::setIconImage now takes two arguments, rather than one. The new argument is a template image for use on macOS where all non-transparent regions will render in a monochrome colour determined dynamically by the operating system. Possible Issues --------------- You will now need to provide two images to display a SystemTrayIconComponent and the SystemTrayIconComponent will have a different appearance on macOS. Workaround ---------- If you are not targeting macOS then you can provide an empty image, `{}`, for the second argument. If you are targeting macOS then you will likely need to design a new monochrome icon. Rationale --------- The introduction of "Dark Mode" in macOS 10.14 means that menu bar icons must support several different colours and highlight modes to retain the same appearance as the native Apple icons. Doing this correctly without delegating the behaviour to the operating system is extremely cumbersome, and the APIs we were previously using to interact with menu bar items have been deprecated. Change ------ The AudioBlock class now differentiates between const and non-const data. Possible Issues --------------- The return type of the getInputBlock() method of the ProcessContextReplacing and ProcessContextNonReplacing classes has changed from AudioBlock to AudioBlock. Workaround ---------- For ProcessContextReplacing you should use getOutputBlock() instead of getInputBlock(). For ProcessContextNonReplacing attempting to modify the input block is very likely an error. Rationale --------- This change makes the intent of the code much clearer and means that we can remove some const_cast operations. Change ------ The formatting of floating point numbers written to XML and JSON files has changed. Note that there is no change in precision - the XML and JSON files containing the new format numbers will parse in exactly the same way, it is only the string representation that has changed. Possible Issues --------------- If you rely upon exactly reproducing XML or JSON files then the new files may be different. Workaround ---------- Update any reference XML or JSON files to use the new format. Rationale --------- The new format retains full precision, provides a human friendly representation of values near 1, and uses scientific notation for small and large numbers. This prevents needless file size bloat from numbers like 0.00000000000000001. Version 5.4.3 ============= Change ------ The global user module path setting in the Projucer can now only contain a single path. Possible Issues --------------- Projects that previously relied on using multiple global user module paths separated by a semicolon will fail to find these modules after re-saving. Workaround ---------- Replace the multiple paths with a single global user module path. Rationale --------- Using multiple global user module paths did not work when saving a project which exported to different OSes. Only allowing a single path will prevent this from silently causing issues. Version 5.4.2 ============= Change ------ The return type of Block::getBlockAreaWithinLayout() has been changed from Rectangle to a simpler BlockArea struct. Possible Issues --------------- Classes that derive from Block and implement this pure virtual method will no longer compile due to a change in the function signature. Workaround ---------- Update the method to return a BlockArea struct and update code that calls getBlockAreaWithinLayout to handle a BlockArea instead of a Rectangle. Rationale --------- The juce_blocks_basics is ISC licensed and therefore cannot depend on the GPL/Commercial licensed juce_graphics module that contains Rectangle. Change ------ Renaming and deletion of open file handles on Windows is now possible using the FILE_SHARE_DELETE flag. Possible Issues --------------- Previous code that relied on open files not being able to be renamed or deleted on Windows may fail. Workaround ---------- No workaround. Rationale --------- This unifies the behaviour across OSes as POSIX systems already allow this. Change ------ Multiple changes to low-level, non-public JNI and Android APIs. Possible Issues --------------- If you were using any non-public, low-level JNI macros, calling java code or recieving JNI callbacks, then your code will probably no longer work. See the forum for further details. Workaround ---------- See the forum for further details. Rationale --------- See the forum for further details. Change ------ The minimum Android version for a JUCE app is now Android 4.1 Possible Issues --------------- Your app may not run on very old versions of Android (less than 0.5% of the devices). Workaround ---------- There is no workaround. Rationale --------- Less than 0.5% of all devices in the world run versions of Android older than Android 4.1. In the interest of keeping JUCE code clean and lean, we must depricate support for very old Android versions from time to time. Version 5.4.0 ============= Change ------ The use of WinRT MIDI functions has been disabled by default for any version of Windows 10 before 1809 (October 2018 Update). Possible Issues --------------- If you were previously using WinRT MIDI functions on older versions of Windows then the new behaviour is to revert to the old Win32 MIDI API. Workaround ---------- Set the preprocessor macro JUCE_FORCE_WINRT_MIDI=1 (in addition to the previously selected JUCE_USE_WINRT_MIDI=1) to allow the use of the WinRT API on older versions of Windows. Rationale --------- Until now JUCE's support for the Windows 10 WinRT MIDI API was experimental, due to longstanding issues within the API itself. These issues have been addressed in the Windows 10 1809 (October 2018 Update) release. Change ------ The VST2 SDK embedded within JUCE has been removed. Possible Issues --------------- 1. Building or hosting VST2 plug-ins requires header files from the VST2 SDK, which is no longer part of JUCE. 2. Building a VST2-compatible VST3 plug-in (the previous default behaviour in JUCE) requires header files from the VST2 SDK, which is no longer part of JUCE. Workaround ---------- 1. The VST2 SDK can be obtained from the vstsdk3610_11_06_2018_build_37 (or older) VST3 SDK or JUCE version 5.3.2. You should put the VST2 SDK in your header search paths or use the "VST (Legacy) SDK Folder" fields in the Projucer. 2. For new plug-in projects where you will be releasing both a VST2 and VST3 version, and you want the VST3 plug-in to replace the VST2 plug-in in hosts that support it, then you should enable the JUCE_VST3_CAN_REPLACE_VST2 option. 3. When a new JUCE plug-in project is created the value of JUCE_VST3_CAN_REPLACE_VST2 will be set to zero. Rationale --------- Distributing VST2 plug-ins requires a VST2 license from Steinberg. Following Steinberg's removal of the VST2 SDK from their public SDKs we are also removing the VST2 SDK from the JUCE codebase. Change ------ The AudioProcessorValueTreeState::createAndAddParameter function has been deprecated. Possible Issues --------------- Deprecation warnings will be seen when compiling code which uses this function and eventually builds will fail when it is later removed from the API. Workaround ---------- Previous calls to createAndAddParameter (paramID, paramName, ...); can be directly replaced with using Parameter = AudioProcessorValueTreeState::Parameter; createAndAddParameter (std::make_unique (paramID, paramName, ...)); but an even better approach is to use the new AudioProcessorValueTreeState constructor where you can pass both RangedAudioParameters and AudioProcessorParameterGroups of RangedAudioParameters to the AudioProcessorValueTreeState and initialise the ValueTree simultaneously. Rationale --------- The new createAndAddParameter method is much more flexible and enables any parameter types derived from RangedAudioParameter to be managed by the AudioProcessorValueTreeState. Change ------ The Projucer's per-exporter Android SDK/NDK path options have been removed. Possible Issues --------------- Projects that previously used these fields may no longer build. Workaround ---------- Use the Projucer's global paths settings to point to these directories, either by opening the "Projucer/File->Global Paths..." menu item or using the "--set-global-search-path" command-line option. Rationale --------- Having multiple places where the paths could be set was confusing and could cause unexpected mismatches. Change ------ SystemStats::getDeviceDescription() will now return the device code on iOS e.g. "iPhone7, 2" for an iPhone 6 instead of just "iPhone". Possible Issues --------------- Code that previously relied on this method returning either explicitly "iPhone" or "iPad" may no longer work. Workaround ---------- Modify this code to handle the new device code string e.g. by changing: SystemStats::getDeviceDescription() == "iPhone"; to SystemStats::getDeviceDescription().contains ("iPhone");. Rationale --------- The exact device model can now be deduced from this information instead of just the device family. Change ------ DragAndDropContainer::performExternalDragDropOfFiles() and ::performExternalDragDropOfText() are now asynchronous on Windows. Possible Issues --------------- Code that previously relied on these operations being synchronous and blocking until completion will no longer work as the methods will return immediately and run asynchronously. Workaround ---------- Use the callback argument that has been added to these methods to register a lambda that will be called when the operation has been completed. Rationale --------- The behaviour of these methods is now consistent across all platforms and the method no longer blocks the message thread on Windows. Change ------ AudioProcessor::getTailLengthSeconds can now return infinity for VST/VST3/AU/AUv3. Possible Issues --------------- If you are using the result of getTailLengthSeconds to allocate a buffer in your host, then your host will now likely crash when loading a plug-in with an infinite tail time. Workaround ---------- Rewrite your code to not use the result of getTailLengthSeconds directly to allocate a buffer. Rationale --------- Before this change there was no way for a JUCE plug-in to report an infinite tail time. Version 5.3.2 ============= Change ------ The behaviour of an UndoManager used by an AudioProcessorValueTreeState has been improved. Possible Issues --------------- If your plug-in contains an UndoManager used by an AudioProcessorValueTreeState and relies upon the old behaviour of the UndoManager then it is possible that the new behaviour is no longer appropriate for your use case. Workaround ---------- Use an external UndoManager to reproduce the old behaviour manually. Rationale --------- This change fixes a few bugs in the behaviour of an UndoManager used by an AudioProcessorValueTreeState. Change ------ JUCE no longer supports OS X deployment targets earlier than 10.7. Possible Issues --------------- If you were previously targeting OS X 10.5 or 10.6 you will no longer be able to build JUCE-based products compatible with those platforms. Workaround ---------- None. With the appropriate JUCE licence you may be able to backport new JUCE features, but there will be no official support for this. Rationale --------- Increasing the minimum supported OS X version allows the JUCE codebase to make use of the more modern C++ features found in the 10.7 standard library, which in turn will increase thread and memory safety. Version 5.3.0 ============= Change ------ The JUCE examples have been cleaned up, modernised and converted into PIPs (Projucer Instant Projects). The JUCE Demo has been removed and replaced by the DemoRunner application and larger projects such as the Audio Plugin Host and the Network Graphics Demo have been moved into the extras directory. Possible Issues --------------- 1. Due to the large number of changes that have occurred in the JUCE Git repository, pulling this version may result in a messy folder structure with empty directories that have been removed. 2. The JUCE Demo project is no longer in the JUCE repository. 3. The Audio Plugin Host project has moved from the examples directory to the extras directory. Workaround ---------- 1. Run a Git clean command (git clean -xdf) in your JUCE directory to remove all untracked files, directories and build products. 2. The new DemoRunner application, located in extras/DemoRunner, can be used to preview all the JUCE examples and see the code side-by-side. 3. Change any file paths that depended on the plugin host project being located in the examples directory to use the extras directory instead. Rationale --------- The JUCE examples had inconsistent naming, coding styles and the projects and build products took up a large amount of space in the repository. Replacing them with PIPs reduces the file size and allows us to categorise the examples better, as well as cleaning up the code. Change ------ When hosting plug-ins all AudioProcessor methods of managing parameters that take a parameter index as an argument have been deprecated. Possible Issues --------------- A single assertion will be fired in debug builds on the first use of a deprecated function. Workaround ---------- When hosting plug-ins you should use the AudioProcessor::getParameters() method and interact with parameters via the returned array of AudioProcessorParameters. For a short-term fix you can also continue past the assertion in your debugger, or temporarily modify the JUCE source code to remove it. Rationale --------- Given the structure of JUCE's API it is impossible to deprecate these functions using only compile-time messages. Therefore a single assertion, which can be safely ignored, serves to indicate that these functions should no longer be used. The move away from the AudioProcessor methods both improves the interface to that class and makes ongoing development work much easier. Change ------ This InAppPurchases class is now a JUCE Singleton. This means that you need to get an instance via InAppPurchases::getInstance(), instead of storing a InAppPurchases object yourself. Possible Issues --------------- Any code using InAppPurchases needs to be updated to retrieve a singleton pointer to InAppPurchases. Workaround ---------- Instead of holding a InAppPurchase member yourself, you should get an instance via InAppPurchases::getInstance(), e.g. instead of: InAppPurchases iap; iap.purchaseProduct (...); call: InAppPurchases::getInstance()->purchaseProduct (...); Rationale --------- This change was required to fix an issue on Android where on failed transaction a listener would not get called. Change ------ JUCE's MPE classes have been updated to reflect the official specification recently approved by the MIDI Manufacturers Association (MMA). Possible Issues --------------- The most significant changes have occurred in the MPEZoneLayout classes and programs using the higher level MPE classes such as MPEInstrument, MPESynthesiser, MPESynthesiserBase and MPESynthesiserVoice should be unaffected. Previously, any MIDI channel from 1 - 15 could be selected to be the master channel of an MPE zone, with a specified number of member channels ascending from the master channel + 1. However, in the new specification this has been simplified so that a device only has a lower and/or an upper zone, where the lower zone has master channel 1 and assigns new member channels ascending from channel 2 and the upper zone has master channel 16 and assigns new member channels descending from channel 15. Workaround ---------- Use the MPEZoneLayout::setLowerZone() and MPEZoneLayout::setUpperZone() methods to set zone layouts. Any UI that allows users to select and set zones on an MPE instrument should also be updated to reflect the specification changes. Rationale --------- The MPE classes in JUCE are out of date and should be updated to reflect the new, official MPE standard. Version 5.2.1 ============= Change ------ Calling JUCEApplicationBase::quit() on Android will now really quit the app, rather than just placing it in background. Starting with API level 21 (Android 5.0), the app will not appear in recent apps list after calling quit(). Prior to API 21, the app will still appear in recent app lists but when a user chooses the app, a new instance of the app will be started. Possible Issues --------------- Any code calling JUCEApplicationBase::quit() to place the app in background will close the app instead. Workaround ---------- Use Process::hide(). Rationale --------- The old behaviour JUCEApplicationBase::quit() was confusing JUCE code, as a new instance of JUCE app was attempted to be created, while the older instance was still running in background. This would result in assertions when starting a second instance. Change ------ On Windows, release builds will now link to the dynamic C++ runtime by default Possible Issues --------------- If you are creating a new .jucer project, then your plug-in will now link to the dynamic C++ runtime by default, which means that you MUST ensure that the C++ runtime libraries exist on your customer's computers. Workaround ---------- If you are only targeting Windows 10, then the C++ runtime is now part of the system core components and will always exist on the computers of your customers (just like kernel332.dll, for example). If you are targeting Windows versions between Vista and Windows 10, then you should build your plug-in with the latest updated version of VS2015 or later, which ensures that it's linked to the universal runtime. Universal runtime is part of the system's core libraries on Windows 10 and on Windows versions Vista to 8.1, it will be available on your customer's computers via Windows Update. Unfortunately, if your customer has just installed Windows 8.1 to Vista on a fresh computer, then there is a chance that the update mechanism for the universal runtime hasn't triggered yet and your plug-in may still fail. Your installer should prompt the user to install all the Windows updates in this case or you can deploy the universal runtime as a redistributable with your installer. If you are targeting earlier versions of Windows then you should always include the runtime as a redistributable with your plug-in's installer. Alternatively, you can change the runtime linking to static (however, see 'Rationale' section). Rationale --------- In a recent update to Windows 10, Microsoft has limited the number of fiber local storage (FLS) slots per process. Effectively, this limits how many plug-ins with static runtime linkage can be loaded into a DAW. In the worst case, this limits the total number of plug-ins to a maximum of 64 plug-ins. There is no workaround for DAW vendors and the only solution is to push plug-in vendors to use the dynamic runtime. To help with this, JUCE has decided to make dynamic runtime linkage the default in JUCE. Change ------ AudioProcessorGraph interface has changed in a number of ways - Node objects are now reference counted, there are different accessor methods to iterate them, and misc other small improvements to the API Possible Issues --------------- The changes won't cause any silent errors in user code, but will require some manual refactoring Workaround ---------- Just find equivalent new methods to replace existing code. Rationale --------- The graph class was extremely old and creaky, and these changes is the start of an improvement process that should eventually result in it being broken down into fundamental graph building block classes for use in other contexts. Version 5.2.0 ============= Change ------ Viewport now enables "scroll on drag" mode by default on Android and iOS. Possible Issues --------------- Any code relying on "scroll on drag" mode being turned off by default, should disable it manually. Workaround ---------- None. Rationale --------- It is expected on mobile devices to be able to scroll a list by just a drag, rather than using a dedicated scrollbar. The scrollbar is still available though if needed. Change ------ The previous setting of Android exporter "Custom manifest xml elements" creating child nodes of element has been replaced by "Custom manifest XML content" setting that allows to specify the content of the entire manifest instead. Any previously values of the old setting will be used in the new setting by default, and they will need changing as mentioned in Workaround. The custom content will be merged with the content auto-generated by Projucer. Any custom elements or custom attributes will override the ones set by Projucer. Projucer will also automatically add any missing and required elements and attributes. Possible Issues --------------- If a Projucer project used "Custom manifest xml elements" field, the value will no longer be compatible with the project generated in the latest Projucer version. The solution is very simple and quick though, as mentioned in the Workaround section. Workaround ---------- For any elements previously used, simply embed them explicitly in elements, for example instead of: simply write: Rationale --------- To maintain the high level of flexibility of generated Android projects and to avoid creating fields in Projucer for every possible future parameter, it is simpler to allow to set up the required parameters manually. This way it is not only possible to add any custom elements but it is also possible to override the default attributes assigned by Projucer for the required elements. For instance, if the default value of element is not satisfactory because you want a support for x-large screens only, simply set "Custom manifest XML content" to: Version 5.1.2 ============= Change ------ The method used to classify AudioUnit, VST3 and AAX plug-in parameters as either continuous or discrete has changed, and AudioUnit and AudioUnit v3 parameters are marked as high precision by default. Possible Issues --------------- Plug-ins: DAW projects with automation data written by an AudioUnit, AudioUnit v3 VST3 or AAX plug-in built with JUCE version 5.1.1 or earlier may load incorrectly when opened by an AudioUnit, AudioUnit v3, VST3 or AAX plug-in built with JUCE version 5.1.2 and later. Hosts: The AudioPluginInstance::getParameterNumSteps method now returns correct values for AU and VST3 plug-ins. Workaround ---------- Plug-ins: Enable JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE in the juce_audio_plugin_client module config page in the Projucer. Hosts: Use AudioPluginInstance::getDefaultNumParameterSteps as the number of steps for all parameters. Rationale --------- The old system for presenting plug-in parameters to a host as either continuous or discrete is inconsistent between plug-in types and lacks sufficient flexibility. This change harmonises the behaviour and allows individual parameters to be marked as continuous or discrete. If AudioUnit and AudioUnit v3 parameters are not marked as high precision then hosts like Logic Pro only offer a limited number of parameter values, which again produces different behaviour for different plug-in types. Change ------ A new FrameRateType fps23976 has been added to AudioPlayHead, Possible Issues --------------- Previously JUCE would report the FrameRateType fps24 for both 24 and 23.976 fps. If your code uses switch statements (or similar) to handle all possible frame rate types, then this change may cause it to fall through. Workaround ---------- Add fps23976 to your switch statement and handle it appropriately. Rationale --------- JUCE should be able to handle all popular frame rate codes but was missing support for 23.976. Change ------ The String (bool) constructor and operator<< (String&, bool) have been explicitly deleted. Possible Issues --------------- Previous code which relied on an implicit bool to int type conversion to produce a String will not compile. Workaround ---------- Cast your bool to an integer to generate a string representation of it. Rationale --------- Letting things implicitly convert to bool to produce a String opens the door to all kinds of nasty type conversion edge cases. Furthermore, before this change, MacOS would automatically convert bools to ints but this wouldn't occur on different platform. Now the behaviour is consistent across all operating systems supported by JUCE. Change ------ The writeAsJSON virtual method of the DynamicObject class requires an additional parameter, maximumDecimalPlaces, to specify the maximum precision of floating point numbers. Possible Issues --------------- Classes which inherit from DynamicObject and override this method will need to update their method signature. Workaround ---------- Your custom DynamicObject class can choose to ignore the additional parameter if you don't wish to support this behaviour. Rationale --------- When serialising the results of calculations to JSON the rounding of floating point numbers can result in numbers with 17 significant figures where only a few are required. This change to DynamicObject is required to support truncating those numbers. Version 5.1.0 ============= Change ------ The JUCE_COMPILER_SUPPORTS_LAMBDAS preprocessor macro has been removed. Possible Issues --------------- If your project is using JUCE_COMPILER_SUPPORTS_LAMBDAS in your source code then it will likely evaluate to "false" and you could end up unnecessarily using code paths which avoid lambda functions. Workaround ---------- Remove the usage of JUCE_COMPILER_SUPPORTS_LAMBDAS from your code. Rationale --------- Lambda functions are now available on all platforms that JUCE supports. Change ------ The option to set the C++ language standard is now located in the project settings instead of the build configuration settings. Possible Issues --------------- Projects that had a specific version of the C++ language standard set for exporter build configurations will instead use the default (C++11) when re-saving with the new Projucer. Workaround ---------- Change the "C++ Language Standard" setting in the main project settings to the required version - the Projucer will add this value to the exported project as a compiler flag when saving exporters. Rationale --------- Having a different C++ language standard option for each build configuration was unnecessary and was not fully implemented for all exporters. Changing it to a per-project settings means that the preference will propagate to all exporters and only needs to be set in one place. Change ------ PopupMenus now scale according to the AffineTransform and scaling factor of their target components. Possible Issues --------------- Developers who have manually scaled their PopupMenus to fit the scaling factor of the parent UI will now have the scaling applied two times in a row. Workaround ---------- 1. Do not apply your own manual scaling to make your popups match the UI scaling or 2. Override the Look&Feel method PopupMenu::LookAndFeelMethods::shouldPopupMenuScaleWithTargetComponent and return false. See https://github.com/juce-framework/JUCE/blob/c288c94c2914af20f36c03ca9c5401fcb555e4e9/modules/juce_gui_basics/menus/juce_PopupMenu.h#725 Rationale --------- Previously, PopupMenus would not scale if the GUI of the target component (or any of it’s parents) were scaled. The only way to scale PopupMenus was via the global scaling factor. This had several drawbacks as the global scaling factor would scale everything. This was especially problematic in plug-in editors. Change ------ Removed the setSecurityFlags() method from the Windows implementation of WebInputStream as it disabled HTTPS security features. Possible Issues --------------- Any code previously relying on connections to insecure webpages succeeding will no longer work. Workaround ---------- Check network connectivity on Windows and re-write any code that relied on insecure connections. Rationale --------- The previous behaviour resulted in network connections on Windows having all the HTTPS security features disabled, exposing users to network attacks. HTTPS connections on Windows are now secure and will fail when connecting to an insecure web address. Change ------ Pointer arithmetic on a pointer will have the same result regardless if it is wrapped in JUCE's Atomic class or not. Possible Issues --------------- Any code using pointer arithmetic on Atomic will now have a different result leading to undefined behaviour or crashes. Workaround ---------- Re-write your code in a way that it does not depend on your pointer being wrapped in JUCE's Atomic or not. See rationale. Rationale --------- Before this change, pointer arithmetic with JUCE's Atomic type would yield confusing results. For example, the following code would assert before this change: int* a; Atomic b; jassert (++a == ++b); Pointer a in the above code would be advanced by sizeof(int) whereas the JUCE's Atomic always advances it's underlying pointer by a single byte. The same is true for operator+=/operator-= and operator--. The difference in behaviour is confusing and unintuitive. Furthermore, this aligns JUCE's Atomic type with std::atomic. Version 4.3.1 ============= Change ------ JUCE has changed the way native VST3/AudioUnit parameter ids are calculated. Possible Issues --------------- DAW projects with automation data written by an AudioUnit or VST3 plug-in built with pre JUCE 4.3.1 versions will load incorrectly when opened by an AudioUnit or VST3 built with JUCE versions 4.3.1 and later. Plug-ins using JUCE_FORCE_USE_LEGACY_PARAM_IDS are not affected. Workaround ---------- Disable JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS in the juce_audio_plugin_client module config page in the Projucer. For new plug-ins, be sure to use the default value for this property. Rationale -------- JUCE needs to convert between its own JUCE parameter id format (strings) to the native parameter id formats of the various plug-in backends. For VST3 and AudioUnits, JUCE uses a hash function to generate a numeric id. However, some VST3/AudioUnit hosts (specifically Studio One) have a bug that ignore any parameters that have a negative parameter id. Therefore, the hash function for VST3/AudioUnits needed to be changed to only return positive-valued hashes. Version 4.3.0 ============= Change ------ A revised multi-bus API was released which supersedes the previously flawed multi-bus API - JUCE versions 4.0.0 - 4.2.4 (inclusive). Possible Issues --------------- If you have developed a plug-in with JUCE versions 4.0.0 - 4.2.4 (inclusive), then you will need to update your plug-in to the new multi-bus API. Pre JUCE 4.0.0 plug-ins are not affected apart from other breaking changes listed in this document. Woraround --------- None. Rationale -------- A flawed multi-bus API was introduced with JUCE versions 4.0.0 up until version 4.2.4 (inclusive) which was not API compatible with pre JUCE 4 plug-ins. JUCE 4.3.0 releases a revised multi-bus API which restores pre JUCE 4 API compatibility. However, the new multi-bus API is not compatible with the flawed multi-bus API (JUCE version 4.0.0 - 4.2.4). Change ------ JUCE now generates the AAX plug-in bus layout configuration id independent from the position as it appears in the Projucer’s legacy "Channel layout configuration" field. Possible Issues --------------- ProTools projects generated with a < 4.3.0 JUCE versions of your plug-in, may load the incorrect bus configuration when upgrading your plug-in to >= 4.3.0 versions of JUCE. Workaround ---------- Implement AudioProcessor’s getAAXPluginIDForMainBusConfig callback to manually override which AAX plug-in id is associated to a specific bus layout of your plug-in. This workaround is only necessary if you have released your plug-in built with a version previous to JUCE 4.3.0. Rationale -------- The new multi-bus API offers more features, flexibility and accuracy in specifying bus layouts which cannot be expressed by the Projucer’s legacy "Channel layout configuration" field. The native plug-in format backends use the new multi-bus callback APIs to negotiate channel layouts with the host - including the AAX plug-in ids assigned to specific bus layouts. With the callback API, there is no notion of an order in which the channel configurations appear - as was the case with the legacy "Channel layout configuration" field - and therefore cannot be used to generate the AAX plug-in id. To remain backward compatible to pre JUCE 4.0.0 plug-ins, JUCE does transparently convert the legacy "Channel layout configuration" field to the new callback based multi-bus API, but this does not take the order into account in which the channel configurations appear in the legacy "Channel layout configuration" field. Version 4.2.1 ============= Change ------ JUCE now uses the paramID property used in AudioProcessorParameterWithID to uniquely identify parameters to the host. Possible Issues --------------- DAW projects with automation data written by an audio plug-in built with pre JUCE 4.2.1 will load incorrectly when opened by an audio plug-in built with JUCE 4.2.1 and later. Workaround ---------- Enable JUCE_FORCE_USE_LEGACY_PARAM_IDS in the juce_audio_plugin_client module config page in the Projucer. For new plug-ins, be sure to disable this property. Rationale -------- Each parameter of the AudioProcessor has an id associated so that the plug-in’s host can uniquely identify parameters. The id has a different data-type for different plug-in types (for example VST uses integers, AAX uses string identifiers). Before 4.2.1, JUCE generated the parameter id by using the index of the parameter, i.e. the first parameter had id zero, the second parameter had id one, etc. This caused problems for certain plug-in types where JUCE needs to add internal parameters to the plug-in (for example VST3 requires the bypass control to be a parameter - so JUCE automatically creates this parameter for you in the VST3 backend). This causes subtle problems if a parameter is added to an update of an already published plug-in. The new parameter’s id would be identical to the id of the bypass parameter in old versions of your plug-in, causing seemingly random plug-in bypass behaviour when user’s upgrade their plug-in. Most plug-in backends differentiate between a parameter’s id an index, so this distinction was adopted starting with JUCE 4.2.1 by deriving the parameter’s unique id from the paramID property of AudioProcessorParameterWithID class.