diff --git a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt index 35379d7a5e..6a032fa594 100644 --- a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt +++ b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt @@ -748,6 +748,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/uid.h" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstcomponent.cpp" @@ -3263,6 +3265,8 @@ set_source_files_properties( "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/uid.h" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstcomponent.cpp" diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj index d34954a154..f80394e608 100644 --- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj @@ -947,6 +947,9 @@ true + + true + true @@ -3552,6 +3555,7 @@ + diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters index 243b2c5399..8a42e5619d 100644 --- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters @@ -1639,6 +1639,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst @@ -5250,6 +5253,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst diff --git a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj index b862217d2c..7b3c5bc01a 100644 --- a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj @@ -947,6 +947,9 @@ true + + true + true @@ -3552,6 +3555,7 @@ + diff --git a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters index 0d8aaf63bc..0269f158b0 100644 --- a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters @@ -1639,6 +1639,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst @@ -5250,6 +5253,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst diff --git a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt index 682db777df..d14a0bf159 100644 --- a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt +++ b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt @@ -703,6 +703,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/uid.h" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstcomponent.cpp" @@ -2901,6 +2903,8 @@ set_source_files_properties( "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/uid.h" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstcomponent.cpp" diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj index bb4feb7fec..723a414e57 100644 --- a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj +++ b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj @@ -907,6 +907,9 @@ true + + true + true @@ -3124,6 +3127,7 @@ + diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters index 6ee29f4608..d9891e52d2 100644 --- a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters +++ b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters @@ -1456,6 +1456,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst @@ -4608,6 +4611,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst diff --git a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt index b4b8f706f5..9e780dd435 100644 --- a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt +++ b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt @@ -736,6 +736,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/uid.h" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstcomponent.cpp" @@ -3087,6 +3089,8 @@ set_source_files_properties( "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/uid.h" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstcomponent.cpp" diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj index bc03d70f9f..0e15fa3ef8 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj @@ -915,6 +915,9 @@ true + + true + true @@ -3304,6 +3307,7 @@ + diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters index 116cf3c080..c9c303abc8 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters @@ -1531,6 +1531,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst @@ -4884,6 +4887,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst diff --git a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj index 6ddce8d84f..8defa769a0 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj @@ -915,6 +915,9 @@ true + + true + true @@ -3304,6 +3307,7 @@ + diff --git a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters index 08e12d981f..00323eac0b 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters @@ -1531,6 +1531,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst @@ -4884,6 +4887,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst diff --git a/extras/Build/CMake/JUCEHelperTargets.cmake b/extras/Build/CMake/JUCEHelperTargets.cmake index 30ed5284fd..e7002ae1c7 100644 --- a/extras/Build/CMake/JUCEHelperTargets.cmake +++ b/extras/Build/CMake/JUCEHelperTargets.cmake @@ -99,6 +99,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") -Wno-implicit-fallthrough -Wno-maybe-uninitialized -Wno-ignored-qualifiers + -Wno-multichar -Wswitch-enum -Wredundant-decls -Wno-strict-overflow diff --git a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt index 984b630ad2..8c6cb29e72 100644 --- a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt +++ b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt @@ -707,6 +707,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/uid.h" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstcomponent.cpp" @@ -2985,6 +2987,8 @@ set_source_files_properties( "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/stringconvert.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/uid.h" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp" + "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.cpp" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstbus.h" "../../../../../modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/vstcomponent.cpp" diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj index 3569fecde8..dbd231cf59 100644 --- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj +++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj @@ -907,6 +907,9 @@ true + + true + true @@ -3215,6 +3218,7 @@ + diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters index 259e43ed02..8540038cb4 100644 --- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters +++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters @@ -1486,6 +1486,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst @@ -4749,6 +4752,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp index 5e91e9bfe7..4b298ffc3a 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp @@ -954,6 +954,7 @@ ProjectExporter::BuildConfiguration::BuildConfiguration (Project& p, const Value "-Wno-maybe-uninitialized", "-Wredundant-decls", "-Wno-strict-overflow", + "-Wno-multichar", "-Wshadow" }); } diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj index 47d67d5b44..b29b374f90 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj +++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj @@ -923,6 +923,9 @@ true + + true + true @@ -3400,6 +3403,7 @@ + diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters index 43aedc6ab7..557924d8bf 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters +++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters @@ -1552,6 +1552,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst @@ -4998,6 +5001,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst diff --git a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj index 3159363a5a..c5f60508cd 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj +++ b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj @@ -923,6 +923,9 @@ true + + true + true @@ -3400,6 +3403,7 @@ + diff --git a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters index f2c1c612b7..977ae82575 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters +++ b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters @@ -1552,6 +1552,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst @@ -4998,6 +5001,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst diff --git a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj index 283f2ea7c9..7a022809df 100644 --- a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj +++ b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj @@ -906,6 +906,9 @@ true + + true + true @@ -3191,6 +3194,7 @@ + diff --git a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj.filters b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj.filters index 5c908a7ecc..7ea6ca93da 100644 --- a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj.filters +++ b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj.filters @@ -1483,6 +1483,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst @@ -4716,6 +4719,9 @@ JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\utility + JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst diff --git a/modules/juce_audio_plugin_client/detail/juce_PluginUtilities.h b/modules/juce_audio_plugin_client/detail/juce_PluginUtilities.h index c73ef16a79..1e7744f94c 100644 --- a/modules/juce_audio_plugin_client/detail/juce_PluginUtilities.h +++ b/modules/juce_audio_plugin_client/detail/juce_PluginUtilities.h @@ -66,10 +66,6 @@ struct PluginUtilities return hostType; } - #ifndef JUCE_VST3_CAN_REPLACE_VST2 - #define JUCE_VST3_CAN_REPLACE_VST2 1 - #endif - // NB: Nasty old-fashioned code in here because it's copied from the Steinberg example code. static void getUUIDForVST2ID (bool forControllerUID, uint8 uuid[16]) { diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp index 568d0c6778..db7eea776a 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp @@ -64,24 +64,6 @@ JUCE_BEGIN_NO_SANITIZE ("vptr") #include #include -#ifndef JUCE_VST3_CAN_REPLACE_VST2 - #define JUCE_VST3_CAN_REPLACE_VST2 1 -#endif - -#if JUCE_VST3_CAN_REPLACE_VST2 - - #if ! JUCE_MSVC && ! defined (__cdecl) - #define __cdecl - #endif - - namespace Vst2 - { - struct AEffect; - #include "pluginterfaces/vst2.x/vstfxstore.h" - } - -#endif - #ifndef JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS #if JucePlugin_WantsMidiInput #define JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS 1 @@ -2824,102 +2806,22 @@ public: } //============================================================================== - #if JUCE_VST3_CAN_REPLACE_VST2 - bool loadVST2VstWBlock (const char* data, int size) - { - jassert (ByteOrder::bigEndianInt ("VstW") == htonl ((uint32) readUnaligned (data))); - jassert (1 == htonl ((uint32) readUnaligned (data + 8))); // version should be 1 according to Steinberg's docs - - auto headerLen = (int) htonl ((uint32) readUnaligned (data + 4)) + 8; - return loadVST2CcnKBlock (data + headerLen, size - headerLen); - } - - bool loadVST2CcnKBlock (const char* data, int size) - { - auto* bank = reinterpret_cast (data); - - jassert (ByteOrder::bigEndianInt ("CcnK") == htonl ((uint32) bank->chunkMagic)); - jassert (ByteOrder::bigEndianInt ("FBCh") == htonl ((uint32) bank->fxMagic)); - jassert (htonl ((uint32) bank->version) == 1 || htonl ((uint32) bank->version) == 2); - jassert (JucePlugin_VSTUniqueID == htonl ((uint32) bank->fxID)); - - setStateInformation (bank->content.data.chunk, - jmin ((int) (size - (bank->content.data.chunk - data)), - (int) htonl ((uint32) bank->content.data.size))); - return true; - } - - bool loadVST3PresetFile (const char* data, int size) - { - if (size < 48) - return false; - - // At offset 4 there's a little-endian version number which seems to typically be 1 - // At offset 8 there's 32 bytes the SDK calls "ASCII-encoded class id" - auto chunkListOffset = (int) ByteOrder::littleEndianInt (data + 40); - jassert (memcmp (data + chunkListOffset, "List", 4) == 0); - auto entryCount = (int) ByteOrder::littleEndianInt (data + chunkListOffset + 4); - jassert (entryCount > 0); - - for (int i = 0; i < entryCount; ++i) - { - auto entryOffset = chunkListOffset + 8 + 20 * i; - - if (entryOffset + 20 > size) - return false; - - if (memcmp (data + entryOffset, "Comp", 4) == 0) - { - // "Comp" entries seem to contain the data. - auto chunkOffset = ByteOrder::littleEndianInt64 (data + entryOffset + 4); - auto chunkSize = ByteOrder::littleEndianInt64 (data + entryOffset + 12); - - if (static_cast (chunkOffset + chunkSize) > static_cast (size)) - { - jassertfalse; - return false; - } - - loadVST2VstWBlock (data + chunkOffset, (int) chunkSize); - } - } - - return true; - } - - bool loadVST2CompatibleState (const char* data, int size) - { - if (size < 4) - return false; - - auto header = htonl ((uint32) readUnaligned (data)); - - if (header == ByteOrder::bigEndianInt ("VstW")) - return loadVST2VstWBlock (data, size); - - if (header == ByteOrder::bigEndianInt ("CcnK")) - return loadVST2CcnKBlock (data, size); - - if (memcmp (data, "VST3", 4) == 0) - { - // In Cubase 5, when loading VST3 .vstpreset files, - // we get the whole content of the files to load. - // In Cubase 7 we get just the contents within and - // we go directly to the loadVST2VstW codepath instead. - return loadVST3PresetFile (data, size); - } - - return false; - } - #endif - - void loadStateData (const void* data, int size) + bool shouldTryToLoadVst2State() { #if JUCE_VST3_CAN_REPLACE_VST2 - if (loadVST2CompatibleState ((const char*) data, size)) - return; + return true; + #else + return false; + #endif + } + + bool shouldWriteStateWithVst2Compatibility() + { + #if JUCE_VST3_CAN_REPLACE_VST2 + return true; + #else + return false; #endif - setStateInformation (data, size); } bool readFromMemoryStream (IBStream* state) @@ -2952,7 +2854,7 @@ public: if (block.getSize() >= 5 && memcmp (block.getData(), "VC2!E", 5) == 0) return false; - loadStateData (block.getData(), (int) block.getSize()); + setStateInformation (block.getData(), (int) block.getSize()); return true; } @@ -2984,10 +2886,21 @@ public: if (dataSize <= 0 || dataSize >= 0x7fffffff) return false; - loadStateData (allData.getData(), (int) dataSize); + setStateInformation (allData.getData(), (int) dataSize); return true; } + bool readVst2State (IBStream* state) + { + if (auto vst2State = VST3::tryVst2StateLoad (*state)) + { + setStateInformation (vst2State->chunk.data(), (int) vst2State->chunk.size()); + return true; + } + + return false; + } + tresult PLUGIN_API setState (IBStream* state) override { // The VST3 spec requires that this function is called from the UI thread. @@ -2999,36 +2912,41 @@ public: FUnknownPtr stateRefHolder (state); // just in case the caller hasn't properly ref-counted the stream object - if (state->seek (0, IBStream::kIBSeekSet, nullptr) == kResultTrue) + const auto seekToBeginningOfStream = [&] { - if (! detail::PluginUtilities::getHostType().isFruityLoops() && readFromMemoryStream (state)) - return kResultTrue; + return state->seek (0, IBStream::kIBSeekSet, nullptr) == kResultTrue; + }; - if (readFromUnknownStream (state)) - return kResultTrue; - } + if (seekToBeginningOfStream() && shouldTryToLoadVst2State() && readVst2State (state)) + return kResultTrue; + + if (seekToBeginningOfStream() && ! detail::PluginUtilities::getHostType().isFruityLoops() && readFromMemoryStream (state)) + return kResultTrue; + + if (seekToBeginningOfStream() && readFromUnknownStream (state)) + return kResultTrue; return kResultFalse; } - #if JUCE_VST3_CAN_REPLACE_VST2 - static tresult writeVST2Header (IBStream* state, bool bypassed) + tresult getStateWithVst2Compatibility (const MemoryBlock& dataChunk, IBStream& outState) { - auto writeVST2IntToState = [state] (uint32 n) - { - auto t = (int32) htonl (n); - return state->write (&t, 4); - }; + VST3::Vst2xState vst2State; - auto status = writeVST2IntToState (ByteOrder::bigEndianInt ("VstW")); + vst2State.chunk.resize (dataChunk.getSize()); + std::copy (dataChunk.begin(), dataChunk.end(), vst2State.chunk.begin()); - if (status == kResultOk) status = writeVST2IntToState (8); // header size - if (status == kResultOk) status = writeVST2IntToState (1); // version - if (status == kResultOk) status = writeVST2IntToState (bypassed ? 1 : 0); // bypass + vst2State.fxUniqueID = JucePlugin_VSTUniqueID; + vst2State.fxVersion = JucePlugin_VersionCode; + vst2State.isBypassed = isBypassed(); - return status; + if (VST3::writeVst2State (vst2State, outState)) + return kResultTrue; + + // Please inform the JUCE team if you hit this assertion + jassertfalse; + return kResultFalse; } - #endif tresult PLUGIN_API getState (IBStream* state) override { @@ -3038,29 +2956,11 @@ public: MemoryBlock mem; getStateInformation (mem); - #if JUCE_VST3_CAN_REPLACE_VST2 - tresult status = writeVST2Header (state, isBypassed()); + if (mem.isEmpty()) + return kResultFalse; - if (status != kResultOk) - return status; - - const int bankBlockSize = 160; - Vst2::fxBank bank; - - zerostruct (bank); - bank.chunkMagic = (int32) htonl (ByteOrder::bigEndianInt ("CcnK")); - bank.byteSize = (int32) htonl (bankBlockSize - 8 + (unsigned int) mem.getSize()); - bank.fxMagic = (int32) htonl (ByteOrder::bigEndianInt ("FBCh")); - bank.version = (int32) htonl (2); - bank.fxID = (int32) htonl (JucePlugin_VSTUniqueID); - bank.fxVersion = (int32) htonl (JucePlugin_VersionCode); - bank.content.data.size = (int32) htonl ((unsigned int) mem.getSize()); - - status = state->write (&bank, bankBlockSize); - - if (status != kResultOk) - return status; - #endif + if (shouldWriteStateWithVst2Compatibility()) + return getStateWithVst2Compatibility (mem, *state); return state->write (mem.getData(), (Steinberg::int32) mem.getSize()); } diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp b/modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp new file mode 100644 index 0000000000..a6ccdb0098 --- /dev/null +++ b/modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.cpp @@ -0,0 +1,633 @@ +//------------------------------------------------------------------------ +// Flags : clang-format SMTGSequencer +// Project : VST3 SDK +// Filename : public.sdk/source/vst/utility/vst2persistence.cpp +// Created by : Steinberg, 12/2019 +// Description : vst2 persistence helper +// +//------------------------------------------------------------------------ +// LICENSE +// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved +//----------------------------------------------------------------------------- +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Steinberg Media Technologies nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. +//----------------------------------------------------------------------------- + +#include "public.sdk/source/vst/utility/vst2persistence.h" +#include "pluginterfaces/base/fplatform.h" +#include + +//------------------------------------------------------------------------ +namespace VST3 { +namespace { +namespace IO { + +//------------------------------------------------------------------------ +enum class Error +{ + NoError, + Unknown, + EndOfFile, + BufferToBig, + NotAllowed, + InvalidArgument, +}; + +//------------------------------------------------------------------------ +enum class SeekMode +{ + Set, + End, + Current +}; + +//------------------------------------------------------------------------ +struct Result +{ + Error error {Error::Unknown}; + uint64_t bytes {0u}; + + Result () noexcept = default; + Result (Error error, uint64_t bytes = 0) noexcept : error (error), bytes (bytes) {} + + operator bool () const noexcept { return error == Error::NoError; } +}; + +//------------------------------------------------------------------------ +struct ReadBufferDesc +{ + const uint64_t bytes; + void* ptr; +}; + +//------------------------------------------------------------------------ +struct WriteBufferDesc +{ + const uint64_t bytes; + const void* ptr; +}; + +//------------------------------------------------------------------------ +template +class ByteOrderStream +{ +public: +//------------------------------------------------------------------------ + ByteOrderStream (Steinberg::IBStream& stream) noexcept : stream (stream) {} + ByteOrderStream (ByteOrderStream&&) noexcept = delete; + ByteOrderStream& operator= (ByteOrderStream&&) noexcept = delete; + ByteOrderStream (const ByteOrderStream&) noexcept = delete; + ByteOrderStream& operator= (const ByteOrderStream&) noexcept = delete; + + inline Result operator<< (const std::string& input) noexcept; + inline Result operator>> (std::string& output) noexcept; + + template + inline Result operator<< (const T& input) noexcept; + template + inline Result operator>> (T& output) const noexcept; + + inline Result read (const ReadBufferDesc& buffer) const noexcept; + inline Result write (const WriteBufferDesc& buffer) noexcept; + inline Result seek (SeekMode mode, int64_t bytes) const noexcept; + inline Result tell () const noexcept; + +//------------------------------------------------------------------------ +private: + template + inline Result swapAndWrite (const uint8_t* buffer) noexcept; + inline void swap (uint8_t* buffer, uint64_t size) const noexcept; + Steinberg::IBStream& stream; +}; + +//------------------------------------------------------------------------ +using LittleEndianStream = ByteOrderStream; +using BigEndianStream = ByteOrderStream; +using NativeEndianStream = ByteOrderStream; + +//------------------------------------------------------------------------ +template +inline Result ByteOrderStream::read (const ReadBufferDesc& buffer) const noexcept +{ + if (buffer.bytes > static_cast (std::numeric_limits::max ())) + return Result (Error::BufferToBig); + Steinberg::int32 readBytes = 0; + auto tres = stream.read (buffer.ptr, static_cast (buffer.bytes), &readBytes); + if (tres != Steinberg::kResultTrue) + return Result (Error::Unknown); + assert (readBytes >= 0); + return Result {Error::NoError, static_cast (readBytes)}; +} + +//------------------------------------------------------------------------ +template +inline Result ByteOrderStream::write (const WriteBufferDesc& buffer) noexcept +{ + if (buffer.bytes > static_cast (std::numeric_limits::max ())) + return Result (Error::BufferToBig); + Steinberg::int32 writtenBytes = 0; + auto tres = stream.write (const_cast (buffer.ptr), + static_cast (buffer.bytes), &writtenBytes); + if (tres != Steinberg::kResultTrue) + return Result (Error::Unknown); + assert (writtenBytes >= 0); + return Result {Error::NoError, static_cast (writtenBytes)}; +} + +//------------------------------------------------------------------------ +template +inline Result ByteOrderStream::seek (SeekMode mode, int64_t bytes) const noexcept +{ + Steinberg::int32 seekMode = 0; + switch (mode) + { + case SeekMode::Set: seekMode = Steinberg::IBStream::kIBSeekSet; break; + case SeekMode::Current: seekMode = Steinberg::IBStream::kIBSeekCur; break; + case SeekMode::End: seekMode = Steinberg::IBStream::kIBSeekEnd; break; + } + Steinberg::int64 seekRes = 0; + auto tres = stream.seek (static_cast (bytes), seekMode, &seekRes); + if (tres != Steinberg::kResultTrue || seekRes < 0) + return Result {Error::Unknown}; + return Result (Error::NoError, static_cast (seekRes)); +} + +//------------------------------------------------------------------------ +template +inline Result ByteOrderStream::tell () const noexcept +{ + Steinberg::int64 tellRes = 0; + auto tres = stream.tell (&tellRes); + if (tres != Steinberg::kResultTrue || tellRes < 0) + return Result {Error::Unknown}; + return Result {Error::NoError, static_cast (tellRes)}; +} + +//------------------------------------------------------------------------ +template +inline Result ByteOrderStream::operator<< (const std::string& input) noexcept +{ + auto res = *this << static_cast (input.length ()); + if (!res) + return res; + res = stream.write (const_cast (static_cast (input.data ())), + static_cast (input.length ())); + res.bytes += sizeof (uint64_t); + return res; +} + +//------------------------------------------------------------------------ +template +inline Result ByteOrderStream::operator>> (std::string& output) noexcept +{ + uint64_t length; + auto res = *this >> length; + if (!res) + return res; + output.resize (length); + if (length > 0) + { + res = stream.read (&output.front (), static_cast (length)); + res.bytes += sizeof (uint64_t); + } + return res; +} + +//------------------------------------------------------------------------ +template +template +inline Result ByteOrderStream::operator<< (const T& input) noexcept +{ + static_assert (std::is_standard_layout::value, "Only standard layout types allowed"); + // with C++17: if constexpr (StreamByteOrder == BYTEORDER) + if (constexpr bool tmp = (StreamByteOrder == BYTEORDER)) + return write (WriteBufferDesc {sizeof (T), static_cast (&input)}); + + return swapAndWrite (reinterpret_cast (&input)); +} + +//------------------------------------------------------------------------ +template +template +inline Result ByteOrderStream::operator>> (T& output) const noexcept +{ + static_assert (std::is_standard_layout::value, "Only standard layout types allowed"); + auto res = read (ReadBufferDesc {sizeof (T), &output}); + // with C++17: if constexpr (StreamByteOrder == BYTEORDER) + if (constexpr bool tmp = (StreamByteOrder == BYTEORDER)) + return res; + + swap (reinterpret_cast (&output), res.bytes); + return res; +} + +//------------------------------------------------------------------------ +template +template +inline Result ByteOrderStream::swapAndWrite (const uint8_t* buffer) noexcept +{ + // with C++17: if constexpr (_size > 1) + if (constexpr bool tmp2 = (_size > 1)) + { + int8_t tmp[_size]; + + constexpr auto halfSize = _size / 2; + auto size = _size; + auto low = buffer; + auto high = buffer + size - 1; + + while (size > halfSize) + { + tmp[size - 2] = buffer[(_size - size) + 1]; + tmp[(_size - size) + 1] = buffer[size - 2]; + tmp[_size - size] = *high; + tmp[size - 1] = *low; + low += 2; + high -= 2; + size -= 2; + } + return write (WriteBufferDesc {_size, tmp}); + } + return write (WriteBufferDesc {1, buffer}); +} + +//------------------------------------------------------------------------ +template +inline void ByteOrderStream::swap (uint8_t* buffer, uint64_t size) const noexcept +{ + if (size < 2) + return; + auto low = buffer; + auto high = buffer + size - 1; + while (size >= 2) + { + auto tmp = *low; + *low = *high; + *high = tmp; + low += 2; + high -= 2; + size -= 2; + } +} + +//------------------------------------------------------------------------ +} // IO + +//------------------------------------------------------------------------ +constexpr int32_t cMagic = 'CcnK'; +constexpr int32_t bankMagic = 'FxBk'; +constexpr int32_t privateChunkID = 'VstW'; +constexpr int32_t chunkBankMagic = 'FBCh'; +constexpr int32_t programMagic = 'FxCk'; +constexpr int32_t chunkProgramMagic = 'FPCh'; + +//------------------------------------------------------------------------ +Optional loadProgram (const IO::BigEndianStream& state, + const Optional& vst2xUniqueID) +{ + Vst2xProgram program; + int32_t id; + if (!(state >> id)) + return {}; + if (id != cMagic) + return {}; + int32_t bankSize; + if (!(state >> bankSize)) + return {}; + int32_t fxMagic; + if (!(state >> fxMagic)) + return {}; + if (!(fxMagic == programMagic || fxMagic == chunkProgramMagic)) + return {}; + int32_t formatVersion; + if (!(state >> formatVersion)) + return {}; + int32_t fxId; + if (!(state >> fxId)) + return {}; + if (vst2xUniqueID && fxId != *vst2xUniqueID) + return {}; + int32_t fxVersion; + if (!(state >> fxVersion)) + return {}; + int32_t numParams; + if (!(state >> numParams)) + return {}; + if (numParams < 0) + return {}; + char name[29]; + if (!state.read ({28, name})) + return {}; + name[28] = 0; + program.name = name; + program.fxUniqueID = fxId; + program.fxVersion = fxVersion; + if (fxMagic == chunkProgramMagic) + { + uint32_t chunkSize; + if (!(state >> chunkSize)) + return {}; + program.chunk.resize (chunkSize); + if (!state.read ({chunkSize, program.chunk.data ()})) + return {}; + } + else + { + program.values.resize (numParams); + float paramValue; + for (int32_t i = 0; i < numParams; ++i) + { + if (!(state >> paramValue)) + return {}; + program.values[i] = paramValue; + } + } + return {std::move (program)}; +} + +//------------------------------------------------------------------------ +bool loadPrograms (Steinberg::IBStream& stream, Vst2xState::Programs& programs, + const Optional& vst2xUniqueID) +{ + IO::BigEndianStream state (stream); + + for (auto& program : programs) + { + if (auto prg = loadProgram (state, vst2xUniqueID)) + std::swap (program, *prg); + else + return false; + } + return true; +} + +//------------------------------------------------------------------------ +template +IO::Error streamSizeWriter (StreamT& stream, Proc proc) +{ + auto startPos = stream.tell (); + if (startPos.error != IO::Error::NoError) + return startPos.error; + auto res = stream << static_cast (0); // placeholder + if (!res) + return res.error; + auto procRes = proc (); + if (procRes != IO::Error::NoError) + return procRes; + auto endPos = stream.tell (); + if (endPos.error != IO::Error::NoError) + return endPos.error; + auto size = (endPos.bytes - startPos.bytes) - 4; + auto typeSize = static_cast (size); + if (size != static_cast (typeSize)) + return IO::Error::Unknown; + res = stream.seek (IO::SeekMode::Set, startPos.bytes); + if (!res) + return res.error; + res = (stream << typeSize); + if (!res) + return res.error; + res = stream.seek (IO::SeekMode::Set, endPos.bytes); + return res.error; +} + +//------------------------------------------------------------------------ +template +IO::Error writePrograms (StreamT& stream, const Vst2xState::Programs& programs) +{ + for (const auto& program : programs) + { + auto res = stream << cMagic; + if (!res) + return res.error; + res = streamSizeWriter (stream, [&] () { + bool writeChunk = !program.chunk.empty (); + if (!(res = stream << (writeChunk ? chunkProgramMagic : programMagic))) + return res.error; + int32_t version = 1; + if (!(res = stream << version)) + return res.error; + if (!(res = stream << program.fxUniqueID)) + return res.error; + int32_t fxVersion = program.fxVersion; + if (!(res = stream << fxVersion)) + return res.error; + uint32_t numParams = static_cast (program.values.size ()); + if (!(res = stream << numParams)) + return res.error; + auto programName = program.name; + programName.resize (28); + for (auto c : programName) + { + if (!(res = stream << c)) + return res.error; + } + if (writeChunk) + { + if (!(res = stream << static_cast (program.chunk.size ()))) + return res.error; + if (!(res = stream.write ({program.chunk.size (), program.chunk.data ()}))) + return res.error; + } + else + { + for (auto value : program.values) + { + if (!(res = stream << value)) + return res.error; + } + } + return IO::Error::NoError; + }); + if (res.error != IO::Error::NoError) + return res.error; + } + return IO::Error::NoError; +} + +//------------------------------------------------------------------------ +} // anonymous + +//------------------------------------------------------------------------ +Optional tryVst2StateLoad (Steinberg::IBStream& stream, + Optional vst2xUniqueID) noexcept +{ + Vst2xState result; + + IO::BigEndianStream state (stream); + int32_t version; + int32_t size; + int32_t id; + if (!(state >> id)) + return {}; + if (id == privateChunkID) + { + if (!(state >> size)) + return {}; + if (!(state >> version)) + return {}; + int32_t bypass; + if (!(state >> bypass)) + return {}; + result.isBypassed = bypass ? true : false; + if (!(state >> id)) + return {}; + } + if (id != cMagic) + return {}; + int32_t bankSize; + if (!(state >> bankSize)) + return {}; + int32_t fxMagic; + if (!(state >> fxMagic)) + return {}; + if (!(fxMagic == bankMagic || fxMagic == chunkBankMagic)) + return {}; + int32_t bankVersion; + if (!(state >> bankVersion)) + return {}; + int32_t fxId; + if (!(state >> fxId)) + return {}; + if (vst2xUniqueID && fxId != *vst2xUniqueID) + return {}; + result.fxUniqueID = fxId; + int32_t fxVersion; + if (!(state >> fxVersion)) + return {}; + result.fxVersion = fxVersion; + + int32_t numPrograms; + if (!(state >> numPrograms)) + return {}; + if (numPrograms < 1) + return {}; + + int32_t currentProgram = 0; + if (bankVersion >= 1) + { + if (!(state >> currentProgram)) + return {}; + state.seek (IO::SeekMode::Current, 124); // future + } + result.currentProgram = currentProgram; + if (fxMagic == bankMagic) + { + result.programs.resize (numPrograms); + if (!loadPrograms (stream, result.programs, vst2xUniqueID)) + return {}; + assert (static_cast (result.programs.size ()) > currentProgram); + } + else + { + uint32_t chunkSize; + if (!(state >> chunkSize)) + return {}; + if (chunkSize == 0) + return {}; + result.chunk.resize (chunkSize); + if (!state.read ({chunkSize, result.chunk.data ()})) + return {}; + } + return {std::move (result)}; +} + +//------------------------------------------------------------------------ +bool writeVst2State (const Vst2xState& state, Steinberg::IBStream& _stream, + bool writeBypassState) noexcept +{ + IO::BigEndianStream stream (_stream); + if (writeBypassState) + { + if (!(stream << privateChunkID)) + return false; + if (streamSizeWriter (stream, [&] () { + uint32_t version = 1; + auto res = (stream << version); + if (!res) + return res.error; + int32_t bypass = state.isBypassed ? 1 : 0; + return (stream << bypass).error; + }) != IO::Error::NoError) + { + return false; + } + } + if (!(stream << cMagic)) + { + return false; + } + if (streamSizeWriter (stream, [&] () { + bool writeChunk = !state.chunk.empty (); + IO::Result res; + if (!(res = (stream << (writeChunk ? chunkBankMagic : bankMagic)))) + return res.error; + int32_t bankVersion = 2; + if (!(res = (stream << bankVersion))) + return res.error; + if (!(res = (stream << state.fxUniqueID))) + return res.error; + if (!(res = (stream << state.fxVersion))) + return res.error; + int32_t numPrograms = writeChunk ? 1 : static_cast (state.programs.size ()); + if (!(res = (stream << numPrograms))) + return res.error; + if (bankVersion > 1) + { + if (!(res = (stream << state.currentProgram))) + return res.error; + // write 124 zero bytes + uint8_t byte = 0; + for (uint32_t i = 0; i < 124; ++i) + if (!(res = (stream << byte))) + return res.error; + } + if (writeChunk) + { + auto chunkSize = static_cast (state.chunk.size ()); + if (!(res = (stream << chunkSize))) + return res.error; + stream.write ({state.chunk.size (), state.chunk.data ()}); + } + else + { + writePrograms (stream, state.programs); + } + return IO::Error::NoError; + }) != IO::Error::NoError) + { + return false; + } + return true; +} + +//------------------------------------------------------------------------ +Optional tryVst2ProgramLoad (Steinberg::IBStream& stream, + Optional vst2xUniqueID) noexcept +{ + IO::BigEndianStream state (stream); + return loadProgram (state, vst2xUniqueID); +} + +//------------------------------------------------------------------------ +} // VST3 diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h b/modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h new file mode 100644 index 0000000000..b731cc6970 --- /dev/null +++ b/modules/juce_audio_processors/format_types/VST3_SDK/public.sdk/source/vst/utility/vst2persistence.h @@ -0,0 +1,123 @@ +//------------------------------------------------------------------------ +// Flags : clang-format SMTGSequencer +// Project : VST3 SDK +// Filename : public.sdk/source/vst/utility/vst2persistence.h +// Created by : Steinberg, 12/2019 +// Description : vst2 persistence helper +// +//------------------------------------------------------------------------ +// LICENSE +// (c) 2024, Steinberg Media Technologies GmbH, All Rights Reserved +//----------------------------------------------------------------------------- +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Steinberg Media Technologies nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. +//----------------------------------------------------------------------------- + +#pragma once + +#include "public.sdk/source/vst/utility/optional.h" +#include "pluginterfaces/base/ibstream.h" +#include +#include + +//------------------------------------------------------------------------ +namespace VST3 { + +//------------------------------------------------------------------------ +using Vst2xChunk = std::vector; + +//------------------------------------------------------------------------ +/** structure holding the content of a vst2 fxp format stream + * + * either the values member is valid or the chunk member but not both + */ +struct Vst2xProgram +{ + using ProgramValues = std::vector; + ProgramValues values; + Vst2xChunk chunk; + int32_t fxUniqueID {0}; + int32_t fxVersion {0}; + std::string name; +}; + +//------------------------------------------------------------------------ +/** structure holding the content of a vst2 fxb format stream + * + * either the programs member is valid or the chunk member but not both + */ +struct Vst2xState +{ + using Programs = std::vector; + Programs programs; + Vst2xChunk chunk; + + int32_t fxUniqueID {0}; + int32_t fxVersion {0}; + int32_t currentProgram {0}; + bool isBypassed {false}; +}; + +//------------------------------------------------------------------------ +/** Try loading the state from an old vst2 fxb format stream + * + * If successfully loaded, the state has either a chunk or programs but not both + * The Vst2xState::isBypassed boolean will be set if a Steinberg host has written the state into a + * project and the plug-in was bypassed. + * + * @param stream the input stream + * @param vst2xUniqueID vst2 unique id expected to be stored in the stream [optional]. If present + * the fxb unique id header entry must be the same as this otherwise the + * return value is empty. + * @return on success the optional has a Vst2xState object with the data + */ +Optional tryVst2StateLoad (Steinberg::IBStream& stream, + Optional vst2xUniqueID = {}) noexcept; + +//------------------------------------------------------------------------ +/** Write a vst2 fxb stream + * + * Writes the state into stream as a vst2 fxb format + * + * @param state the state which should be written + * @param stream the stream where the state should be written into + * @param writeBypassState write extra chunk with bypass state + * @return true on success + */ +bool writeVst2State (const Vst2xState& state, Steinberg::IBStream& stream, + bool writeBypassState = true) noexcept; + +//------------------------------------------------------------------------ +/** Try loading the state from on old vst2 fxp format stream + * + * If successfully loaded, the program has either a chunk or plain values but not both + * + * @param stream the input stream + * @param vst2xUniqueID vst2 unique id expected to be stored in the stream + * @return on success the optional has a Vst2xProgram object with the data + */ +Optional tryVst2ProgramLoad (Steinberg::IBStream& stream, + Optional vst2xUniqueID) noexcept; + +//------------------------------------------------------------------------ +} // VST3 diff --git a/modules/juce_audio_processors/format_types/juce_VST3Headers.h b/modules/juce_audio_processors/format_types/juce_VST3Headers.h index 2d757df6da..b8eb6dcddd 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3Headers.h +++ b/modules/juce_audio_processors/format_types/juce_VST3Headers.h @@ -162,6 +162,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-W#warnings", #pragma push_macro ("False") #undef False + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmultichar", "-Wfour-char-constants") + #include #include #include @@ -176,6 +178,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-W#warnings", #include #include #include + #include #include #include #include @@ -185,6 +188,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-W#warnings", #include #include + JUCE_END_IGNORE_WARNINGS_GCC_LIKE + #pragma pop_macro ("True") #pragma pop_macro ("False")