From 748d0e203f87928fafacbbd84049e9343e5f2676 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 31 Jul 2019 22:43:51 +0100 Subject: [PATCH] APVTS: Refactor the parameter attachment classes --- .../Builds/Android/app/CMakeLists.txt | 4 + .../VisualStudio2015/DemoRunner_App.vcxproj | 4 + .../DemoRunner_App.vcxproj.filters | 6 + .../VisualStudio2017/DemoRunner_App.vcxproj | 4 + .../DemoRunner_App.vcxproj.filters | 6 + .../VisualStudio2019/DemoRunner_App.vcxproj | 4 + .../DemoRunner_App.vcxproj.filters | 6 + .../Builds/Android/app/CMakeLists.txt | 4 + .../AudioPerformanceTest_App.vcxproj | 4 + .../AudioPerformanceTest_App.vcxproj.filters | 6 + .../Builds/Android/app/CMakeLists.txt | 4 + .../AudioPluginHost_App.vcxproj | 4 + .../AudioPluginHost_App.vcxproj.filters | 6 + .../AudioPluginHost_App.vcxproj | 4 + .../AudioPluginHost_App.vcxproj.filters | 6 + .../AudioPluginHost_App.vcxproj | 4 + .../AudioPluginHost_App.vcxproj.filters | 6 + .../Builds/Android/app/CMakeLists.txt | 4 + .../NetworkGraphicsDemo_App.vcxproj | 4 + .../NetworkGraphicsDemo_App.vcxproj.filters | 6 + .../UnitTestRunner_ConsoleApp.vcxproj | 4 + .../UnitTestRunner_ConsoleApp.vcxproj.filters | 6 + .../UnitTestRunner_ConsoleApp.vcxproj | 4 + .../UnitTestRunner_ConsoleApp.vcxproj.filters | 6 + .../WindowsDLL_StaticLibrary.vcxproj | 4 + .../WindowsDLL_StaticLibrary.vcxproj.filters | 6 + .../juce_audio_processors.cpp | 1 + .../juce_audio_processors.h | 1 + .../juce_AudioProcessorValueTreeState.cpp | 308 ++---------------- .../juce_AudioProcessorValueTreeState.h | 27 +- .../utilities/juce_ParameterAttachments.cpp | 257 +++++++++++++++ .../utilities/juce_ParameterAttachments.h | 235 +++++++++++++ 32 files changed, 652 insertions(+), 303 deletions(-) create mode 100644 modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp create mode 100644 modules/juce_audio_processors/utilities/juce_ParameterAttachments.h diff --git a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt index 02f9c8fd60..14325e7a4f 100644 --- a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt +++ b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt @@ -466,6 +466,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h" "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" + "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" + "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" @@ -2074,6 +2076,8 @@ set_source_files_properties("../../../../../modules/juce_audio_processors/utilit set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj index 34933e60f0..02f2fc6e2c 100644 --- a/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj @@ -629,6 +629,9 @@ true + + true + true @@ -2506,6 +2509,7 @@ + diff --git a/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj.filters index 54f99e377e..cb339acce1 100644 --- a/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj.filters @@ -1042,6 +1042,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3579,6 +3582,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj index 9b921f557a..acef99f06b 100644 --- a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj @@ -629,6 +629,9 @@ true + + true + true @@ -2506,6 +2509,7 @@ + diff --git a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters index da89dbd840..4054ac98da 100644 --- a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters @@ -1042,6 +1042,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3579,6 +3582,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj index 44e19ff233..6b38d9f84e 100644 --- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj @@ -629,6 +629,9 @@ true + + true + true @@ -2506,6 +2509,7 @@ + diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters index b842c832b8..bf8bbde2e3 100644 --- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters @@ -1042,6 +1042,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3579,6 +3582,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt index 14a9a5420a..2862b8322b 100644 --- a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt +++ b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt @@ -447,6 +447,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h" "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" + "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" + "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" @@ -1739,6 +1741,8 @@ set_source_files_properties("../../../../../modules/juce_audio_processors/utilit set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj b/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj index 5f245bec0d..a73907298b 100644 --- a/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj +++ b/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj @@ -610,6 +610,9 @@ true + + true + true @@ -2100,6 +2103,7 @@ + diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj.filters b/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj.filters index b79dd06477..dc2b6ad15a 100644 --- a/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj.filters +++ b/extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj.filters @@ -874,6 +874,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -2973,6 +2976,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt index 71a2458ddc..da82d1cff8 100644 --- a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt +++ b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt @@ -464,6 +464,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h" "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" + "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" + "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" @@ -1887,6 +1889,8 @@ set_source_files_properties("../../../../../modules/juce_audio_processors/utilit set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj index 0e7c0c9028..06a696821c 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj @@ -617,6 +617,9 @@ true + + true + true @@ -2243,6 +2246,7 @@ + diff --git a/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj.filters index 4bd2d17b4d..d44fa72524 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj.filters @@ -952,6 +952,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3219,6 +3222,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj index 46eff04ce4..8b1f25c327 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj @@ -617,6 +617,9 @@ true + + true + true @@ -2243,6 +2246,7 @@ + diff --git a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters index 8297afdec8..b2353b1a65 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters @@ -952,6 +952,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3219,6 +3222,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj index 212edcaa21..8464ac43b3 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj @@ -617,6 +617,9 @@ true + + true + true @@ -2243,6 +2246,7 @@ + diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters index 2dc24a282a..ca2836c6d5 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters @@ -952,6 +952,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3219,6 +3222,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt index b42e6bfd63..d92c6e562d 100644 --- a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt +++ b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt @@ -451,6 +451,8 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h" "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" + "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" + "../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" @@ -1818,6 +1820,8 @@ set_source_files_properties("../../../../../modules/juce_audio_processors/utilit set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_ParameterAttachments.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h" PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties("../../../../../modules/juce_audio_processors/juce_audio_processors.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj b/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj index 60d80f49ff..97b34b722b 100644 --- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj +++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj @@ -610,6 +610,9 @@ true + + true + true @@ -2185,6 +2188,7 @@ + diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj.filters b/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj.filters index 118807326e..a214376484 100644 --- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj.filters +++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj.filters @@ -904,6 +904,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3108,6 +3111,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj index c8d44414ca..4aab4e5fea 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj +++ b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj @@ -626,6 +626,9 @@ true + + true + true @@ -2356,6 +2359,7 @@ + diff --git a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters index 5220044812..aaa4448115 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters +++ b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters @@ -991,6 +991,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3369,6 +3372,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj index 7c39f54375..b5d50bed9b 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj +++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj @@ -626,6 +626,9 @@ true + + true + true @@ -2356,6 +2359,7 @@ + diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters index 851af349ea..97d351203f 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters +++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters @@ -991,6 +991,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3369,6 +3372,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj b/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj index cb5ff33ac9..cd9c01cb9d 100644 --- a/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj +++ b/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj @@ -609,6 +609,9 @@ true + + true + true @@ -2161,6 +2164,7 @@ + diff --git a/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj.filters b/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj.filters index ab6aa28619..b125be3701 100644 --- a/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj.filters +++ b/extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj.filters @@ -901,6 +901,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities @@ -3075,6 +3078,9 @@ JUCE Modules\juce_audio_processors\utilities + + JUCE Modules\juce_audio_processors\utilities + JUCE Modules\juce_audio_processors\utilities diff --git a/modules/juce_audio_processors/juce_audio_processors.cpp b/modules/juce_audio_processors/juce_audio_processors.cpp index a18a99a310..b1c1697aab 100644 --- a/modules/juce_audio_processors/juce_audio_processors.cpp +++ b/modules/juce_audio_processors/juce_audio_processors.cpp @@ -146,4 +146,5 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations", "-Wcast-align" #include "utilities/juce_AudioParameterInt.cpp" #include "utilities/juce_AudioParameterBool.cpp" #include "utilities/juce_AudioParameterChoice.cpp" +#include "utilities/juce_ParameterAttachments.cpp" #include "utilities/juce_AudioProcessorValueTreeState.cpp" diff --git a/modules/juce_audio_processors/juce_audio_processors.h b/modules/juce_audio_processors/juce_audio_processors.h index 0bee1c4318..e70e84bff4 100644 --- a/modules/juce_audio_processors/juce_audio_processors.h +++ b/modules/juce_audio_processors/juce_audio_processors.h @@ -124,4 +124,5 @@ #include "utilities/juce_AudioParameterInt.h" #include "utilities/juce_AudioParameterBool.h" #include "utilities/juce_AudioParameterChoice.h" +#include "utilities/juce_ParameterAttachments.h" #include "utilities/juce_AudioProcessorValueTreeState.h" diff --git a/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp b/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp index a32ce4aebf..6cdd07c1af 100644 --- a/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp +++ b/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp @@ -450,305 +450,39 @@ void AudioProcessorValueTreeState::timerCallback() } //============================================================================== -struct AttachedControlBase : public AudioProcessorValueTreeState::Listener, - public AsyncUpdater +template +std::unique_ptr makeAttachment (const AudioProcessorValueTreeState& stateToUse, + const String& parameterID, + Control& control) { - AttachedControlBase (AudioProcessorValueTreeState& s, const String& p) - : state (s), paramID (p), lastValue (0) - { - state.addParameterListener (paramID, this); - } + if (auto* parameter = stateToUse.getParameter (parameterID)) + return std::make_unique (*parameter, control, stateToUse.undoManager); - void removeListener() - { - state.removeParameterListener (paramID, this); - } + jassertfalse; + return nullptr; +} - void setNewDenormalisedValue (float newDenormalisedValue) - { - if (auto* p = state.getParameter (paramID)) - { - const float newValue = state.getParameterRange (paramID) - .convertTo0to1 (newDenormalisedValue); - - if (p->getValue() != newValue) - p->setValueNotifyingHost (newValue); - } - } - - void sendInitialUpdate() - { - if (auto* v = state.getRawParameterValue (paramID)) - parameterChanged (paramID, *v); - } - - void parameterChanged (const String&, float newValue) override - { - lastValue = newValue; - - if (MessageManager::getInstance()->isThisTheMessageThread()) - { - cancelPendingUpdate(); - setValue (newValue); - } - else - { - triggerAsyncUpdate(); - } - } - - void beginParameterChange() - { - if (auto* p = state.getParameter (paramID)) - { - if (state.undoManager != nullptr) - state.undoManager->beginNewTransaction(); - - p->beginChangeGesture(); - } - } - - void endParameterChange() - { - if (AudioProcessorParameter* p = state.getParameter (paramID)) - p->endChangeGesture(); - } - - void handleAsyncUpdate() override - { - setValue (lastValue); - } - - virtual void setValue (float) = 0; - - AudioProcessorValueTreeState& state; - String paramID; - std::atomic lastValue; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AttachedControlBase) -}; - -//============================================================================== -struct AudioProcessorValueTreeState::SliderAttachment::Pimpl : private AttachedControlBase, - private Slider::Listener -{ - Pimpl (AudioProcessorValueTreeState& s, const String& p, Slider& sl) - : AttachedControlBase (s, p), slider (sl), ignoreCallbacks (false) - { - NormalisableRange range (state.getParameterRange (paramID)); - - if (auto* param = state.getParameterAdapter (paramID)) - { - slider.valueFromTextFunction = [param](const String& text) { return (double) param->getDenormalisedValueForText (text); }; - slider.textFromValueFunction = [param](double value) { return param->getTextForDenormalisedValue ((float) value); }; - slider.setDoubleClickReturnValue (true, range.convertFrom0to1 (param->getParameter().getDefaultValue())); - } - - auto convertFrom0To1Function = [range](double currentRangeStart, - double currentRangeEnd, - double normalisedValue) mutable - { - range.start = (float) currentRangeStart; - range.end = (float) currentRangeEnd; - return (double) range.convertFrom0to1 ((float) normalisedValue); - }; - - auto convertTo0To1Function = [range](double currentRangeStart, - double currentRangeEnd, - double mappedValue) mutable - { - range.start = (float) currentRangeStart; - range.end = (float) currentRangeEnd; - return (double) range.convertTo0to1 ((float) mappedValue); - }; - - auto snapToLegalValueFunction = [range](double currentRangeStart, - double currentRangeEnd, - double valueToSnap) mutable - { - range.start = (float) currentRangeStart; - range.end = (float) currentRangeEnd; - return (double) range.snapToLegalValue ((float) valueToSnap); - }; - - NormalisableRange newRange { (double) range.start, - (double) range.end, - convertFrom0To1Function, - convertTo0To1Function, - snapToLegalValueFunction }; - newRange.interval = (double) range.interval; - newRange.skew = (double) range.skew; - - slider.setNormalisableRange (newRange); - - sendInitialUpdate(); - slider.addListener (this); - } - - ~Pimpl() override - { - slider.removeListener (this); - removeListener(); - } - - void setValue (float newValue) override - { - const ScopedLock selfCallbackLock (selfCallbackMutex); - - { - ScopedValueSetter svs (ignoreCallbacks, true); - slider.setValue (newValue, sendNotificationSync); - } - } - - void sliderValueChanged (Slider* s) override - { - const ScopedLock selfCallbackLock (selfCallbackMutex); - - if ((! ignoreCallbacks) && (! ModifierKeys::currentModifiers.isRightButtonDown())) - setNewDenormalisedValue ((float) s->getValue()); - } - - void sliderDragStarted (Slider*) override { beginParameterChange(); } - void sliderDragEnded (Slider*) override { endParameterChange(); } - - Slider& slider; - bool ignoreCallbacks; - CriticalSection selfCallbackMutex; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) -}; - -AudioProcessorValueTreeState::SliderAttachment::SliderAttachment (AudioProcessorValueTreeState& s, const String& p, Slider& sl) - : pimpl (new Pimpl (s, p, sl)) +AudioProcessorValueTreeState::SliderAttachment::SliderAttachment (AudioProcessorValueTreeState& stateToUse, + const String& parameterID, + Slider& slider) + : attachment (makeAttachment (stateToUse, parameterID, slider)) { } -AudioProcessorValueTreeState::SliderAttachment::~SliderAttachment() {} - -//============================================================================== -struct AudioProcessorValueTreeState::ComboBoxAttachment::Pimpl : private AttachedControlBase, - private ComboBox::Listener -{ - Pimpl (AudioProcessorValueTreeState& s, const String& p, ComboBox& c) - : AttachedControlBase (s, p), combo (c), ignoreCallbacks (false) - { - sendInitialUpdate(); - combo.addListener (this); - } - - ~Pimpl() override - { - combo.removeListener (this); - removeListener(); - } - - void setValue (float newValue) override - { - const ScopedLock selfCallbackLock (selfCallbackMutex); - - if (state.getParameter (paramID) != nullptr) - { - auto normValue = state.getParameterRange (paramID) - .convertTo0to1 (newValue); - auto index = roundToInt (normValue * (combo.getNumItems() - 1)); - - if (index != combo.getSelectedItemIndex()) - { - ScopedValueSetter svs (ignoreCallbacks, true); - combo.setSelectedItemIndex (index, sendNotificationSync); - } - } - } - - void comboBoxChanged (ComboBox*) override - { - const ScopedLock selfCallbackLock (selfCallbackMutex); - - if (! ignoreCallbacks) - { - if (auto* p = state.getParameter (paramID)) - { - auto newValue = (float) combo.getSelectedItemIndex() / (combo.getNumItems() - 1); - - if (p->getValue() != newValue) - { - beginParameterChange(); - p->setValueNotifyingHost (newValue); - endParameterChange(); - } - } - } - } - - ComboBox& combo; - bool ignoreCallbacks; - CriticalSection selfCallbackMutex; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) -}; - -AudioProcessorValueTreeState::ComboBoxAttachment::ComboBoxAttachment (AudioProcessorValueTreeState& s, const String& p, ComboBox& c) - : pimpl (new Pimpl (s, p, c)) +AudioProcessorValueTreeState::ComboBoxAttachment::ComboBoxAttachment (AudioProcessorValueTreeState& stateToUse, + const String& parameterID, + ComboBox& combo) + : attachment (makeAttachment (stateToUse, parameterID, combo)) { } -AudioProcessorValueTreeState::ComboBoxAttachment::~ComboBoxAttachment() {} - -//============================================================================== -struct AudioProcessorValueTreeState::ButtonAttachment::Pimpl : private AttachedControlBase, - private Button::Listener -{ - Pimpl (AudioProcessorValueTreeState& s, const String& p, Button& b) - : AttachedControlBase (s, p), button (b), ignoreCallbacks (false) - { - sendInitialUpdate(); - button.addListener (this); - } - - ~Pimpl() override - { - button.removeListener (this); - removeListener(); - } - - void setValue (float newValue) override - { - const ScopedLock selfCallbackLock (selfCallbackMutex); - - { - ScopedValueSetter svs (ignoreCallbacks, true); - button.setToggleState (newValue >= 0.5f, sendNotificationSync); - } - } - - void buttonClicked (Button* b) override - { - const ScopedLock selfCallbackLock (selfCallbackMutex); - - if (! ignoreCallbacks) - { - beginParameterChange(); - setNewDenormalisedValue (b->getToggleState() ? 1.0f : 0.0f); - endParameterChange(); - } - } - - Button& button; - bool ignoreCallbacks; - CriticalSection selfCallbackMutex; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) -}; - -AudioProcessorValueTreeState::ButtonAttachment::ButtonAttachment (AudioProcessorValueTreeState& s, const String& p, Button& b) - : pimpl (new Pimpl (s, p, b)) +AudioProcessorValueTreeState::ButtonAttachment::ButtonAttachment (AudioProcessorValueTreeState& stateToUse, + const String& parameterID, + Button& button) + : attachment (makeAttachment (stateToUse, parameterID, button)) { } -AudioProcessorValueTreeState::ButtonAttachment::~ButtonAttachment() {} - - //============================================================================== //============================================================================== #if JUCE_UNIT_TESTS diff --git a/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h b/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h index 1f2334201c..345b2ed406 100644 --- a/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h +++ b/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h @@ -353,11 +353,12 @@ public: /** Provides access to the undo manager that this object is using. */ UndoManager* const undoManager; - //============================================================================== private: + //============================================================================== class ParameterAdapter; public: + //============================================================================== /** A parameter class that maintains backwards compatibility with deprecated AudioProcessorValueTreeState functionality. @@ -433,14 +434,12 @@ public: class JUCE_API SliderAttachment { public: - SliderAttachment (AudioProcessorValueTreeState& stateToControl, + SliderAttachment (AudioProcessorValueTreeState& stateToUse, const String& parameterID, - Slider& sliderToControl); - ~SliderAttachment(); + Slider& slider); private: - struct Pimpl; - std::unique_ptr pimpl; + std::unique_ptr attachment; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderAttachment) }; @@ -461,14 +460,12 @@ public: class JUCE_API ComboBoxAttachment { public: - ComboBoxAttachment (AudioProcessorValueTreeState& stateToControl, + ComboBoxAttachment (AudioProcessorValueTreeState& stateToUse, const String& parameterID, - ComboBox& comboBoxToControl); - ~ComboBoxAttachment(); + ComboBox& combo); private: - struct Pimpl; - std::unique_ptr pimpl; + std::unique_ptr attachment; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBoxAttachment) }; @@ -484,14 +481,12 @@ public: class JUCE_API ButtonAttachment { public: - ButtonAttachment (AudioProcessorValueTreeState& stateToControl, + ButtonAttachment (AudioProcessorValueTreeState& stateToUse, const String& parameterID, - Button& buttonToControl); - ~ButtonAttachment(); + Button& button); private: - struct Pimpl; - std::unique_ptr pimpl; + std::unique_ptr attachment; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonAttachment) }; diff --git a/modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp b/modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp new file mode 100644 index 0000000000..f207af5444 --- /dev/null +++ b/modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp @@ -0,0 +1,257 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ + +ParameterAttachment::ParameterAttachment (RangedAudioParameter& param, + std::function parameterChangedCallback, + UndoManager* um) + : parameter (param), + undoManager (um), + setValue (std::move (parameterChangedCallback)) +{ + parameter.addListener (this); +} + +ParameterAttachment::~ParameterAttachment() +{ + parameter.removeListener (this); + cancelPendingUpdate(); +} + +void ParameterAttachment::sendInitialUpdate() +{ + parameterValueChanged ({}, parameter.getValue()); +} + +void ParameterAttachment::setValueAsCompleteGesture (float newDenormalisedValue) +{ + callIfParameterValueChanged (newDenormalisedValue, [this] (float f) + { + beginGesture(); + parameter.setValueNotifyingHost (f); + endGesture(); + }); +} + +void ParameterAttachment::beginGesture() +{ + if (undoManager != nullptr) + undoManager->beginNewTransaction(); + + parameter.beginChangeGesture(); +} + +void ParameterAttachment::setValueAsPartOfGesture (float newDenormalisedValue) +{ + callIfParameterValueChanged (newDenormalisedValue, [this] (float f) + { + parameter.setValueNotifyingHost (f); + }); +} + +void ParameterAttachment::endGesture() +{ + parameter.endChangeGesture(); +} + +template +void ParameterAttachment::callIfParameterValueChanged (float newDenormalisedValue, + Callback&& callback) +{ + const auto newValue = normalise (newDenormalisedValue); + + if (parameter.getValue() != newValue) + callback (newValue); +} + +void ParameterAttachment::parameterValueChanged (int, float newValue) +{ + lastValue = newValue; + + if (MessageManager::getInstance()->isThisTheMessageThread()) + { + cancelPendingUpdate(); + handleAsyncUpdate(); + } + else + { + triggerAsyncUpdate(); + } +} + +void ParameterAttachment::handleAsyncUpdate() +{ + if (setValue != nullptr) + setValue (parameter.convertFrom0to1 (lastValue)); +} + +//============================================================================== +SliderParameterAttachment::SliderParameterAttachment (RangedAudioParameter& param, + Slider& s, + UndoManager* um) + : slider (s), + attachment (param, [this] (float f) { setValue (f); }, um) +{ + slider.valueFromTextFunction = [¶m] (const String& text) { return (double) param.convertFrom0to1 (param.getValueForText (text)); }; + slider.textFromValueFunction = [¶m] (double value) { return param.getText (param.convertTo0to1 ((float) value), 0); }; + slider.setDoubleClickReturnValue (true, param.convertFrom0to1 (param.getDefaultValue())); + + auto range = param.getNormalisableRange(); + + auto convertFrom0To1Function = [range] (double currentRangeStart, + double currentRangeEnd, + double normalisedValue) mutable + { + range.start = (float) currentRangeStart; + range.end = (float) currentRangeEnd; + return (double) range.convertFrom0to1 ((float) normalisedValue); + }; + + auto convertTo0To1Function = [range] (double currentRangeStart, + double currentRangeEnd, + double mappedValue) mutable + { + range.start = (float) currentRangeStart; + range.end = (float) currentRangeEnd; + return (double) range.convertTo0to1 ((float) mappedValue); + }; + + auto snapToLegalValueFunction = [range] (double currentRangeStart, + double currentRangeEnd, + double mappedValue) mutable + { + range.start = (float) currentRangeStart; + range.end = (float) currentRangeEnd; + return (double) range.snapToLegalValue ((float) mappedValue); + }; + + NormalisableRange newRange { (double) range.start, + (double) range.end, + std::move (convertFrom0To1Function), + std::move (convertTo0To1Function), + std::move (snapToLegalValueFunction) }; + newRange.interval = range.interval; + newRange.skew = range.skew; + newRange.symmetricSkew = range.symmetricSkew; + + slider.setNormalisableRange (newRange); + + sendInitialUpdate(); + slider.valueChanged(); + slider.addListener (this); +} + +SliderParameterAttachment::~SliderParameterAttachment() +{ + slider.removeListener (this); +} + +void SliderParameterAttachment::sendInitialUpdate() { attachment.sendInitialUpdate(); } + +void SliderParameterAttachment::setValue (float newValue) +{ + const ScopedValueSetter svs (ignoreCallbacks, true); + slider.setValue (newValue, sendNotificationSync); +} + +void SliderParameterAttachment::sliderValueChanged (Slider*) +{ + if (ignoreCallbacks || ModifierKeys::currentModifiers.isRightButtonDown()) + return; + + attachment.setValueAsPartOfGesture ((float) slider.getValue()); +} + +//============================================================================== +ComboBoxParameterAttachment::ComboBoxParameterAttachment (RangedAudioParameter& param, + ComboBox& c, + UndoManager* um) + : comboBox (c), + attachment (param, [this] (float f) { setValue (f); }, um) +{ + sendInitialUpdate(); + comboBox.addListener (this); +} + +ComboBoxParameterAttachment::~ComboBoxParameterAttachment() +{ + comboBox.removeListener (this); +} + +void ComboBoxParameterAttachment::sendInitialUpdate() +{ + attachment.sendInitialUpdate(); +} + +void ComboBoxParameterAttachment::setValue (float newValue) +{ + const auto index = roundToInt (newValue); + + if (index == comboBox.getSelectedItemIndex()) + return; + + const ScopedValueSetter svs (ignoreCallbacks, true); + comboBox.setSelectedItemIndex (index, sendNotificationSync); +} + +void ComboBoxParameterAttachment::comboBoxChanged (ComboBox*) +{ + if (ignoreCallbacks) + return; + + attachment.setValueAsCompleteGesture ((float) comboBox.getSelectedItemIndex()); +} + +//============================================================================== +ButtonParameterAttachment::ButtonParameterAttachment (RangedAudioParameter& param, + Button& b, + UndoManager* um) + : button (b), + attachment (param, [this] (float f) { setValue (f); }, um) +{ + sendInitialUpdate(); + button.addListener (this); +} + +ButtonParameterAttachment::~ButtonParameterAttachment() +{ + button.removeListener (this); +} + +void ButtonParameterAttachment::sendInitialUpdate() +{ + attachment.sendInitialUpdate(); +} + +void ButtonParameterAttachment::setValue (float newValue) +{ + const ScopedValueSetter svs (ignoreCallbacks, true); + button.setToggleState (newValue >= 0.5f, sendNotificationSync); +} + +void ButtonParameterAttachment::buttonClicked (Button*) +{ + if (ignoreCallbacks) + return; + + attachment.setValueAsCompleteGesture (button.getToggleState() ? 1.0f : 0.0f); +} + +} // namespace juce diff --git a/modules/juce_audio_processors/utilities/juce_ParameterAttachments.h b/modules/juce_audio_processors/utilities/juce_ParameterAttachments.h new file mode 100644 index 0000000000..bc0efc19c7 --- /dev/null +++ b/modules/juce_audio_processors/utilities/juce_ParameterAttachments.h @@ -0,0 +1,235 @@ +/* + ============================================================================== + + This file is part of the JUCE 6 technical preview. + Copyright (c) 2017 - ROLI Ltd. + + You may use this code under the terms of the GPL v3 + (see www.gnu.org/licenses). + + For this technical preview, this file is not subject to commercial licensing. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ + +/** Used to implement 'attachments' or 'controllers' that link a plug-in + parameter to a UI element. + + To implement a new attachment type, create a new class which includes an + instance of this class as a data member. Your class should pass a function + to the constructor of the ParameterAttachment, which will then be called on + the message thread when the parameter changes. You can use this function to + update the state of the UI control. Your class should also register as a + listener of the UI control and respond to respond to changes in the UI element + by calling either setValueAsCompleteGesture or beginGesture, + setValueAsPartOfGesture and endGesture. + + Make sure to call `sendInitialUpdate` at the end of your new attachment's + constructor, so that the UI immediately reflects the state of the parameter. +*/ +class ParameterAttachment : private AudioProcessorParameter::Listener, + private AsyncUpdater +{ +public: + /** Listens to a parameter and calls the the provided function in response to + parameter changes. If an undoManager is supplied `beginNewTransaction` will + be called on it whenever the UI requests a parameter change via this attachment. + + @param parameter The parameter to which this attachment will listen + @param parameterChangedCallback The function that will be called on the message thread in response + to parameter changes + @param uundoManager The UndoManager that will be used to begin transactions when the UI + requests a parameter change. + */ + ParameterAttachment (RangedAudioParameter& parameter, + std::function parameterChangedCallback, + UndoManager* undoManager = nullptr); + + /** Destructor. */ + ~ParameterAttachment() override; + + /** Calls the parameterChangedCallback function that was registered in + the constructor, making the UI reflect the current parameter state. + + This function should be called after doing any necessary setup on + the UI control that is being managed (e.g. adding ComboBox entries, + making buttons toggle-able). + */ + void sendInitialUpdate(); + + /** Triggers a full gesture message on the managed parameter. + + Call this in the listener callback of the UI control in response + to a one-off change in the UI like a button-press. + */ + void setValueAsCompleteGesture (float newDenormalisedValue); + + /** Begins a gesture on the managed parameter. + + Call this when the UI is about to begin a continuous interaction, + like when the mouse button is pressed on a slider. + */ + void beginGesture(); + + /** Updates the parameter value during a gesture. + + Call this during a continuous interaction, like a slider value + changed callback. + */ + void setValueAsPartOfGesture (float newDenormalisedValue); + + /** Ends a gesture on the managed parameter. + + Call this when the UI has finished a continuous interaction, + like when the mouse button is released on a slider. + */ + void endGesture(); + +private: + float normalise (float f) const { return parameter.convertTo0to1 (f); } + + template + void callIfParameterValueChanged (float newDenormalisedValue, Callback&& callback); + + void parameterValueChanged (int, float) override; + void parameterGestureChanged (int, bool) override {} + void handleAsyncUpdate() override; + + RangedAudioParameter& parameter; + std::atomic lastValue { 0.0f }; + UndoManager* undoManager = nullptr; + std::function setValue; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParameterAttachment) +}; + +//============================================================================== +/** An object of this class maintains a connection between a Slider and a + plug-in parameter. + + During the lifetime of this object it keeps the two things in sync, making + it easy to connect a slider to a parameter. When this object is deleted, the + connection is broken. Make sure that your parameter and Slider are not + deleted before this object! +*/ +class SliderParameterAttachment : private Slider::Listener +{ +public: + /** Creates a connection between a plug-in parameter and a Slider. + + @param parameter The parameter to use + @param slider The Slider to use + @param undoManager An optional UndoManager + */ + SliderParameterAttachment (RangedAudioParameter& parameter, Slider& slider, + UndoManager* undoManager = nullptr); + + /** Destructor. */ + ~SliderParameterAttachment() override; + + /** Call this after setting up your slider in the case where you need to do + extra setup after constructing this attachment. + */ + void sendInitialUpdate(); + +private: + void setValue (float newValue); + void sliderValueChanged (Slider*) override; + + void sliderDragStarted (Slider*) override { attachment.beginGesture(); } + void sliderDragEnded (Slider*) override { attachment.endGesture(); } + + Slider& slider; + ParameterAttachment attachment; + bool ignoreCallbacks = false; +}; + +//============================================================================== +/** An object of this class maintains a connection between a ComboBox and a + plug-in parameter. + + ComboBox items will be spaced linearly across the range of the parameter. For + example if the range is specified by NormalisableRange (-0.5f, 0.5f, 0.5f) + and you add three items then the first will be mapped to a value of -0.5, the + second to 0, and the third to 0.5. + + During the lifetime of this object it keeps the two things in sync, making it + easy to connect a combo box to a parameter. When this object is deleted, the + connection is broken. Make sure that your parameter and ComboBox are not deleted + before this object! +*/ +class ComboBoxParameterAttachment : private ComboBox::Listener +{ +public: + /** Creates a connection between a plug-in parameter and a ComboBox. + + @param parameter The parameter to use + @param combo The ComboBox to use + @param undoManager An optional UndoManager + */ + ComboBoxParameterAttachment (RangedAudioParameter& parameter, ComboBox& combo, + UndoManager* undoManager = nullptr); + + /** Destructor. */ + ~ComboBoxParameterAttachment() override; + + /** Call this after setting up your combo box in the case where you need to do + extra setup after constructing this attachment. + */ + void sendInitialUpdate(); + +private: + void setValue (float newValue); + void comboBoxChanged (ComboBox*) override; + + ComboBox& comboBox; + ParameterAttachment attachment; + bool ignoreCallbacks = false; +}; + +//============================================================================== +/** An object of this class maintains a connection between a Button and a + plug-in parameter. + + During the lifetime of this object it keeps the two things in sync, making it + easy to connect a button to a parameter. When this object is deleted, the + connection is broken. Make sure that your parameter and Button are not deleted + before this object! +*/ +class ButtonParameterAttachment : private Button::Listener +{ +public: + /** Creates a connection between a plug-in parameter and a Button. + + @param parameter The parameter to use + @param combo The Button to use + @param undoManager An optional UndoManager + */ + ButtonParameterAttachment (RangedAudioParameter& parameter, Button& button, + UndoManager* undoManager = nullptr); + + /** Destructor. */ + ~ButtonParameterAttachment() override; + + /** Call this after setting up your button in the case where you need to do + extra setup after constructing this attachment. + */ + void sendInitialUpdate(); + +private: + void setValue (float newValue); + void buttonClicked (Button*) override; + + Button& button; + ParameterAttachment attachment; + bool ignoreCallbacks = false; +}; + +} // namespace juce