New upstream version 5.4.6~ds0
authorIOhannes m zmölnig <zmoelnig@umlautS.umlaeute.mur.at>
Thu, 6 Feb 2020 08:52:23 +0000 (09:52 +0100)
committerIOhannes m zmölnig <zmoelnig@umlautS.umlaeute.mur.at>
Thu, 6 Feb 2020 08:52:23 +0000 (09:52 +0100)
438 files changed:
BREAKING-CHANGES.txt
ChangeList.txt
examples/Assets/DemoUtilities.h
examples/BLOCKS/BlocksDrawingDemo.h
examples/BLOCKS/BlocksMonitorDemo.h
examples/DemoRunner/Builds/Android/app/CMakeLists.txt
examples/DemoRunner/Builds/Android/app/src/main/AndroidManifest.xml
examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h
examples/DemoRunner/Builds/Android/build.gradle
examples/DemoRunner/Builds/Android/gradle/wrapper/gradle-wrapper.properties
examples/DemoRunner/Builds/LinuxMakefile/Makefile
examples/DemoRunner/Builds/MacOSX/App.entitlements [new file with mode: 0644]
examples/DemoRunner/Builds/MacOSX/DemoRunner.entitlements [deleted file]
examples/DemoRunner/Builds/MacOSX/DemoRunner.xcodeproj/project.pbxproj
examples/DemoRunner/Builds/MacOSX/Info-App.plist
examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj
examples/DemoRunner/Builds/VisualStudio2015/DemoRunner_App.vcxproj.filters
examples/DemoRunner/Builds/VisualStudio2015/resources.rc
examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj
examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters
examples/DemoRunner/Builds/VisualStudio2017/resources.rc
examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj
examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters
examples/DemoRunner/Builds/VisualStudio2019/resources.rc
examples/DemoRunner/Builds/iOS/App.entitlements [new file with mode: 0644]
examples/DemoRunner/Builds/iOS/DemoRunner.entitlements [deleted file]
examples/DemoRunner/Builds/iOS/DemoRunner.xcodeproj/project.pbxproj
examples/DemoRunner/Builds/iOS/Info-App.plist
examples/DemoRunner/DemoRunner.jucer
examples/DemoRunner/JuceLibraryCode/AppConfig.h
examples/DemoRunner/JuceLibraryCode/JuceHeader.h
examples/DemoRunner/Source/Demos/DemoPIPs1.cpp
examples/DemoRunner/Source/Demos/DemoPIPs2.cpp
examples/DemoRunner/Source/Demos/JUCEDemos.cpp
examples/DemoRunner/Source/Main.cpp
examples/DemoRunner/Source/UI/DemoContentComponent.cpp
examples/DemoRunner/Source/UI/DemoContentComponent.h
examples/DemoRunner/Source/UI/MainComponent.h
examples/GUI/FontsDemo.h
examples/GUI/ImagesDemo.h
examples/GUI/MDIDemo.h
examples/GUI/WidgetsDemo.h
examples/Plugins/InterAppAudioEffectPluginDemo.h
examples/Utilities/InAppPurchasesDemo.h
examples/Utilities/SystemInfoDemo.h
examples/Utilities/TimersAndEventsDemo.h
examples/Utilities/XMLandJSONDemo.h
extras/AudioPerformanceTest/AudioPerformanceTest.jucer
extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt
extras/AudioPerformanceTest/Builds/Android/app/src/main/AndroidManifest.xml
extras/AudioPerformanceTest/Builds/Android/build.gradle
extras/AudioPerformanceTest/Builds/Android/gradle/wrapper/gradle-wrapper.properties
extras/AudioPerformanceTest/Builds/MacOSX/App.entitlements [new file with mode: 0644]
extras/AudioPerformanceTest/Builds/MacOSX/AudioPerformanceTest.entitlements [deleted file]
extras/AudioPerformanceTest/Builds/MacOSX/AudioPerformanceTest.xcodeproj/project.pbxproj
extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj
extras/AudioPerformanceTest/Builds/VisualStudio2019/AudioPerformanceTest_App.vcxproj.filters
extras/AudioPerformanceTest/Builds/iOS/App.entitlements [new file with mode: 0644]
extras/AudioPerformanceTest/Builds/iOS/AudioPerformanceTest.entitlements [deleted file]
extras/AudioPerformanceTest/Builds/iOS/AudioPerformanceTest.xcodeproj/project.pbxproj
extras/AudioPerformanceTest/JuceLibraryCode/AppConfig.h
extras/AudioPerformanceTest/Source/Main.cpp
extras/AudioPerformanceTest/Source/MainComponent.h
extras/AudioPluginHost/AudioPluginHost.jucer
extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt
extras/AudioPluginHost/Builds/Android/app/src/main/AndroidManifest.xml
extras/AudioPluginHost/Builds/Android/build.gradle
extras/AudioPluginHost/Builds/Android/gradle/wrapper/gradle-wrapper.properties
extras/AudioPluginHost/Builds/MacOSX/App.entitlements [new file with mode: 0644]
extras/AudioPluginHost/Builds/MacOSX/AudioPluginHost.entitlements [deleted file]
extras/AudioPluginHost/Builds/MacOSX/AudioPluginHost.xcodeproj/project.pbxproj
extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj
extras/AudioPluginHost/Builds/VisualStudio2015/AudioPluginHost_App.vcxproj.filters
extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj
extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters
extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj
extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters
extras/AudioPluginHost/Builds/iOS/App.entitlements [new file with mode: 0644]
extras/AudioPluginHost/Builds/iOS/AudioPluginHost.entitlements [deleted file]
extras/AudioPluginHost/Builds/iOS/AudioPluginHost.xcodeproj/project.pbxproj
extras/AudioPluginHost/JuceLibraryCode/AppConfig.h
extras/AudioPluginHost/Source/HostStartup.cpp
extras/AudioPluginHost/Source/Plugins/IOConfigurationWindow.cpp
extras/AudioPluginHost/Source/Plugins/InternalPlugins.cpp
extras/AudioPluginHost/Source/Plugins/InternalPlugins.h
extras/AudioPluginHost/Source/Plugins/PluginGraph.cpp
extras/AudioPluginHost/Source/UI/GraphEditorPanel.cpp
extras/AudioPluginHost/Source/UI/GraphEditorPanel.h
extras/AudioPluginHost/Source/UI/MainHostWindow.cpp
extras/AudioPluginHost/Source/UI/PluginWindow.h
extras/BinaryBuilder/BinaryBuilder.jucer
extras/BinaryBuilder/Builds/MacOSX/BinaryBuilder.entitlements [deleted file]
extras/BinaryBuilder/Builds/MacOSX/BinaryBuilder.xcodeproj/project.pbxproj
extras/BinaryBuilder/Builds/MacOSX/ConsoleApp.entitlements [new file with mode: 0644]
extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj
extras/BinaryBuilder/Builds/VisualStudio2019/BinaryBuilder_ConsoleApp.vcxproj.filters
extras/BinaryBuilder/JuceLibraryCode/AppConfig.h
extras/BinaryBuilder/Source/Main.cpp
extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt
extras/NetworkGraphicsDemo/Builds/Android/app/src/main/AndroidManifest.xml
extras/NetworkGraphicsDemo/Builds/Android/build.gradle
extras/NetworkGraphicsDemo/Builds/Android/gradle/wrapper/gradle-wrapper.properties
extras/NetworkGraphicsDemo/Builds/MacOSX/App.entitlements [new file with mode: 0644]
extras/NetworkGraphicsDemo/Builds/MacOSX/NetworkGraphicsDemo.entitlements [deleted file]
extras/NetworkGraphicsDemo/Builds/MacOSX/NetworkGraphicsDemo.xcodeproj/project.pbxproj
extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj
extras/NetworkGraphicsDemo/Builds/VisualStudio2019/NetworkGraphicsDemo_App.vcxproj.filters
extras/NetworkGraphicsDemo/Builds/iOS/App.entitlements [new file with mode: 0644]
extras/NetworkGraphicsDemo/Builds/iOS/NetworkGraphicsDemo.entitlements [deleted file]
extras/NetworkGraphicsDemo/Builds/iOS/NetworkGraphicsDemo.xcodeproj/project.pbxproj
extras/NetworkGraphicsDemo/JuceLibraryCode/AppConfig.h
extras/NetworkGraphicsDemo/NetworkGraphicsDemo.jucer
extras/NetworkGraphicsDemo/Source/Main.cpp
extras/Projucer/Builds/LinuxMakefile/Makefile
extras/Projucer/Builds/MacOSX/App.entitlements [new file with mode: 0644]
extras/Projucer/Builds/MacOSX/Info-App.plist
extras/Projucer/Builds/MacOSX/Projucer.entitlements [deleted file]
extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj
extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj
extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters
extras/Projucer/Builds/VisualStudio2015/resources.rc
extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj
extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters
extras/Projucer/Builds/VisualStudio2017/resources.rc
extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj
extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters
extras/Projucer/Builds/VisualStudio2019/resources.rc
extras/Projucer/JuceLibraryCode/AppConfig.h
extras/Projucer/JuceLibraryCode/BinaryData.cpp
extras/Projucer/JuceLibraryCode/BinaryData.h
extras/Projucer/JuceLibraryCode/JuceHeader.h
extras/Projucer/Projucer.jucer
extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h
extras/Projucer/Source/Application/jucer_Application.cpp
extras/Projucer/Source/Application/jucer_AutoUpdater.cpp
extras/Projucer/Source/Application/jucer_AutoUpdater.h
extras/Projucer/Source/Application/jucer_Headers.h
extras/Projucer/Source/Application/jucer_MainWindow.cpp
extras/Projucer/Source/Application/jucer_MainWindow.h
extras/Projucer/Source/BinaryData/Templates/jucer_ComponentTemplate.h
extras/Projucer/Source/BinaryData/Templates/jucer_PIPMain.cpp
extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementImage.cpp
extras/Projucer/Source/ComponentEditor/jucer_GeneratedCode.cpp
extras/Projucer/Source/ComponentEditor/jucer_GeneratedCode.h
extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp
extras/Projucer/Source/LiveBuildEngine/jucer_CompileEngineClient.cpp
extras/Projucer/Source/LiveBuildEngine/jucer_DownloadCompileEngineThread.cpp
extras/Projucer/Source/Project/UI/Sidebar/jucer_ModuleTreeItems.h
extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.cpp
extras/Projucer/Source/Project/jucer_Module.cpp
extras/Projucer/Source/Project/jucer_Project.cpp
extras/Projucer/Source/Project/jucer_Project.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h
extras/Projucer/Source/Settings/jucer_StoredSettings.cpp
extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.cpp
extras/Projucer/Source/Utility/Helpers/jucer_CodeHelpers.h
extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h
extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.cpp [new file with mode: 0644]
extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.h [new file with mode: 0644]
extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp
extras/Projucer/Source/Utility/UI/PropertyComponents/jucer_FilePathPropertyComponent.h
extras/Projucer/Source/Wizards/jucer_NewFileWizard.cpp
extras/Projucer/Source/Wizards/jucer_NewProjectWizardComponent.h
extras/Projucer/Source/Wizards/jucer_ProjectWizard_Animated.h
extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioApp.h
extras/Projucer/Source/Wizards/jucer_ProjectWizard_AudioPlugin.h
extras/Projucer/Source/Wizards/jucer_ProjectWizard_Console.h
extras/Projucer/Source/Wizards/jucer_ProjectWizard_GUIApp.h
extras/Projucer/Source/Wizards/jucer_ProjectWizard_openGL.h
extras/UnitTestRunner/Builds/MacOSX/ConsoleApp.entitlements [new file with mode: 0644]
extras/UnitTestRunner/Builds/MacOSX/UnitTestRunner.entitlements [deleted file]
extras/UnitTestRunner/Builds/MacOSX/UnitTestRunner.xcodeproj/project.pbxproj
extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj
extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters
extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj
extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters
extras/UnitTestRunner/JuceLibraryCode/AppConfig.h
extras/UnitTestRunner/Source/Main.cpp
extras/UnitTestRunner/UnitTestRunner.jucer
extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj
extras/WindowsDLL/Builds/VisualStudio2019/WindowsDLL_StaticLibrary.vcxproj.filters
extras/WindowsDLL/JuceLibraryCode/AppConfig.h
extras/WindowsDLL/WindowsDLL.jucer
modules/juce_analytics/analytics/juce_ButtonTracker.h
modules/juce_analytics/juce_analytics.h
modules/juce_audio_basics/buffers/juce_AudioProcessLoadMeasurer.h
modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h
modules/juce_audio_basics/juce_audio_basics.h
modules/juce_audio_basics/midi/juce_MidiKeyboardState.h
modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp
modules/juce_audio_basics/midi/juce_MidiRPN.h
modules/juce_audio_basics/mpe/juce_MPEInstrument.h
modules/juce_audio_basics/mpe/juce_MPEMessages.h
modules/juce_audio_basics/mpe/juce_MPESynthesiser.h
modules/juce_audio_basics/mpe/juce_MPEUtils.cpp
modules/juce_audio_basics/sources/juce_AudioSource.h
modules/juce_audio_basics/utilities/juce_ADSR.h
modules/juce_audio_basics/utilities/juce_SmoothedValue.h
modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h
modules/juce_audio_devices/juce_audio_devices.h
modules/juce_audio_devices/midi_io/juce_MidiDevices.h
modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp
modules/juce_audio_devices/native/juce_android_OpenSL.cpp
modules/juce_audio_devices/native/juce_linux_ALSA.cpp
modules/juce_audio_devices/native/juce_linux_Bela.cpp [changed mode: 0755->0644]
modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp
modules/juce_audio_devices/native/juce_win32_ASIO.cpp
modules/juce_audio_devices/native/juce_win32_Midi.cpp
modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h
modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp
modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp
modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp
modules/juce_audio_formats/format/juce_AudioFormat.h
modules/juce_audio_formats/juce_audio_formats.h
modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
modules/juce_audio_plugin_client/juce_audio_plugin_client.h
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm
modules/juce_audio_plugin_client/juce_audio_plugin_client_Standalone.cpp
modules/juce_audio_plugin_client/utility/juce_PluginHostType.h
modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h
modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
modules/juce_audio_processors/format_types/juce_VST3Common.h
modules/juce_audio_processors/format_types/juce_VST3Headers.h
modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
modules/juce_audio_processors/juce_audio_processors.h
modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
modules/juce_audio_processors/processors/juce_AudioProcessor.h
modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp
modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h
modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp
modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h
modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h
modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.cpp
modules/juce_audio_processors/processors/juce_AudioProcessorParameterGroup.h
modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp
modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp
modules/juce_audio_processors/utilities/juce_AudioParameterBool.cpp
modules/juce_audio_processors/utilities/juce_AudioParameterBool.h
modules/juce_audio_processors/utilities/juce_AudioParameterChoice.cpp
modules/juce_audio_processors/utilities/juce_AudioParameterChoice.h
modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp
modules/juce_audio_processors/utilities/juce_AudioParameterFloat.h
modules/juce_audio_processors/utilities/juce_AudioParameterInt.cpp
modules/juce_audio_processors/utilities/juce_AudioParameterInt.h
modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp
modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h
modules/juce_audio_utils/gui/juce_AudioAppComponent.h
modules/juce_audio_utils/juce_audio_utils.h
modules/juce_blocks_basics/blocks/juce_Block.h
modules/juce_blocks_basics/blocks/juce_BlockConfigManager.h
modules/juce_blocks_basics/blocks/juce_BlocksVersion.h
modules/juce_blocks_basics/blocks/juce_ControlButton.h
modules/juce_blocks_basics/blocks/juce_TouchList.h
modules/juce_blocks_basics/juce_blocks_basics.cpp
modules/juce_blocks_basics/juce_blocks_basics.h
modules/juce_blocks_basics/protocol/juce_BlockModels.h
modules/juce_blocks_basics/protocol/juce_BlocksProtocolDefinitions.h
modules/juce_blocks_basics/topology/internal/juce_BlockImplementation.cpp
modules/juce_blocks_basics/topology/internal/juce_DepreciatedVersionReader.cpp
modules/juce_blocks_basics/topology/internal/juce_Detector.cpp
modules/juce_blocks_basics/topology/internal/juce_MIDIDeviceDetector.cpp
modules/juce_blocks_basics/topology/juce_BlockGraph.h
modules/juce_blocks_basics/topology/juce_Topology.h
modules/juce_box2d/juce_box2d.h
modules/juce_core/containers/juce_Array.h
modules/juce_core/containers/juce_ArrayBase.cpp
modules/juce_core/containers/juce_DynamicObject.h
modules/juce_core/containers/juce_PropertySet.h
modules/juce_core/containers/juce_Variant.h
modules/juce_core/files/juce_File.cpp
modules/juce_core/javascript/juce_Javascript.cpp
modules/juce_core/juce_core.cpp [changed mode: 0755->0644]
modules/juce_core/juce_core.h
modules/juce_core/logging/juce_FileLogger.h
modules/juce_core/memory/juce_ReferenceCountedObject.h
modules/juce_core/misc/juce_ConsoleApplication.cpp
modules/juce_core/misc/juce_ConsoleApplication.h
modules/juce_core/misc/juce_StdFunctionCompat.cpp [deleted file]
modules/juce_core/misc/juce_StdFunctionCompat.h [deleted file]
modules/juce_core/native/juce_android_Network.cpp
modules/juce_core/native/juce_linux_SystemStats.cpp [changed mode: 0755->0644]
modules/juce_core/native/juce_mac_ClangBugWorkaround.h
modules/juce_core/native/juce_mac_Files.mm
modules/juce_core/native/juce_mac_SystemStats.mm
modules/juce_core/native/juce_mac_Threads.mm
modules/juce_core/native/juce_posix_SharedCode.h
modules/juce_core/native/juce_win32_SystemStats.cpp
modules/juce_core/native/juce_win32_Threads.cpp
modules/juce_core/network/juce_Socket.cpp
modules/juce_core/network/juce_URL.cpp
modules/juce_core/network/juce_WebInputStream.h
modules/juce_core/streams/juce_MemoryOutputStream.h
modules/juce_core/system/juce_StandardHeader.h
modules/juce_core/system/juce_SystemStats.cpp
modules/juce_core/system/juce_SystemStats.h
modules/juce_core/text/juce_LocalisedStrings.h
modules/juce_core/threads/juce_Process.h
modules/juce_core/threads/juce_ReadWriteLock.cpp
modules/juce_core/threads/juce_ReadWriteLock.h
modules/juce_core/threads/juce_ThreadPool.h
modules/juce_core/threads/juce_TimeSliceThread.h
modules/juce_core/threads/juce_WaitableEvent.cpp [new file with mode: 0644]
modules/juce_core/threads/juce_WaitableEvent.h
modules/juce_core/zip/juce_ZipFile.cpp
modules/juce_core/zip/juce_ZipFile.h
modules/juce_cryptography/encryption/juce_BlowFish.h
modules/juce_cryptography/juce_cryptography.h
modules/juce_data_structures/juce_data_structures.h
modules/juce_data_structures/values/juce_ValueTree.h
modules/juce_dsp/containers/juce_AudioBlock.h
modules/juce_dsp/containers/juce_AudioBlock_test.cpp
modules/juce_dsp/containers/juce_SIMDRegister.h
modules/juce_dsp/containers/juce_SIMDRegister_test.cpp
modules/juce_dsp/frequency/juce_FFT.h
modules/juce_dsp/juce_dsp.h
modules/juce_dsp/maths/juce_Matrix.h
modules/juce_dsp/processors/juce_LadderFilter.h
modules/juce_dsp/processors/juce_Oscillator.h
modules/juce_dsp/processors/juce_Oversampling.cpp
modules/juce_dsp/processors/juce_Oversampling.h
modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp
modules/juce_events/interprocess/juce_NetworkServiceDiscovery.cpp
modules/juce_events/interprocess/juce_NetworkServiceDiscovery.h
modules/juce_events/juce_events.h
modules/juce_events/messages/juce_MessageListener.cpp
modules/juce_events/messages/juce_MessageManager.h
modules/juce_events/native/juce_linux_Messaging.cpp
modules/juce_events/native/juce_win32_Messaging.cpp
modules/juce_graphics/colour/juce_Colour.h
modules/juce_graphics/colour/juce_Colours.cpp
modules/juce_graphics/colour/juce_Colours.h
modules/juce_graphics/contexts/juce_GraphicsContext.h
modules/juce_graphics/fonts/juce_Font.h
modules/juce_graphics/fonts/juce_GlyphArrangement.cpp
modules/juce_graphics/fonts/juce_TextLayout.cpp
modules/juce_graphics/fonts/juce_Typeface.h
modules/juce_graphics/geometry/juce_AffineTransform.h
modules/juce_graphics/geometry/juce_Parallelogram.h
modules/juce_graphics/geometry/juce_Path.h
modules/juce_graphics/images/juce_Image.h
modules/juce_graphics/images/juce_ImageConvolutionKernel.h
modules/juce_graphics/juce_graphics.h
modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h
modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm
modules/juce_graphics/native/juce_mac_Fonts.mm
modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp
modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp
modules/juce_gui_basics/buttons/juce_TextButton.h
modules/juce_gui_basics/components/juce_Component.cpp
modules/juce_gui_basics/components/juce_Component.h
modules/juce_gui_basics/drawables/juce_Drawable.h
modules/juce_gui_basics/drawables/juce_SVGParser.cpp
modules/juce_gui_basics/filebrowser/juce_FileChooser.h
modules/juce_gui_basics/filebrowser/juce_FilePreviewComponent.h
modules/juce_gui_basics/juce_gui_basics.h
modules/juce_gui_basics/keyboard/juce_KeyPress.cpp
modules/juce_gui_basics/keyboard/juce_KeyPress.h
modules/juce_gui_basics/keyboard/juce_ModifierKeys.h
modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp
modules/juce_gui_basics/layout/juce_ConcertinaPanel.cpp
modules/juce_gui_basics/layout/juce_SidePanel.cpp
modules/juce_gui_basics/layout/juce_Viewport.cpp
modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp
modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp
modules/juce_gui_basics/menus/juce_PopupMenu.cpp
modules/juce_gui_basics/menus/juce_PopupMenu.h
modules/juce_gui_basics/mouse/juce_ComponentDragger.h
modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp
modules/juce_gui_basics/mouse/juce_DragAndDropTarget.h
modules/juce_gui_basics/mouse/juce_FileDragAndDropTarget.h
modules/juce_gui_basics/mouse/juce_MouseCursor.h
modules/juce_gui_basics/mouse/juce_MouseEvent.h
modules/juce_gui_basics/mouse/juce_MouseInputSource.h
modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h
modules/juce_gui_basics/native/juce_android_ContentSharer.cpp
modules/juce_gui_basics/native/juce_android_Windowing.cpp
modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp
modules/juce_gui_basics/native/juce_ios_FileChooser.mm
modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm
modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp
modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm
modules/juce_gui_basics/native/juce_mac_Windowing.mm
modules/juce_gui_basics/native/juce_win32_FileChooser.cpp
modules/juce_gui_basics/native/juce_win32_Windowing.cpp
modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.h
modules/juce_gui_basics/properties/juce_PropertyPanel.h
modules/juce_gui_basics/widgets/juce_ComboBox.cpp
modules/juce_gui_basics/widgets/juce_ComboBox.h
modules/juce_gui_basics/widgets/juce_Slider.h
modules/juce_gui_basics/widgets/juce_TableHeaderComponent.h
modules/juce_gui_basics/widgets/juce_TreeView.h
modules/juce_gui_basics/windows/juce_AlertWindow.cpp
modules/juce_gui_basics/windows/juce_DialogWindow.h
modules/juce_gui_basics/windows/juce_ResizableWindow.h
modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.h
modules/juce_gui_extra/embedding/juce_ScopedDPIAwarenessDisabler.h
modules/juce_gui_extra/juce_gui_extra.h
modules/juce_gui_extra/misc/juce_BubbleMessageComponent.h
modules/juce_gui_extra/misc/juce_ColourSelector.cpp
modules/juce_gui_extra/misc/juce_ColourSelector.h
modules/juce_gui_extra/misc/juce_PushNotifications.h
modules/juce_gui_extra/native/juce_android_PushNotifications.cpp
modules/juce_gui_extra/native/juce_ios_PushNotifications.cpp
modules/juce_gui_extra/native/juce_mac_PushNotifications.cpp
modules/juce_gui_extra/native/juce_mac_SystemTrayIcon.cpp
modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp
modules/juce_opengl/juce_opengl.h
modules/juce_opengl/native/juce_OpenGL_ios.h
modules/juce_opengl/opengl/juce_OpenGLContext.cpp
modules/juce_opengl/opengl/juce_OpenGLContext.h
modules/juce_osc/juce_osc.h
modules/juce_osc/osc/juce_OSCAddress.h
modules/juce_osc/osc/juce_OSCTimeTag.h
modules/juce_product_unlocking/in_app_purchases/juce_InAppPurchases.cpp
modules/juce_product_unlocking/in_app_purchases/juce_InAppPurchases.h
modules/juce_product_unlocking/juce_product_unlocking.h
modules/juce_product_unlocking/marketplace/juce_OnlineUnlockForm.h
modules/juce_product_unlocking/native/javaopt/app/com/roli/juce/JuceBillingClient.java [new file with mode: 0644]
modules/juce_product_unlocking/native/juce_android_InAppPurchases.cpp
modules/juce_product_unlocking/native/juce_ios_InAppPurchases.cpp
modules/juce_video/juce_video.h
modules/juce_video/native/juce_android_CameraDevice.h
modules/juce_video/native/juce_ios_CameraDevice.h

index 61d162fcc17cce9748ce6cbc61515e84f3a8afcf..93754f7156813bb37cc075010c320f796ac948c1 100644 (file)
@@ -1,9 +1,105 @@
 JUCE breaking changes
 =====================
 
+Version 5.4.6
+=============
+
+Change
+------
+AudioProcessorValueTreeState::getRawParameterValue now returns a
+std::atomic<float>* instead of a float*.
+
+Possible Issues
+---------------
+Existing code which explicitly mentions the type of the returned value, or
+interacts with the dereferenced float in ways unsupported by the std::atomic
+wrapper, will fail to compile. Certain evaluation-reordering compiler
+optimisations may no longer be possible.
+
+Workaround
+----------
+Update your code to deal with a std::atomic<float>* instead of a float*.
+
+Rationale
+---------
+Returning a std::atomic<float>* allows the JUCE framework to have much stronger
+guarantees about thread safety.
+
+
+Change
+------
+Removed a workaround from the ASIOAudioIODevice::getOutputLatencyInSamples()
+and ASIOAudioIODevice::getInputLatencyInSamples() methods which was adding an
+arbitrary amount to the reported latencies to compensate for dodgy, old
+drivers.
+
+Possible Issues
+---------------
+Code which relied on these altered values may now behave differently.
+
+Workaround
+----------
+Update your code to deal with the new, correct values reported from the drivers
+directly.
+
+Rationale
+---------
+JUCE will now return the latency values as reported by the drivers without
+adding anything to them. The workaround was for old drivers and the current
+drivers should report the correct values without the need for the workaround.
+
+
+Change
+------
+The default behaviour of the AU and AUv3 plug-in wrappers is now to call
+get/setStateInformation instead of get/setProgramStateInformation.
+
+Possible Issues
+---------------
+AudioProcessor subclasses which have overridden the default implementations of
+get/setProgramStateInformation (which simply call through to
+get/setStateInformation) may be unable to load previously saved state; state
+previously saved via a call to getProgramStateInformation will be presented to
+setStateInformation.
+
+Workaround
+----------
+Enable the JUCE_AU_WRAPPERS_SAVE_PROGRAM_STATES configuration option in the
+juce_audio_plugin_client module to preserve backwards compatibility if
+required.
+
+Rationale
+---------
+When using overridden get/setProgramStateInformation methods the previous
+behaviour of the AU and AUv3 wrappers does not correctly save and restore
+state.
+
+
 Version 5.4.5
 =============
 
+Change
+------
+The alignment of text rendered on macOS using CoreGraphics may have shifted
+slightly, depending on the font you have used. The default macOS font has
+shifted downwards.
+
+Possible Issues
+---------------
+Meticulously aligned text components of a GUI may now be misaligned.
+
+Workaround
+----------
+Use a custom LookAndFeel to change the location where text is drawn, or use a
+different font that matches the previous alignment of your original font.
+
+Rationale
+---------
+This was an unintentional change resulting from moving away from a deprecated
+macOS text API. The new alignment is consistent with other rendering engines
+(web browsers and text editors) and the software renderer.
+
+
 Change
 ------
 The JUCEApplicationBase::backButtonPressed() method now returns a bool to
index bf40c1c39ec9b1d15868bb4300507694fa4b9183..8be146308ceb05231d1d75f6624b6a0736fb99ec 100644 (file)
@@ -3,6 +3,15 @@
 This file just lists the more notable headline features. For more detailed info\r
 about minor changes and bugfixes, please see the git log!\r
 \r
+Version 5.4.6\r
+  - Fixed compatibility with macOS versions below 10.11\r
+  - Multiple thread safety improvements\r
+  - Added dynamic parameter and parameter group names\r
+  - Updated to the latest Android In-App Purchases API\r
+  - Improvements to the Windows message queue under high load\r
+  - Replaced WaitableEvent internals with std::condition_variable\r
+  - Fixed some macOS text alignment issues\r
+\r
 Version 5.4.5\r
   - Improved message queue performance on Linux\r
   - Added missing lifecycle callbacks on Android Q\r
index c6438e27edab4b84399199d38bed9b03ccf599d4..0893cfc0d77392119b7fc4c180a9da095c4e349c 100644 (file)
@@ -19,7 +19,7 @@
 \r
 #pragma once\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 \r
 #ifndef PIP_DEMO_UTILITIES_INCLUDED\r
  #define PIP_DEMO_UTILITIES_INCLUDED 1\r
index ed454ebf910533278a80defff305fff43e5758ff..d3539397d201f9d6996bfaf25aa6edbbca4b87d0 100644 (file)
@@ -409,7 +409,7 @@ public:
                     setLEDProgram (*activeBlock);\r
                 }\r
 \r
-                // Make the on screen Lighpad component visible\r
+                // Make the on screen Lightpad component visible\r
                 lightpadComponent.setVisible (true);\r
                 infoLabel.setVisible (false);\r
 \r
@@ -566,7 +566,7 @@ private:
                 return;\r
             }\r
 \r
-            // If there is no ActiveLED obejct for this LED then create one,\r
+            // If there is no ActiveLED object for this LED then create one,\r
             // add it to the array, set the LED on the Block and return\r
             if (index < 0)\r
             {\r
index 3656ccccb1dcf90f3a7a2d14b112e2a99b3fcfc8..c92c0e63b21aa13d2843d67897411c22aa418c3b 100644 (file)
@@ -95,7 +95,7 @@ public:
             button->removeListener (this);\r
     }\r
 \r
-    /** Called periodically to update the tooltip with inforamtion about the Block */\r
+    /** Called periodically to update the tooltip with information about the Block */\r
     void updateStatsAndTooltip()\r
     {\r
         // Get the battery level of this Block and inform any subclasses\r
@@ -972,6 +972,8 @@ private:
     }\r
 \r
     //==============================================================================\r
+    TooltipWindow tooltipWindow;\r
+\r
     PhysicalTopologySource topologySource;\r
     OwnedArray<BlockComponent> blockComponents;\r
     BlockComponent* masterBlockComponent = nullptr;\r
index a6fa1d43bd62cb984e8ca8ff6025993553a131ab..c75d3d7ce7ad92be72d1cc4ffdbb5fc5b9ef02f1 100644 (file)
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
 add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
 set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
 
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY=\"com/roli/juce/JuceActivity\"" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=5.4.5" "-DJUCE_APP_VERSION_HEX=0x50405")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY=\"com/roli/juce/JuceActivity\"" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=5.4.6" "-DJUCE_APP_VERSION_HEX=0x50406")
 
 include_directories( AFTER
     "../../../JuceLibraryCode"
@@ -729,8 +729,6 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/misc/juce_Result.h"
     "../../../../../modules/juce_core/misc/juce_RuntimePermissions.cpp"
     "../../../../../modules/juce_core/misc/juce_RuntimePermissions.h"
-    "../../../../../modules/juce_core/misc/juce_StdFunctionCompat.cpp"
-    "../../../../../modules/juce_core/misc/juce_StdFunctionCompat.h"
     "../../../../../modules/juce_core/misc/juce_Uuid.cpp"
     "../../../../../modules/juce_core/misc/juce_Uuid.h"
     "../../../../../modules/juce_core/misc/juce_WindowsRegistry.h"
@@ -846,6 +844,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/threads/juce_ThreadPool.h"
     "../../../../../modules/juce_core/threads/juce_TimeSliceThread.cpp"
     "../../../../../modules/juce_core/threads/juce_TimeSliceThread.h"
+    "../../../../../modules/juce_core/threads/juce_WaitableEvent.cpp"
     "../../../../../modules/juce_core/threads/juce_WaitableEvent.h"
     "../../../../../modules/juce_core/time/juce_PerformanceCounter.cpp"
     "../../../../../modules/juce_core/time/juce_PerformanceCounter.h"
@@ -2334,8 +2333,6 @@ set_source_files_properties("../../../../../modules/juce_core/misc/juce_Result.c
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Result.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_RuntimePermissions.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_RuntimePermissions.h" PROPERTIES HEADER_FILE_ONLY TRUE)
-set_source_files_properties("../../../../../modules/juce_core/misc/juce_StdFunctionCompat.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
-set_source_files_properties("../../../../../modules/juce_core/misc/juce_StdFunctionCompat.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Uuid.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Uuid.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_WindowsRegistry.h" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2451,6 +2448,7 @@ set_source_files_properties("../../../../../modules/juce_core/threads/juce_Threa
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_ThreadPool.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_TimeSliceThread.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_TimeSliceThread.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_core/threads/juce_WaitableEvent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_WaitableEvent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/time/juce_PerformanceCounter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/time/juce_PerformanceCounter.h" PROPERTIES HEADER_FILE_ONLY TRUE)
index 80922f549eddf28920fff6ed24591a5d7c2831be..f577cd8c09675f5d1fa1b238a93d9f05587cfac8 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="5.4.5"
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="5.4.6"
           package="com.juce.demorunner">
   <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"/>
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
@@ -10,6 +10,7 @@
   <uses-permission android:name="android.permission.BLUETOOTH"/>
   <uses-permission android:name="android.permission.CAMERA"/>
   <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+  <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-feature android:glEsVersion="0x00030000" android:required="true"/>
   <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false">
index c6438e27edab4b84399199d38bed9b03ccf599d4..0893cfc0d77392119b7fc4c180a9da095c4e349c 100644 (file)
@@ -19,7 +19,7 @@
 \r
 #pragma once\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 \r
 #ifndef PIP_DEMO_UTILITIES_INCLUDED\r
  #define PIP_DEMO_UTILITIES_INCLUDED 1\r
index 2df9a8e7076a7c1110c575417185fcd99f0e8e02..cfd3a2f8b52ed9e0f43513b48d34aa4898905c8e 100644 (file)
@@ -4,7 +4,7 @@ buildscript {
        jcenter()
    }
    dependencies {
-       classpath 'com.android.tools.build:gradle:3.2.1'
+       classpath 'com.android.tools.build:gradle:3.5.3'
    }
 }
 
index b460908d4f41c2a33b8090ee16c36e6fe85f7433..b66802c71420c8d2327970a31630797f9076bf53 100644 (file)
@@ -1 +1 @@
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
\ No newline at end of file
index a63eabe4e271695c876eea748a0fc00096a95a7b..56acdc6f4c2f800c8b2667d79c00b03adb0a7f30 100644 (file)
@@ -35,7 +35,7 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := -march=native
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DDEBUG=1 -D_DEBUG=1 -DJUCE_DEMO_RUNNER=1 -DJUCE_UNIT_TESTS=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=5.4.5 -DJUCE_APP_VERSION_HEX=0x50405 $(shell pkg-config --cflags alsa x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0 libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DDEBUG=1 -D_DEBUG=1 -DJUCE_DEMO_RUNNER=1 -DJUCE_UNIT_TESTS=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=5.4.6 -DJUCE_APP_VERSION_HEX=0x50406 $(shell pkg-config --cflags alsa x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0 libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0 -DJucePlugin_Build_Unity=0
   JUCE_TARGET_APP := DemoRunner
 
@@ -56,7 +56,7 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := -march=native
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DNDEBUG=1 -DJUCE_DEMO_RUNNER=1 -DJUCE_UNIT_TESTS=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=5.4.5 -DJUCE_APP_VERSION_HEX=0x50405 $(shell pkg-config --cflags alsa x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0 libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DNDEBUG=1 -DJUCE_DEMO_RUNNER=1 -DJUCE_UNIT_TESTS=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=5.4.6 -DJUCE_APP_VERSION_HEX=0x50406 $(shell pkg-config --cflags alsa x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0 libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0 -DJucePlugin_Build_Unity=0
   JUCE_TARGET_APP := DemoRunner
 
diff --git a/examples/DemoRunner/Builds/MacOSX/App.entitlements b/examples/DemoRunner/Builds/MacOSX/App.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
diff --git a/examples/DemoRunner/Builds/MacOSX/DemoRunner.entitlements b/examples/DemoRunner/Builds/MacOSX/DemoRunner.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 0aee90e6137106e01165ba1a53cc35f9e7607f28..2b5ef85586080180c71156c177fb7ae8195354f1 100644 (file)
                        isa = PBXBuildFile;
                        fileRef = 96D99A08027CA35D6A4E5CFD;
                };
+               47ED2C78B05B8A6A00E36C46 = {
+                       isa = PBXBuildFile;
+                       fileRef = 685A261BE78585293F3EAD36;
+               };
                D3D8CDCE42E8BE31C7247E38 = {
                        isa = PBXBuildFile;
                        fileRef = 0ECB4FCD24794CE516792552;
                        path = "../../../../modules/juce_audio_utils";
                        sourceTree = "SOURCE_ROOT";
                };
-               0CCFDC1D1C7B8A12BF4822F1 = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = DemoRunner.entitlements;
-                       path = DemoRunner.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                0ECB4FCD24794CE516792552 = {
                        isa = PBXFileReference;
                        lastKnownFileType = folder;
                        path = "../../../../modules/juce_audio_basics";
                        sourceTree = "SOURCE_ROOT";
                };
+               685A261BE78585293F3EAD36 = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = folder;
+                       name = Assets;
+                       path = ../../../Assets;
+                       sourceTree = "<group>";
+               };
                6C198AF93E1F6E682189E2F6 = {
                        isa = PBXFileReference;
                        lastKnownFileType = file;
                D87DCD5DA4EC8D78DFF37FCC = {
                        isa = PBXGroup;
                        children = (
+                               685A261BE78585293F3EAD36,
                                0ECB4FCD24794CE516792552,
                                388A8209DBB1B08594266121,
                                5CD17151385A69F1E07FE85B,
                                        "JUCE_DEMO_RUNNER=1",
                                        "JUCE_UNIT_TESTS=1",
                                        "JUCER_XCODE_MAC_F6D2F4CF=1",
-                                       "JUCE_APP_VERSION=5.4.5",
-                                       "JUCE_APP_VERSION_HEX=0x50405",
+                                       "JUCE_APP_VERSION=5.4.6",
+                                       "JUCE_APP_VERSION_HEX=0x50406",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                                        "JUCE_DEMO_RUNNER=1",
                                        "JUCE_UNIT_TESTS=1",
                                        "JUCER_XCODE_MAC_F6D2F4CF=1",
-                                       "JUCE_APP_VERSION=5.4.5",
-                                       "JUCE_APP_VERSION_HEX=0x50405",
+                                       "JUCE_APP_VERSION=5.4.6",
+                                       "JUCE_APP_VERSION_HEX=0x50406",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "DemoRunner";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                PRODUCT_NAME = "DemoRunner";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               47ED2C78B05B8A6A00E36C46,
                                D3D8CDCE42E8BE31C7247E38,
                                3B3952A9A14320312EF890A5,
                                41BAB55E0D992708EF06E2C4,
index 9aee797cfb36bdbaf0a0ad1a7cb70c326d8245af..2c5d4b3840f320c7355de2784192e045af08c7d3 100644 (file)
@@ -22,9 +22,9 @@
     <key>CFBundleSignature</key>\r
     <string>????</string>\r
     <key>CFBundleShortVersionString</key>\r
-    <string>5.4.5</string>\r
+    <string>5.4.6</string>\r
     <key>CFBundleVersion</key>\r
-    <string>5.4.5</string>\r
+    <string>5.4.6</string>\r
     <key>NSHumanReadableCopyright</key>\r
     <string>Copyright (c) 2018 - ROLI Ltd.</string>\r
     <key>NSHighResolutionCapable</key>\r
index 05447de16eb397ac9c2e26442ad205bff46cf0ca..b0db8d97f3547b9da701c752f1598892a91288bf 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index d669b59020bf02febba3cc0271b5e3cd0570d3d5..8bdd409cffa04a1c955de06fa657661231728142 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index b9e17aa798ca8c02a2343347b8cf8c0a004f5604..ea054be68ae4bca76e54c88c42ae8b430eaf367e 100644 (file)
@@ -7,7 +7,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  5,4,5,0\r
+FILEVERSION  5,4,6,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -16,9 +16,9 @@ BEGIN
       VALUE "CompanyName",  "ROLI Ltd.\0"\r
       VALUE "LegalCopyright",  "Copyright (c) 2018 - ROLI Ltd.\0"\r
       VALUE "FileDescription",  "DemoRunner\0"\r
-      VALUE "FileVersion",  "5.4.5\0"\r
+      VALUE "FileVersion",  "5.4.6\0"\r
       VALUE "ProductName",  "DemoRunner\0"\r
-      VALUE "ProductVersion",  "5.4.5\0"\r
+      VALUE "ProductVersion",  "5.4.6\0"\r
     END\r
   END\r
 \r
index cd93c15b80fdec998935e00df8b63649db79cf11..0f6f601f44c998567d634523064c100d413686e7 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 1c01ce48da0abc4190cf18957c8d9e7d30237778..4b163b6d3308b839fcb7efee623efed70cc59311 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index b9e17aa798ca8c02a2343347b8cf8c0a004f5604..ea054be68ae4bca76e54c88c42ae8b430eaf367e 100644 (file)
@@ -7,7 +7,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  5,4,5,0\r
+FILEVERSION  5,4,6,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -16,9 +16,9 @@ BEGIN
       VALUE "CompanyName",  "ROLI Ltd.\0"\r
       VALUE "LegalCopyright",  "Copyright (c) 2018 - ROLI Ltd.\0"\r
       VALUE "FileDescription",  "DemoRunner\0"\r
-      VALUE "FileVersion",  "5.4.5\0"\r
+      VALUE "FileVersion",  "5.4.6\0"\r
       VALUE "ProductName",  "DemoRunner\0"\r
-      VALUE "ProductVersion",  "5.4.5\0"\r
+      VALUE "ProductVersion",  "5.4.6\0"\r
     END\r
   END\r
 \r
index 8ce8e59268ca3f08afb3beab14d0908ff11beda5..779d691d006ec28876e0ac0245f68eb8f56070d6 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 71680ce40424f4f53cd83d0dc2277bef06adc64d..334070cb99372c7ec2ca0071ac45e0429ae7d11b 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index b9e17aa798ca8c02a2343347b8cf8c0a004f5604..ea054be68ae4bca76e54c88c42ae8b430eaf367e 100644 (file)
@@ -7,7 +7,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  5,4,5,0\r
+FILEVERSION  5,4,6,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -16,9 +16,9 @@ BEGIN
       VALUE "CompanyName",  "ROLI Ltd.\0"\r
       VALUE "LegalCopyright",  "Copyright (c) 2018 - ROLI Ltd.\0"\r
       VALUE "FileDescription",  "DemoRunner\0"\r
-      VALUE "FileVersion",  "5.4.5\0"\r
+      VALUE "FileVersion",  "5.4.6\0"\r
       VALUE "ProductName",  "DemoRunner\0"\r
-      VALUE "ProductVersion",  "5.4.5\0"\r
+      VALUE "ProductVersion",  "5.4.6\0"\r
     END\r
   END\r
 \r
diff --git a/examples/DemoRunner/Builds/iOS/App.entitlements b/examples/DemoRunner/Builds/iOS/App.entitlements
new file mode 100644 (file)
index 0000000..42bc7ba
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>com.apple.developer.icloud-container-identifiers</key>
+       <array>
+        <string>iCloud.$(CFBundleIdentifier)</string>
+    </array>
+       <key>com.apple.developer.icloud-services</key>
+       <array>
+        <string>CloudDocuments</string>
+    </array>
+       <key>com.apple.developer.ubiquity-container-identifiers</key>
+       <array>
+        <string>iCloud.$(CFBundleIdentifier)</string>
+    </array>
+</dict>
+</plist>
diff --git a/examples/DemoRunner/Builds/iOS/DemoRunner.entitlements b/examples/DemoRunner/Builds/iOS/DemoRunner.entitlements
deleted file mode 100644 (file)
index 42bc7ba..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-       <key>com.apple.developer.icloud-container-identifiers</key>
-       <array>
-        <string>iCloud.$(CFBundleIdentifier)</string>
-    </array>
-       <key>com.apple.developer.icloud-services</key>
-       <array>
-        <string>CloudDocuments</string>
-    </array>
-       <key>com.apple.developer.ubiquity-container-identifiers</key>
-       <array>
-        <string>iCloud.$(CFBundleIdentifier)</string>
-    </array>
-</dict>
-</plist>
index 5751f07482d9c0c6aee80d40bccdd9c64bdd3e70..49d4408e1440365171fc80f17d69586da1f6e12f 100644 (file)
                        path = "../../../../modules/juce_audio_utils";
                        sourceTree = "SOURCE_ROOT";
                };
-               0CCFDC1D1C7B8A12BF4822F1 = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = DemoRunner.entitlements;
-                       path = DemoRunner.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                112FFCB73597157E721BCDF2 = {
                        isa = PBXFileReference;
                        lastKnownFileType = file;
                        path = ../../Source/Main.cpp;
                        sourceTree = "SOURCE_ROOT";
                };
+               2CDA0CB288452DA016E874BC = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.plist.xml;
+                       name = App.entitlements;
+                       path = App.entitlements;
+                       sourceTree = "SOURCE_ROOT";
+               };
                346450C70C964FD9640B6086 = {
                        isa = PBXFileReference;
                        lastKnownFileType = file;
                                CLANG_CXX_LANGUAGE_STANDARD = "c++14";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_ENTITLEMENTS = "DemoRunner.entitlements";
+                               CODE_SIGN_ENTITLEMENTS = "App.entitlements";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                COPY_PHASE_STRIP = NO;
                                        "JUCE_DEMO_RUNNER=1",
                                        "JUCE_UNIT_TESTS=1",
                                        "JUCER_XCODE_IPHONE_5BC26AE3=1",
-                                       "JUCE_APP_VERSION=5.4.5",
-                                       "JUCE_APP_VERSION_HEX=0x50405",
+                                       "JUCE_APP_VERSION=5.4.6",
+                                       "JUCE_APP_VERSION_HEX=0x50406",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                                CLANG_CXX_LANGUAGE_STANDARD = "c++14";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_ENTITLEMENTS = "DemoRunner.entitlements";
+                               CODE_SIGN_ENTITLEMENTS = "App.entitlements";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                DEAD_CODE_STRIPPING = YES;
                                        "JUCE_DEMO_RUNNER=1",
                                        "JUCE_UNIT_TESTS=1",
                                        "JUCER_XCODE_IPHONE_5BC26AE3=1",
-                                       "JUCE_APP_VERSION=5.4.5",
-                                       "JUCE_APP_VERSION_HEX=0x50405",
+                                       "JUCE_APP_VERSION=5.4.6",
+                                       "JUCE_APP_VERSION_HEX=0x50406",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
index 39de13f091897e8f4800b39f867e08c1218abebd..1b8b1b7042a26341b6d2297805e11d7d2c04659a 100644 (file)
@@ -30,9 +30,9 @@
     <key>CFBundleSignature</key>\r
     <string>????</string>\r
     <key>CFBundleShortVersionString</key>\r
-    <string>5.4.5</string>\r
+    <string>5.4.6</string>\r
     <key>CFBundleVersion</key>\r
-    <string>5.4.5</string>\r
+    <string>5.4.6</string>\r
     <key>NSHumanReadableCopyright</key>\r
     <string>Copyright (c) 2018 - ROLI Ltd.</string>\r
     <key>NSHighResolutionCapable</key>\r
index 4a28f30c59937764ca5dc47a8a832a534ddf04d3..56059d32cb98108529d14b3685921598210a8847 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 \r
-<JUCERPROJECT name="DemoRunner" projectType="guiapp" jucerVersion="5.4.5" defines="JUCE_DEMO_RUNNER=1&#10;JUCE_UNIT_TESTS=1"\r
-              bundleIdentifier="com.juce.demorunner" version="5.4.5" companyName="ROLI Ltd."\r
+<JUCERPROJECT name="DemoRunner" projectType="guiapp" jucerVersion="5.4.6" defines="JUCE_DEMO_RUNNER=1&#10;JUCE_UNIT_TESTS=1"\r
+              bundleIdentifier="com.juce.demorunner" version="5.4.6" companyName="ROLI Ltd."\r
               companyCopyright="Copyright (c) 2018 - ROLI Ltd." companyWebsite="https://www.juce.com/"\r
               companyEmail="info@juce.com" id="yj7xMM" reportAppUsage="1">\r
   <MAINGROUP id="G8kbr7" name="DemoRunner">\r
@@ -30,7 +30,7 @@
   </MAINGROUP>\r
   <EXPORTFORMATS>\r
     <XCODE_MAC targetFolder="Builds/MacOSX" smallIcon="YyqWd2" bigIcon="YyqWd2"\r
-               customXcodeResourceFolders="../Audio &#10;../BLOCKS &#10;../DSP &#10;../GUI &#10;../Utilities"\r
+               customXcodeResourceFolders="../Assets&#10;../Audio &#10;../BLOCKS &#10;../DSP &#10;../GUI &#10;../Utilities"\r
                microphonePermissionNeeded="1" cameraPermissionNeeded="1">\r
       <CONFIGURATIONS>\r
         <CONFIGURATION isDebug="1" name="Debug" recommendedWarnings="LLVM"/>\r
index fd7cbb98922c7143dc59bd407eeba7a9237578b3..048b13f167f6708e3486e3e341ae1894dd2bbe98 100644 (file)
@@ -47,7 +47,7 @@
 \r
 #define JUCE_USE_DARK_SPLASH_SCREEN 1\r
 \r
-#define JUCE_PROJUCER_VERSION 0x50405\r
+#define JUCE_PROJUCER_VERSION 0x50406\r
 \r
 //==============================================================================\r
 #define JUCE_MODULE_AVAILABLE_juce_analytics              1\r
 //==============================================================================\r
 // juce_events flags:\r
 \r
-#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK\r
- //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 0\r
+#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK\r
+ //#define JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 0\r
 #endif\r
 \r
 //==============================================================================\r
index c1d016dd9018df98980d0c65aec5740c822ad514..0d632903da66c15ce1210b37db745da3235b3d4c 100644 (file)
@@ -56,7 +56,7 @@ namespace ProjectInfo
 {\r
     const char* const  projectName    = "DemoRunner";\r
     const char* const  companyName    = "ROLI Ltd.";\r
-    const char* const  versionString  = "5.4.5";\r
-    const int          versionNumber  = 0x50405;\r
+    const char* const  versionString  = "5.4.6";\r
+    const int          versionNumber  = 0x50406;\r
 }\r
 #endif\r
index 9fe417f9eaf3fff217fb3bff5babca52c7861db6..f030078ef837e166a17d3bccd65f59a27b5bb82a 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "../../../Assets/DemoUtilities.h"\r
 #include "JUCEDemos.h"\r
 \r
index b7d95de83a5fbb9285a2e0d24537f14f3b3ddd07..d2584529bdca0ce46302d83eeede741bb169f66c 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "../../../Assets/DemoUtilities.h"\r
 #include "JUCEDemos.h"\r
 \r
index e60922167096bc56e2ecc826be49024a2b94912a..9c7f5132d3b417f5dae06dc9c60b18ea759ba598 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "../../../Assets/DemoUtilities.h"\r
 #include "JUCEDemos.h"\r
 \r
index edbd8f8e616b223fbcdc90712e2c95ee14c78747..537d83079c3d84fe8649f6a181eaeaba252f8ef1 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "../../Assets/DemoUtilities.h"\r
 \r
 #include "UI/MainComponent.h"\r
index 1c6d9a3562282ba1a8aac29d927dd51d35149f95..c00b8165e0bd1d2fe94e1cf36101ab916a7ba07f 100644 (file)
@@ -103,7 +103,7 @@ struct CodeContent    : public Component
 //==============================================================================\r
 DemoContentComponent::DemoContentComponent (Component& mainComponent, std::function<void(bool)> callback)\r
     : TabbedComponent (TabbedButtonBar::Orientation::TabsAtTop),\r
-      demoChangedCallback (callback)\r
+      demoChangedCallback (std::move (callback))\r
 {\r
     demoContent.reset (new DemoContent());\r
     addTab ("Demo",     Colours::transparentBlack, demoContent.get(), false);\r
index b4daee1140be4e78522ff21baab22721d95b5d18..7a15f5372d7295bbfb073a82f75e11449b343555 100644 (file)
@@ -26,7 +26,7 @@
 \r
 #pragma once\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "../Demos/JUCEDemos.h"\r
 \r
 struct DemoContent;\r
index 5833cb917138c37fdddf757c48b29325e67b6327..24863830204a73293fe3bb8e8b3a186350e82737 100644 (file)
@@ -26,7 +26,7 @@
 \r
 #pragma once\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "DemoContentComponent.h"\r
 \r
 //==============================================================================\r
index baeb14d95bd311f0352f1f5704b8817c720ec7b2..035fd8c54424d29e850642133ab0981fcca372ec 100644 (file)
@@ -151,11 +151,13 @@ public:
 \r
         r.removeFromLeft (verticalDividerBar->getRight());\r
 \r
-        styleBox.setBounds (r.removeFromBottom (26));\r
-        r.removeFromBottom (8);\r
-\r
         int labelWidth = 60;\r
 \r
+        auto styleArea = r.removeFromBottom (26);\r
+        styleArea.removeFromLeft (labelWidth);\r
+        styleBox.setBounds (styleArea);\r
+        r.removeFromBottom (8);\r
+\r
         auto row = r.removeFromBottom (30);\r
         row.removeFromLeft (labelWidth);\r
         boldToggle.setBounds (row.removeFromLeft (row.getWidth() / 2));\r
@@ -215,8 +217,8 @@ private:
 \r
     Label heightLabel   { {}, "Height:" },\r
           kerningLabel  { {}, "Kerning:" },\r
-          scaleLabel    { "Scale:" },\r
-          styleLabel    { "Style" };\r
+          scaleLabel    { {}, "Scale:" },\r
+          styleLabel    { {}, "Style:" };\r
 \r
     ToggleButton boldToggle   { "Bold" },\r
                  italicToggle { "Italic" };\r
index 61a0e4fe9909c2fd517469b7a3008a73da86ab8c..478bf4944d14cdc737c9365ba1511c088b635c52 100644 (file)
@@ -126,7 +126,7 @@ private:
         if (selectedFile.existsAsFile())\r
             imagePreview.setImage (ImageCache::getFromFile (selectedFile));\r
 \r
-        // the image cahce is a handly way to load images from files or directly from memory and\r
+        // the image cache is a handy way to load images from files or directly from memory and\r
         // will keep them hanging around for a few seconds in case they are requested elsewhere\r
     }\r
 \r
index 040cebb75aa28a17787086fb40cd3182e90899cf..7b3c06323c8dfce7ff6cdb2cbc284cc8d670ba6b 100644 (file)
@@ -51,7 +51,7 @@
 //==============================================================================\r
 /** The Note class contains text editor used to display and edit the note's contents and will\r
     also listen to changes in the text and mark the FileBasedDocument as 'dirty'. This 'dirty'\r
-    flag is used to promt the user to save the note when it is closed.\r
+    flag is used to prompt the user to save the note when it is closed.\r
  */\r
 class Note    : public Component,\r
                 public FileBasedDocument\r
index 27a622003818cffea932ac12a53c295baffd44f6..9ee29bccb9b617989b8d62018937bafa36680084 100644 (file)
@@ -87,7 +87,12 @@ public:
 \r
     void clicked() override\r
     {\r
-        auto* colourSelector = new ColourSelector();\r
+        auto* colourSelector = new ColourSelector (ColourSelector::showAlphaChannel\r
+                                                   | ColourSelector::showColourAtTop\r
+                                                   | ColourSelector::editableColour\r
+                                                   | ColourSelector::showSliders\r
+                                                   | ColourSelector::showColourspace);\r
+\r
         colourSelector->setName ("background");\r
         colourSelector->setCurrentColour (findColour (TextButton::buttonColourId));\r
         colourSelector->addChangeListener (this);\r
@@ -439,6 +444,8 @@ private:
     OwnedArray<Component> components;\r
     std::unique_ptr<BubbleMessageComponent> bubbleMessage;\r
 \r
+    TooltipWindow tooltipWindow;\r
+\r
     // This little function avoids a bit of code-duplication by adding a component to\r
     // our list as well as calling addAndMakeVisible on it..\r
     template <typename ComponentType>\r
index c159dd582079c2213a81fbf7d630ff0450a7b9cd..4b750e86ce1a6c6afbc752fc0b135af8cd81ffb2 100644 (file)
@@ -180,7 +180,7 @@ public:
 \r
     void processBlock (AudioBuffer<float>& buffer, MidiBuffer&) override\r
     {\r
-        auto gain = *parameters.getRawParameterValue ("gain");\r
+        float gain = *parameters.getRawParameterValue ("gain");\r
 \r
         auto totalNumInputChannels  = getTotalNumInputChannels();\r
         auto totalNumOutputChannels = getTotalNumOutputChannels();\r
index f726acbef886e3c4dca9b6fcaa5cb50262d92acf..7937857d6f0e3f393aac1118395b370136422a0e 100644 (file)
 \r
 #include "../Assets/DemoUtilities.h"\r
 \r
+/*\r
+    To finish the setup of this demo, do the following in the Projucer project:\r
+\r
+    1. In the project settings, set the "Bundle Identifier" to com.roli.juceInAppPurchaseSample\r
+    2. In the Android exporter settings, change the following settings:\r
+         - "In-App Billing" - Enabled\r
+         - "Key Signing: key.store" - path to InAppPurchase.keystore file in examples/Assets/Signing\r
+         - "Key Signing: key.store.password" - amazingvoices\r
+         - "Key Signing: key-alias" - InAppPurchase\r
+         - "Key Signing: key.alias.password" - amazingvoices\r
+    3. Re-save the project\r
+*/\r
+\r
 //==============================================================================\r
 class VoicePurchases      : private InAppPurchases::Listener\r
 {\r
@@ -108,7 +121,7 @@ public:
                 purchaseInProgress = true;\r
 \r
                 product.purchaseInProgress = true;\r
-                InAppPurchases::getInstance()->purchaseProduct (product.identifier, false);\r
+                InAppPurchases::getInstance()->purchaseProduct (product.identifier);\r
 \r
                 guiUpdater.triggerAsyncUpdate();\r
             }\r
index 85123712732baf2e4caa0d2464b1d966a66f9d1d..5e6294e406c44521730cc2e88c663dc0fd88b6f7 100644 (file)
@@ -149,6 +149,8 @@ static String getAllSystemInfo()
       << "CPU model:               " << SystemStats::getCpuModel()  << newLine\r
       << "CPU speed:               " << SystemStats::getCpuSpeedInMegahertz() << " MHz" << newLine\r
       << "CPU has MMX:             " << (SystemStats::hasMMX()             ? "yes" : "no") << newLine\r
+      << "CPU has FMA3:            " << (SystemStats::hasFMA3()            ? "yes" : "no") << newLine\r
+      << "CPU has FMA4:            " << (SystemStats::hasFMA4()            ? "yes" : "no") << newLine\r
       << "CPU has SSE:             " << (SystemStats::hasSSE()             ? "yes" : "no") << newLine\r
       << "CPU has SSE2:            " << (SystemStats::hasSSE2()            ? "yes" : "no") << newLine\r
       << "CPU has SSE3:            " << (SystemStats::hasSSE3()            ? "yes" : "no") << newLine\r
index 01b29a89fcf448a943b2138e2b7a47b78fc13774..56ca48e3a5f0d9d80218a1027edf482cf564e31c 100644 (file)
@@ -134,7 +134,7 @@ private:
         {\r
             stopFlashing();\r
             sendChangeMessage();\r
-            // Once we've finsihed flashing send a change message to trigger the next component to flash\r
+            // Once we've finished flashing send a change message to trigger the next component to flash\r
         }\r
 \r
         repaint();\r
@@ -173,7 +173,7 @@ public:
         addAndMakeVisible (randomColourButton);\r
         randomColourButton.onClick = [this] { randomColourButtonClicked(); };\r
 \r
-        // lay out our components in a psudo random grid\r
+        // lay out our components in a pseudo random grid\r
         Rectangle<int> area (0, 100, 150, 150);\r
 \r
         for (auto* comp : flashingComponents)\r
index 79d18661a22afb6da0761c6d8dd7e470572920f2..b780a1deb6d4bef5bbea060070a5e70253708225 100644 (file)
@@ -345,7 +345,7 @@ private:
         resultsTree.setRootItem (rootItem.get());\r
     }\r
 \r
-    /** Parses the editors contects as XML. */\r
+    /** Parses the editor's contents as XML. */\r
     TreeViewItem* rebuildXml()\r
     {\r
         parsedXml.reset();\r
@@ -368,7 +368,7 @@ private:
         return new XmlTreeItem (*parsedXml);\r
     }\r
 \r
-    /** Parses the editors contects as JSON. */\r
+    /** Parses the editor's contents as JSON. */\r
     TreeViewItem* rebuildJson()\r
     {\r
         var parsedJson;\r
index f030db71421d907e9e5ed5c9eba64b4cec184b5f..61c0a854e33b66de7cc2f6a426cd1b7260fe0517 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 \r
 <JUCERPROJECT id="AKfc5m" name="AudioPerformanceTest" projectType="guiapp"\r
-              bundleIdentifier="com.juce.AudioPerformanceTest" jucerVersion="5.4.5"\r
+              bundleIdentifier="com.juce.AudioPerformanceTest" jucerVersion="5.4.6"\r
               displaySplashScreen="0" reportAppUsage="0" companyName="ROLI Ltd."\r
               companyCopyright="ROLI Ltd.">\r
   <MAINGROUP id="b1eVTe" name="AudioPerformanceTest">\r
index 90e4d179577faa359ad2a277627b815a8a546058..762bb07feee83c7bd23c713f27d7380fad969704 100644 (file)
@@ -568,8 +568,6 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/misc/juce_Result.h"
     "../../../../../modules/juce_core/misc/juce_RuntimePermissions.cpp"
     "../../../../../modules/juce_core/misc/juce_RuntimePermissions.h"
-    "../../../../../modules/juce_core/misc/juce_StdFunctionCompat.cpp"
-    "../../../../../modules/juce_core/misc/juce_StdFunctionCompat.h"
     "../../../../../modules/juce_core/misc/juce_Uuid.cpp"
     "../../../../../modules/juce_core/misc/juce_Uuid.h"
     "../../../../../modules/juce_core/misc/juce_WindowsRegistry.h"
@@ -685,6 +683,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/threads/juce_ThreadPool.h"
     "../../../../../modules/juce_core/threads/juce_TimeSliceThread.cpp"
     "../../../../../modules/juce_core/threads/juce_TimeSliceThread.h"
+    "../../../../../modules/juce_core/threads/juce_WaitableEvent.cpp"
     "../../../../../modules/juce_core/threads/juce_WaitableEvent.h"
     "../../../../../modules/juce_core/time/juce_PerformanceCounter.cpp"
     "../../../../../modules/juce_core/time/juce_PerformanceCounter.h"
@@ -1858,8 +1857,6 @@ set_source_files_properties("../../../../../modules/juce_core/misc/juce_Result.c
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Result.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_RuntimePermissions.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_RuntimePermissions.h" PROPERTIES HEADER_FILE_ONLY TRUE)
-set_source_files_properties("../../../../../modules/juce_core/misc/juce_StdFunctionCompat.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
-set_source_files_properties("../../../../../modules/juce_core/misc/juce_StdFunctionCompat.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Uuid.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Uuid.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_WindowsRegistry.h" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -1975,6 +1972,7 @@ set_source_files_properties("../../../../../modules/juce_core/threads/juce_Threa
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_ThreadPool.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_TimeSliceThread.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_TimeSliceThread.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_core/threads/juce_WaitableEvent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_WaitableEvent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/time/juce_PerformanceCounter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/time/juce_PerformanceCounter.h" PROPERTIES HEADER_FILE_ONLY TRUE)
index de868f8819d73b5a524f6af1245f2d38e7f44320..6a6b111846f2b42dbaaf146cd250ae6ea8295249 100644 (file)
@@ -8,6 +8,7 @@
   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
   <uses-permission android:name="android.permission.BLUETOOTH"/>
+  <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:hardwareAccelerated="false">
     <activity android:name="com.roli.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize"
index 2df9a8e7076a7c1110c575417185fcd99f0e8e02..cfd3a2f8b52ed9e0f43513b48d34aa4898905c8e 100644 (file)
@@ -4,7 +4,7 @@ buildscript {
        jcenter()
    }
    dependencies {
-       classpath 'com.android.tools.build:gradle:3.2.1'
+       classpath 'com.android.tools.build:gradle:3.5.3'
    }
 }
 
index b460908d4f41c2a33b8090ee16c36e6fe85f7433..b66802c71420c8d2327970a31630797f9076bf53 100644 (file)
@@ -1 +1 @@
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
\ No newline at end of file
diff --git a/extras/AudioPerformanceTest/Builds/MacOSX/App.entitlements b/extras/AudioPerformanceTest/Builds/MacOSX/App.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
diff --git a/extras/AudioPerformanceTest/Builds/MacOSX/AudioPerformanceTest.entitlements b/extras/AudioPerformanceTest/Builds/MacOSX/AudioPerformanceTest.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 0772d9b1b02ace95f9515c936c05e1e34fadd3f7..776ea1e1682b3d6432b5f6a58997aed372bb2866 100644 (file)
                        path = "../../JuceLibraryCode/include_juce_audio_utils.mm";
                        sourceTree = "SOURCE_ROOT";
                };
-               C3BE13F50343166A30728D8A = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = AudioPerformanceTest.entitlements;
-                       path = AudioPerformanceTest.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                C8EE61FDD1F06817A014B881 = {
                        isa = PBXFileReference;
                        lastKnownFileType = file;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "AudioPerformanceTest";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                PRODUCT_NAME = "AudioPerformanceTest";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
index 7115eb29b0daf616097a4df72f0ba76be5657e22..8531b49226b3baee2bc5a27ce032e906a8936201 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 3c1483fe17cab5dce1c756e665a0fe4c4cfbe0e7..12212e518715f26496af8a98b4fe3931907a8aae 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
diff --git a/extras/AudioPerformanceTest/Builds/iOS/App.entitlements b/extras/AudioPerformanceTest/Builds/iOS/App.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
diff --git a/extras/AudioPerformanceTest/Builds/iOS/AudioPerformanceTest.entitlements b/extras/AudioPerformanceTest/Builds/iOS/AudioPerformanceTest.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 979f35672b86945dcccc01671f7263278afd2028..54933a532f01650c7e3570605325e48631a7c1fd 100644 (file)
                        path = "../../JuceLibraryCode/include_juce_audio_utils.mm";
                        sourceTree = "SOURCE_ROOT";
                };
-               C3BE13F50343166A30728D8A = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = AudioPerformanceTest.entitlements;
-                       path = AudioPerformanceTest.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                C6030BFC7A19A5075AB0EC28 = {
                        isa = PBXFileReference;
                        lastKnownFileType = wrapper.framework;
index 9032f6ee16486679d489dc4648b42dee51f40909..c03b022dc0ec2fb2a5ea8faaa7d5ad01951fc878 100644 (file)
@@ -47,7 +47,7 @@
 \r
 #define JUCE_USE_DARK_SPLASH_SCREEN 1\r
 \r
-#define JUCE_PROJUCER_VERSION 0x50405\r
+#define JUCE_PROJUCER_VERSION 0x50406\r
 \r
 //==============================================================================\r
 #define JUCE_MODULE_AVAILABLE_juce_audio_basics          1\r
 //==============================================================================\r
 // juce_events flags:\r
 \r
-#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK\r
- //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 0\r
+#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK\r
+ //#define JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 0\r
 #endif\r
 \r
 //==============================================================================\r
index bfce625b56007a2d360ce59f5a822c6c33795963..76c3337fd9c491e89548332cdd8989357bdfa06c 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "MainComponent.h"\r
 \r
 Component* createMainContentComponent();\r
index f30b83e4c5f412ebe2da5620730bb05895a6b10c..73dc3a1853e9c0fce21cdfea9162935a1277a1ff 100644 (file)
@@ -26,7 +26,7 @@
 \r
 #pragma once\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include <mutex>\r
 \r
 //==============================================================================\r
index 8ace7ccf009a4d58bfae55e7f633e39e176f960e..ac227ba1b8d6bf58675a3ff0f6cb8eb0cdb2074f 100644 (file)
@@ -2,7 +2,7 @@
 \r
 <JUCERPROJECT id="NTe0XB0ij" name="AudioPluginHost" projectType="guiapp" version="1.0.0"\r
               juceFolder="../../../juce" bundleIdentifier="com.roli.juce.pluginhost"\r
-              jucerVersion="5.4.5" companyName="ROLI Ltd." displaySplashScreen="0"\r
+              jucerVersion="5.4.6" companyName="ROLI Ltd." displaySplashScreen="0"\r
               reportAppUsage="0" companyCopyright="ROLI Ltd.">\r
   <EXPORTFORMATS>\r
     <XCODE_MAC targetFolder="Builds/MacOSX" rtasFolder="~/SDKs/PT_80_SDK" objCExtraSuffix="M73TRi"\r
       <FILE id="c97aUr" name="JUCEAppIcon.png" compile="0" resource="1" file="Source/JUCEAppIcon.png"/>\r
     </GROUP>\r
   </MAINGROUP>\r
-  <JUCEOPTIONS JUCE_WASAPI="1" JUCE_DIRECTSOUND="1" JUCE_ALSA="1" JUCE_QUICKTIME="disabled"\r
-               JUCE_USE_FLAC="0" JUCE_USE_OGGVORBIS="0" JUCE_USE_CDBURNER="0"\r
-               JUCE_USE_CDREADER="0" JUCE_USE_CAMERA="0" JUCE_PLUGINHOST_AU="1"\r
-               JUCE_WEB_BROWSER="0" JUCE_PLUGINHOST_VST3="1" JUCE_PLUGINHOST_LADSPA="1"/>\r
+  <JUCEOPTIONS JUCE_WASAPI="1" JUCE_DIRECTSOUND="1" JUCE_ALSA="1" JUCE_USE_FLAC="0"\r
+               JUCE_USE_OGGVORBIS="0" JUCE_USE_CDBURNER="0" JUCE_USE_CDREADER="0"\r
+               JUCE_USE_CAMERA="0" JUCE_PLUGINHOST_AU="1" JUCE_WEB_BROWSER="0"\r
+               JUCE_PLUGINHOST_VST3="1" JUCE_PLUGINHOST_LADSPA="1"/>\r
   <MODULES>\r
     <MODULE id="juce_audio_basics" showAllCode="1"/>\r
     <MODULE id="juce_audio_devices" showAllCode="1"/>\r
index e2174833fa5644b1fdeeddc8ee7ea386f2355904..eded0ed772ac815ac4cd2db6b4141a7973af7c58 100644 (file)
@@ -585,8 +585,6 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/misc/juce_Result.h"
     "../../../../../modules/juce_core/misc/juce_RuntimePermissions.cpp"
     "../../../../../modules/juce_core/misc/juce_RuntimePermissions.h"
-    "../../../../../modules/juce_core/misc/juce_StdFunctionCompat.cpp"
-    "../../../../../modules/juce_core/misc/juce_StdFunctionCompat.h"
     "../../../../../modules/juce_core/misc/juce_Uuid.cpp"
     "../../../../../modules/juce_core/misc/juce_Uuid.h"
     "../../../../../modules/juce_core/misc/juce_WindowsRegistry.h"
@@ -702,6 +700,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/threads/juce_ThreadPool.h"
     "../../../../../modules/juce_core/threads/juce_TimeSliceThread.cpp"
     "../../../../../modules/juce_core/threads/juce_TimeSliceThread.h"
+    "../../../../../modules/juce_core/threads/juce_WaitableEvent.cpp"
     "../../../../../modules/juce_core/threads/juce_WaitableEvent.h"
     "../../../../../modules/juce_core/time/juce_PerformanceCounter.cpp"
     "../../../../../modules/juce_core/time/juce_PerformanceCounter.h"
@@ -1948,8 +1947,6 @@ set_source_files_properties("../../../../../modules/juce_core/misc/juce_Result.c
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Result.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_RuntimePermissions.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_RuntimePermissions.h" PROPERTIES HEADER_FILE_ONLY TRUE)
-set_source_files_properties("../../../../../modules/juce_core/misc/juce_StdFunctionCompat.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
-set_source_files_properties("../../../../../modules/juce_core/misc/juce_StdFunctionCompat.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Uuid.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Uuid.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_WindowsRegistry.h" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2065,6 +2062,7 @@ set_source_files_properties("../../../../../modules/juce_core/threads/juce_Threa
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_ThreadPool.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_TimeSliceThread.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_TimeSliceThread.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_core/threads/juce_WaitableEvent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_WaitableEvent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/time/juce_PerformanceCounter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/time/juce_PerformanceCounter.h" PROPERTIES HEADER_FILE_ONLY TRUE)
index a81c4764c6a5f71e72eaa485bd212ca7efb3fa6d..bc704681681cea9c0313b415133d2da7bade1797 100644 (file)
@@ -9,6 +9,7 @@
   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
   <uses-permission android:name="android.permission.BLUETOOTH"/>
   <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+  <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-feature android:glEsVersion="0x00030000" android:required="true"/>
   <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false">
index 2df9a8e7076a7c1110c575417185fcd99f0e8e02..cfd3a2f8b52ed9e0f43513b48d34aa4898905c8e 100644 (file)
@@ -4,7 +4,7 @@ buildscript {
        jcenter()
    }
    dependencies {
-       classpath 'com.android.tools.build:gradle:3.2.1'
+       classpath 'com.android.tools.build:gradle:3.5.3'
    }
 }
 
index b460908d4f41c2a33b8090ee16c36e6fe85f7433..b66802c71420c8d2327970a31630797f9076bf53 100644 (file)
@@ -1 +1 @@
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
\ No newline at end of file
diff --git a/extras/AudioPluginHost/Builds/MacOSX/App.entitlements b/extras/AudioPluginHost/Builds/MacOSX/App.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
diff --git a/extras/AudioPluginHost/Builds/MacOSX/AudioPluginHost.entitlements b/extras/AudioPluginHost/Builds/MacOSX/AudioPluginHost.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 8ba981feaaa74ffed6590df940f007facc5d628a..9afcda35a02847c969aeda98bba0ebda1a25dad5 100644 (file)
@@ -9,6 +9,10 @@
                        isa = PBXBuildFile;
                        fileRef = 8D8BBC353637DA442C5575DA;
                };
+               B288A89F96704F142ED8E939 = {
+                       isa = PBXBuildFile;
+                       fileRef = 5ACC21AA45BBF48C3C64D56D;
+               };
                73E371F1B912FCCAE0CD7E5D = {
                        isa = PBXBuildFile;
                        fileRef = 86CA337014D3F67E906FFD28;
                        isa = PBXBuildFile;
                        fileRef = D4EBC17BDB7F88CCBC76730B;
                };
-               B288A89F96704F142ED8E939 = {
-                       isa = PBXBuildFile;
-                       fileRef = 5ACC21AA45BBF48C3C64D56D;
-               };
                851C1165C9E4ACDD19C56A96 = {
                        isa = PBXBuildFile;
                        fileRef = 942A0F04EFB8D0B2FF9780BA;
                        path = System/Library/Frameworks/CoreAudioKit.framework;
                        sourceTree = SDKROOT;
                };
-               EC252E34CF52A70B4A836BDC = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = AudioPluginHost.entitlements;
-                       path = AudioPluginHost.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                F14CDB17EFE157DA3C3A5A91 = {
                        isa = PBXFileReference;
                        lastKnownFileType = sourcecode.c.h;
                D1C4804CD275CB57A5C89A2D = {
                        isa = PBXGroup;
                        children = (
+                               5ACC21AA45BBF48C3C64D56D,
                                86CA337014D3F67E906FFD28,
                                D4EBC17BDB7F88CCBC76730B,
-                               5ACC21AA45BBF48C3C64D56D,
                                942A0F04EFB8D0B2FF9780BA,
                                A4B568E26157FC282214976F,
                                B0935EBBA4F6E2B05F3D1C0A,
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "AudioPluginHost";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                PRODUCT_NAME = "AudioPluginHost";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               B288A89F96704F142ED8E939,
                                73E371F1B912FCCAE0CD7E5D,
                                21D330A5B13178B12BEAFC3C,
-                               B288A89F96704F142ED8E939,
                                851C1165C9E4ACDD19C56A96,
                                AF42316D915057E930A5624E,
                                2B4B9CF71F94BDD1E3AC89AE,
index a65519c4d8d57f0b8e9322a9df3f34df298bf815..8436bc80ae9cb3bacd56d85a63c76530af89fee3 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 74ef99ca0d88f040797bbb114be74c3c0833ab29..f60af172da66c0aba29ee5caf8ef22509eaccdee 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index 630e31bd133baf6e88bef35705c6428a7292bdad..2a305ff49efb025d78045ef854ce2f310af10f54 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 3d2f44766137bbbe99aa8aa40b22f3c3d863b275..a94fc227bf0edb66dff46236acd786945b3b1e57 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index 007c667cd225d912331fffd9e0c486a385976104..81848a76aebb7c29ce41c960677392a3fb73ca80 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 3b679132f5e9c8f537da27edf1520b7b7c54f681..adc0637e5a5c905b1d7075a807c2a8009de0b4ce 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
diff --git a/extras/AudioPluginHost/Builds/iOS/App.entitlements b/extras/AudioPluginHost/Builds/iOS/App.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
diff --git a/extras/AudioPluginHost/Builds/iOS/AudioPluginHost.entitlements b/extras/AudioPluginHost/Builds/iOS/AudioPluginHost.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 56ef09ea9d5c918391d1ae3e3539125337cab8ee..9cfd7dea7ef3a29e58a0871b01be32fe3757aada 100644 (file)
                        path = System/Library/Frameworks/CoreAudioKit.framework;
                        sourceTree = SDKROOT;
                };
-               EC252E34CF52A70B4A836BDC = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = AudioPluginHost.entitlements;
-                       path = AudioPluginHost.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                F14CDB17EFE157DA3C3A5A91 = {
                        isa = PBXFileReference;
                        lastKnownFileType = sourcecode.c.h;
index 0a43cec5aa57c4880f00a21352c1458bf0c8e0f4..f14dc27fa09a238b1f71c1a8e14034a790b8fe4d 100644 (file)
@@ -49,7 +49,7 @@
 \r
 #define JUCE_USE_DARK_SPLASH_SCREEN 1\r
 \r
-#define JUCE_PROJUCER_VERSION 0x50405\r
+#define JUCE_PROJUCER_VERSION 0x50406\r
 \r
 //==============================================================================\r
 #define JUCE_MODULE_AVAILABLE_juce_audio_basics          1\r
 //==============================================================================\r
 // juce_events flags:\r
 \r
-#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK\r
- //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 0\r
+#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK\r
+ //#define JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 0\r
 #endif\r
 \r
 //==============================================================================\r
index e45009acaac099cd22f3737afe2afdd7bd247cbe..cce530eb4579b97c2683e7763398dce22e944db4 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "UI/MainHostWindow.h"\r
 #include "Plugins/InternalPlugins.h"\r
 \r
index 2a8ac4d089340592dea417c8828c3ddc6bafed1d..03b3454141d4cd9a988fc5feaa9439a3ace84e99 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "../UI/GraphEditorPanel.h"\r
 #include "InternalPlugins.h"\r
 #include "../UI/MainHostWindow.h"\r
index ac887559ff9bef88439156df359abe9f4eec6162..eb10b98b989adf17bb7367d5ecfe2050aa79bb77 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "InternalPlugins.h"\r
 #include "PluginGraph.h"\r
 \r
@@ -357,6 +357,11 @@ InternalPluginFormat::InternalPluginFormat()
         AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode);\r
         p.fillInPluginDescription (midiInDesc);\r
     }\r
+\r
+    {\r
+        AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode);\r
+        p.fillInPluginDescription (midiOutDesc);\r
+    }\r
 }\r
 \r
 std::unique_ptr<AudioPluginInstance> InternalPluginFormat::createInstance (const String& name)\r
@@ -364,6 +369,7 @@ std::unique_ptr<AudioPluginInstance> InternalPluginFormat::createInstance (const
     if (name == audioOutDesc.name) return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode);\r
     if (name == audioInDesc.name)  return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode);\r
     if (name == midiInDesc.name)   return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode);\r
+    if (name == midiOutDesc.name)  return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode);\r
 \r
     if (name == SineWaveSynth::getIdentifier()) return std::make_unique<SineWaveSynth> (SineWaveSynth::getPluginDescription());\r
     if (name == ReverbPlugin::getIdentifier())  return std::make_unique<ReverbPlugin>  (ReverbPlugin::getPluginDescription());\r
@@ -388,7 +394,6 @@ bool InternalPluginFormat::requiresUnblockedMessageThreadDuringCreation (const P
 \r
 void InternalPluginFormat::getAllTypes (Array<PluginDescription>& results)\r
 {\r
-    results.add (audioInDesc, audioOutDesc, midiInDesc,\r
-                 SineWaveSynth::getPluginDescription(),\r
-                 ReverbPlugin::getPluginDescription());\r
+    results.add (audioInDesc, audioOutDesc, midiInDesc, midiOutDesc,\r
+                 SineWaveSynth::getPluginDescription(), ReverbPlugin::getPluginDescription());\r
 }\r
index 82baf6e77b6847c945e7f25099c8a94fd1066b99..b5282a09e6b7b0ec0dd1de5dcf0315da0eefe6d8 100644 (file)
@@ -41,7 +41,7 @@ public:
     ~InternalPluginFormat() override {}\r
 \r
     //==============================================================================\r
-    PluginDescription audioInDesc, audioOutDesc, midiInDesc;\r
+    PluginDescription audioInDesc, audioOutDesc, midiInDesc, midiOutDesc;\r
     void getAllTypes (Array<PluginDescription>&);\r
 \r
     //==============================================================================\r
index 082911e504b0d4edd3a47a1b307ce8e4b41a7e96..8d9b9261fbd82ca8fc36ec70aedc61104c5a1c24 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "../UI/MainHostWindow.h"\r
 #include "PluginGraph.h"\r
 #include "InternalPlugins.h"\r
@@ -202,11 +202,13 @@ void PluginGraph::newDocument()
     addPlugin (internalFormat.audioInDesc,  { 0.5,  0.1 });\r
     addPlugin (internalFormat.midiInDesc,   { 0.25, 0.1 });\r
     addPlugin (internalFormat.audioOutDesc, { 0.5,  0.9 });\r
+    addPlugin (internalFormat.midiOutDesc,  { 0.25, 0.9 });\r
 \r
-    MessageManager::callAsync ([this] () {\r
+    MessageManager::callAsync ([this]\r
+    {\r
         setChangedFlag (false);\r
         graph.addChangeListener (this);\r
-    } );\r
+    });\r
 }\r
 \r
 Result PluginGraph::loadDocument (const File& file)\r
index a74497f6d9fb3c11f53a398b7ac0547b50be1d03..afa65bdbee460add01920d26546406165b18a84c 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "GraphEditorPanel.h"\r
 #include "../Plugins/InternalPlugins.h"\r
 #include "MainHostWindow.h"\r
@@ -1167,10 +1167,13 @@ GraphDocumentComponent::GraphDocumentComponent (AudioPluginFormatManager& fm,
     deviceManager.addChangeListener (graphPanel.get());\r
     deviceManager.addAudioCallback (&graphPlayer);\r
     deviceManager.addMidiInputDeviceCallback ({}, &graphPlayer.getMidiMessageCollector());\r
+    deviceManager.addChangeListener (this);\r
 }\r
 \r
 void GraphDocumentComponent::init()\r
 {\r
+    updateMidiOutput();\r
+\r
     graphPanel.reset (new GraphEditorPanel (*graph));\r
     addAndMakeVisible (graphPanel.get());\r
     graphPlayer.setProcessor (&graph->graph);\r
@@ -1213,6 +1216,9 @@ void GraphDocumentComponent::init()
 \r
 GraphDocumentComponent::~GraphDocumentComponent()\r
 {\r
+    if (midiOutput != nullptr)\r
+        midiOutput->stopBackgroundThread();\r
+\r
     releaseGraph();\r
 \r
     keyState.removeListener (&graphPlayer.getMidiMessageCollector());\r
@@ -1326,3 +1332,23 @@ bool GraphDocumentComponent::closeAnyOpenPluginWindows()
 {\r
     return graphPanel->graph.closeAnyOpenPluginWindows();\r
 }\r
+\r
+void GraphDocumentComponent::changeListenerCallback (ChangeBroadcaster*)\r
+{\r
+    updateMidiOutput();\r
+}\r
+\r
+void GraphDocumentComponent::updateMidiOutput()\r
+{\r
+    auto* defaultMidiOutput = deviceManager.getDefaultMidiOutput();\r
+\r
+    if (midiOutput != defaultMidiOutput)\r
+    {\r
+        midiOutput = defaultMidiOutput;\r
+\r
+        if (midiOutput != nullptr)\r
+            midiOutput->startBackgroundThread();\r
+\r
+        graphPlayer.setMidiOutput (midiOutput);\r
+    }\r
+}\r
index 2796b75046823048fe222b9835795e90714083cd..f5a5a6cc38fd0e568aa66657241dfaa2f1d6ce2f 100644 (file)
@@ -100,7 +100,8 @@ private:
 */\r
 class GraphDocumentComponent  : public Component,\r
                                 public DragAndDropTarget,\r
-                                public DragAndDropContainer\r
+                                public DragAndDropContainer,\r
+                                private ChangeListener\r
 {\r
 public:\r
     GraphDocumentComponent (AudioPluginFormatManager& formatManager,\r
@@ -142,6 +143,7 @@ private:
 \r
     AudioProcessorPlayer graphPlayer;\r
     MidiKeyboardState keyState;\r
+    MidiOutput* midiOutput = nullptr;\r
 \r
     struct TooltipBar;\r
     std::unique_ptr<TooltipBar> statusBar;\r
@@ -160,8 +162,11 @@ private:
     SidePanel* lastOpenedSidePanel = nullptr;\r
 \r
     //==============================================================================\r
+    void changeListenerCallback (ChangeBroadcaster*) override;\r
+\r
     void init();\r
     void checkAvailableWidth();\r
+    void updateMidiOutput();\r
 \r
     //==============================================================================\r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GraphDocumentComponent)\r
index 28678c2c4c51dc7894ec984f6c80d7f3e65f64cf..104b8aaef893779f6ea28b2ed9b044eeb98d616b 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "MainHostWindow.h"\r
 #include "../Plugins/InternalPlugins.h"\r
 \r
index e2abee46652a80ce22a3b3e3e627fa60fc8f2b57..ac1af990d03184e45731bd816b33a1a60f8ba6fa 100644 (file)
@@ -31,7 +31,7 @@
 class PluginGraph;\r
 \r
 /**\r
-    A window that shows a log of parameter change messagse sent by the plugin.\r
+    A window that shows a log of parameter change messages sent by the plugin.\r
 */\r
 class PluginDebugWindow : public AudioProcessorEditor,\r
                           public AudioProcessorParameter::Listener,\r
index 8c13340bb789e06d89e38a84281ff9e6e0d10046..ada60fc15ff41754e5d7d29a12ba1fb0826411eb 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 \r
 <JUCERPROJECT id="3t6YqETY1" name="BinaryBuilder" projectType="consoleapp"\r
-              juceFolder="../../../juce" jucerVersion="5.4.5" bundleIdentifier="com.roli.binarybuilder"\r
+              juceFolder="../../../juce" jucerVersion="5.4.6" bundleIdentifier="com.roli.binarybuilder"\r
               displaySplashScreen="0" reportAppUsage="0" companyName="ROLI Ltd."\r
               companyCopyright="ROLI Ltd.">\r
   <EXPORTFORMATS>\r
diff --git a/extras/BinaryBuilder/Builds/MacOSX/BinaryBuilder.entitlements b/extras/BinaryBuilder/Builds/MacOSX/BinaryBuilder.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 479760bf0db531b27ca53e9cf503c60e8b0eff95..557784d5513d50d1c2409c1e8a52911cb3a646e4 100644 (file)
                        path = RecentFilesMenuTemplate.nib;
                        sourceTree = "SOURCE_ROOT";
                };
-               25C3A81567A43C28D8A9C143 = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = BinaryBuilder.entitlements;
-                       path = BinaryBuilder.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                50B7C64414A3E778021F5EC4 = {
                        isa = PBXFileReference;
                        lastKnownFileType = sourcecode.cpp.cpp;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "BinaryBuilder";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                PRODUCT_NAME = "BinaryBuilder";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
diff --git a/extras/BinaryBuilder/Builds/MacOSX/ConsoleApp.entitlements b/extras/BinaryBuilder/Builds/MacOSX/ConsoleApp.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
index 34d798a8c5206e8935cd38ff75a21642ecc3ad0e..7e823639954d43e9855c416f8c90c1d7ec3ceb4a 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index ce4e94ceb1bf8afcaaa76f38ab5cc51cdbbc0131..98e8371458c64bb70c59090fe6c2c3a20ab62f5e 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index ee326c0319db59d9d2a0a109d0ab02c58206f2d8..8fcbef4aaf87e925bb1eff25fddce7e294ff0928 100644 (file)
@@ -47,7 +47,7 @@
 \r
 #define JUCE_USE_DARK_SPLASH_SCREEN 1\r
 \r
-#define JUCE_PROJUCER_VERSION 0x50405\r
+#define JUCE_PROJUCER_VERSION 0x50406\r
 \r
 //==============================================================================\r
 #define JUCE_MODULE_AVAILABLE_juce_core      1\r
index e6c4aeaac53aab8a9a53ee035d3caa632fec3147..9716d7c10f40d203d793d6462b4de9f8df84ba44 100644 (file)
@@ -35,7 +35,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 \r
 \r
 //==============================================================================\r
index 6da7075a4cf545f1227ff0cf05613c6a0a21867d..0b74a58e0b392d65db05dd4b0e37e540566171ac 100644 (file)
@@ -572,8 +572,6 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/misc/juce_Result.h"
     "../../../../../modules/juce_core/misc/juce_RuntimePermissions.cpp"
     "../../../../../modules/juce_core/misc/juce_RuntimePermissions.h"
-    "../../../../../modules/juce_core/misc/juce_StdFunctionCompat.cpp"
-    "../../../../../modules/juce_core/misc/juce_StdFunctionCompat.h"
     "../../../../../modules/juce_core/misc/juce_Uuid.cpp"
     "../../../../../modules/juce_core/misc/juce_Uuid.h"
     "../../../../../modules/juce_core/misc/juce_WindowsRegistry.h"
@@ -689,6 +687,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/threads/juce_ThreadPool.h"
     "../../../../../modules/juce_core/threads/juce_TimeSliceThread.cpp"
     "../../../../../modules/juce_core/threads/juce_TimeSliceThread.h"
+    "../../../../../modules/juce_core/threads/juce_WaitableEvent.cpp"
     "../../../../../modules/juce_core/threads/juce_WaitableEvent.h"
     "../../../../../modules/juce_core/time/juce_PerformanceCounter.cpp"
     "../../../../../modules/juce_core/time/juce_PerformanceCounter.h"
@@ -1937,8 +1936,6 @@ set_source_files_properties("../../../../../modules/juce_core/misc/juce_Result.c
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Result.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_RuntimePermissions.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_RuntimePermissions.h" PROPERTIES HEADER_FILE_ONLY TRUE)
-set_source_files_properties("../../../../../modules/juce_core/misc/juce_StdFunctionCompat.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
-set_source_files_properties("../../../../../modules/juce_core/misc/juce_StdFunctionCompat.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Uuid.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_Uuid.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/misc/juce_WindowsRegistry.h" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2054,6 +2051,7 @@ set_source_files_properties("../../../../../modules/juce_core/threads/juce_Threa
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_ThreadPool.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_TimeSliceThread.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_TimeSliceThread.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_core/threads/juce_WaitableEvent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/threads/juce_WaitableEvent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/time/juce_PerformanceCounter.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
 set_source_files_properties("../../../../../modules/juce_core/time/juce_PerformanceCounter.h" PROPERTIES HEADER_FILE_ONLY TRUE)
index 87a55c1e277544096e8c5fdc01516fc53580854c..d3befd5e9f2f75daeb372fe29c2640345e466928 100644 (file)
@@ -8,6 +8,7 @@
   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
   <uses-permission android:name="android.permission.BLUETOOTH"/>
+  <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
   <application android:label="@string/app_name" android:name="com.roli.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false">
index 2df9a8e7076a7c1110c575417185fcd99f0e8e02..cfd3a2f8b52ed9e0f43513b48d34aa4898905c8e 100644 (file)
@@ -4,7 +4,7 @@ buildscript {
        jcenter()
    }
    dependencies {
-       classpath 'com.android.tools.build:gradle:3.2.1'
+       classpath 'com.android.tools.build:gradle:3.5.3'
    }
 }
 
index b460908d4f41c2a33b8090ee16c36e6fe85f7433..b66802c71420c8d2327970a31630797f9076bf53 100644 (file)
@@ -1 +1 @@
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
\ No newline at end of file
diff --git a/extras/NetworkGraphicsDemo/Builds/MacOSX/App.entitlements b/extras/NetworkGraphicsDemo/Builds/MacOSX/App.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
diff --git a/extras/NetworkGraphicsDemo/Builds/MacOSX/NetworkGraphicsDemo.entitlements b/extras/NetworkGraphicsDemo/Builds/MacOSX/NetworkGraphicsDemo.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 8d4427ba549d50c43952b4ba974e0aa09fb565e6..2a3a20b3d78b96d44e7a0bab6f9b35e238f5cfd2 100644 (file)
                        path = ../../Source/SharedCanvas.h;
                        sourceTree = "SOURCE_ROOT";
                };
-               280A781618BDE3AF9BE15495 = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = NetworkGraphicsDemo.entitlements;
-                       path = NetworkGraphicsDemo.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                2E13A899F4E3C99054A3656F = {
                        isa = PBXFileReference;
                        lastKnownFileType = wrapper.framework;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "JUCE Network Graphics Demo";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                PRODUCT_NAME = "JUCE Network Graphics Demo";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
index 69815331a31e1b9e1df8d6b4104b7e1051c8f7af..99d26bb39c9a5997d5e78366bef2a259b9974888 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index aa2ae0b1d210363b5a9536e73cce43e2560c8ca6..0181b46d2c68f8b41b72eb802e00fd9bab746880 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
diff --git a/extras/NetworkGraphicsDemo/Builds/iOS/App.entitlements b/extras/NetworkGraphicsDemo/Builds/iOS/App.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
diff --git a/extras/NetworkGraphicsDemo/Builds/iOS/NetworkGraphicsDemo.entitlements b/extras/NetworkGraphicsDemo/Builds/iOS/NetworkGraphicsDemo.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 00987e47fdcfd1947535c926f41d8871d7a62ffc..69eb61843eaf3bb6ed9e7eb58d010414da339391 100644 (file)
                        path = ../../Source/SharedCanvas.h;
                        sourceTree = "SOURCE_ROOT";
                };
-               280A781618BDE3AF9BE15495 = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = NetworkGraphicsDemo.entitlements;
-                       path = NetworkGraphicsDemo.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                2E13A899F4E3C99054A3656F = {
                        isa = PBXFileReference;
                        lastKnownFileType = wrapper.framework;
index f0cdeab24baee0aec1a147fb049f3ad81e44374d..a5889ec1a42c273c3f71d7ac7d5dde3bf0ce2055 100644 (file)
@@ -47,7 +47,7 @@
 \r
 #define JUCE_USE_DARK_SPLASH_SCREEN 1\r
 \r
-#define JUCE_PROJUCER_VERSION 0x50405\r
+#define JUCE_PROJUCER_VERSION 0x50406\r
 \r
 //==============================================================================\r
 #define JUCE_MODULE_AVAILABLE_juce_audio_basics          1\r
 //==============================================================================\r
 // juce_events flags:\r
 \r
-#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK\r
- //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 0\r
+#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK\r
+ //#define JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 0\r
 #endif\r
 \r
 //==============================================================================\r
index 79a87de7c5b2368e85f477cbade1636b54dbdfe1..319f8865a6a2ad53dd03a003cac089d09f22cfd6 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 \r
 <JUCERPROJECT id="gWI5Ir" name="NetworkGraphicsDemo" projectType="guiapp" bundleIdentifier="com.juce.NetworkGraphicsDemo"\r
-              jucerVersion="5.4.5" displaySplashScreen="0" reportAppUsage="0"\r
+              jucerVersion="5.4.6" displaySplashScreen="0" reportAppUsage="0"\r
               companyName="ROLI Ltd." companyCopyright="ROLI Ltd.">\r
   <MAINGROUP id="OT9rJ2" name="NetworkGraphicsDemo">\r
     <GROUP id="{48D54E6E-37F4-B20A-E038-C63E4EDFD4D9}" name="Source">\r
index 40c0597b3b7058914147af08f461a738dd7c6365..07298d41aeeec4b3a8a370485ab6b0a3d27c34dc 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 \r
 namespace\r
 {\r
index 25b490460d4b136f97d80a308f910690fd354ba9..b98883b30cee07a52e7d3045afd07949c5684b95 100644 (file)
@@ -35,7 +35,7 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := -march=native
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DDEBUG=1 -D_DEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=5.4.5 -DJUCE_APP_VERSION_HEX=0x50405 $(shell pkg-config --cflags x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DDEBUG=1 -D_DEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=5.4.6 -DJUCE_APP_VERSION_HEX=0x50406 $(shell pkg-config --cflags x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0 -DJucePlugin_Build_Unity=0
   JUCE_TARGET_APP := Projucer
 
@@ -56,7 +56,7 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := -march=native
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DNDEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=5.4.5 -DJUCE_APP_VERSION_HEX=0x50405 $(shell pkg-config --cflags x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DNDEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=5.4.6 -DJUCE_APP_VERSION_HEX=0x50406 $(shell pkg-config --cflags x11 xinerama xext freetype2 webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0 -DJucePlugin_Build_Unity=0
   JUCE_TARGET_APP := Projucer
 
@@ -113,6 +113,7 @@ OBJECTS_APP := \
   $(JUCE_OBJDIR)/jucer_CodeHelpers_1e797672.o \
   $(JUCE_OBJDIR)/jucer_FileHelpers_54f12f83.o \
   $(JUCE_OBJDIR)/jucer_MiscUtilities_31fc8dd8.o \
+  $(JUCE_OBJDIR)/jucer_VersionInfo_46f3ed40.o \
   $(JUCE_OBJDIR)/jucer_PIPGenerator_fd3402c7.o \
   $(JUCE_OBJDIR)/jucer_Icons_d02d18f1.o \
   $(JUCE_OBJDIR)/jucer_JucerTreeViewBase_9b9f2ff0.o \
@@ -368,6 +369,11 @@ $(JUCE_OBJDIR)/jucer_MiscUtilities_31fc8dd8.o: ../../Source/Utility/Helpers/juce
        @echo "Compiling jucer_MiscUtilities.cpp"
        $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
 
+$(JUCE_OBJDIR)/jucer_VersionInfo_46f3ed40.o: ../../Source/Utility/Helpers/jucer_VersionInfo.cpp
+       -$(V_AT)mkdir -p $(JUCE_OBJDIR)
+       @echo "Compiling jucer_VersionInfo.cpp"
+       $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
+
 $(JUCE_OBJDIR)/jucer_PIPGenerator_fd3402c7.o: ../../Source/Utility/PIPs/jucer_PIPGenerator.cpp
        -$(V_AT)mkdir -p $(JUCE_OBJDIR)
        @echo "Compiling jucer_PIPGenerator.cpp"
diff --git a/extras/Projucer/Builds/MacOSX/App.entitlements b/extras/Projucer/Builds/MacOSX/App.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
index c221483427aa4c830132fe82365fb364d639a3f6..6ea5928a41ff9b9c80ea91e24927ecbe19ddb560 100644 (file)
@@ -37,9 +37,9 @@
     <key>CFBundleSignature</key>\r
     <string>????</string>\r
     <key>CFBundleShortVersionString</key>\r
-    <string>5.4.5</string>\r
+    <string>5.4.6</string>\r
     <key>CFBundleVersion</key>\r
-    <string>5.4.5</string>\r
+    <string>5.4.6</string>\r
     <key>NSHumanReadableCopyright</key>\r
     <string>ROLI Ltd.</string>\r
     <key>NSHighResolutionCapable</key>\r
diff --git a/extras/Projucer/Builds/MacOSX/Projucer.entitlements b/extras/Projucer/Builds/MacOSX/Projucer.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 6db9d9057c4232ccc7a46f731ea5a0d08a523e30..3990ab682573d2ff2112dedbbb467007f4b973ef 100644 (file)
@@ -9,6 +9,10 @@
                        isa = PBXBuildFile;
                        fileRef = 09DE066936CF037E9709ADB1;
                };
+               8B4A593B3869815BBAC3EF93 = {
+                       isa = PBXBuildFile;
+                       fileRef = 7B3F7ECF6DBF8C8EE5C2CB86;
+               };
                A578EAD4BB55680E8097BE0F = {
                        isa = PBXBuildFile;
                        fileRef = 80D62B907248523E6943298B;
                        isa = PBXBuildFile;
                        fileRef = 5A75806B34E4EA6598A6024A;
                };
-               8B4A593B3869815BBAC3EF93 = {
-                       isa = PBXBuildFile;
-                       fileRef = 7B3F7ECF6DBF8C8EE5C2CB86;
-               };
                A14C2C2725DA3CA7995D2815 = {
                        isa = PBXBuildFile;
                        fileRef = 210CD22F25F2C22F9CEEB025;
                        isa = PBXBuildFile;
                        fileRef = 486E8D02DAD2A0BF54A901C0;
                };
+               44AD0D81A65C5EAE3BE588FD = {
+                       isa = PBXBuildFile;
+                       fileRef = FF3A6A384D536E1AEF47CD54;
+               };
                638C7247B6DBA67EFE46E124 = {
                        isa = PBXBuildFile;
                        fileRef = 191330B20DAC08B890656EA0;
                        path = "../../../../modules/juce_graphics";
                        sourceTree = "SOURCE_ROOT";
                };
-               B7017BD3427B46FBAAAE448A = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = Projucer.entitlements;
-                       path = Projucer.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                B8385E9A644BD3CD94876448 = {
                        isa = PBXFileReference;
                        lastKnownFileType = sourcecode.c.h;
                        path = "../../Source/Wizards/jucer_TemplateThumbnailsComponent.h";
                        sourceTree = "SOURCE_ROOT";
                };
+               C16F9F479A3A5F6DAD7647A2 = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = "jucer_VersionInfo.h";
+                       path = "../../Source/Utility/Helpers/jucer_VersionInfo.h";
+                       sourceTree = "SOURCE_ROOT";
+               };
                C187718F7B9EBA88584B43F3 = {
                        isa = PBXFileReference;
                        lastKnownFileType = sourcecode.cpp.cpp;
                        path = "../../Source/Utility/UI/jucer_ProjucerLookAndFeel.h";
                        sourceTree = "SOURCE_ROOT";
                };
+               FF3A6A384D536E1AEF47CD54 = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = "jucer_VersionInfo.cpp";
+                       path = "../../Source/Utility/Helpers/jucer_VersionInfo.cpp";
+                       sourceTree = "SOURCE_ROOT";
+               };
                FF68231DE2B395461009116C = {
                        isa = PBXFileReference;
                        lastKnownFileType = sourcecode.c.h;
                                A6C4AE13FB409DE414094CFA,
                                6FD8DBC0FF42C87D8BEE2452,
                                00515BA4EC5A7D4DC078ED37,
+                               FF3A6A384D536E1AEF47CD54,
+                               C16F9F479A3A5F6DAD7647A2,
                        );
                        name = Helpers;
                        sourceTree = "<group>";
                0FFEF043CA89142B18C79ABE = {
                        isa = PBXGroup;
                        children = (
+                               7B3F7ECF6DBF8C8EE5C2CB86,
                                80D62B907248523E6943298B,
                                5A75806B34E4EA6598A6024A,
-                               7B3F7ECF6DBF8C8EE5C2CB86,
                                210CD22F25F2C22F9CEEB025,
                                D00F311BFC3C2625C457CB9B,
                                D1F9B0E9F5D54FE48BEB46EA,
                                        "_DEBUG=1",
                                        "DEBUG=1",
                                        "JUCER_XCODE_MAC_F6D2F4CF=1",
-                                       "JUCE_APP_VERSION=5.4.5",
-                                       "JUCE_APP_VERSION_HEX=0x50405",
+                                       "JUCE_APP_VERSION=5.4.6",
+                                       "JUCE_APP_VERSION_HEX=0x50406",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                                        "_NDEBUG=1",
                                        "NDEBUG=1",
                                        "JUCER_XCODE_MAC_F6D2F4CF=1",
-                                       "JUCE_APP_VERSION=5.4.5",
-                                       "JUCE_APP_VERSION_HEX=0x50405",
+                                       "JUCE_APP_VERSION=5.4.6",
+                                       "JUCE_APP_VERSION_HEX=0x50406",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "Projucer";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                PRODUCT_NAME = "Projucer";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                                8BE478303CDF061B72F219E2,
                                BF913199032B4CE970E82AA3,
                                25EF9B3FECB4C9F0F522DCAA,
+                               44AD0D81A65C5EAE3BE588FD,
                                638C7247B6DBA67EFE46E124,
                                D0E26EB54B0087C8BE3D541E,
                                468548FB21D264DC12321327,
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               8B4A593B3869815BBAC3EF93,
                                A578EAD4BB55680E8097BE0F,
                                C1B9334AE849F93FB3C56B34,
-                               8B4A593B3869815BBAC3EF93,
                                A14C2C2725DA3CA7995D2815,
                                1E76E36772355E2A43CF4961,
                                241F29FCBB7A17BB44A0B10C,
index a025ed0944177d7cb875ab568d87c4f7775a3b5f..a72d79547930db958044f6f6bc4dfc3eae0fb13c 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCER_VS2015_78A5022=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_CodeHelpers.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_FileHelpers.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_MiscUtilities.cpp"/>\r
+    <ClCompile Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\UI\jucer_Icons.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\UI\jucer_JucerTreeViewBase.cpp"/>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_RelativePath.h"/>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_TranslationHelpers.h"/>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_ValueSourceHelpers.h"/>\r
+    <ClInclude Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.h"/>\r
     <ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h"/>\r
     <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h"/>\r
     <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 7bc5135c08a1eb305e42414b26f6ecfb8e3914e6..16e2c05db32b65422f959911ce1d5c8e37358bc1 100644 (file)
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_MiscUtilities.cpp">\r
       <Filter>Projucer\Utility\Helpers</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.cpp">\r
+      <Filter>Projucer\Utility\Helpers</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp">\r
       <Filter>Projucer\Utility\PIPs</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_ValueSourceHelpers.h">\r
       <Filter>Projucer\Utility\Helpers</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.h">\r
+      <Filter>Projucer\Utility\Helpers</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h">\r
       <Filter>Projucer\Utility\PIPs</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index c41432352aa234636f672bedf2bf3c221d408859..0dfcbc7f57583d298dcb909596165869c99519b0 100644 (file)
@@ -7,7 +7,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  5,4,5,0\r
+FILEVERSION  5,4,6,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -16,9 +16,9 @@ BEGIN
       VALUE "CompanyName",  "ROLI Ltd.\0"\r
       VALUE "LegalCopyright",  "ROLI Ltd.\0"\r
       VALUE "FileDescription",  "Projucer\0"\r
-      VALUE "FileVersion",  "5.4.5\0"\r
+      VALUE "FileVersion",  "5.4.6\0"\r
       VALUE "ProductName",  "Projucer\0"\r
-      VALUE "ProductVersion",  "5.4.5\0"\r
+      VALUE "ProductVersion",  "5.4.6\0"\r
     END\r
   END\r
 \r
index 7c8751a7fb46df0fe8be8cb6bb2437f3e39524c0..0bc1479014dc87bcda14c40a5213856f213a9248 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_CodeHelpers.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_FileHelpers.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_MiscUtilities.cpp"/>\r
+    <ClCompile Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\UI\jucer_Icons.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\UI\jucer_JucerTreeViewBase.cpp"/>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_RelativePath.h"/>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_TranslationHelpers.h"/>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_ValueSourceHelpers.h"/>\r
+    <ClInclude Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.h"/>\r
     <ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h"/>\r
     <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h"/>\r
     <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index a2ec767bd7b7e49534903257231fa460b1f928ea..8148e932e239cbf876041c3e139fa2d245bad5ec 100644 (file)
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_MiscUtilities.cpp">\r
       <Filter>Projucer\Utility\Helpers</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.cpp">\r
+      <Filter>Projucer\Utility\Helpers</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp">\r
       <Filter>Projucer\Utility\PIPs</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_ValueSourceHelpers.h">\r
       <Filter>Projucer\Utility\Helpers</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.h">\r
+      <Filter>Projucer\Utility\Helpers</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h">\r
       <Filter>Projucer\Utility\PIPs</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index c41432352aa234636f672bedf2bf3c221d408859..0dfcbc7f57583d298dcb909596165869c99519b0 100644 (file)
@@ -7,7 +7,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  5,4,5,0\r
+FILEVERSION  5,4,6,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -16,9 +16,9 @@ BEGIN
       VALUE "CompanyName",  "ROLI Ltd.\0"\r
       VALUE "LegalCopyright",  "ROLI Ltd.\0"\r
       VALUE "FileDescription",  "Projucer\0"\r
-      VALUE "FileVersion",  "5.4.5\0"\r
+      VALUE "FileVersion",  "5.4.6\0"\r
       VALUE "ProductName",  "Projucer\0"\r
-      VALUE "ProductVersion",  "5.4.5\0"\r
+      VALUE "ProductVersion",  "5.4.6\0"\r
     END\r
   END\r
 \r
index 0a28052e5811f24bc1fca93688007689bb731cff..dc49d5194a5eebe71b18173cc13049d3eba403ab 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=5.4.5;JUCE_APP_VERSION_HEX=0x50405;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=5.4.6;JUCE_APP_VERSION_HEX=0x50406;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_RTAS=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader/>\r
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_CodeHelpers.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_FileHelpers.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_MiscUtilities.cpp"/>\r
+    <ClCompile Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\UI\jucer_Icons.cpp"/>\r
     <ClCompile Include="..\..\Source\Utility\UI\jucer_JucerTreeViewBase.cpp"/>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_RelativePath.h"/>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_TranslationHelpers.h"/>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_ValueSourceHelpers.h"/>\r
+    <ClInclude Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.h"/>\r
     <ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h"/>\r
     <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_ColourPropertyComponent.h"/>\r
     <ClInclude Include="..\..\Source\Utility\UI\PropertyComponents\jucer_FilePathPropertyComponent.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 754d0ff9360955a9d11192d81a07380cb2127012..1acc5e809027c2673cb73ef8e36b801f15c6a84e 100644 (file)
     <ClCompile Include="..\..\Source\Utility\Helpers\jucer_MiscUtilities.cpp">\r
       <Filter>Projucer\Utility\Helpers</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.cpp">\r
+      <Filter>Projucer\Utility\Helpers</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.cpp">\r
       <Filter>Projucer\Utility\PIPs</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\Source\Utility\Helpers\jucer_ValueSourceHelpers.h">\r
       <Filter>Projucer\Utility\Helpers</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\Source\Utility\Helpers\jucer_VersionInfo.h">\r
+      <Filter>Projucer\Utility\Helpers</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\Source\Utility\PIPs\jucer_PIPGenerator.h">\r
       <Filter>Projucer\Utility\PIPs</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index c41432352aa234636f672bedf2bf3c221d408859..0dfcbc7f57583d298dcb909596165869c99519b0 100644 (file)
@@ -7,7 +7,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  5,4,5,0\r
+FILEVERSION  5,4,6,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -16,9 +16,9 @@ BEGIN
       VALUE "CompanyName",  "ROLI Ltd.\0"\r
       VALUE "LegalCopyright",  "ROLI Ltd.\0"\r
       VALUE "FileDescription",  "Projucer\0"\r
-      VALUE "FileVersion",  "5.4.5\0"\r
+      VALUE "FileVersion",  "5.4.6\0"\r
       VALUE "ProductName",  "Projucer\0"\r
-      VALUE "ProductVersion",  "5.4.5\0"\r
+      VALUE "ProductVersion",  "5.4.6\0"\r
     END\r
   END\r
 \r
index dffd5af7550e94b407c0657b379c451d176483a1..e9598ed9d49d1352cca7534b333fd2df823f3ece 100644 (file)
@@ -66,7 +66,7 @@
 \r
 #define JUCE_USE_DARK_SPLASH_SCREEN 1\r
 \r
-#define JUCE_PROJUCER_VERSION 0x50405\r
+#define JUCE_PROJUCER_VERSION 0x50406\r
 \r
 //==============================================================================\r
 #define JUCE_MODULE_AVAILABLE_juce_analytics            1\r
 //==============================================================================\r
 // juce_events flags:\r
 \r
-#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK\r
- //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 0\r
+#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK\r
+ //#define JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 0\r
 #endif\r
 \r
 //==============================================================================\r
index 3e796febb1a533deef8d0d30bc5e79faa6d52883..096299a5e930781db1e6716d61ad1723d7bf6614 100644 (file)
@@ -6174,7 +6174,7 @@ static const unsigned char temp_binary_data_35[] =
 "#pragma once\r\n"\r
 "\r\n"\r
 "//[Headers]     -- You can add your own extra header files here --\r\n"\r
-"%%include_juce_header%%\r\n"\r
+"%%include_juce%%\r\n"\r
 "//[/Headers]\r\n"\r
 "\r\n"\r
 "%%include_files_h%%\r\n"\r
@@ -6192,7 +6192,7 @@ static const unsigned char temp_binary_data_35[] =
 "public:\r\n"\r
 "    //==============================================================================\r\n"\r
 "    %%class_name%% (%%constructor_params%%);\r\n"\r
-"    ~%%class_name%%();\r\n"\r
+"    ~%%class_name%%() override;\r\n"\r
 "\r\n"\r
 "    //==============================================================================\r\n"\r
 "    //[UserMethods]     -- You can add your own custom methods in this section.\r\n"\r
@@ -7204,7 +7204,7 @@ static const unsigned char temp_binary_data_53[] =
 "  ==============================================================================\r\n"\r
 "*/\r\n"\r
 "\r\n"\r
-"#include \"../JuceLibraryCode/JuceHeader.h\"\r\n"\r
+"%%include_juce%%\r\n"\r
 "#include \"%%filename%%\"\r\n"\r
 "\r\n"\r
 "%%component_begin%%\r\n"\r
@@ -7846,7 +7846,7 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes)
         case 0x51b49ac5:  numBytes = 6036; return jucer_AudioPluginFilterTemplate_cpp;\r
         case 0x488afa0a:  numBytes = 2272; return jucer_AudioPluginFilterTemplate_h;\r
         case 0xabad7041:  numBytes = 2126; return jucer_ComponentTemplate_cpp;\r
-        case 0xfc72fe86:  numBytes = 2042; return jucer_ComponentTemplate_h;\r
+        case 0xfc72fe86:  numBytes = 2044; return jucer_ComponentTemplate_h;\r
         case 0x1657b643:  numBytes = 1693; return jucer_ContentCompSimpleTemplate_h;\r
         case 0x0b66646c:  numBytes = 1190; return jucer_ContentCompTemplate_cpp;\r
         case 0x6fa10171:  numBytes = 1071; return jucer_ContentCompTemplate_h;\r
@@ -7864,7 +7864,7 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes)
         case 0x7fbac252:  numBytes = 1665; return jucer_OpenGLComponentTemplate_cpp;\r
         case 0x491fa0d7:  numBytes = 1263; return jucer_OpenGLComponentTemplate_h;\r
         case 0xbc050edc:  numBytes = 4926; return jucer_PIPAudioProcessorTemplate_h;\r
-        case 0xf4ca9e9a:  numBytes = 2447; return jucer_PIPMain_cpp;\r
+        case 0xf4ca9e9a:  numBytes = 2421; return jucer_PIPMain_cpp;\r
         case 0x0b16e320:  numBytes = 517; return jucer_PIPTemplate_h;\r
         case 0xcd472557:  numBytes = 6433; return jucer_UnityPluginGUIScript_cs;\r
         case 0x763d39dc:  numBytes = 1050; return colourscheme_dark_xml;\r
index 1f027de67c5e38b595136986ce0957272a78f33d..474d506e9bce98cda0d115ee8727738bae7c92fd 100644 (file)
@@ -114,7 +114,7 @@ namespace BinaryData
     const int            jucer_ComponentTemplate_cppSize = 2126;\r
 \r
     extern const char*   jucer_ComponentTemplate_h;\r
-    const int            jucer_ComponentTemplate_hSize = 2042;\r
+    const int            jucer_ComponentTemplate_hSize = 2044;\r
 \r
     extern const char*   jucer_ContentCompSimpleTemplate_h;\r
     const int            jucer_ContentCompSimpleTemplate_hSize = 1693;\r
@@ -168,7 +168,7 @@ namespace BinaryData
     const int            jucer_PIPAudioProcessorTemplate_hSize = 4926;\r
 \r
     extern const char*   jucer_PIPMain_cpp;\r
-    const int            jucer_PIPMain_cppSize = 2447;\r
+    const int            jucer_PIPMain_cppSize = 2421;\r
 \r
     extern const char*   jucer_PIPTemplate_h;\r
     const int            jucer_PIPTemplate_hSize = 517;\r
index 765b42656df8c9ba4cd7cba64cf68ee751f328df..acb1d2cf220915579ea0b8a7ea52fd34f037f62e 100644 (file)
@@ -45,7 +45,7 @@ namespace ProjectInfo
 {\r
     const char* const  projectName    = "Projucer";\r
     const char* const  companyName    = "ROLI Ltd.";\r
-    const char* const  versionString  = "5.4.5";\r
-    const int          versionNumber  = 0x50405;\r
+    const char* const  versionString  = "5.4.6";\r
+    const int          versionNumber  = 0x50406;\r
 }\r
 #endif\r
index 6f4f708036e2bd33276a8047666dfcaeb0452a9e..0df4502653b4b72036b811ca516db454ad3ba53f 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 \r
 <JUCERPROJECT id="M70qfTRRk" name="Projucer" projectType="guiapp" juceFolder="../../juce"\r
-              jucerVersion="5.4.5" version="5.4.5" bundleIdentifier="com.juce.theprojucer"\r
+              jucerVersion="5.4.6" version="5.4.6" bundleIdentifier="com.juce.theprojucer"\r
               splashScreenColour="Dark" displaySplashScreen="0" reportAppUsage="0"\r
               companyName="ROLI Ltd." companyCopyright="ROLI Ltd." cppLanguageStandard="11">\r
   <EXPORTFORMATS>\r
               file="Source/Utility/Helpers/jucer_TranslationHelpers.h"/>\r
         <FILE id="EuC4K4" name="jucer_ValueSourceHelpers.h" compile="0" resource="0"\r
               file="Source/Utility/Helpers/jucer_ValueSourceHelpers.h"/>\r
+        <FILE id="BPCoKV" name="jucer_VersionInfo.cpp" compile="1" resource="0"\r
+              file="Source/Utility/Helpers/jucer_VersionInfo.cpp"/>\r
+        <FILE id="TnBQtv" name="jucer_VersionInfo.h" compile="0" resource="0"\r
+              file="Source/Utility/Helpers/jucer_VersionInfo.h"/>\r
       </GROUP>\r
       <GROUP id="{A07C4A97-0855-5346-CAF2-A005580B6773}" name="PIPs">\r
         <FILE id="joAnDa" name="jucer_PIPGenerator.cpp" compile="1" resource="0"\r
index 94505ffd35b483112ca57a3d74a34f13052676f8..4dee4ce789a856ac2d30d7b5dbf924e872e0117f 100644 (file)
@@ -197,7 +197,7 @@ private:
         builder.add (new FilePathPropertyComponent (juceModulePathValue, "JUCE Modules", true, isThisOS),\r
                      String ("This should be the path to the folder containing the JUCE modules that you wish to use, typically the \"modules\" directory of your JUCE folder.")\r
                      + (isThisOS ? " Use the button below to re-scan a new path." : ""));\r
-        builder.add (new FilePathPropertyComponent (userModulePathValue, "User Modules", true, isThisOS, {}, {}, true),\r
+        builder.add (new FilePathPropertyComponent (userModulePathValue, "User Modules", true, isThisOS),\r
                      String ("A path to a folder containing any custom modules that you wish to use.")\r
                      + (isThisOS ? " Use the button below to re-scan new paths." : ""));\r
 \r
index b1f8aef02b7b89deec20d1a96474f3d261ad0259..af8514ec7f6a50f48e7f135dc44d5b329320c727 100644 (file)
@@ -1163,9 +1163,11 @@ bool ProjucerApplication::perform (const InvocationInfo& info)
 void ProjucerApplication::createNewProject()\r
 {\r
     auto* mw = mainWindowList.getOrCreateEmptyWindow();\r
+    jassert (mw != nullptr);\r
+\r
     mw->showStartPage();\r
 \r
-    mainWindowList.avoidSuperimposedWindows (mw);\r
+    mainWindowList.checkWindowBounds (*mw);\r
 }\r
 \r
 void ProjucerApplication::createNewProjectFromClipboard()\r
index a54b52736a115c19025a69bde2ba7e362272912e..94e8eb720c05cedb5ec33e15f3fddded14a4e659 100644 (file)
@@ -52,119 +52,65 @@ void LatestVersionCheckerAndUpdater::checkForNewVersion (bool showAlerts)
 //==============================================================================\r
 void LatestVersionCheckerAndUpdater::run()\r
 {\r
-    queryUpdateServer();\r
+    auto info = VersionInfo::fetchLatestFromUpdateServer();\r
 \r
-    if (! threadShouldExit())\r
-        MessageManager::callAsync ([this] { processResult(); });\r
-}\r
-\r
-//==============================================================================\r
-String getOSString()\r
-{\r
-   #if JUCE_MAC\r
-    return "OSX";\r
-   #elif JUCE_WINDOWS\r
-    return "Windows";\r
-   #elif JUCE_LINUX\r
-    return "Linux";\r
-   #else\r
-    jassertfalse;\r
-    return "Unknown";\r
-   #endif\r
-}\r
-\r
-namespace VersionHelpers\r
-{\r
-    String formatProductVersion (int versionNum)\r
+    if (info == nullptr)\r
     {\r
-        int major = (versionNum & 0xff0000) >> 16;\r
-        int minor = (versionNum & 0x00ff00) >> 8;\r
-        int build = (versionNum & 0x0000ff) >> 0;\r
-\r
-        return String (major) + '.' + String (minor) + '.' + String (build);\r
-    }\r
+        if (showAlertWindows)\r
+            AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,\r
+                                              "Update Server Communication Error",\r
+                                              "Failed to communicate with the JUCE update server.\n"\r
+                                              "Please try again in a few minutes.\n\n"\r
+                                              "If this problem persists you can download the latest version of JUCE from juce.com");\r
 \r
-    String getProductVersionString()\r
-    {\r
-        return formatProductVersion (ProjectInfo::versionNumber);\r
+        return;\r
     }\r
 \r
-    bool isNewVersion (const String& current, const String& other)\r
+    if (! info->isNewerVersionThanCurrent())\r
     {\r
-        auto currentTokens = StringArray::fromTokens (current, ".", {});\r
-        auto otherTokens   = StringArray::fromTokens (other, ".", {});\r
-\r
-        jassert (currentTokens.size() == 3 && otherTokens.size() == 3);\r
-\r
-        if (currentTokens[0].getIntValue() == otherTokens[0].getIntValue())\r
-        {\r
-            if (currentTokens[1].getIntValue() == otherTokens[1].getIntValue())\r
-                return currentTokens[2].getIntValue() < otherTokens[2].getIntValue();\r
-\r
-            return currentTokens[1].getIntValue() < otherTokens[1].getIntValue();\r
-        }\r
-\r
-        return currentTokens[0].getIntValue() < otherTokens[0].getIntValue();\r
-    }\r
-}\r
-\r
-void LatestVersionCheckerAndUpdater::queryUpdateServer()\r
-{\r
-    StringPairArray responseHeaders;\r
-\r
-    URL latestVersionURL ("https://my.roli.com/software_versions/update_to/Projucer/"\r
-                          + VersionHelpers::getProductVersionString() + '/' + getOSString()\r
-                          + "?language=" + SystemStats::getUserLanguage());\r
-\r
-    std::unique_ptr<InputStream> inStream (latestVersionURL.createInputStream (false, nullptr, nullptr,\r
-                                                                               "X-API-Key: 265441b-343403c-20f6932-76361d\nContent-Type: "\r
-                                                                               "application/json\nAccept: application/json; version=1",\r
-                                                                               0, &responseHeaders, &statusCode, 0));\r
-\r
-    if (threadShouldExit())\r
+        if (showAlertWindows)\r
+            AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon,\r
+                                              "No New Version Available",\r
+                                              "Your JUCE version is up to date.");\r
         return;\r
-\r
-    if (inStream.get() != nullptr && (statusCode == 303 || statusCode == 400))\r
-    {\r
-        if (statusCode == 303)\r
-            relativeDownloadPath = responseHeaders["Location"];\r
-\r
-        jassert (relativeDownloadPath.isNotEmpty());\r
-\r
-        jsonReply = JSON::parse (inStream->readEntireStreamAsString());\r
-    }\r
-    else if (showAlertWindows)\r
-    {\r
-        if (statusCode == 204)\r
-            AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon, "No New Version Available", "Your JUCE version is up to date.");\r
-        else\r
-            AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Network Error", "Could not connect to the web server.\n"\r
-                                                                                          "Please check your internet connection and try again.");\r
     }\r
-}\r
-\r
-void LatestVersionCheckerAndUpdater::processResult()\r
-{\r
-    if (! jsonReply.isObject())\r
-        return;\r
 \r
-    if (statusCode == 400)\r
+    auto osString = []\r
     {\r
-        auto errorObject = jsonReply.getDynamicObject()->getProperty ("error");\r
-\r
-        if (errorObject.isObject())\r
+       #if JUCE_MAC\r
+        return "osx";\r
+       #elif JUCE_WINDOWS\r
+        return "windows";\r
+       #elif JUCE_LINUX\r
+        return "linux";\r
+       #else\r
+        jassertfalse;\r
+        return "Unknown";\r
+       #endif\r
+    }();\r
+\r
+    String requiredFilename ("juce-" + info->versionString + "-" + osString + ".zip");\r
+\r
+    for (auto& asset : info->assets)\r
+    {\r
+        if (asset.name == requiredFilename)\r
         {\r
-            auto message = errorObject.getProperty ("message", {}).toString();\r
+            auto versionString = info->versionString;\r
+            auto releaseNotes  = info->releaseNotes;\r
 \r
-            if (message.isNotEmpty())\r
-                AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "JUCE Updater", message);\r
+            MessageManager::callAsync ([this, versionString, releaseNotes, asset]\r
+            {\r
+                askUserAboutNewVersion (versionString, releaseNotes, asset);\r
+            });\r
+\r
+            return;\r
         }\r
     }\r
-    else if (statusCode == 303)\r
-    {\r
-        askUserAboutNewVersion (jsonReply.getProperty ("version", {}).toString(),\r
-                                jsonReply.getProperty ("notes",   {}).toString());\r
-    }\r
+\r
+    if (showAlertWindows)\r
+        AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,\r
+                                          "Failed to find any new downloads",\r
+                                          "Please try again in a few minutes.");\r
 }\r
 \r
 //==============================================================================\r
@@ -246,14 +192,15 @@ public:
                                   RectanglePlacement::stretchToFit, 1.0f);\r
     }\r
 \r
-    static std::unique_ptr<DialogWindow> launchDialog (const String& newVersion, const String& releaseNotes)\r
+    static std::unique_ptr<DialogWindow> launchDialog (const String& newVersionString,\r
+                                                       const String& releaseNotes)\r
     {\r
         DialogWindow::LaunchOptions options;\r
 \r
-        options.dialogTitle = "Download JUCE version " + newVersion + "?";\r
+        options.dialogTitle = "Download JUCE version " + newVersionString + "?";\r
         options.resizable = false;\r
 \r
-        auto* content = new UpdateDialog (newVersion, releaseNotes);\r
+        auto* content = new UpdateDialog (newVersionString, releaseNotes);\r
         options.content.set (content, true);\r
 \r
         std::unique_ptr<DialogWindow> dialog (options.create());\r
@@ -292,66 +239,83 @@ private:
     DialogWindow* parentWindow = nullptr;\r
 };\r
 \r
-void LatestVersionCheckerAndUpdater::askUserForLocationToDownload()\r
+void LatestVersionCheckerAndUpdater::askUserForLocationToDownload (const VersionInfo::Asset& asset)\r
 {\r
-    FileChooser chooser ("Please select the location into which you'd like to install the new version",\r
+    FileChooser chooser ("Please select the location into which you would like to install the new version",\r
                          { getAppSettings().getStoredPath (Ids::jucePath, TargetOS::getThisOS()).get() });\r
 \r
     if (chooser.browseForDirectory())\r
     {\r
         auto targetFolder = chooser.getResult();\r
 \r
-        if (isJUCEFolder (targetFolder))\r
+        // By default we will install into 'targetFolder/JUCE', but we should install into\r
+        // 'targetFolder' if that is an existing JUCE directory.\r
+        bool willOverwriteJuceFolder = [&targetFolder]\r
+        {\r
+            if (isJUCEFolder (targetFolder))\r
+                return true;\r
+\r
+            targetFolder = targetFolder.getChildFile ("JUCE");\r
+\r
+            return isJUCEFolder (targetFolder);\r
+        }();\r
+\r
+        auto targetFolderPath = targetFolder.getFullPathName();\r
+\r
+        if (willOverwriteJuceFolder)\r
         {\r
             if (targetFolder.getChildFile (".git").isDirectory())\r
             {\r
                 AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Downloading New JUCE Version",\r
-                                                  "This folder is a GIT repository!\n\nYou should use a \"git pull\" to update it to the latest version.");\r
+                                                  targetFolderPath + "\n\nis a GIT repository!\n\nYou should use a \"git pull\" to update it to the latest version.");\r
 \r
                 return;\r
             }\r
 \r
             if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, "Overwrite Existing JUCE Folder?",\r
-                                                String ("Do you want to overwrite the folder:\n\n" + targetFolder.getFullPathName() + "\n\n..with the latest version from juce.com?\n\n"\r
-                                                        "This will move the existing folder to " + targetFolder.getFullPathName() + "_old.")))\r
+                                                "Do you want to replace the folder\n\n" + targetFolderPath + "\n\nwith the latest version from juce.com?\n\n"\r
+                                                "This will move the existing folder to " + targetFolderPath + "_old."))\r
             {\r
                 return;\r
             }\r
         }\r
-        else\r
+        else if (targetFolder.exists())\r
         {\r
-            targetFolder = targetFolder.getChildFile ("JUCE").getNonexistentSibling();\r
+            if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, "Existing File Or Directory",\r
+                                                "Do you want to move\n\n" + targetFolderPath + "\n\nto\n\n" + targetFolderPath + "_old?"))\r
+            {\r
+                return;\r
+            }\r
         }\r
 \r
-        downloadAndInstall (targetFolder);\r
+        downloadAndInstall (asset, targetFolder);\r
     }\r
 }\r
 \r
-void LatestVersionCheckerAndUpdater::askUserAboutNewVersion (const String& newVersion, const String& releaseNotes)\r
+void LatestVersionCheckerAndUpdater::askUserAboutNewVersion (const String& newVersionString,\r
+                                                             const String& releaseNotes,\r
+                                                             const VersionInfo::Asset& asset)\r
 {\r
-    if (newVersion.isNotEmpty() && releaseNotes.isNotEmpty()\r
-        && VersionHelpers::isNewVersion (VersionHelpers::getProductVersionString(), newVersion))\r
-    {\r
-        dialogWindow = UpdateDialog::launchDialog (newVersion, releaseNotes);\r
+    dialogWindow = UpdateDialog::launchDialog (newVersionString, releaseNotes);\r
 \r
-        if (auto* mm = ModalComponentManager::getInstance())\r
-            mm->attachCallback (dialogWindow.get(), ModalCallbackFunction::create ([this] (int result)\r
-                                                                             {\r
-                                                                                 if (result == 1)\r
-                                                                                     askUserForLocationToDownload();\r
+    if (auto* mm = ModalComponentManager::getInstance())\r
+        mm->attachCallback (dialogWindow.get(),\r
+                            ModalCallbackFunction::create ([this, asset] (int result)\r
+                                                           {\r
+                                                               if (result == 1)\r
+                                                                    askUserForLocationToDownload (asset);\r
 \r
-                                                                                 dialogWindow.reset();\r
-                                                                             }));\r
-    }\r
+                                                                dialogWindow.reset();\r
+                                                            }));\r
 }\r
 \r
 //==============================================================================\r
 class DownloadAndInstallThread   : private ThreadWithProgressWindow\r
 {\r
 public:\r
-    DownloadAndInstallThread  (const URL& u, const File& t, std::function<void()>&& cb)\r
+    DownloadAndInstallThread  (const VersionInfo::Asset& a, const File& t, std::function<void()>&& cb)\r
         : ThreadWithProgressWindow ("Downloading New Version", true, true),\r
-          downloadURL (u), targetFolder (t), completionCallback (std::move (cb))\r
+          asset (a), targetFolder (t), completionCallback (std::move (cb))\r
     {\r
         launchThread (3);\r
     }\r
@@ -368,7 +332,9 @@ private:
             result = install (zipData);\r
 \r
         if (result.failed())\r
-            MessageManager::callAsync ([result] () { AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Installation Failed", result.getErrorMessage()); });\r
+            MessageManager::callAsync ([result] { AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,\r
+                                                                                    "Installation Failed",\r
+                                                                                    result.getErrorMessage()); });\r
         else\r
             MessageManager::callAsync (completionCallback);\r
     }\r
@@ -378,10 +344,7 @@ private:
         setStatusMessage ("Downloading...");\r
 \r
         int statusCode = 0;\r
-        StringPairArray responseHeaders;\r
-\r
-        std::unique_ptr<InputStream> inStream (downloadURL.createInputStream (false, nullptr, nullptr, {}, 0,\r
-                                                                              &responseHeaders, &statusCode, 0));\r
+        auto inStream = VersionInfo::createInputStreamForAsset (asset, statusCode);\r
 \r
         if (inStream != nullptr && statusCode == 200)\r
         {\r
@@ -406,106 +369,97 @@ private:
             return Result::ok();\r
         }\r
 \r
-        return Result::fail ("Failed to download from: " + downloadURL.toString (false));\r
+        return Result::fail ("Failed to download from: " + asset.url);\r
     }\r
 \r
-    Result install (MemoryBlock& data)\r
+    Result install (const MemoryBlock& data)\r
     {\r
         setStatusMessage ("Installing...");\r
 \r
-        auto result = unzipDownload (data);\r
-\r
-        if (threadShouldExit())\r
-            result = Result::fail ("Cancelled");\r
-\r
-        if (result.failed())\r
-            return result;\r
-\r
-        return Result::ok();\r
-    }\r
-\r
-    Result unzipDownload (const MemoryBlock& data)\r
-    {\r
         MemoryInputStream input (data, false);\r
         ZipFile zip (input);\r
 \r
         if (zip.getNumEntries() == 0)\r
             return Result::fail ("The downloaded file was not a valid JUCE file!");\r
 \r
-        auto unzipTarget = File::createTempFile ({});\r
+        struct ScopedDownloadFolder\r
+        {\r
+            ScopedDownloadFolder (const File& installTargetFolder)\r
+            {\r
+                folder = installTargetFolder.getSiblingFile (installTargetFolder.getFileNameWithoutExtension() + "_download").getNonexistentSibling();\r
+                jassert (folder.createDirectory());\r
+            }\r
+\r
+            ~ScopedDownloadFolder()   { folder.deleteRecursively(); }\r
+\r
+            File folder;\r
+        };\r
+\r
+        ScopedDownloadFolder unzipTarget (targetFolder);\r
 \r
-        if (! unzipTarget.createDirectory())\r
+        if (! unzipTarget.folder.isDirectory())\r
             return Result::fail ("Couldn't create a temporary folder to unzip the new version!");\r
 \r
-        auto r = zip.uncompressTo (unzipTarget);\r
+        auto r = zip.uncompressTo (unzipTarget.folder);\r
 \r
         if (r.failed())\r
-        {\r
-            unzipTarget.deleteRecursively();\r
             return r;\r
-        }\r
 \r
-        r = applyAutoUpdaterFile (unzipTarget);\r
+        if (threadShouldExit())\r
+            return Result::fail ("Cancelled");\r
+\r
+       #if JUCE_LINUX || JUCE_MAC\r
+        r = setFilePermissions (unzipTarget.folder, zip);\r
 \r
         if (r.failed())\r
-        {\r
-            unzipTarget.deleteRecursively();\r
             return r;\r
-        }\r
+\r
+        if (threadShouldExit())\r
+            return Result::fail ("Cancelled");\r
+       #endif\r
 \r
         if (targetFolder.exists())\r
         {\r
             auto oldFolder = targetFolder.getSiblingFile (targetFolder.getFileNameWithoutExtension() + "_old").getNonexistentSibling();\r
 \r
             if (! targetFolder.moveFileTo (oldFolder))\r
-            {\r
-                unzipTarget.deleteRecursively();\r
                 return Result::fail ("Could not remove the existing folder!\n\n"\r
                                      "This may happen if you are trying to download into a directory that requires administrator privileges to modify.\n"\r
                                      "Please select a folder that is writable by the current user.");\r
-            }\r
         }\r
 \r
-        if (! unzipTarget.moveFileTo (targetFolder))\r
-        {\r
-            unzipTarget.deleteRecursively();\r
+        if (! unzipTarget.folder.getChildFile ("JUCE").moveFileTo (targetFolder))\r
             return Result::fail ("Could not overwrite the existing folder!\n\n"\r
                                  "This may happen if you are trying to download into a directory that requires administrator privileges to modify.\n"\r
                                  "Please select a folder that is writable by the current user.");\r
-        }\r
 \r
         return Result::ok();\r
     }\r
 \r
-    Result applyAutoUpdaterFile (const File& root)\r
+    Result setFilePermissions (const File& root, const ZipFile& zip)\r
     {\r
-        auto autoUpdaterFile = root.getChildFile (".autoupdater.xml");\r
+        constexpr uint32 executableFlag = (1 << 22);\r
 \r
-        if (autoUpdaterFile.existsAsFile())\r
+        for (int i = 0; i < zip.getNumEntries(); ++i)\r
         {\r
-           #if JUCE_LINUX || JUCE_MAC\r
-            if (auto parent = parseXML (autoUpdaterFile))\r
+            auto* entry = zip.getEntry (i);\r
+\r
+            if ((entry->externalFileAttributes & executableFlag) != 0 && entry->filename.getLastCharacter() != '/')\r
             {\r
-                if (auto* execElement = parent->getChildByName ("EXECUTABLE"))\r
-                {\r
-                    forEachXmlChildElementWithTagName (*execElement, e, "FILE")\r
-                    {\r
-                        auto file = root.getChildFile (e->getAllSubText());\r
-\r
-                        if (file.exists() && ! file.setExecutePermission (true))\r
-                            return Result::fail ("Failed to set executable file permission for " + file.getFileName());\r
-                    }\r
-                }\r
-            }\r
-           #endif\r
+                auto exeFile = root.getChildFile (entry->filename);\r
 \r
-            autoUpdaterFile.deleteFile();\r
+                if (! exeFile.exists())\r
+                    return Result::fail ("Failed to find executable file when setting permissions " + exeFile.getFileName());\r
+\r
+                if (! exeFile.setExecutePermission (true))\r
+                    return Result::fail ("Failed to set executable file permission for " + exeFile.getFileName());\r
+            }\r
         }\r
 \r
         return Result::ok();\r
     }\r
 \r
-    URL downloadURL;\r
+    VersionInfo::Asset asset;\r
     File targetFolder;\r
     std::function<void()> completionCallback;\r
 };\r
@@ -536,9 +490,9 @@ void restartProcess (const File& targetFolder)
     }\r
 }\r
 \r
-void LatestVersionCheckerAndUpdater::downloadAndInstall (const File& targetFolder)\r
+void LatestVersionCheckerAndUpdater::downloadAndInstall (const VersionInfo::Asset& asset, const File& targetFolder)\r
 {\r
-    installer.reset (new DownloadAndInstallThread ({ relativeDownloadPath }, targetFolder,\r
+    installer.reset (new DownloadAndInstallThread (asset, targetFolder,\r
                                                    [this, targetFolder]\r
                                                    {\r
                                                        installer.reset();\r
index aa1949376f9c1be481275fcee65a9f2412815986..2f4b288b581dd9a48fd00f872a6720832f246a17 100644 (file)
@@ -26,6 +26,8 @@
 \r
 #pragma once\r
 \r
+#include "../Utility/Helpers/jucer_VersionInfo.h"\r
+\r
 class DownloadAndInstallThread;\r
 \r
 class LatestVersionCheckerAndUpdater   : public DeletedAtShutdown,\r
@@ -43,17 +45,12 @@ public:
 private:\r
     //==============================================================================\r
     void run() override;\r
-    void queryUpdateServer();\r
-    void processResult();\r
-    void askUserAboutNewVersion (const String&, const String&);\r
-    void askUserForLocationToDownload();\r
-    void downloadAndInstall (const File&);\r
+    void askUserAboutNewVersion (const String&, const String&, const VersionInfo::Asset&);\r
+    void askUserForLocationToDownload (const VersionInfo::Asset&);\r
+    void downloadAndInstall (const VersionInfo::Asset&, const File&);\r
 \r
     //==============================================================================\r
     bool showAlertWindows = false;\r
-    int statusCode = 0;\r
-    String relativeDownloadPath;\r
-    var jsonReply;\r
 \r
     std::unique_ptr<DownloadAndInstallThread> installer;\r
     std::unique_ptr<Component> dialogWindow;\r
index 048a9aa3e7c3f71311bcb5241396988a979e27d5..b96a1bbf0f7643f162349b6eee87ed1332e685de 100644 (file)
@@ -26,7 +26,7 @@
 \r
 #pragma once\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 #include "jucer_CommonHeaders.h"\r
 \r
 #if JUCE_DEBUG\r
index 68d2ddab0a5e854bcefef5e95aa3e1a644af6f98..8a10d2c058317c4ef90933312439f76801d883be 100644 (file)
@@ -50,13 +50,15 @@ MainWindow::MainWindow()
     setResizable (true, false);\r
     centreWithSize (800, 600);\r
 \r
-    ApplicationCommandManager& commandManager = ProjucerApplication::getCommandManager();\r
+    auto& commandManager = ProjucerApplication::getCommandManager();\r
 \r
-    // Register all the app commands..\r
-    commandManager.registerAllCommandsForTarget (this);\r
-    commandManager.registerAllCommandsForTarget (getProjectContentComponent());\r
+    auto registerAllAppCommands = [&]\r
+    {\r
+        commandManager.registerAllCommandsForTarget (this);\r
+        commandManager.registerAllCommandsForTarget (getProjectContentComponent());\r
+    };\r
 \r
-    // update key mappings..\r
+    auto updateAppKeyMappings = [&]\r
     {\r
         commandManager.getKeyMappings()->resetToDefaultMappings();\r
 \r
@@ -64,13 +66,13 @@ MainWindow::MainWindow()
             commandManager.getKeyMappings()->restoreFromXml (*keys);\r
 \r
         addKeyListener (commandManager.getKeyMappings());\r
-    }\r
+    };\r
 \r
-    // don't want the window to take focus when the title-bar is clicked..\r
-    setWantsKeyboardFocus (false);\r
+    registerAllAppCommands();\r
+    updateAppKeyMappings();\r
 \r
+    setWantsKeyboardFocus (false);\r
     getLookAndFeel().setColour (ColourSelector::backgroundColourId, Colours::transparentBlack);\r
-\r
     projectNameValue.addListener (this);\r
 \r
     setResizeLimits (600, 500, 32000, 32000);\r
@@ -83,8 +85,6 @@ MainWindow::~MainWindow()
    #endif\r
 \r
     removeKeyListener (ProjucerApplication::getCommandManager().getKeyMappings());\r
-\r
-    // save the current size and position to our settings file..\r
     getGlobalProperties().setValue ("lastMainWindowPos", getWindowStateAsString());\r
 \r
     clearContentComponent();\r
@@ -97,7 +97,6 @@ void MainWindow::createProjectContentCompIfNeeded()
     {\r
         clearContentComponent();\r
         setContentOwned (new ProjectContentComponent(), false);\r
-        jassert (getProjectContentComponent() != nullptr);\r
     }\r
 }\r
 \r
@@ -119,12 +118,10 @@ void MainWindow::setTitleBarIcon()
 \r
 void MainWindow::makeVisible()\r
 {\r
-    restoreWindowPosition();\r
     setVisible (true);\r
-    addToDesktop();  // (must add before restoring size so that fullscreen will work)\r
+    addToDesktop();\r
     restoreWindowPosition();\r
     setTitleBarIcon();\r
-\r
     getContentComponent()->grabKeyboardFocus();\r
 }\r
 \r
@@ -138,14 +135,12 @@ void MainWindow::closeButtonPressed()
     ProjucerApplication::getApp().mainWindowList.closeWindow (this);\r
 }\r
 \r
-bool MainWindow::closeProject (Project* project, bool askUserToSave)\r
+bool MainWindow::closeCurrentProject (bool askUserToSave)\r
 {\r
-    jassert (project == currentProject.get() && project != nullptr);\r
-\r
-    if (project == nullptr)\r
+    if (currentProject == nullptr)\r
         return true;\r
 \r
-    project->getStoredProperties().setValue (getProjectWindowPosName(), getWindowStateAsString());\r
+    currentProject->getStoredProperties().setValue (getProjectWindowPosName(), getWindowStateAsString());\r
 \r
     if (auto* pcc = getProjectContentComponent())\r
     {\r
@@ -154,28 +149,24 @@ bool MainWindow::closeProject (Project* project, bool askUserToSave)
         pcc->hideEditor();\r
     }\r
 \r
-    if (! ProjucerApplication::getApp().openDocumentManager.closeAllDocumentsUsingProject (*project, askUserToSave))\r
-        return false;\r
-\r
-    if (! askUserToSave || (project->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk))\r
+    if (ProjucerApplication::getApp().openDocumentManager\r
+         .closeAllDocumentsUsingProject (*currentProject, askUserToSave))\r
     {\r
-        setProject (nullptr);\r
-        return true;\r
+        if (! askUserToSave || (currentProject->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk))\r
+        {\r
+            setProject (nullptr);\r
+            return true;\r
+        }\r
     }\r
 \r
     return false;\r
 }\r
 \r
-bool MainWindow::closeCurrentProject()\r
-{\r
-    return currentProject == nullptr || closeProject (currentProject.get());\r
-}\r
-\r
 void MainWindow::moveProject (File newProjectFileToOpen)\r
 {\r
     auto openInIDE = currentProject->shouldOpenInIDEAfterSaving();\r
 \r
-    closeProject (currentProject.get(), false);\r
+    closeCurrentProject (false);\r
     openFile (newProjectFileToOpen);\r
 \r
     if (currentProject != nullptr)\r
@@ -186,21 +177,25 @@ void MainWindow::moveProject (File newProjectFileToOpen)
     }\r
 }\r
 \r
-void MainWindow::setProject (Project* newProject)\r
+void MainWindow::setProject (std::unique_ptr<Project> newProject)\r
 {\r
-    createProjectContentCompIfNeeded();\r
-    getProjectContentComponent()->setProject (newProject);\r
-    currentProject.reset (newProject);\r
-\r
-    if (currentProject != nullptr)\r
-        projectNameValue.referTo (currentProject->getProjectValue (Ids::name));\r
-    else\r
+    if (newProject == nullptr)\r
+    {\r
+        getProjectContentComponent()->setProject (nullptr);\r
         projectNameValue.referTo (Value());\r
 \r
-    if (newProject != nullptr)\r
+        currentProject.reset();\r
+    }\r
+    else\r
     {\r
+        currentProject = std::move (newProject);\r
+\r
+        createProjectContentCompIfNeeded();\r
+        getProjectContentComponent()->setProject (currentProject.get());\r
+        projectNameValue.referTo (currentProject->getProjectValue (Ids::name));\r
+\r
         if (auto* peer = getPeer())\r
-            peer->setRepresentedFile (newProject->getFile());\r
+            peer->setRepresentedFile (currentProject->getFile());\r
     }\r
 \r
     ProjucerApplication::getCommandManager().commandStatusChanged();\r
@@ -232,20 +227,16 @@ bool MainWindow::openFile (const File& file)
 \r
     if (file.hasFileExtension (Project::projectFileExtension))\r
     {\r
-        std::unique_ptr<Project> newDoc (new Project (file));\r
-\r
+        auto newDoc = std::make_unique<Project> (file);\r
         auto result = newDoc->loadFrom (file, true);\r
 \r
-        if (result.wasOk() && closeCurrentProject())\r
+        if (result.wasOk() && closeCurrentProject (true))\r
         {\r
-            setProject (newDoc.get());\r
-            newDoc.release()->setChangedFlag (false);\r
+            setProject (std::move (newDoc));\r
+            currentProject->setChangedFlag (false);\r
 \r
-            jassert (getProjectContentComponent() != nullptr);\r
             getProjectContentComponent()->reloadLastOpenDocuments();\r
-\r
-            if (auto* p = getProject())\r
-                p->updateDeprecatedProjectSettingsInteractively();\r
+            currentProject->updateDeprecatedProjectSettingsInteractively();\r
 \r
             return true;\r
         }\r
@@ -606,7 +597,7 @@ bool MainWindowList::askAllWindowsToClose()
 \r
     while (windows.size() > 0)\r
     {\r
-        if (! windows[0]->closeCurrentProject())\r
+        if (! windows[0]->closeCurrentProject (true))\r
             return false;\r
 \r
         windows.remove (0);\r
@@ -617,7 +608,7 @@ bool MainWindowList::askAllWindowsToClose()
 \r
 void MainWindowList::createWindowIfNoneAreOpen()\r
 {\r
-    if (windows.size() == 0)\r
+    if (windows.isEmpty())\r
         createNewMainWindow()->showStartPage();\r
 }\r
 \r
@@ -633,7 +624,7 @@ void MainWindowList::closeWindow (MainWindow* w)
     else\r
    #endif\r
     {\r
-        if (w->closeCurrentProject())\r
+        if (w->closeCurrentProject (true))\r
         {\r
             windows.removeObject (w);\r
             saveCurrentlyOpenProjectList();\r
@@ -689,22 +680,21 @@ bool MainWindowList::openFile (const File& file, bool openInBackground)
         WeakReference<Component> previousFrontWindow (getFrontmostWindow());\r
 \r
         auto* w = getOrCreateEmptyWindow();\r
-        bool ok = w->openFile (file);\r
+        jassert (w != nullptr);\r
 \r
-        if (ok)\r
+        if (w->openFile (file))\r
         {\r
             w->makeVisible();\r
-            avoidSuperimposedWindows (w);\r
-        }\r
-        else\r
-        {\r
-            closeWindow (w);\r
-        }\r
+            checkWindowBounds (*w);\r
 \r
-        if (openInBackground && previousFrontWindow != nullptr)\r
-            previousFrontWindow->toFront (true);\r
+            if (openInBackground && previousFrontWindow != nullptr)\r
+                previousFrontWindow->toFront (true);\r
+\r
+            return true;\r
+        }\r
 \r
-        return ok;\r
+        closeWindow (w);\r
+        return false;\r
     }\r
 \r
     if (getFrontmostWindow()->tryToOpenPIP (file))\r
@@ -718,11 +708,8 @@ bool MainWindowList::openFile (const File& file, bool openInBackground)
 \r
 MainWindow* MainWindowList::createNewMainWindow()\r
 {\r
-    auto w = new MainWindow();\r
-    windows.add (w);\r
-    w->restoreWindowPosition();\r
-    avoidSuperimposedWindows (w);\r
-    return w;\r
+    windows.add (new MainWindow());\r
+    return windows.getLast();\r
 }\r
 \r
 MainWindow* MainWindowList::getFrontmostWindow (bool createIfNotFound)\r
@@ -732,8 +719,11 @@ MainWindow* MainWindowList::getFrontmostWindow (bool createIfNotFound)
         if (createIfNotFound)\r
         {\r
             auto* w = createNewMainWindow();\r
-            avoidSuperimposedWindows (w);\r
+            jassert (w != nullptr);\r
+\r
             w->makeVisible();\r
+            checkWindowBounds (*w);\r
+\r
             return w;\r
         }\r
 \r
@@ -784,29 +774,52 @@ MainWindow* MainWindowList::getMainWindowForFile (const File& file)
     return nullptr;\r
 }\r
 \r
-void MainWindowList::avoidSuperimposedWindows (MainWindow* const mw)\r
+void MainWindowList::checkWindowBounds (MainWindow& windowToCheck)\r
 {\r
-    for (int i = windows.size(); --i >= 0;)\r
+    auto avoidSuperimposedWindows = [&]\r
     {\r
-        auto* other = windows.getUnchecked(i);\r
+        for (auto* otherWindow : windows)\r
+        {\r
+            if (otherWindow == nullptr || otherWindow == &windowToCheck)\r
+                continue;\r
 \r
-        auto b1 = mw->getBounds();\r
-        auto b2 = other->getBounds();\r
+            auto boundsToCheck = windowToCheck.getScreenBounds();\r
+            auto otherBounds = otherWindow->getScreenBounds();\r
 \r
-        if (mw != other\r
-             && std::abs (b1.getX() - b2.getX()) < 3\r
-             && std::abs (b1.getY() - b2.getY()) < 3\r
-             && std::abs (b1.getRight()  - b2.getRight()) < 3\r
-             && std::abs (b1.getBottom() - b2.getBottom()) < 3)\r
-        {\r
-            int dx = 40, dy = 30;\r
+            if (std::abs (boundsToCheck.getX() - otherBounds.getX()) < 3\r
+                 && std::abs (boundsToCheck.getY() - otherBounds.getY()) < 3\r
+                 && std::abs (boundsToCheck.getRight()  - otherBounds.getRight()) < 3\r
+                 && std::abs (boundsToCheck.getBottom() - otherBounds.getBottom()) < 3)\r
+            {\r
+                int dx = 40, dy = 30;\r
 \r
-            if (b1.getCentreX() >= mw->getScreenBounds().getCentreX())   dx = -dx;\r
-            if (b1.getCentreY() >= mw->getScreenBounds().getCentreY())   dy = -dy;\r
+                if (otherBounds.getCentreX() >= boundsToCheck.getCentreX())  dx = -dx;\r
+                if (otherBounds.getCentreY() >= boundsToCheck.getCentreY())  dy = -dy;\r
 \r
-            mw->setBounds (b1.translated (dx, dy));\r
+                windowToCheck.setBounds (boundsToCheck.translated (dx, dy));\r
+            }\r
         }\r
-    }\r
+    };\r
+\r
+    auto ensureWindowIsFullyOnscreen = [&]\r
+    {\r
+        auto windowBounds = windowToCheck.getScreenBounds();\r
+        auto screenLimits = Desktop::getInstance().getDisplays().findDisplayForRect (windowBounds).userArea;\r
+\r
+        if (auto* peer = windowToCheck.getPeer())\r
+            peer->getFrameSize().subtractFrom (screenLimits);\r
+\r
+        auto constrainedX = jlimit (screenLimits.getX(), jmax (screenLimits.getX(), screenLimits.getRight()  - windowBounds.getWidth()),  windowBounds.getX());\r
+        auto constrainedY = jlimit (screenLimits.getY(), jmax (screenLimits.getY(), screenLimits.getBottom() - windowBounds.getHeight()), windowBounds.getY());\r
+\r
+        Point<int> constrainedTopLeft (constrainedX, constrainedY);\r
+\r
+        if (windowBounds.getPosition() != constrainedTopLeft)\r
+            windowToCheck.setTopLeftPosition (constrainedTopLeft);\r
+    };\r
+\r
+    avoidSuperimposedWindows();\r
+    ensureWindowIsFullyOnscreen();\r
 }\r
 \r
 void MainWindowList::saveCurrentlyOpenProjectList()\r
index 919691f7abf26f5a49e01e2ec1c647cf7e2cab58..43de4be5ae82ee37f457e900a95499398c6e5f6b 100644 (file)
@@ -50,14 +50,15 @@ public:
     //==============================================================================\r
     bool canOpenFile (const File& file) const;\r
     bool openFile (const File& file);\r
-    void setProject (Project* newProject);\r
-    Project* getProject() const                 { return currentProject.get(); }\r
+\r
+    void setProject (std::unique_ptr<Project> newProject);\r
+    Project* getProject() const  { return currentProject.get(); }\r
+\r
     bool tryToOpenPIP (const File& f);\r
 \r
     void makeVisible();\r
     void restoreWindowPosition();\r
-    bool closeProject (Project* project, bool askToSave = true);\r
-    bool closeCurrentProject();\r
+    bool closeCurrentProject (bool askToSave);\r
     void moveProject (File newProjectFile);\r
 \r
     void showStartPage();\r
@@ -118,7 +119,7 @@ public:
     void reopenLastProjects();\r
     void saveCurrentlyOpenProjectList();\r
 \r
-    void avoidSuperimposedWindows (MainWindow*);\r
+    void checkWindowBounds (MainWindow&);\r
 \r
     void sendLookAndFeelChange();\r
 \r
index d47a398799f43340f21e7a43b54f1b72e6be6b2b..ffaafbfcb147bbdbf35c3d6d2c2b00b568298377 100644 (file)
@@ -20,7 +20,7 @@
 #pragma once\r
 \r
 //[Headers]     -- You can add your own extra header files here --\r
-%%include_juce_header%%\r
+%%include_juce%%\r
 //[/Headers]\r
 \r
 %%include_files_h%%\r
@@ -38,7 +38,7 @@
 public:\r
     //==============================================================================\r
     %%class_name%% (%%constructor_params%%);\r
-    ~%%class_name%%();\r
+    ~%%class_name%%() override;\r
 \r
     //==============================================================================\r
     //[UserMethods]     -- You can add your own custom methods in this section.\r
index c26a2d0465946409833f2fc3d13275eb69a398e1..da0677bdd1aa09c6772328ae944f7c6e0b8b1c06 100644 (file)
@@ -6,7 +6,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+%%include_juce%%\r
 #include "%%filename%%"\r
 \r
 %%component_begin%%\r
index 5b6a4a4f513e366ac6fe2398789cad99c95be46a..0ab742211dc8e9e8b683745e5d2c3b669cf06d65 100644 (file)
@@ -145,8 +145,8 @@ void PaintElementImage::fillInGeneratedCode (GeneratedCode& code, String& paintM
                 else\r
                     r << "    g.setColour (Colours::black.withAlpha (" << CodeHelpers::floatLiteral (opacity, 3) << "));\n";\r
 \r
-                r << "    jassert (" << imageVariable << " != 0);\n"\r
-                  << "    if (" << imageVariable << " != 0)\n"\r
+                r << "    jassert (" << imageVariable << " != nullptr);\n"\r
+                  << "    if (" << imageVariable << " != nullptr)\n"\r
                   << "        " << imageVariable  << "->drawWithin (g, Rectangle<int> (x, y, width, height).toFloat(),\n"\r
                   << "    " << String::repeatedString (" ", imageVariable.length() + 18)\r
                   << (mode == stretched ? "RectanglePlacement::stretchToFit"\r
index 0b43f9eef924e15c1f87c3187852ea4705796700..a63a13fe9d88904533bbae7a5c1d1cd005fab540 100644 (file)
@@ -319,10 +319,7 @@ static void copyAcrossUserSections (String& dest, const String& src)
 }
 
 //==============================================================================
-void GeneratedCode::applyToCode (String& code,
-                                 const File& targetFile,
-                                 const String& oldFileWithUserData,
-                                 Project* project) const
+void GeneratedCode::applyToCode (String& code, const File& targetFile, const String& oldFileWithUserData) const
 {
     replaceTemplate (code, "version", JUCEApplicationBase::getInstance()->getApplicationVersion());
     replaceTemplate (code, "creationTime", Time::getCurrentTime().toString (true, true, true));
@@ -337,11 +334,8 @@ void GeneratedCode::applyToCode (String& code,
 
     replaceTemplate (code, "method_definitions", getCallbackDefinitions());
 
-    File juceHeaderFile = project != nullptr ? project->getAppIncludeFile()
-                                             : targetFile.getSiblingFile ("JuceHeader.h");
-
-    replaceTemplate (code, "include_juce_header", CodeHelpers::createIncludeStatement (juceHeaderFile, targetFile));
-
+    replaceTemplate (code, "include_juce", CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename()));
+    
     replaceTemplate (code, "include_files_h", getIncludeFileCode (includeFilesH, targetFile));
     replaceTemplate (code, "include_files_cpp", getIncludeFileCode (includeFilesCPP, targetFile));
 
index 29eda964a3f85678c2e83769a57ae38390fe2045..5f62f35dd0c542ab714f65ba6abf0d9cc5921846 100644 (file)
@@ -41,11 +41,7 @@ public:
     ~GeneratedCode();\r
 \r
     //==============================================================================\r
-    void applyToCode (String& code,\r
-                      const File& targetFile,\r
-                      const String& oldFileWithUserData,\r
-                      Project* project) const;\r
-\r
+    void applyToCode (String& code, const File& targetFile, const String& oldFileWithUserData) const;\r
     int getUniqueSuffix();\r
 \r
     //==============================================================================\r
@@ -54,7 +50,7 @@ public:
     String className;\r
     String componentName;\r
     String parentClassInitialiser;  // optional parent class initialiser to go before the items in the initialisers list\r
-    StringArray initialisers; // (a list of the member variables that need initalising after the constructor declaration)\r
+    StringArray initialisers; // (a list of the member variables that need initialising after the constructor declaration)\r
     String parentClasses;\r
     String constructorParams;\r
     String privateMemberDeclarations;\r
index dea80bcde3727cc651fb80b59bd9807f3836e326..ad1e8a8e9fe457ab1d12029811826bc29fe46639 100644 (file)
@@ -532,11 +532,8 @@ bool JucerDocument::flushChangesToDocuments (Project* project, bool isInitial)
         String existingHeader (header->getCodeDocument().getAllContent());\r
         String existingCpp (cpp->getCodeDocument().getAllContent());\r
 \r
-        generated.applyToCode (headerTemplate, headerFile,\r
-                               existingHeader, project);\r
-\r
-        generated.applyToCode (cppTemplate, headerFile.withFileExtension (".cpp"),\r
-                               existingCpp, project);\r
+        generated.applyToCode (headerTemplate, headerFile, existingHeader);\r
+        generated.applyToCode (cppTemplate, headerFile.withFileExtension (".cpp"), existingCpp);\r
 \r
         if (isInitial)\r
         {\r
index 40d6767ed021146976f42ee714fb2d44f492ce00..d852991a71199063d6f3856f2be138e7f002435a 100644 (file)
@@ -336,9 +336,6 @@ private:
             if (exporter->canLaunchProject())\r
                 defs.add (exporter->getExporterIdentifierMacro() + "=1");\r
 \r
-        // Use the JUCE implementation of std::function until the live build\r
-        // engine can compile the one from the standard library\r
-        defs.add (" _LIBCPP_FUNCTIONAL=1");\r
         defs.removeEmptyStrings();\r
 \r
         return defs.joinIntoString (" ");\r
@@ -380,7 +377,7 @@ private:
             auto isVSTHost = project.getEnabledModules().isModuleEnabled ("juce_audio_processors")\r
                    && (project.isConfigFlagEnabled ("JUCE_PLUGINHOST_VST3") || project.isConfigFlagEnabled ("JUCE_PLUGINHOST_VST"));\r
 \r
-            auto isPluginProject = proj.getProjectType().isAudioPlugin();\r
+            auto isPluginProject = proj.isAudioPluginProject();\r
 \r
             OwnedArray<LibraryModule> modules;\r
             proj.getEnabledModules().createRequiredModules (modules);\r
@@ -462,6 +459,7 @@ private:
     StringArray getSystemIncludePaths()\r
     {\r
         StringArray paths;\r
+        paths.add (project.getGeneratedCodeFolder().getFullPathName());\r
         paths.addArray (getSearchPathsFromString (project.getCompileEngineSettings().getSystemHeaderPathString()));\r
 \r
         auto isVSTHost = project.getEnabledModules().isModuleEnabled ("juce_audio_processors")\r
@@ -470,7 +468,7 @@ private:
 \r
         auto customVst3Path = getAppSettings().getStoredPath (Ids::vst3Path, TargetOS::getThisOS()).get().toString();\r
 \r
-        if (customVst3Path.isNotEmpty() && (project.getProjectType().isAudioPlugin() || isVSTHost))\r
+        if (customVst3Path.isNotEmpty() && (project.isAudioPluginProject() || isVSTHost))\r
             paths.add (customVst3Path);\r
 \r
         OwnedArray<LibraryModule> modules;\r
@@ -480,7 +478,7 @@ private:
         {\r
             paths.addIfNotAlreadyThere (module->getFolder().getParentDirectory().getFullPathName());\r
 \r
-            if (customVst3Path.isEmpty() && (project.getProjectType().isAudioPlugin() || isVSTHost))\r
+            if (customVst3Path.isEmpty() && (project.isAudioPluginProject() || isVSTHost))\r
                 if (module->getID() == "juce_audio_processors")\r
                     paths.addIfNotAlreadyThere (module->getFolder().getChildFile ("format_types").getChildFile ("VST3_SDK").getFullPathName());\r
         }\r
index b3273dee2fb73a150bdf663e9b04906d52114f78..5b65750066ad73d9f0138b1abc5f1620b9c90057 100644 (file)
@@ -27,6 +27,7 @@
 #include "../Application/jucer_Headers.h"\r
 #include "jucer_DownloadCompileEngineThread.h"\r
 #include "../LiveBuildEngine/jucer_CompileEngineDLL.h"\r
+#include "../Utility/Helpers/jucer_VersionInfo.h"\r
 \r
 //==============================================================================\r
 bool DownloadCompileEngineThread::downloadAndInstall()\r
@@ -83,38 +84,60 @@ void DownloadCompileEngineThread::run()
 \r
 Result DownloadCompileEngineThread::download (MemoryBlock& dest)\r
 {\r
-    int statusCode = 302;\r
-    const int timeoutMs = 10000;\r
-    StringPairArray responseHeaders;\r
+    auto info = VersionInfo::fetchFromUpdateServer (ProjectInfo::versionString);\r
 \r
-    URL url = getDownloadUrl();\r
-    std::unique_ptr<InputStream> in (url.createInputStream (false, nullptr, nullptr,\r
-                                                            String(), timeoutMs, &responseHeaders,\r
-                                                            &statusCode, 0));\r
+    if (info == nullptr)\r
+        return Result::fail ("Download error: cannot communicate with server");\r
 \r
-    if (in == nullptr || statusCode != 200)\r
-        return Result::fail ("Download error: cannot establish connection");\r
+    auto requiredAssetName = []\r
+    {\r
+        String name ("JUCECompileEngine_");\r
 \r
-    MemoryOutputStream mo (dest, true);\r
+       #if JUCE_MAC\r
+        name << "osx_";\r
+       #elif JUCE_WINDOWS\r
+        name << "windows_";\r
+       #else\r
+        jassertfalse;\r
+       #endif\r
 \r
-    int64 size = in->getTotalLength();\r
-    int64 bytesReceived = -1;\r
-    String msg("Downloading...  (123)");\r
+        return name + ProjectInfo::versionString + ".zip";\r
+    }();\r
 \r
-    for (int64 pos = 0; pos < size; pos += bytesReceived)\r
+    for (auto& asset : info->assets)\r
     {\r
-        setStatusMessage (msg.replace ("123", File::descriptionOfSizeInBytes (pos)));\r
+        if (asset.name == requiredAssetName)\r
+        {\r
+            int statusCode = 0;\r
+            auto in = VersionInfo::createInputStreamForAsset (asset, statusCode);\r
+\r
+            if (in == nullptr || statusCode != 200)\r
+                return Result::fail ("Download error: cannot establish connection");\r
+\r
+            MemoryOutputStream mo (dest, true);\r
+\r
+            int64 size = in->getTotalLength();\r
+            int64 bytesReceived = -1;\r
+            String msg("Downloading...  (123)");\r
+\r
+            for (int64 pos = 0; pos < size; pos += bytesReceived)\r
+            {\r
+                setStatusMessage (msg.replace ("123", File::descriptionOfSizeInBytes (pos)));\r
+\r
+                if (threadShouldExit())\r
+                    return Result::fail ("Download error: operation interrupted");\r
 \r
-        if (threadShouldExit())\r
-            return Result::fail ("Download error: operation interrupted");\r
+                bytesReceived = mo.writeFromInputStream (*in, 8192);\r
 \r
-        bytesReceived = mo.writeFromInputStream (*in, 8192);\r
+                if (bytesReceived == 0)\r
+                    return Result::fail ("Download error: lost connection");\r
+            }\r
 \r
-        if (bytesReceived == 0)\r
-            return Result::fail ("Download error: lost connection");\r
+            return Result::ok();\r
+        }\r
     }\r
 \r
-    return Result::ok();\r
+    return Result::fail ("Download error: no downloads available");\r
 }\r
 \r
 Result DownloadCompileEngineThread::install (const MemoryBlock& data, File& targetFolder)\r
@@ -131,21 +154,6 @@ Result DownloadCompileEngineThread::install (const MemoryBlock& data, File& targ
     return zip.uncompressTo (targetFolder);\r
 }\r
 \r
-URL DownloadCompileEngineThread::getDownloadUrl()\r
-{\r
-    String urlStub ("http://assets.roli.com/juce/JUCECompileEngine_");\r
-\r
-   #if JUCE_MAC\r
-    urlStub << "osx_";\r
-   #elif JUCE_WINDOWS\r
-    urlStub << "windows_";\r
-   #else\r
-    jassertfalse;\r
-   #endif\r
-\r
-    return urlStub + ProjectInfo::versionString + ".zip";\r
-}\r
-\r
 File DownloadCompileEngineThread::getInstallFolder()\r
 {\r
     return CompileEngineDLL::getVersionedUserAppSupportFolder();\r
index 9cee8477da7169b0a6e8240d2367ef035dd8c1e6..7917a4fdd4b476f6d54af75f7d34e0fa2ffd3616 100644 (file)
@@ -151,6 +151,7 @@ private:
                 props.add (new CppStandardWarningComponent());\r
 \r
             group.properties.clear();\r
+            exporterModulePathDefaultValues.clear();\r
             exporterModulePathValues.clear();\r
 \r
             for (Project::ExporterIterator exporter (project); exporter.next();)\r
@@ -158,23 +159,32 @@ private:
                 if (exporter->isCLion())\r
                     continue;\r
 \r
-                exporterModulePathValues.add (exporter->getPathForModuleValue (moduleID));\r
+                exporterModulePathDefaultValues.add (exporter->getPathForModuleValue (moduleID));\r
+                auto& defaultValue = exporterModulePathDefaultValues.getReference (exporterModulePathDefaultValues.size() - 1);\r
 \r
-                auto& value = exporterModulePathValues.getReference (exporterModulePathValues.size() - 1);\r
-                value.onDefaultChange = [this] { startTimer (50); };\r
+                exporterModulePathValues.add (defaultValue.getPropertyAsValue());\r
 \r
-                auto* pathComponent = new FilePathPropertyComponent (value, "Path for " + exporter->getName().quoted(), true,\r
-                                                                     exporter->getTargetOSForExporter() == TargetOS::getThisOS(),\r
-                                                                     "*", project.getProjectFolder());\r
+                auto pathComponent = std::make_unique<FilePathPropertyComponent> (defaultValue,\r
+                                                                                  "Path for " + exporter->getName().quoted(),\r
+                                                                                  true,\r
+                                                                                  exporter->getTargetOSForExporter() == TargetOS::getThisOS(),\r
+                                                                                  "*",\r
+                                                                                  project.getProjectFolder());\r
 \r
-                props.add (pathComponent,\r
+                pathComponent->setEnabled (! modules.shouldUseGlobalPath (moduleID));\r
+\r
+                props.add (pathComponent.release(),\r
                            "A path to the folder that contains the " + moduleID + " module when compiling the "\r
                            + exporter->getName().quoted() + " target. "\r
                            "This can be an absolute path, or relative to the jucer project folder, but it "\r
                            "must be valid on the filesystem of the target machine that will be performing this build. If this "\r
                            "is empty then the global path will be used.");\r
+            }\r
 \r
-                pathComponent->setEnabled (! modules.shouldUseGlobalPath (moduleID));\r
+            for (int i = 0; i < exporterModulePathDefaultValues.size(); ++i)\r
+            {\r
+                exporterModulePathDefaultValues.getReference (i).onDefaultChange = [this] { startTimer (50); };\r
+                exporterModulePathValues.getReference (i).addListener (this);\r
             }\r
 \r
             globalPathValue.removeListener (this);\r
@@ -227,11 +237,32 @@ private:
         String getModuleID() const noexcept    { return moduleID; }\r
 \r
     private:\r
-        void valueChanged (Value&) override    { startTimer (50); }\r
-        void timerCallback() override          { stopTimer(); refresh(); }\r
+        void valueChanged (Value& v) override\r
+        {\r
+            auto isExporterPathValue = [&]\r
+            {\r
+                for (auto& exporterValue : exporterModulePathValues)\r
+                    if (exporterValue.refersToSameSourceAs (v))\r
+                        return true;\r
+\r
+                return false;\r
+            }();\r
+\r
+            if (isExporterPathValue)\r
+                project.rescanExporterPathModules();\r
+\r
+            startTimer (50);\r
+        }\r
+\r
+        void timerCallback() override\r
+        {\r
+            stopTimer();\r
+            refresh();\r
+        }\r
 \r
         //==============================================================================\r
-        Array<ValueWithDefault> exporterModulePathValues;\r
+        Array<ValueWithDefault> exporterModulePathDefaultValues;\r
+        Array<Value> exporterModulePathValues;\r
         Value globalPathValue;\r
 \r
         OwnedArray <Project::ConfigFlag> configFlags;\r
index 8e3a367c3e2c28058150e9265bda90e94c8f0e3a..052e3c00155f39d849bf5857710f9a4478ac31ff 100644 (file)
@@ -559,7 +559,7 @@ bool ProjectContentComponent::saveProject (bool shouldWait, bool openInIDE)
 void ProjectContentComponent::closeProject()\r
 {\r
     if (auto* mw = findParentComponentOfClass<MainWindow>())\r
-        mw->closeCurrentProject();\r
+        mw->closeCurrentProject (true);\r
 }\r
 \r
 void ProjectContentComponent::showProjectSettings()\r
index e33a28f5bce7876797333cf97f3f95b9080f720d..a81d322ce3df52e27c41b95e255b29fbbe337d8d 100644 (file)
@@ -302,7 +302,12 @@ void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, P
         auto& xcodeExporter = dynamic_cast<XcodeProjectExporter&> (exporter);\r
 \r
         if (project.isAUPluginHost())\r
-            xcodeExporter.xcodeFrameworks.addTokens (xcodeExporter.isOSX() ? "AudioUnit CoreAudioKit" : "CoreAudioKit", false);\r
+        {\r
+            xcodeExporter.xcodeFrameworks.add ("CoreAudioKit");\r
+\r
+            if (xcodeExporter.isOSX())\r
+                xcodeExporter.xcodeFrameworks.add ("AudioUnit");\r
+        }\r
 \r
         auto frameworks = moduleInfo.moduleInfo [xcodeExporter.isOSX() ? "OSXFrameworks" : "iOSFrameworks"].toString();\r
         xcodeExporter.xcodeFrameworks.addTokens (frameworks, ", ", {});\r
@@ -566,7 +571,7 @@ bool EnabledModuleList::isModuleEnabled (const String& moduleID) const
 \r
 bool EnabledModuleList::isAudioPluginModuleMissing() const\r
 {\r
-    return project.getProjectType().isAudioPlugin()\r
+    return project.isAudioPluginProject()\r
             && ! isModuleEnabled ("juce_audio_plugin_client");\r
 }\r
 \r
index 45f5b35124975120db413648dee80b0ce50c54da..9d760505d3f41985accfa296bb6f303a30492e84 100644 (file)
@@ -326,6 +326,7 @@ void Project::removeDefunctExporters()
     oldExporters.set ("MSVC6",   "MSVC6");\r
     oldExporters.set ("VS2010",  "Visual Studio 2010");\r
     oldExporters.set ("VS2012",  "Visual Studio 2012");\r
+    oldExporters.set ("VS2013",  "Visual Studio 2013");\r
 \r
     for (auto& key : oldExporters.getAllKeys())\r
     {\r
@@ -514,7 +515,7 @@ static int getJuceVersion (const String& v)
          + getVersionElement (v, 0);\r
 }\r
 \r
-static int getBuiltJuceVersion()\r
+static constexpr int getBuiltJuceVersion()\r
 {\r
     return JUCE_MAJOR_VERSION * 100000\r
          + JUCE_MINOR_VERSION * 1000\r
@@ -523,11 +524,7 @@ static int getBuiltJuceVersion()
 \r
 static bool isModuleNewerThanProjucer (const ModuleDescription& module)\r
 {\r
-    if (module.getID().startsWith ("juce_")\r
-        && getJuceVersion (module.getVersion()) > getBuiltJuceVersion())\r
-        return true;\r
-\r
-    return false;\r
+    return module.getID().startsWith ("juce_") && getJuceVersion (module.getVersion()) > getBuiltJuceVersion();\r
 }\r
 \r
 void Project::warnAboutOldProjucerVersion()\r
@@ -536,7 +533,6 @@ void Project::warnAboutOldProjucerVersion()
     {\r
         if (isModuleNewerThanProjucer ({ juceModule.second }))\r
         {\r
-            // Projucer is out of date!\r
             if (ProjucerApplication::getApp().isRunningCommandLine)\r
                 std::cout <<  "WARNING! This version of the Projucer is out-of-date!" << std::endl;\r
             else\r
@@ -1010,7 +1006,7 @@ void Project::createPropertyEditors (PropertyListBuilder& props)
     props.add (new TextPropertyComponent (bundleIdentifierValue, "Bundle Identifier", 256, false),\r
                "A unique identifier for this product, mainly for use in OSX/iOS builds. It should be something like 'com.yourcompanyname.yourproductname'");\r
 \r
-    if (getProjectType().isAudioPlugin())\r
+    if (isAudioPluginProject())\r
         createAudioPluginPropertyEditors (props);\r
 \r
     {\r
index 16b8be9d87c323258c097816a6f9003c23944697..80711e8ba4a0b1b900fc1779276a3fc0d59790b9 100644 (file)
@@ -67,9 +67,8 @@ public:
     File getBinaryDataCppFile (int index) const;\r
     File getBinaryDataHeaderFile() const                        { return getBinaryDataCppFile (0).withFileExtension (".h"); }\r
 \r
-    String getAppConfigFilename() const                         { return "AppConfig.h"; }\r
-    String getJuceSourceFilenameRoot() const                    { return "JuceLibraryCode"; }\r
-    String getJuceSourceHFilename() const                       { return "JuceHeader.h"; }\r
+    static String getAppConfigFilename()                        { return "AppConfig.h"; }\r
+    static String getJuceSourceHFilename()                      { return "JuceHeader.h"; }\r
 \r
     //==============================================================================\r
     template <class FileType>\r
@@ -148,7 +147,6 @@ public:
     String getVSTNumMIDIInputsString() const          { return pluginVSTNumMidiInputsValue.get(); }\r
     String getVSTNumMIDIOutputsString() const         { return pluginVSTNumMidiOutputsValue.get(); }\r
 \r
-    //==============================================================================\r
     static bool checkMultiChoiceVar (const ValueWithDefault& valueToCheck, Identifier idToCheck) noexcept\r
     {\r
         if (! valueToCheck.get().isArray())\r
@@ -162,18 +160,18 @@ public:
         return false;\r
     }\r
 \r
-    //==============================================================================\r
-    bool shouldBuildVST() const                       { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildVST); }\r
-    bool shouldBuildVST3() const                      { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildVST3); }\r
-    bool shouldBuildAU() const                        { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildAU); }\r
-    bool shouldBuildAUv3() const                      { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildAUv3); }\r
-    bool shouldBuildRTAS() const                      { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildRTAS); }\r
-    bool shouldBuildAAX() const                       { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildAAX); }\r
-    bool shouldBuildStandalonePlugin() const          { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildStandalone); }\r
-    bool shouldBuildUnityPlugin() const               { return checkMultiChoiceVar (pluginFormatsValue, Ids::buildUnity); }\r
-    bool shouldEnableIAA() const                      { return checkMultiChoiceVar (pluginFormatsValue, Ids::enableIAA); }\r
+    bool isAudioPluginProject() const                 { return getProjectType().isAudioPlugin(); }\r
+\r
+    bool shouldBuildVST() const                       { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildVST); }\r
+    bool shouldBuildVST3() const                      { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildVST3); }\r
+    bool shouldBuildAU() const                        { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildAU); }\r
+    bool shouldBuildAUv3() const                      { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildAUv3); }\r
+    bool shouldBuildRTAS() const                      { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildRTAS); }\r
+    bool shouldBuildAAX() const                       { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildAAX); }\r
+    bool shouldBuildStandalonePlugin() const          { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildStandalone); }\r
+    bool shouldBuildUnityPlugin() const               { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::buildUnity); }\r
+    bool shouldEnableIAA() const                      { return isAudioPluginProject() && checkMultiChoiceVar (pluginFormatsValue, Ids::enableIAA); }\r
 \r
-    //==============================================================================\r
     bool isPluginSynth() const                        { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginIsSynth); }\r
     bool pluginWantsMidiInput() const                 { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginWantsMidiIn); }\r
     bool pluginProducesMidiOutput() const             { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginProducesMidiOut); }\r
@@ -184,7 +182,6 @@ public:
     bool isPluginAAXBypassDisabled() const            { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginAAXDisableBypass); }\r
     bool isPluginAAXMultiMonoDisabled() const         { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginAAXDisableMultiMono); }\r
 \r
-    //==============================================================================\r
     static StringArray getAllAUMainTypeStrings() noexcept;\r
     static Array<var> getAllAUMainTypeVars() noexcept;\r
     Array<var> getDefaultAUMainTypes() const noexcept;\r
index cc24249b7f10a08b4f7e7ff13a2291eec7f8627b..bed3870db8c890a5bcf298a5acf1e751416cb445 100644 (file)
@@ -140,9 +140,9 @@ public:
           androidKeyStorePass                  (settings, Ids::androidKeyStorePass,                  getUndoManager(), "android"),\r
           androidKeyAlias                      (settings, Ids::androidKeyAlias,                      getUndoManager(), "androiddebugkey"),\r
           androidKeyAliasPass                  (settings, Ids::androidKeyAliasPass,                  getUndoManager(), "android"),\r
-          gradleVersion                        (settings, Ids::gradleVersion,                        getUndoManager(), "4.10"),\r
+          gradleVersion                        (settings, Ids::gradleVersion,                        getUndoManager(), "5.4.1"),\r
           gradleToolchain                      (settings, Ids::gradleToolchain,                      getUndoManager(), "clang"),\r
-          androidPluginVersion                 (settings, Ids::androidPluginVersion,                 getUndoManager(), "3.2.1"),\r
+          androidPluginVersion                 (settings, Ids::androidPluginVersion,                 getUndoManager(), "3.5.3"),\r
           AndroidExecutable                    (getAppSettings().getStoredPath (Ids::androidStudioExePath, TargetOS::getThisOS()).get().toString())\r
     {\r
         name = getName();\r
@@ -840,6 +840,9 @@ private:
         for (auto& d : StringArray::fromLines (androidJavaLibs.get().toString()))\r
             mo << "        implementation files('libs/" << File (d).getFileName() << "')" << newLine;\r
 \r
+        if (isInAppBillingEnabled())\r
+            mo << "        implementation 'com.android.billingclient:billing:2.1.0'" << newLine;\r
+\r
         if (areRemoteNotificationsEnabled())\r
         {\r
             mo << "        implementation 'com.google.firebase:firebase-core:16.0.1'" << newLine;\r
@@ -909,6 +912,9 @@ private:
         if (areRemoteNotificationsEnabled())\r
             addOptJavaFolderToSourceSetsForModule (javaSourceSets, modules, "juce_gui_extra");\r
 \r
+        if (project.getEnabledModules().isModuleEnabled ("juce_product_unlocking") && isInAppBillingEnabled())\r
+            addOptJavaFolderToSourceSetsForModule (javaSourceSets, modules, "juce_product_unlocking");\r
+\r
         MemoryOutputStream mo;\r
         mo.setNewLineString ("\n");\r
 \r
@@ -1215,20 +1221,13 @@ private:
     bool arePushNotificationsEnabled() const    { return androidPushNotifications.get(); }\r
     bool areRemoteNotificationsEnabled() const  { return arePushNotificationsEnabled() && androidEnableRemoteNotifications.get(); }\r
 \r
+    bool isInAppBillingEnabled() const          { return androidInAppBillingPermission.get(); }\r
+\r
     String getJNIActivityClassName() const\r
     {\r
         return getActivityClassString().replaceCharacter ('.', '/');\r
     }\r
 \r
-    static LibraryModule* getCoreModule (const OwnedArray<LibraryModule>& modules)\r
-    {\r
-        for (int i = modules.size(); --i >= 0;)\r
-            if (modules.getUnchecked (i)->getID() == "juce_core")\r
-                return modules.getUnchecked (i);\r
-\r
-        return nullptr;\r
-    }\r
-\r
     //==============================================================================\r
     String getNativeModuleBinaryName (const AndroidBuildConfiguration& config) const\r
     {\r
@@ -1351,7 +1350,7 @@ private:
             mo << "    \"" << file.toUnixStyle() << "\"" << newLine;\r
 \r
             if ((! projectItem.shouldBeCompiled()) || (! shouldFileBeCompiledByDefault (f))\r
-                || (getProject().getProjectType().isAudioPlugin()\r
+                || (getProject().isAudioPluginProject()\r
                     && targetType != ProjectType::Target::SharedCodeTarget\r
                     && targetType != ProjectType::Target::StandalonePlugIn))\r
             {\r
@@ -1442,10 +1441,10 @@ private:
         if (arePushNotificationsEnabled())\r
         {\r
             defines.set ("JUCE_PUSH_NOTIFICATIONS", "1");\r
-            defines.set ("JUCE_PUSH_NOTIFICATIONS_ACTIVITY", String::formatted("\"%s\"", getJNIActivityClassName().toUTF8()));\r
+            defines.set ("JUCE_PUSH_NOTIFICATIONS_ACTIVITY", getJNIActivityClassName().quoted());\r
         }\r
 \r
-        if (androidInAppBillingPermission.get())\r
+        if (isInAppBillingEnabled())\r
             defines.set ("JUCE_IN_APP_PURCHASES", "1");\r
 \r
         if (supportsGLv3())\r
@@ -1808,7 +1807,10 @@ private:
         StringArray s = StringArray::fromTokens (androidOtherPermissions.get().toString(), ", ", {});\r
 \r
         if (androidInternetNeeded.get())\r
+        {\r
             s.add ("android.permission.INTERNET");\r
+            s.add ("android.permission.CHANGE_WIFI_MULTICAST_STATE");\r
+        }\r
 \r
         if (androidMicNeeded.get())\r
             s.add ("android.permission.RECORD_AUDIO");\r
@@ -1829,7 +1831,7 @@ private:
         if (androidExternalWritePermission.get())\r
             s.add ("android.permission.WRITE_EXTERNAL_STORAGE");\r
 \r
-        if (androidInAppBillingPermission.get())\r
+        if (isInAppBillingEnabled())\r
             s.add ("com.android.vending.BILLING");\r
 \r
         if (androidVibratePermission.get())\r
index 0384e55ffa5a0589d6df89e19ed29ec3f56d4ba5..df743afd4db8e0474469073369a3b56cab07d312 100644 (file)
@@ -304,7 +304,7 @@ private:
     template <class Target, class Exporter>\r
     void getFileInfoList (Target& target, Exporter& exporter, const Project::Item& projectItem, std::vector<std::tuple<String, bool, String>>& fileInfoList) const\r
     {\r
-        auto targetType = (getProject().getProjectType().isAudioPlugin() ? target.type : Target::Type::SharedCodeTarget);\r
+        auto targetType = (getProject().isAudioPluginProject() ? target.type : Target::Type::SharedCodeTarget);\r
 \r
         if (projectItem.isGroup())\r
         {\r
index 722b566abe2f948271e58cf664897077f05b0281..c43928e6e453d8bebb6c2d2c6da7e37cc253ecd1 100644 (file)
@@ -432,7 +432,7 @@ private:
 \r
         if (config.exporter.isLinux())\r
         {\r
-            if (target.isDynamicLibrary() || getProject().getProjectType().isAudioPlugin())\r
+            if (target.isDynamicLibrary() || getProject().isAudioPluginProject())\r
                 flags.add ("-fPIC");\r
 \r
             auto packages = getPackages();\r
@@ -495,7 +495,7 @@ private:
     {\r
         auto librarySearchPaths = config.getLibrarySearchPaths();\r
 \r
-        if (getProject().getProjectType().isAudioPlugin() && target.type != ProjectType::Target::SharedCodeTarget)\r
+        if (getProject().isAudioPluginProject() && target.type != ProjectType::Target::SharedCodeTarget)\r
             librarySearchPaths.add (RelativePath (getSharedCodePath (config), RelativePath::buildTargetFolder).getParentDirectory().toUnixStyle().quoted());\r
 \r
         return librarySearchPaths;\r
@@ -601,7 +601,7 @@ private:
         xml.createNewChildElement ("Option")->setAttribute ("type", getTypeIndex (target.type));\r
         xml.createNewChildElement ("Option")->setAttribute ("compiler", "gcc");\r
 \r
-        if (getProject().getProjectType().isAudioPlugin() && target.type != ProjectType::Target::SharedCodeTarget)\r
+        if (getProject().isAudioPluginProject() && target.type != ProjectType::Target::SharedCodeTarget)\r
             xml.createNewChildElement ("Option")->setAttribute ("external_deps", getSharedCodePath (config));\r
 \r
         {\r
@@ -635,7 +635,7 @@ private:
         {\r
             auto* linker = xml.createNewChildElement ("Linker");\r
 \r
-            if (getProject().getProjectType().isAudioPlugin() && target.type != ProjectType::Target::SharedCodeTarget)\r
+            if (getProject().isAudioPluginProject() && target.type != ProjectType::Target::SharedCodeTarget)\r
                 setAddOption (*linker, "option", getSharedCodePath (config).quoted());\r
 \r
             for (auto& flag : getLinkerFlags (config, target))\r
@@ -747,7 +747,7 @@ private:
     // the single target\r
     CodeBlocksTarget& getMainTarget() const\r
     {\r
-        if (getProject().getProjectType().isAudioPlugin())\r
+        if (getProject().isAudioPluginProject())\r
             return getTargetWithType (ProjectType::Target::SharedCodeTarget);\r
 \r
         for (auto* target : targets)\r
@@ -761,7 +761,7 @@ private:
 \r
     CodeBlocksTarget& getTargetForProjectItem (const Project::Item& projectItem) const\r
     {\r
-        if (getProject().getProjectType().isAudioPlugin())\r
+        if (getProject().isAudioPluginProject())\r
         {\r
             if (! projectItem.shouldBeCompiled())\r
                 return getTargetWithType (ProjectType::Target::SharedCodeTarget);\r
index f47c1331a42473f462d97259dad82e8da0f8d5a0..bf46cb1f20b137d6c2ada48af5b3d3d09ff14105 100644 (file)
@@ -196,7 +196,8 @@ public:
 \r
         void createConfigProperties (PropertyListBuilder& props) override\r
         {\r
-            addVisualStudioPluginInstallPathProperties (props);\r
+            if (project.isAudioPluginProject())\r
+                addVisualStudioPluginInstallPathProperties (props);\r
 \r
             props.add (new ChoicePropertyComponent (architectureTypeValue, "Architecture",\r
                                                     { get32BitArchName(), get64BitArchName() },\r
@@ -741,7 +742,7 @@ public:
         //==============================================================================\r
         void addFilesToCompile (const Project::Item& projectItem, XmlElement& cpps, XmlElement& headers, XmlElement& otherFiles) const\r
         {\r
-            auto targetType = (getOwner().getProject().getProjectType().isAudioPlugin() ? type : SharedCodeTarget);\r
+            auto targetType = (getOwner().getProject().isAudioPluginProject() ? type : SharedCodeTarget);\r
 \r
             if (projectItem.isGroup())\r
             {\r
@@ -823,7 +824,7 @@ public:
         bool addFilesToFilter (const Project::Item& projectItem, const String& path,\r
                                XmlElement& cpps, XmlElement& headers, XmlElement& otherFiles, XmlElement& groups) const\r
         {\r
-            auto targetType = (getOwner().getProject().getProjectType().isAudioPlugin() ? type : SharedCodeTarget);\r
+            auto targetType = (getOwner().getProject().isAudioPluginProject() ? type : SharedCodeTarget);\r
 \r
             if (projectItem.isGroup())\r
             {\r
@@ -1133,7 +1134,7 @@ public:
 \r
         String getPostBuildSteps (const MSVCBuildConfiguration& config) const\r
         {\r
-            auto postBuild = config.getPostbuildCommandString();\r
+            auto postBuild = config.getPostbuildCommandString().replace ("\n", "\r\n");;\r
             auto extraPostBuild = getExtraPostBuildSteps (config);\r
 \r
             return postBuild + String (postBuild.isNotEmpty() && extraPostBuild.isNotEmpty() ? "\r\n" : "") + extraPostBuild;\r
@@ -1141,7 +1142,7 @@ public:
 \r
         String getPreBuildSteps (const MSVCBuildConfiguration& config) const\r
         {\r
-            auto preBuild = config.getPrebuildCommandString();\r
+            auto preBuild = config.getPrebuildCommandString().replace ("\n", "\r\n");;\r
             auto extraPreBuild = getExtraPreBuildSteps (config);\r
 \r
             return preBuild + String (preBuild.isNotEmpty() && extraPreBuild.isNotEmpty() ? "\r\n" : "") + extraPreBuild;\r
index 88fd4f1ed581cd25964a473c34bcacd45221dbe5..02e4b223ab54f17c9b57f8f932a12ef67df52167 100644 (file)
@@ -718,7 +718,7 @@ private:
                 }\r
                 else\r
                 {\r
-                    if (! getProject().getProjectType().isAudioPlugin())\r
+                    if (! getProject().isAudioPluginProject())\r
                         out << "all : " << target->getBuildProduct() << newLine << newLine;\r
 \r
                     target->writeTargetLine (out, packages);\r
@@ -903,7 +903,7 @@ private:
         {\r
             Array<std::pair<File, String>> targetFiles;\r
 \r
-            auto targetType = (p.getProjectType().isAudioPlugin() ? target->type : MakefileTarget::SharedCodeTarget);\r
+            auto targetType = (p.isAudioPluginProject() ? target->type : MakefileTarget::SharedCodeTarget);\r
 \r
             for (auto& f : files)\r
                 if (p.getTargetTypeFromFilePath (f.first, true) == targetType)\r
@@ -955,7 +955,7 @@ private:
 \r
         phonyTargetLine << ".PHONY: clean all strip";\r
 \r
-        if (! getProject().getProjectType().isAudioPlugin())\r
+        if (! getProject().isAudioPluginProject())\r
             return phonyTargetLine.toString();\r
 \r
         for (auto target : targets)\r
index 1764dcaae7879abc544d6430f349c828197c4c02..1331222d60a6f75c0fd05024f89ebfb703d27da0 100644 (file)
@@ -46,6 +46,15 @@ namespace
     static String getSDKDisplayName (int version)  { return getVersionName (version) + " SDK"; }\r
     static String getSDKRootName    (int version)  { return "macosx" + getVersionName (version); }\r
 \r
+    static String getOSXSDKVersion (const String& sdkVersion)\r
+    {\r
+        for (int v = oldestSDKVersion; v <= currentSDKVersion; ++v)\r
+            if (sdkVersion == getSDKDisplayName (v))\r
+                return getSDKRootName (v);\r
+\r
+        return "macosx";\r
+    }\r
+\r
     template<class ContainerType>\r
     static ContainerType getSDKChoiceList (int oldestVersion, bool displayName)\r
     {\r
@@ -95,6 +104,7 @@ public:
           customXcodeResourceFoldersValue              (settings, Ids::customXcodeResourceFolders,              getUndoManager()),\r
           customXcassetsFolderValue                    (settings, Ids::customXcassetsFolder,                    getUndoManager()),\r
           appSandboxValue                              (settings, Ids::appSandbox,                              getUndoManager()),\r
+          appSandboxInheritanceValue                   (settings, Ids::appSandboxInheritance,                   getUndoManager()),\r
           appSandboxOptionsValue                       (settings, Ids::appSandboxOptions,                       getUndoManager(), Array<var>(), ","),\r
           hardenedRuntimeValue                         (settings, Ids::hardenedRuntime,                         getUndoManager()),\r
           hardenedRuntimeOptionsValue                  (settings, Ids::hardenedRuntimeOptions,                  getUndoManager(), Array<var>(), ","),\r
@@ -168,6 +178,7 @@ public:
     Array<var> getHardenedRuntimeOptions() const       { return *hardenedRuntimeOptionsValue.get().getArray(); }\r
 \r
     bool isAppSandboxEnabled() const                   { return appSandboxValue.get(); }\r
+    bool isAppSandboxInhertianceEnabled() const        { return appSandboxInheritanceValue.get(); }\r
     Array<var> getAppSandboxOptions() const            { return *appSandboxOptionsValue.get().getArray(); }\r
 \r
     bool isMicrophonePermissionEnabled() const         { return microphonePermissionNeededValue.get(); }\r
@@ -264,7 +275,7 @@ public:
                    "This way you can specify them for OS X and iOS separately, and modify the content of the resource folders "\r
                    "without re-saving the Projucer project.");\r
 \r
-        if (getProject().getProjectType().isAudioPlugin())\r
+        if (getProject().isAudioPluginProject())\r
             props.add (new ChoicePropertyComponent (duplicateAppExResourcesFolderValue, "Add Duplicate Resources Folder to App Extension"),\r
                        "Disable this to prevent the Projucer from creating a duplicate resources folder for AUv3 app extensions.");\r
 \r
@@ -309,6 +320,11 @@ public:
             props.add (new ChoicePropertyComponent (appSandboxValue, "Use App Sandbox"),\r
                        "Enable this to use the app sandbox.");\r
 \r
+            props.add (new ChoicePropertyComponentWithEnablement (appSandboxInheritanceValue, appSandboxValue, "App Sandbox Inheritance"),\r
+                       "If app sandbox is enabled, this setting will configure a child process to inherit the sandbox of its parent. "\r
+                       "Note that if you enable this and have specified any other app sandbox entitlements below, the child process "\r
+                       "will fail to launch.");\r
+\r
             std::vector<std::pair<String, String>> sandboxOptions\r
             {\r
                 { "Network: Incoming Connections (Server)",         "network.server" },\r
@@ -333,7 +349,18 @@ public:
                 { "File Access: Music Folder (Read Only)",          "assets.music.read-only" },\r
                 { "File Access: Music Folder (Read/Write)",         "assets.music.read-write" },\r
                 { "File Access: Movies Folder (Read Only)",         "assets.movies.read-only" },\r
-                { "File Access: Movies Folder (Read/Write)",        "assets.movies.read-write" }\r
+                { "File Access: Movies Folder (Read/Write)",        "assets.movies.read-write" },\r
+\r
+                { "Temporary Exception: Audio Unit Hosting",                       "temporary-exception.audio-unit-host" },\r
+                { "Temporary Exception: Global Mach Service",                      "temporary-exception.mach-lookup.global-name" },\r
+                { "Temporary Exception: Global Mach Service Dynamic Registration", "temporary-exception.mach-register.global-name" },\r
+                { "Temporary Exception: Home Directory File Access (Read Only)",   "temporary-exception.files.home-relative-path.read-only" },\r
+                { "Temporary Exception: Home Directory File Access (Read/Write)",  "temporary-exception.files.home-relative-path.read-write" },\r
+                { "Temporary Exception: Absolute Path File Access (Read Only)",    "temporary-exception.files.absolute-path.read-only" },\r
+                { "Temporary Exception: Absolute Path File Access (Read/Write)",   "temporary-exception.files.absolute-path.read-write" },\r
+                { "Temporary Exception: IOKit User Client Class",                  "temporary-exception.iokit-user-client-class" },\r
+                { "Temporary Exception: Shared Preference Domain (Read Only)",     "temporary-exception.shared-preference.read-only" },\r
+                { "Temporary Exception: Shared Preference Domain (Read/Write)",    "temporary-exception.shared-preference.read-write" }\r
             };\r
 \r
             StringArray sandboxKeys;\r
@@ -470,7 +497,7 @@ public:
 \r
         props.add (new TextPropertyComponent (subprojectsValue, "Xcode Subprojects", 8192, true),\r
                    "Paths to Xcode projects that should be added to the build (one per line). "\r
-                   "The names of the required build products can be specified after a colon, comma seperated, "\r
+                   "The names of the required build products can be specified after a colon, comma separated, "\r
                    "e.g. \"path/to/MySubProject.xcodeproj: MySubProject, OtherTarget\". "\r
                    "If no build products are specified, all build products associated with a subproject will be added.");\r
 \r
@@ -647,7 +674,9 @@ protected:
         //==============================================================================\r
         void createConfigProperties (PropertyListBuilder& props) override\r
         {\r
-            addXcodePluginInstallPathProperties (props);\r
+            if (project.isAudioPluginProject())\r
+                addXcodePluginInstallPathProperties (props);\r
+\r
             addRecommendedLLVMCompilerWarningsProperty (props);\r
             addGCCOptimisationProperty (props);\r
 \r
@@ -665,8 +694,7 @@ protected:
             {\r
                 props.add (new ChoicePropertyComponent (osxSDKVersion, "OSX Base SDK Version", getSDKChoiceList<StringArray> (oldestSDKVersion, true),\r
                                                                                                getSDKChoiceList<Array<var>>  (oldestSDKVersion, true)),\r
-                           "The version of OSX to link against in the Xcode build. If \"Default\" is selected then the field will be left "\r
-                           "empty and the Xcode default will be used.");\r
+                           "The version of the macOS SDK to link against. If \"Default\" is selected then the Xcode default will be used.");\r
 \r
                 props.add (new ChoicePropertyComponent (osxDeploymentTarget, "OSX Deployment Target", getSDKChoiceList<StringArray> (oldestDeploymentTarget, false),\r
                                                                                                       getSDKChoiceList<Array<var>>  (oldestDeploymentTarget, true)),\r
@@ -693,7 +721,10 @@ protected:
 \r
             props.add (new ChoicePropertyComponent (stripLocalSymbolsEnabled, "Strip Local Symbols"),\r
                        "Enable this to strip any locally defined symbols resulting in a smaller binary size. Enabling this "\r
-                       "will also remove any function names from crash logs. Must be disabled for static library projects.");\r
+                       "will also remove any function names from crash logs. Must be disabled for static library projects. "\r
+                       "Note that disabling this will not necessarily generate full debug symbols. For release configs, "\r
+                       "you will also need to add the following to the \"Custom Xcode Flags\" field: "\r
+                       "GCC_GENERATE_DEBUGGING_SYMBOLS = YES, STRIP_INSTALLED_PRODUCT = NO, COPY_PHASE_STRIP = NO");\r
         }\r
 \r
         String getModuleLibraryArchName() const override\r
@@ -968,6 +999,11 @@ public:
             return String ("Info-") + String (getName()).replace (" ", "_") + String (".plist");\r
         }\r
 \r
+        String getEntitlementsFilename() const\r
+        {\r
+            return String (getName()).replace (" ", "_") + String (".entitlements");\r
+        }\r
+\r
         String xcodePackageType, xcodeBundleSignature, xcodeBundleExtension;\r
         String xcodeProductType, xcodeFileType;\r
         String xcodeOtherRezFlags, xcodeBundleIDSubPath;\r
@@ -990,7 +1026,7 @@ public:
         {\r
             Array<SourceFileInfo> result;\r
 \r
-            auto targetType = (owner.getProject().getProjectType().isAudioPlugin() ? type : SharedCodeTarget);\r
+            auto targetType = (owner.getProject().isAudioPluginProject() ? type : SharedCodeTarget);\r
 \r
             if (projectItem.isGroup())\r
             {\r
@@ -1161,8 +1197,8 @@ public:
              || (owner.isiOS() && owner.isiCloudPermissionsEnabled()))\r
                 return true;\r
 \r
-            if (owner.project.getProjectType().isAudioPlugin()\r
-                && (   (owner.isOSX() && type == Target::AudioUnitv3PlugIn)\r
+            if (owner.project.isAudioPluginProject()\r
+                && ((owner.isOSX() && type == Target::AudioUnitv3PlugIn)\r
                     || (owner.isiOS() && type == Target::StandalonePlugIn && owner.getProject().shouldEnableIAA())))\r
                 return true;\r
 \r
@@ -1196,11 +1232,7 @@ public:
                 // the aggregate target needs to have the deployment target set for\r
                 // pre-/post-build scripts\r
                 s.set ("MACOSX_DEPLOYMENT_TARGET", getOSXDeploymentTarget (config.getOSXDeploymentTargetString()));\r
-\r
-                auto sdkRoot = getOSXSDKVersion (config.getOSXSDKVersionString());\r
-\r
-                if (sdkRoot.isNotEmpty())\r
-                    s.set ("SDKROOT", sdkRoot);\r
+                s.set ("SDKROOT", getOSXSDKVersion (config.getOSXSDKVersionString()));\r
 \r
                 return s;\r
             }\r
@@ -1331,11 +1363,6 @@ public:
             else\r
             {\r
                 s.set ("MACOSX_DEPLOYMENT_TARGET", getOSXDeploymentTarget (config.getOSXDeploymentTargetString()));\r
-\r
-                auto sdkRoot = getOSXSDKVersion (config.getOSXSDKVersionString());\r
-\r
-                if (sdkRoot.isNotEmpty())\r
-                    s.set ("SDKROOT", sdkRoot);\r
             }\r
 \r
             s.set ("GCC_VERSION", gccVersion);\r
@@ -1352,7 +1379,7 @@ public:
                 s.set ("DEVELOPMENT_TEAM", owner.getDevelopmentTeamIDString());\r
 \r
             if (shouldAddEntitlements())\r
-                s.set ("CODE_SIGN_ENTITLEMENTS", owner.getEntitlementsFileName().quoted());\r
+                s.set ("CODE_SIGN_ENTITLEMENTS", getEntitlementsFilename().quoted());\r
 \r
             {\r
                 auto cppStandard = owner.project.getCppStandardString();\r
@@ -1487,7 +1514,7 @@ public:
                     librarySearchPaths.add (owner.getSearchPathForStaticLibrary (lib));\r
                 }\r
 \r
-                if (owner.project.getProjectType().isAudioPlugin())\r
+                if (owner.project.isAudioPluginProject())\r
                 {\r
                     if (owner.getTargetOfType (Target::SharedCodeTarget) != nullptr)\r
                     {\r
@@ -1768,7 +1795,7 @@ public:
                                  " -I \\\"$(DEVELOPER_DIR)/Extras/CoreAudio/AudioUnits/AUPublic/AUBase\\\""\r
                                  " -I \\\"$(DEVELOPER_DIR)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/AudioUnit.framework/Headers\\\"";\r
 \r
-            xcodeFrameworks.addTokens ("AudioUnit CoreAudioKit", false);\r
+            xcodeFrameworks.addArray ({ "AudioUnit", "CoreAudioKit" });\r
 \r
             XmlElement plistKey ("key");\r
             plistKey.addTextElement ("AudioComponents");\r
@@ -1815,10 +1842,10 @@ public:
 \r
         void addExtraAudioUnitv3PlugInTargetSettings()\r
         {\r
-            if (owner.isiOS())\r
-                xcodeFrameworks.addTokens ("CoreAudioKit AVFoundation", false);\r
-            else\r
-                xcodeFrameworks.addTokens ("AudioUnit CoreAudioKit AVFoundation", false);\r
+            xcodeFrameworks.addArray ({ "AVFoundation", "CoreAudioKit" });\r
+\r
+            if (owner.isOSX())\r
+                xcodeFrameworks.add ("AudioUnit");\r
 \r
             XmlElement plistKey ("key");\r
             plistKey.addTextElement ("NSExtension");\r
@@ -1934,15 +1961,6 @@ public:
             return getVersionName (minVersion);\r
         }\r
 \r
-        String getOSXSDKVersion (const String& sdkVersion) const\r
-        {\r
-            for (int v = oldestSDKVersion; v <= currentSDKVersion; ++v)\r
-                if (sdkVersion == getSDKDisplayName (v))\r
-                    return getSDKRootName (v);\r
-\r
-            return {};\r
-        }\r
-\r
         //==============================================================================\r
         const XcodeProjectExporter& owner;\r
 \r
@@ -1974,7 +1992,7 @@ private:
                      postbuildCommandValue, prebuildCommandValue,\r
                      duplicateAppExResourcesFolderValue, iosDeviceFamilyValue, iPhoneScreenOrientationValue,\r
                      iPadScreenOrientationValue, customXcodeResourceFoldersValue, customXcassetsFolderValue,\r
-                     appSandboxValue, appSandboxOptionsValue,\r
+                     appSandboxValue, appSandboxInheritanceValue, appSandboxOptionsValue,\r
                      hardenedRuntimeValue, hardenedRuntimeOptionsValue,\r
                      microphonePermissionNeededValue, microphonePermissionsTextValue, cameraPermissionNeededValue, cameraPermissionTextValue, iosBluetoothPermissionNeededValue, iosBluetoothPermissionTextValue,\r
                      uiFileSharingEnabledValue, uiSupportsDocumentBrowserValue, uiStatusBarHiddenValue, documentExtensionsValue, iosInAppPurchasesValue,\r
@@ -2133,7 +2151,8 @@ private:
 \r
     void addFilesAndGroupsToProject (StringArray& topLevelGroupIDs) const\r
     {\r
-        addEntitlementsFile();\r
+        for (auto* target : targets)\r
+            addEntitlementsFile (*target);\r
 \r
         for (auto& group : getAllGroups())\r
         {\r
@@ -2216,7 +2235,7 @@ private:
                 auto sourceFiles = target->sourceIDs;\r
 \r
                 if (target->type == XcodeTarget::SharedCodeTarget\r
-                     || (! project.getProjectType().isAudioPlugin()))\r
+                     || (! project.isAudioPluginProject()))\r
                     sourceFiles.addArray (sourceIDs);\r
 \r
                 target->addBuildPhase ("PBXSourcesBuildPhase", sourceFiles);\r
@@ -2227,11 +2246,11 @@ private:
 \r
             target->addShellScriptBuildPhase ("Post-build script", getPostBuildScript());\r
 \r
-            if (project.getProjectType().isAudioPlugin() && project.shouldBuildAUv3()\r
+            if (project.isAudioPluginProject() && project.shouldBuildAUv3()\r
                 && project.shouldBuildStandalonePlugin() && target->type == XcodeTarget::StandalonePlugIn)\r
                 embedAppExtension();\r
 \r
-            if (project.getProjectType().isAudioPlugin() && project.shouldBuildUnityPlugin()\r
+            if (project.isAudioPluginProject() && project.shouldBuildUnityPlugin()\r
                 && target->type == XcodeTarget::UnityPlugIn)\r
                 embedUnityScript();\r
 \r
@@ -2338,7 +2357,7 @@ private:
     {\r
         StringArray dependencies;\r
 \r
-        if (project.getProjectType().isAudioPlugin())\r
+        if (project.isAudioPluginProject())\r
         {\r
             if (target.type == XcodeTarget::StandalonePlugIn) // depends on AUv3 and shared code\r
             {\r
@@ -2617,6 +2636,10 @@ private:
             s.set ("TARGETED_DEVICE_FAMILY", getDeviceFamilyString().quoted());\r
             s.set ("IPHONEOS_DEPLOYMENT_TARGET", config.getiOSDeploymentTargetString());\r
         }\r
+        else\r
+        {\r
+            s.set ("SDKROOT", getOSXSDKVersion (config.getOSXSDKVersionString()));\r
+        }\r
 \r
         s.set ("ZERO_LINK", "NO");\r
 \r
@@ -2656,6 +2679,16 @@ private:
             s.removeDuplicates (true);\r
             s.sort (true);\r
 \r
+            // When building against the 10.15 SDK we need to make sure the\r
+            // AudioUnit framework is linked before the AudioToolbox framework.\r
+            auto audioUnitIndex = s.indexOf ("AudioUnit", false, 1);\r
+\r
+            if (audioUnitIndex != -1)\r
+            {\r
+                s.remove (audioUnitIndex);\r
+                s.insert (0, "AudioUnit");\r
+            }\r
+\r
             for (auto& framework : s)\r
             {\r
                 auto frameworkID = addFramework (framework);\r
@@ -3079,26 +3112,14 @@ private:
         return {};\r
     }\r
 \r
-    String getEntitlementsFileName() const\r
-    {\r
-        return project.getProjectFilenameRootString() + String (".entitlements");\r
-    }\r
-\r
-    StringPairArray getEntitlements() const\r
+    StringPairArray getEntitlements (XcodeTarget& target) const\r
     {\r
         StringPairArray entitlements;\r
 \r
-        if (project.getProjectType().isAudioPlugin())\r
+        if (project.isAudioPluginProject())\r
         {\r
-            if (isiOS())\r
-            {\r
-                if (project.shouldEnableIAA())\r
-                    entitlements.set ("inter-app-audio", "<true/>");\r
-            }\r
-            else\r
-            {\r
-                entitlements.set ("com.apple.security.app-sandbox", "<true/>");\r
-            }\r
+            if (isiOS() && project.shouldEnableIAA())\r
+                entitlements.set ("inter-app-audio", "<true/>");\r
         }\r
         else\r
         {\r
@@ -3125,9 +3146,22 @@ private:
             for (auto& option : getHardenedRuntimeOptions())\r
                 entitlements.set (option, "<true/>");\r
 \r
-        if (isAppSandboxEnabled())\r
-            for (auto& option : getAppSandboxOptions())\r
-                entitlements.set (option, "<true/>");\r
+        if (isAppSandboxEnabled() || (project.isAudioPluginProject() && target.type == XcodeTarget::AudioUnitv3PlugIn))\r
+        {\r
+            entitlements.set ("com.apple.security.app-sandbox", "<true/>");\r
+\r
+            if (isAppSandboxInhertianceEnabled())\r
+            {\r
+                // no other sandbox options can be specified if sandbox inheritance is enabled!\r
+                jassert (getAppSandboxOptions().isEmpty());\r
+\r
+                entitlements.set ("com.apple.security.inherit", "<true/>");\r
+            }\r
+\r
+            if (isAppSandboxEnabled())\r
+                for (auto& option : getAppSandboxOptions())\r
+                    entitlements.set (option, "<true/>");\r
+        }\r
 \r
         if (isiOS() && isiCloudPermissionsEnabled())\r
         {\r
@@ -3150,30 +3184,31 @@ private:
         return entitlements;\r
     }\r
 \r
-    String addEntitlementsFile() const\r
+    void addEntitlementsFile (XcodeTarget& target) const\r
     {\r
-        String content =\r
-            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"\r
-            "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"\r
-            "<plist version=\"1.0\">\n"\r
-            "<dict>\n";\r
-\r
-        auto entitlements = getEntitlements();\r
-        auto keys = entitlements.getAllKeys();\r
+        auto entitlements = getEntitlements (target);\r
 \r
-        for (auto& key : keys)\r
+        if (entitlements.size() > 0)\r
         {\r
-            content += "\t<key>" + key + "</key>\n"\r
-                       "\t" + entitlements[key] + "\n";\r
-        }\r
-        content += "</dict>\n"\r
-                   "</plist>\n";\r
+            String content =\r
+                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"\r
+                "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"\r
+                "<plist version=\"1.0\">\n"\r
+                "<dict>\n";\r
 \r
-        auto entitlementsFile = getTargetFolder().getChildFile (getEntitlementsFileName());\r
-        overwriteFileIfDifferentOrThrow (entitlementsFile, content);\r
+            for (auto& key : entitlements.getAllKeys())\r
+                content += "\t<key>" + key + "</key>\n"\r
+                           "\t" + entitlements[key] + "\n";\r
 \r
-        RelativePath plistPath (entitlementsFile, getTargetFolder(), RelativePath::buildTargetFolder);\r
-        return addFile (plistPath, false, false, false, false, nullptr, {});\r
+            content += "</dict>\n"\r
+                       "</plist>\n";\r
+\r
+            auto entitlementsFile = getTargetFolder().getChildFile (target.getEntitlementsFilename());\r
+            overwriteFileIfDifferentOrThrow (entitlementsFile, content);\r
+\r
+            RelativePath entitlementsPath (entitlementsFile, getTargetFolder(), RelativePath::buildTargetFolder);\r
+            addFile (entitlementsPath, false, false, false, false, nullptr, {});\r
+        }\r
     }\r
 \r
     String addProjectItem (const Project::Item& projectItem) const\r
index c2711ecc9b75d62b667be07bf9e5e7fb45cd7c69..ec3ae4a0ec9d4937e68ba234640d0786a37134ed 100644 (file)
@@ -95,7 +95,7 @@ public:
 \r
             auto projectRootHash = project.getProjectRoot().toXmlString().hashCode();\r
 \r
-            if (project.getProjectType().isAudioPlugin())\r
+            if (project.isAudioPluginProject())\r
             {\r
                 writePluginCharacteristicsFile();\r
 \r
@@ -125,7 +125,7 @@ public:
 \r
             if (errors.size() == 0)\r
             {\r
-                // Workaround for a bug where Xcode thinks the project is invalid if opened immedietely\r
+                // Workaround for a bug where Xcode thinks the project is invalid if opened immediately\r
                 // after writing\r
                 if (waitAfterSaving)\r
                     Thread::sleep (2000);\r
@@ -157,7 +157,7 @@ public:
 \r
         if (errors.size() == 0)\r
         {\r
-            if (project.getProjectType().isAudioPlugin())\r
+            if (project.isAudioPluginProject())\r
                 writePluginCharacteristicsFile();\r
 \r
             writeAppConfigFile (modules, loadUserContentFromAppConfig());\r
@@ -348,7 +348,7 @@ private:
         return longest;\r
     }\r
 \r
-    File getAppConfigFile() const   { return generatedCodeFolder.getChildFile (project.getAppConfigFilename()); }\r
+    File getAppConfigFile() const   { return generatedCodeFolder.getChildFile (Project::getAppConfigFilename()); }\r
 \r
     String loadUserContentFromAppConfig() const\r
     {\r
@@ -525,7 +525,7 @@ private:
         mem.setNewLineString (projectLineFeed);\r
 \r
         writeAppConfig (mem, modules, userContent);\r
-        saveGeneratedFile (project.getAppConfigFilename(), mem);\r
+        saveGeneratedFile (Project::getAppConfigFilename(), mem);\r
     }\r
 \r
     void writeAppHeader (MemoryOutputStream& out, const OwnedArray<LibraryModule>& modules)\r
@@ -542,7 +542,7 @@ private:
         out << "#pragma once" << newLine << newLine;\r
 \r
         if (appConfigFile.exists())\r
-            out << CodeHelpers::createIncludeStatement (project.getAppConfigFilename()) << newLine;\r
+            out << CodeHelpers::createIncludeStatement (Project::getAppConfigFilename()) << newLine;\r
 \r
         if (modules.size() > 0)\r
         {\r
@@ -590,7 +590,7 @@ private:
         mem.setNewLineString (projectLineFeed);\r
 \r
         writeAppHeader (mem, modules);\r
-        saveGeneratedFile (project.getJuceSourceHFilename(), mem);\r
+        saveGeneratedFile (Project::getJuceSourceHFilename(), mem);\r
     }\r
 \r
     void writeModuleCppWrappers (const OwnedArray<LibraryModule>& modules)\r
@@ -606,7 +606,7 @@ private:
 \r
                 mem << "*/" << newLine\r
                     << newLine\r
-                    << "#include " << project.getAppConfigFilename().quoted() << newLine\r
+                    << "#include " << Project::getAppConfigFilename().quoted() << newLine\r
                     << "#include <";\r
 \r
                 if (cu.file.getFileExtension() != ".r")   // .r files are included without the path\r
index 08da017aacd6263cecd06b5079b8b9fb746337ee..74f751e7d9eef194e842cce8b4fdfe67bf4fe210 100644 (file)
@@ -409,12 +409,16 @@ static String getFallbackPathForOS (const Identifier& key, DependencyPathOS os)
     }\r
     else if (key == Ids::androidSDKPath)\r
     {\r
-        return (os == TargetOS::linux ? "${user.home}/Android/Sdk" :\r
-                                        "${user.home}/Library/Android/sdk");\r
+        if      (os == TargetOS::windows)  return "${user.home}\\AppData\\Local\\Android\\Sdk";\r
+        else if (os == TargetOS::osx)      return "${user.home}/Library/Android/sdk";\r
+        else if (os == TargetOS::linux)    return "${user.home}/Android/Sdk";\r
+\r
+        jassertfalse;\r
+        return {};\r
     }\r
     else if (key == Ids::androidNDKPath)\r
     {\r
-        return getFallbackPathForOS (Ids::androidSDKPath, os) + "/ndk-bundle";\r
+        return getFallbackPathForOS (Ids::androidSDKPath, os) + File::getSeparatorChar() + "ndk-bundle";\r
     }\r
     else if (key == Ids::clionExePath)\r
     {\r
index bf7af246f38d91299b6b0afe844f766a4c8b2e4b..18a1a7990b1dd091be668c17e8faa427892d3cf7 100644 (file)
@@ -135,6 +135,11 @@ namespace CodeHelpers
         return "#include \"" + includePath + "\"";\r
     }\r
 \r
+    String createIncludePathIncludeStatement (const String& includedFilename)\r
+    {\r
+        return "#include <" + includedFilename + ">";\r
+    }\r
+\r
     String makeBinaryDataIdentifierName (const File& file)\r
     {\r
         return makeValidIdentifier (file.getFileName()\r
index d348f8367a4c53dbf2f24de5872565d0088467e3..5947e083ec7879a020299523a52cd1cff4f50826 100644 (file)
@@ -34,9 +34,11 @@ namespace CodeHelpers
     String unindent (const String& code, int numSpaces);\r
     String makeValidIdentifier (String s, bool capitalise, bool removeColons,\r
                                 bool allowTemplates, bool allowAsterisks = false);\r
+    String makeBinaryDataIdentifierName (const File& file);\r
+\r
     String createIncludeStatement (const File& includedFile, const File& targetFile);\r
     String createIncludeStatement (const String& includePath);\r
-    String makeBinaryDataIdentifierName (const File& file);\r
+    String createIncludePathIncludeStatement (const String& includedFilename);\r
 \r
     String stringLiteral (const String& text, int maxLineLength = -1);\r
     String floatLiteral (double value, int numDecPlaces);\r
index 5a3ef9cbc35ee2804f96fcedba14670895591c01..54012f3f345a5cbd2b4eb4105cfd832c74aff1a6 100644 (file)
@@ -187,6 +187,7 @@ namespace Ids
     DECLARE_ID (useLocalCopy);\r
     DECLARE_ID (overwriteOnSave);\r
     DECLARE_ID (appSandbox);\r
+    DECLARE_ID (appSandboxInheritance);\r
     DECLARE_ID (appSandboxOptions);\r
     DECLARE_ID (hardenedRuntime);\r
     DECLARE_ID (hardenedRuntimeOptions);\r
diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.cpp b/extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.cpp
new file mode 100644 (file)
index 0000000..63cefab
--- /dev/null
@@ -0,0 +1,115 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2017 - ROLI Ltd.\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   By using JUCE, you agree to the terms of both the JUCE 5 End-User License\r
+   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the\r
+   27th April 2017).\r
+\r
+   End User License Agreement: www.juce.com/juce-5-licence\r
+   Privacy Policy: www.juce.com/juce-5-privacy-policy\r
+\r
+   Or: You may also use this code under the terms of the GPL v3 (see\r
+   www.gnu.org/licenses).\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+#include "../../Application/jucer_Headers.h"\r
+#include "jucer_VersionInfo.h"\r
+\r
+std::unique_ptr<VersionInfo> VersionInfo::fetchFromUpdateServer (const String& versionString)\r
+{\r
+    return fetch ("tags/" + versionString);\r
+}\r
+\r
+std::unique_ptr<VersionInfo> VersionInfo::fetchLatestFromUpdateServer()\r
+{\r
+    return fetch ("latest");\r
+}\r
+\r
+std::unique_ptr<InputStream> VersionInfo::createInputStreamForAsset (const Asset& asset, int& statusCode)\r
+{\r
+    URL downloadUrl (asset.url);\r
+    StringPairArray responseHeaders;\r
+\r
+    return std::unique_ptr<InputStream> (downloadUrl.createInputStream (false, nullptr, nullptr,\r
+                                                                        "Accept: application/octet-stream",\r
+                                                                        0, &responseHeaders, &statusCode, 1));\r
+}\r
+\r
+bool VersionInfo::isNewerVersionThanCurrent()\r
+{\r
+    jassert (versionString.isNotEmpty());\r
+\r
+    auto currentTokens = StringArray::fromTokens (ProjectInfo::versionString, ".", {});\r
+    auto thisTokens    = StringArray::fromTokens (versionString, ".", {});\r
+\r
+    jassert (thisTokens.size() == 3 && thisTokens.size() == 3);\r
+\r
+    if (currentTokens[0].getIntValue() == thisTokens[0].getIntValue())\r
+    {\r
+        if (currentTokens[1].getIntValue() == thisTokens[1].getIntValue())\r
+            return currentTokens[2].getIntValue() < thisTokens[2].getIntValue();\r
+\r
+        return currentTokens[1].getIntValue() < thisTokens[1].getIntValue();\r
+    }\r
+\r
+    return currentTokens[0].getIntValue() < thisTokens[0].getIntValue();\r
+}\r
+\r
+std::unique_ptr<VersionInfo> VersionInfo::fetch (const String& endpoint)\r
+{\r
+    URL latestVersionURL ("https://api.github.com/repos/WeAreROLI/JUCE/releases/" + endpoint);\r
+    std::unique_ptr<InputStream> inStream (latestVersionURL.createInputStream (false));\r
+\r
+    if (inStream == nullptr)\r
+        return nullptr;\r
+\r
+    auto content = inStream->readEntireStreamAsString();\r
+    auto latestReleaseDetails = JSON::parse (content);\r
+\r
+    auto* json = latestReleaseDetails.getDynamicObject();\r
+\r
+    if (json == nullptr)\r
+        return nullptr;\r
+\r
+    auto versionString = json->getProperty ("tag_name").toString();\r
+\r
+    if (versionString.isEmpty())\r
+        return nullptr;\r
+\r
+    auto* assets = json->getProperty ("assets").getArray();\r
+\r
+    if (assets == nullptr)\r
+        return nullptr;\r
+\r
+    auto releaseNotes = json->getProperty ("body").toString();\r
+    std::vector<VersionInfo::Asset> parsedAssets;\r
+\r
+    for (auto& asset : *assets)\r
+    {\r
+        if (auto* assetJson = asset.getDynamicObject())\r
+        {\r
+            parsedAssets.push_back ({ assetJson->getProperty ("name").toString(),\r
+                                      assetJson->getProperty ("url").toString() });\r
+            jassert (parsedAssets.back().name.isNotEmpty());\r
+            jassert (parsedAssets.back().url.isNotEmpty());\r
+        }\r
+        else\r
+        {\r
+            jassertfalse;\r
+        }\r
+    }\r
+\r
+    return std::unique_ptr<VersionInfo> (new VersionInfo ({ versionString, releaseNotes, std::move (parsedAssets) }));\r
+}\r
diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.h b/extras/Projucer/Source/Utility/Helpers/jucer_VersionInfo.h
new file mode 100644 (file)
index 0000000..68ec8e7
--- /dev/null
@@ -0,0 +1,54 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2017 - ROLI Ltd.\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   By using JUCE, you agree to the terms of both the JUCE 5 End-User License\r
+   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the\r
+   27th April 2017).\r
+\r
+   End User License Agreement: www.juce.com/juce-5-licence\r
+   Privacy Policy: www.juce.com/juce-5-privacy-policy\r
+\r
+   Or: You may also use this code under the terms of the GPL v3 (see\r
+   www.gnu.org/licenses).\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+#pragma once\r
+\r
+\r
+//==============================================================================\r
+class VersionInfo\r
+{\r
+public:\r
+    struct Asset\r
+    {\r
+        const String name;\r
+        const String url;\r
+    };\r
+\r
+    static std::unique_ptr<VersionInfo> fetchFromUpdateServer (const String& versionString);\r
+    static std::unique_ptr<VersionInfo> fetchLatestFromUpdateServer();\r
+    static std::unique_ptr<InputStream> createInputStreamForAsset (const Asset& asset, int& statusCode);\r
+\r
+    bool isNewerVersionThanCurrent();\r
+\r
+    const String versionString;\r
+    const String releaseNotes;\r
+    const std::vector<Asset> assets;\r
+\r
+private:\r
+    VersionInfo() = default;\r
+\r
+    static std::unique_ptr<VersionInfo> fetch (const String&);\r
+};\r
index 483ad06dd68f191380ef2aff63a78b07f9f0d22c..6e219fe661df62d154686d7af483f9112c578b43 100644 (file)
@@ -425,10 +425,16 @@ String PIPGenerator::getMainFileTextForType()
 {\r
     String mainTemplate (BinaryData::jucer_PIPMain_cpp);\r
 \r
-    mainTemplate = mainTemplate.replace ("%%filename%%", useLocalCopy ? pipFile.getFileName()\r
-                                                                      : isTemp ? pipFile.getFullPathName()\r
-                                                                               : RelativePath (pipFile, outputDirectory.getChildFile ("Source"),\r
-                                                                                               RelativePath::unknown).toUnixStyle());\r
+    auto includeFilename = [&]\r
+    {\r
+        if (useLocalCopy) return pipFile.getFileName();\r
+        if (isTemp)       return pipFile.getFullPathName();\r
+\r
+        return RelativePath (pipFile, outputDirectory.getChildFile ("Source"), RelativePath::unknown).toUnixStyle();\r
+    }();\r
+\r
+    mainTemplate = mainTemplate.replace ("%%filename%%", includeFilename)\r
+                               .replace ("%%include_juce%%", CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename()));\r
 \r
     auto type = metadata[Ids::type].toString();\r
 \r
index ed558a21c2260c0aaadcf02561588124cef8692a..bda4a63a0a936c8a1bb58d316fdad97a788c50b8 100644 (file)
@@ -39,25 +39,23 @@ class FilePathPropertyComponent    : public PropertyComponent,
 {\r
 public:\r
     FilePathPropertyComponent (Value valueToControl, const String& propertyName, bool isDir, bool thisOS = true,\r
-                               const String& wildcardsToUse = "*", const File& relativeRoot = File(), bool multiPath = false)\r
+                               const String& wildcardsToUse = "*", const File& relativeRoot = File())\r
         : PropertyComponent (propertyName),\r
           text (valueToControl, propertyName, 1024, false),\r
-          isDirectory (isDir), isThisOS (thisOS), supportsMultiplePaths (multiPath), wildcards (wildcardsToUse), root (relativeRoot)\r
+          isDirectory (isDir), isThisOS (thisOS), wildcards (wildcardsToUse), root (relativeRoot)\r
     {\r
         textValue.referTo (valueToControl);\r
-\r
         init();\r
     }\r
 \r
     /** Displays a default value when no value is specified by the user. */\r
     FilePathPropertyComponent (ValueWithDefault& valueToControl, const String& propertyName, bool isDir, bool thisOS = true,\r
-                               const String& wildcardsToUse = "*", const File& relativeRoot = File(), bool multiPath = false)\r
+                               const String& wildcardsToUse = "*", const File& relativeRoot = File())\r
        : PropertyComponent (propertyName),\r
          text (valueToControl, propertyName, 1024, false),\r
-         isDirectory (isDir), isThisOS (thisOS), supportsMultiplePaths (multiPath), wildcards (wildcardsToUse), root (relativeRoot)\r
+         isDirectory (isDir), isThisOS (thisOS), wildcards (wildcardsToUse), root (relativeRoot)\r
     {\r
         textValue = valueToControl.getPropertyAsValue();\r
-\r
         init();\r
     }\r
 \r
@@ -89,15 +87,8 @@ public:
 \r
     void filesDropped (const StringArray& selectedFiles, int, int) override\r
     {\r
-        if (supportsMultiplePaths)\r
-        {\r
-            for (auto& f : selectedFiles)\r
-                setTo (f);\r
-        }\r
-        else\r
-        {\r
-            setTo (selectedFiles[0]);\r
-        }\r
+\r
+        setTo (selectedFiles[0]);\r
 \r
         highlightForDragAndDrop = false;\r
         repaint();\r
@@ -126,11 +117,6 @@ private:
         auto pathName = (root == File()) ? f.getFullPathName()\r
                                          : f.getRelativePathFrom (root);\r
 \r
-        auto currentPath = text.getText();\r
-\r
-        if (supportsMultiplePaths && currentPath.isNotEmpty())\r
-            pathName = currentPath.trimCharactersAtEnd (" ;") + "; " + pathName;\r
-\r
         text.setText (pathName);\r
         updateEditorColour();\r
     }\r
@@ -160,24 +146,24 @@ private:
 \r
     void updateEditorColour()\r
     {\r
-        if (supportsMultiplePaths || ! isThisOS)\r
-            return;\r
-\r
-        text.setColour (TextPropertyComponent::textColourId, findColour (widgetTextColourId));\r
+        if (isThisOS)\r
+        {\r
+            text.setColour (TextPropertyComponent::textColourId, findColour (widgetTextColourId));\r
 \r
-        auto pathToCheck = text.getText();\r
+            auto pathToCheck = text.getText();\r
 \r
-        if (pathToCheck.isNotEmpty())\r
-        {\r
-            pathToCheck.replace ("${user.home}", "~");\r
+            if (pathToCheck.isNotEmpty())\r
+            {\r
+                pathToCheck.replace ("${user.home}", "~");\r
 \r
-           #if JUCE_WINDOWS\r
-            if (pathToCheck.startsWith ("~"))\r
-                pathToCheck = pathToCheck.replace ("~", File::getSpecialLocation (File::userHomeDirectory).getFullPathName());\r
-           #endif\r
+               #if JUCE_WINDOWS\r
+                if (pathToCheck.startsWith ("~"))\r
+                    pathToCheck = pathToCheck.replace ("~", File::getSpecialLocation (File::userHomeDirectory).getFullPathName());\r
+               #endif\r
 \r
-            if (! root.getChildFile (pathToCheck).exists())\r
-                text.setColour (TextPropertyComponent::textColourId, Colours::red);\r
+                if (! root.getChildFile (pathToCheck).exists())\r
+                    text.setColour (TextPropertyComponent::textColourId, Colours::red);\r
+            }\r
         }\r
     }\r
 \r
@@ -200,7 +186,7 @@ private:
     TextPropertyComponent text;\r
     TextButton browseButton { "..." };\r
 \r
-    bool isDirectory, isThisOS, supportsMultiplePaths, highlightForDragAndDrop = false;\r
+    bool isDirectory, isThisOS, highlightForDragAndDrop = false;\r
     String wildcards;\r
     File root;\r
 \r
index 70a84940d7c212f01ff82db8632cf4f81eef75cf..831430036be1bb5d8d5d158f98efdaa89c6255f2 100644 (file)
@@ -170,7 +170,7 @@ public:
     {\r
         auto content = fillInBasicTemplateFields (newFile, parent, templateName)\r
                            .replace ("%%component_class%%", className)\r
-                           .replace ("%%include_juce%%", CodeHelpers::createIncludeStatement (parent.project.getAppIncludeFile(), newFile));\r
+                           .replace ("%%include_juce%%", CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename()));\r
 \r
         content = replaceLineFeeds (content, parent.project.getProjectLineFeed());\r
 \r
index 9df1483705a1f550dd80257d3e223f813f8f3f45..8c83da375968d26044cfe4383ff05e8ee32b2aab 100644 (file)
@@ -54,9 +54,7 @@ public:
         addAndMakeVisible (modulesLabel);\r
         modulesLabel.attachToComponent (&currentPathBox, true);\r
 \r
-        addAndMakeVisible (useGlobalPathsToggle);\r
-        useGlobalPathsToggle.setToggleState (true, sendNotification);\r
-        useGlobalPathsToggle.onClick = [this]\r
+        auto updateEnablement = [this]\r
         {\r
             isUsingGlobalPaths = useGlobalPathsToggle.getToggleState();\r
 \r
@@ -64,6 +62,12 @@ public:
             openFolderButton.setEnabled (! isUsingGlobalPaths);\r
             modulesLabel.setEnabled     (! isUsingGlobalPaths);\r
         };\r
+\r
+        addAndMakeVisible (useGlobalPathsToggle);\r
+        useGlobalPathsToggle.setToggleState (true, sendNotification);\r
+        useGlobalPathsToggle.onClick = [updateEnablement] { updateEnablement(); };\r
+\r
+        updateEnablement();\r
     }\r
 \r
     void resized() override\r
@@ -419,7 +423,10 @@ public:
                     return;\r
 \r
                 if (modulesPathBox.isUsingGlobalPaths)\r
+                {\r
                     getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).setValue (wizard->modulesFolder.getFullPathName(), nullptr);\r
+                    ProjucerApplication::getApp().rescanJUCEPathModules();\r
+                }\r
             }\r
 \r
             auto projectDir = fileBrowser.getSelectedFile (0);\r
@@ -429,7 +436,7 @@ public:
 \r
             if (project != nullptr)\r
             {\r
-                mw->setProject (project.release());\r
+                mw->setProject (std::move (project));\r
                 getAppSettings().lastWizardFolder = projectDir.getParentDirectory();\r
             }\r
         }\r
index 6988b26bafd531e4718329750f4b3fbd54868e95..5dbd0d388affed5fc9a5c64ae120ce50be2307b4 100644 (file)
@@ -71,14 +71,13 @@ struct AnimatedAppWizard   : public NewProjectWizard
 \r
         setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));\r
 \r
-        String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));\r
+        auto juceHeaderInclude = CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename());\r
+        auto appHeaders = juceHeaderInclude + newLine + CodeHelpers::createIncludeStatement (contentCompH, mainCppFile);\r
 \r
         // create main window\r
-        appHeaders << newLine << CodeHelpers::createIncludeStatement (contentCompH, mainCppFile);\r
-\r
         String windowH = project.getFileTemplate (createCppFile ? "jucer_AnimatedComponentTemplate_h"\r
                                                                 : "jucer_AnimatedComponentSimpleTemplate_h")\r
-                            .replace ("%%include_juce%%", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompH), false)\r
+                            .replace ("%%include_juce%%", juceHeaderInclude)\r
                             .replace ("%%content_component_class%%", contentCompName, false);\r
 \r
         if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompH, windowH))\r
@@ -89,7 +88,7 @@ struct AnimatedAppWizard   : public NewProjectWizard
         if (createCppFile)\r
         {\r
             String windowCpp = project.getFileTemplate ("jucer_AnimatedComponentTemplate_cpp")\r
-                                  .replace ("%%include_juce%%", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompCpp), false)\r
+                                  .replace ("%%include_juce%%", juceHeaderInclude)\r
                                   .replace ("%%include_corresponding_header%%", CodeHelpers::createIncludeStatement (contentCompH, contentCompCpp), false)\r
                                   .replace ("%%content_component_class%%", contentCompName, false);\r
 \r
index 80aa745f1d70c924aedc96f36eb17ea48b01e1d3..45eed35783a3e7856d2431c479f129a35892ddbc 100644 (file)
@@ -71,14 +71,13 @@ struct AudioAppWizard   : public NewProjectWizard
 \r
         setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));\r
 \r
-        String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));\r
+        auto juceHeaderInclude = CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename());\r
+        auto appHeaders = juceHeaderInclude + newLine + CodeHelpers::createIncludeStatement (contentCompH, mainCppFile);\r
 \r
         // create main window\r
-        appHeaders << newLine << CodeHelpers::createIncludeStatement (contentCompH, mainCppFile);\r
-\r
         String windowH = project.getFileTemplate (createCppFile ? "jucer_AudioComponentTemplate_h"\r
                                                                 : "jucer_AudioComponentSimpleTemplate_h")\r
-                            .replace ("%%include_juce%%", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompH), false)\r
+                            .replace ("%%include_juce%%", juceHeaderInclude)\r
                             .replace ("%%content_component_class%%", contentCompName, false);\r
 \r
         if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompH, windowH))\r
@@ -89,7 +88,7 @@ struct AudioAppWizard   : public NewProjectWizard
         if (createCppFile)\r
         {\r
             String windowCpp = project.getFileTemplate ("jucer_AudioComponentTemplate_cpp")\r
-                                  .replace ("%%include_juce%%", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompCpp), false)\r
+                                  .replace ("%%include_juce%%", juceHeaderInclude)\r
                                   .replace ("%%include_corresponding_header%%", CodeHelpers::createIncludeStatement (contentCompH, contentCompCpp), false)\r
                                   .replace ("%%content_component_class%%", contentCompName, false);\r
 \r
index b81d28744c1f0e4a7e00d0d7e958d1e395b17aa8..767efd83ad737a125a09c7b38e309987ca168c3f 100644 (file)
@@ -62,7 +62,7 @@ struct AudioPluginAppWizard   : public NewProjectWizard
 \r
         setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));\r
 \r
-        String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), filterCppFile));\r
+        auto juceHeaderInclude = CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename());\r
 \r
         String filterCpp = project.getFileTemplate ("jucer_AudioPluginFilterTemplate_cpp")\r
                             .replace ("%%filter_headers%%", CodeHelpers::createIncludeStatement (filterHFile, filterCppFile)\r
@@ -71,7 +71,7 @@ struct AudioPluginAppWizard   : public NewProjectWizard
                             .replace ("%%editor_class_name%%", editorClassName, false);\r
 \r
         String filterH = project.getFileTemplate ("jucer_AudioPluginFilterTemplate_h")\r
-                            .replace ("%%app_headers%%", appHeaders, false)\r
+                            .replace ("%%app_headers%%", juceHeaderInclude, false)\r
                             .replace ("%%filter_class_name%%", filterClassName, false);\r
 \r
         String editorCpp = project.getFileTemplate ("jucer_AudioPluginEditorTemplate_cpp")\r
@@ -81,7 +81,7 @@ struct AudioPluginAppWizard   : public NewProjectWizard
                             .replace ("%%editor_class_name%%", editorClassName, false);\r
 \r
         String editorH = project.getFileTemplate ("jucer_AudioPluginEditorTemplate_h")\r
-                            .replace ("%%editor_headers%%", appHeaders + newLine + CodeHelpers::createIncludeStatement (filterHFile, filterCppFile), false)\r
+                            .replace ("%%editor_headers%%", juceHeaderInclude + newLine + CodeHelpers::createIncludeStatement (filterHFile, filterCppFile), false)\r
                             .replace ("%%filter_class_name%%", filterClassName, false)\r
                             .replace ("%%editor_class_name%%", editorClassName, false);\r
 \r
index 277bd8b0819cf3018478b9122eb520d91c63d4fc..3aba175c8baeca51761263b8af1e110fceaec51a 100644 (file)
@@ -69,10 +69,9 @@ struct ConsoleAppWizard   : public NewProjectWizard
         if (createMainCpp)\r
         {\r
             File mainCppFile = getSourceFilesFolder().getChildFile ("Main.cpp");\r
-            String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));\r
 \r
             String mainCpp = project.getFileTemplate ("jucer_MainConsoleAppTemplate_cpp")\r
-                                .replace ("%%app_headers%%", appHeaders, false);\r
+                                .replace ("%%app_headers%%", CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename()), false);\r
 \r
             if (! FileHelpers::overwriteFileWithNewDataIfDifferent (mainCppFile, mainCpp))\r
                 failedFiles.add (mainCppFile.getFullPathName());\r
index 2f39be9a4ce3fc3fd71bdb6c016de9798f6c5d9b..710ae57627f9e421c1512e3a89456e7d09c465e9 100644 (file)
@@ -75,7 +75,8 @@ struct GUIAppWizard   : public NewProjectWizard
 \r
         setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));\r
 \r
-        String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));\r
+        auto juceHeaderInclude = CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename());\r
+        auto appHeaders = juceHeaderInclude;\r
 \r
         if (createWindow)\r
         {\r
@@ -83,7 +84,7 @@ struct GUIAppWizard   : public NewProjectWizard
 \r
             String windowH = project.getFileTemplate (createCppFile ? "jucer_ContentCompTemplate_h"\r
                                                                     : "jucer_ContentCompSimpleTemplate_h")\r
-                                .replace ("%%include_juce%%", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompH), false)\r
+                                .replace ("%%include_juce%%", juceHeaderInclude)\r
                                 .replace ("%%content_component_class%%", contentCompName, false);\r
 \r
             if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompH, windowH))\r
@@ -94,7 +95,7 @@ struct GUIAppWizard   : public NewProjectWizard
             if (createCppFile)\r
             {\r
                 String windowCpp = project.getFileTemplate ("jucer_ContentCompTemplate_cpp")\r
-                                    .replace ("%%include_juce%%", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompCpp), false)\r
+                                    .replace ("%%include_juce%%", juceHeaderInclude)\r
                                     .replace ("%%include_corresponding_header%%", CodeHelpers::createIncludeStatement (contentCompH, contentCompCpp), false)\r
                                     .replace ("%%content_component_class%%", contentCompName, false);\r
 \r
index 44dee4c0faed52efbbe7e5b7441e414d151ade6e..29b092b2231f6c0255e2aa89b9629274a2799788 100644 (file)
@@ -71,14 +71,13 @@ struct OpenGLAppWizard   : public NewProjectWizard
 \r
         setExecutableNameForAllTargets (project, File::createLegalFileName (appTitle));\r
 \r
-        String appHeaders (CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), mainCppFile));\r
+        auto juceHeaderInclude = CodeHelpers::createIncludePathIncludeStatement (Project::getJuceSourceHFilename());\r
+        auto appHeaders = juceHeaderInclude + newLine + CodeHelpers::createIncludeStatement (contentCompH, mainCppFile);\r
 \r
         // create main window\r
-        appHeaders << newLine << CodeHelpers::createIncludeStatement (contentCompH, mainCppFile);\r
-\r
         String windowH = project.getFileTemplate (createCppFile ? "jucer_OpenGLComponentTemplate_h"\r
                                                                 : "jucer_OpenGLComponentSimpleTemplate_h")\r
-                            .replace ("%%include_juce%%", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompH), false)\r
+                            .replace ("%%include_juce%%", juceHeaderInclude)\r
                             .replace ("%%content_component_class%%", contentCompName, false);\r
 \r
         if (! FileHelpers::overwriteFileWithNewDataIfDifferent (contentCompH, windowH))\r
@@ -89,7 +88,7 @@ struct OpenGLAppWizard   : public NewProjectWizard
         if (createCppFile)\r
         {\r
             String windowCpp = project.getFileTemplate ("jucer_OpenGLComponentTemplate_cpp")\r
-                                  .replace ("%%include_juce%%", CodeHelpers::createIncludeStatement (project.getAppIncludeFile(), contentCompCpp), false)\r
+                                  .replace ("%%include_juce%%", juceHeaderInclude)\r
                                   .replace ("%%include_corresponding_header%%", CodeHelpers::createIncludeStatement (contentCompH, contentCompCpp), false)\r
                                   .replace ("%%content_component_class%%", contentCompName, false);\r
 \r
diff --git a/extras/UnitTestRunner/Builds/MacOSX/ConsoleApp.entitlements b/extras/UnitTestRunner/Builds/MacOSX/ConsoleApp.entitlements
new file mode 100644 (file)
index 0000000..6631ffa
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+</dict>
+</plist>
diff --git a/extras/UnitTestRunner/Builds/MacOSX/UnitTestRunner.entitlements b/extras/UnitTestRunner/Builds/MacOSX/UnitTestRunner.entitlements
deleted file mode 100644 (file)
index 6631ffa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-</dict>
-</plist>
index 02ced2bb59bdc286b6106ac0760a7d322163bd5b..5ac149dc10cb2306dff3291e570a6e2195aa161a 100644 (file)
                        path = System/Library/Frameworks/CoreMedia.framework;
                        sourceTree = SDKROOT;
                };
-               911BC81C9C4E07C2E2FD68C1 = {
-                       isa = PBXFileReference;
-                       lastKnownFileType = text.plist.xml;
-                       name = UnitTestRunner.entitlements;
-                       path = UnitTestRunner.entitlements;
-                       sourceTree = "SOURCE_ROOT";
-               };
                9514F6D920549F8A44B2E332 = {
                        isa = PBXFileReference;
                        lastKnownFileType = file;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "UnitTestRunner";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                PRODUCT_NAME = "UnitTestRunner";
+                               SDKROOT = macosx;
                                WARNING_CFLAGS = "-Wreorder";
                                ZERO_LINK = NO;
                        };
index b6d6721d0625c0c3e55dacf5aaa8644d18b23e19..a6ada508116ae2270f777477f82636665f2535e8 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 40c5b96d75a566d11db5dda89245a6370dcb8d00..e7fc4f99361c6e1dd1e291949aa43f0997d8b9a1 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index 8fda398210cf952afe070cb82a48576eb7be59d5..9da5d1f4e3816815cce0a80f52dfb00382e4c652 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 473a89cd408af41206af11c1a0ca7f40e5fc452c..968333e781233c1f5cd65341ae1a85d37b5e386c 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index e270488f1b4538d44ef60687064c54090a794edd..87396c71b8e78257529344cd485bcf2a0ac79030 100644 (file)
@@ -47,7 +47,7 @@
 \r
 #define JUCE_USE_DARK_SPLASH_SCREEN 1\r
 \r
-#define JUCE_PROJUCER_VERSION 0x50405\r
+#define JUCE_PROJUCER_VERSION 0x50406\r
 \r
 //==============================================================================\r
 #define JUCE_MODULE_AVAILABLE_juce_analytics              1\r
 //==============================================================================\r
 // juce_events flags:\r
 \r
-#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK\r
- //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 0\r
+#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK\r
+ //#define JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 0\r
 #endif\r
 \r
 //==============================================================================\r
index 47ebd68281bbfbad339eb9d127ff3bc2dd540a68..3c9a56ad44304f52d68815c1c95907e8bacf52cc 100644 (file)
@@ -24,7 +24,7 @@
   ==============================================================================\r
 */\r
 \r
-#include "../JuceLibraryCode/JuceHeader.h"\r
+#include <JuceHeader.h>\r
 \r
 //==============================================================================\r
 class ConsoleLogger : public Logger\r
index 6cbcabaa9662ce02eaf2e5a1ec2593e493ebc69f..d0f8dcb2882ec5b2fe6f1d96d2f423e576a76eaf 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 \r
 <JUCERPROJECT id="Z2Xzcp" name="UnitTestRunner" projectType="consoleapp" bundleIdentifier="com.roli.UnitTestRunner"\r
-              jucerVersion="5.4.5" defines="JUCE_UNIT_TESTS=1" displaySplashScreen="0"\r
+              jucerVersion="5.4.6" defines="JUCE_UNIT_TESTS=1" displaySplashScreen="0"\r
               reportAppUsage="0" companyName="ROLI Ltd." companyCopyright="ROLI Ltd.">\r
   <MAINGROUP id="GZdWCU" name="UnitTestRunner">\r
     <GROUP id="{22894462-E1A9-036F-ED94-B51A50C87552}" name="Source">\r
index 7ffe29c8dff94fb93f2c93ad9d9503f0c639ab5a..4474794535d88673050b9b3f57e57bb66cd61e0b 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <ExcludedFromBuild>true</ExcludedFromBuild>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_ConsoleApplication.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Result.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_WindowsRegistry.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_android_JNIHelpers.h"/>\r
index 651289cb74aadeafcef0ccc8556bfab6735e4c0a..b521de4defd6c9587a86fdac1c6e997c076700c8 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.cpp">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.cpp">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_TimeSliceThread.cpp">\r
       <Filter>JUCE Modules\juce_core\threads</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_core\threads\juce_WaitableEvent.cpp">\r
+      <Filter>JUCE Modules\juce_core\threads</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_core\time\juce_PerformanceCounter.cpp">\r
       <Filter>JUCE Modules\juce_core\time</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_RuntimePermissions.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_StdFunctionCompat.h">\r
-      <Filter>JUCE Modules\juce_core\misc</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\misc\juce_Uuid.h">\r
       <Filter>JUCE Modules\juce_core\misc</Filter>\r
     </ClInclude>\r
index 146de870e6bedabc707e5f9c0a6a11660e34504c..5a607cdb337cae64c4809008f81c9a8a45432169 100644 (file)
@@ -47,7 +47,7 @@
 \r
 #define JUCE_USE_DARK_SPLASH_SCREEN 1\r
 \r
-#define JUCE_PROJUCER_VERSION 0x50405\r
+#define JUCE_PROJUCER_VERSION 0x50406\r
 \r
 //==============================================================================\r
 #define JUCE_MODULE_AVAILABLE_juce_audio_basics          1\r
 //==============================================================================\r
 // juce_events flags:\r
 \r
-#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK\r
- //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 0\r
+#ifndef    JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK\r
+ //#define JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 0\r
 #endif\r
 \r
 //==============================================================================\r
index d713ca99bc3ed30dda968b2216ad0ab4f1f8eb6e..6eda8d9fc0d7c478a9f55a69959d27ab4f96a03f 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 \r
 <JUCERPROJECT id="IvabE4" name="WindowsDLL" projectType="library" juceLinkage="none"\r
-              bundleIdentifier="com.roli.jucedll" jucerVersion="5.4.5" defines="JUCE_DLL_BUILD=1"\r
+              bundleIdentifier="com.roli.jucedll" jucerVersion="5.4.6" defines="JUCE_DLL_BUILD=1"\r
               displaySplashScreen="0" reportAppUsage="0" companyName="ROLI Ltd."\r
               companyCopyright="ROLI Ltd.">\r
   <EXPORTFORMATS>\r
index 8b005bbac5ff000dacb9ea754661690b116daf61..a385c6ad3c21d8421917f0ef5ab69cd803c46944 100644 (file)
@@ -42,7 +42,7 @@ public:
     //==============================================================================\r
     /**\r
         Creating one of these automatically sends analytics events to the Analytics\r
-        singeton when the corresponding button is clicked.\r
+        singleton when the corresponding button is clicked.\r
 \r
         The name and parameters of the analytics event will be populated from the\r
         variables supplied here. If clicking changes the button's state then the\r
index 0bf9255ed6e69cc3885607bca463f657676ac648..aef59e71acaf6bb9f5d609986a7b4ddb9890cf46 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_analytics\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE analytics classes\r
-  description:      Classes to collect analytics and send to destinations\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
+  ID:                 juce_analytics\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE analytics classes\r
+  description:        Classes to collect analytics and send to destinations\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
 \r
-  dependencies:     juce_gui_basics\r
+  dependencies:       juce_gui_basics\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 53a3377cb108e5a600df08ec063d4f23e7bf0a1d..8cf5970686d5464a7ba41af4c30298617c384298 100644 (file)
@@ -31,6 +31,8 @@ namespace juce
 /**\r
     Maintains an ongoing measurement of the proportion of time which is being\r
     spent inside an audio callback.\r
+\r
+    @tags{Audio}\r
 */\r
 class JUCE_API  AudioProcessLoadMeasurer\r
 {\r
@@ -68,6 +70,8 @@ public:
             myCallback->doTheCallback();\r
         }\r
         @endcode\r
+\r
+        @tags{Audio}\r
     */\r
     struct JUCE_API  ScopedTimer\r
     {\r
index 5e68694af5b62f7e3dd48dc1e190ec0b636ed2b5..f4ab1df073eb641d38c9a5e6661ee27bb34b82b9 100644 (file)
@@ -116,7 +116,7 @@ public:
     /** Copies another buffer.\r
 \r
         This buffer will make its own copy of the other's data, unless the buffer was created\r
-        using an external data buffer, in which case boths buffers will just point to the same\r
+        using an external data buffer, in which case both buffers will just point to the same\r
         shared block of data.\r
     */\r
     AudioBuffer (const AudioBuffer& other)\r
@@ -1075,8 +1075,17 @@ private:
 \r
     void allocateData()\r
     {\r
+        static_assert (std::alignment_of<Type>::value <= std::alignment_of<std::max_align_t>::value,\r
+                       "AudioBuffer cannot hold types with alignment requirements larger than that guaranteed by malloc");\r
         jassert (size >= 0);\r
+\r
         auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*);\r
+        auto requiredSampleAlignment = std::alignment_of<Type>::value;\r
+        size_t alignmentOverflow = channelListSize % requiredSampleAlignment;\r
+\r
+        if (alignmentOverflow != 0)\r
+            channelListSize += requiredSampleAlignment - alignmentOverflow;\r
+\r
         allocatedBytes = (size_t) numChannels * (size_t) size * sizeof (Type) + channelListSize + 32;\r
         allocatedData.malloc (allocatedBytes);\r
         channels = reinterpret_cast<Type**> (allocatedData.get());\r
index 83a108310e0787a045bb249c1abd19dc14c3a425..53556a41adf232fc70ee9f341cfeb4538387fae5 100644 (file)
@@ -20,6 +20,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_audio_basics\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE audio and MIDI data classes\r
-  description:      Classes for audio buffer manipulation, midi message handling, synthesis, etc.\r
-  website:          http://www.juce.com/juce\r
-  license:          ISC\r
-\r
-  dependencies:     juce_core\r
-  OSXFrameworks:    Accelerate\r
-  iOSFrameworks:    Accelerate\r
+  ID:                 juce_audio_basics\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE audio and MIDI data classes\r
+  description:        Classes for audio buffer manipulation, midi message handling, synthesis, etc.\r
+  website:            http://www.juce.com/juce\r
+  license:            ISC\r
+\r
+  dependencies:       juce_core\r
+  OSXFrameworks:      Accelerate\r
+  iOSFrameworks:      Accelerate\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 5b20bc570edd3c263f8697043d0671d03977de5b..47aaf6923c62f50fa17044ffd5ad01d29205ffdc 100644 (file)
@@ -73,7 +73,7 @@ public:
     Represents a piano keyboard, keeping track of which keys are currently pressed.\r
 \r
     This object can parse a stream of midi events, using them to update its idea\r
-    of which keys are pressed for each individiual midi channel.\r
+    of which keys are pressed for each individual midi channel.\r
 \r
     When keys go up or down, it can broadcast these events to listener objects.\r
 \r
@@ -135,7 +135,7 @@ public:
         It will also trigger a synchronous callback to the listeners to tell them that the key has\r
         gone up.\r
 \r
-        But if the note isn't acutally down for the given channel, this method will in fact do nothing.\r
+        But if the note isn't actually down for the given channel, this method will in fact do nothing.\r
     */\r
     void noteOff (int midiChannel, int midiNoteNumber, float velocity);\r
 \r
index f58fd788af79bcd0068baa6db27ad17288697134..d74aa583dd56e6fab9b47450a4b039f42365c4ba 100644 (file)
@@ -378,7 +378,7 @@ struct MidiMessageSequenceTest  : public UnitTest
         expectEquals (s.getIndexOfMatchingKeyUp (0), 2);\r
         expectEquals (s.getIndexOfMatchingKeyUp (1), 3);\r
 \r
-        beginTest ("Time & indeces");\r
+        beginTest ("Time & indices");\r
         expectEquals (s.getNextIndexAtTime (0.5), 1);\r
         expectEquals (s.getNextIndexAtTime (2.5), 2);\r
         expectEquals (s.getNextIndexAtTime (9.0), 4);\r
index 94ffc731e322579bd72fc9d5b4044f6a3dd92056..869afac782ad38662fc7ddbc5ff0ae172b72e2c5 100644 (file)
@@ -142,7 +142,7 @@ public:
 \r
         @param use14BitValue     If true (default), the value will have 14-bit precision\r
                                  (two MIDI bytes). If false, instead the value will have\r
-                                 7-bit presision (a single MIDI byte).\r
+                                 7-bit precision (a single MIDI byte).\r
     */\r
     static MidiBuffer generate (int channel,\r
                                 int parameterNumber,\r
index 1f0b132da70efd214c955f80d4d271af39acdc23..91a0b2b3dcd9a2fa709bcad0e4fa899577f148c7 100644 (file)
@@ -27,7 +27,7 @@ namespace juce
 /**\r
     This class represents an instrument handling MPE.\r
 \r
-    It has an MPE zone layout and maintans a state of currently\r
+    It has an MPE zone layout and maintains a state of currently\r
     active (playing) notes and the values of their dimensions of expression.\r
 \r
     You can trigger and modulate notes:\r
index a6e31e854d647d98ebd0b4f74fb6fef57dbbd810..1275dacd395198c66e88b552e57957d913ed005f 100644 (file)
@@ -99,7 +99,7 @@ public:
 \r
     /** Returns the sequence of MIDI messages that, if sent to an Expressive\r
         MIDI device, will reset the whole MPE zone layout of the\r
-        device to the laoyut passed in. This will first clear the current lower and upper\r
+        device to the layout passed in. This will first clear the current lower and upper\r
         zones, then then set the zones contained in the passed-in zone layout, and set their\r
         per-note and master pitchbend ranges to their current values.\r
     */\r
index 587ce4df5dd483e3de0909433fc9ec8f429fa183..8a999d66e8313be5c1629080455c3895299a037a 100644 (file)
@@ -247,7 +247,7 @@ protected:
                              int numSamples) override;\r
 \r
     /** This will simply call renderNextBlock for each currently active\r
-        voice and fill the buffer with the sum. (souble-precision version)\r
+        voice and fill the buffer with the sum. (double-precision version)\r
         Override this method if you need to do more work to render your audio.\r
     */\r
     void renderNextSubBlock (AudioBuffer<double>& outputAudio,\r
index b8d973c20a0f4744c83e3b2aa4235169186d2d03..8ebc185b70d99ab0262bb556b1f165cfb5edf3a8 100644 (file)
@@ -49,7 +49,7 @@ MPEChannelAssigner::MPEChannelAssigner (Range<int> channelRange)
 \r
 int MPEChannelAssigner::findMidiChannelForNewNote (int noteNumber) noexcept\r
 {\r
-    if (numChannels == 1)\r
+    if (numChannels <= 1)\r
         return firstChannel;\r
 \r
     for (auto ch = firstChannel; (isLegacy || zone->isLowerZone() ? ch <= lastChannel : ch >= lastChannel); ch += channelIncrement)\r
index 3b48ee06607b61871f741ae0a3d25614e4915bc3..401c4f772ed9723a2a7a08a946d58ab4b846a79b 100644 (file)
@@ -122,7 +122,7 @@ public:
 \r
         An AudioSource has two states: prepared and unprepared.\r
 \r
-        The prepareToPlay() method is guaranteed to be called at least once on an 'unpreprared'\r
+        The prepareToPlay() method is guaranteed to be called at least once on an 'unprepared'\r
         source to put it into a 'prepared' state before any calls will be made to getNextAudioBlock().\r
         This callback allows the source to initialise any resources it might need when playing.\r
 \r
index 6de3e8dae1347f513d01db5cd5f1e2e51512e61a..8f50ceefdad15934f577c7d94f1de4d2e49cbdea 100644 (file)
@@ -30,6 +30,8 @@ namespace juce
     To use it, call setSampleRate() with the current sample rate and give it some parameters\r
     with setParameters() then call getNextSample() to get the envelope value to be applied\r
     to each audio sample or applyEnvelopeToBuffer() to apply the envelope to a whole buffer.\r
+\r
+    @tags{Audio}\r
 */\r
 class ADSR\r
 {\r
@@ -42,7 +44,11 @@ public:
     }\r
 \r
     //==============================================================================\r
-    /** Holds the parameters being used by an ADSR object. */\r
+    /**\r
+        Holds the parameters being used by an ADSR object.\r
+\r
+        @tags{Audio}\r
+    */\r
     struct Parameters\r
     {\r
         /** Attack time in seconds. */\r
@@ -102,12 +108,6 @@ public:
     {\r
         envelopeVal = 0.0f;\r
         currentState = State::idle;\r
-\r
-        if (resetReleaseRate)\r
-        {\r
-            releaseRate = static_cast<float> (sustainLevel / (currentParameters.release * sr));\r
-            resetReleaseRate = false;\r
-        }\r
     }\r
 \r
     /** Starts the attack phase of the envelope. */\r
@@ -133,14 +133,9 @@ public:
     {\r
         if (currentState != State::idle)\r
         {\r
-            if (releaseRate > 0.0f)\r
+            if (currentParameters.release > 0.0f)\r
             {\r
-                if (currentState != State::sustain)\r
-                {\r
-                    releaseRate = static_cast<float> (envelopeVal / (currentParameters.release * sr));\r
-                    resetReleaseRate = true;\r
-                }\r
-\r
+                releaseRate = static_cast<float> (envelopeVal / (currentParameters.release * sr));\r
                 currentState = State::release;\r
             }\r
             else\r
@@ -231,7 +226,6 @@ private:
 \r
         attackRate  = (parameters.attack  > 0.0f ? static_cast<float> (1.0f                  / (parameters.attack * sr))  : -1.0f);\r
         decayRate   = (parameters.decay   > 0.0f ? static_cast<float> ((1.0f - sustainLevel) / (parameters.decay * sr))   : -1.0f);\r
-        releaseRate = (parameters.release > 0.0f ? static_cast<float> (sustainLevel          / (parameters.release * sr)) : -1.0f);\r
     }\r
 \r
     void checkCurrentState()\r
@@ -249,7 +243,6 @@ private:
 \r
     double sr = 0.0;\r
     float envelopeVal = 0.0f, sustainLevel = 0.0f, attackRate = 0.0f, decayRate = 0.0f, releaseRate = 0.0f;\r
-    bool resetReleaseRate = false;\r
 };\r
 \r
 } // namespace juce\r
index ac6073e3d8f139d3132326c8e3602cefe1ec4ea9..a472fb00c2ae745353096465b3f6027131698b46 100644 (file)
@@ -179,10 +179,18 @@ protected:
 */\r
 namespace ValueSmoothingTypes\r
 {\r
-    /** Used to indicate a linear smoothing between values. */\r
+    /**\r
+        Used to indicate a linear smoothing between values.\r
+\r
+        @tags{Audio}\r
+    */\r
     struct Linear {};\r
 \r
-    /** Used to indicate a smoothing between multiplicative values. */\r
+    /**\r
+        Used to indicate a smoothing between multiplicative values.\r
+\r
+        @tags{Audio}\r
+    */\r
     struct Multiplicative {};\r
 }\r
 \r
index a26a3bf49cc00a6363d8fab5222d92882c107f01..7c8625c567a21abe0d3a3bd77e9dd3f50c86d36b 100644 (file)
@@ -105,7 +105,7 @@ void AudioDeviceManager::createDeviceTypesIfNeeded()
         createAudioDeviceTypes (types);\r
 \r
         for (auto* t : types)\r
-            addAudioDeviceType (t);\r
+            addAudioDeviceType (std::unique_ptr<AudioIODeviceType> (t));\r
 \r
         types.clear (false);\r
 \r
@@ -172,23 +172,40 @@ void AudioDeviceManager::createAudioDeviceTypes (OwnedArray<AudioIODeviceType>&
     addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ASIO());\r
     addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_CoreAudio());\r
     addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_iOSAudio());\r
+    addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Bela());\r
     addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ALSA());\r
     addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_JACK());\r
-    addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Bela());\r
     addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Oboe());\r
     addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_OpenSLES());\r
     addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Android());\r
 }\r
 \r
-void AudioDeviceManager::addAudioDeviceType (AudioIODeviceType* newDeviceType)\r
+void AudioDeviceManager::addAudioDeviceType (std::unique_ptr<AudioIODeviceType> newDeviceType)\r
 {\r
     if (newDeviceType != nullptr)\r
     {\r
         jassert (lastDeviceTypeConfigs.size() == availableDeviceTypes.size());\r
-        availableDeviceTypes.add (newDeviceType);\r
+\r
+        availableDeviceTypes.add (newDeviceType.release());\r
         lastDeviceTypeConfigs.add (new AudioDeviceSetup());\r
 \r
-        newDeviceType->addListener (callbackHandler.get());\r
+        availableDeviceTypes.getLast()->addListener (callbackHandler.get());\r
+    }\r
+}\r
+\r
+void AudioDeviceManager::removeAudioDeviceType (AudioIODeviceType* deviceTypeToRemove)\r
+{\r
+    if (deviceTypeToRemove != nullptr)\r
+    {\r
+        jassert (lastDeviceTypeConfigs.size() == availableDeviceTypes.size());\r
+\r
+        auto index = availableDeviceTypes.indexOf (deviceTypeToRemove);\r
+\r
+        if (auto removed = std::unique_ptr<AudioIODeviceType> (availableDeviceTypes.removeAndReturn (index)))\r
+        {\r
+            removed->removeListener (callbackHandler.get());\r
+            lastDeviceTypeConfigs.remove (index, true);\r
+        }\r
     }\r
 }\r
 \r
index 83b49c1e519f3b2e75429025652f4986279ca40a..b855d51e46bc428e0e8efe149a634f1265ac12a6 100644 (file)
@@ -391,10 +391,11 @@ public:
     */\r
     virtual void createAudioDeviceTypes (OwnedArray<AudioIODeviceType>& types);\r
 \r
-    /** Adds a new device type to the list of types.\r
-        The manager will take ownership of the object that is passed-in.\r
-    */\r
-    void addAudioDeviceType (AudioIODeviceType* newDeviceType);\r
+    /** Adds a new device type to the list of types. */\r
+    void addAudioDeviceType (std::unique_ptr<AudioIODeviceType> newDeviceType);\r
+\r
+    /** Removes a previously added device type from the manager. */\r
+    void removeAudioDeviceType (AudioIODeviceType* deviceTypeToRemove);\r
 \r
     //==============================================================================\r
     /** Plays a beep through the current audio device.\r
index 20a2c5f6480afd182e58d3b707ff91206e0813cd..c39ab0f55f1a7785031a4fbf25caae62804e9d23 100644 (file)
@@ -20,6 +20,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_audio_devices\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE audio and MIDI I/O device classes\r
-  description:      Classes to play and record from audio and MIDI I/O devices\r
-  website:          http://www.juce.com/juce\r
-  license:          ISC\r
+  ID:                 juce_audio_devices\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE audio and MIDI I/O device classes\r
+  description:        Classes to play and record from audio and MIDI I/O devices\r
+  website:            http://www.juce.com/juce\r
+  license:            ISC\r
 \r
-  dependencies:     juce_audio_basics, juce_events\r
-  OSXFrameworks:    CoreAudio CoreMIDI AudioToolbox\r
-  iOSFrameworks:    CoreAudio CoreMIDI AudioToolbox AVFoundation\r
-  linuxPackages:    alsa\r
-  mingwLibs:        winmm\r
+  dependencies:       juce_audio_basics, juce_events\r
+  OSXFrameworks:      CoreAudio CoreMIDI AudioToolbox\r
+  iOSFrameworks:      CoreAudio CoreMIDI AudioToolbox AVFoundation\r
+  linuxPackages:      alsa\r
+  mingwLibs:          winmm\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
@@ -63,7 +64,7 @@
     Enables the use of the Windows Runtime API for MIDI, allowing connections\r
     to Bluetooth Low Energy devices on Windows 10 version 1809 (October 2018\r
     Update) and later. If you enable this flag then older, unsupported,\r
-    versions of Windows will automatically fall back to using the regualar\r
+    versions of Windows will automatically fall back to using the regular\r
     Win32 MIDI API.\r
 \r
     You will need version 10.0.14393.0 of the Windows Standalone SDK to compile\r
index eb9d7eaf88c4d9b07230f6344e1fe3b67106726b..054a376ab0b2e5f379c9c7ee4a1a23da21f9e7ac 100644 (file)
@@ -30,6 +30,8 @@ namespace juce
     getDefaultDevice() methods of MidiInput and MidiOutput or by calling getDeviceInfo()\r
     on an instance of these classes. Devices can be opened by passing the identifier to\r
     the openDevice() method.\r
+\r
+    @tags{Audio}\r
 */\r
 struct MidiDeviceInfo\r
 {\r
index 50ca20569aa15f2cc3f0eff6e97ee140474ffae7..97f7330340083aa0d39d5cbfc4e7f702bb942d63 100644 (file)
@@ -34,9 +34,10 @@ MidiMessageCollector::~MidiMessageCollector()
 //==============================================================================\r
 void MidiMessageCollector::reset (const double newSampleRate)\r
 {\r
+    const ScopedLock sl (midiCallbackLock);\r
+\r
     jassert (newSampleRate > 0);\r
 \r
-    const ScopedLock sl (midiCallbackLock);\r
    #if JUCE_DEBUG\r
     hasCalledReset = true;\r
    #endif\r
@@ -47,6 +48,8 @@ void MidiMessageCollector::reset (const double newSampleRate)
 \r
 void MidiMessageCollector::addMessageToQueue (const MidiMessage& message)\r
 {\r
+    const ScopedLock sl (midiCallbackLock);\r
+\r
    #if JUCE_DEBUG\r
     jassert (hasCalledReset); // you need to call reset() to set the correct sample rate before using this object\r
    #endif\r
@@ -55,8 +58,6 @@ void MidiMessageCollector::addMessageToQueue (const MidiMessage& message)
     // for details of what the number should be.\r
     jassert (message.getTimeStamp() != 0);\r
 \r
-    const ScopedLock sl (midiCallbackLock);\r
-\r
     auto sampleNumber = (int) ((message.getTimeStamp() - 0.001 * lastCallbackTime) * sampleRate);\r
 \r
     incomingMessages.addEvent (message, sampleNumber);\r
@@ -70,6 +71,8 @@ void MidiMessageCollector::addMessageToQueue (const MidiMessage& message)
 void MidiMessageCollector::removeNextBlockOfMessages (MidiBuffer& destBuffer,\r
                                                       const int numSamples)\r
 {\r
+    const ScopedLock sl (midiCallbackLock);\r
+\r
    #if JUCE_DEBUG\r
     jassert (hasCalledReset); // you need to call reset() to set the correct sample rate before using this object\r
    #endif\r
@@ -79,7 +82,6 @@ void MidiMessageCollector::removeNextBlockOfMessages (MidiBuffer& destBuffer,
     auto timeNow = Time::getMillisecondCounterHiRes();\r
     auto msElapsed = timeNow - lastCallbackTime;\r
 \r
-    const ScopedLock sl (midiCallbackLock);\r
     lastCallbackTime = timeNow;\r
 \r
     if (! incomingMessages.isEmpty())\r
index 7e67c1d00664b370c7858083f13dfd791d6c3881..4a19f7710b48bd7b3bbe07002e05deff125f45fa 100644 (file)
@@ -757,7 +757,7 @@ public:
             // only the player or the recorder should enter this section at any time\r
             if (guard.compareAndSetBool (1, 0))\r
             {\r
-                // are there enough buffers avaialable to process some audio\r
+                // are there enough buffers available to process some audio\r
                 if ((inputChannels == 0 || recorder->isBufferAvailable()) && (outputChannels == 0 || player->isBufferAvailable()))\r
                 {\r
                     T* recorderBuffer = (inputChannels  > 0 ? recorder->getNextBuffer() : nullptr);\r
@@ -854,7 +854,7 @@ public:
                                         22050.0, 24000.0, 32000.0, 44100.0, 48000.0 };\r
         Array<double> retval (rates, numElementsInArray (rates));\r
 \r
-        // make sure the native sample rate is pafrt of the list\r
+        // make sure the native sample rate is part of the list\r
         double native = getNativeSampleRate();\r
 \r
         if (native != 0.0 && ! retval.contains (native))\r
index 9fff0b1efedc2bed248c48f2c14abf8037d34962..f126c1dcb7d0a680c5881141332e1d0723bc286e 100644 (file)
@@ -1249,7 +1249,7 @@ private:
             snd_device_name_free_hint (hints);\r
         }\r
 \r
-        // sometimes the "default" device is not listed, but it is nice to see it explicitely in the list\r
+        // sometimes the "default" device is not listed, but it is nice to see it explicitly in the list\r
         if (! outputIds.contains ("default"))\r
             testDevice ("default", "Default ALSA Output", "Default ALSA Input");\r
 \r
old mode 100755 (executable)
new mode 100644 (file)
index b13eceb..133e39b
@@ -373,7 +373,7 @@ public:
     BigInteger getActiveInputChannels() const override    { BigInteger b; b.setRange (0, actualNumberOfInputs, true);  return b; }\r
     int getOutputLatencyInSamples() override              { /* TODO */ return 0; }\r
     int getInputLatencyInSamples() override               { /* TODO */ return 0; }\r
-    int getXRunCount() const noexcept                     { return underruns; }\r
+    int getXRunCount() const noexcept override            { return underruns; }\r
 \r
     //==============================================================================\r
     static const char* const belaTypeName;\r
index 35302a31603f2a3a5b783a370d32e1b5f9447492..b916d7aaaac75d65d01b421f12d32a7919929602 100644 (file)
@@ -105,7 +105,11 @@ namespace
 \r
 //==============================================================================\r
 #ifndef JUCE_JACK_CLIENT_NAME\r
- #define JUCE_JACK_CLIENT_NAME "JUCEJack"\r
+ #ifdef JucePlugin_Name\r
+  #define JUCE_JACK_CLIENT_NAME JucePlugin_Name\r
+ #else\r
+  #define JUCE_JACK_CLIENT_NAME "JUCEJack"\r
+ #endif\r
 #endif\r
 \r
 struct JackPortIterator\r
index 8f1004e0102f016779bf2bae52847e8c5fc22005..86b064047fc813bf6c9634fd3fdbfd52393075d3 100644 (file)
@@ -31,7 +31,7 @@ namespace juce
 \r
 #ifdef __clang__\r
  #pragma clang diagnostic push\r
- #pragma clang diagnostic ignored "-Wnonnull" // aovid some spurious 10.11 SDK warnings\r
+ #pragma clang diagnostic ignored "-Wnonnull" // avoid some spurious 10.11 SDK warnings\r
 #endif\r
 \r
 //==============================================================================\r
index 6e9aa954791db08cd8c3ccf4e5f9c358246d006e..8b1e352d718e1a02ecfd0dc6a2fdef2b35baa0a4 100644 (file)
@@ -499,7 +499,7 @@ std::unique_ptr<MidiInput> MidiInput::createNewDevice (const String& deviceName,
 \r
             if (CHECK_ERROR (MIDIObjectSetIntegerProperty (endpoint, kMIDIPropertyUniqueID, (SInt32) deviceIdentifier)))\r
             {\r
-                mpc->portAndEndpoint = std::make_unique<MidiPortAndEndpoint> (0, endpoint);\r
+                mpc->portAndEndpoint = std::make_unique<MidiPortAndEndpoint> ((UInt32) 0, endpoint);\r
 \r
                 std::unique_ptr<MidiInput> midiInput (new MidiInput (deviceName, String (deviceIdentifier)));\r
 \r
@@ -630,7 +630,7 @@ std::unique_ptr<MidiOutput> MidiOutput::createNewDevice (const String& deviceNam
 \r
         if (CHECK_ERROR (err))\r
         {\r
-            auto deviceIdentifier = createUniqueIDForMidiPort (deviceName, true);\r
+            auto deviceIdentifier = createUniqueIDForMidiPort (deviceName, false);\r
 \r
             if (CHECK_ERROR (MIDIObjectSetIntegerProperty (endpoint, kMIDIPropertyUniqueID, (SInt32) deviceIdentifier)))\r
             {\r
index 810c4b0a5417ca1dde29b447b00ce83d5b3c2044..34f438f25beed865bda61aa1815c9ca2593fa602 100644 (file)
@@ -43,7 +43,9 @@ namespace ASIODebugging
     {\r
         message = "ASIO: " + message;\r
         DBG (message);\r
-        Logger::writeToLog (message);\r
+\r
+        if (Logger::getCurrentLogger() != nullptr)\r
+            Logger::writeToLog (message);\r
     }\r
 \r
     static void logError (const String& context, long error)\r
@@ -336,7 +338,9 @@ public:
 \r
         close();\r
         JUCE_ASIO_LOG ("closed");\r
-        removeCurrentDriver();\r
+\r
+        if (! removeCurrentDriver())\r
+            JUCE_ASIO_LOG ("** Driver crashed while being closed");\r
     }\r
 \r
     void updateSampleRates()\r
@@ -451,7 +455,9 @@ public:
         if (needToReset)\r
         {\r
             JUCE_ASIO_LOG (" Resetting");\r
-            removeCurrentDriver();\r
+\r
+            if (! removeCurrentDriver())\r
+                JUCE_ASIO_LOG ("** Driver crashed while being closed");\r
 \r
             loadDriver();\r
             String initError = initDriver();\r
@@ -640,8 +646,8 @@ public:
     BigInteger getActiveOutputChannels() const override    { return currentChansOut; }\r
     BigInteger getActiveInputChannels() const override     { return currentChansIn; }\r
 \r
-    int getOutputLatencyInSamples() override     { return outputLatency + currentBlockSizeSamples / 4; }\r
-    int getInputLatencyInSamples() override      { return inputLatency + currentBlockSizeSamples / 4; }\r
+    int getOutputLatencyInSamples() override     { return outputLatency; }\r
+    int getInputLatencyInSamples() override      { return inputLatency; }\r
 \r
     void start (AudioIODeviceCallback* callback) override\r
     {\r
@@ -1075,28 +1081,32 @@ private:
         }\r
     }\r
 \r
-    static bool shouldReleaseObject (const String& driverName)\r
+    bool removeCurrentDriver()\r
     {\r
-        return driverName != "Yamaha Steinberg USB ASIO";\r
-    }\r
+        bool releasedOK = true;\r
 \r
-    void removeCurrentDriver()\r
-    {\r
         if (asioObject != nullptr)\r
         {\r
-            char buffer[512] = {};\r
-            asioObject->getDriverName (buffer);\r
-\r
-            if (shouldReleaseObject (buffer))\r
+           #if ! JUCE_MINGW\r
+            __try\r
+           #endif\r
+            {\r
                 asioObject->Release();\r
+            }\r
+           #if ! JUCE_MINGW\r
+            __except (EXCEPTION_EXECUTE_HANDLER) { releasedOK = false; }\r
+           #endif\r
 \r
             asioObject = nullptr;\r
         }\r
+\r
+        return releasedOK;\r
     }\r
 \r
     bool loadDriver()\r
     {\r
-        removeCurrentDriver();\r
+        if (! removeCurrentDriver())\r
+            JUCE_ASIO_LOG ("** Driver crashed while being closed");\r
 \r
         bool crashed = false;\r
         bool ok = tryCreatingDriver (crashed);\r
@@ -1256,7 +1266,9 @@ private:
         {\r
             JUCE_ASIO_LOG_ERROR (error, err);\r
             disposeBuffers();\r
-            removeCurrentDriver();\r
+\r
+            if (! removeCurrentDriver())\r
+                JUCE_ASIO_LOG ("** Driver crashed while being closed");\r
         }\r
         else\r
         {\r
index ae2a9683fc316b4ed389a99f5b8a2a94a8103c50..5a39111a1556742724e398f9fece940e69f3b6a5 100644 (file)
@@ -716,15 +716,17 @@ public:
     //==============================================================================\r
     WinRTMidiService()\r
     {\r
-        if (! WinRTWrapper::getInstance()->isInitialised())\r
+        auto* wrtWrapper = WinRTWrapper::getInstance();\r
+\r
+        if (! wrtWrapper->isInitialised())\r
             throw std::runtime_error ("Failed to initialise the WinRT wrapper");\r
 \r
-        midiInFactory = WinRTWrapper::getInstance()->getWRLFactory<IMidiInPortStatics> (&RuntimeClass_Windows_Devices_Midi_MidiInPort[0]);\r
+        midiInFactory = wrtWrapper->getWRLFactory<IMidiInPortStatics> (&RuntimeClass_Windows_Devices_Midi_MidiInPort[0]);\r
 \r
         if (midiInFactory == nullptr)\r
             throw std::runtime_error ("Failed to create midi in factory");\r
 \r
-        midiOutFactory = WinRTWrapper::getInstance()->getWRLFactory<IMidiOutPortStatics> (&RuntimeClass_Windows_Devices_Midi_MidiOutPort[0]);\r
+        midiOutFactory = wrtWrapper->getWRLFactory<IMidiOutPortStatics> (&RuntimeClass_Windows_Devices_Midi_MidiOutPort[0]);\r
 \r
         if (midiOutFactory == nullptr)\r
             throw std::runtime_error ("Failed to create midi out factory");\r
@@ -784,16 +786,24 @@ private:
 \r
         bool attach (HSTRING deviceSelector, DeviceInformationKind infoKind)\r
         {\r
-            auto deviceInfoFactory = WinRTWrapper::getInstance()->getWRLFactory<IDeviceInformationStatics2> (&RuntimeClass_Windows_Devices_Enumeration_DeviceInformation[0]);\r
+            auto* wrtWrapper = WinRTWrapper::getInstanceWithoutCreating();\r
+\r
+            if (wrtWrapper == nullptr)\r
+            {\r
+                JUCE_WINRT_MIDI_LOG ("Failed to get the WinRTWrapper singleton!");\r
+                return false;\r
+            }\r
+\r
+            auto deviceInfoFactory = wrtWrapper->getWRLFactory<IDeviceInformationStatics2> (&RuntimeClass_Windows_Devices_Enumeration_DeviceInformation[0]);\r
 \r
             if (deviceInfoFactory == nullptr)\r
                 return false;\r
 \r
             // A quick way of getting an IVector<HSTRING>...\r
-            auto requestedProperties = []\r
+            auto requestedProperties = [wrtWrapper]\r
             {\r
-                auto devicePicker = WinRTWrapper::getInstance()->activateInstance<IDevicePicker> (&RuntimeClass_Windows_Devices_Enumeration_DevicePicker[0],\r
-                                                                                                  __uuidof (IDevicePicker));\r
+                auto devicePicker = wrtWrapper->activateInstance<IDevicePicker> (&RuntimeClass_Windows_Devices_Enumeration_DevicePicker[0],\r
+                                                                                 __uuidof (IDevicePicker));\r
                 jassert (devicePicker != nullptr);\r
 \r
                 IVector<HSTRING>* result;\r
@@ -806,9 +816,9 @@ private:
                 return result;\r
             }();\r
 \r
-            StringArray propertyKeys = { "System.Devices.ContainerId",\r
-                                         "System.Devices.Aep.ContainerId",\r
-                                         "System.Devices.Aep.IsConnected" };\r
+            StringArray propertyKeys ("System.Devices.ContainerId",\r
+                                      "System.Devices.Aep.ContainerId",\r
+                                      "System.Devices.Aep.IsConnected");\r
 \r
             for (auto& key : propertyKeys)\r
             {\r
@@ -994,7 +1004,7 @@ private:
                     Callback<ITypedEventHandler<DeviceWatcher*, DeviceInformationUpdate*>> (\r
                         [handlerPtr](IDeviceWatcher*, IDeviceInformationUpdate* infoUpdate) { return handlerPtr->updateDevice (infoUpdate); }\r
                     ).Get(),\r
-                    &deviceRemovedToken);\r
+                    &deviceUpdatedToken);\r
 \r
                 watcher->Start();\r
             }\r
@@ -1045,7 +1055,15 @@ private:
                 return S_OK;\r
             }\r
 \r
-            auto deviceID = WinRTWrapper::getInstance()->hStringToString (deviceIDHst);\r
+            auto* wrtWrapper = WinRTWrapper::getInstanceWithoutCreating();\r
+\r
+            if (wrtWrapper == nullptr)\r
+            {\r
+                JUCE_WINRT_MIDI_LOG ("Failed to get the WinRTWrapper singleton!");\r
+                return false;\r
+            }\r
+\r
+            auto deviceID = wrtWrapper->hStringToString (deviceIDHst);\r
             JUCE_WINRT_MIDI_LOG ("Detected paired BLE device: " << deviceID);\r
 \r
             if (auto* containerIDValue = getValueFromDeviceInfo ("System.Devices.Aep.ContainerId", addedDeviceInfo))\r
@@ -1082,7 +1100,15 @@ private:
                 return S_OK;\r
             }\r
 \r
-            auto removedDeviceId = WinRTWrapper::getInstance()->hStringToString (removedDeviceIdHstr);\r
+            auto* wrtWrapper = WinRTWrapper::getInstanceWithoutCreating();\r
+\r
+            if (wrtWrapper == nullptr)\r
+            {\r
+                JUCE_WINRT_MIDI_LOG ("Failed to get the WinRTWrapper singleton!");\r
+                return false;\r
+            }\r
+\r
+            auto removedDeviceId = wrtWrapper->hStringToString (removedDeviceIdHstr);\r
 \r
             JUCE_WINRT_MIDI_LOG ("Removing BLE device: " << removedDeviceId);\r
 \r
@@ -1112,7 +1138,15 @@ private:
                 return S_OK;\r
             }\r
 \r
-            auto updatedDeviceId = WinRTWrapper::getInstance()->hStringToString (updatedDeviceIdHstr);\r
+            auto* wrtWrapper = WinRTWrapper::getInstanceWithoutCreating();\r
+\r
+            if (wrtWrapper == nullptr)\r
+            {\r
+                JUCE_WINRT_MIDI_LOG ("Failed to get the WinRTWrapper singleton!");\r
+                return false;\r
+            }\r
+\r
+            auto updatedDeviceId = wrtWrapper->hStringToString (updatedDeviceIdHstr);\r
 \r
             JUCE_WINRT_MIDI_LOG ("Updating BLE device: " << updatedDeviceId);\r
 \r
@@ -1209,7 +1243,15 @@ private:
                 return S_OK;\r
             }\r
 \r
-            info.deviceID = WinRTWrapper::getInstance()->hStringToString (deviceID);\r
+            auto* wrtWrapper = WinRTWrapper::getInstanceWithoutCreating();\r
+\r
+            if (wrtWrapper == nullptr)\r
+            {\r
+                JUCE_WINRT_MIDI_LOG ("Failed to get the WinRTWrapper singleton!");\r
+                return false;\r
+            }\r
+\r
+            info.deviceID = wrtWrapper->hStringToString (deviceID);\r
 \r
             JUCE_WINRT_MIDI_LOG ("Detected MIDI device: " << info.deviceID);\r
 \r
@@ -1235,7 +1277,7 @@ private:
                 return S_OK;\r
             }\r
 \r
-            info.name = WinRTWrapper::getInstance()->hStringToString (name);\r
+            info.name = wrtWrapper->hStringToString (name);\r
 \r
             boolean isDefault = false;\r
             hr = addedDeviceInfo->get_IsDefault (&isDefault);\r
@@ -1269,7 +1311,15 @@ private:
                 return S_OK;\r
             }\r
 \r
-            auto removedDeviceId = WinRTWrapper::getInstance()->hStringToString (removedDeviceIdHstr);\r
+            auto* wrtWrapper = WinRTWrapper::getInstanceWithoutCreating();\r
+\r
+            if (wrtWrapper == nullptr)\r
+            {\r
+                JUCE_WINRT_MIDI_LOG ("Failed to get the WinRTWrapper singleton!");\r
+                return false;\r
+            }\r
+\r
+            auto removedDeviceId = wrtWrapper->hStringToString (removedDeviceIdHstr);\r
 \r
             JUCE_WINRT_MIDI_LOG ("Removing MIDI device: " << removedDeviceId);\r
 \r
@@ -1408,8 +1458,8 @@ private:
                 }\r
             ).Get());\r
 \r
-            // We need to use a timout here, rather than waiting indefinitely, as the\r
-            // WinRT API can occaisonally hang!\r
+            // We need to use a timeout here, rather than waiting indefinitely, as the\r
+            // WinRT API can occasionally hang!\r
             portOpened.wait (2000);\r
         }\r
 \r
@@ -1674,7 +1724,12 @@ private:
             if (midiPort == nullptr)\r
                 throw std::runtime_error ("Timed out waiting for midi output port creation");\r
 \r
-            auto bufferFactory = WinRTWrapper::getInstance()->getWRLFactory<IBufferFactory> (&RuntimeClass_Windows_Storage_Streams_Buffer[0]);\r
+            auto* wrtWrapper = WinRTWrapper::getInstanceWithoutCreating();\r
+\r
+            if (wrtWrapper == nullptr)\r
+                throw std::runtime_error ("Failed to get the WinRTWrapper singleton!");\r
+\r
+            auto bufferFactory = wrtWrapper->getWRLFactory<IBufferFactory> (&RuntimeClass_Windows_Storage_Streams_Buffer[0]);\r
 \r
             if (bufferFactory == nullptr)\r
                 throw std::runtime_error ("Failed to create output buffer factory");\r
@@ -1739,13 +1794,15 @@ private:
 \r
 //==============================================================================\r
 //==============================================================================\r
-extern RTL_OSVERSIONINFOW getWindowsVersionInfo();\r
+#if ! JUCE_MINGW\r
+ extern RTL_OSVERSIONINFOW getWindowsVersionInfo();\r
+#endif\r
 \r
 struct MidiService :  public DeletedAtShutdown\r
 {\r
     MidiService()\r
     {\r
-      #if JUCE_USE_WINRT_MIDI\r
+      #if JUCE_USE_WINRT_MIDI && ! JUCE_MINGW\r
        #if ! JUCE_FORCE_WINRT_MIDI\r
         auto windowsVersionInfo = getWindowsVersionInfo();\r
         if (windowsVersionInfo.dwMajorVersion >= 10 && windowsVersionInfo.dwBuildNumber >= 17763)\r
index 3f5a87d3f47f954c4f2cf12c2eefd95611182d07..f1356022c3426247091bf4fde8fa4733e4b5bdff 100644 (file)
@@ -105,7 +105,8 @@ private:
     float* outputChans[128];\r
     const float* inputChans[128];\r
     AudioBuffer<float> tempBuffer;\r
-    float lastGain = 1.0f, gain = 1.0f;\r
+    float lastGain = 1.0f;\r
+    std::atomic<float> gain { 1.0f };\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioSourcePlayer)\r
 };\r
index 330b86b2c03e76901af065ec4b49bab8d47ffec1..dd6737a8ca20c9e539eb714e50bde2112a331202 100644 (file)
@@ -352,9 +352,9 @@ public:
 \r
         auto status = AudioFileOpenWithCallbacks (this,\r
                                                   &readCallback,\r
-                                                  nullptr,  // write needs to be null to avoid permisisions errors\r
+                                                  nullptr,  // write needs to be null to avoid permissions errors\r
                                                   &getSizeCallback,\r
-                                                  nullptr,  // setSize needs to be null to avoid permisisions errors\r
+                                                  nullptr,  // setSize needs to be null to avoid permissions errors\r
                                                   0,        // AudioFileTypeID inFileTypeHint\r
                                                   &audioFileID);\r
         if (status == noErr)\r
@@ -616,7 +616,7 @@ public:
         : UnitTest ("Core Audio Layout <-> JUCE channel layout conversion", UnitTestCategories::audio)\r
     {}\r
 \r
-    // some ambisonic tags which are not explicitely defined\r
+    // some ambisonic tags which are not explicitly defined\r
     enum\r
     {\r
         kAudioChannelLayoutTag_HOA_ACN_SN3D_0Order = (190U<<16) | 1,\r
index a2459c6db0e0b8f55b9c1c272a6d957a2a23242a..3515786aedcc891715a757bcad451edc592fa6cb 100644 (file)
@@ -1052,8 +1052,15 @@ public:
                 }\r
                 else if (chunkType == chunkName ("data"))\r
                 {\r
-                    if (! isRF64) // data size is expected to be -1, actual data size is in ds64 chunk\r
+                    if (isRF64)\r
+                    {\r
+                        if (dataLength > 0)\r
+                            chunkEnd = input->getPosition() + dataLength + (dataLength & 1);\r
+                    }\r
+                    else\r
+                    {\r
                         dataLength = length;\r
+                    }\r
 \r
                     dataChunkStart = input->getPosition();\r
                     lengthInSamples = (bytesPerFrame > 0) ? (dataLength / bytesPerFrame) : 0;\r
@@ -1349,7 +1356,7 @@ public:
         {\r
             // failed to write to disk, so let's try writing the header.\r
             // If it's just run out of disk space, then if it does manage\r
-            // to write the header, we'll still have a useable file..\r
+            // to write the header, we'll still have a usable file..\r
             writeHeader();\r
             writeFailed = true;\r
             return false;\r
index 016889374040dfcdda45721fb0ea8ba5e8b6d43c..3474442567637b4766c1188a471a1057f9a26ee1 100644 (file)
@@ -206,7 +206,7 @@ public:
                     if (hasJumped)\r
                         bufferedRange.setStart ((int64) ((sampleTime * (int64) sampleRate) / 10000000));\r
                     else\r
-                        bufferedRange.setStart (bufferedRange.getEnd()); // (because the positions returned often aren't continguous)\r
+                        bufferedRange.setStart (bufferedRange.getEnd()); // (because the positions returned often aren't contiguous)\r
 \r
                     bufferedRange.setLength ((int64) (dataLength / stride));\r
 \r
index dd6bacca979ec58eb9f4d1cacd4882df87afa69c..d3008572d2deba127aadb3b9f3ec51684a3656e2 100644 (file)
@@ -132,9 +132,7 @@ public:
                                     to try to open a different format, etc\r
         @param sampleRateToUse      the sample rate for the file, which must be one of the ones\r
                                     returned by getPossibleSampleRates()\r
-        @param numberOfChannels     the number of channels - this must be either 1 or 2, and\r
-                                    the choice will depend on the results of canDoMono() and\r
-                                    canDoStereo()\r
+        @param numberOfChannels     the number of channels\r
         @param bitsPerSample        the bits per sample to use - this must be one of the values\r
                                     returned by getPossibleBitDepths()\r
         @param metadataValues       a set of metadata values that the writer should try to write\r
index 179d89f804fe5112a462c0d55406b09fde5c34bc..54b307633c54b45ff4dd20a7635427dc582bd7d8 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_audio_formats\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE audio file format codecs\r
-  description:      Classes for reading and writing various audio file formats.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
-\r
-  dependencies:     juce_audio_basics\r
-  OSXFrameworks:    CoreAudio CoreMIDI QuartzCore AudioToolbox\r
-  iOSFrameworks:    AudioToolbox QuartzCore\r
+  ID:                 juce_audio_formats\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE audio file format codecs\r
+  description:        Classes for reading and writing various audio file formats.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
+\r
+  dependencies:       juce_audio_basics\r
+  OSXFrameworks:      CoreAudio CoreMIDI QuartzCore AudioToolbox\r
+  iOSFrameworks:      AudioToolbox QuartzCore\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index adc374e1e817dcafc1d91723621d1f9c2f566494..9499b037765b95fa1904826b7a419edaa469d59b 100644 (file)
@@ -1004,7 +1004,12 @@ namespace AAXClasses
             info.timeInSeconds = info.timeInSamples / sampleRate;\r
 \r
             int64_t ticks = 0;\r
-            check (transport.GetCurrentTickPosition (&ticks));\r
+\r
+            if (info.isPlaying)\r
+                check (transport.GetCustomTickPosition (&ticks, info.timeInSamples));\r
+            else\r
+                check (transport.GetCurrentTickPosition (&ticks));\r
+\r
             info.ppqPosition = ticks / 960000.0;\r
 \r
             info.isLooping = false;\r
@@ -1652,7 +1657,7 @@ namespace AAXClasses
 \r
             if (isInAudioSuite())\r
             {\r
-                // AudioSuite doesnt support multiple output buses\r
+                // AudioSuite doesn't support multiple output buses\r
                 for (int i = 1; i < newLayout.outputBuses.size(); ++i)\r
                     newLayout.outputBuses.getReference (i) = AudioChannelSet::disabled();\r
 \r
@@ -1823,7 +1828,7 @@ namespace AAXClasses
                 if (LegacyAudioParameter::getParamID (aaxMeters[idx], false) == paramID)\r
                     break;\r
 \r
-            // you sepecified a parameter id in your curve but the parameter does not have the meter\r
+            // you specified a parameter id in your curve but the parameter does not have the meter\r
             // category\r
             jassert (idx < aaxMeters.size());\r
             return 'Metr' + static_cast<AAX_CTypeID> (idx);\r
index 0cc15378bda276e8702d0771e3ec8351fdfdd7ea..2069d93ee6101fcd4c6883761d5c02d4c413b543 100644 (file)
@@ -255,36 +255,23 @@ public:
     {\r
         DialogWindow::LaunchOptions o;\r
 \r
-        int minNumInputs  = std::numeric_limits<int>::max(), maxNumInputs  = 0,\r
-            minNumOutputs = std::numeric_limits<int>::max(), maxNumOutputs = 0;\r
-\r
-        auto updateMinAndMax = [] (int newValue, int& minValue, int& maxValue)\r
-        {\r
-            minValue = jmin (minValue, newValue);\r
-            maxValue = jmax (maxValue, newValue);\r
-        };\r
+        int maxNumInputs = 0, maxNumOutputs = 0;\r
 \r
         if (channelConfiguration.size() > 0)\r
         {\r
-            auto defaultConfig = channelConfiguration.getReference (0);\r
-            updateMinAndMax ((int) defaultConfig.numIns,  minNumInputs,  maxNumInputs);\r
-            updateMinAndMax ((int) defaultConfig.numOuts, minNumOutputs, maxNumOutputs);\r
+            auto& defaultConfig = channelConfiguration.getReference (0);\r
+\r
+            maxNumInputs  = jmax (0, (int) defaultConfig.numIns);\r
+            maxNumOutputs = jmax (0, (int) defaultConfig.numOuts);\r
         }\r
 \r
         if (auto* bus = processor->getBus (true, 0))\r
-            updateMinAndMax (bus->getDefaultLayout().size(), minNumInputs, maxNumInputs);\r
+            maxNumInputs = jmax (0, bus->getDefaultLayout().size());\r
 \r
         if (auto* bus = processor->getBus (false, 0))\r
-            updateMinAndMax (bus->getDefaultLayout().size(), minNumOutputs, maxNumOutputs);\r
-\r
-        minNumInputs  = jmin (minNumInputs,  maxNumInputs);\r
-        minNumOutputs = jmin (minNumOutputs, maxNumOutputs);\r
+            maxNumOutputs = jmax (0, bus->getDefaultLayout().size());\r
 \r
-        o.content.setOwned (new SettingsComponent (*this, deviceManager,\r
-                                                          minNumInputs,\r
-                                                          maxNumInputs,\r
-                                                          minNumOutputs,\r
-                                                          maxNumOutputs));\r
+        o.content.setOwned (new SettingsComponent (*this, deviceManager, maxNumInputs, maxNumOutputs));\r
         o.content->setSize (500, 550);\r
 \r
         o.dialogTitle                   = TRANS("Audio/MIDI Settings");\r
@@ -425,14 +412,12 @@ private:
     public:\r
         SettingsComponent (StandalonePluginHolder& pluginHolder,\r
                            AudioDeviceManager& deviceManagerToUse,\r
-                           int minAudioInputChannels,\r
                            int maxAudioInputChannels,\r
-                           int minAudioOutputChannels,\r
                            int maxAudioOutputChannels)\r
             : owner (pluginHolder),\r
               deviceSelector (deviceManagerToUse,\r
-                              minAudioInputChannels, maxAudioInputChannels,\r
-                              minAudioOutputChannels, maxAudioOutputChannels,\r
+                              0, maxAudioInputChannels,\r
+                              0, maxAudioOutputChannels,\r
                               true,\r
                               (pluginHolder.processor.get() != nullptr && pluginHolder.processor->producesMidi()),\r
                               true, false),\r
index 9b9a7f9f38ea4bb4643d5c49ccebe1d6412d582c..879c9066b47fe2f6b0c22e3774abcce94566a1f6 100644 (file)
 \r
 #if JucePlugin_VersionCode < 0x010000   // Major < 0\r
 \r
- #if (JucePlugin_VersionCode & 0x00FF00) > (9 * 0x100) // check if Minor number exceeeds 9\r
+ #if (JucePlugin_VersionCode & 0x00FF00) > (9 * 0x100) // check if Minor number exceeds 9\r
   JUCE_COMPILER_WARNING ("When version has 'major' = 0, VST2 has trouble displaying 'minor' exceeding 9")\r
  #endif\r
 \r
- #if (JucePlugin_VersionCode & 0xFF) > 9   // check if Bugfix number exceeeds 9\r
+ #if (JucePlugin_VersionCode & 0xFF) > 9   // check if Bugfix number exceeds 9\r
   JUCE_COMPILER_WARNING ("When version has 'major' = 0, VST2 has trouble displaying 'bugfix' exceeding 9")\r
  #endif\r
 \r
 #elif JucePlugin_VersionCode >= 0x650000   // Major >= 101\r
 \r
- #if (JucePlugin_VersionCode & 0x00FF00) > (99 * 0x100) // check if Minor number exceeeds 99\r
+ #if (JucePlugin_VersionCode & 0x00FF00) > (99 * 0x100) // check if Minor number exceeds 99\r
   JUCE_COMPILER_WARNING ("When version has 'major' > 100, VST2 has trouble displaying 'minor' exceeding 99")\r
  #endif\r
 \r
- #if (JucePlugin_VersionCode & 0xFF) > 99  // check if Bugfix number exceeeds 99\r
+ #if (JucePlugin_VersionCode & 0xFF) > 99  // check if Bugfix number exceeds 99\r
   JUCE_COMPILER_WARNING ("When version has 'major' > 100, VST2 has trouble displaying 'bugfix' exceeding 99")\r
  #endif\r
 \r
index da1fb9895d9b2bab9e95a0cb8142a062fd7eebdb..3672ab73582fd71e500a4b64e1deaeda751fbb96 100644 (file)
@@ -230,7 +230,7 @@ void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSVi
             // The event loop needs to be run between closing the window and deleting the plugin,\r
             // presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes\r
             // in Live when you delete the plugin with its window open.\r
-            // (Doing it this way rather than using a single longer timout means that we can guarantee\r
+            // (Doing it this way rather than using a single longer timeout means that we can guarantee\r
             // how many messages will be dispatched, which seems to be vital in Reaper)\r
             if (needToRunMessageLoop)\r
                 for (int i = 20; --i >= 0;)\r
index d94d022a2dba1d0039ffea0808635439d8387877..0947eb5f72484ef7e6be01bf95da0e7ca34f127c 100644 (file)
@@ -423,19 +423,19 @@ public:
     {\r
         Param (JuceVST3EditController& editController, AudioProcessorParameter& p,\r
                Vst::ParamID vstParamID, Vst::UnitID vstUnitID,\r
-               bool isBypassParameter, bool forceLegacyParamIDs)\r
+               bool isBypassParameter)\r
             : owner (editController), param (p)\r
         {\r
             info.id = vstParamID;\r
             info.unitId = vstUnitID;\r
 \r
-            toString128 (info.title,      param.getName (128));\r
-            toString128 (info.shortTitle, param.getName (8));\r
-            toString128 (info.units,      param.getLabel());\r
+            updateParameterInfo();\r
 \r
             info.stepCount = (Steinberg::int32) 0;\r
 \r
-            if (! forceLegacyParamIDs && param.isDiscrete())\r
+           #if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE\r
+            if (param.isDiscrete())\r
+           #endif\r
             {\r
                 const int numSteps = param.getNumSteps();\r
                 info.stepCount = (Steinberg::int32) (numSteps > 0 && numSteps < 0x7fffffff ? numSteps - 1 : 0);\r
@@ -458,6 +458,13 @@ public:
 \r
         virtual ~Param() override = default;\r
 \r
+        void updateParameterInfo()\r
+        {\r
+            toString128 (info.title,      param.getName (128));\r
+            toString128 (info.shortTitle, param.getName (8));\r
+            toString128 (info.units,      param.getLabel());\r
+        }\r
+\r
         bool setNormalized (Vst::ParamValue v) override\r
         {\r
             v = jlimit (0.0, 1.0, v);\r
@@ -682,9 +689,13 @@ public:
     tresult PLUGIN_API getMidiControllerAssignment (Steinberg::int32 /*busIndex*/, Steinberg::int16 channel,\r
                                                     Vst::CtrlNumber midiControllerNumber, Vst::ParamID& resultID) override\r
     {\r
+       #if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS\r
         resultID = midiControllerToParameter[channel][midiControllerNumber];\r
-\r
         return kResultTrue; // Returning false makes some hosts stop asking for further MIDI Controller Assignments\r
+       #else\r
+        ignoreUnused (channel, midiControllerNumber, resultID);\r
+        return kResultFalse;\r
+       #endif\r
     }\r
 \r
     // Converts an incoming parameter index to a MIDI controller:\r
@@ -881,6 +892,12 @@ public:
 \r
     void audioProcessorChanged (AudioProcessor*) override\r
     {\r
+        auto numParameters = parameters.getParameterCount();\r
+\r
+        for (int32 i = 0; i < numParameters; ++i)\r
+            if (auto* param = dynamic_cast<Param*> (parameters.getParameterByIndex (i)))\r
+                param->updateParameterInfo();\r
+\r
         if (auto* pluginInstance = getPluginInstance())\r
         {\r
             if (pluginInstance->getNumPrograms() > 1)\r
@@ -889,7 +906,7 @@ public:
         }\r
 \r
         if (componentHandler != nullptr && ! inSetupProcessing)\r
-            componentHandler->restartComponent (Vst::kLatencyChanged | Vst::kParamValuesChanged);\r
+            componentHandler->restartComponent (Vst::kLatencyChanged | Vst::kParamValuesChanged | Vst::kParamTitlesChanged);\r
     }\r
 \r
     void parameterValueChanged (int, float newValue) override\r
@@ -950,12 +967,6 @@ private:
 \r
             if (parameters.getParameterCount() <= 0)\r
             {\r
-               #if JUCE_FORCE_USE_LEGACY_PARAM_IDS\r
-                const bool forceLegacyParamIDs = true;\r
-               #else\r
-                const bool forceLegacyParamIDs = false;\r
-               #endif\r
-\r
                 auto n = audioProcessor->getNumParameters();\r
 \r
                 for (int i = 0; i < n; ++i)\r
@@ -966,7 +977,7 @@ private:
                     auto unitID = JuceAudioProcessor::getUnitID (parameterGroup);\r
 \r
                     parameters.addParameter (new Param (*this, *juceParam, vstParamID, unitID,\r
-                                                        (vstParamID == audioProcessor->bypassParamID), forceLegacyParamIDs));\r
+                                                        (vstParamID == audioProcessor->bypassParamID)));\r
                 }\r
 \r
                 if (pluginInstance->getNumPrograms() > 1)\r
@@ -1070,6 +1081,9 @@ private:
             component->addToDesktop (0, parent);\r
             component->setOpaque (true);\r
             component->setVisible (true);\r
+            #if JUCE_WIN_PER_MONITOR_DPI_AWARE\r
+             component->checkScaleFactorIsCorrect();\r
+            #endif\r
            #else\r
             isNSView = (strcmp (type, kPlatformTypeNSView) == 0);\r
             macHostWindow = juce::attachComponentToWindowRefVST (component.get(), parent, isNSView);\r
@@ -2423,7 +2437,7 @@ public:
                             pluginInstance->setCurrentProgram (programValue);\r
                     }\r
                    #if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS\r
-                    else if (juceVST3EditController->isMidiControllerParamID (vstParamID))\r
+                    else if (juceVST3EditController != nullptr && juceVST3EditController->isMidiControllerParamID (vstParamID))\r
                         addParameterChangeToMidiBuffer (offsetSamples, vstParamID, value);\r
                    #endif\r
                     else\r
@@ -2567,6 +2581,10 @@ private:
 \r
             for (int bus = 0; bus < n && totalOutputChans < plugInOutputChannels; ++bus)\r
             {\r
+                if (auto* busObject = pluginInstance->getBus (false, bus))\r
+                    if (! busObject->isEnabled())\r
+                        continue;\r
+\r
                 if (bus < vstOutputs)\r
                 {\r
                     if (auto** const busChannels = getPointerForAudioBus<FloatType> (data.outputs[bus]))\r
@@ -2608,6 +2626,10 @@ private:
 \r
             for (int bus = 0; bus < n && totalInputChans < plugInInputChannels; ++bus)\r
             {\r
+                if (auto* busObject = pluginInstance->getBus (true, bus))\r
+                    if (! busObject->isEnabled())\r
+                        continue;\r
+\r
                 if (bus < vstInputs)\r
                 {\r
                     if (auto** const busChannels = getPointerForAudioBus<FloatType> (data.inputs[bus]))\r
index d884d0ac9c60c7962118c7b82bab495729470eaf..95b70c234ce0577f64aa3f7285e778947a730d1e 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_audio_plugin_client\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE audio plugin wrapper classes\r
-  description:      Classes for building VST, VST3, AudioUnit, AAX and RTAS plugins.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
+  ID:                 juce_audio_plugin_client\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE audio plugin wrapper classes\r
+  description:        Classes for building VST, VST3, AudioUnit, AAX and RTAS plugins.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
 \r
-  dependencies:     juce_gui_basics, juce_audio_basics, juce_audio_processors\r
+  dependencies:       juce_gui_basics, juce_audio_basics, juce_audio_processors\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
 /** Config: JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS\r
 \r
     Enable this if you want JUCE to use parameter ids which are compatible\r
-    with Studio One. Studio One ignores any parameter ids which are negative.\r
+    with Studio One, as Studio One ignores any parameter ids which are negative.\r
     Enabling this option will make JUCE generate only positive parameter ids.\r
     Note that if you have already released a plug-in prior to JUCE 4.3.0 then\r
-    enabling this will change your parameter ids making your plug-in\r
-    incompatible to old automation data.\r
+    enabling this will change your parameter ids, making your plug-in\r
+    incompatible with old automation data.\r
 */\r
 #ifndef JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS\r
  #define JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS 1\r
 #endif\r
 \r
+/** Config: JUCE_AU_WRAPPERS_SAVE_PROGRAM_STATES\r
+\r
+    Enable this if you want to receive get/setProgramStateInformation calls,\r
+    instead of get/setStateInformation calls, from the AU and AUv3 plug-in\r
+    wrappers. In JUCE version 5.4.5 and earlier this was the default behaviour,\r
+    so if you have modified the default implementations of get/setProgramStateInformation\r
+    (where the default implementations simply call through to get/setStateInformation)\r
+    then you may need to enable this configuration option to maintain backwards\r
+    compatibility with previously saved state.\r
+*/\r
+#ifndef JUCE_AU_WRAPPERS_SAVE_PROGRAM_STATES\r
+ #define JUCE_AU_WRAPPERS_SAVE_PROGRAM_STATES 0\r
+#endif\r
+\r
 /** Config: JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE\r
 \r
     Enable this if you want your standalone plugin window to use kiosk mode.\r
index 4fcd685e5f74fb98c582b3a164f2c98af7715848..72623a82f88056cf60c72d1d3cb4c769ca036069 100644 (file)
@@ -25,7 +25,7 @@
 */\r
 \r
 #define UseExtendedThingResource 1\r
-#include <AudioUnit/AudioUnit.r>\r
+#include <AudioUnit.r>\r
 \r
 //==============================================================================\r
 /*  The AppConfig.h file should be a file in your project, containing info to describe the\r
index 2edb687f1130fe103b5f0a226cfaad30331da495..5b83f67116fdfa9c688d5b756b30c4ca6b0d0df0 100644 (file)
@@ -24,6 +24,8 @@
   ==============================================================================\r
 */\r
 \r
+#if JucePlugin_Build_AU\r
+\r
 #ifdef __clang__\r
  #pragma clang diagnostic push\r
  #pragma clang diagnostic ignored "-Wparentheses"\r
@@ -43,6 +45,9 @@
  #if __has_warning("-Wnullable-to-nonnull-conversion")\r
   #pragma clang diagnostic ignored "-Wnullable-to-nonnull-conversion"\r
  #endif\r
+ #if __has_warning("-Wignored-qualifiers")\r
+  #pragma clang diagnostic ignored "-Wignored-qualifiers"\r
+ #endif\r
 #endif\r
 \r
 // From MacOS 10.13 and iOS 11 Apple has (sensibly!) stopped defining a whole\r
@@ -81,3 +86,5 @@
 #ifdef __clang__\r
  #pragma clang diagnostic pop\r
 #endif\r
+\r
+#endif\r
index bd8ad9228428ea0c55013e3ddc41469b84b8e707..19fa722a550356a92da85f78489fb85bcc4bcce7 100644 (file)
@@ -24,6 +24,8 @@
   ==============================================================================\r
 */\r
 \r
+#if JucePlugin_Build_Standalone\r
+\r
 #if ! JUCE_MODULE_AVAILABLE_juce_audio_utils\r
  #error To compile AudioUnitv3 and/or Standalone plug-ins, you need to add the juce_audio_utils and juce_audio_devices modules!\r
 #endif\r
@@ -42,3 +44,5 @@
 #endif\r
 \r
 JUCE_MAIN_FUNCTION_DEFINITION\r
+\r
+#endif\r
index 3607a4418e6964baf77ce651de8803c34ae3d163..11f5d8ff2675f58ed1900ff935bd9f550e23d0f0 100644 (file)
@@ -77,6 +77,7 @@ public:
         MuseReceptorGeneric,        /**< Represents Muse Receptor. */\r
         pluginval,                  /**< Represents pluginval. */\r
         Reaper,                     /**< Represents Cockos Reaper. */\r
+        Reason,                     /**< Represents Reason. */\r
         Renoise,                    /**< Represents Renoise. */\r
         SADiE,                      /**< Represents SADiE. */\r
         SteinbergCubase4,           /**< Represents Steinberg Cubase 4. */\r
@@ -89,6 +90,7 @@ public:
         SteinbergCubase9,           /**< Represents Steinberg Cubase 9. */\r
         SteinbergCubase9_5,         /**< Represents Steinberg Cubase 9.5. */\r
         SteinbergCubase10,          /**< Represents Steinberg Cubase 10. */\r
+        SteinbergCubase10_5,        /**< Represents Steinberg Cubase 10.5. */\r
         SteinbergCubaseGeneric,     /**< Represents Steinberg Cubase. */\r
         SteinbergNuendo3,           /**< Represents Steinberg Nuendo 3. */\r
         SteinbergNuendo4,           /**< Represents Steinberg Nuendo 4. */\r
@@ -105,6 +107,7 @@ public:
         TracktionGeneric,           /**< Represents Tracktion. */\r
         TracktionWaveform,          /**< Represents Tracktion Waveform. */\r
         VBVSTScanner,               /**< Represents VB Audio VST Scanner. */\r
+        ViennaEnsemblePro,          /**< Represents Vienna Ensemble Pro. */\r
         WaveBurner                  /**< Represents Apple WaveBurner. */\r
     };\r
 \r
@@ -112,7 +115,8 @@ public:
 \r
     //==============================================================================\r
     /** Returns true if the host is any version of Ableton Live. */\r
-    bool isAbletonLive() const noexcept       { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8 || type == AbletonLive9 || type == AbletonLive10 || type == AbletonLiveGeneric; }\r
+    bool isAbletonLive() const noexcept       { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8\r
+                                                      || type == AbletonLive9 || type == AbletonLive10 || type == AbletonLiveGeneric; }\r
     /** Returns true if the host is Adobe Audition. */\r
     bool isAdobeAudition() const noexcept     { return type == AdobeAudition; }\r
     /** Returns true if the host is Ardour. */\r
@@ -120,7 +124,9 @@ public:
     /** Returns true if the host is Bitwig Studio. */\r
     bool isBitwigStudio() const noexcept      { return type == BitwigStudio; }\r
     /** Returns true if the host is any version of Steinberg Cubase. */\r
-    bool isCubase() const noexcept            { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6 || type == SteinbergCubase7 || type == SteinbergCubase8 || type == SteinbergCubase8_5 || type == SteinbergCubase9 || type == SteinbergCubase9_5 || type == SteinbergCubase10 || type == SteinbergCubaseGeneric; }\r
+    bool isCubase() const noexcept            { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6\r
+                                                      || type == SteinbergCubase7 || type == SteinbergCubase8 || type == SteinbergCubase8_5 || type == SteinbergCubase9\r
+                                                      || type == SteinbergCubase9_5 || type == SteinbergCubase10 || type == SteinbergCubase10_5 || type == SteinbergCubaseGeneric; }\r
     /** Returns true if the host is Steinberg Cubase 7 or later. */\r
     bool isCubase7orLater() const noexcept    { return isCubase() && ! (type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase6); }\r
     /** Returns true if the host is Steinberg Cubase 5 Bridged. */\r
@@ -155,6 +161,8 @@ public:
     bool isReceptor() const noexcept          { return type == MuseReceptorGeneric; }\r
     /** Returns true if the host is Cockos Reaper. */\r
     bool isReaper() const noexcept            { return type == Reaper; }\r
+    /** Returns true if the host is Reason. */\r
+    bool isReason() const noexcept            { return type == Reason; }\r
     /** Returns true if the host is Renoise. */\r
     bool isRenoise() const noexcept           { return type == Renoise; }\r
     /** Returns true if the host is SADiE. */\r
@@ -177,6 +185,8 @@ public:
     bool isTracktionWaveform() const noexcept { return type == TracktionWaveform; }\r
     /** Returns true if the host is VB Audio VST Scanner. */\r
     bool isVBVSTScanner() const noexcept      { return type == VBVSTScanner; }\r
+    /** Returns true if the host is Vienna Ensemble Pro. */\r
+    bool isViennaEnsemblePro() const noexcept { return type == ViennaEnsemblePro; }\r
     /** Returns true if the host is Apple WaveBurner. */\r
     bool isWaveBurner() const noexcept        { return type == WaveBurner; }\r
     /** Returns true if the host is any version of Steinberg WaveLab. */\r
@@ -218,6 +228,7 @@ public:
             case MergingPyramix:           return "Pyramix";\r
             case MuseReceptorGeneric:      return "Muse Receptor";\r
             case Reaper:                   return "Reaper";\r
+            case Reason:                   return "Reason";\r
             case Renoise:                  return "Renoise";\r
             case SADiE:                    return "SADiE";\r
             case SteinbergCubase4:         return "Steinberg Cubase 4";\r
@@ -230,6 +241,7 @@ public:
             case SteinbergCubase9:         return "Steinberg Cubase 9";\r
             case SteinbergCubase9_5:       return "Steinberg Cubase 9.5";\r
             case SteinbergCubase10:        return "Steinberg Cubase 10";\r
+            case SteinbergCubase10_5:      return "Steinberg Cubase 10.5";\r
             case SteinbergCubaseGeneric:   return "Steinberg Cubase";\r
             case SteinbergNuendo3:         return "Steinberg Nuendo 3";\r
             case SteinbergNuendo4:         return "Steinberg Nuendo 4";\r
@@ -246,6 +258,7 @@ public:
             case TracktionGeneric:         return "Tracktion";\r
             case TracktionWaveform:        return "Tracktion Waveform";\r
             case VBVSTScanner:             return "VBVSTScanner";\r
+            case ViennaEnsemblePro:        return "Vienna Ensemble Pro";\r
             case WaveBurner:               return "WaveBurner";\r
             default:                       break;\r
         }\r
@@ -299,107 +312,114 @@ private:
         auto hostFilename = File (hostPath).getFileName();\r
 \r
        #if JUCE_MAC\r
-        if (hostPath.containsIgnoreCase       ("Final Cut Pro.app")) return FinalCut;\r
-        if (hostPath.containsIgnoreCase       ("Final Cut Pro Trial.app")) return FinalCut;\r
-        if (hostPath.containsIgnoreCase       ("Live 6."))           return AbletonLive6;\r
-        if (hostPath.containsIgnoreCase       ("Live 7."))           return AbletonLive7;\r
-        if (hostPath.containsIgnoreCase       ("Live 8."))           return AbletonLive8;\r
-        if (hostPath.containsIgnoreCase       ("Live 9."))           return AbletonLive9;\r
-        if (hostPath.containsIgnoreCase       ("Live 10."))          return AbletonLive10;\r
-        if (hostFilename.containsIgnoreCase   ("Live"))              return AbletonLiveGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("Adobe Premiere"))    return AdobePremierePro;\r
-        if (hostFilename.containsIgnoreCase   ("GarageBand"))        return AppleGarageBand;\r
-        if (hostFilename.containsIgnoreCase   ("Logic"))             return AppleLogic;\r
-        if (hostFilename.containsIgnoreCase   ("MainStage"))         return AppleMainStage;\r
-        if (hostFilename.containsIgnoreCase   ("Pro Tools"))         return AvidProTools;\r
-        if (hostFilename.containsIgnoreCase   ("Nuendo 3"))          return SteinbergNuendo3;\r
-        if (hostFilename.containsIgnoreCase   ("Nuendo 4"))          return SteinbergNuendo4;\r
-        if (hostFilename.containsIgnoreCase   ("Nuendo 5"))          return SteinbergNuendo5;\r
-        if (hostFilename.containsIgnoreCase   ("Nuendo"))            return SteinbergNuendoGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase 4"))          return SteinbergCubase4;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase 5"))          return SteinbergCubase5;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase 6"))          return SteinbergCubase6;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase 7"))          return SteinbergCubase7;\r
-        if (hostPath.containsIgnoreCase       ("Cubase 8.app"))      return SteinbergCubase8;\r
-        if (hostPath.containsIgnoreCase       ("Cubase 8.5.app"))    return SteinbergCubase8_5;\r
-        if (hostPath.containsIgnoreCase       ("Cubase 9.app"))      return SteinbergCubase9;\r
-        if (hostPath.containsIgnoreCase       ("Cubase 9.5.app"))    return SteinbergCubase9_5;\r
-        if (hostPath.containsIgnoreCase       ("Cubase 10.app"))     return SteinbergCubase10;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase"))            return SteinbergCubaseGeneric;\r
-        if (hostPath.containsIgnoreCase       ("Wavelab 7"))         return SteinbergWavelab7;\r
-        if (hostPath.containsIgnoreCase       ("Wavelab 8"))         return SteinbergWavelab8;\r
-        if (hostFilename.containsIgnoreCase   ("Wavelab"))           return SteinbergWavelabGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("WaveBurner"))        return WaveBurner;\r
-        if (hostPath.containsIgnoreCase       ("Digital Performer")) return DigitalPerformer;\r
-        if (hostFilename.containsIgnoreCase   ("reaper"))            return Reaper;\r
-        if (hostPath.containsIgnoreCase       ("Studio One"))        return StudioOne;\r
-        if (hostFilename.startsWithIgnoreCase ("Waveform"))          return TracktionWaveform;\r
-        if (hostPath.containsIgnoreCase       ("Tracktion 3"))       return Tracktion3;\r
-        if (hostFilename.containsIgnoreCase   ("Tracktion"))         return TracktionGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("Renoise"))           return Renoise;\r
-        if (hostFilename.containsIgnoreCase   ("Resolve"))           return DaVinciResolve;\r
-        if (hostFilename.startsWith           ("Bitwig"))            return BitwigStudio;\r
-        if (hostFilename.containsIgnoreCase   ("OsxFL"))             return FruityLoops;\r
-        if (hostFilename.containsIgnoreCase   ("pluginval"))         return pluginval;\r
-        if (hostFilename.containsIgnoreCase   ("AudioPluginHost"))   return JUCEPluginHost;\r
+        if (hostPath.containsIgnoreCase       ("Final Cut Pro.app"))        return FinalCut;\r
+        if (hostPath.containsIgnoreCase       ("Final Cut Pro Trial.app"))  return FinalCut;\r
+        if (hostPath.containsIgnoreCase       ("Live 6"))                   return AbletonLive6;\r
+        if (hostPath.containsIgnoreCase       ("Live 7"))                   return AbletonLive7;\r
+        if (hostPath.containsIgnoreCase       ("Live 8"))                   return AbletonLive8;\r
+        if (hostPath.containsIgnoreCase       ("Live 9"))                   return AbletonLive9;\r
+        if (hostPath.containsIgnoreCase       ("Live 10"))                  return AbletonLive10;\r
+        if (hostFilename.containsIgnoreCase   ("Live"))                     return AbletonLiveGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("Adobe Premiere"))           return AdobePremierePro;\r
+        if (hostFilename.containsIgnoreCase   ("GarageBand"))               return AppleGarageBand;\r
+        if (hostFilename.containsIgnoreCase   ("Logic"))                    return AppleLogic;\r
+        if (hostFilename.containsIgnoreCase   ("MainStage"))                return AppleMainStage;\r
+        if (hostFilename.containsIgnoreCase   ("Pro Tools"))                return AvidProTools;\r
+        if (hostFilename.containsIgnoreCase   ("Nuendo 3"))                 return SteinbergNuendo3;\r
+        if (hostFilename.containsIgnoreCase   ("Nuendo 4"))                 return SteinbergNuendo4;\r
+        if (hostFilename.containsIgnoreCase   ("Nuendo 5"))                 return SteinbergNuendo5;\r
+        if (hostFilename.containsIgnoreCase   ("Nuendo"))                   return SteinbergNuendoGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase 4"))                 return SteinbergCubase4;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase 5"))                 return SteinbergCubase5;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase 6"))                 return SteinbergCubase6;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase 7"))                 return SteinbergCubase7;\r
+        if (hostPath.containsIgnoreCase       ("Cubase 8.app"))             return SteinbergCubase8;\r
+        if (hostPath.containsIgnoreCase       ("Cubase 8.5.app"))           return SteinbergCubase8_5;\r
+        if (hostPath.containsIgnoreCase       ("Cubase 9.app"))             return SteinbergCubase9;\r
+        if (hostPath.containsIgnoreCase       ("Cubase 9.5.app"))           return SteinbergCubase9_5;\r
+        if (hostPath.containsIgnoreCase       ("Cubase 10.app"))            return SteinbergCubase10;\r
+        if (hostPath.containsIgnoreCase       ("Cubase 10.5.app"))          return SteinbergCubase10_5;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase"))                   return SteinbergCubaseGeneric;\r
+        if (hostPath.containsIgnoreCase       ("Wavelab 7"))                return SteinbergWavelab7;\r
+        if (hostPath.containsIgnoreCase       ("Wavelab 8"))                return SteinbergWavelab8;\r
+        if (hostFilename.containsIgnoreCase   ("Wavelab"))                  return SteinbergWavelabGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("WaveBurner"))               return WaveBurner;\r
+        if (hostPath.containsIgnoreCase       ("Digital Performer"))        return DigitalPerformer;\r
+        if (hostFilename.containsIgnoreCase   ("reaper"))                   return Reaper;\r
+        if (hostFilename.containsIgnoreCase   ("Reason"))                   return Reason;\r
+        if (hostPath.containsIgnoreCase       ("Studio One"))               return StudioOne;\r
+        if (hostFilename.startsWithIgnoreCase ("Waveform"))                 return TracktionWaveform;\r
+        if (hostPath.containsIgnoreCase       ("Tracktion 3"))              return Tracktion3;\r
+        if (hostFilename.containsIgnoreCase   ("Tracktion"))                return TracktionGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("Renoise"))                  return Renoise;\r
+        if (hostFilename.containsIgnoreCase   ("Resolve"))                  return DaVinciResolve;\r
+        if (hostFilename.startsWith           ("Bitwig"))                   return BitwigStudio;\r
+        if (hostFilename.containsIgnoreCase   ("OsxFL"))                    return FruityLoops;\r
+        if (hostFilename.containsIgnoreCase   ("pluginval"))                return pluginval;\r
+        if (hostFilename.containsIgnoreCase   ("AudioPluginHost"))          return JUCEPluginHost;\r
+        if (hostFilename.containsIgnoreCase   ("Vienna Ensemble Pro"))      return ViennaEnsemblePro;\r
 \r
        #elif JUCE_WINDOWS\r
-        if (hostFilename.containsIgnoreCase   ("Live 6."))           return AbletonLive6;\r
-        if (hostFilename.containsIgnoreCase   ("Live 7."))           return AbletonLive7;\r
-        if (hostFilename.containsIgnoreCase   ("Live 8."))           return AbletonLive8;\r
-        if (hostFilename.containsIgnoreCase   ("Live 9."))           return AbletonLive9;\r
-        if (hostFilename.containsIgnoreCase   ("Live 10."))          return AbletonLive10;\r
-        if (hostFilename.containsIgnoreCase   ("Live "))             return AbletonLiveGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("Audition"))          return AdobeAudition;\r
-        if (hostFilename.containsIgnoreCase   ("Adobe Premiere"))    return AdobePremierePro;\r
-        if (hostFilename.containsIgnoreCase   ("ProTools"))          return AvidProTools;\r
-        if (hostPath.containsIgnoreCase       ("SONAR 8"))           return CakewalkSonar8;\r
-        if (hostFilename.containsIgnoreCase   ("SONAR"))             return CakewalkSonarGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("Cakewalk.exe"))      return CakewalkByBandlab;\r
-        if (hostFilename.containsIgnoreCase   ("GarageBand"))        return AppleGarageBand;\r
-        if (hostFilename.containsIgnoreCase   ("Logic"))             return AppleLogic;\r
-        if (hostFilename.containsIgnoreCase   ("MainStage"))         return AppleMainStage;\r
-        if (hostFilename.startsWithIgnoreCase ("Waveform"))          return TracktionWaveform;\r
-        if (hostPath.containsIgnoreCase       ("Tracktion 3"))       return Tracktion3;\r
-        if (hostFilename.containsIgnoreCase   ("Tracktion"))         return TracktionGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("reaper"))            return Reaper;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase4"))           return SteinbergCubase4;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase5"))           return SteinbergCubase5;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase6"))           return SteinbergCubase6;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase7"))           return SteinbergCubase7;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase8.exe"))       return SteinbergCubase8;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase8.5.exe"))     return SteinbergCubase8_5;\r
+        if (hostFilename.containsIgnoreCase   ("Live 6"))                return AbletonLive6;\r
+        if (hostFilename.containsIgnoreCase   ("Live 7"))                return AbletonLive7;\r
+        if (hostFilename.containsIgnoreCase   ("Live 8"))                return AbletonLive8;\r
+        if (hostFilename.containsIgnoreCase   ("Live 9"))                return AbletonLive9;\r
+        if (hostFilename.containsIgnoreCase   ("Live 10"))               return AbletonLive10;\r
+        if (hostFilename.containsIgnoreCase   ("Live "))                 return AbletonLiveGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("Audition"))              return AdobeAudition;\r
+        if (hostFilename.containsIgnoreCase   ("Adobe Premiere"))        return AdobePremierePro;\r
+        if (hostFilename.containsIgnoreCase   ("ProTools"))              return AvidProTools;\r
+        if (hostPath.containsIgnoreCase       ("SONAR 8"))               return CakewalkSonar8;\r
+        if (hostFilename.containsIgnoreCase   ("SONAR"))                 return CakewalkSonarGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("Cakewalk.exe"))          return CakewalkByBandlab;\r
+        if (hostFilename.containsIgnoreCase   ("GarageBand"))            return AppleGarageBand;\r
+        if (hostFilename.containsIgnoreCase   ("Logic"))                 return AppleLogic;\r
+        if (hostFilename.containsIgnoreCase   ("MainStage"))             return AppleMainStage;\r
+        if (hostFilename.startsWithIgnoreCase ("Waveform"))              return TracktionWaveform;\r
+        if (hostPath.containsIgnoreCase       ("Tracktion 3"))           return Tracktion3;\r
+        if (hostFilename.containsIgnoreCase   ("Tracktion"))             return TracktionGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("reaper"))                return Reaper;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase4"))               return SteinbergCubase4;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase5"))               return SteinbergCubase5;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase6"))               return SteinbergCubase6;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase7"))               return SteinbergCubase7;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase8.exe"))           return SteinbergCubase8;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase8.5.exe"))         return SteinbergCubase8_5;\r
         // Later version of Cubase scan plug-ins with a separate executable "vst2xscanner"\r
         if (hostFilename.containsIgnoreCase   ("Cubase9.5.exe")\r
-            || hostPath.containsIgnoreCase    ("Cubase 9.5"))        return SteinbergCubase9_5;\r
+            || hostPath.containsIgnoreCase    ("Cubase 9.5"))            return SteinbergCubase9_5;\r
         if (hostFilename.containsIgnoreCase   ("Cubase9.exe")\r
-            || hostPath.containsIgnoreCase    ("Cubase 9"))          return SteinbergCubase9;\r
+            || hostPath.containsIgnoreCase    ("Cubase 9"))              return SteinbergCubase9;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase10.5.exe")\r
+            || hostPath.containsIgnoreCase    ("Cubase 10.5"))           return SteinbergCubase10_5;\r
         if (hostFilename.containsIgnoreCase   ("Cubase10.exe")\r
-            || hostPath.containsIgnoreCase    ("Cubase 10"))         return SteinbergCubase10;\r
-        if (hostFilename.containsIgnoreCase   ("Cubase"))            return SteinbergCubaseGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("VSTBridgeApp"))      return SteinbergCubase5Bridged;\r
-        if (hostPath.containsIgnoreCase       ("Wavelab 5"))         return SteinbergWavelab5;\r
-        if (hostPath.containsIgnoreCase       ("Wavelab 6"))         return SteinbergWavelab6;\r
-        if (hostPath.containsIgnoreCase       ("Wavelab 7"))         return SteinbergWavelab7;\r
-        if (hostPath.containsIgnoreCase       ("Wavelab 8"))         return SteinbergWavelab8;\r
-        if (hostPath.containsIgnoreCase       ("Nuendo"))            return SteinbergNuendoGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("Wavelab"))           return SteinbergWavelabGeneric;\r
-        if (hostFilename.containsIgnoreCase   ("TestHost"))          return SteinbergTestHost;\r
-        if (hostFilename.containsIgnoreCase   ("rm-host"))           return MuseReceptorGeneric;\r
-        if (hostFilename.startsWith           ("FL"))                return FruityLoops;\r
-        if (hostFilename.contains             ("ilbridge."))         return FruityLoops;\r
-        if (hostPath.containsIgnoreCase       ("Studio One"))        return StudioOne;\r
-        if (hostPath.containsIgnoreCase       ("Digital Performer")) return DigitalPerformer;\r
-        if (hostFilename.containsIgnoreCase   ("VST_Scanner"))       return VBVSTScanner;\r
-        if (hostPath.containsIgnoreCase       ("Merging Technologies")) return MergingPyramix;\r
-        if (hostFilename.startsWithIgnoreCase ("Sam"))               return MagixSamplitude;\r
-        if (hostFilename.startsWithIgnoreCase ("Sequoia"))           return MagixSequoia;\r
-        if (hostFilename.containsIgnoreCase   ("Renoise"))           return Renoise;\r
-        if (hostFilename.containsIgnoreCase   ("Resolve"))           return DaVinciResolve;\r
-        if (hostPath.containsIgnoreCase       ("Bitwig Studio"))     return BitwigStudio;\r
-        if (hostFilename.containsIgnoreCase   ("Sadie"))             return SADiE;\r
-        if (hostFilename.containsIgnoreCase   ("pluginval"))         return pluginval;\r
-        if (hostFilename.containsIgnoreCase   ("AudioPluginHost"))   return JUCEPluginHost;\r
+            || hostPath.containsIgnoreCase    ("Cubase 10"))             return SteinbergCubase10;\r
+        if (hostFilename.containsIgnoreCase   ("Cubase"))                return SteinbergCubaseGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("VSTBridgeApp"))          return SteinbergCubase5Bridged;\r
+        if (hostPath.containsIgnoreCase       ("Wavelab 5"))             return SteinbergWavelab5;\r
+        if (hostPath.containsIgnoreCase       ("Wavelab 6"))             return SteinbergWavelab6;\r
+        if (hostPath.containsIgnoreCase       ("Wavelab 7"))             return SteinbergWavelab7;\r
+        if (hostPath.containsIgnoreCase       ("Wavelab 8"))             return SteinbergWavelab8;\r
+        if (hostPath.containsIgnoreCase       ("Nuendo"))                return SteinbergNuendoGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("Wavelab"))               return SteinbergWavelabGeneric;\r
+        if (hostFilename.containsIgnoreCase   ("TestHost"))              return SteinbergTestHost;\r
+        if (hostFilename.containsIgnoreCase   ("rm-host"))               return MuseReceptorGeneric;\r
+        if (hostFilename.startsWith           ("FL"))                    return FruityLoops;\r
+        if (hostFilename.contains             ("ilbridge."))             return FruityLoops;\r
+        if (hostPath.containsIgnoreCase       ("Studio One"))            return StudioOne;\r
+        if (hostPath.containsIgnoreCase       ("Digital Performer"))     return DigitalPerformer;\r
+        if (hostFilename.containsIgnoreCase   ("VST_Scanner"))           return VBVSTScanner;\r
+        if (hostPath.containsIgnoreCase       ("Merging Technologies"))  return MergingPyramix;\r
+        if (hostFilename.startsWithIgnoreCase ("Sam"))                   return MagixSamplitude;\r
+        if (hostFilename.startsWithIgnoreCase ("Sequoia"))               return MagixSequoia;\r
+        if (hostFilename.containsIgnoreCase   ("Reason"))                return Reason;\r
+        if (hostFilename.containsIgnoreCase   ("Renoise"))               return Renoise;\r
+        if (hostFilename.containsIgnoreCase   ("Resolve"))               return DaVinciResolve;\r
+        if (hostPath.containsIgnoreCase       ("Bitwig Studio"))         return BitwigStudio;\r
+        if (hostFilename.containsIgnoreCase   ("Sadie"))                 return SADiE;\r
+        if (hostFilename.containsIgnoreCase   ("pluginval"))             return pluginval;\r
+        if (hostFilename.containsIgnoreCase   ("AudioPluginHost"))       return JUCEPluginHost;\r
+        if (hostFilename.containsIgnoreCase   ("Vienna Ensemble Pro"))   return ViennaEnsemblePro;\r
 \r
        #elif JUCE_LINUX\r
         if (hostFilename.containsIgnoreCase   ("Ardour"))            return Ardour;\r
index 3b7d8d31168b5a35c83d4fddf86e67a5d953bea8..8ae1aa6ed2054f9a9017ae41ae0382d7ff0b14c1 100644 (file)
@@ -78,7 +78,7 @@ public:
         errorMessage string.\r
 \r
         If you intend to instantiate a AudioUnit v3 plug-in then you must either\r
-        use the non-blocking asynchrous version below - or call this method from a\r
+        use the non-blocking asynchronous version below - or call this method from a\r
         thread other than the message thread and without blocking the message\r
         thread.\r
     */\r
@@ -90,7 +90,7 @@ public:
         all the formats that this manager knows about.\r
 \r
         The caller must supply a callback object which will be called when\r
-        the instantantiation has completed.\r
+        the instantiation has completed.\r
 \r
         If it can't load the plugin then the callback function will be called\r
         passing a nullptr as the instance argument along with an error message.\r
@@ -105,7 +105,7 @@ public:
         the callback function.\r
 \r
         If you intend to instantiate a AudioUnit v3 plug-in then you must use\r
-        this non-blocking asynchrous version - or call the synchrous method\r
+        this non-blocking asynchronous version - or call the synchronous method\r
         from an auxiliary thread.\r
     */\r
     void createPluginInstanceAsync (const PluginDescription& description,\r
index 33974d48713f6d0a769ecfcfe01094f6ef9e991e..0136e58bafebae06a1c9225c02a1172d51ae00ca 100644 (file)
@@ -236,36 +236,53 @@ namespace AudioUnitFormatHelpers
                 UseResFile (resFileId);\r
 \r
                 const OSType thngType = stringToOSType ("thng");\r
+                auto numResources = Count1Resources (thngType);\r
 \r
-                for (ResourceIndex i = 1; i <= Count1Resources (thngType); ++i)\r
+                if (numResources > 0)\r
                 {\r
-                    if (Handle h = Get1IndResource (thngType, i))\r
+                    for (ResourceIndex i = 1; i <= numResources; ++i)\r
                     {\r
-                        HLock (h);\r
-                        const uint32* const types = (const uint32*) *h;\r
-\r
-                        if (types[0] == kAudioUnitType_MusicDevice\r
-                             || types[0] == kAudioUnitType_MusicEffect\r
-                             || types[0] == kAudioUnitType_Effect\r
-                             || types[0] == kAudioUnitType_Generator\r
-                             || types[0] == kAudioUnitType_Panner\r
-                             || types[0] == kAudioUnitType_Mixer\r
-                             || types[0] == kAudioUnitType_MIDIProcessor)\r
+                        if (Handle h = Get1IndResource (thngType, i))\r
                         {\r
-                            desc.componentType = types[0];\r
-                            desc.componentSubType = types[1];\r
-                            desc.componentManufacturer = types[2];\r
+                            HLock (h);\r
+                            const uint32* const types = (const uint32*) *h;\r
+\r
+                            if (types[0] == kAudioUnitType_MusicDevice\r
+                                 || types[0] == kAudioUnitType_MusicEffect\r
+                                 || types[0] == kAudioUnitType_Effect\r
+                                 || types[0] == kAudioUnitType_Generator\r
+                                 || types[0] == kAudioUnitType_Panner\r
+                                 || types[0] == kAudioUnitType_Mixer\r
+                                 || types[0] == kAudioUnitType_MIDIProcessor)\r
+                            {\r
+                                desc.componentType = types[0];\r
+                                desc.componentSubType = types[1];\r
+                                desc.componentManufacturer = types[2];\r
 \r
-                            if (AudioComponent comp = AudioComponentFindNext (nullptr, &desc))\r
-                                getNameAndManufacturer (comp, name, manufacturer);\r
+                                if (AudioComponent comp = AudioComponentFindNext (nullptr, &desc))\r
+                                    getNameAndManufacturer (comp, name, manufacturer);\r
 \r
-                            break;\r
-                        }\r
+                                break;\r
+                            }\r
 \r
-                        HUnlock (h);\r
-                        ReleaseResource (h);\r
+                            HUnlock (h);\r
+                            ReleaseResource (h);\r
+                        }\r
                     }\r
                 }\r
+                else\r
+                {\r
+                    NSBundle* bundle = [[NSBundle alloc] initWithPath: (NSString*) fileOrIdentifier.toCFString()];\r
+\r
+                    NSArray* audioComponents = [bundle objectForInfoDictionaryKey: @"AudioComponents"];\r
+                    NSDictionary* dict = audioComponents[0];\r
+\r
+                    desc.componentManufacturer = stringToOSType (nsStringToJuce ((NSString*) [dict valueForKey: @"manufacturer"]));\r
+                    desc.componentType         = stringToOSType (nsStringToJuce ((NSString*) [dict valueForKey: @"type"]));\r
+                    desc.componentSubType      = stringToOSType (nsStringToJuce ((NSString*) [dict valueForKey: @"subtype"]));\r
+\r
+                    [bundle release];\r
+                }\r
 \r
                 CFBundleCloseBundleResourceMap (bundleRef, resFileId);\r
                 CFRelease (bundleRef);\r
@@ -781,19 +798,19 @@ public:
 \r
                         // try to convert the layout into a tag\r
                         actualTag = CoreAudioLayouts::toCoreAudio (CoreAudioLayouts::fromCoreAudio (layout));\r
-                    }\r
 \r
-                    if (actualTag != requestedTag)\r
-                    {\r
-                        zerostruct (layout);\r
-                        layout.mChannelLayoutTag = requestedTag;\r
+                        if (actualTag != requestedTag)\r
+                        {\r
+                            zerostruct (layout);\r
+                            layout.mChannelLayoutTag = requestedTag;\r
 \r
-                        err = AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, scope, static_cast<UInt32> (i), &layout, minDataSize);\r
+                            err = AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, scope, static_cast<UInt32> (i), &layout, minDataSize);\r
 \r
-                        // only bail out if the plug-in claims to support layouts\r
-                        // See AudioUnit headers on kAudioUnitProperty_AudioChannelLayout\r
-                        if (err != noErr && supportsLayouts && isInitialized)\r
-                            return false;\r
+                            // only bail out if the plug-in claims to support layouts\r
+                            // See AudioUnit headers on kAudioUnitProperty_AudioChannelLayout\r
+                            if (err != noErr && supportsLayouts && isInitialized)\r
+                                return false;\r
+                        }\r
                     }\r
                 }\r
             }\r
@@ -1239,7 +1256,18 @@ public:
     {\r
         AUPreset current;\r
         current.presetNumber = newIndex;\r
-        current.presetName = CFSTR("");\r
+\r
+        CFArrayRef presets;\r
+        UInt32 sz = sizeof (CFArrayRef);\r
+\r
+        if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_FactoryPresets,\r
+                                  kAudioUnitScope_Global, 0, &presets, &sz) == noErr)\r
+        {\r
+            if (auto* p = (const AUPreset*) CFArrayGetValueAtIndex (presets, newIndex))\r
+                current.presetName = p->presetName;\r
+\r
+            CFRelease (presets);\r
+        }\r
 \r
         AudioUnitSetProperty (audioUnit, kAudioUnitProperty_PresentPreset,\r
                               kAudioUnitScope_Global, 0, &current, sizeof (AUPreset));\r
@@ -1253,12 +1281,25 @@ public:
         CFArrayRef presets;\r
         UInt32 sz = sizeof (CFArrayRef);\r
 \r
-        if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_FactoryPresets,\r
-                                  kAudioUnitScope_Global, 0, &presets, &sz) == noErr)\r
+        if (index == -1)\r
+        {\r
+            AUPreset current;\r
+            current.presetNumber = -1;\r
+            current.presetName = CFSTR("");\r
+\r
+            UInt32 prstsz = sizeof (AUPreset);\r
+\r
+            AudioUnitGetProperty (audioUnit, kAudioUnitProperty_PresentPreset,\r
+                                  kAudioUnitScope_Global, 0, &current, &prstsz);\r
+\r
+            s = String::fromCFString (current.presetName);\r
+        }\r
+        else if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_FactoryPresets,\r
+                                       kAudioUnitScope_Global, 0, &presets, &sz) == noErr)\r
         {\r
             for (CFIndex i = 0; i < CFArrayGetCount (presets); ++i)\r
             {\r
-                if (const AUPreset* p = (const AUPreset*) CFArrayGetValueAtIndex (presets, i))\r
+                if (auto* p = (const AUPreset*) CFArrayGetValueAtIndex (presets, i))\r
                 {\r
                     if (p->presetNumber == index)\r
                     {\r
@@ -1791,14 +1832,23 @@ private:
 \r
             default:\r
                 if (event.mArgument.mProperty.mPropertyID == kAudioUnitProperty_ParameterList)\r
+                {\r
                     updateHostDisplay();\r
+                }\r
                 else if (event.mArgument.mProperty.mPropertyID == kAudioUnitProperty_PresentPreset)\r
+                {\r
                     sendAllParametersChangedEvents();\r
+                    updateHostDisplay();\r
+                }\r
                 else if (event.mArgument.mProperty.mPropertyID == kAudioUnitProperty_Latency)\r
+                {\r
                     updateLatency();\r
+                }\r
                 else if (event.mArgument.mProperty.mPropertyID == kAudioUnitProperty_BypassEffect)\r
+                {\r
                     if (bypassParam != nullptr)\r
                         bypassParam->setValueNotifyingHost (bypassParam->getValue());\r
+                }\r
 \r
                 break;\r
         }\r
index dbbc8e163d893b301f723b736a6c8ecb8629d77c..dc40caf601c2f5955e7acf9fea37edf89720d9eb 100644 (file)
@@ -536,7 +536,7 @@ public:
                 }\r
             }\r
 \r
-            Steinberg::Vst::Event e = { 0 };\r
+            Steinberg::Vst::Event e{};\r
 \r
             if (msg.isNoteOn())\r
             {\r
index ccdfa19a7219e8eae106a333d44dd74f5448af62..f8b1351de75a9a35eb3e994f20184c316e705ca9 100644 (file)
  #if __has_warning("-Wcast-align")\r
   #pragma clang diagnostic ignored "-Wcast-align"\r
  #endif\r
+ #if __has_warning("-Wignored-qualifiers")\r
+  #pragma clang diagnostic ignored "-Wignored-qualifiers"\r
+ #endif\r
+ #if __has_warning("-Wmissing-field-initializers")\r
+  #pragma clang diagnostic ignored "-Wmissing-field-initializers"\r
+ #endif\r
 #endif\r
 \r
 #undef DEVELOPMENT\r
index 14810fb59a995fd391de025765a014a2f183088f..4e290c5348b299739919cf427ec956b507feb5f3 100644 (file)
@@ -774,7 +774,8 @@ struct DescriptionFactory
                 }\r
             }\r
 \r
-            result = performOnDescription (desc);\r
+            if (desc.uid != 0)\r
+                result = performOnDescription (desc);\r
 \r
             if (result.failed())\r
                 break;\r
@@ -1593,9 +1594,11 @@ public:
     struct VST3Parameter final  : public Parameter\r
     {\r
         VST3Parameter (VST3PluginInstance& parent,\r
+                       int vstParameterIndex,\r
                        Steinberg::Vst::ParamID parameterID,\r
                        bool parameterIsAutomatable)\r
             : pluginInstance (parent),\r
+              vstParamIndex (vstParameterIndex),\r
               paramID (parameterID),\r
               automatable (parameterIsAutomatable)\r
         {\r
@@ -1653,19 +1656,24 @@ public:
             return Parameter::getValueForText (text);\r
         }\r
 \r
+        Vst::ParameterInfo getParameterInfo() const\r
+        {\r
+            return pluginInstance.getParameterInfoForIndex (vstParamIndex);\r
+        }\r
+\r
         float getDefaultValue() const override\r
         {\r
-            return (float) pluginInstance.getParameterInfoForIndex (getParameterIndex()).defaultNormalizedValue;\r
+            return (float) getParameterInfo().defaultNormalizedValue;\r
         }\r
 \r
         String getName (int /*maximumStringLength*/) const override\r
         {\r
-            return toString (pluginInstance.getParameterInfoForIndex (getParameterIndex()).title);\r
+            return toString (getParameterInfo().title);\r
         }\r
 \r
         String getLabel() const override\r
         {\r
-            return toString (pluginInstance.getParameterInfoForIndex (getParameterIndex()).units);\r
+            return toString (getParameterInfo().units);\r
         }\r
 \r
         bool isAutomatable() const override\r
@@ -1680,7 +1688,7 @@ public:
 \r
         int getNumSteps() const override\r
         {\r
-            auto stepCount = pluginInstance.getParameterInfoForIndex (getParameterIndex()).stepCount;\r
+            auto stepCount = getParameterInfo().stepCount;\r
             return stepCount == 0 ? AudioProcessor::getDefaultNumParameterSteps()\r
                                   : stepCount + 1;\r
         }\r
@@ -1691,6 +1699,7 @@ public:
         }\r
 \r
         VST3PluginInstance& pluginInstance;\r
+        const int vstParamIndex;\r
         const Steinberg::Vst::ParamID paramID;\r
         const bool automatable;\r
     };\r
@@ -1699,7 +1708,7 @@ public:
     VST3PluginInstance (VST3ComponentHolder* componentHolder)\r
         : AudioPluginInstance (getBusProperties (componentHolder->component)),\r
           holder (componentHolder),\r
-          inputParameterChanges (new ParamValueQueueList()),\r
+          inputParameterChanges  (new ParamValueQueueList()),\r
           outputParameterChanges (new ParamValueQueueList()),\r
           midiInputs (new MidiEventList()),\r
           midiOutputs (new MidiEventList())\r
@@ -2337,23 +2346,37 @@ public:
         JUCE_DECLARE_VST3_COM_REF_METHODS\r
         JUCE_DECLARE_VST3_COM_QUERY_METHODS\r
 \r
-        Steinberg::int32 PLUGIN_API getParameterCount() override                                { return numQueuesUsed; }\r
-        Vst::IParamValueQueue* PLUGIN_API getParameterData (Steinberg::int32 index) override    { return isPositiveAndBelow (static_cast<int> (index), numQueuesUsed) ? queues[(int) index] : nullptr; }\r
+        Steinberg::int32 PLUGIN_API getParameterCount() override\r
+        {\r
+            const ScopedLock sl (queuesLock);\r
+            return numQueuesUsed;\r
+        }\r
+\r
+        Vst::IParamValueQueue* PLUGIN_API getParameterData (Steinberg::int32 index) override\r
+        {\r
+            const ScopedLock sl (queuesLock);\r
+            return isPositiveAndBelow (static_cast<int> (index), numQueuesUsed) ? queues[(int) index] : nullptr;\r
+        }\r
 \r
         Vst::IParamValueQueue* PLUGIN_API addParameterData (const Vst::ParamID& id, Steinberg::int32& index) override\r
         {\r
+            const ScopedLock sl (queuesLock);\r
+\r
             for (int i = numQueuesUsed; --i >= 0;)\r
             {\r
-                if (queues.getUnchecked (i)->getParameterId() == id)\r
+                if (auto* q = queues.getUnchecked (i))\r
                 {\r
-                    index = (Steinberg::int32) i;\r
-                    return queues.getUnchecked (i);\r
+                    if (q->getParameterId() == id)\r
+                    {\r
+                        index = (Steinberg::int32) i;\r
+                        return q;\r
+                    }\r
                 }\r
             }\r
 \r
             index = numQueuesUsed++;\r
-            ParamValueQueue* valueQueue = (index < queues.size() ? queues[index]\r
-                                                                 : queues.add (new ParamValueQueue()));\r
+            auto* valueQueue = (index < queues.size() ? queues[index]\r
+                                                      : queues.add (new ParamValueQueue()));\r
 \r
             valueQueue->clear();\r
             valueQueue->setParamID (id);\r
@@ -2363,6 +2386,7 @@ public:
 \r
         void clearAllQueues() noexcept\r
         {\r
+            const ScopedLock sl (queuesLock);\r
             numQueuesUsed = 0;\r
         }\r
 \r
@@ -2387,18 +2411,20 @@ public:
                                                     Steinberg::int32& sampleOffset,\r
                                                     Steinberg::Vst::ParamValue& value) override\r
             {\r
-                const ScopedLock sl (pointLock);\r
+                const ScopedLock sl (points.getLock());\r
 \r
                 if (isPositiveAndBelow ((int) index, points.size()))\r
                 {\r
-                    ParamPoint e (points.getUnchecked ((int) index));\r
+                    auto e = points.getUnchecked ((int) index);\r
                     sampleOffset = e.sampleOffset;\r
                     value = e.value;\r
+\r
                     return kResultTrue;\r
                 }\r
 \r
                 sampleOffset = -1;\r
                 value = 0.0;\r
+\r
                 return kResultFalse;\r
             }\r
 \r
@@ -2406,19 +2432,12 @@ public:
                                                     Steinberg::Vst::ParamValue value,\r
                                                     Steinberg::int32& index) override\r
             {\r
-                ParamPoint p = { sampleOffset, value };\r
-\r
-                const ScopedLock sl (pointLock);\r
                 index = (Steinberg::int32) points.size();\r
-                points.add (p);\r
+                points.add ({ sampleOffset, value });\r
                 return kResultTrue;\r
             }\r
 \r
-            void clear() noexcept\r
-            {\r
-                const ScopedLock sl (pointLock);\r
-                points.clearQuick();\r
-            }\r
+            void clear() noexcept  { points.clearQuick(); }\r
 \r
         private:\r
             struct ParamPoint\r
@@ -2429,15 +2448,16 @@ public:
 \r
             Atomic<int> refCount;\r
             Vst::ParamID paramID = static_cast<Vst::ParamID> (-1);\r
-            Array<ParamPoint> points;\r
-            CriticalSection pointLock;\r
+            Array<ParamPoint, CriticalSection> points;\r
 \r
             JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamValueQueue)\r
         };\r
 \r
         Atomic<int> refCount;\r
+\r
         OwnedArray<ParamValueQueue> queues;\r
         int numQueuesUsed = 0;\r
+        CriticalSection queuesLock;\r
 \r
         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamValueQueueList)\r
     };\r
@@ -2549,7 +2569,7 @@ private:
 \r
             for (int i = 1; i < numUnits; ++i)\r
             {\r
-                Vst::UnitInfo ui = { 0 };\r
+                Vst::UnitInfo ui{};\r
                 unitInfo->getUnitInfo (i, ui);\r
                 infoMap[ui.id] = std::move (ui);\r
             }\r
@@ -2559,6 +2579,7 @@ private:
         {\r
             auto paramInfo = getParameterInfoForIndex (i);\r
             auto* param = new VST3Parameter (*this,\r
+                                             i,\r
                                              paramInfo.id,\r
                                              (paramInfo.flags & Vst::ParameterInfo::kCanAutomate) != 0);\r
 \r
@@ -2566,7 +2587,6 @@ private:
                 bypassParam = param;\r
 \r
             std::function<AudioProcessorParameterGroup*(Vst::UnitID)> findOrCreateGroup;\r
-\r
             findOrCreateGroup = [&groupMap, &infoMap, &findOrCreateGroup](Vst::UnitID groupID)\r
             {\r
                 auto existingGroup = groupMap.find (groupID);\r
@@ -2765,7 +2785,7 @@ private:
 \r
     Vst::ParameterInfo getParameterInfoForIndex (int index) const\r
     {\r
-        Vst::ParameterInfo paramInfo = { 0 };\r
+        Vst::ParameterInfo paramInfo{};\r
 \r
         if (processor != nullptr)\r
             editController->getParameterInfo (index, paramInfo);\r
@@ -2775,7 +2795,7 @@ private:
 \r
     Vst::ProgramListInfo getProgramListInfo (int index) const\r
     {\r
-        Vst::ProgramListInfo paramInfo = { 0 };\r
+        Vst::ProgramListInfo paramInfo{};\r
 \r
         if (unitInfo != nullptr)\r
             unitInfo->getProgramListInfo (index, paramInfo);\r
@@ -2791,7 +2811,7 @@ private:
             return;\r
 \r
         Vst::UnitID programUnitID;\r
-        Vst::ParameterInfo paramInfo = { 0 };\r
+        Vst::ParameterInfo paramInfo{};\r
 \r
         {\r
             int idx, num = editController->getParameterCount();\r
@@ -2810,7 +2830,7 @@ private:
 \r
         if (unitInfo != nullptr)\r
         {\r
-            Vst::UnitInfo uInfo = { 0 };\r
+            Vst::UnitInfo uInfo{};\r
             const int unitCount = unitInfo->getUnitCount();\r
 \r
             for (int idx = 0; idx < unitCount; ++idx)\r
@@ -2822,7 +2842,7 @@ private:
 \r
                     for (int j = 0; j < programListCount; ++j)\r
                     {\r
-                        Vst::ProgramListInfo programListInfo = { 0 };\r
+                        Vst::ProgramListInfo programListInfo{};\r
 \r
                         if (unitInfo->getProgramListInfo (j, programListInfo) == kResultOk\r
                               && programListInfo.id == uInfo.programListId)\r
@@ -3014,7 +3034,19 @@ tresult VST3HostContext::ContextMenu::popup (Steinberg::UCoord x, Steinberg::UCo
     PopupMenu::Options options;\r
 \r
     if (auto* ed = owner.getActiveEditor())\r
+    {\r
+       #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
+        if (auto* peer = ed->getPeer())\r
+        {\r
+            auto scale = peer->getPlatformScaleFactor();\r
+\r
+            x = roundToInt (x / scale);\r
+            y = roundToInt (y / scale);\r
+        }\r
+       #endif\r
+\r
         options = options.withTargetScreenArea (ed->getScreenBounds().translated ((int) x, (int) y).withSize (1, 1));\r
+    }\r
 \r
    #if JUCE_MODAL_LOOPS_PERMITTED\r
     // Unfortunately, Steinberg's docs explicitly say this should be modal..\r
index 85dfb785cc0a76ea51c71a811310d90aefa507f7..bdc935fc390241665df692e0c666482962000cea 100644 (file)
@@ -1213,7 +1213,7 @@ struct VSTPluginInstance     : public AudioPluginInstance,
         desc.version = getVersion();\r
         desc.numInputChannels = getTotalNumInputChannels();\r
         desc.numOutputChannels = getTotalNumOutputChannels();\r
-        desc.isInstrument = (vstEffect != nullptr && (vstEffect->flags & Vst2::effFlagsIsSynth) != 0);\r
+        desc.isInstrument = isSynthPlugin();\r
     }\r
 \r
     bool initialiseEffect (double initialSampleRate, int initialBlockSize)\r
@@ -1269,7 +1269,7 @@ struct VSTPluginInstance     : public AudioPluginInstance,
         if (getVstCategory() != Vst2::kPlugCategShell) // (workaround for Waves 5 plugins which crash during this call)\r
             updateStoredProgramNames();\r
 \r
-        wantsMidiMessages = pluginCanDo ("receiveVstMidiEvent") > 0;\r
+        wantsMidiMessages = pluginCanDo ("receiveVstMidiEvent") > 0 || isSynthPlugin();\r
 \r
        #if JUCE_MAC && JUCE_SUPPORT_CARBON\r
         usesCocoaNSView = ((unsigned int) pluginCanDo ("hasCockosViewAsConfig") & 0xffff0000ul) == 0xbeef0000ul;\r
@@ -1338,7 +1338,9 @@ struct VSTPluginInstance     : public AudioPluginInstance,
 \r
     Vst2::VstPlugCategory getVstCategory() const noexcept     { return (Vst2::VstPlugCategory) dispatch (Vst2::effGetPlugCategory, 0, 0, nullptr, 0); }\r
 \r
-    int pluginCanDo (const char* text) const     { return (int) dispatch (Vst2::effCanDo, 0, 0, (void*) text,  0); }\r
+    bool isSynthPlugin() const  { return (vstEffect != nullptr && (vstEffect->flags & Vst2::effFlagsIsSynth) != 0); }\r
+\r
+    int pluginCanDo (const char* text) const  { return (int) dispatch (Vst2::effCanDo, 0, 0, (void*) text,  0); }\r
 \r
     //==============================================================================\r
     void prepareToPlay (double rate, int samplesPerBlockExpected) override\r
@@ -1369,7 +1371,7 @@ struct VSTPluginInstance     : public AudioPluginInstance,
 \r
         if (initialised)\r
         {\r
-            wantsMidiMessages = wantsMidiMessages || (pluginCanDo ("receiveVstMidiEvent") > 0);\r
+            wantsMidiMessages = wantsMidiMessages || (pluginCanDo ("receiveVstMidiEvent") > 0) || isSynthPlugin();\r
 \r
             if (wantsMidiMessages)\r
                 midiEventsToSend.ensureSize (256);\r
@@ -2050,7 +2052,8 @@ private:
     //==============================================================================\r
     String name;\r
     CriticalSection lock;\r
-    bool wantsMidiMessages = false, initialised = false, isPowerOn = false;\r
+    std::atomic<bool> wantsMidiMessages { false };\r
+    bool initialised = false, isPowerOn = false;\r
     bool lastProcessBlockCallWasBypass = false, vstSupportsBypass = false;\r
     mutable StringArray programNames;\r
     AudioBuffer<float> outOfPlaceBuffer;\r
@@ -2319,7 +2322,7 @@ private:
         // Workaround: unfortunately old JUCE VST-2 plug-ins had a bug and would crash if\r
         // you try to get the speaker arrangement when there are no input channels present.\r
         // Hopefully, one day (when there are no more old JUCE plug-ins around), we can\r
-        // commment out the next two lines.\r
+        // comment out the next two lines.\r
         if (effect->numInputs == 0)\r
             return false;\r
 \r
@@ -2924,7 +2927,11 @@ public:
         if (auto* peer = getTopLevelComponent()->getPeer())\r
             setScaleFactorAndDispatchMessage (peer->getPlatformScaleFactor());\r
 \r
+       #if JUCE_LINUX\r
+        MessageManager::callAsync ([this] { componentMovedOrResized (true, true); });\r
+       #else\r
         componentMovedOrResized (true, true);\r
+       #endif\r
     }\r
 \r
     using ComponentMovementWatcher::componentVisibilityChanged;\r
index 62b0f498d8dfcec4a047d2112b1cd6d5aef599a7..f2f4c73d187daf8e992a9ce3ab1d50005692fa26 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_audio_processors\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE audio processor classes\r
-  description:      Classes for loading and playing VST, AU, LADSPA, or internally-generated audio processors.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
-\r
-  dependencies:     juce_gui_extra, juce_audio_basics\r
-  OSXFrameworks:    CoreAudio CoreMIDI AudioToolbox\r
-  iOSFrameworks:    AudioToolbox\r
+  ID:                 juce_audio_processors\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE audio processor classes\r
+  description:        Classes for loading and playing VST, AU, LADSPA, or internally-generated audio processors.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
+\r
+  dependencies:       juce_gui_extra, juce_audio_basics\r
+  OSXFrameworks:      CoreAudio CoreMIDI AudioToolbox\r
+  iOSFrameworks:      AudioToolbox\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 7e62e7a2b92dd1f5c9373f476a83a01d8ed443d4..bd40623c53be298b103192a08cd0275a5f08b92c 100644 (file)
@@ -52,8 +52,12 @@ AudioProcessor::AudioProcessor (const BusesProperties& ioConfig)
 \r
 AudioProcessor::~AudioProcessor()\r
 {\r
-    // ooh, nasty - the editor should have been deleted before its AudioProcessor.\r
-    jassert (activeEditor == nullptr);\r
+    {\r
+        const ScopedLock sl (activeEditorLock);\r
+\r
+        // ooh, nasty - the editor should have been deleted before its AudioProcessor.\r
+        jassert (activeEditor == nullptr);\r
+    }\r
 \r
    #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING\r
     // This will fail if you've called beginParameterChangeGesture() for one\r
@@ -424,41 +428,18 @@ void AudioProcessor::updateHostDisplay()
             l->audioProcessorChanged (this);\r
 }\r
 \r
-#if JUCE_DEBUG\r
-void AudioProcessor::checkDuplicateParamIDs()\r
+void AudioProcessor::checkForDuplicateParamID (AudioProcessorParameter* param)\r
 {\r
-    duplicateParamIDCheck.reset();\r
-\r
-    StringArray usedIDs;\r
-    usedIDs.ensureStorageAllocated (flatParameterList.size());\r
-\r
-    for (auto& p : flatParameterList)\r
-        if (auto* withID = dynamic_cast<AudioProcessorParameterWithID*> (p))\r
-            usedIDs.add (withID->paramID);\r
-\r
-    usedIDs.sort (false);\r
-\r
-    // This assertion checks whether you attempted to add two or more parameters with the same ID\r
-    for (int i = 1; i < usedIDs.size(); ++i)\r
-        jassert (usedIDs[i - 1] != usedIDs[i]);\r
-}\r
+    ignoreUnused (param);\r
 \r
-struct AudioProcessor::DuplicateParamIDCheck  : private AsyncUpdater\r
-{\r
-    DuplicateParamIDCheck (AudioProcessor& p) : owner (p)   { triggerAsyncUpdate(); }\r
-    ~DuplicateParamIDCheck() override                       { cancelPendingUpdate(); }\r
-\r
-    void handleAsyncUpdate() override                       { owner.checkDuplicateParamIDs(); }\r
-\r
-    AudioProcessor& owner;\r
-};\r
-#endif\r
-\r
-void AudioProcessor::triggerDuplicateParamIDCheck()\r
-{\r
    #if JUCE_DEBUG\r
-    if (MessageManager::getInstanceWithoutCreating() != nullptr)\r
-        duplicateParamIDCheck = std::make_unique<DuplicateParamIDCheck> (*this);\r
+    if (auto* withID = dynamic_cast<AudioProcessorParameterWithID*> (param))\r
+    {\r
+        auto insertResult = paramIDs.insert (withID->paramID);\r
+\r
+        // If you hit this assertion then the parameter ID is not unique\r
+        jassert (insertResult.second);\r
+    }\r
    #endif\r
 }\r
 \r
@@ -474,7 +455,7 @@ void AudioProcessor::addParameter (AudioProcessorParameter* param)
     param->parameterIndex = flatParameterList.size();\r
     flatParameterList.add (param);\r
 \r
-    triggerDuplicateParamIDCheck();\r
+    checkForDuplicateParamID (param);\r
 }\r
 \r
 void AudioProcessor::addParameterGroup (std::unique_ptr<AudioProcessorParameterGroup> group)\r
@@ -489,14 +470,19 @@ void AudioProcessor::addParameterGroup (std::unique_ptr<AudioProcessorParameterG
         auto p = flatParameterList.getUnchecked (i);\r
         p->processor = this;\r
         p->parameterIndex = i;\r
+\r
+        checkForDuplicateParamID (p);\r
     }\r
 \r
     parameterTree.addChild (std::move (group));\r
-    triggerDuplicateParamIDCheck();\r
 }\r
 \r
 void AudioProcessor::setParameterTree (AudioProcessorParameterGroup&& newTree)\r
 {\r
+   #if JUCE_DEBUG\r
+    paramIDs.clear();\r
+   #endif\r
+\r
     parameterTree = std::move (newTree);\r
     flatParameterList = parameterTree.getParameters (true);\r
 \r
@@ -505,9 +491,9 @@ void AudioProcessor::setParameterTree (AudioProcessorParameterGroup&& newTree)
         auto p = flatParameterList.getUnchecked (i);\r
         p->processor = this;\r
         p->parameterIndex = i;\r
-    }\r
 \r
-    triggerDuplicateParamIDCheck();\r
+        checkForDuplicateParamID (p);\r
+    }\r
 }\r
 \r
 void AudioProcessor::refreshParameterList() {}\r
@@ -821,14 +807,22 @@ void AudioProcessor::audioIOChanged (bool busNumberChanged, bool channelNumChang
 //==============================================================================\r
 void AudioProcessor::editorBeingDeleted (AudioProcessorEditor* const editor) noexcept\r
 {\r
-    const ScopedLock sl (callbackLock);\r
+    const ScopedLock sl (activeEditorLock);\r
 \r
     if (activeEditor == editor)\r
         activeEditor = nullptr;\r
 }\r
 \r
+AudioProcessorEditor* AudioProcessor::getActiveEditor() const noexcept\r
+{\r
+    const ScopedLock sl (activeEditorLock);\r
+    return activeEditor;\r
+}\r
+\r
 AudioProcessorEditor* AudioProcessor::createEditorIfNeeded()\r
 {\r
+    const ScopedLock sl (activeEditorLock);\r
+\r
     if (activeEditor != nullptr)\r
         return activeEditor;\r
 \r
@@ -838,8 +832,6 @@ AudioProcessorEditor* AudioProcessor::createEditorIfNeeded()
     {\r
         // you must give your editor comp a size before returning it..\r
         jassert (ed->getWidth() > 0 && ed->getHeight() > 0);\r
-\r
-        const ScopedLock sl (callbackLock);\r
         activeEditor = ed;\r
     }\r
 \r
index 04a11a92328947f0df276e8007bbf540217fe1ef..836b09c7c987d0feb15d349055f951d1ea160d81 100644 (file)
@@ -51,7 +51,7 @@ protected:
     //==============================================================================\r
     /** Constructor.\r
 \r
-        This constructor will create a main input and output bus which are diabled\r
+        This constructor will create a main input and output bus which are disabled\r
         by default. If you need more fine-grained control then use the other constructors.\r
     */\r
     AudioProcessor();\r
@@ -400,7 +400,7 @@ public:
         /** Return the number of channels of the current bus. */\r
         inline int getNumberOfChannels() const noexcept                 { return cachedChannelCount; }\r
 \r
-        /** Set the number of channles of this bus. This will return false if the AudioProcessor\r
+        /** Set the number of channels of this bus. This will return false if the AudioProcessor\r
             does not support this layout.\r
         */\r
         bool setNumberOfChannels (int channels);\r
@@ -627,7 +627,7 @@ public:
      */\r
     int getChannelIndexInProcessBlockBuffer (bool isInput, int busIndex, int channelIndex) const noexcept;\r
 \r
-    /** Returns the offset in a bus's buffer from an absolute channel indes.\r
+    /** Returns the offset in a bus's buffer from an absolute channel index.\r
 \r
         This method returns the offset in a bus's buffer given an absolute channel index.\r
         It also provides the bus index. For example, this method would return one\r
@@ -771,7 +771,7 @@ public:
 \r
     /** Returns the next best layout which is contained in a channel layout map.\r
 \r
-        You can use this mehtod to help you implement getNextBestLayout. For example:\r
+        You can use this method to help you implement getNextBestLayout. For example:\r
 \r
         @code\r
         BusesLayout getNextBestLayout (const BusesLayout& layouts) override\r
@@ -900,7 +900,7 @@ public:
         If this method returns a nullptr then you can still control the bypass by\r
         calling processBlockBypassed instead of processBlock. On the other hand,\r
         if this method returns a non-null value, you should never call\r
-        processBlockBypassed but use the returned parameter to conrol the bypass\r
+        processBlockBypassed but use the returned parameter to control the bypass\r
         state instead.\r
 \r
         A plug-in can override this function to return a parameter which control's your\r
@@ -964,10 +964,13 @@ public:
     virtual bool hasEditor() const = 0;\r
 \r
     //==============================================================================\r
-    /** Returns the active editor, if there is one.\r
-        Bear in mind this can return nullptr, even if an editor has previously been opened.\r
+    /** Returns the active editor, if there is one. Bear in mind this can return nullptr\r
+        even if an editor has previously been opened.\r
+\r
+        Note that you should only call this method from the message thread as the active\r
+        editor may be deleted by the message thread, causing a dangling pointer.\r
     */\r
-    AudioProcessorEditor* getActiveEditor() const noexcept             { return activeEditor; }\r
+    AudioProcessorEditor* getActiveEditor() const noexcept;\r
 \r
     /** Returns the active editor, or if there isn't one, it will create one.\r
         This may call createEditor() internally to create the component.\r
@@ -1011,14 +1014,21 @@ public:
     /** Returns the group of parameters managed by this AudioProcessor. */\r
     const AudioProcessorParameterGroup& getParameterTree() const;\r
 \r
-    /** Sets the group of parameters managed by this AudioProcessor. */\r
+    /** Sets the group of parameters managed by this AudioProcessor.\r
+\r
+        Replacing the tree after your AudioProcessor has been constructed will\r
+        crash many hosts, so don't do it! You may, however, change parameter and\r
+        group names by iterating the tree returned by getParameterTree().\r
+        Afterwards, call updateHostDisplay() to inform the host of the changes.\r
+        Not all hosts support dynamic changes to parameters and group names.\r
+    */\r
     void setParameterTree (AudioProcessorParameterGroup&& newTree);\r
 \r
     /** A processor should implement this method so that the host can ask it to\r
         rebuild its parameter tree.\r
-        If a plugin never changes its parameters, it's enough to create its\r
-        parameters in its constructor and do nothing in this method, but some\r
-        may want to\r
+\r
+        For most plug-ins it's enough to simply add your parameters in the\r
+        constructor and leave this unimplemented.\r
     */\r
     virtual void refreshParameterList();\r
 \r
@@ -1221,7 +1231,7 @@ public:
         AudioProcessor about which track the AudioProcessor is loaded on. This method\r
         may only be called on the message thread.\r
 \r
-        If you are implemeting an AudioProcessor then you can override this callback\r
+        If you are implementing an AudioProcessor then you can override this callback\r
         to do something useful with the track properties such as changing the colour\r
         of your AudioProcessor's editor. It's entirely up to the host when and how\r
         often this callback will be called.\r
@@ -1362,7 +1372,7 @@ protected:
 \r
     //==============================================================================\r
     /** @internal */\r
-    AudioPlayHead* playHead = nullptr;\r
+    std::atomic<AudioPlayHead*> playHead { nullptr };\r
 \r
     /** @internal */\r
     void sendParamChangeMessageToListeners (int parameterIndex, float newValue);\r
@@ -1458,7 +1468,7 @@ private:
     int blockSize = 0, latencySamples = 0;\r
     bool suspended = false, nonRealtime = false;\r
     ProcessingPrecision processingPrecision = singlePrecision;\r
-    CriticalSection callbackLock, listenerLock;\r
+    CriticalSection callbackLock, listenerLock, activeEditorLock;\r
 \r
     friend class Bus;\r
     mutable OwnedArray<Bus> inputBuses, outputBuses;\r
@@ -1477,17 +1487,15 @@ private:
     #endif\r
 \r
     bool textRecursionCheck = false;\r
-\r
-    struct DuplicateParamIDCheck;\r
-    std::unique_ptr<DuplicateParamIDCheck> duplicateParamIDCheck;\r
-    void checkDuplicateParamIDs();\r
+    std::unordered_set<String> paramIDs;\r
    #endif\r
 \r
+    void checkForDuplicateParamID (AudioProcessorParameter*);\r
+\r
     AudioProcessorListener* getListenerLocked (int) const noexcept;\r
     void updateSpeakerFormatStrings();\r
     void audioIOChanged (bool busNumberChanged, bool channelNumChanged);\r
     void getNextBestLayout (const BusesLayout&, BusesLayout&) const;\r
-    void triggerDuplicateParamIDCheck();\r
 \r
     template <typename floatType>\r
     void processBypassed (AudioBuffer<floatType>&, MidiBuffer&);\r
index 8e44bb29e9055db54f3cfecc6de350b37c36c279..0c660ae67a555ab90523d486f08128aec162a1a5 100644 (file)
@@ -103,15 +103,9 @@ void AudioProcessorEditor::setResizable (const bool shouldBeResizable, const boo
     if (shouldHaveCornerResizer != (resizableCorner != nullptr))\r
     {\r
         if (shouldHaveCornerResizer)\r
-        {\r
-            resizableCorner.reset (new ResizableCornerComponent (this, constrainer));\r
-            Component::addChildComponent (resizableCorner.get());\r
-            resizableCorner->setAlwaysOnTop (true);\r
-        }\r
+            attachResizableCornerComponent();\r
         else\r
-        {\r
             resizableCorner.reset();\r
-        }\r
     }\r
 }\r
 \r
@@ -146,6 +140,9 @@ void AudioProcessorEditor::setConstrainer (ComponentBoundsConstrainer* newConstr
                       || newConstrainer->getMinimumHeight() != newConstrainer->getMaximumHeight());\r
 \r
         attachConstrainer (newConstrainer);\r
+\r
+        if (resizableCorner != nullptr)\r
+            attachResizableCornerComponent();\r
     }\r
 }\r
 \r
@@ -158,6 +155,14 @@ void AudioProcessorEditor::attachConstrainer (ComponentBoundsConstrainer* newCon
     }\r
 }\r
 \r
+void AudioProcessorEditor::attachResizableCornerComponent()\r
+{\r
+    resizableCorner.reset (new ResizableCornerComponent (this, constrainer));\r
+    Component::addChildComponent (resizableCorner.get());\r
+    resizableCorner->setAlwaysOnTop (true);\r
+    editorResized (true);\r
+}\r
+\r
 void AudioProcessorEditor::setBoundsConstrained (Rectangle<int> newBounds)\r
 {\r
     if (constrainer != nullptr)\r
index d7f9282f53ce447193792e69a80795c410050daa..623390ffc9feb9fa0e24f097c4916c1b089e15d4 100644 (file)
@@ -200,6 +200,7 @@ private:
     void editorResized (bool wasResized);\r
     void updatePeer();\r
     void attachConstrainer (ComponentBoundsConstrainer*);\r
+    void attachResizableCornerComponent();\r
 \r
     //==============================================================================\r
     std::unique_ptr<AudioProcessorEditorListener> resizeListener;\r
index 123b2e396ef94d8175c0cfd122bb0667f06daa68..1a016a9c42954adda10aed46c5f42f8e338bf982 100644 (file)
@@ -275,18 +275,18 @@ private:
                 tempBufferDouble.makeCopyOf (buffer, true);\r
 \r
                 if (node->isBypassed())\r
-                    processor.processBlockBypassed (tempBufferDouble, midiMessages);\r
+                    node->processBlockBypassed (tempBufferDouble, midiMessages);\r
                 else\r
-                    processor.processBlock (tempBufferDouble, midiMessages);\r
+                    node->processBlock (tempBufferDouble, midiMessages);\r
 \r
                 buffer.makeCopyOf (tempBufferDouble, true);\r
             }\r
             else\r
             {\r
                 if (node->isBypassed())\r
-                    processor.processBlockBypassed (buffer, midiMessages);\r
+                    node->processBlockBypassed (buffer, midiMessages);\r
                 else\r
-                    processor.processBlock (buffer, midiMessages);\r
+                    node->processBlock (buffer, midiMessages);\r
             }\r
         }\r
 \r
@@ -295,18 +295,18 @@ private:
             if (processor.isUsingDoublePrecision())\r
             {\r
                 if (node->isBypassed())\r
-                    processor.processBlockBypassed (buffer, midiMessages);\r
+                    node->processBlockBypassed (buffer, midiMessages);\r
                 else\r
-                    processor.processBlock (buffer, midiMessages);\r
+                    node->processBlock (buffer, midiMessages);\r
             }\r
             else\r
             {\r
                 tempBufferFloat.makeCopyOf (buffer, true);\r
 \r
                 if (node->isBypassed())\r
-                    processor.processBlockBypassed (tempBufferFloat, midiMessages);\r
+                    node->processBlockBypassed (tempBufferFloat, midiMessages);\r
                 else\r
-                    processor.processBlock (tempBufferFloat, midiMessages);\r
+                    node->processBlock (tempBufferFloat, midiMessages);\r
 \r
                 buffer.makeCopyOf (tempBufferFloat, true);\r
             }\r
@@ -806,9 +806,10 @@ AudioProcessorGraph::Node::Node (NodeID n, std::unique_ptr<AudioProcessor> p) no
 void AudioProcessorGraph::Node::prepare (double newSampleRate, int newBlockSize,\r
                                          AudioProcessorGraph* graph, ProcessingPrecision precision)\r
 {\r
+    const ScopedLock lock (processorLock);\r
+\r
     if (! isPrepared)\r
     {\r
-        isPrepared = true;\r
         setParentGraph (graph);\r
 \r
         // try to align the precision of the processor and the graph\r
@@ -817,11 +818,17 @@ void AudioProcessorGraph::Node::prepare (double newSampleRate, int newBlockSize,
 \r
         processor->setRateAndBufferSizeDetails (newSampleRate, newBlockSize);\r
         processor->prepareToPlay (newSampleRate, newBlockSize);\r
+\r
+        // This may be checked from other threads that haven't taken the processorLock,\r
+        // so we need to leave it until the processor has been completely prepared\r
+        isPrepared = true;\r
     }\r
 }\r
 \r
 void AudioProcessorGraph::Node::unprepare()\r
 {\r
+    const ScopedLock lock (processorLock);\r
+\r
     if (isPrepared)\r
     {\r
         isPrepared = false;\r
@@ -831,6 +838,8 @@ void AudioProcessorGraph::Node::unprepare()
 \r
 void AudioProcessorGraph::Node::setParentGraph (AudioProcessorGraph* const graph) const\r
 {\r
+    const ScopedLock lock (processorLock);\r
+\r
     if (auto* ioProc = dynamic_cast<AudioProcessorGraph::AudioGraphIOProcessor*> (processor.get()))\r
         ioProc->setParentGraph (graph);\r
 }\r
@@ -876,6 +885,7 @@ AudioProcessorGraph::AudioProcessorGraph()
 \r
 AudioProcessorGraph::~AudioProcessorGraph()\r
 {\r
+    cancelPendingUpdate();\r
     clearRenderingSequence();\r
     clear();\r
 }\r
@@ -890,7 +900,7 @@ void AudioProcessorGraph::topologyChanged()
 {\r
     sendChangeMessage();\r
 \r
-    if (isPrepared.get() != 0)\r
+    if (isPrepared)\r
         triggerAsyncUpdate();\r
 }\r
 \r
@@ -940,7 +950,12 @@ AudioProcessorGraph::Node::Ptr AudioProcessorGraph::addNode (std::unique_ptr<Aud
     newProcessor->setPlayHead (getPlayHead());\r
 \r
     Node::Ptr n (new Node (nodeID, std::move (newProcessor)));\r
-    nodes.add (n.get());\r
+\r
+    {\r
+        const ScopedLock sl (getCallbackLock());\r
+        nodes.add (n.get());\r
+    }\r
+\r
     n->setParentGraph (this);\r
     topologyChanged();\r
     return n;\r
@@ -948,6 +963,8 @@ AudioProcessorGraph::Node::Ptr AudioProcessorGraph::addNode (std::unique_ptr<Aud
 \r
 bool AudioProcessorGraph::removeNode (NodeID nodeId)\r
 {\r
+    const ScopedLock sl (getCallbackLock());\r
+\r
     for (int i = nodes.size(); --i >= 0;)\r
     {\r
         if (nodes.getUnchecked(i)->nodeID == nodeId)\r
@@ -1203,50 +1220,46 @@ bool AudioProcessorGraph::anyNodesNeedPreparing() const noexcept
 \r
 void AudioProcessorGraph::buildRenderingSequence()\r
 {\r
-    std::unique_ptr<RenderSequenceFloat>  newSequenceF (new RenderSequenceFloat());\r
-    std::unique_ptr<RenderSequenceDouble> newSequenceD (new RenderSequenceDouble());\r
+    auto newSequenceF = std::make_unique<RenderSequenceFloat>();\r
+    auto newSequenceD = std::make_unique<RenderSequenceDouble>();\r
 \r
-    {\r
-        MessageManagerLock mml;\r
+    RenderSequenceBuilder<RenderSequenceFloat>  builderF (*this, *newSequenceF);\r
+    RenderSequenceBuilder<RenderSequenceDouble> builderD (*this, *newSequenceD);\r
 \r
-        RenderSequenceBuilder<RenderSequenceFloat>  builderF (*this, *newSequenceF);\r
-        RenderSequenceBuilder<RenderSequenceDouble> builderD (*this, *newSequenceD);\r
-    }\r
+    const ScopedLock sl (getCallbackLock());\r
 \r
-    {\r
-        const ScopedLock sl (getCallbackLock());\r
-        newSequenceF->prepareBuffers (getBlockSize());\r
-        newSequenceD->prepareBuffers (getBlockSize());\r
-    }\r
+    const auto currentBlockSize = getBlockSize();\r
+    newSequenceF->prepareBuffers (currentBlockSize);\r
+    newSequenceD->prepareBuffers (currentBlockSize);\r
 \r
     if (anyNodesNeedPreparing())\r
     {\r
-        {\r
-            const ScopedLock sl (getCallbackLock());\r
-            renderSequenceFloat.reset();\r
-            renderSequenceDouble.reset();\r
-        }\r
+        renderSequenceFloat.reset();\r
+        renderSequenceDouble.reset();\r
 \r
         for (auto* node : nodes)\r
-            node->prepare (getSampleRate(), getBlockSize(), this, getProcessingPrecision());\r
+            node->prepare (getSampleRate(), currentBlockSize, this, getProcessingPrecision());\r
     }\r
 \r
-    const ScopedLock sl (getCallbackLock());\r
+    isPrepared = 1;\r
 \r
-    std::swap (renderSequenceFloat, newSequenceF);\r
+    std::swap (renderSequenceFloat,  newSequenceF);\r
     std::swap (renderSequenceDouble, newSequenceD);\r
 }\r
 \r
 void AudioProcessorGraph::handleAsyncUpdate()\r
 {\r
     buildRenderingSequence();\r
-    isPrepared = 1;\r
 }\r
 \r
 //==============================================================================\r
 void AudioProcessorGraph::prepareToPlay (double sampleRate, int estimatedSamplesPerBlock)\r
 {\r
-    setRateAndBufferSizeDetails (sampleRate, estimatedSamplesPerBlock);\r
+    {\r
+        const ScopedLock sl (getCallbackLock());\r
+        setRateAndBufferSizeDetails (sampleRate, estimatedSamplesPerBlock);\r
+    }\r
+\r
     clearRenderingSequence();\r
 \r
     if (MessageManager::getInstance()->isThisTheMessageThread())\r
@@ -1264,6 +1277,8 @@ void AudioProcessorGraph::releaseResources()
 {\r
     const ScopedLock sl (getCallbackLock());\r
 \r
+    cancelPendingUpdate();\r
+\r
     isPrepared = 0;\r
 \r
     for (auto* n : nodes)\r
@@ -1304,11 +1319,11 @@ template <typename FloatType, typename SequenceType>
 static void processBlockForBuffer (AudioBuffer<FloatType>& buffer, MidiBuffer& midiMessages,\r
                                    AudioProcessorGraph& graph,\r
                                    std::unique_ptr<SequenceType>& renderSequence,\r
-                                   Atomic<int>& isPrepared)\r
+                                   std::atomic<bool>& isPrepared)\r
 {\r
     if (graph.isNonRealtime())\r
     {\r
-        while (isPrepared.get() == 0)\r
+        while (! isPrepared)\r
             Thread::sleep (1);\r
 \r
         const ScopedLock sl (graph.getCallbackLock());\r
@@ -1320,7 +1335,7 @@ static void processBlockForBuffer (AudioBuffer<FloatType>& buffer, MidiBuffer& m
     {\r
         const ScopedLock sl (graph.getCallbackLock());\r
 \r
-        if (isPrepared.get() == 1)\r
+        if (isPrepared)\r
         {\r
             if (renderSequence != nullptr)\r
                 renderSequence->perform (buffer, midiMessages, graph.getPlayHead());\r
@@ -1335,7 +1350,7 @@ static void processBlockForBuffer (AudioBuffer<FloatType>& buffer, MidiBuffer& m
 \r
 void AudioProcessorGraph::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)\r
 {\r
-    if (isPrepared.get() == 0 && MessageManager::getInstance()->isThisTheMessageThread())\r
+    if ((! isPrepared) && MessageManager::getInstance()->isThisTheMessageThread())\r
         handleAsyncUpdate();\r
 \r
     processBlockForBuffer<float> (buffer, midiMessages, *this, renderSequenceFloat, isPrepared);\r
@@ -1343,7 +1358,7 @@ void AudioProcessorGraph::processBlock (AudioBuffer<float>& buffer, MidiBuffer&
 \r
 void AudioProcessorGraph::processBlock (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)\r
 {\r
-    if (isPrepared.get() == 0 && MessageManager::getInstance()->isThisTheMessageThread())\r
+    if ((! isPrepared) && MessageManager::getInstance()->isThisTheMessageThread())\r
         handleAsyncUpdate();\r
 \r
     processBlockForBuffer<double> (buffer, midiMessages, *this, renderSequenceDouble, isPrepared);\r
index f7ce5789fb06c942f0f2cb47d0ededed2571bb0a..bb28badf5a04657d33dc61f465b095649dce3d36 100644 (file)
@@ -132,6 +132,8 @@ public:
     private:\r
         //==============================================================================\r
         friend class AudioProcessorGraph;\r
+        template <typename Float>\r
+        friend struct GraphRenderSequence;\r
 \r
         struct Connection\r
         {\r
@@ -143,7 +145,8 @@ public:
 \r
         const std::unique_ptr<AudioProcessor> processor;\r
         Array<Connection> inputs, outputs;\r
-        bool isPrepared = false, bypassed = false;\r
+        bool isPrepared = false;\r
+        std::atomic<bool> bypassed { false };\r
 \r
         Node (NodeID, std::unique_ptr<AudioProcessor>) noexcept;\r
 \r
@@ -151,6 +154,22 @@ public:
         void prepare (double newSampleRate, int newBlockSize, AudioProcessorGraph*, ProcessingPrecision);\r
         void unprepare();\r
 \r
+        template <typename Sample>\r
+        void processBlock (AudioBuffer<Sample>& audio, MidiBuffer& midi)\r
+        {\r
+            const ScopedLock lock (processorLock);\r
+            processor->processBlock (audio, midi);\r
+        }\r
+\r
+        template <typename Sample>\r
+        void processBlockBypassed (AudioBuffer<Sample>& audio, MidiBuffer& midi)\r
+        {\r
+            const ScopedLock lock (processorLock);\r
+            processor->processBlockBypassed (audio, midi);\r
+        }\r
+\r
+        CriticalSection processorLock;\r
+\r
         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Node)\r
     };\r
 \r
@@ -210,8 +229,8 @@ public:
         added a processor to the graph, the graph owns it and will delete it later when\r
         it is no longer needed.\r
 \r
-        The optional nodeId parameter lets you specify an ID to use for the node, but\r
-        if the value is already in use, this new node will overwrite the old one.\r
+        The optional nodeId parameter lets you specify a unique ID to use for the node.\r
+        If the value is already in use, this method will fail and return an empty node.\r
 \r
         If this succeeds, it returns a pointer to the newly-created node.\r
     */\r
@@ -396,7 +415,7 @@ private:
 \r
     friend class AudioGraphIOProcessor;\r
 \r
-    Atomic<int> isPrepared { 0 };\r
+    std::atomic<bool> isPrepared { false };\r
 \r
     void topologyChanged();\r
     void handleAsyncUpdate() override;\r
index 1d3b390077e65149424307aeb824af8254a20e7f..8552d7d3971abbbcd0e3c896f4f20e6c083c9bc6 100644 (file)
@@ -205,7 +205,7 @@ public:
     /** Returns the current value of the parameter as a String.\r
 \r
         This function can be called when you are hosting plug-ins to get a\r
-        more specialsed textual represenation of the current value from the\r
+        more specialised textual representation of the current value from the\r
         plug-in, for example "On" rather than "1.0".\r
 \r
         If you are implementing a plug-in then you should ignore this function\r
index cc2a75a4b83bddc6e82625a559792c94abeff5a1..62216b3cc57cd0389f6cb8f89ac2086795d32221 100644 (file)
@@ -97,6 +97,8 @@ String AudioProcessorParameterGroup::getName() const
 String AudioProcessorParameterGroup::getSeparator() const                                      { return separator; }\r
 const AudioProcessorParameterGroup* AudioProcessorParameterGroup::getParent() const noexcept   { return parent; }\r
 \r
+void AudioProcessorParameterGroup::setName (String newName)                                    { name = std::move (newName); }\r
+\r
 const AudioProcessorParameterGroup::AudioProcessorParameterNode* const* AudioProcessorParameterGroup::begin() const noexcept  { return const_cast<const AudioProcessorParameterNode**> (children.begin()); }\r
 const AudioProcessorParameterGroup::AudioProcessorParameterNode* const* AudioProcessorParameterGroup::end()   const noexcept  { return const_cast<const AudioProcessorParameterNode**> (children.end()); }\r
 \r
index f0137f92446f7953ad59ece5aeba1d87fe1b3dc9..6c1580ad5ec045331a89ceac1ff84ea4cdf59963 100644 (file)
@@ -143,9 +143,17 @@ public:
         addChild (std::forward<Args> (remainingChildren)...);\r
     }\r
 \r
+    /** Once a group has been added to an AudioProcessor don't try to mutate it by\r
+        moving or swapping it - this will crash most hosts.\r
+    */\r
     AudioProcessorParameterGroup (AudioProcessorParameterGroup&&);\r
+\r
+    /** Once a group has been added to an AudioProcessor don't try to mutate it by\r
+        moving or swapping it - this will crash most hosts.\r
+    */\r
     AudioProcessorParameterGroup& operator= (AudioProcessorParameterGroup&&);\r
 \r
+    /** Destructor. */\r
     ~AudioProcessorParameterGroup();\r
 \r
     //==============================================================================\r
@@ -158,9 +166,16 @@ public:
     /** Returns the group's separator string. */\r
     String getSeparator() const;\r
 \r
-    /** Returns the parent of the group, or nullptr if this is a top-levle group. */\r
+    /** Returns the parent of the group, or nullptr if this is a top-level group. */\r
     const AudioProcessorParameterGroup* getParent() const noexcept;\r
 \r
+    //==============================================================================\r
+    /** Changes the name of the group. If you do this after the group has been added\r
+        to an AudioProcessor, call updateHostDisplay() to inform the host of the\r
+        change. Not all hosts support dynamic group name changes.\r
+    */\r
+    void setName (String newName);\r
+\r
     //==============================================================================\r
     const AudioProcessorParameterNode* const* begin() const noexcept;\r
     const AudioProcessorParameterNode* const* end()   const noexcept;\r
@@ -186,7 +201,11 @@ public:
     Array<const AudioProcessorParameterGroup*> getGroupsForParameter (AudioProcessorParameter*) const;\r
 \r
     //==============================================================================\r
-    /** Adds a child to the group. */\r
+    /** Adds a child to the group.\r
+\r
+        Do not add children to a group which has itself already been added to the\r
+        AudioProcessor - the new elements will be ignored.\r
+    */\r
     template <typename ParameterOrGroup>\r
     void addChild (std::unique_ptr<ParameterOrGroup> child)\r
     {\r
@@ -196,7 +215,11 @@ public:
         append (std::move (child));\r
     }\r
 \r
-    /** Adds multiple parameters or sub-groups to this group. */\r
+    /** Adds multiple parameters or sub-groups to this group.\r
+\r
+        Do not add children to a group which has itself already been added to the\r
+        AudioProcessor - the new elements will be ignored.\r
+    */\r
     template <typename ParameterOrGroup, typename... Args>\r
     void addChild (std::unique_ptr<ParameterOrGroup> firstChild, Args&&... remainingChildren)\r
     {\r
@@ -205,8 +228,10 @@ public:
     }\r
 \r
    #ifndef DOXYGEN\r
-    // This class now has a move operator, so if you're try to move them around, you should\r
-    // use that, or if you really need to swap two groups, just call std::swap\r
+    // This class now has a move operator, so if you're trying to move them around, you\r
+    // should use that, or if you really need to swap two groups, just call std::swap.\r
+    // However, remember that swapping a group that's already owned by an AudioProcessor\r
+    // will most likely crash the host, so don't do that.\r
     JUCE_DEPRECATED_WITH_BODY (void swapWith (AudioProcessorParameterGroup& other), { std::swap (*this, other); })\r
    #endif\r
 \r
index 9cb9692749bd0babc6ae1f03ab2fbc4cb21fb80b..08fb9a5da76604f304806f6acbbaafa94e268705 100644 (file)
@@ -485,7 +485,7 @@ public:
             height += comp->getHeight();\r
         }\r
 \r
-        setSize (maxWidth, jmax (height, 100));\r
+        setSize (maxWidth, jmax (height, 125));\r
     }\r
 \r
     ~ParametersPanel() override\r
index 9e76edc23b3511edd75220c0b1969ada9c8f4413..2c120c4b979f054225b1efd2f891bd7e13436883 100644 (file)
@@ -398,7 +398,7 @@ public:
         // You need to use at least one thread when scanning plug-ins asynchronously\r
         jassert (! allowAsync || (numThreads > 0));\r
 \r
-        // If the filesOrIdentifiersToScan argumnent isn't empty, we should only scan these\r
+        // If the filesOrIdentifiersToScan argument isn't empty, we should only scan these\r
         // If the path is empty, then paths aren't used for this format.\r
         if (filesOrIdentifiersToScan.isEmpty() && path.getNumPaths() > 0)\r
         {\r
index 388e194c0fdbd92f27157be57fc8be91d3ec37be..ca3fcff60d1f5240f1a3b26aa4798fab47561835 100644 (file)
@@ -69,7 +69,13 @@ AudioParameterBool::AudioParameterBool (const String& idToUse, const String& nam
     }\r
 }\r
 \r
-AudioParameterBool::~AudioParameterBool() {}\r
+AudioParameterBool::~AudioParameterBool()\r
+{\r
+    #if __cpp_lib_atomic_is_always_lock_free\r
+     static_assert (std::atomic<float>::is_always_lock_free,\r
+                    "AudioParameterBool requires a lock-free std::atomic<float>");\r
+    #endif\r
+}\r
 \r
 float AudioParameterBool::getValue() const                               { return value; }\r
 void AudioParameterBool::setValue (float newValue)                       { value = newValue; valueChanged (get()); }\r
index 1f728404ef4a9a909e12edaef6c982b32046bcd8..f43ec7501295a9dcd4b6073ae63bbf58c7956d6b 100644 (file)
@@ -88,7 +88,7 @@ private:
     float getValueForText (const String&) const override;\r
 \r
     const NormalisableRange<float> range { 0.0f, 1.0f, 1.0f };\r
-    float value;\r
+    std::atomic<float> value;\r
     const float defaultValue;\r
     std::function<String(bool, int)> stringFromBoolFunction;\r
     std::function<bool(const String&)> boolFromStringFunction;\r
index 3cf7999130ae2e1cd9bf874847b292f7266f2d30..121f837dce9e042709a09f5a713add2493ae2db6 100644 (file)
@@ -55,7 +55,13 @@ AudioParameterChoice::AudioParameterChoice (const String& idToUse, const String&
         indexFromStringFunction = [this] (const String& text) { return choices.indexOf (text); };\r
 }\r
 \r
-AudioParameterChoice::~AudioParameterChoice() {}\r
+AudioParameterChoice::~AudioParameterChoice()\r
+{\r
+    #if __cpp_lib_atomic_is_always_lock_free\r
+     static_assert (std::atomic<float>::is_always_lock_free,\r
+                    "AudioParameterChoice requires a lock-free std::atomic<float>");\r
+    #endif\r
+}\r
 \r
 float AudioParameterChoice::getValue() const                             { return convertTo0to1 (value); }\r
 void AudioParameterChoice::setValue (float newValue)                     { value = convertFrom0to1 (newValue); valueChanged (getIndex()); }\r
index 32b30e7b28216a8992dc07d49ae1688117b30958..e0d242dbaa652d4894b90efc6737560303252ddb 100644 (file)
@@ -63,7 +63,7 @@ public:
     ~AudioParameterChoice() override;\r
 \r
     /** Returns the current index of the selected item. */\r
-    int getIndex() const noexcept                   { return roundToInt (value); }\r
+    int getIndex() const noexcept                   { return roundToInt (value.load()); }\r
 \r
     /** Returns the current index of the selected item. */\r
     operator int() const noexcept                   { return getIndex(); }\r
@@ -100,7 +100,7 @@ private:
     float getValueForText (const String&) const override;\r
 \r
     const NormalisableRange<float> range;\r
-    float value;\r
+    std::atomic<float> value;\r
     const float defaultValue;\r
     std::function<String(int, int)> stringFromIndexFunction;\r
     std::function<int(const String&)> indexFromStringFunction;\r
index f209ccc6979ebee17a0b9dbd093877de2e586895..894cf4ea917cf35579f19c80ea3a0817e067974a 100644 (file)
@@ -76,7 +76,13 @@ AudioParameterFloat::AudioParameterFloat (String pid, String nm, float minValue,
 {\r
 }\r
 \r
-AudioParameterFloat::~AudioParameterFloat() {}\r
+AudioParameterFloat::~AudioParameterFloat()\r
+{\r
+    #if __cpp_lib_atomic_is_always_lock_free\r
+     static_assert (std::atomic<float>::is_always_lock_free,\r
+                    "AudioParameterFloat requires a lock-free std::atomic<float>");\r
+    #endif\r
+}\r
 \r
 float AudioParameterFloat::getValue() const                              { return convertTo0to1 (value); }\r
 void AudioParameterFloat::setValue (float newValue)                      { value = convertFrom0to1 (newValue); valueChanged (get()); }\r
index 57c2ae09bf88d1c425b0ae27c4a13e04ceb367cd..62700c448ebe2a0f041c92c54841ce3cf839ef5b 100644 (file)
@@ -106,7 +106,7 @@ private:
     String getText (float, int) const override;\r
     float getValueForText (const String&) const override;\r
 \r
-    float value;\r
+    std::atomic<float> value;\r
     const float defaultValue;\r
     std::function<String(float, int)> stringFromValueFunction;\r
     std::function<float(const String&)> valueFromStringFunction;\r
index 53a78f9a9b0fa739d3323085b0e9724ce185dfc1..913bcf366e3ec826f3419e0c977952c7feb1fda8 100644 (file)
@@ -56,7 +56,13 @@ AudioParameterInt::AudioParameterInt (const String& idToUse, const String& nameT
         intFromStringFunction = [] (const String& text) { return text.getIntValue(); };\r
 }\r
 \r
-AudioParameterInt::~AudioParameterInt() {}\r
+AudioParameterInt::~AudioParameterInt()\r
+{\r
+    #if __cpp_lib_atomic_is_always_lock_free\r
+     static_assert (std::atomic<float>::is_always_lock_free,\r
+                    "AudioParameterInt requires a lock-free std::atomic<float>");\r
+    #endif\r
+}\r
 \r
 float AudioParameterInt::getValue() const                                { return convertTo0to1 (value); }\r
 void AudioParameterInt::setValue (float newValue)                        { value = convertFrom0to1 (newValue); valueChanged (get()); }\r
index 610feb18f253bc0bb568115142a820d18d9474d7..868e28cabb723aed068781ff1771f649acb5a150 100644 (file)
@@ -64,7 +64,7 @@ public:
     ~AudioParameterInt() override;\r
 \r
     /** Returns the parameter's current value as an integer. */\r
-    int get() const noexcept                    { return roundToInt (value); }\r
+    int get() const noexcept                    { return roundToInt (value.load()); }\r
 \r
     /** Returns the parameter's current value as an integer. */\r
     operator int() const noexcept               { return get(); }\r
@@ -96,7 +96,7 @@ private:
     float getValueForText (const String&) const override;\r
 \r
     const NormalisableRange<float> range;\r
-    float value;\r
+    std::atomic<float> value;\r
     const float defaultValue;\r
     std::function<String(int, int)> stringFromIntFunction;\r
     std::function<int(const String&)> intFromStringFunction;\r
index ad36c5aa0d186bf5af0382c9f0264c3a6d82498c..252dad8f14ca4a60e198d9c62240b530c25cf008 100644 (file)
@@ -124,8 +124,8 @@ public:
         return parameter.getText (normalise (value), 0);\r
     }\r
 \r
-    float getDenormalisedValue() const   { return unnormalisedValue; }\r
-    float& getRawDenormalisedValue()     { return unnormalisedValue; }\r
+    float getDenormalisedValue() const                { return unnormalisedValue; }\r
+    std::atomic<float>& getRawDenormalisedValue()     { return unnormalisedValue; }\r
 \r
     bool flushToTree (const Identifier& key, UndoManager* um)\r
     {\r
@@ -139,12 +139,12 @@ public:
             if ((float) *valueProperty != unnormalisedValue)\r
             {\r
                 ScopedValueSetter<bool> svs (ignoreParameterChangedCallbacks, true);\r
-                tree.setProperty (key, unnormalisedValue, um);\r
+                tree.setProperty (key, unnormalisedValue.load(), um);\r
             }\r
         }\r
         else\r
         {\r
-            tree.setProperty (key, unnormalisedValue, nullptr);\r
+            tree.setProperty (key, unnormalisedValue.load(), nullptr);\r
         }\r
 \r
         return true;\r
@@ -188,7 +188,7 @@ private:
 \r
     RangedAudioParameter& parameter;\r
     ListenerList<Listener> listeners;\r
-    float unnormalisedValue{};\r
+    std::atomic<float> unnormalisedValue{};\r
     std::atomic<bool> needsUpdate { true };\r
     bool listenersNeedCalling { true }, ignoreParameterChangedCallbacks { false };\r
 };\r
@@ -258,7 +258,10 @@ AudioProcessorValueTreeState::AudioProcessorValueTreeState (AudioProcessor& p, U
     state.addListener (this);\r
 }\r
 \r
-AudioProcessorValueTreeState::~AudioProcessorValueTreeState() {}\r
+AudioProcessorValueTreeState::~AudioProcessorValueTreeState()\r
+{\r
+    stopTimer();\r
+}\r
 \r
 //==============================================================================\r
 RangedAudioParameter* AudioProcessorValueTreeState::createAndAddParameter (const String& paramID,\r
@@ -355,7 +358,7 @@ RangedAudioParameter* AudioProcessorValueTreeState::getParameter (StringRef para
     return nullptr;\r
 }\r
 \r
-float* AudioProcessorValueTreeState::getRawParameterValue (StringRef paramID) const noexcept\r
+std::atomic<float>* AudioProcessorValueTreeState::getRawParameterValue (StringRef paramID) const noexcept\r
 {\r
     if (auto* p = getParameterAdapter (paramID))\r
         return &p->getRawDenormalisedValue();\r
@@ -791,7 +794,7 @@ struct ParameterAdapterTests  : public UnitTest
                 adapter.setDenormalisedValue (value);\r
 \r
                 expectEquals (adapter.getDenormalisedValue(), value);\r
-                expectEquals (adapter.getRawDenormalisedValue(), value);\r
+                expectEquals (adapter.getRawDenormalisedValue().load(), value);\r
             };\r
 \r
             test ({ -20, -10 }, -15);\r
@@ -1044,7 +1047,7 @@ public:
             const auto value = 0.5f;\r
             param->setValueNotifyingHost (value);\r
 \r
-            expectEquals (*proc.state.getRawParameterValue (key), value);\r
+            expectEquals (proc.state.getRawParameterValue (key)->load(), value);\r
         }\r
 \r
         beginTest ("After adding an APVTS::Parameter, its value is the default value");\r
@@ -1062,7 +1065,7 @@ public:
                 nullptr,\r
                 nullptr));\r
 \r
-            expectEquals (*proc.state.getRawParameterValue (key), value);\r
+            expectEquals (proc.state.getRawParameterValue (key)->load(), value);\r
         }\r
 \r
         beginTest ("Listeners receive notifications when parameters change");\r
@@ -1138,7 +1141,7 @@ public:
             value = newValue;\r
 \r
             expectEquals (param->getValue(), newValue);\r
-            expectEquals (*proc.state.getRawParameterValue (key), newValue);\r
+            expectEquals (proc.state.getRawParameterValue (key)->load(), newValue);\r
         }\r
 \r
         beginTest ("When the parameter value is changed, custom parameter values are updated");\r
@@ -1154,7 +1157,7 @@ public:
             value = newValue;\r
 \r
             expectEquals (paramPtr->getCurrentChoiceName(), choices[int (newValue)]);\r
-            expectEquals (*proc.state.getRawParameterValue (key), newValue);\r
+            expectEquals (proc.state.getRawParameterValue (key)->load(), newValue);\r
         }\r
 \r
         beginTest ("When the parameter value is changed, listeners are notified");\r
index f1ee8a434abc0458489602e35d2b8214168bf9ac..f06a70ba4150a6b189d94318cca8c0b832fc28de 100644 (file)
@@ -285,7 +285,7 @@ public:
         Note that calling this method from within AudioProcessorValueTreeState::Listener::parameterChanged()\r
         is not guaranteed to return an up-to-date value for the parameter.\r
     */\r
-    float* getRawParameterValue (StringRef parameterID) const noexcept;\r
+    std::atomic<float>* getRawParameterValue (StringRef parameterID) const noexcept;\r
 \r
     //==============================================================================\r
     /** A listener class that can be attached to an AudioProcessorValueTreeState.\r
index 303632067a602eb23e921415fd7e85b03eafc64c..e64eeccc3067b99422af5cdb7e8962534263e9c7 100644 (file)
@@ -61,7 +61,7 @@ public:
 \r
         An AudioSource has two states: prepared and unprepared.\r
 \r
-        The prepareToPlay() method is guaranteed to be called at least once on an 'unpreprared'\r
+        The prepareToPlay() method is guaranteed to be called at least once on an 'unprepared'\r
         source to put it into a 'prepared' state before any calls will be made to getNextAudioBlock().\r
         This callback allows the source to initialise any resources it might need when playing.\r
 \r
index e346c70b4b60038164c343957f17769bdee33353..95f06f3a7c3fe1b4302e42df52099e5ec25d49f3 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_audio_utils\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE extra audio utility classes\r
-  description:      Classes for audio-related GUI and miscellaneous tasks.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
-\r
-  dependencies:     juce_gui_extra, juce_audio_processors, juce_audio_formats, juce_audio_devices\r
-  OSXFrameworks:    CoreAudioKit DiscRecording\r
-  iOSFrameworks:    CoreAudioKit\r
+  ID:                 juce_audio_utils\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE extra audio utility classes\r
+  description:        Classes for audio-related GUI and miscellaneous tasks.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
+\r
+  dependencies:       juce_gui_extra, juce_audio_processors, juce_audio_formats, juce_audio_devices\r
+  OSXFrameworks:      CoreAudioKit DiscRecording\r
+  iOSFrameworks:      CoreAudioKit\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 41def683c666ca546c3ab83613b26d55bae56c1e..b4717c9401bb0f6b6991cb96e8c246d20695a665 100644 (file)
@@ -46,7 +46,8 @@ public:
         loopBlock,             /**< Loop control block type.      */\r
         developerControlBlock, /**< Developer control block type. */\r
         touchBlock,            /**< Touch control block type.     */\r
-        seaboardBlock          /**< Seaboard block type.          */\r
+        seaboardBlock,         /**< Seaboard block type.          */\r
+        lumiKeysBlock          /**< LUMI Keys block type          */\r
     };\r
 \r
     /** The Block class is reference-counted, so always use a Block::Ptr when\r
@@ -457,7 +458,7 @@ public:
     /** Provides a callback that will be called when a config changes. */\r
     virtual void setConfigChangedCallback (std::function<void(Block&, const ConfigMetaData&, uint32)>) = 0;\r
 \r
-    /** Provides a callback that will be called when a prgoram has been loaded. */\r
+    /** Provides a callback that will be called when a program has been loaded. */\r
     virtual void setProgramLoadedCallback (std::function<void(Block&)> programLoaded) = 0;\r
 \r
     //==============================================================================\r
index e93e5857e03d2ccae1221c81f3f8cd2bc0db2ad5..b314ce8ef143b926b0372a998ba6c23f4e96d7b6 100644 (file)
@@ -44,11 +44,6 @@ using ConfigType = Block::ConfigMetaData::ConfigType;
 */\r
 struct BlockConfigManager\r
 {\r
-    void setDeviceIndex (TopologyIndex newDeviceIndex)                       { deviceIndex = newDeviceIndex; }\r
-    void setDeviceComms (PhysicalTopologySource::DeviceConnection* newConn)  { deviceConnection = newConn; }\r
-\r
-    static constexpr uint32 numConfigItems = 69;\r
-\r
     /** Structure describing a configuration */\r
     struct ConfigDescription\r
     {\r
@@ -70,102 +65,122 @@ struct BlockConfigManager
         }\r
     };\r
 \r
+    BlockConfigManager (Array<ConfigDescription> defaultConfig)\r
+    {\r
+        for (auto c : defaultConfig)\r
+        {\r
+            uint32 itemIndex;\r
+\r
+            if (getIndexForItem (c.item, itemIndex))\r
+                configList[itemIndex] = c;\r
+        }\r
+    }\r
+\r
+    void setDeviceIndex (TopologyIndex newDeviceIndex)                       { deviceIndex = newDeviceIndex; }\r
+    void setDeviceComms (PhysicalTopologySource::DeviceConnection* newConn)  { deviceConnection = newConn; }\r
+\r
+    static constexpr uint32 numConfigItems = 69;\r
+\r
+    static constexpr const char* midiSettingsGroup = "MIDI Settings";\r
+    static constexpr const char* pitchGroup = "Pitch";\r
+    static constexpr const char* playGroup = "Play mode";\r
+    static constexpr const char* sensitivityGroup = "Sensitivity";\r
+    static constexpr const char* rhythmGroup = "Rhythm";\r
+    static constexpr const char* coloursGroup = "Colors";\r
+\r
     ConfigDescription configList[numConfigItems] =\r
     {\r
-        { midiStartChannel,     2,      1,      16,     false,  "MIDI Start Channel",   ConfigType::integer,    {},               "MIDI Settings" },\r
-        { midiEndChannel,       16,     1,      16,     false,  "MIDI End Channel",     ConfigType::integer,    {},               "MIDI Settings" },\r
-        { midiUseMPE,           1,      0,      2,      false,  "MIDI Mode",            ConfigType::options,    { "Multi Channel",\r
+        { midiStartChannel,     2,      1,      16,         false,  "MIDI Start Channel",   ConfigType::integer,    {},               midiSettingsGroup },\r
+        { midiEndChannel,       16,     1,      16,         false,  "MIDI End Channel",     ConfigType::integer,    {},               midiSettingsGroup },\r
+        { midiUseMPE,           1,      0,      2,          false,  "MIDI Mode",            ConfigType::options,    { "Multi Channel",\r
                                                                                                                   "MPE",\r
-                                                                                                                  "Single Channel" }, "MIDI Settings" },\r
-        { pitchBendRange,       48,     1,      96,     false,  "Pitch Bend Range",     ConfigType::integer,    {},               "MIDI Settings" },\r
-        { midiChannelRange,     15,     1,      15,     false,  "No. MIDI Channels",    ConfigType::integer,    {},               "MIDI Settings" },\r
-        { MPEZone,              0,      0,      1,      false,  "MPE Zone",             ConfigType::options,    { "Lower Zone",\r
-                                                                                                                  "Upper Zone"},  "MIDI Settings" },\r
-        { octave,               0,      -4,     6,      false,  "Octave",               ConfigType::integer,    {},               "Pitch" },\r
-        { transpose,            0,      -11,    11,     false,  "Transpose",            ConfigType::integer,    {},               "Pitch" },\r
-        { slideCC,              74,     0,      127,    false,  "Slide CC",             ConfigType::integer,    {},               "Play mode" },\r
-        { slideMode,            0,      0,      2,      false,  "Slide Mode",           ConfigType::options,    { "Absolute",\r
+                                                                                                                  "Single Channel" }, midiSettingsGroup },\r
+        { pitchBendRange,       48,     1,      96,         false,  "Pitch Bend Range",     ConfigType::integer,    {},               midiSettingsGroup },\r
+        { midiChannelRange,     15,     1,      15,         false,  "No. MIDI Channels",    ConfigType::integer,    {},               midiSettingsGroup },\r
+        { MPEZone,              0,      0,      1,          false,  "MPE Zone",             ConfigType::options,    { "Lower Zone",\r
+                                                                                                                  "Upper Zone"},      midiSettingsGroup },\r
+        { octave,               0,      -4,     6,          false,  "Octave",               ConfigType::integer,    {},               pitchGroup },\r
+        { transpose,            0,      -11,    11,         false,  "Transpose",            ConfigType::integer,    {},               pitchGroup },\r
+        { slideCC,              74,     0,      127,        false,  "Slide CC",             ConfigType::integer,    {},               playGroup },\r
+        { slideMode,            0,      0,      2,          false,  "Slide Mode",           ConfigType::options,    { "Absolute",\r
                                                                                                                   "Relative Unipolar",\r
-                                                                                                                  "Relative Bipolar" }, "Play mode" },\r
-        { velocitySensitivity,  100,    0,      127,    false,  "Strike Sensitivity",   ConfigType::integer,    {},               "5D Touch" },\r
-        { glideSensitivity,     100,    0,      127,    false,  "Glide Sensitivity",    ConfigType::integer,    {},               "5D Touch" },\r
-        { slideSensitivity,     100,    0,      127,    false,  "Slide Sensitivity",    ConfigType::integer,    {},               "5D Touch" },\r
-        { pressureSensitivity,  100,    0,      127,    false,  "Pressure Sensitivity", ConfigType::integer,    {},               "5D Touch" },\r
-        { liftSensitivity,      100,    0,      127,    false,  "Lift Sensitivity",     ConfigType::integer,    {},               "5D Touch" },\r
-        { fixedVelocity,        0,      0,      1,      false,  "Fixed Velocity",       ConfigType::boolean,    {},               "5D Touch" },\r
-        { fixedVelocityValue,   127,    1,      127,    false,  "Fixed Velocity Value", ConfigType::integer,    {},               "5D Touch" },\r
-        { pianoMode,            0,      0,      1,      false,  "Piano Mode",           ConfigType::boolean,    {},               "Play mode" },\r
-        { glideLock,            0,      0,      127,    false,  "Glide Rate",           ConfigType::integer,    {},               "Play mode" },\r
-        { glideLockEnable,      0,      0,      1,      false,  "Glide Lock Enable",    ConfigType::boolean,    {},               "Play mode" },\r
-        { mode,                 4,      1,      5,      false,  "Mode",                 ConfigType::integer,    {},               "Play mode" },\r
-        { volume,               100,    0,      127,    false,  "Volume",               ConfigType::integer,    {},               "Play mode" },\r
-        { scale,                0,      0,      18,     false,  "Scale",                ConfigType::integer,    {},               "Play mode" }, // NOTE: Should be options\r
-        { key,                  0,      0,      11,     false,  "Key",                  ConfigType::options,    { "C", "C#", "D", "D#",\r
-                                                                                                                  "E", "F", "F#", "G",\r
-                                                                                                                  "G#", "A", "A#", "B"}, "Play mode" },\r
-        { hideMode,             0,      0,      1,      false,  "Hide Mode",            ConfigType::boolean,    {},               "Play mode" },\r
-        { chord,                0,      0,      127,    false,  "Chord",                ConfigType::integer,    {},               "Play mode" }, // NOTE: Should be options\r
-        { arpPattern,           0,      0,      127,    false,  "Arp Pattern",          ConfigType::integer,    {},               "Play mode" },\r
-        { tempo,                120,    1,      300,    false,  "Tempo",                ConfigType::integer,    {},               "Rhythm" },\r
-        { key,                  0,      0,      11,     false,  "Key",                  ConfigType::options,    { "C", "C#", "D", "D#",\r
+                                                                                                                  "Relative Bipolar" }, playGroup },\r
+        { velocitySensitivity,  100,    0,      127,        false,  "Strike Sensitivity",   ConfigType::integer,    {},               sensitivityGroup },\r
+        { glideSensitivity,     100,    0,      127,        false,  "Glide Sensitivity",    ConfigType::integer,    {},               sensitivityGroup },\r
+        { slideSensitivity,     100,    0,      127,        false,  "Slide Sensitivity",    ConfigType::integer,    {},               sensitivityGroup },\r
+        { pressureSensitivity,  100,    0,      127,        false,  "Pressure Sensitivity", ConfigType::integer,    {},               sensitivityGroup },\r
+        { liftSensitivity,      100,    0,      127,        false,  "Lift Sensitivity",     ConfigType::integer,    {},               sensitivityGroup },\r
+        { fixedVelocity,        0,      0,      1,          false,  "Fixed Velocity",       ConfigType::boolean,    {},               sensitivityGroup },\r
+        { fixedVelocityValue,   127,    1,      127,        false,  "Fixed Velocity Value", ConfigType::integer,    {},               sensitivityGroup },\r
+        { pianoMode,            0,      0,      1,          false,  "Piano Mode",           ConfigType::boolean,    {},               playGroup },\r
+        { glideLock,            0,      0,      127,        false,  "Glide Rate",           ConfigType::integer,    {},               playGroup },\r
+        { glideLockEnable,      0,      0,      1,          false,  "Glide Lock Enable",    ConfigType::boolean,    {},               playGroup },\r
+        { mode,                 4,      1,      5,          false,  "Mode",                 ConfigType::integer,    {},               playGroup },\r
+        { volume,               100,    0,      127,        false,  "Volume",               ConfigType::integer,    {},               playGroup },\r
+        { scale,                0,      0,      18,         false,  "Scale",                ConfigType::integer,    {},               playGroup }, // NOTE: Should be options\r
+        { hideMode,             0,      0,      1,          false,  "Hide Mode",            ConfigType::boolean,    {},               playGroup },\r
+        { chord,                0,      0,      127,        false,  "Chord",                ConfigType::integer,    {},               playGroup }, // NOTE: Should be options\r
+        { arpPattern,           0,      0,      127,        false,  "Arp Pattern",          ConfigType::integer,    {},               playGroup },\r
+        { tempo,                120,    1,      300,        false,  "Tempo",                ConfigType::integer,    {},               rhythmGroup },\r
+        { key,                  0,      0,      11,         false,  "Key",                  ConfigType::options,    { "C", "C#", "D", "D#",\r
                                                                                                                   "E", "F", "F#", "G",\r
-                                                                                                                  "G#", "A", "A#", "B"}, "Play mode" },\r
-        { autoTransposeToKey,   0,      0,      1,      false,  "Auto Transpose To Key",ConfigType::boolean,    {},               "Pitch" },\r
-        { xTrackingMode,        1,      1,      4,      false,  "Glide Tracking Mode",  ConfigType::options,    { "Multi-Channel",\r
+                                                                                                                  "G#", "A", "A#", "B"}, playGroup },\r
+        { autoTransposeToKey,   0,      0,      1,          false,  "Auto Transpose To Key",ConfigType::boolean,    {},               pitchGroup },\r
+        { xTrackingMode,        1,      1,      4,          false,  "Glide Tracking Mode",  ConfigType::options,    { "Multi-Channel",\r
                                                                                                                   "Last Played",\r
                                                                                                                   "Highest",\r
                                                                                                                   "Lowest",\r
-                                                                                                                  "Disabled" },   "Play mode" },\r
-        { yTrackingMode,        1,      1,      4,      false,  "Slide Tracking Mode",  ConfigType::options,    { "Multi-Channel",\r
+                                                                                                                  "Disabled" },   playGroup },\r
+        { yTrackingMode,        1,      1,      4,          false,  "Slide Tracking Mode",  ConfigType::options,    { "Multi-Channel",\r
                                                                                                                   "Last Played",\r
                                                                                                                   "Highest",\r
                                                                                                                   "Lowest",\r
-                                                                                                                  "Disabled" },   "Play mode" },\r
-        { zTrackingMode,        1,      0,      4,      false,  "Pressure Tracking Mode",  ConfigType::options, { "Multi-Channel",\r
+                                                                                                                  "Disabled" },   playGroup },\r
+        { zTrackingMode,        1,      0,      4,          false,  "Pressure Tracking Mode", ConfigType::options, { "Poly Aftertouch",\r
                                                                                                                   "Last Played",\r
                                                                                                                   "Highest",\r
                                                                                                                   "Lowest",\r
                                                                                                                   "Disabled",\r
-                                                                                                                  "Hardest" },    "Play mode" },\r
+                                                                                                                  "Hardest" },    playGroup },\r
 \r
-        { gammaCorrection,      0,      0,      1,      false,  "Gamma Correction",     ConfigType::boolean,    {},               {} },\r
-        { globalKeyColour,      INT32_MIN, INT32_MIN, INT32_MAX, false,  "Global Key Colour", ConfigType::colour, {},             "Colour" },\r
-        { rootKeyColour,        INT32_MIN, INT32_MIN, INT32_MAX, false,  "Root Key Colour"  , ConfigType::colour, {},             "Colour" },\r
-        { brightness,           100,    0,    100,      false,  "Brightness",           ConfigType::integer,    {},               "Colour" },\r
+        { gammaCorrection,      0,         0,         1,    false,  "Gamma Correction",     ConfigType::boolean,    {},             coloursGroup },\r
+        { globalKeyColour, INT32_MIN, INT32_MIN, INT32_MAX, false,  "Global Key Color",     ConfigType::colour,     {},             coloursGroup },\r
+        { rootKeyColour,   INT32_MIN, INT32_MIN, INT32_MAX, false,  "Root Key Color"  ,     ConfigType::colour,     {},             coloursGroup },\r
+        { brightness,           100,    0,    100,          false,  "Brightness",           ConfigType::integer,    {},             coloursGroup },\r
 \r
         // These can be defined for unique usage for a given Littlefoot script\r
-        { user0,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user1,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user2,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user3,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user4,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user5,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user6,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user7,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user8,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user9,                0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user10,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user11,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user12,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user13,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user14,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user15,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user16,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user17,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user18,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user19,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user20,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user21,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user22,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user23,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user24,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user25,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user26,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user27,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user28,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user29,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user30,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} },\r
-        { user31,               0,    0,      127,      false,  {},                     ConfigType::integer,    {},               {} }\r
+        { user0,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user1,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user2,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user3,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user4,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user5,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user6,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user7,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user8,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user9,                0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user10,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user11,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user12,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user13,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user14,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user15,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user16,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user17,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user18,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user19,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user20,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user21,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user22,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user23,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user24,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user25,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user26,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user27,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user28,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user29,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user30,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} },\r
+        { user31,               0,    0,      127,          false,  {},                     ConfigType::integer,    {},               {} }\r
     };\r
 \r
     //==============================================================================\r
index 66f8bbf5b28cde602350fa2f8d8e4aa9abfb92d4..e20ad5f2196ca2ca1e80eba3a7aa7d739b1dd770 100644 (file)
@@ -40,10 +40,10 @@ public:
     /** The release tag for this version, such as "beta", "alpha", "rc", etc */\r
     String releaseType;\r
 \r
-    /** A numberical value assosiated with the release tag, such as "beta 4" */\r
+    /** A numerical value associated with the release tag, such as "beta 4" */\r
     int releaseCount = 0;\r
 \r
-    /** The assosiated git commit that generated this firmware version */\r
+    /** The associated git commit that generated this firmware version */\r
     String commit;\r
 \r
     /** Identify "forced" firmware builds **/\r
index 426a14a217cb16b293260f80a27825ec112847f7..ec09b012a1f42e8972b08a40d2ef1e5dab698b82 100644 (file)
@@ -95,13 +95,13 @@ public:
 \r
     /** Returns the position of this button on the device, in device units.\r
         For buttons that are on the side of the device, this may want to return a value that\r
-        is beyond the phyiscal block size.\r
+        is beyond the physical block size.\r
     */\r
     virtual float getPositionX() const = 0;\r
 \r
     /** Returns the position of this button on the device, in device units.\r
         For buttons that are on the side of the device, this may want to return a value that\r
-        is beyond the phyiscal block size.\r
+        is beyond the physical block size.\r
     */\r
     virtual float getPositionY() const = 0;\r
 \r
index 5f7287d9397077bf0f409e8f2bd484961b0011b8..30ee830634995116f05c926140fd4916a431adca 100644 (file)
@@ -130,7 +130,7 @@ public:
     TouchEntry* end() noexcept                 { return touches.end(); }\r
     const TouchEntry* end() const noexcept     { return touches.end(); }\r
 \r
-    /** Retrieve a reference to particular item in the list of touch entires. */\r
+    /** Retrieve a reference to particular item in the list of touch entries. */\r
     TouchEntry& operator[] (const int index)   { return touches.getReference (index); }\r
 \r
     /** Resets all contents, doest not generate any call-backs. */\r
index d833b3f1dbf97a8b78978fe216506b7aafc2a2c1..132dcfe06b8f7df8552079e9292ab889484fbe08 100644 (file)
@@ -39,9 +39,8 @@ namespace juce
 #include "protocol/juce_BlocksProtocolDefinitions.h"\r
 #include "protocol/juce_HostPacketDecoder.h"\r
 #include "protocol/juce_HostPacketBuilder.h"\r
-#include "protocol/juce_BlockModels.h"\r
-\r
 #include "blocks/juce_BlockConfigManager.h"\r
+#include "protocol/juce_BlockModels.h"\r
 #include "blocks/juce_Block.cpp"\r
 #include "blocks/juce_BlocksVersion.cpp"\r
 #include "topology/juce_BlockGraph.cpp"\r
index aa8f3396ce613ef2d8f4eefa7cae35129a6befbc..41035250a9f0fcd99db058d006e74e3514f07926 100644 (file)
@@ -20,6 +20,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
   ID:                 juce_blocks_basics\r
   vendor:             juce\r
-  version:            5.4.5\r
+  version:            5.4.6\r
   name:               Provides low-level control over ROLI BLOCKS devices\r
   description:        JUCE wrapper for low-level control over ROLI BLOCKS devices.\r
   website:            http://developer.roli.com\r
   license:            ISC\r
   minimumCppStandard: 14\r
 \r
-  dependencies:     juce_events juce_audio_devices\r
+  dependencies:       juce_events juce_audio_devices\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index d22f505175db4dae26decc0ecfa7b42ed96208f9..709697ad29de498965820bdc56fe9577ef94456e 100644 (file)
@@ -33,12 +33,13 @@ struct BlockDataSheet
 {\r
     BlockDataSheet (const BlocksProtocol::BlockSerialNumber& serial)  : serialNumber (serial)\r
     {\r
-        if (serialNumber.isPadBlock())      initialiseForPadBlock2x2();\r
-        if (serialNumber.isLiveBlock())     initialiseForControlBlockLive();\r
-        if (serialNumber.isLoopBlock())     initialiseForControlBlockLoop();\r
-        if (serialNumber.isDevCtrlBlock())  initialiseForControlBlockDeveloper();\r
-        if (serialNumber.isTouchBlock())    initialiseForControlBlockTouch();\r
-        if (serialNumber.isSeaboardBlock()) initialiseForSeaboardBlock();\r
+        if (serialNumber.isPadBlock())          initialiseForPadBlock2x2();\r
+        if (serialNumber.isLiveBlock())         initialiseForControlBlockLive();\r
+        if (serialNumber.isLoopBlock())         initialiseForControlBlockLoop();\r
+        if (serialNumber.isDevCtrlBlock())      initialiseForControlBlockDeveloper();\r
+        if (serialNumber.isTouchBlock())        initialiseForControlBlockTouch();\r
+        if (serialNumber.isSeaboardBlock())     initialiseForSeaboardBlock();\r
+        if (serialNumber.isLumiKeysBlock())     initialiseForLumiKeysBlock();\r
     }\r
 \r
     Block::ConnectionPort convertPortIndexToConnectorPort (BlocksProtocol::ConnectorPort port) const noexcept\r
@@ -78,6 +79,7 @@ struct BlockDataSheet
     Array<StatusLEDInfo> statusLEDs;\r
     Array<Block::ConnectionPort> ports;\r
     Array<const char*> dials;\r
+    Array<BlockConfigManager::ConfigDescription> defaultConfig;\r
 \r
 private:\r
     //==============================================================================\r
@@ -224,6 +226,45 @@ private:
         addModeButton();\r
     }\r
 \r
+    void initialiseForLumiKeysBlock()\r
+    {\r
+        apiType = Block::Type::lumiKeysBlock;\r
+\r
+        description = "LUMI Keys BLOCK (6x3)";\r
+\r
+        widthUnits = 6;\r
+        heightUnits = 3;\r
+\r
+        lightGridWidth = 0;\r
+        lightGridHeight = 0;\r
+        numKeywaves = 24;\r
+\r
+        addButtons (ControlButton::ButtonFunction::mode, 0.2f, 0.2f,\r
+                    ControlButton::ButtonFunction::down, 0.6f, 0.2f,\r
+                    ControlButton::ButtonFunction::up, 1.0f, 0.2f);\r
+\r
+        addPortsSW (Block::ConnectionPort::DeviceEdge::west, 2);\r
+        addPortsNE (Block::ConnectionPort::DeviceEdge::north, 4);\r
+        addPortsNE (Block::ConnectionPort::DeviceEdge::east, 2);\r
+\r
+        hasTouchSurface = true;\r
+        programAndHeapSize = BlocksProtocol::padBlockProgramAndHeapSize;\r
+\r
+        defaultConfig.add ({ mode, 0, 0, 3, false,\r
+                           "Color Mode", ConfigType::options,\r
+                           { "Multi-color Mode",\r
+                             "Single Color Mode",\r
+                             "Piano Mode",\r
+                             "Night Mode"\r
+                           },\r
+                           BlockConfigManager::playGroup });\r
+\r
+        defaultConfig.add ({ zTrackingMode, 0, 0, 1, false,\r
+                            "Pressure Tracking Mode", ConfigType::options,\r
+                            { "Poly Aftertouch", "Channel Pressure" },\r
+                            BlockConfigManager::playGroup });\r
+    }\r
+\r
     //==============================================================================\r
     void addStatusLED (const char* name, float x, float y)\r
     {\r
index b2399d5007be1719c553674af8293a7d70d58181..7a80fe5ab4f113ae5135676b4ba0994aada63281 100644 (file)
@@ -185,7 +185,7 @@ struct BlockSerialNumber : public BlockStringData<16>
             if (c == 0)\r
                 return false;\r
 \r
-        return isAnyControlBlock() || isPadBlock() || isSeaboardBlock();\r
+        return isAnyControlBlock() || isPadBlock() || isSeaboardBlock() || isLumiKeysBlock();\r
     }\r
 \r
     bool isPadBlock() const noexcept            { return hasPrefix ("LPB") || hasPrefix ("LPM"); }\r
@@ -194,6 +194,7 @@ struct BlockSerialNumber : public BlockStringData<16>
     bool isDevCtrlBlock() const noexcept        { return hasPrefix ("DCB"); }\r
     bool isTouchBlock() const noexcept          { return hasPrefix ("TCB"); }\r
     bool isSeaboardBlock() const noexcept       { return hasPrefix ("SBB"); }\r
+    bool isLumiKeysBlock() const noexcept       { return hasPrefix ("LKB"); }\r
 \r
     bool isAnyControlBlock() const noexcept     { return isLiveBlock() || isLoopBlock() || isDevCtrlBlock() || isTouchBlock(); }\r
 \r
index 6d3a7fbde12e3377e6f6210cc7d6dbbf30556569..45dc0c07bba03bad3d0c4c1cb57598ae4d292a91 100644 (file)
@@ -40,7 +40,8 @@ public:
                  deviceInfo.name.asString()),\r
           modelData (deviceInfo.serial),\r
           remoteHeap (modelData.programAndHeapSize),\r
-          detector (&detectorToUse)\r
+          detector (&detectorToUse),\r
+          config (modelData.defaultConfig)\r
     {\r
         markReconnected (deviceInfo);\r
 \r
@@ -219,10 +220,7 @@ public:
     bool sendMessageToDevice (const PacketBuilder& builder)\r
     {\r
         if (detector != nullptr)\r
-        {\r
-            lastMessageSendTime = Time::getCurrentTime();\r
             return detector->sendMessageToDevice (uid, builder);\r
-        }\r
 \r
         return false;\r
     }\r
@@ -456,7 +454,7 @@ public:
 \r
     void pingFromDevice()\r
     {\r
-        lastMessageReceiveTime = Time::getCurrentTime();\r
+        lastPingReceiveTime = Time::getCurrentTime();\r
     }\r
 \r
     MIDIDeviceConnection* getDeviceConnection()\r
@@ -510,8 +508,11 @@ public:
 \r
         remoteHeap.sendChanges (*this, false);\r
 \r
-        if (lastMessageSendTime < Time::getCurrentTime() - getPingInterval())\r
+        if (lastPingSendTime < Time::getCurrentTime() - getPingInterval())\r
+        {\r
+            lastPingSendTime = Time::getCurrentTime();\r
             sendCommandMessage (BlocksProtocol::ping);\r
+        }\r
     }\r
 \r
     RelativeTime getPingInterval()\r
@@ -653,7 +654,7 @@ public:
     RemoteHeapType remoteHeap;\r
 \r
     WeakReference<Detector> detector;\r
-    Time lastMessageSendTime, lastMessageReceiveTime;\r
+    Time lastPingSendTime, lastPingReceiveTime;\r
 \r
     BlockConfigManager config;\r
     std::function<void(Block&, const ConfigMetaData&, uint32)> configChangedCallback;\r
index c871d0924bbb32e6541bef0e2580fdc4bb424507..f237ee19f285450f26e86d6a650bf804632dc80c 100644 (file)
@@ -25,7 +25,7 @@ namespace juce
 \r
 /**\r
     Firmware below 0.3.0 does not report its version over the Blocks API.\r
-    This class can make requests and process responses to retreive the master Block version.\r
+    This class can make requests and process responses to retrieve the master Block version.\r
 */\r
 class DepreciatedVersionReader :  private MIDIDeviceConnection::Listener,\r
                                   private Timer\r
index 09bffab6254863cafe3d525b0e2f84331704b203..9a0df53d1c82c5a2105c07ae97c0a49447540d4e 100644 (file)
@@ -537,6 +537,24 @@ private:
                     return 1;\r
                 }\r
             }\r
+            else if (block->getType() == Block::lumiKeysBlock)\r
+            {\r
+                if (edge == Block::ConnectionPort::DeviceEdge::north)\r
+                {\r
+                    switch (index)\r
+                    {\r
+                        case 0 : return 0;\r
+                        case 1 : return 2;\r
+                        case 2 : return 3;\r
+                        case 3 : return 5;\r
+                        default : jassertfalse;\r
+                    }\r
+                }\r
+                else if (edge == Block::ConnectionPort::DeviceEdge::south)\r
+                {\r
+                    jassertfalse;\r
+                }\r
+            }\r
 \r
             if (edge == Block::ConnectionPort::DeviceEdge::south)\r
                 return block->getWidth() - (index + 1);\r
index 43a845389fc74d1e07f5085cd4b080b502e256c3..725afb5476268afc46d380992e8e9f7d81d0087a 100644 (file)
@@ -149,8 +149,8 @@ private:
     bool lockedFromOutside = true;\r
 \r
     /** For backwards compatibility, the block interprocess lock has to use the midi input name.\r
-        The below is necceccary because blocks of the same type might duplicate a port name, so\r
-        must share an interporcess lock.\r
+        The below is necessary because blocks of the same type might duplicate a port name, so\r
+        must share an interprocess lock.\r
      */\r
     std::shared_ptr<InterProcessLock> createMidiPortLock (const String& midiInName, const String& midiOutName)\r
     {\r
index 7509c029d2f2031b2f79ea1ac107211cf462ca16..989ec4e28b5f9f901b3f9a992e2802c137d7f7f0 100644 (file)
@@ -27,11 +27,13 @@ namespace juce
 \r
 /**\r
     Represents traversal paths from master blocks and any connected blocks.\r
+\r
+    @tags{Blocks}\r
 */\r
 class BlockGraph\r
 {\r
 public:\r
-    /** Creates a BlockGraph object from a BlockTopology with an optional filter fucntion. This\r
+    /** Creates a BlockGraph object from a BlockTopology with an optional filter function. This\r
         will build a block graph of traversal paths for each master.\r
     */\r
     BlockGraph (const BlockTopology topology, std::function<bool(Block::Ptr block)> filter = nullptr);\r
index d2ab65ef009483e52320afe22b0e52ac10439df7..46c122acfeef47df2b65af01c39dc9bbd53ed09a 100644 (file)
@@ -23,7 +23,7 @@
 namespace juce\r
 {\r
 \r
-/** Describes a phyiscal connection between two ports of two block devices.\r
+/** Describes a physical connection between two ports of two block devices.\r
 \r
     @tags{Blocks}\r
 */\r
index 5080c705f9f55cf89fdde5de90b9e8d8179c4e61..f4310a6dd129edf103dbf1e2ef7b5804d95b965f 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_box2d\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE wrapper for the Box2D physics engine\r
-  description:      The Box2D physics engine and some utility classes.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
+  ID:                 juce_box2d\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE wrapper for the Box2D physics engine\r
+  description:        The Box2D physics engine and some utility classes.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
 \r
-  dependencies:     juce_graphics\r
+  dependencies:       juce_graphics\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 3b516751f42e41bf037177a667ae4048b132ae8b..a2a37186cccf985b6d64454fc07369a5205f47f9 100644 (file)
@@ -30,7 +30,7 @@ namespace juce
     Examples of arrays are: Array<int>, Array<Rectangle> or Array<MyClass*>\r
 \r
     The Array class can be used to hold simple, non-polymorphic objects as well as primitive types - to\r
-    do so, the class must fulfil these requirements:\r
+    do so, the class must fulfill these requirements:\r
     - it must have a copy constructor and assignment operator\r
     - it must be able to be relocated in memory by a memcpy without this causing any problems - so\r
       objects whose functionality relies on external pointers or references to themselves can not be used.\r
index 6893e0638f31ded279c5e13a9bdb42d5dc2c8ad3..7a79da62bf24d68272079888de338a9985a24507 100644 (file)
@@ -304,7 +304,7 @@ public:
             checkEqual (copyableContainer, noncopyableContainer, referenceContainer);\r
         }\r
 \r
-        beginTest ("add array from initilizer list");\r
+        beginTest ("add array from initializer_list");\r
         {\r
             std::vector<CopyableType> referenceContainer;\r
             ArrayBase<CopyableType,    DummyCriticalSection> copyableContainer;\r
index 9085e090aeec6c0dfbedb543339eae87f9dcf31d..aed21086f94938b176761196a04529f0a51f4972 100644 (file)
@@ -78,7 +78,7 @@ public:
         call, then it invokes it.\r
 \r
         This method is virtual to allow more dynamic invocation to used for objects\r
-        where the methods may not already be set as properies.\r
+        where the methods may not already be set as properties.\r
     */\r
     virtual var invokeMethod (Identifier methodName,\r
                               const var::NativeFunctionArgs& args);\r
index de83ba21a2dc8b74488fae945df28db9d13dbf6e..b14cabf5cad3479dc7487b421ab6fc33cb584d2c 100644 (file)
@@ -143,7 +143,7 @@ public:
     */\r
     void removeValue (StringRef keyName);\r
 \r
-    /** Returns true if the properies include the given key. */\r
+    /** Returns true if the properties include the given key. */\r
     bool containsKey (StringRef keyName) const noexcept;\r
 \r
     /** Removes all values. */\r
@@ -190,7 +190,7 @@ public:
     PropertySet* getFallbackPropertySet() const noexcept                { return fallbackProperties; }\r
 \r
 protected:\r
-    /** Subclasses can override this to be told when one of the properies has been changed. */\r
+    /** Subclasses can override this to be told when one of the properties has been changed. */\r
     virtual void propertyChanged();\r
 \r
 private:\r
index e115d770bbe4fee7a6a305c58a6f1f5bec8d2b00..2596576c2b514d12fd39ddea1f00c66c167c3e51 100644 (file)
@@ -302,7 +302,7 @@ private:
         int64 int64Value;\r
         bool boolValue;\r
         double doubleValue;\r
-        char stringValue [sizeof (String)];\r
+        char stringValue[sizeof (String)];\r
         ReferenceCountedObject* objectValue;\r
         MemoryBlock* binaryValue;\r
         NativeFunction* methodValue;\r
@@ -319,6 +319,8 @@ private:
     // This is needed to prevent the wrong constructor/operator being called\r
     var (const ReferenceCountedObject*) = delete;\r
     var& operator= (const ReferenceCountedObject*) = delete;\r
+    var (const void*) = delete;\r
+    var& operator= (const void*) = delete;\r
 };\r
 \r
 /** Compares the values of two var objects, using the var::equals() comparison. */\r
index e07968b1924a0ae5629f74504c628cb88ccba408..7041ecd8860e1ed8f5d81b5b3c8f9e264aa6253e 100644 (file)
@@ -104,6 +104,26 @@ static String removeEllipsis (const String& path)
     return path;\r
 }\r
 \r
+static String normaliseSeparators (const String& path)\r
+{\r
+    auto normalisedPath = path;\r
+\r
+    String separator (File::getSeparatorString());\r
+    String doubleSeparator (separator + separator);\r
+\r
+    auto uncPath = normalisedPath.startsWith (doubleSeparator)\r
+                  && ! normalisedPath.fromFirstOccurrenceOf (doubleSeparator, false, false).startsWith (separator);\r
+\r
+    if (uncPath)\r
+        normalisedPath = normalisedPath.fromFirstOccurrenceOf (doubleSeparator, false, false);\r
+\r
+    while (normalisedPath.contains (doubleSeparator))\r
+         normalisedPath = normalisedPath.replace (doubleSeparator, separator);\r
+\r
+    return uncPath ? doubleSeparator + normalisedPath\r
+                   : normalisedPath;\r
+}\r
+\r
 bool File::isRoot() const\r
 {\r
     return fullPath.isNotEmpty() && *this == getParentDirectory();\r
@@ -114,9 +134,9 @@ String File::parseAbsolutePath (const String& p)
     if (p.isEmpty())\r
         return {};\r
 \r
-#if JUCE_WINDOWS\r
+   #if JUCE_WINDOWS\r
     // Windows..\r
-    auto path = removeEllipsis (p.replaceCharacter ('/', '\\'));\r
+    auto path = normaliseSeparators (removeEllipsis (p.replaceCharacter ('/', '\\')));\r
 \r
     if (path.startsWithChar (getSeparatorChar()))\r
     {\r
@@ -147,7 +167,7 @@ String File::parseAbsolutePath (const String& p)
 \r
         return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();\r
     }\r
-#else\r
+   #else\r
     // Mac or Linux..\r
 \r
     // Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here\r
@@ -155,7 +175,7 @@ String File::parseAbsolutePath (const String& p)
     // If that's why you've ended up here, use File::getChildFile() to build your paths instead.\r
     jassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));\r
 \r
-    auto path = removeEllipsis (p);\r
+    auto path = normaliseSeparators (removeEllipsis (p));\r
 \r
     if (path.startsWithChar ('~'))\r
     {\r
@@ -196,7 +216,7 @@ String File::parseAbsolutePath (const String& p)
 \r
         return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();\r
     }\r
-#endif\r
+   #endif\r
 \r
     while (path.endsWithChar (getSeparatorChar()) && path != getSeparatorString()) // careful not to turn a single "/" into an empty string.\r
         path = path.dropLastCharacters (1);\r
index 6cfcc909935a3ebcf16d380b2c7cd20aec7f0a5e..4a92686c73bf48772b0dc51e2f2fa07581cd69fa 100644 (file)
@@ -816,7 +816,8 @@ struct JavascriptEngine::RootObject   : public DynamicObject
             for (int i = 0; i < values.size(); ++i)\r
                 a.add (values.getUnchecked(i)->getResult (s));\r
 \r
-            return a;\r
+            // std::move() needed here for older compilers\r
+            return std::move (a);\r
         }\r
 \r
         OwnedArray<Expression> values;\r
@@ -1625,7 +1626,8 @@ struct JavascriptEngine::RootObject   : public DynamicObject
                 for (int i = 2; i < a.numArguments; ++i)\r
                     array->insert (start++, get (a, i));\r
 \r
-                return itemsRemoved;\r
+                // std::move() needed here for older compilers\r
+                return std::move (itemsRemoved);\r
             }\r
 \r
             return var::undefined();\r
old mode 100755 (executable)
new mode 100644 (file)
index a7d26cd..1c58ba7
  #include <android/log.h>\r
 #endif\r
 \r
-#if JUCE_BELA\r
- #include <alchemy/timer.h>\r
-#endif\r
-\r
 #undef check\r
 \r
 //==============================================================================\r
 #include "misc/juce_RuntimePermissions.cpp"\r
 #include "misc/juce_Result.cpp"\r
 #include "misc/juce_Uuid.cpp"\r
-#include "misc/juce_StdFunctionCompat.cpp"\r
 #include "misc/juce_ConsoleApplication.cpp"\r
 #include "network/juce_MACAddress.cpp"\r
 #include "network/juce_NamedPipe.cpp"\r
 \r
 #include "threads/juce_ChildProcess.cpp"\r
 #include "threads/juce_HighResolutionTimer.cpp"\r
+#include "threads/juce_WaitableEvent.cpp"\r
 #include "network/juce_URL.cpp"\r
 #include "network/juce_WebInputStream.cpp"\r
 #include "streams/juce_URLInputSource.cpp"\r
index 9cd414694650a1deced41b01f201ee251bc00abf..3a88ff18ab20e87dd01371168a36933cb1a8244c 100644 (file)
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_core\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE core classes\r
-  description:      The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.\r
-  website:          http://www.juce.com/juce\r
-  license:          ISC\r
+  ID:                 juce_core\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE core classes\r
+  description:        The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.\r
+  website:            http://www.juce.com/juce\r
+  license:            ISC\r
 \r
   dependencies:\r
-  OSXFrameworks:    Cocoa IOKit\r
-  iOSFrameworks:    Foundation\r
-  linuxLibs:        rt dl pthread\r
-  mingwLibs:        uuid wsock32 wininet version ole32 ws2_32 oleaut32 imm32 comdlg32 shlwapi rpcrt4 winmm\r
+  OSXFrameworks:      Cocoa IOKit\r
+  iOSFrameworks:      Foundation\r
+  linuxLibs:          rt dl pthread\r
+  mingwLibs:          uuid wsock32 wininet version ole32 ws2_32 oleaut32 imm32 comdlg32 shlwapi rpcrt4 winmm\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
 \r
 /** Config: JUCE_LOAD_CURL_SYMBOLS_LAZILY\r
     If enabled, JUCE will load libcurl lazily when required (for example, when WebInputStream\r
-    is used). Enabling this flag may also help with library dependency erros as linking\r
+    is used). Enabling this flag may also help with library dependency errors as linking\r
     libcurl at compile-time may instruct the linker to hard depend on a specific version\r
     of libcurl. It's also useful if you want to limit the amount of JUCE dependencies and\r
     you are not using WebInputStream or the URL classes.\r
index b6b10745c48f03ba7bb8a9052440992a93168b64..50e5c8742885a8fa5399987091b1d410d0fffe76 100644 (file)
@@ -83,7 +83,7 @@ public:
 \r
         The filename used is based on the root and suffix strings provided, along with a\r
         time and date string, meaning that a new, empty log file will be always be created\r
-        rather than appending to an exising one.\r
+        rather than appending to an existing one.\r
 \r
         The method might return nullptr if the file can't be created for some reason.\r
 \r
index 617d2d091d6c0753bd6a0ee90c681357590b248c..575687d8c32645fe193e6e1d54072dfec6edb96c 100644 (file)
@@ -49,9 +49,14 @@ namespace juce
     Once a new ReferenceCountedObject has been assigned to a pointer, be\r
     careful not to delete the object manually.\r
 \r
-    This class uses an Atomic<int> value to hold the reference count, so that\r
-    the pointers can be passed between threads safely. For a faster but non-thread-safe\r
-    version, use SingleThreadedReferenceCountedObject instead.\r
+    This class uses an Atomic<int> value to hold the reference count, so\r
+    the reference count can be updated on multiple threads. Note that\r
+    whilst it's thread-safe to create and delete a ReferenceCountedObjectPtr\r
+    to a ReferenceCountedObject shared between threads, it's not thread-safe\r
+    to modify or swap the ReferenceCountedObject.\r
+\r
+    For a faster but non-thread-safe version, use SingleThreadedReferenceCountedObject\r
+    instead.\r
 \r
     @see ReferenceCountedObjectPtr, ReferenceCountedArray, SingleThreadedReferenceCountedObject\r
 \r
index bf3bf5c737b4ce297ad810c067168962502d920d..da5548b41a95aca7c3596b06657ea14e83201e25 100644 (file)
@@ -308,7 +308,7 @@ int ConsoleApplication::invokeCatchingFailures (std::function<int()>&& f)
     }\r
     catch (const ConsoleAppFailureCode& error)\r
     {\r
-        std::cout << error.errorMessage << std::endl;\r
+        std::cerr << error.errorMessage << std::endl;\r
         returnCode = error.returnCode;\r
     }\r
 \r
index bc46c51440328e94ada81215a02fe89ff806f26e..a6440177bc17314dbb8fb394a218b468d97f96d8 100644 (file)
@@ -32,6 +32,8 @@ namespace juce
     main() function to parse.\r
 \r
     @see ConsoleApplication\r
+\r
+    @tags{Core}\r
 */\r
 struct ArgumentList\r
 {\r
@@ -50,6 +52,8 @@ struct ArgumentList
     //==============================================================================\r
     /**\r
         One of the arguments in an ArgumentList.\r
+\r
+        @tags{Core}\r
     */\r
     struct Argument\r
     {\r
@@ -226,13 +230,18 @@ struct ArgumentList
     @endcode\r
 \r
     @see ArgumentList\r
+\r
+    @tags{Core}\r
 */\r
 struct ConsoleApplication\r
 {\r
     //==============================================================================\r
     /**\r
         Represents a command that can be executed if its command-line arguments are matched.\r
+\r
         @see ConsoleApplication::addCommand(), ConsoleApplication::findAndRunCommand()\r
+\r
+        @tags{Core}\r
     */\r
     struct Command\r
     {\r
diff --git a/modules/juce_core/misc/juce_StdFunctionCompat.cpp b/modules/juce_core/misc/juce_StdFunctionCompat.cpp
deleted file mode 100644 (file)
index ece1e5e..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/*\r
-  ==============================================================================\r
-\r
-   This file is part of the JUCE library.\r
-   Copyright (c) 2017 - ROLI Ltd.\r
-\r
-   Permission is granted to use this software under the terms of the ISC license\r
-   http://www.isc.org/downloads/software-support-policy/isc-license/\r
-\r
-   Permission to use, copy, modify, and/or distribute this software for any\r
-   purpose with or without fee is hereby granted, provided that the above\r
-   copyright notice and this permission notice appear in all copies.\r
-\r
-   THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD\r
-   TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
-   FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,\r
-   OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF\r
-   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\r
-   TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE\r
-   OF THIS SOFTWARE.\r
-\r
-   -----------------------------------------------------------------------------\r
-\r
-   To release a closed-source product which uses other parts of JUCE not\r
-   licensed under the ISC terms, commercial licenses are available: visit\r
-   www.juce.com for more information.\r
-\r
-  ==============================================================================\r
-*/\r
-\r
-namespace juce\r
-{\r
-\r
-#if JUCE_UNIT_TESTS\r
-\r
-namespace FunctionTestsHelpers\r
-{\r
-    static void incrementArgument (int& x) { x++; }\r
-    static double multiply (double x, double a) noexcept { return a * x; }\r
-\r
-    struct BigData\r
-    {\r
-        BigData()\r
-        {\r
-            for (auto i = 0; i < bigDataSize; ++i)\r
-                content[i] = i + 1;\r
-        }\r
-\r
-        int sum() const\r
-        {\r
-            int result = 0;\r
-            for (auto i = 0; i < bigDataSize; ++i)\r
-                result += content[i];\r
-\r
-            return result;\r
-        }\r
-\r
-        static const int bigDataSize = 32,\r
-                         bigDataSum = bigDataSize * (bigDataSize + 1) / 2;\r
-        int content[bigDataSize];\r
-    };\r
-\r
-    struct FunctionObject\r
-    {\r
-        FunctionObject() = default;\r
-\r
-        FunctionObject (const FunctionObject& other)\r
-        {\r
-            bigData.reset (new BigData (*other.bigData));\r
-        }\r
-\r
-        int operator()(int i) const { return bigData->sum() + i; }\r
-\r
-        std::unique_ptr<BigData> bigData { new BigData() };\r
-\r
-        JUCE_LEAK_DETECTOR (FunctionObject)\r
-    };\r
-\r
-    struct BigFunctionObject\r
-    {\r
-        BigFunctionObject() = default;\r
-\r
-        BigFunctionObject (const BigFunctionObject& other)\r
-        {\r
-            bigData.reset (new BigData (*other.bigData));\r
-        }\r
-\r
-        int operator()(int i) const { return bigData->sum() + i; }\r
-\r
-        std::unique_ptr<BigData> bigData { new BigData() };\r
-\r
-        int stackUsage[32];\r
-\r
-        JUCE_LEAK_DETECTOR (BigFunctionObject)\r
-    };\r
-}\r
-\r
-class FunctionTests  : public UnitTest\r
-{\r
-public:\r
-    FunctionTests()\r
-        : UnitTest ("Function", UnitTestCategories::function)\r
-    {}\r
-\r
-    void runTest() override\r
-    {\r
-        FunctionTestsHelpers::BigData bigData;\r
-\r
-        {\r
-            beginTest ("Functions");\r
-\r
-            std::function<void(int&)> f1 (FunctionTestsHelpers::incrementArgument);\r
-\r
-            auto x = 0;\r
-            f1 (x);\r
-            expectEquals (x, 1);\r
-\r
-            std::function<double(double, double)> f2 (FunctionTestsHelpers::multiply);\r
-            expectEquals (6.0, f2 (2.0, 3.0));\r
-        }\r
-\r
-        {\r
-            beginTest ("Function objects");\r
-\r
-            std::function<int(int)> f1 = FunctionTestsHelpers::FunctionObject();\r
-            expectEquals (f1 (5), FunctionTestsHelpers::BigData::bigDataSum + 5);\r
-\r
-            std::function<int(int)> f2 { FunctionTestsHelpers::BigFunctionObject() };\r
-            expectEquals (f2 (5), FunctionTestsHelpers::BigData::bigDataSum + 5);\r
-        }\r
-\r
-        {\r
-            beginTest ("Lambdas");\r
-\r
-            std::function<int()> fStack ([] { return 3; });\r
-            expectEquals (fStack(), 3);\r
-\r
-            std::function<int()> fHeap ([=] { return bigData.sum(); });\r
-            expectEquals (fHeap(), FunctionTestsHelpers::BigData::bigDataSum);\r
-        }\r
-\r
-        {\r
-            beginTest ("Boolean");\r
-\r
-            std::function<void(int&)> f1;\r
-\r
-            if (f1)\r
-                expect (false);\r
-\r
-            std::function<int()> f2 ([]() { return 3; });\r
-\r
-            if (! f2)\r
-                expect (false);\r
-        }\r
-\r
-        std::function<int()> fEmpty;\r
-\r
-        std::function<int()> fStack ([] { return 3; });\r
-\r
-        std::function<int()> fHeap ([=] { return bigData.sum(); });\r
-\r
-        {\r
-            beginTest ("copy constructor");\r
-\r
-            std::function<int()> f1 (fStack);\r
-            expectEquals (f1(), 3);\r
-\r
-            std::function<int()> f2 (fHeap);\r
-            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);\r
-\r
-            std::function<int()> f3 (fEmpty);\r
-            if (f3)\r
-                expect (false);\r
-        }\r
-\r
-        {\r
-            beginTest ("assignment");\r
-\r
-            std::function<int()> f1;\r
-            f1 = fStack;\r
-            expectEquals (f1(), 3);\r
-\r
-            std::function<int()> f2;\r
-            f2 = fHeap;\r
-            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);\r
-\r
-            f1 = fHeap;\r
-            expectEquals (f1(), FunctionTestsHelpers::BigData::bigDataSum);\r
-\r
-            f2 = fStack;\r
-            expectEquals (f2(), 3);\r
-\r
-            f1 = fEmpty;\r
-            if (f1)\r
-                expect (false);\r
-        }\r
-\r
-        {\r
-            beginTest ("move constructor");\r
-\r
-            std::unique_ptr<std::function<int()>> fStackTmp (new std::function<int()> (fStack));\r
-            std::function<int()> f1 (std::move (*fStackTmp));\r
-\r
-            fStackTmp.reset();\r
-            expectEquals (f1(), 3);\r
-\r
-            std::unique_ptr<std::function<int()>> fHeapTmp (new std::function<int()> (fHeap));\r
-            std::function<int()> f2 (std::move (*fHeapTmp));\r
-            if (*fHeapTmp)\r
-                expect (false);\r
-\r
-            fHeapTmp.reset();\r
-            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);\r
-\r
-            std::unique_ptr<std::function<int()>> fEmptyTmp (new std::function<int()>());\r
-            std::function<int()> f3 (std::move (*fEmptyTmp));\r
-            fEmptyTmp.reset();\r
-            if (f3)\r
-                expect (false);\r
-        }\r
-\r
-        {\r
-            beginTest ("move assignment");\r
-\r
-            std::function<int()> f1 (fHeap);\r
-            std::unique_ptr<std::function<int()>> fStackTmp (new std::function<int()> (fStack));\r
-            f1 = std::move (*fStackTmp);\r
-\r
-            fStackTmp.reset();\r
-            expectEquals (f1(), 3);\r
-\r
-            std::function<int()> f2 (fStack);\r
-            std::unique_ptr<std::function<int()>> fHeapTmp (new std::function<int()> (fHeap));\r
-            f2 = std::move (*fHeapTmp);\r
-            if (*fHeapTmp)\r
-                expect (false);\r
-\r
-            fHeapTmp.reset();\r
-            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);\r
-\r
-            std::function<int()> f3 (fHeap);\r
-            std::unique_ptr<std::function<int()>> fEmptyTmp (new std::function<int()>());\r
-            f3 = std::move (*fEmptyTmp);\r
-            fEmptyTmp.reset();\r
-            if (f3)\r
-                expect (false);\r
-        }\r
-\r
-        {\r
-            beginTest ("nullptr");\r
-\r
-            std::function<int()> f1 (nullptr);\r
-            if (f1)\r
-                expect (false);\r
-\r
-            std::function<int()> f2 ([]() { return 11; });\r
-            f2 = nullptr;\r
-            if (f2)\r
-                expect (false);\r
-        }\r
-\r
-        {\r
-            beginTest ("Swap");\r
-\r
-            std::function<int()> f1;\r
-            std::function<int()> f2 (fStack);\r
-            f2.swap (f1);\r
-            expectEquals (f1(), 3);\r
-            if (f2)\r
-                expect (false);\r
-\r
-            std::function<int()> f3 (fHeap);\r
-            f3.swap (f1);\r
-            expectEquals (f3(), 3);\r
-            expectEquals (f1(), FunctionTestsHelpers::BigData::bigDataSum);\r
-        }\r
-    }\r
-};\r
-\r
-static FunctionTests functionTests;\r
-\r
-#endif\r
-\r
-} // namespace juce\r
diff --git a/modules/juce_core/misc/juce_StdFunctionCompat.h b/modules/juce_core/misc/juce_StdFunctionCompat.h
deleted file mode 100644 (file)
index 94c65f4..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*\r
-  ==============================================================================\r
-\r
-   This file is part of the JUCE library.\r
-   Copyright (c) 2017 - ROLI Ltd.\r
-\r
-   Permission is granted to use this software under the terms of the ISC license\r
-   http://www.isc.org/downloads/software-support-policy/isc-license/\r
-\r
-   Permission to use, copy, modify, and/or distribute this software for any\r
-   purpose with or without fee is hereby granted, provided that the above\r
-   copyright notice and this permission notice appear in all copies.\r
-\r
-   THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD\r
-   TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
-   FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,\r
-   OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF\r
-   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\r
-   TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE\r
-   OF THIS SOFTWARE.\r
-\r
-   -----------------------------------------------------------------------------\r
-\r
-   To release a closed-source product which uses other parts of JUCE not\r
-   licensed under the ISC terms, commercial licenses are available: visit\r
-   www.juce.com for more information.\r
-\r
-  ==============================================================================\r
-*/\r
-\r
-namespace std\r
-{\r
-    /**\r
-        This class provides an alternative to std::function that is compatible\r
-        with OS X 10.6 and earlier. This will only be used in OS X versions 10.6\r
-        and earlier and the Projucer live build.\r
-\r
-        @tags{Core}\r
-    */\r
-    template <typename>\r
-    class function;\r
-\r
-    #ifndef DOXYGEN\r
-    template <typename Result, typename... Arguments>\r
-    class function<Result (Arguments...)>\r
-    {\r
-    public:\r
-        /** Creates an empty function. */\r
-        function() noexcept {}\r
-\r
-        /** Creates an empty function. */\r
-        function (decltype (nullptr)) noexcept {}\r
-\r
-        /** Creates a function targeting the provided Functor. */\r
-        template <typename Functor>\r
-        function (Functor f)\r
-        {\r
-            functorHolderHelper = getFunctorStorage (sizeof (FunctorHolder<Functor, Result, Arguments...>));\r
-            new (functorHolderHelper) FunctorHolder<Functor, Result, Arguments...> (f);\r
-        }\r
-\r
-        /** Copy constructor. */\r
-        function (function const& other)\r
-        {\r
-            copy (other);\r
-        }\r
-\r
-        /** Move constructor */\r
-        function (function&& other)\r
-        {\r
-            move (other);\r
-        }\r
-\r
-        /** Destructor. */\r
-        ~function()\r
-        {\r
-            release();\r
-        }\r
-\r
-        /** Replaces the contents of this function with the contents of another. */\r
-        function& operator= (function const& other)\r
-        {\r
-            release();\r
-            copy (other);\r
-\r
-            return *this;\r
-        }\r
-\r
-        /** Moves the contents of another function into this one. */\r
-        function& operator= (function&& other)\r
-        {\r
-            release();\r
-            move (other);\r
-\r
-            return *this;\r
-        }\r
-\r
-        /** Allows conditional expressions to test if this function is empty. */\r
-        explicit operator bool() const noexcept\r
-        {\r
-            return functorHolderHelper != nullptr;\r
-        }\r
-\r
-        /** Swaps the contents of this function with another. After this operation the\r
-            two functions will be pointing at each other's targets. */\r
-        void swap (function& other)\r
-        {\r
-            function<Result (Arguments...)> tmp (*this);\r
-            *this = other;\r
-            other = tmp;\r
-        }\r
-\r
-        /** Invokes the target of this function. */\r
-        Result operator() (Arguments... args) const\r
-        {\r
-            return (*functorHolderHelper) (std::forward<Arguments> (args)...);\r
-        }\r
-\r
-        bool operator== (decltype (nullptr)) const noexcept     { return (functorHolderHelper == nullptr); }\r
-        bool operator!= (decltype (nullptr)) const noexcept     { return (functorHolderHelper != nullptr); }\r
-\r
-    private:\r
-        //==============================================================================\r
-        template <typename ReturnType, typename... Args>\r
-        struct FunctorHolderBase\r
-        {\r
-            virtual ~FunctorHolderBase() {}\r
-            virtual int getSize() const noexcept = 0;\r
-            virtual void copy (void*) const = 0;\r
-            virtual ReturnType operator()(Args...) = 0;\r
-        };\r
-\r
-        template <typename Functor, typename ReturnType, typename... Args>\r
-        struct FunctorHolder : FunctorHolderBase<Result, Arguments...>\r
-        {\r
-            FunctorHolder (Functor func) : f (func) {}\r
-\r
-            int getSize() const noexcept override final\r
-            {\r
-                return sizeof (*this);\r
-            }\r
-\r
-            void copy (void* destination) const override final\r
-            {\r
-                new (destination) FunctorHolder (f);\r
-            }\r
-\r
-            ReturnType operator()(Args... args) override final\r
-            {\r
-                return f (std::forward<Arguments> (args)...);\r
-            }\r
-\r
-            Functor f;\r
-        };\r
-\r
-        FunctorHolderBase<Result, Arguments...>* getFunctorStorage (int size)\r
-        {\r
-            return reinterpret_cast<FunctorHolderBase<Result, Arguments...>*>\r
-                       (size > functorHolderStackSize ? new char [static_cast<unsigned long> (size)]\r
-                                                      : &(stackFunctorStorage[0]));\r
-        }\r
-\r
-        void copy (function const& other)\r
-        {\r
-            if (other.functorHolderHelper != nullptr)\r
-            {\r
-                functorHolderHelper = getFunctorStorage (other.functorHolderHelper->getSize());\r
-                other.functorHolderHelper->copy (functorHolderHelper);\r
-            }\r
-        }\r
-\r
-        void move (function& other)\r
-        {\r
-            if (other.functorHolderHelper != nullptr)\r
-            {\r
-                if (other.functorHolderHelper->getSize() > functorHolderStackSize)\r
-                {\r
-                    functorHolderHelper = other.functorHolderHelper;\r
-                }\r
-                else\r
-                {\r
-                    std::copy (other.stackFunctorStorage, other.stackFunctorStorage + functorHolderStackSize,\r
-                               stackFunctorStorage);\r
-                    functorHolderHelper = reinterpret_cast<FunctorHolderBase<Result, Arguments...>*> (&(stackFunctorStorage[0]));\r
-                }\r
-\r
-                other.functorHolderHelper = nullptr;\r
-            }\r
-        }\r
-\r
-        void release()\r
-        {\r
-            if (functorHolderHelper != nullptr)\r
-            {\r
-                functorHolderHelper->~FunctorHolderBase<Result, Arguments...>();\r
-                functorHolderHelper = nullptr;\r
-            }\r
-        }\r
-\r
-        static const int functorHolderStackSize = 24;\r
-        char stackFunctorStorage[functorHolderStackSize];\r
-\r
-        FunctorHolderBase<Result, Arguments...>* functorHolderHelper = nullptr;\r
-    };\r
-    #endif\r
-}\r
index 83e8522d0a70c91dfbab08179c76f6b1f6d8538e..8808d1707e9d2d3483335f80e29c06dbb90a9925 100644 (file)
@@ -213,6 +213,62 @@ DECLARE_JNI_CLASS_WITH_BYTECODE (HTTPStream, "com/roli/juce/JuceHTTPStream", 16,
 DECLARE_JNI_CLASS (AndroidInputStream, "java/io/InputStream")\r
 #undef JNI_CLASS_MEMBERS\r
 \r
+//==============================================================================\r
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
+  METHOD (acquire, "acquire", "()V") \\r
+  METHOD (release, "release", "()V") \\r
+\r
+DECLARE_JNI_CLASS (AndroidMulticastLock, "android/net/wifi/WifiManager$MulticastLock")\r
+#undef JNI_CLASS_MEMBERS\r
+\r
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
+  METHOD (createMulticastLock, "createMulticastLock", "(Ljava/lang/String;)Landroid/net/wifi/WifiManager$MulticastLock;") \\r
+\r
+DECLARE_JNI_CLASS (AndroidWifiManager, "android/net/wifi/WifiManager")\r
+#undef JNI_CLASS_MEMBERS\r
+\r
+static LocalRef<jobject> getMulticastLock()\r
+{\r
+    static LocalRef<jobject> multicastLock;\r
+    static bool hasChecked = false;\r
+\r
+    if (! hasChecked)\r
+    {\r
+        hasChecked = true;\r
+\r
+        auto* env = getEnv();\r
+\r
+        LocalRef<jobject> wifiManager (env->CallObjectMethod (getAppContext().get(),\r
+                                                              AndroidContext.getSystemService,\r
+                                                              javaString ("wifi").get()));\r
+\r
+        if (wifiManager != nullptr)\r
+        {\r
+            multicastLock = LocalRef<jobject> (env->CallObjectMethod (wifiManager.get(),\r
+                                                                      AndroidWifiManager.createMulticastLock,\r
+                                                                      javaString ("JUCE_MulticastLock").get()));\r
+        }\r
+    }\r
+\r
+    return multicastLock;\r
+}\r
+\r
+JUCE_API void JUCE_CALLTYPE acquireMulticastLock()\r
+{\r
+    auto multicastLock = getMulticastLock();\r
+\r
+    if (multicastLock != nullptr)\r
+        getEnv()->CallVoidMethod (multicastLock.get(), AndroidMulticastLock.acquire);\r
+}\r
+\r
+JUCE_API void JUCE_CALLTYPE releaseMulticastLock()\r
+{\r
+    auto multicastLock = getMulticastLock();\r
+\r
+    if (multicastLock != nullptr)\r
+        getEnv()->CallVoidMethod (multicastLock.get(), AndroidMulticastLock.release);\r
+}\r
+\r
 //==============================================================================\r
 void MACAddress::findAllAddresses (Array<MACAddress>& /*result*/)\r
 {\r
old mode 100755 (executable)
new mode 100644 (file)
index 8d553e4..7ba2b5e
@@ -20,6 +20,9 @@
   ==============================================================================\r
 */\r
 \r
+#if JUCE_BELA\r
+extern "C" int cobalt_thread_mode();\r
+#endif\r
 \r
 namespace juce\r
 {\r
@@ -146,6 +149,8 @@ void CPUInformation::initialise() noexcept
     auto flags = getCpuInfo ("flags");\r
 \r
     hasMMX             = flags.contains ("mmx");\r
+    hasFMA3            = flags.contains ("fma");\r
+    hasFMA4            = flags.contains ("fma4");\r
     hasSSE             = flags.contains ("sse");\r
     hasSSE2            = flags.contains ("sse2");\r
     hasSSE3            = flags.contains ("sse3");\r
@@ -183,13 +188,18 @@ uint32 juce_millisecondsSinceStartup() noexcept
 \r
 int64 Time::getHighResolutionTicks() noexcept\r
 {\r
+    timespec t;\r
+\r
    #if JUCE_BELA\r
-    return rt_timer_read() / 1000;\r
+    if (cobalt_thread_mode() == 0x200 /*XNRELAX*/)\r
+        clock_gettime (CLOCK_MONOTONIC, &t);\r
+    else\r
+        __wrap_clock_gettime (CLOCK_MONOTONIC, &t);\r
    #else\r
-    timespec t;\r
     clock_gettime (CLOCK_MONOTONIC, &t);\r
-    return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000);\r
    #endif\r
+\r
+    return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000);\r
 }\r
 \r
 int64 Time::getHighResolutionTicksPerSecond() noexcept\r
index 0eac3a315e14d11494b8b4aba94b11b779f5f033..eb02c1710ee0cf6c4655c8b1c86219f9e5d408f4 100644 (file)
   ==============================================================================\r
 */\r
 \r
-\r
-// This hack is a workaround for a bug (?) in Apple's 10.11 SDK headers\r
-// which cause some configurations of Clang to throw out a spurious error..\r
 #if JUCE_PROJUCER_LIVE_BUILD && (defined (__APPLE_CPP__) || defined(__APPLE_CC__))\r
+\r
+ // This hack is a workaround for a bug (?) in Apple's 10.11 SDK headers\r
+ // which cause some configurations of Clang to throw out a spurious error..\r
  #include <CoreFoundation/CFAvailability.h>\r
  #undef CF_OPTIONS\r
  #define CF_OPTIONS(_type, _name) _type _name; enum\r
  #define _Nullable\r
  #define _Nonnull\r
 \r
- // In later versions of libc++ these methods are defined in the functional header,\r
- // which we don't compile in the live-build engine, so we'll define them here\r
- #if defined (_LIBCPP_VERSION) && _LIBCPP_VERSION >= 7000\r
-  #include <memory>\r
-\r
-  namespace std { inline namespace __1 {\r
-      template <class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2>\r
-      pair<_ForwardIterator1, _ForwardIterator1> _LIBCPP_CONSTEXPR_AFTER_CXX11\r
-      __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,\r
-               _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred,\r
-               forward_iterator_tag, forward_iterator_tag)\r
-      {\r
-          if (__first2 == __last2)\r
-              return make_pair(__first1, __first1);  // Everything matches an empty sequence\r
-          while (true)\r
-          {\r
-              // Find first element in sequence 1 that matchs *__first2, with a mininum of loop checks\r
-              while (true)\r
-              {\r
-                  if (__first1 == __last1)  // return __last1 if no element matches *__first2\r
-                      return make_pair(__last1, __last1);\r
-                  if (__pred(*__first1, *__first2))\r
-                      break;\r
-                  ++__first1;\r
-              }\r
-              // *__first1 matches *__first2, now match elements after here\r
-              _ForwardIterator1 __m1 = __first1;\r
-              _ForwardIterator2 __m2 = __first2;\r
-              while (true)\r
-              {\r
-                  if (++__m2 == __last2)  // If pattern exhausted, __first1 is the answer (works for 1 element pattern)\r
-                      return make_pair(__first1, __m1);\r
-                  if (++__m1 == __last1)  // Otherwise if source exhaused, pattern not found\r
-                      return make_pair(__last1, __last1);\r
-                  if (!__pred(*__m1, *__m2))  // if there is a mismatch, restart with a new __first1\r
-                  {\r
-                      ++__first1;\r
-                      break;\r
-                  }  // else there is a match, check next elements\r
-              }\r
-          }\r
-      }\r
-\r
-      template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2>\r
-      _LIBCPP_CONSTEXPR_AFTER_CXX11\r
-      pair<_RandomAccessIterator1, _RandomAccessIterator1>\r
-      __search(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,\r
-               _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __pred,\r
-               random_access_iterator_tag, random_access_iterator_tag)\r
-      {\r
-          typedef typename iterator_traits<_RandomAccessIterator1>::difference_type _D1;\r
-          typedef typename iterator_traits<_RandomAccessIterator2>::difference_type _D2;\r
-          // Take advantage of knowing source and pattern lengths.  Stop short when source is smaller than pattern\r
-          const _D2 __len2 = __last2 - __first2;\r
-          if (__len2 == 0)\r
-              return make_pair(__first1, __first1);\r
-          const _D1 __len1 = __last1 - __first1;\r
-          if (__len1 < __len2)\r
-              return make_pair(__last1, __last1);\r
-          const _RandomAccessIterator1 __s = __last1 - (__len2 - 1);  // Start of pattern match can't go beyond here\r
-\r
-          while (true)\r
-          {\r
-              while (true)\r
-              {\r
-                  if (__first1 == __s)\r
-                      return make_pair(__last1, __last1);\r
-                  if (__pred(*__first1, *__first2))\r
-                      break;\r
-                  ++__first1;\r
-              }\r
-\r
-              _RandomAccessIterator1 __m1 = __first1;\r
-              _RandomAccessIterator2 __m2 = __first2;\r
-              while (true)\r
-              {\r
-                  if (++__m2 == __last2)\r
-                      return make_pair(__first1, __first1 + __len2);\r
-                  ++__m1;          // no need to check range on __m1 because __s guarantees we have enough source\r
-                  if (!__pred(*__m1, *__m2))\r
-                  {\r
-                      ++__first1;\r
-                      break;\r
-                  }\r
-              }\r
-          }\r
-      }\r
-  } }\r
- #endif\r
+ // A workaround for compiling the 10.15 headers with an older compiler version\r
+ #undef API_UNAVAILABLE_BEGIN\r
+ #define API_UNAVAILABLE_BEGIN(...)\r
+ #undef API_UNAVAILABLE_END\r
+ #define API_UNAVAILABLE_END\r
 #endif\r
index 1446ca1f82097a394194f089eb5a36364d545350..53031211121ea359a186dcfb9ab65b95ecad677a 100644 (file)
@@ -415,10 +415,7 @@ bool JUCE_CALLTYPE Process::openDocument (const String& fileName, const String&
         NSWorkspace* workspace = [NSWorkspace sharedWorkspace];\r
 \r
         if (parameters.isEmpty())\r
-            // NB: the length check here is because of strange failures involving long filenames,\r
-            // probably due to filesystem name length limitations..\r
-            return (fileName.length() < 1024 && [workspace openFile: juceStringToNS (fileName)])\r
-                    || [workspace openURL: filenameAsURL];\r
+            return [workspace openURL: filenameAsURL];\r
 \r
         const File file (fileName);\r
 \r
index 885a45d8ede1c3521584bb8122fdf7ebc1e6b270..588886084458a6114a8f5a93b0bce88daf2cc4b7 100644 (file)
@@ -81,10 +81,14 @@ void CPUInformation::initialise() noexcept
     has3DNow = (b & (1u << 31)) != 0;\r
     hasSSE3  = (c & (1u <<  0)) != 0;\r
     hasSSSE3 = (c & (1u <<  9)) != 0;\r
+    hasFMA3  = (c & (1u << 12)) != 0;\r
     hasSSE41 = (c & (1u << 19)) != 0;\r
     hasSSE42 = (c & (1u << 20)) != 0;\r
     hasAVX   = (c & (1u << 28)) != 0;\r
 \r
+    SystemStatsHelpers::doCPUID (a, b, c, d, 0x80000001);\r
+    hasFMA4  = (c & (1u << 16)) != 0;\r
+\r
     SystemStatsHelpers::doCPUID (a, b, c, d, 7);\r
     hasAVX2            = (b & (1u <<  5)) != 0;\r
     hasAVX512F         = (b & (1u << 16)) != 0;\r
index 36943c77a9b906a258db6260cd1cdc5a1a25d443..bd8084cf1187fdffa88bc50a0bd7509190e01374 100644 (file)
@@ -65,20 +65,10 @@ JUCE_API void JUCE_CALLTYPE Process::hide()
     }\r
 }\r
 \r
-JUCE_API void JUCE_CALLTYPE Process::raisePrivilege()\r
-{\r
-    jassertfalse;\r
-}\r
+JUCE_API void JUCE_CALLTYPE Process::raisePrivilege() {}\r
+JUCE_API void JUCE_CALLTYPE Process::lowerPrivilege() {}\r
 \r
-JUCE_API void JUCE_CALLTYPE Process::lowerPrivilege()\r
-{\r
-    jassertfalse;\r
-}\r
-\r
-JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority)\r
-{\r
-    // xxx\r
-}\r
+JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority) {}\r
 \r
 //==============================================================================\r
 JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger() noexcept\r
index e035a107a2b0dc8fab1c916f79be59bf1010e40f..5d30962c43f1e2a18166d234ccc22c85e3a570b7 100644 (file)
@@ -40,95 +40,6 @@ void CriticalSection::enter() const noexcept        { pthread_mutex_lock (&lock)
 bool CriticalSection::tryEnter() const noexcept     { return pthread_mutex_trylock (&lock) == 0; }\r
 void CriticalSection::exit() const noexcept         { pthread_mutex_unlock (&lock); }\r
 \r
-//==============================================================================\r
-WaitableEvent::WaitableEvent (bool useManualReset) noexcept\r
-    : triggered (false), manualReset (useManualReset)\r
-{\r
-    pthread_cond_init (&condition, {});\r
-\r
-    pthread_mutexattr_t atts;\r
-    pthread_mutexattr_init (&atts);\r
-   #if ! JUCE_ANDROID\r
-    pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT);\r
-   #endif\r
-    pthread_mutex_init (&mutex, &atts);\r
-    pthread_mutexattr_destroy (&atts);\r
-}\r
-\r
-WaitableEvent::~WaitableEvent() noexcept\r
-{\r
-    pthread_cond_destroy (&condition);\r
-    pthread_mutex_destroy (&mutex);\r
-}\r
-\r
-bool WaitableEvent::wait (int timeOutMillisecs) const noexcept\r
-{\r
-    pthread_mutex_lock (&mutex);\r
-\r
-    if (! triggered)\r
-    {\r
-        if (timeOutMillisecs < 0)\r
-        {\r
-            do\r
-            {\r
-                pthread_cond_wait (&condition, &mutex);\r
-            }\r
-            while (! triggered);\r
-        }\r
-        else\r
-        {\r
-            struct timeval now;\r
-            gettimeofday (&now, nullptr);\r
-\r
-            struct timespec time;\r
-            time.tv_sec  = now.tv_sec  + (timeOutMillisecs / 1000);\r
-            time.tv_nsec = (now.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000;\r
-\r
-            if (time.tv_nsec >= 1000000000)\r
-            {\r
-                time.tv_nsec -= 1000000000;\r
-                time.tv_sec++;\r
-            }\r
-\r
-            do\r
-            {\r
-                if (pthread_cond_timedwait (&condition, &mutex, &time) == ETIMEDOUT)\r
-                {\r
-                    pthread_mutex_unlock (&mutex);\r
-                    return false;\r
-                }\r
-            }\r
-            while (! triggered);\r
-        }\r
-    }\r
-\r
-    if (! manualReset)\r
-        triggered = false;\r
-\r
-    pthread_mutex_unlock (&mutex);\r
-    return true;\r
-}\r
-\r
-void WaitableEvent::signal() const noexcept\r
-{\r
-    pthread_mutex_lock (&mutex);\r
-\r
-    if (! triggered)\r
-    {\r
-        triggered = true;\r
-        pthread_cond_broadcast (&condition);\r
-    }\r
-\r
-    pthread_mutex_unlock (&mutex);\r
-}\r
-\r
-void WaitableEvent::reset() const noexcept\r
-{\r
-    pthread_mutex_lock (&mutex);\r
-    triggered = false;\r
-    pthread_mutex_unlock (&mutex);\r
-}\r
-\r
 //==============================================================================\r
 void JUCE_CALLTYPE Thread::sleep (int millisecs)\r
 {\r
@@ -1242,7 +1153,7 @@ public:
                 if (numBytesRead > 0 || feof (readHandle))\r
                     return numBytesRead;\r
 \r
-                // signal occured during fread() so try again\r
+                // signal occurred during fread() so try again\r
                 if (ferror (readHandle) && errno == EINTR)\r
                     continue;\r
 \r
index fa0befe2554213f0bce6ce4273f1f786befdf46b..5c74c207e6869cb362248fc7a63dc727ca3de224 100644 (file)
@@ -144,11 +144,15 @@ void CPUInformation::initialise() noexcept
     hasSSE2  = (info[3] & (1 << 26)) != 0;\r
     hasSSE3  = (info[2] & (1 <<  0)) != 0;\r
     hasAVX   = (info[2] & (1 << 28)) != 0;\r
+    hasFMA3  = (info[2] & (1 << 12)) != 0;\r
     hasSSSE3 = (info[2] & (1 <<  9)) != 0;\r
     hasSSE41 = (info[2] & (1 << 19)) != 0;\r
     hasSSE42 = (info[2] & (1 << 20)) != 0;\r
     has3DNow = (info[1] & (1 << 31)) != 0;\r
 \r
+    callCPUID (info, 0x80000001);\r
+    hasFMA4  = (info[2] & (1 << 16)) != 0;\r
+\r
     callCPUID (info, 7);\r
 \r
     hasAVX2            = (info[1] & (1 << 5))   != 0;\r
@@ -185,32 +189,63 @@ static DebugFlagsInitialiser debugFlagsInitialiser;
 #endif\r
 \r
 //==============================================================================\r
-RTL_OSVERSIONINFOW getWindowsVersionInfo()\r
-{\r
-    RTL_OSVERSIONINFOW versionInfo = { 0 };\r
-\r
-    if (auto* moduleHandle = ::GetModuleHandleW (L"ntdll.dll"))\r
-    {\r
-        using RtlGetVersion = LONG (WINAPI*) (PRTL_OSVERSIONINFOW);\r
-\r
-        if (auto* rtlGetVersion = (RtlGetVersion) ::GetProcAddress (moduleHandle, "RtlGetVersion"))\r
-        {\r
-            versionInfo.dwOSVersionInfoSize = sizeof (versionInfo);\r
-            LONG STATUS_SUCCESS = 0;\r
-\r
-            if (rtlGetVersion (&versionInfo) != STATUS_SUCCESS)\r
-                versionInfo = { 0 };\r
-        }\r
-    }\r
-\r
-    return versionInfo;\r
-}\r
+#if JUCE_MINGW\r
+ static uint32 getWindowsVersion()\r
+ {\r
+     auto filename = _T("kernel32.dll");\r
+     DWORD handle = 0;\r
+\r
+     if (auto size = GetFileVersionInfoSize (filename, &handle))\r
+     {\r
+         HeapBlock<char> data (size);\r
+\r
+         if (GetFileVersionInfo (filename, handle, size, data))\r
+         {\r
+             VS_FIXEDFILEINFO* info = nullptr;\r
+             UINT verSize = 0;\r
+\r
+             if (VerQueryValue (data, (LPCTSTR) _T("\\"), (void**) &info, &verSize))\r
+                 if (size > 0 && info != nullptr && info->dwSignature == 0xfeef04bd)\r
+                     return (uint32) info->dwFileVersionMS;\r
+         }\r
+     }\r
+\r
+     return 0;\r
+ }\r
+#else\r
+ RTL_OSVERSIONINFOW getWindowsVersionInfo()\r
+ {\r
+     RTL_OSVERSIONINFOW versionInfo = { 0 };\r
+\r
+     if (auto* moduleHandle = ::GetModuleHandleW (L"ntdll.dll"))\r
+     {\r
+         using RtlGetVersion = LONG (WINAPI*) (PRTL_OSVERSIONINFOW);\r
+\r
+         if (auto* rtlGetVersion = (RtlGetVersion) ::GetProcAddress (moduleHandle, "RtlGetVersion"))\r
+         {\r
+             versionInfo.dwOSVersionInfoSize = sizeof (versionInfo);\r
+             LONG STATUS_SUCCESS = 0;\r
+\r
+             if (rtlGetVersion (&versionInfo) != STATUS_SUCCESS)\r
+                 versionInfo = { 0 };\r
+         }\r
+     }\r
+\r
+     return versionInfo;\r
+ }\r
+#endif\r
 \r
 SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()\r
 {\r
+   #if JUCE_MINGW\r
+    auto v = getWindowsVersion();\r
+    auto major = (v >> 16) & 0xff;\r
+    auto minor = (v >> 0)  & 0xff;\r
+   #else\r
     auto versionInfo = getWindowsVersionInfo();\r
     auto major = versionInfo.dwMajorVersion;\r
     auto minor = versionInfo.dwMinorVersion;\r
+   #endif\r
 \r
     jassert (major <= 10); // need to add support for new version!\r
 \r
index aa826d017df218ac9e95bde3671c3cd1e1ac1977..749bf7476fabb96b563f26c4dcfd4fe5ac6ca707 100644 (file)
@@ -48,20 +48,6 @@ bool CriticalSection::tryEnter() const noexcept     { return TryEnterCriticalSec
 void CriticalSection::exit() const noexcept         { LeaveCriticalSection ((CRITICAL_SECTION*) lock); }\r
 \r
 \r
-//==============================================================================\r
-WaitableEvent::WaitableEvent (const bool manualReset) noexcept\r
-    : handle (CreateEvent (0, manualReset ? TRUE : FALSE, FALSE, 0)) {}\r
-\r
-WaitableEvent::~WaitableEvent() noexcept        { CloseHandle (handle); }\r
-\r
-void WaitableEvent::signal() const noexcept     { SetEvent (handle); }\r
-void WaitableEvent::reset() const noexcept      { ResetEvent (handle); }\r
-\r
-bool WaitableEvent::wait (const int timeOutMs) const noexcept\r
-{\r
-    return WaitForSingleObject (handle, (DWORD) timeOutMs) == WAIT_OBJECT_0;\r
-}\r
-\r
 //==============================================================================\r
 void JUCE_API juce_threadEntryPoint (void*);\r
 \r
@@ -258,15 +244,8 @@ void JUCE_CALLTYPE Process::setCurrentModuleInstanceHandle (void* const newHandl
     currentModuleHandle = newHandle;\r
 }\r
 \r
-void JUCE_CALLTYPE Process::raisePrivilege()\r
-{\r
-    jassertfalse; // xxx not implemented\r
-}\r
-\r
-void JUCE_CALLTYPE Process::lowerPrivilege()\r
-{\r
-    jassertfalse; // xxx not implemented\r
-}\r
+void JUCE_CALLTYPE Process::raisePrivilege() {}\r
+void JUCE_CALLTYPE Process::lowerPrivilege() {}\r
 \r
 void JUCE_CALLTYPE Process::terminate()\r
 {\r
index 1c15fc56453367da354c38e90722805c18ca77a6..1e28be5a617b41c6334b845e8c607fbfe374e47a 100644 (file)
@@ -36,9 +36,6 @@ namespace juce
  using juce_socklen_t       = int;\r
  using juce_recvsend_size_t = int;\r
  using SocketHandle         = SOCKET;\r
- #if ! JUCE_MINGW\r
-  using pollfd              = WSAPOLLFD;\r
- #endif\r
  static const SocketHandle invalidSocket = INVALID_SOCKET;\r
 #elif JUCE_ANDROID\r
  using juce_socklen_t       = socklen_t;\r
@@ -286,9 +283,25 @@ namespace SocketHelpers
         if (! lock.isLocked())\r
             return -1;\r
 \r
+        auto hasErrorOccurred = [&handle] () -> bool\r
+        {\r
+            auto h = handle.load();\r
+\r
+            if (h == invalidSocket)\r
+                return true;\r
+\r
+            int opt;\r
+            juce_socklen_t len = sizeof (opt);\r
+\r
+            if (getsockopt (h, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0  || opt != 0)\r
+                return true;\r
+\r
+            return false;\r
+        };\r
+\r
         auto h = handle.load();\r
 \r
-       #if JUCE_MINGW\r
+       #if JUCE_WINDOWS || JUCE_MINGW\r
         struct timeval timeout;\r
         struct timeval* timeoutp;\r
 \r
@@ -309,12 +322,15 @@ namespace SocketHelpers
         FD_ZERO (&wset);\r
         FD_SET (h, &wset);\r
 \r
-        fd_set* const prset = forReading ? &rset : nullptr;\r
-        fd_set* const pwset = forReading ? nullptr : &wset;\r
+        fd_set* prset = forReading ? &rset : nullptr;\r
+        fd_set* pwset = forReading ? nullptr : &wset;\r
 \r
-        if (select ((int) h + 1, prset, pwset, 0, timeoutp) < 0)\r
+        // NB - need to use select() here as WSAPoll is broken on Windows\r
+        if (select ((int) h + 1, prset, pwset, nullptr, timeoutp) < 0 || hasErrorOccurred())\r
             return -1;\r
-       #else\r
+\r
+        return FD_ISSET (h, forReading ? &rset : &wset) ? 1 : 0;\r
+      #else\r
         short eventsFlag = (forReading ? POLLIN : POLLOUT);\r
         pollfd pfd { (SocketHandle) h, eventsFlag, 0 };\r
 \r
@@ -322,46 +338,17 @@ namespace SocketHelpers
 \r
         for (;;)\r
         {\r
-           #if JUCE_WINDOWS\r
-            result = WSAPoll (&pfd, 1, timeoutMsecs);\r
-           #else\r
             result = poll (&pfd, 1, timeoutMsecs);\r
-           #endif\r
 \r
-            if (result >= 0\r
-               #if JUCE_WINDOWS\r
-                || result == SOCKET_ERROR\r
-               #else\r
-                || errno != EINTR\r
-               #endif\r
-                )\r
-            {\r
+            if (result >= 0 || errno != EINTR)\r
                 break;\r
-            }\r
         }\r
 \r
-        if (result < 0)\r
-            return -1;\r
-       #endif\r
-\r
-        // we are closing\r
-        if (handle.load() < 0)\r
+        if (result < 0 || hasErrorOccurred())\r
             return -1;\r
 \r
-        {\r
-            int opt;\r
-            juce_socklen_t len = sizeof (opt);\r
-\r
-            if (getsockopt (h, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0\r
-                 || opt != 0)\r
-                return -1;\r
-        }\r
-\r
-       #if JUCE_MINGW\r
-        return FD_ISSET (h, forReading ? &rset : &wset) ? 1 : 0;\r
-       #else\r
         return (pfd.revents & eventsFlag) != 0;\r
-       #endif\r
+      #endif\r
     }\r
 \r
     static addrinfo* getAddressInfo (bool isDatagram, const String& hostName, int portNumber)\r
index 26169129a514fde0b694d184744356d70b1dcb78..56f2a3cecbecc7a78190cc1aa3257c2d4d4c8817 100644 (file)
@@ -82,7 +82,7 @@ struct FallbackDownloadTask  : public URL::DownloadTask,
                 break;\r
         }\r
 \r
-        fileStream->flush();\r
+        fileStream.reset();\r
 \r
         if (threadShouldExit() || stream->isError())\r
             error = true;\r
@@ -97,7 +97,7 @@ struct FallbackDownloadTask  : public URL::DownloadTask,
     }\r
 \r
     //==============================================================================\r
-    const std::unique_ptr<FileOutputStream> fileStream;\r
+    std::unique_ptr<FileOutputStream> fileStream;\r
     const std::unique_ptr<WebInputStream> stream;\r
     const size_t bufferSize;\r
     HeapBlock<char> buffer;\r
index 18602e7b4e9d87312b542319809c16a11451b33c..b4a81944401a09aec2322520acf312daefde3698 100644 (file)
@@ -190,10 +190,10 @@ class JUCE_API WebInputStream : public InputStream
         The position is an absolute number of bytes from the stream's start.\r
 \r
         For a WebInputStream, this method will fail if wantedPos is smaller\r
-        than the curent position. If wantedPos is greater than the current\r
+        than the current position. If wantedPos is greater than the current\r
         position, then calling setPosition is the same as calling read, i.e.\r
         the skipped data will still be downloaded, although skipped bytes will\r
-        be discarded immedietely.\r
+        be discarded immediately.\r
 \r
         @returns  true if the stream manages to reposition itself correctly\r
         @see getPosition\r
index 0a2480306ee286cf887f3be0807ebff7b2c36b95..231a7f5fb9244a62cc2f199bce8b40b97a325f79 100644 (file)
@@ -45,7 +45,7 @@ public:
 \r
         Note that the destination block will always be larger than the amount of data\r
         that has been written to the stream, because the MemoryOutputStream keeps some\r
-        spare capactity at its end. To trim the block's size down to fit the actual\r
+        spare capacity at its end. To trim the block's size down to fit the actual\r
         data, call flush(), or delete the MemoryOutputStream.\r
 \r
         @param memoryBlockToWriteTo             the block into which new data will be written.\r
index 34aed37315a0f59fcbadc358427c84891116c7da..68c81a03c959fef78c097374edd9cc0caea0949d 100644 (file)
@@ -29,7 +29,7 @@
 */\r
 #define JUCE_MAJOR_VERSION      5\r
 #define JUCE_MINOR_VERSION      4\r
-#define JUCE_BUILDNUMBER        5\r
+#define JUCE_BUILDNUMBER        6\r
 \r
 /** Current JUCE version number.\r
 \r
 #include <sstream>\r
 #include <iomanip>\r
 #include <map>\r
+#include <cstddef>\r
+#include <unordered_set>\r
+#include <mutex>\r
+#include <condition_variable>\r
+#include <queue>\r
 \r
 //==============================================================================\r
 #include "juce_CompilerSupport.h"\r
 #undef minor\r
 #undef KeyPress\r
 \r
-// Include a replacement for std::function\r
-#if JUCE_PROJUCER_LIVE_BUILD\r
- #include "../misc/juce_StdFunctionCompat.h"\r
-#endif\r
-\r
 //==============================================================================\r
 // DLL building settings on Windows\r
 #if JUCE_MSVC\r
index 0520840c4ae5fd4a8549e4db83c490f406592433..2ea90f80a05332056e6e891d809df1dac3fb06c5 100644 (file)
@@ -90,9 +90,9 @@ struct CPUInformation
 \r
     int numLogicalCPUs = 0, numPhysicalCPUs = 0;\r
 \r
-    bool hasMMX      = false, hasSSE        = false, hasSSE2       = false, hasSSE3 = false,\r
-         has3DNow    = false, hasSSSE3      = false, hasSSE41      = false,\r
-         hasSSE42    = false, hasAVX        = false, hasAVX2       = false,\r
+    bool hasMMX      = false, hasSSE        = false, hasSSE2       = false, hasSSE3       = false,\r
+         has3DNow    = false, hasFMA3       = false, hasFMA4       = false, hasSSSE3      = false,\r
+         hasSSE41    = false, hasSSE42      = false, hasAVX        = false, hasAVX2       = false,\r
          hasAVX512F  = false, hasAVX512BW   = false, hasAVX512CD   = false,\r
          hasAVX512DQ = false, hasAVX512ER   = false, hasAVX512IFMA = false,\r
          hasAVX512PF = false, hasAVX512VBMI = false, hasAVX512VL   = false,\r
@@ -110,6 +110,8 @@ int SystemStats::getNumCpus() noexcept          { return getCPUInformation().num
 int SystemStats::getNumPhysicalCpus() noexcept  { return getCPUInformation().numPhysicalCPUs; }\r
 bool SystemStats::hasMMX() noexcept             { return getCPUInformation().hasMMX; }\r
 bool SystemStats::has3DNow() noexcept           { return getCPUInformation().has3DNow; }\r
+bool SystemStats::hasFMA3() noexcept            { return getCPUInformation().hasFMA3; }\r
+bool SystemStats::hasFMA4() noexcept            { return getCPUInformation().hasFMA4; }\r
 bool SystemStats::hasSSE() noexcept             { return getCPUInformation().hasSSE; }\r
 bool SystemStats::hasSSE2() noexcept            { return getCPUInformation().hasSSE2; }\r
 bool SystemStats::hasSSE3() noexcept            { return getCPUInformation().hasSSE3; }\r
index 9234a23a5d3705cadb4f910dc704d73f35bb1362..7926c32b904fbace4544f2d4ffc2acd31df7701c 100644 (file)
@@ -172,6 +172,8 @@ public:
 \r
     static bool hasMMX() noexcept;             /**< Returns true if Intel MMX instructions are available. */\r
     static bool has3DNow() noexcept;           /**< Returns true if AMD 3DNOW instructions are available. */\r
+    static bool hasFMA3() noexcept;            /**< Returns true if AMD FMA3 instructions are available. */\r
+    static bool hasFMA4() noexcept;            /**< Returns true if AMD FMA4 instructions are available. */\r
     static bool hasSSE() noexcept;             /**< Returns true if Intel SSE instructions are available. */\r
     static bool hasSSE2() noexcept;            /**< Returns true if Intel SSE2 instructions are available. */\r
     static bool hasSSE3() noexcept;            /**< Returns true if Intel SSE3 instructions are available. */\r
index 1ff0e47447e5f6022246c715bce8a485948ccd1b..195341e0a3c575650784dc3473da22c1c2e6b101 100644 (file)
@@ -161,7 +161,7 @@ public:
         countries: fr be mc ch lu\r
         @endcode\r
 \r
-        The country codes are supposed to be 2-character ISO complient codes.\r
+        The country codes are supposed to be 2-character ISO compliant codes.\r
     */\r
     const StringArray& getCountryCodes() const            { return countryCodes; }\r
 \r
index 726fa193848b38b7640a3f172483984b2e7811bf..bc868ef7bf3f7525231fe31d33cf52ef17662599 100644 (file)
@@ -133,7 +133,7 @@ public:
     static void JUCE_CALLTYPE setCurrentModuleInstanceHandle (void* newHandle) noexcept;\r
    #endif\r
 \r
-   #if JUCE_MAC || DOXYGEN\r
+   #if (JUCE_MAC && JUCE_MODULE_AVAILABLE_juce_gui_basics) || DOXYGEN\r
     //==============================================================================\r
     /** OSX ONLY - Shows or hides the OSX dock icon for this app. */\r
     static void setDockIconVisible (bool isVisible);\r
index af607b7fa0f77ed569c363603edd820315a620f2..86f6afe221ae4416acfda344de4b972c4cbd942b 100644 (file)
@@ -38,22 +38,20 @@ ReadWriteLock::~ReadWriteLock() noexcept
 void ReadWriteLock::enterRead() const noexcept\r
 {\r
     while (! tryEnterRead())\r
-        waitEvent.wait (100);\r
+        readWaitEvent.wait (100);\r
 }\r
 \r
 bool ReadWriteLock::tryEnterRead() const noexcept\r
 {\r
-    const Thread::ThreadID threadId = Thread::getCurrentThreadId();\r
+    auto threadId = Thread::getCurrentThreadId();\r
 \r
     const SpinLock::ScopedLockType sl (accessLock);\r
 \r
-    for (int i = 0; i < readerThreads.size(); ++i)\r
+    for (auto& readerThread : readerThreads)\r
     {\r
-        ThreadRecursionCount& trc = readerThreads.getReference(i);\r
-\r
-        if (trc.threadID == threadId)\r
+        if (readerThread.threadID == threadId)\r
         {\r
-            trc.count++;\r
+            readerThread.count++;\r
             return true;\r
         }\r
     }\r
@@ -61,8 +59,7 @@ bool ReadWriteLock::tryEnterRead() const noexcept
     if (numWriters + numWaitingWriters == 0\r
          || (threadId == writerThreadId && numWriters > 0))\r
     {\r
-        ThreadRecursionCount trc = { threadId, 1 };\r
-        readerThreads.add (trc);\r
+        readerThreads.add ({ threadId, 1 });\r
         return true;\r
     }\r
 \r
@@ -71,19 +68,21 @@ bool ReadWriteLock::tryEnterRead() const noexcept
 \r
 void ReadWriteLock::exitRead() const noexcept\r
 {\r
-    const Thread::ThreadID threadId = Thread::getCurrentThreadId();\r
+    auto threadId = Thread::getCurrentThreadId();\r
     const SpinLock::ScopedLockType sl (accessLock);\r
 \r
     for (int i = 0; i < readerThreads.size(); ++i)\r
     {\r
-        ThreadRecursionCount& trc = readerThreads.getReference(i);\r
+        auto& readerThread = readerThreads.getReference (i);\r
 \r
-        if (trc.threadID == threadId)\r
+        if (readerThread.threadID == threadId)\r
         {\r
-            if (--(trc.count) == 0)\r
+            if (--(readerThread.count) == 0)\r
             {\r
                 readerThreads.remove (i);\r
-                waitEvent.signal();\r
+\r
+                readWaitEvent.signal();\r
+                writeWaitEvent.signal();\r
             }\r
 \r
             return;\r
@@ -96,14 +95,14 @@ void ReadWriteLock::exitRead() const noexcept
 //==============================================================================\r
 void ReadWriteLock::enterWrite() const noexcept\r
 {\r
-    const Thread::ThreadID threadId = Thread::getCurrentThreadId();\r
+    auto threadId = Thread::getCurrentThreadId();\r
     const SpinLock::ScopedLockType sl (accessLock);\r
 \r
     while (! tryEnterWriteInternal (threadId))\r
     {\r
         ++numWaitingWriters;\r
         accessLock.exit();\r
-        waitEvent.wait (100);\r
+        writeWaitEvent.wait (100);\r
         accessLock.enter();\r
         --numWaitingWriters;\r
     }\r
@@ -119,7 +118,7 @@ bool ReadWriteLock::tryEnterWriteInternal (Thread::ThreadID threadId) const noex
 {\r
     if (readerThreads.size() + numWriters == 0\r
          || threadId == writerThreadId\r
-         || (readerThreads.size() == 1 && readerThreads.getReference(0).threadID == threadId))\r
+         || (readerThreads.size() == 1 && readerThreads.getReference (0).threadID == threadId))\r
     {\r
         writerThreadId = threadId;\r
         ++numWriters;\r
@@ -139,7 +138,9 @@ void ReadWriteLock::exitWrite() const noexcept
     if (--numWriters == 0)\r
     {\r
         writerThreadId = {};\r
-        waitEvent.signal();\r
+\r
+        readWaitEvent.signal();\r
+        writeWaitEvent.signal();\r
     }\r
 }\r
 \r
index c954a87496c969230b267347a4db228734865286..28c5b725ce7a6332b7160df35deb03e43617c2c4 100644 (file)
@@ -126,7 +126,7 @@ public:
 private:\r
     //==============================================================================\r
     SpinLock accessLock;\r
-    WaitableEvent waitEvent;\r
+    WaitableEvent readWaitEvent, writeWaitEvent;\r
     mutable int numWaitingWriters = 0, numWriters = 0;\r
     mutable Thread::ThreadID writerThreadId = {};\r
 \r
index d39ca67aee21afec8a4fe9055c0b829fd5c64d26..21973e134cc56d69a6e87adc66311c5625f8b8bd 100644 (file)
@@ -76,7 +76,7 @@ public:
                                      again when a thread is free. */\r
     };\r
 \r
-    /** Peforms the actual work that this job needs to do.\r
+    /** Performs the actual work that this job needs to do.\r
 \r
         Your subclass must implement this method, in which is does its work.\r
 \r
index 61b0ea2f40310eaa5c8f860298f8ba37e7263a13..f661cff33774fe531975581d88534b91144c074b 100644 (file)
@@ -57,7 +57,7 @@ public:
         @returns    Your method should return the number of milliseconds which it would like to wait before being called\r
                     again. Returning 0 will make the thread call again as soon as possible (after possibly servicing\r
                     other busy clients). If you return a value below zero, your client will be removed from the list of clients,\r
-                    and won't be called again. The value you specify isn't a guaranteee, and is only used as a hint by the\r
+                    and won't be called again. The value you specify isn't a guarantee, and is only used as a hint by the\r
                     thread - the actual time before the next callback may be more or less than specified.\r
                     You can force the TimeSliceThread to wake up and poll again immediately by calling its notify() method.\r
     */\r
diff --git a/modules/juce_core/threads/juce_WaitableEvent.cpp b/modules/juce_core/threads/juce_WaitableEvent.cpp
new file mode 100644 (file)
index 0000000..8b01c4d
--- /dev/null
@@ -0,0 +1,70 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2017 - ROLI Ltd.\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   The code included in this file is provided under the terms of the ISC license\r
+   http://www.isc.org/downloads/software-support-policy/isc-license. Permission\r
+   To use, copy, modify, and/or distribute this software for any purpose with or\r
+   without fee is hereby granted provided that the above copyright notice and\r
+   this permission notice appear in all copies.\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+WaitableEvent::WaitableEvent (bool manualReset) noexcept\r
+    : useManualReset (manualReset)\r
+{\r
+}\r
+\r
+bool WaitableEvent::wait (int timeOutMilliseconds) const\r
+{\r
+    std::unique_lock<std::mutex> lock (mutex);\r
+\r
+    if (! triggered)\r
+    {\r
+        if (timeOutMilliseconds < 0)\r
+        {\r
+            condition.wait (lock, [this] { return triggered == true; });\r
+        }\r
+        else\r
+        {\r
+            if (! condition.wait_for (lock, std::chrono::milliseconds (timeOutMilliseconds),\r
+                                      [this] { return triggered == true; }))\r
+            {\r
+                return false;\r
+            }\r
+        }\r
+    }\r
+\r
+    if (! useManualReset)\r
+        reset();\r
+\r
+    return true;\r
+}\r
+\r
+void WaitableEvent::signal() const\r
+{\r
+    std::unique_lock<std::mutex> lock (mutex);\r
+\r
+    triggered = true;\r
+    condition.notify_all();\r
+}\r
+\r
+void WaitableEvent::reset() const\r
+{\r
+    triggered = false;\r
+}\r
+\r
+} // namespace juce\r
index 012b83ac69494d98a9d3ff7e41c980686137c75d..3e31a97723cd45003bd5ce43813f8753d7c2a0e8 100644 (file)
@@ -46,13 +46,6 @@ public:
     */\r
     explicit WaitableEvent (bool manualReset = false) noexcept;\r
 \r
-    /** Destructor.\r
-\r
-        If other threads are waiting on this object when it gets deleted, this\r
-        can cause nasty errors, so be careful!\r
-    */\r
-    ~WaitableEvent() noexcept;\r
-\r
     //==============================================================================\r
     /** Suspends the calling thread until the event has been signalled.\r
 \r
@@ -68,9 +61,8 @@ public:
         @returns    true if the object has been signalled, false if the timeout expires first.\r
         @see signal, reset\r
     */\r
-    bool wait (int timeOutMilliseconds = -1) const noexcept;\r
+    bool wait (int timeOutMilliseconds = -1) const;\r
 \r
-    //==============================================================================\r
     /** Wakes up any threads that are currently waiting on this object.\r
 \r
         If signal() is called when nothing is waiting, the next thread to call wait()\r
@@ -86,24 +78,20 @@ public:
 \r
         @see wait, reset\r
     */\r
-    void signal() const noexcept;\r
+    void signal() const;\r
 \r
-    //==============================================================================\r
     /** Resets the event to an unsignalled state.\r
         If it's not already signalled, this does nothing.\r
     */\r
-    void reset() const noexcept;\r
-\r
+    void reset() const;\r
 \r
 private:\r
     //==============================================================================\r
-   #if JUCE_WINDOWS\r
-    void* handle;\r
-   #else\r
-    mutable pthread_cond_t condition;\r
-    mutable pthread_mutex_t mutex;\r
-    mutable bool triggered, manualReset;\r
-   #endif\r
+    bool useManualReset;\r
+\r
+    mutable std::mutex mutex;\r
+    mutable std::condition_variable condition;\r
+    mutable std::atomic<bool> triggered { false };\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WaitableEvent)\r
 };\r
index 16b9cbe27d684ff225c30344bd23ac51db797456..4c4922553b2ce9f3dfce7880a34d47dcdd990660 100644 (file)
@@ -46,10 +46,10 @@ struct ZipFile::ZipEntryHolder
         entry.uncompressedSize = (int64) readUnalignedLittleEndianInt (buffer + 24);\r
         streamOffset           = (int64) readUnalignedLittleEndianInt (buffer + 42);\r
 \r
-        auto externalFileAttributes = (int32) readUnalignedLittleEndianInt (buffer + 38);\r
-        auto fileType   = (externalFileAttributes >> 28) & 0xf;\r
-\r
+        entry.externalFileAttributes = readUnalignedLittleEndianInt (buffer + 38);\r
+        auto fileType = (entry.externalFileAttributes >> 28) & 0xf;\r
         entry.isSymbolicLink = (fileType == 0xA);\r
+\r
         entry.filename = String::fromUTF8 (buffer + 46, fileNameLen);\r
     }\r
 \r
index 45173daa3754855a7aa50b36b65947071115cfbe..e3f8b7641f0977e32a822d5737fcbad0d79048bc 100644 (file)
@@ -82,6 +82,12 @@ public:
 \r
         /** True if the zip entry is a symbolic link. */\r
         bool isSymbolicLink;\r
+\r
+        /** Platform specific data. Depending on how the zip file was created this\r
+            may contain macOS and Linux file types, permissions and\r
+            setuid/setgid/sticky bits.\r
+        */\r
+        uint32 externalFileAttributes;\r
     };\r
 \r
     //==============================================================================\r
index f6cd04bc8154d54e1af7f277bfdfdd5d119aada6..57ab8c63c686c37ead964c0ff5b3eed25e0778a6 100644 (file)
@@ -73,11 +73,11 @@ public:
         @param buffer       The message that should be encrypted. See bufferSize on size\r
                             requirements!\r
         @param sizeOfMsg    The size of the message that should be encrypted in bytes\r
-        @param bufferSize   The size of the buffer in bytes. To accommodate the encypted\r
+        @param bufferSize   The size of the buffer in bytes. To accommodate the encrypted\r
                             data, the buffer must be larger than the message: the size of\r
                             the buffer needs to be equal or greater than the size of the\r
-                            message in bytes rounded to the next integer which is divisable\r
-                            by eight. If the message size in bytes is already divisable by eight\r
+                            message in bytes rounded to the next integer which is divisible\r
+                            by eight. If the message size in bytes is already divisible by eight\r
                             then you need to add eight bytes to the buffer size. If in doubt\r
                             simply use bufferSize = sizeOfMsg + 8.\r
 \r
index 86d5ca36c6960c46bf82514c510771d7409713a9..3ecee08229a27c28eb60ac5beac882c62601510b 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_cryptography\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE cryptography classes\r
-  description:      Classes for various basic cryptography functions, including RSA, Blowfish, MD5, SHA, etc.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
+  ID:                 juce_cryptography\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE cryptography classes\r
+  description:        Classes for various basic cryptography functions, including RSA, Blowfish, MD5, SHA, etc.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
 \r
-  dependencies:     juce_core\r
+  dependencies:       juce_core\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 85ec23f5419529031e1312295e379abb3094491a..e838b11e6a5572ef0e16455f9ada7742ecdde2fb 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_data_structures\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE data model helper classes\r
-  description:      Classes for undo/redo management, and smart data structures.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
+  ID:                 juce_data_structures\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE data model helper classes\r
+  description:        Classes for undo/redo management, and smart data structures.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
 \r
-  dependencies:     juce_events\r
+  dependencies:       juce_events\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 1145a68aeeaad96b25c44ea8e0616b35428bbff5..0f4f725a48d85b43d801f2c0a4e3e0255f82248d 100644 (file)
@@ -62,7 +62,7 @@ namespace juce
     will correspond to the order in which the property was added, or that it will remain\r
     constant when other properties are added or removed.\r
 \r
-    Listeners can be added to a ValueTree to be told when properies change and when\r
+    Listeners can be added to a ValueTree to be told when properties change and when\r
     sub-trees are added or removed.\r
 \r
     @see var, XmlElement\r
index 7f289cdf088d430a37fe6f4fae4ed5740f615736..b8c0074bfb7b34cdf5e00cd38670b3c92f0eca3c 100644 (file)
@@ -234,7 +234,7 @@ public:
         return AudioBlock (channels + channel, 1, startSample, numSamples);\r
     }\r
 \r
-    /** Returns a subset of continguous channels\r
+    /** Returns a subset of contiguous channels\r
         @param channelStart       First channel of the subset\r
         @param numChannelsToUse   Count of channels in the subset\r
     */\r
@@ -288,8 +288,8 @@ public:
     const AudioBlock& clear() const noexcept   { clearInternal(); return *this; }\r
 \r
     /** Fills the memory referenced by this AudioBlock with value. */\r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE fill (SampleType value)       noexcept   { fillInternal (value); return *this; }\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE fill (SampleType value) const noexcept   { fillInternal (value); return *this; }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE fill (NumericType value)       noexcept   { fillInternal (value); return *this; }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE fill (NumericType value) const noexcept   { fillInternal (value); return *this; }\r
 \r
     /** Copies the values in src to this block. */\r
     template <typename OtherSampleType>\r
@@ -297,25 +297,25 @@ public:
     template <typename OtherSampleType>\r
     const AudioBlock& copyFrom (const AudioBlock<OtherSampleType>& src) const noexcept   { copyFromInternal (src); return *this; }\r
 \r
-    /** Copy the values from a JUCE's AudioBuffer to this block.\r
+    /** Copy the values from an AudioBuffer to this block.\r
 \r
-        All indices and sizes are in the receiver's units, i.e. if SampleType is a\r
+        All indices and sizes are in this AudioBlock's units, i.e. if SampleType is a\r
         SIMDRegister then incrementing srcPos by one will increase the sample position\r
         in the AudioBuffer's units by a factor of SIMDRegister<SampleType>::SIMDNumElements.\r
     */\r
-    template <typename OtherSampleType>\r
-    AudioBlock&       copyFrom (const AudioBuffer<OtherSampleType>& src,\r
+    template <typename OtherNumericType>\r
+    AudioBlock&       copyFrom (const AudioBuffer<OtherNumericType>& src,\r
                                 size_t srcPos = 0, size_t dstPos = 0,\r
                                 size_t numElements = std::numeric_limits<size_t>::max())         { copyFromInternal (src, srcPos, dstPos, numElements); return *this; }\r
-    template <typename OtherSampleType>\r
-    const AudioBlock& copyFrom (const AudioBuffer<OtherSampleType>& src,\r
+    template <typename OtherNumericType>\r
+    const AudioBlock& copyFrom (const AudioBuffer<OtherNumericType>& src,\r
                                 size_t srcPos = 0, size_t dstPos = 0,\r
                                 size_t numElements = std::numeric_limits<size_t>::max()) const   { copyFromInternal (src, srcPos, dstPos, numElements); return *this; }\r
 \r
 \r
     /** Copies the values from this block to an AudioBuffer.\r
 \r
-        All indices and sizes are in the receiver's units, i.e. if SampleType is a\r
+        All indices and sizes are in this AudioBlock's units, i.e. if SampleType is a\r
         SIMDRegister then incrementing dstPos by one will increase the sample position\r
         in the AudioBuffer's units by a factor of SIMDRegister<SampleType>::SIMDNumElements.\r
     */\r
@@ -329,7 +329,8 @@ public:
         for (size_t ch = 0; ch < maxChannels; ++ch)\r
             FloatVectorOperations::copy (dst.getWritePointer (static_cast<int> (ch),\r
                                                               static_cast<int> (dstPos * sizeFactor)),\r
-                                         getChannelPointer (ch) + srcPos, n);\r
+                                         getDataPointer (ch) + (srcPos * sizeFactor),\r
+                                         n);\r
     }\r
 \r
     /** Move memory within this block from the position srcPos to the position dstPos.\r
@@ -375,8 +376,8 @@ public:
 \r
     //==============================================================================\r
     /** Adds a fixed value to the elements in this block. */\r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE add (SampleType value)       noexcept   { addInternal (value); return *this; }\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE add (SampleType value) const noexcept   { addInternal (value); return *this; }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE add (NumericType value)       noexcept   { addInternal (value); return *this; }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE add (NumericType value) const noexcept   { addInternal (value); return *this; }\r
 \r
     /** Adds the elements in the src block to the elements in this block. */\r
     template <typename OtherSampleType>\r
@@ -386,9 +387,9 @@ public:
 \r
     /** Adds a fixed value to each source value and replaces the contents of this block. */\r
     template <typename OtherSampleType>\r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE replaceWithSumOf (AudioBlock<OtherSampleType> src, SampleType value)      noexcept    { replaceWithSumOfInternal (src, value); return *this; }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE replaceWithSumOf (AudioBlock<OtherSampleType> src, NumericType value)      noexcept    { replaceWithSumOfInternal (src, value); return *this; }\r
     template <typename OtherSampleType>\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithSumOf (AudioBlock<OtherSampleType> src, SampleType value) const noexcept   { replaceWithSumOfInternal (src, value); return *this; }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithSumOf (AudioBlock<OtherSampleType> src, NumericType value) const noexcept   { replaceWithSumOfInternal (src, value); return *this; }\r
 \r
     /** Adds each source1 value to the corresponding source2 value and replaces the contents of this block. */\r
     template <typename Src1SampleType, typename Src2SampleType>\r
@@ -398,8 +399,8 @@ public:
 \r
     //==============================================================================\r
     /** Subtracts a fixed value from the elements in this block. */\r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE subtract (SampleType value)       noexcept   { subtractInternal (value); return *this; }\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE subtract (SampleType value) const noexcept   { subtractInternal (value); return *this; }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE subtract (NumericType value)       noexcept   { subtractInternal (value); return *this; }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE subtract (NumericType value) const noexcept   { subtractInternal (value); return *this; }\r
 \r
     /** Subtracts the source values from the elements in this block. */\r
     template <typename OtherSampleType>\r
@@ -409,9 +410,9 @@ public:
 \r
     /** Subtracts a fixed value from each source value and replaces the contents of this block. */\r
     template <typename OtherSampleType>\r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE replaceWithDifferenceOf (AudioBlock<OtherSampleType> src, SampleType value)       noexcept   { replaceWithDifferenceOfInternal (src, value); return *this; }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE replaceWithDifferenceOf (AudioBlock<OtherSampleType> src, NumericType value)       noexcept   { replaceWithDifferenceOfInternal (src, value); return *this; }\r
     template <typename OtherSampleType>\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithDifferenceOf (AudioBlock<OtherSampleType> src, SampleType value) const noexcept   { replaceWithDifferenceOfInternal (src, value); return *this; }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithDifferenceOf (AudioBlock<OtherSampleType> src, NumericType value) const noexcept   { replaceWithDifferenceOfInternal (src, value); return *this; }\r
 \r
     /** Subtracts each source2 value from the corresponding source1 value and replaces the contents of this block. */\r
     template <typename Src1SampleType, typename Src2SampleType>\r
@@ -421,8 +422,8 @@ public:
 \r
     //==============================================================================\r
     /** Multiplies the elements in this block by a fixed value. */\r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE multiplyBy (SampleType value)       noexcept   { multiplyByInternal (value); return *this; }\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE multiplyBy (SampleType value) const noexcept   { multiplyByInternal (value); return *this; }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE multiplyBy (NumericType value)       noexcept   { multiplyByInternal (value); return *this; }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE multiplyBy (NumericType value) const noexcept   { multiplyByInternal (value); return *this; }\r
 \r
     /** Multiplies the elements in this block by the elements in the src block */\r
     template <typename OtherSampleType>\r
@@ -432,9 +433,9 @@ public:
 \r
     /** Replaces the elements in this block with the product of the elements in the source src block and a fixed value. */\r
     template <typename OtherSampleType>\r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE replaceWithProductOf (AudioBlock<OtherSampleType> src, SampleType value)       noexcept   { replaceWithProductOfInternal (src, value); return *this; }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE replaceWithProductOf (AudioBlock<OtherSampleType> src, NumericType value)       noexcept   { replaceWithProductOfInternal (src, value); return *this; }\r
     template <typename OtherSampleType>\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithProductOf (AudioBlock<OtherSampleType> src, SampleType value) const noexcept   { replaceWithProductOfInternal (src, value); return *this; }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithProductOf (AudioBlock<OtherSampleType> src, NumericType value) const noexcept   { replaceWithProductOfInternal (src, value); return *this; }\r
 \r
     /** Replaces the elements in this block with the product of the elements in the src1 and scr2 blocks. */\r
     template <typename Src1SampleType, typename Src2SampleType>\r
@@ -458,9 +459,9 @@ public:
     //==============================================================================\r
     /** Multiplies each value in src by a fixed value and adds the result to this block. */\r
     template <typename OtherSampleType>\r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE addProductOf (AudioBlock<OtherSampleType> src, SampleType factor)       noexcept   { addProductOfInternal (src, factor); return *this; }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE addProductOf (AudioBlock<OtherSampleType> src, NumericType factor)       noexcept   { addProductOfInternal (src, factor); return *this; }\r
     template <typename OtherSampleType>\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE addProductOf (AudioBlock<OtherSampleType> src, SampleType factor) const noexcept   { addProductOfInternal (src, factor); return *this; }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE addProductOf (AudioBlock<OtherSampleType> src, NumericType factor) const noexcept   { addProductOfInternal (src, factor); return *this; }\r
 \r
     /** Multiplies each value in srcA with the corresponding value in srcB and adds the result to this block. */\r
     template <typename Src1SampleType, typename Src2SampleType>\r
@@ -506,30 +507,30 @@ public:
             return {};\r
 \r
         auto n = static_cast<int> (numSamples * sizeFactor);\r
-        auto minmax = FloatVectorOperations::findMinAndMax (getChannelPointer (0), n);\r
+        auto minmax = FloatVectorOperations::findMinAndMax (getDataPointer (0), n);\r
 \r
         for (size_t ch = 1; ch < numChannels; ++ch)\r
-            minmax = minmax.getUnionWith (FloatVectorOperations::findMinAndMax (getChannelPointer (ch), n));\r
+            minmax = minmax.getUnionWith (FloatVectorOperations::findMinAndMax (getDataPointer (ch), n));\r
 \r
         return minmax;\r
     }\r
 \r
     //==============================================================================\r
     // Convenient operator wrappers.\r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE operator+= (SampleType value)       noexcept   { return add (value); }\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE operator+= (SampleType value) const noexcept   { return add (value); }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE operator+= (NumericType value)       noexcept   { return add (value); }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE operator+= (NumericType value) const noexcept   { return add (value); }\r
 \r
     AudioBlock&                            operator+= (AudioBlock src)         noexcept   { return add (src); }\r
     const AudioBlock&                      operator+= (AudioBlock src)   const noexcept   { return add (src); }\r
 \r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE operator-= (SampleType value)       noexcept   { return subtract (value); }\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE operator-= (SampleType value) const noexcept   { return subtract (value); }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE operator-= (NumericType value)       noexcept   { return subtract (value); }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE operator-= (NumericType value) const noexcept   { return subtract (value); }\r
 \r
     AudioBlock&                            operator-= (AudioBlock src)         noexcept   { return subtract (src); }\r
     const AudioBlock&                      operator-= (AudioBlock src)   const noexcept   { return subtract (src); }\r
 \r
-    AudioBlock&       JUCE_VECTOR_CALLTYPE operator*= (SampleType value)       noexcept   { return multiplyBy (value); }\r
-    const AudioBlock& JUCE_VECTOR_CALLTYPE operator*= (SampleType value) const noexcept   { return multiplyBy (value); }\r
+    AudioBlock&       JUCE_VECTOR_CALLTYPE operator*= (NumericType value)       noexcept   { return multiplyBy (value); }\r
+    const AudioBlock& JUCE_VECTOR_CALLTYPE operator*= (NumericType value) const noexcept   { return multiplyBy (value); }\r
 \r
     AudioBlock&                            operator*= (AudioBlock src)         noexcept   { return multiplyBy (src); }\r
     const AudioBlock&                      operator*= (AudioBlock src)   const noexcept   { return multiplyBy (src); }\r
@@ -574,42 +575,48 @@ public:
     }\r
 \r
 private:\r
+    NumericType* getDataPointer (size_t channel) const noexcept\r
+    {\r
+        return reinterpret_cast<NumericType*> (getChannelPointer (channel));\r
+    }\r
+\r
     //==============================================================================\r
     void JUCE_VECTOR_CALLTYPE clearInternal() const noexcept\r
     {\r
         auto n = static_cast<int> (numSamples * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::clear (getChannelPointer (ch), n);\r
+            FloatVectorOperations::clear (getDataPointer (ch), n);\r
     }\r
 \r
-    void JUCE_VECTOR_CALLTYPE fillInternal (SampleType value) const noexcept\r
+    void JUCE_VECTOR_CALLTYPE fillInternal (NumericType value) const noexcept\r
     {\r
         auto n = static_cast<int> (numSamples * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::fill (getChannelPointer (ch), value, n);\r
+            FloatVectorOperations::fill (getDataPointer (ch), value, n);\r
     }\r
 \r
     template <typename OtherSampleType>\r
     void copyFromInternal (const AudioBlock<OtherSampleType>& src) const noexcept\r
     {\r
         auto maxChannels = jmin (src.numChannels, numChannels);\r
-        auto n = static_cast<int> (jmin (src.numSamples, numSamples) * sizeFactor);\r
+        auto n = static_cast<int> (jmin (src.numSamples * src.sizeFactor,\r
+                                         numSamples * sizeFactor));\r
 \r
         for (size_t ch = 0; ch < maxChannels; ++ch)\r
-            FloatVectorOperations::copy (getChannelPointer (ch), src.getChannelPointer (ch), n);\r
+            FloatVectorOperations::copy (getDataPointer (ch), src.getDataPointer (ch), n);\r
     }\r
 \r
-    template <typename OtherSampleType>\r
-    void copyFromInternal (const AudioBuffer<OtherSampleType>& src, size_t srcPos, size_t dstPos, size_t numElements) const\r
+    template <typename OtherNumericType>\r
+    void copyFromInternal (const AudioBuffer<OtherNumericType>& src, size_t srcPos, size_t dstPos, size_t numElements) const\r
     {\r
         auto srclen = static_cast<size_t> (src.getNumSamples()) / sizeFactor;\r
         auto n = static_cast<int> (jmin (srclen - srcPos, numSamples - dstPos, numElements) * sizeFactor);\r
         auto maxChannels = jmin (static_cast<size_t> (src.getNumChannels()), static_cast<size_t> (numChannels));\r
 \r
         for (size_t ch = 0; ch < maxChannels; ++ch)\r
-            FloatVectorOperations::copy (getChannelPointer (ch) + dstPos,\r
+            FloatVectorOperations::copy (getDataPointer (ch) + (dstPos * sizeFactor),\r
                                          src.getReadPointer (static_cast<int> (ch),\r
                                                              static_cast<int> (srcPos * sizeFactor)),\r
                                          n);\r
@@ -628,12 +635,12 @@ private:
     }\r
 \r
     //==============================================================================\r
-    void JUCE_VECTOR_CALLTYPE addInternal (SampleType value) const noexcept\r
+    void JUCE_VECTOR_CALLTYPE addInternal (NumericType value) const noexcept\r
     {\r
         auto n = static_cast<int> (numSamples * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::add (getChannelPointer (ch), value, n);\r
+            FloatVectorOperations::add (getDataPointer (ch), value, n);\r
     }\r
 \r
     template <typename OtherSampleType>\r
@@ -643,17 +650,17 @@ private:
         auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::add (getChannelPointer (ch), src.getChannelPointer (ch), n);\r
+            FloatVectorOperations::add (getDataPointer (ch), src.getDataPointer (ch), n);\r
     }\r
 \r
     template <typename OtherSampleType>\r
-    void JUCE_VECTOR_CALLTYPE replaceWithSumOfInternal (AudioBlock<OtherSampleType> src, SampleType value) const noexcept\r
+    void JUCE_VECTOR_CALLTYPE replaceWithSumOfInternal (AudioBlock<OtherSampleType> src, NumericType value) const noexcept\r
     {\r
         jassert (numChannels == src.numChannels);\r
         auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::add (getChannelPointer (ch), src.getChannelPointer (ch), value, n);\r
+            FloatVectorOperations::add (getDataPointer (ch), src.getDataPointer (ch), value, n);\r
     }\r
 \r
     template <typename Src1SampleType, typename Src2SampleType>\r
@@ -663,13 +670,13 @@ private:
         auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::add (getChannelPointer (ch), src1.getChannelPointer (ch), src2.getChannelPointer (ch), n);\r
+            FloatVectorOperations::add (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);\r
     }\r
 \r
     //==============================================================================\r
-    constexpr void JUCE_VECTOR_CALLTYPE subtractInternal (SampleType value) const noexcept\r
+    constexpr void JUCE_VECTOR_CALLTYPE subtractInternal (NumericType value) const noexcept\r
     {\r
-        addInternal (value * static_cast<SampleType> (-1.0));\r
+        addInternal (value * static_cast<NumericType> (-1.0));\r
     }\r
 \r
     template <typename OtherSampleType>\r
@@ -679,13 +686,13 @@ private:
         auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::subtract (getChannelPointer (ch), src.getChannelPointer (ch), n);\r
+            FloatVectorOperations::subtract (getDataPointer (ch), src.getDataPointer (ch), n);\r
     }\r
 \r
     template <typename OtherSampleType>\r
-    void JUCE_VECTOR_CALLTYPE replaceWithDifferenceOfInternal (AudioBlock<OtherSampleType> src, SampleType value) const noexcept\r
+    void JUCE_VECTOR_CALLTYPE replaceWithDifferenceOfInternal (AudioBlock<OtherSampleType> src, NumericType value) const noexcept\r
     {\r
-        replaceWithSumOfInternal (src, static_cast<SampleType> (-1.0) * value);\r
+        replaceWithSumOfInternal (src, static_cast<NumericType> (-1.0) * value);\r
     }\r
 \r
     template <typename Src1SampleType, typename Src2SampleType>\r
@@ -695,16 +702,16 @@ private:
         auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::subtract (getChannelPointer (ch), src1.getChannelPointer (ch), src2.getChannelPointer (ch), n);\r
+            FloatVectorOperations::subtract (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);\r
     }\r
 \r
     //==============================================================================\r
-    void JUCE_VECTOR_CALLTYPE multiplyByInternal (SampleType value) const noexcept\r
+    void JUCE_VECTOR_CALLTYPE multiplyByInternal (NumericType value) const noexcept\r
     {\r
         auto n = static_cast<int> (numSamples * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::multiply (getChannelPointer (ch), value, n);\r
+            FloatVectorOperations::multiply (getDataPointer (ch), value, n);\r
     }\r
 \r
     template <typename OtherSampleType>\r
@@ -714,17 +721,17 @@ private:
         auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::multiply (getChannelPointer (ch), src.getChannelPointer (ch), n);\r
+            FloatVectorOperations::multiply (getDataPointer (ch), src.getDataPointer (ch), n);\r
     }\r
 \r
     template <typename OtherSampleType>\r
-    void JUCE_VECTOR_CALLTYPE replaceWithProductOfInternal (AudioBlock<OtherSampleType> src, SampleType value) const noexcept\r
+    void JUCE_VECTOR_CALLTYPE replaceWithProductOfInternal (AudioBlock<OtherSampleType> src, NumericType value) const noexcept\r
     {\r
         jassert (numChannels == src.numChannels);\r
         auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::multiply (getChannelPointer (ch), src.getChannelPointer (ch), value, n);\r
+            FloatVectorOperations::multiply (getDataPointer (ch), src.getDataPointer (ch), value, n);\r
     }\r
 \r
     template <typename Src1SampleType, typename Src2SampleType>\r
@@ -734,7 +741,7 @@ private:
         auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::multiply (getChannelPointer (ch), src1.getChannelPointer (ch), src2.getChannelPointer (ch), n);\r
+            FloatVectorOperations::multiply (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);\r
     }\r
 \r
     template <typename SmoothingType>\r
@@ -751,7 +758,7 @@ private:
                 const auto scaler = value.getNextValue();\r
 \r
                 for (size_t ch = 0; ch < numChannels; ++ch)\r
-                    getChannelPointer (ch)[i] *= scaler;\r
+                    getDataPointer (ch)[i] *= scaler;\r
             }\r
         }\r
     }\r
@@ -774,20 +781,20 @@ private:
                 const auto scaler = value.getNextValue();\r
 \r
                 for (size_t ch = 0; ch < numChannels; ++ch)\r
-                    getChannelPointer (ch)[i] = scaler * src.getChannelPointer (ch)[i];\r
+                    getDataPointer (ch)[i] = scaler * src.getChannelPointer (ch)[i];\r
             }\r
         }\r
     }\r
 \r
     //==============================================================================\r
     template <typename OtherSampleType>\r
-    void JUCE_VECTOR_CALLTYPE addProductOfInternal (AudioBlock<OtherSampleType> src, SampleType factor) const noexcept\r
+    void JUCE_VECTOR_CALLTYPE addProductOfInternal (AudioBlock<OtherSampleType> src, NumericType factor) const noexcept\r
     {\r
         jassert (numChannels == src.numChannels);\r
         auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::addWithMultiply (getChannelPointer (ch), src.getChannelPointer (ch), factor, n);\r
+            FloatVectorOperations::addWithMultiply (getDataPointer (ch), src.getDataPointer (ch), factor, n);\r
     }\r
 \r
     template <typename Src1SampleType, typename Src2SampleType>\r
@@ -797,13 +804,13 @@ private:
         auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::addWithMultiply (getChannelPointer (ch), src1.getChannelPointer (ch), src2.getChannelPointer (ch), n);\r
+            FloatVectorOperations::addWithMultiply (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);\r
     }\r
 \r
     //==============================================================================\r
     constexpr void negateInternal() const noexcept\r
     {\r
-        multiplyByInternal (static_cast<SampleType> (-1.0));\r
+        multiplyByInternal (static_cast<NumericType> (-1.0));\r
     }\r
 \r
     template <typename OtherSampleType>\r
@@ -813,7 +820,7 @@ private:
         auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::negate (getChannelPointer (ch), src.getChannelPointer (ch), n);\r
+            FloatVectorOperations::negate (getDataPointer (ch), src.getDataPointer (ch), n);\r
     }\r
 \r
     template <typename OtherSampleType>\r
@@ -823,7 +830,7 @@ private:
         auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::abs (getChannelPointer (ch), src.getChannelPointer (ch), n);\r
+            FloatVectorOperations::abs (getDataPointer (ch), src.getDataPointer (ch), n);\r
     }\r
 \r
     //==============================================================================\r
@@ -834,7 +841,7 @@ private:
         auto n = static_cast<int> (jmin (src1.numSamples, src2.numSamples, numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::min (getChannelPointer (ch), src1.getChannelPointer (ch), src2.getChannelPointer (ch), n);\r
+            FloatVectorOperations::min (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);\r
     }\r
 \r
     template <typename Src1SampleType, typename Src2SampleType>\r
@@ -844,7 +851,7 @@ private:
         auto n = static_cast<int> (jmin (src1.numSamples, src2.numSamples, numSamples) * sizeFactor);\r
 \r
         for (size_t ch = 0; ch < numChannels; ++ch)\r
-            FloatVectorOperations::max (getChannelPointer (ch), src1.getChannelPointer (ch), src2.getChannelPointer (ch), n);\r
+            FloatVectorOperations::max (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);\r
     }\r
 \r
     //==============================================================================\r
index f0192e8ad193b64f94777cab9b6d44e81b44ef1f..ce86f05f7781a7d570c0789a86d1de5dd5751a3b 100644 (file)
@@ -29,12 +29,32 @@ namespace juce
 namespace dsp\r
 {\r
 \r
+template <typename SampleType>\r
 class AudioBlockUnitTests   : public UnitTest\r
 {\r
 public:\r
+    //==============================================================================\r
+    using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;\r
+\r
     AudioBlockUnitTests()\r
         : UnitTest ("AudioBlock", UnitTestCategories::dsp)\r
-    {}\r
+    {\r
+        for (auto v : { &data, &otherData })\r
+            for (auto& channel : *v)\r
+                channel = allocateAlignedMemory (numSamples);\r
+\r
+        block      = { data.data(),      data.size(),      (size_t) numSamples };\r
+        otherBlock = { otherData.data(), otherData.size(), (size_t) numSamples };\r
+\r
+        resetBlocks();\r
+    }\r
+\r
+    ~AudioBlockUnitTests() override\r
+    {\r
+        for (auto v : { &data, &otherData })\r
+            for (auto channel : *v)\r
+                deallocateAlignedMemory (channel);\r
+    }\r
 \r
     void runTest() override\r
     {\r
@@ -46,13 +66,13 @@ public:
 \r
         beginTest ("Constructors");\r
         {\r
-            expect (block == AudioBlock<float> (data.getArrayOfWritePointers(), (size_t) data.getNumChannels(), (size_t) data.getNumSamples()));\r
-            expect (block == AudioBlock<float> (data.getArrayOfWritePointers(), (size_t) data.getNumChannels(), (size_t) 0, (size_t) data.getNumSamples()));\r
-            expect (block == AudioBlock<float> (block));\r
+            expect (block == AudioBlock<SampleType> (data.data(), data.size(), numSamples));\r
+            expect (block == AudioBlock<SampleType> (data.data(), data.size(), (size_t) 0, numSamples));\r
+            expect (block == AudioBlock<SampleType> (block));\r
 \r
-            expect (block == AudioBlock<const float> (data.getArrayOfWritePointers(), (size_t) data.getNumChannels(), (size_t) data.getNumSamples()));\r
-            expect (block == AudioBlock<const float> (data.getArrayOfWritePointers(), (size_t) data.getNumChannels(), (size_t) 0, (size_t) data.getNumSamples()));\r
-            expect (block == AudioBlock<const float> (block));\r
+            expect (block == AudioBlock<const SampleType> (data.data(), data.size(), numSamples));\r
+            expect (block == AudioBlock<const SampleType> (data.data(), data.size(), (size_t) 0, numSamples));\r
+            expect (block == AudioBlock<const SampleType> (block));\r
         }\r
 \r
         beginTest ("Swap");\r
@@ -60,188 +80,159 @@ public:
             resetBlocks();\r
 \r
             expect (block != otherBlock);\r
-            expectEquals (block.getSample (0, 0), 1.0f);\r
-            expectEquals (block.getSample (0, 4), 5.0f);\r
-            expectEquals (otherBlock.getSample (0, 0), -1.0f);\r
-            expectEquals (otherBlock.getSample (0, 3), -4.0f);\r
+            expect (block.getSample (0, 0) == SampleType (1.0));\r
+            expect (block.getSample (0, 4) == SampleType (5.0));\r
+            expect (otherBlock.getSample (0, 0) == SampleType (-1.0));\r
+            expect (otherBlock.getSample (0, 3) == SampleType (-4.0));\r
 \r
             block.swap (otherBlock);\r
 \r
             expect (block != otherBlock);\r
-            expectEquals (otherBlock.getSample (0, 0), 1.0f);\r
-            expectEquals (otherBlock.getSample (0, 4), 5.0f);\r
-            expectEquals (block.getSample (0, 0), -1.0f);\r
-            expectEquals (block.getSample (0, 3), -4.0f);\r
+            expect (otherBlock.getSample (0, 0) == SampleType (1.0));\r
+            expect (otherBlock.getSample (0, 4) == SampleType (5.0));\r
+            expect (block.getSample (0, 0) == SampleType (-1.0));\r
+            expect (block.getSample (0, 3) == SampleType (-4.0));\r
+\r
+            block.swap (otherBlock);\r
+\r
+            expect (block.getSample (0, 0) == SampleType (1.0));\r
+            expect (block.getSample (0, 4) == SampleType (5.0));\r
+            expect (otherBlock.getSample (0, 0) == SampleType (-1.0));\r
+            expect (otherBlock.getSample (0, 3) == SampleType (-4.0));\r
         }\r
 \r
         beginTest ("Getters and setters");\r
         {\r
             resetBlocks();\r
 \r
-            expectEquals ((int) block.getNumChannels(), data.getNumChannels());\r
-            expectEquals ((int) block.getNumSamples(),  data.getNumSamples());\r
+            expectEquals ((int) block.getNumChannels(), (int) data.size());\r
+            expectEquals ((int) block.getNumSamples(), numSamples);\r
 \r
-            expectEquals (block.getChannelPointer (0)[2], 3.0f);\r
-            block.getChannelPointer (0)[2] = 999.0f;\r
-            expectEquals (block.getChannelPointer (0)[2], 999.0f);\r
+            expect (block.getChannelPointer (0)[2] == SampleType (3.0));\r
+            block.getChannelPointer (0)[2] = SampleType (999.0);\r
+            expect (block.getChannelPointer (0)[2] == SampleType (999.0));\r
 \r
-            expectEquals (block.getSample (0, 4), 5.0f);\r
-            expectEquals (block.getSample (1, 4), 11.0f);\r
+            expect (block.getSample (0, 4) == SampleType (5.0));\r
+            expect (block.getSample (1, 4) == SampleType (11.0));\r
 \r
-            expectEquals (block.getSingleChannelBlock (1).getSample (0, 3), block.getSample (1, 3));\r
+            expect (block.getSingleChannelBlock (1).getSample (0, 3) == block.getSample (1, 3));\r
 \r
-            expectEquals (block.getSubsetChannelBlock (0, 2).getSample (1, 3), block.getSample (1, 3));\r
-            expectEquals (block.getSubsetChannelBlock (1, 1).getSample (0, 3), block.getSample (1, 3));\r
+            expect (block.getSubsetChannelBlock (0, 2).getSample (1, 3) == block.getSample (1, 3));\r
+            expect (block.getSubsetChannelBlock (1, 1).getSample (0, 3) == block.getSample (1, 3));\r
 \r
-            block.setSample (1, 1, 777.0f);\r
-            expectEquals (block.getSample (1, 1), 777.0f);\r
+            block.setSample (1, 1, SampleType (777.0));\r
+            expect (block.getSample (1, 1) == SampleType (777.0));\r
 \r
-            block.addSample (1, 1, 1.0f);\r
-            expectEquals (block.getSample (1, 1), 778.0f);\r
+            block.addSample (1, 1, SampleType (1.0));\r
+            expect (block.getSample (1, 1) == SampleType (778.0));\r
         }\r
 \r
-        beginTest ("Copying");\r
+        beginTest ("Basic copying");\r
         {\r
             block.clear();\r
-            expectEquals (block.getSample (0, 2), 0.0f);\r
-            expectEquals (block.getSample (1, 4), 0.0f);\r
+            expect (block.getSample (0, 2) == SampleType (0.0));\r
+            expect (block.getSample (1, 4) == SampleType (0.0));\r
 \r
-            block.fill (456.0f);\r
-            expectEquals (block.getSample (0, 2), 456.0f);\r
-            expectEquals (block.getSample (1, 4), 456.0f);\r
+            block.fill ((NumericType) 456.0);\r
+            expect (block.getSample (0, 2) == SampleType (456.0));\r
+            expect (block.getSample (1, 4) == SampleType (456.0));\r
 \r
             block.copyFrom (otherBlock);\r
             expect (block != otherBlock);\r
-            expectEquals (block.getSample (0, 2), otherBlock.getSample (0, 2));\r
-            expectEquals (block.getSample (1, 4), otherBlock.getSample (1, 4));\r
+            expect (block.getSample (0, 2) == otherBlock.getSample (0, 2));\r
+            expect (block.getSample (1, 4) == otherBlock.getSample (1, 4));\r
 \r
             resetBlocks();\r
 \r
-            AudioBuffer<float> otherBuffer ((int) block.getNumChannels(), (int) block.getNumSamples());\r
-            otherBlock.copyTo (otherBuffer);\r
-            expectEquals (otherBlock.getSample (0, 2), otherBuffer.getSample (0, 2));\r
-            expectEquals (otherBlock.getSample (1, 4), otherBuffer.getSample (1, 4));\r
-\r
-            block.copyFrom (otherBuffer);\r
-            expectEquals (block.getSample (0, 2), otherBlock.getSample (0, 2));\r
-            expectEquals (block.getSample (1, 4), otherBlock.getSample (1, 4));\r
-\r
-            float testSample1 = block.getSample (0, 2);\r
-            float testSample2 = block.getSample (1, 3);\r
+            SampleType testSample1 = block.getSample (0, 2);\r
+            SampleType testSample2 = block.getSample (1, 3);\r
             expect (testSample1 != block.getSample (0, 4));\r
             expect (testSample2 != block.getSample (1, 5));\r
             block.move (0, 2);\r
-            expectEquals (block.getSample (0, 4), testSample1);\r
-            expectEquals (block.getSample (1, 5), testSample2);\r
+            expect (block.getSample (0, 4) == testSample1);\r
+            expect (block.getSample (1, 5) == testSample2);\r
         }\r
 \r
         beginTest ("Addition");\r
         {\r
             resetBlocks();\r
 \r
-            block.add (15.0f);\r
-            expectEquals (block.getSample (0, 4), 20.0f);\r
-            expectEquals (block.getSample (1, 4), 26.0f);\r
+            block.add ((NumericType) 15.0);\r
+            expect (block.getSample (0, 4) == SampleType (20.0));\r
+            expect (block.getSample (1, 4) == SampleType (26.0));\r
 \r
             block.add (otherBlock);\r
-            expectEquals (block.getSample (0, 4), 15.0f);\r
-            expectEquals (block.getSample (1, 4), 15.0f);\r
+            expect (block.getSample (0, 4) == SampleType (15.0));\r
+            expect (block.getSample (1, 4) == SampleType (15.0));\r
 \r
-            block.replaceWithSumOf (otherBlock, 9.0f);\r
-            expectEquals (block.getSample (0, 4), 4.0f);\r
-            expectEquals (block.getSample (1, 4), -2.0f);\r
+            block.replaceWithSumOf (otherBlock, (NumericType) 9.0);\r
+            expect (block.getSample (0, 4) == SampleType (4.0));\r
+            expect (block.getSample (1, 4) == SampleType (-2.0));\r
 \r
             resetBlocks();\r
 \r
             block.replaceWithSumOf (block, otherBlock);\r
-            expectEquals (block.getSample (0, 4), 0.0f);\r
-            expectEquals (block.getSample (1, 4), 0.0f);\r
+            expect (block.getSample (0, 4) == SampleType (0.0));\r
+            expect (block.getSample (1, 4) == SampleType (0.0));\r
         }\r
 \r
         beginTest ("Subtraction");\r
         {\r
             resetBlocks();\r
 \r
-            block.subtract (15.0f);\r
-            expectEquals (block.getSample (0, 4), -10.0f);\r
-            expectEquals (block.getSample (1, 4), -4.0f);\r
+            block.subtract ((NumericType) 15.0);\r
+            expect (block.getSample (0, 4) == SampleType (-10.0));\r
+            expect (block.getSample (1, 4) == SampleType (-4.0));\r
 \r
             block.subtract (otherBlock);\r
-            expectEquals (block.getSample (0, 4), -5.0f);\r
-            expectEquals (block.getSample (1, 4), 7.0f);\r
+            expect (block.getSample (0, 4) == SampleType (-5.0));\r
+            expect (block.getSample (1, 4) == SampleType (7.0));\r
 \r
-            block.replaceWithDifferenceOf (otherBlock, 9.0f);\r
-            expectEquals (block.getSample (0, 4), -14.0f);\r
-            expectEquals (block.getSample (1, 4), -20.0f);\r
+            block.replaceWithDifferenceOf (otherBlock, (NumericType) 9.0);\r
+            expect (block.getSample (0, 4) == SampleType (-14.0));\r
+            expect (block.getSample (1, 4) == SampleType (-20.0));\r
 \r
             resetBlocks();\r
 \r
             block.replaceWithDifferenceOf (block, otherBlock);\r
-            expectEquals (block.getSample (0, 4), 10.0f);\r
-            expectEquals (block.getSample (1, 4), 22.0f);\r
+            expect (block.getSample (0, 4) == SampleType (10.0));\r
+            expect (block.getSample (1, 4) == SampleType (22.0));\r
         }\r
 \r
         beginTest ("Multiplication");\r
         {\r
             resetBlocks();\r
 \r
-            block.multiplyBy (10.0f);\r
-            expectEquals (block.getSample (0, 4), 50.0f);\r
-            expectEquals (block.getSample (1, 4), 110.0f);\r
+            block.multiplyBy ((NumericType) 10.0);\r
+            expect (block.getSample (0, 4) == SampleType (50.0));\r
+            expect (block.getSample (1, 4) == SampleType (110.0));\r
 \r
             block.multiplyBy (otherBlock);\r
-            expectEquals (block.getSample (0, 4), -250.0f);\r
-            expectEquals (block.getSample (1, 4), -1210.0f);\r
+            expect (block.getSample (0, 4) == SampleType (-250.0));\r
+            expect (block.getSample (1, 4) == SampleType (-1210.0));\r
 \r
-            block.replaceWithProductOf (otherBlock, 3.0f);\r
-            expectEquals (block.getSample (0, 4), -15.0f);\r
-            expectEquals (block.getSample (1, 4), -33.0f);\r
+            block.replaceWithProductOf (otherBlock, (NumericType) 3.0);\r
+            expect (block.getSample (0, 4) == SampleType (-15.0));\r
+            expect (block.getSample (1, 4) == SampleType (-33.0));\r
 \r
             resetBlocks();\r
 \r
             block.replaceWithProductOf (block, otherBlock);\r
-            expectEquals (block.getSample (0, 4), -25.0f);\r
-            expectEquals (block.getSample (1, 4), -121.0f);\r
-        }\r
-\r
-        beginTest ("Smoothing");\r
-        {\r
-            block.fill (1.0f);\r
-            SmoothedValue<float> sv { 1.0f };\r
-            sv.reset (1, 4);\r
-            sv.setTargetValue (0.0f);\r
-\r
-            block.multiplyBy (sv);\r
-            expect (block.getSample (0, 2) < 1.0f);\r
-            expect (block.getSample (1, 2) < 1.0f);\r
-            expect (block.getSample (0, 2) > 0.0f);\r
-            expect (block.getSample (1, 2) > 0.0f);\r
-            expectEquals (block.getSample (0, 5), 0.0f);\r
-            expectEquals (block.getSample (1, 5), 0.0f);\r
-\r
-            sv.setCurrentAndTargetValue (-1.0f);\r
-            sv.setTargetValue (0.0f);\r
-            otherBlock.fill (-1.0f);\r
-            block.replaceWithProductOf (otherBlock, sv);\r
-            expect (block.getSample (0, 2) < 1.0f);\r
-            expect (block.getSample (1, 2) < 1.0f);\r
-            expect (block.getSample (0, 2) > 0.0f);\r
-            expect (block.getSample (1, 2) > 0.0f);\r
-            expectEquals (block.getSample (0, 5), 0.0f);\r
-            expectEquals (block.getSample (1, 5), 0.0f);\r
+            expect (block.getSample (0, 4) == SampleType (-25.0));\r
+            expect (block.getSample (1, 4) == SampleType (-121.0));\r
         }\r
 \r
         beginTest ("Multiply add");\r
         {\r
             resetBlocks();\r
 \r
-            block.addProductOf (otherBlock, -1.0f);\r
-            expectEquals (block.getSample (0, 4), 10.0f);\r
-            expectEquals (block.getSample (1, 4), 22.0f);\r
+            block.addProductOf (otherBlock, (NumericType) -1.0);\r
+            expect (block.getSample (0, 4) == SampleType (10.0));\r
+            expect (block.getSample (1, 4) == SampleType (22.0));\r
 \r
             block.addProductOf (otherBlock, otherBlock);\r
-            expectEquals (block.getSample (0, 4), 35.0f);\r
-            expectEquals (block.getSample (1, 4), 143.0f);\r
+            expect (block.getSample (0, 4) == SampleType (35.0));\r
+            expect (block.getSample (1, 4) == SampleType (143.0));\r
         }\r
 \r
         beginTest ("Negative abs min max");\r
@@ -250,93 +241,259 @@ public:
             otherBlock.negate();\r
 \r
             block.add (otherBlock);\r
-            expectEquals (block.getSample (0, 4), 10.0f);\r
-            expectEquals (block.getSample (1, 4), 22.0f);\r
+            expect (block.getSample (0, 4) == SampleType (10.0));\r
+            expect (block.getSample (1, 4) == SampleType (22.0));\r
 \r
             block.replaceWithNegativeOf (otherBlock);\r
-            expectEquals (block.getSample (0, 4), -5.0f);\r
-            expectEquals (block.getSample (1, 4), -11.0f);\r
+            expect (block.getSample (0, 4) == SampleType (-5.0));\r
+            expect (block.getSample (1, 4) == SampleType (-11.0));\r
 \r
             block.clear();\r
             otherBlock.negate();\r
             block.replaceWithAbsoluteValueOf (otherBlock);\r
-            expectEquals (block.getSample (0, 4), 5.0f);\r
-            expectEquals (block.getSample (1, 4), 11.0f);\r
+            expect (block.getSample (0, 4) == SampleType (5.0));\r
+            expect (block.getSample (1, 4) == SampleType (11.0));\r
 \r
             resetBlocks();\r
             block.replaceWithMinOf (block, otherBlock);\r
-            expectEquals (block.getSample (0, 4), -5.0f);\r
-            expectEquals (block.getSample (1, 4), -11.0f);\r
+            expect (block.getSample (0, 4) == SampleType (-5.0));\r
+            expect (block.getSample (1, 4) == SampleType (-11.0));\r
 \r
             resetBlocks();\r
             block.replaceWithMaxOf (block, otherBlock);\r
-            expectEquals (block.getSample (0, 4), 5.0f);\r
-            expectEquals (block.getSample (1, 4), 11.0f);\r
+            expect (block.getSample (0, 4) == SampleType (5.0));\r
+            expect (block.getSample (1, 4) == SampleType (11.0));\r
 \r
             resetBlocks();\r
             auto range = block.findMinAndMax();\r
-            expectEquals (range.getStart(), 1.0f);\r
-            expectEquals (range.getEnd(), 12.0f);\r
+            expect (SampleType (range.getStart()) == SampleType (1.0));\r
+            expect (SampleType (range.getEnd()) == SampleType (12.0));\r
         }\r
 \r
         beginTest ("Operators");\r
         {\r
             resetBlocks();\r
-            block += 10.0f;\r
-            expectEquals (block.getSample (0, 4), 15.0f);\r
-            expectEquals (block.getSample (1, 4), 21.0f);\r
+            block += (NumericType) 10.0;\r
+            expect (block.getSample (0, 4) == SampleType (15.0));\r
+            expect (block.getSample (1, 4) == SampleType (21.0));\r
             block += otherBlock;\r
-            expectEquals (block.getSample (0, 4), 10.0f);\r
-            expectEquals (block.getSample (1, 4), 10.0f);\r
+            expect (block.getSample (0, 4) == SampleType (10.0));\r
+            expect (block.getSample (1, 4) == SampleType (10.0));\r
 \r
             resetBlocks();\r
-            block -= 10.0f;\r
-            expectEquals (block.getSample (0, 4), -5.0f);\r
-            expectEquals (block.getSample (1, 4), 1.0f);\r
+            block -= (NumericType) 10.0;\r
+            expect (block.getSample (0, 4) == SampleType (-5.0));\r
+            expect (block.getSample (1, 4) == SampleType (1.0));\r
             block -= otherBlock;\r
-            expectEquals (block.getSample (0, 4), 0.0f);\r
-            expectEquals (block.getSample (1, 4), 12.0f);\r
+            expect (block.getSample (0, 4) == SampleType (0.0));\r
+            expect (block.getSample (1, 4) == SampleType (12.0));\r
 \r
             resetBlocks();\r
-            block *= 10.0f;\r
-            expectEquals (block.getSample (0, 4), 50.0f);\r
-            expectEquals (block.getSample (1, 4), 110.0f);\r
+            block *= (NumericType) 10.0;\r
+            expect (block.getSample (0, 4) == SampleType (50.0));\r
+            expect (block.getSample (1, 4) == SampleType (110.0));\r
             block *= otherBlock;\r
-            expectEquals (block.getSample (0, 4), -250.0f);\r
-            expectEquals (block.getSample (1, 4), -1210.0f);\r
+            expect (block.getSample (0, 4) == SampleType (-250.0));\r
+            expect (block.getSample (1, 4) == SampleType (-1210.0));\r
         }\r
 \r
         beginTest ("Process");\r
         {\r
             resetBlocks();\r
-            AudioBlock<float>::process (block, otherBlock, [](float x) { return x + 1.0f; });\r
-            expectEquals (otherBlock.getSample (0, 4), 6.0f);\r
-            expectEquals (otherBlock.getSample (1, 4), 12.0f);\r
+            AudioBlock<SampleType>::process (block, otherBlock, [](SampleType x) { return x + (NumericType) 1.0; });\r
+            expect (otherBlock.getSample (0, 4) == SampleType (6.0));\r
+            expect (otherBlock.getSample (1, 4) == SampleType (12.0));\r
+        }\r
+\r
+        beginTest ("Copying");\r
+        {\r
+            resetBlocks();\r
+            copyingTests();\r
+        }\r
+\r
+        beginTest ("Smoothing");\r
+        {\r
+            resetBlocks();\r
+            smoothedValueTests();\r
         }\r
     }\r
 \r
 private:\r
-    AudioBuffer<float> data { 2, 6 }, otherData { 2, 6 };\r
-    AudioBlock<float> block { data }, otherBlock { otherData };\r
+    //==============================================================================\r
+    template <typename T>\r
+    using ScalarVoid = typename std::enable_if_t <  std::is_scalar <T>::value, void>;\r
+\r
+    template <typename T>\r
+    using SIMDVoid   = typename std::enable_if_t <! std::is_scalar <T>::value, void>;\r
+\r
+    //==============================================================================\r
+    template <typename T = SampleType>\r
+    ScalarVoid<T> copyingTests()\r
+    {\r
+        auto unchangedElement1 = block.getSample (0, 4);\r
+        auto unchangedElement2 = block.getSample (1, 1);\r
+\r
+        AudioBuffer<SampleType> otherBuffer (otherData.data(), (int) otherData.size(), numSamples);\r
+\r
+        block.copyFrom (otherBuffer, 1, 2, 2);\r
+\r
+        expectEquals (block.getSample (0, 4), unchangedElement1);\r
+        expectEquals (block.getSample (1, 1), unchangedElement2);\r
+        expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1));\r
+        expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2));\r
 \r
+        resetBlocks();\r
+\r
+        unchangedElement1 = otherBuffer.getSample (0, 4);\r
+        unchangedElement2 = otherBuffer.getSample (1, 3);\r
+\r
+        block.copyTo (otherBuffer, 2, 1, 2);\r
+\r
+        expectEquals (otherBuffer.getSample (0, 4), unchangedElement1);\r
+        expectEquals (otherBuffer.getSample (1, 3), unchangedElement2);\r
+        expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2));\r
+        expectEquals (otherBuffer.getSample (1, 2), block.getSample (1, 3));\r
+    }\r
+\r
+    template <typename T = SampleType>\r
+    SIMDVoid<T> copyingTests()\r
+    {\r
+        auto numSIMDElements = SIMDRegister<NumericType>::SIMDNumElements;\r
+        AudioBuffer<NumericType> numericData ((int) block.getNumChannels(),\r
+                                              (int) (block.getNumSamples() * numSIMDElements));\r
+\r
+        for (int c = 0; c < numericData.getNumChannels(); ++c)\r
+            std::fill_n (numericData.getWritePointer (c), numericData.getNumSamples(), (NumericType) 1.0);\r
+\r
+        numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 0.127, (NumericType) 17.3);\r
+\r
+        auto lastUnchangedIndexBeforeCopiedRange = (int) ((numSIMDElements * 2) - 1);\r
+        auto firstUnchangedIndexAfterCopiedRange = (int) ((numSIMDElements * 4) + 1);\r
+        auto unchangedElement1 = numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange);\r
+        auto unchangedElement2 = numericData.getSample (1, firstUnchangedIndexAfterCopiedRange);\r
+\r
+        block.copyTo (numericData, 1, 2, 2);\r
+\r
+        expectEquals (numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange), unchangedElement1);\r
+        expectEquals (numericData.getSample (1, firstUnchangedIndexAfterCopiedRange), unchangedElement2);\r
+        expect (SampleType (numericData.getSample (0, 2 * (int) numSIMDElements)) == block.getSample (0, 1));\r
+        expect (SampleType (numericData.getSample (1, 3 * (int) numSIMDElements)) == block.getSample (1, 2));\r
+\r
+        numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 15.1, (NumericType) 0.7);\r
+\r
+        auto unchangedSIMDElement1 = block.getSample (0, 1);\r
+        auto unchangedSIMDElement2 = block.getSample (1, 4);\r
+\r
+        block.copyFrom (numericData, 1, 2, 2);\r
+\r
+        expect (block.getSample (0, 1) == unchangedSIMDElement1);\r
+        expect (block.getSample (1, 4) == unchangedSIMDElement2);\r
+        expectEquals (block.getSample (0, 2).get (0), numericData.getSample (0, (int) numSIMDElements));\r
+        expectEquals (block.getSample (1, 3).get (0), numericData.getSample (1, (int) (numSIMDElements * 2)));\r
+\r
+        if (numSIMDElements > 1)\r
+        {\r
+            expectEquals (block.getSample (0, 2).get (1), numericData.getSample (0, (int) (numSIMDElements + 1)));\r
+            expectEquals (block.getSample (1, 3).get (1), numericData.getSample (1, (int) ((numSIMDElements * 2) + 1)));\r
+        }\r
+    }\r
+\r
+    //==============================================================================\r
+    template <typename T = SampleType>\r
+    ScalarVoid<T> smoothedValueTests()\r
+    {\r
+        block.fill ((SampleType) 1.0);\r
+        SmoothedValue<SampleType> sv { (SampleType) 1.0 };\r
+        sv.reset (1, 4);\r
+        sv.setTargetValue ((SampleType) 0.0);\r
+\r
+        block.multiplyBy (sv);\r
+        expect (block.getSample (0, 2) < (SampleType) 1.0);\r
+        expect (block.getSample (1, 2) < (SampleType) 1.0);\r
+        expect (block.getSample (0, 2) > (SampleType) 0.0);\r
+        expect (block.getSample (1, 2) > (SampleType) 0.0);\r
+        expectEquals (block.getSample (0, 5), (SampleType) 0.0);\r
+        expectEquals (block.getSample (1, 5), (SampleType) 0.0);\r
+\r
+        sv.setCurrentAndTargetValue (-1.0f);\r
+        sv.setTargetValue (0.0f);\r
+        otherBlock.fill (-1.0f);\r
+        block.replaceWithProductOf (otherBlock, sv);\r
+        expect (block.getSample (0, 2) < (SampleType) 1.0);\r
+        expect (block.getSample (1, 2) < (SampleType) 1.0);\r
+        expect (block.getSample (0, 2) > (SampleType) 0.0);\r
+        expect (block.getSample (1, 2) > (SampleType) 0.0);\r
+        expectEquals (block.getSample (0, 5), (SampleType) 0.0);\r
+        expectEquals (block.getSample (1, 5), (SampleType) 0.0);\r
+    }\r
+\r
+    template <typename T = SampleType>\r
+    SIMDVoid<T> smoothedValueTests() {}\r
+\r
+    //==============================================================================\r
     void resetBlocks()\r
     {\r
-        auto value = 1.0f;\r
+        auto value = SampleType (1.0);\r
 \r
         for (size_t c = 0; c < block.getNumChannels(); ++c)\r
         {\r
             for (size_t i = 0; i < block.getNumSamples(); ++i)\r
             {\r
                 block.setSample ((int) c, (int) i, value);\r
-                value += 1.0f;\r
+                value += SampleType (1.0);\r
             }\r
         }\r
 \r
         otherBlock.replaceWithNegativeOf (block);\r
     }\r
+\r
+    //==============================================================================\r
+    static SampleType* allocateAlignedMemory (int numSamplesToAllocate)\r
+    {\r
+        auto alignmentLowerBound = std::alignment_of<SampleType>::value;\r
+       #if ! JUCE_WINDOWS\r
+        alignmentLowerBound = jmax (sizeof (void*), alignmentLowerBound);\r
+       #endif\r
+        auto alignmentOrder = std::ceil (std::log2 (alignmentLowerBound));\r
+        auto requiredAlignment = (size_t) std::pow (2, alignmentOrder);\r
+\r
+        auto size = (size_t) numSamplesToAllocate * sizeof (SampleType);\r
+\r
+       #if JUCE_WINDOWS\r
+        auto* memory = _aligned_malloc (size, requiredAlignment);\r
+       #else\r
+        void* memory;\r
+        auto result = posix_memalign (&memory, requiredAlignment, size);\r
+\r
+        if (result != 0)\r
+        {\r
+            jassertfalse;\r
+            return nullptr;\r
+        }\r
+       #endif\r
+\r
+        return static_cast<SampleType*> (memory);\r
+    }\r
+\r
+    void deallocateAlignedMemory (void* address)\r
+    {\r
+       #if JUCE_WINDOWS\r
+        _aligned_free (address);\r
+       #else\r
+        free (address);\r
+       #endif\r
+    }\r
+\r
+    //==============================================================================\r
+    static constexpr int numChannels = 2, numSamples = 6;\r
+    std::array<SampleType*, numChannels> data, otherData;\r
+    AudioBlock<SampleType> block, otherBlock;\r
 };\r
 \r
-static AudioBlockUnitTests audioBlockUnitTests;\r
+static AudioBlockUnitTests<float> audioBlockFloatUnitTests;\r
+static AudioBlockUnitTests<double> audioBlockDoubleUnitTests;\r
+static AudioBlockUnitTests<SIMDRegister<float>> audioBlockSIMDFloatUnitTests;\r
+static AudioBlockUnitTests<SIMDRegister<double>> audioBlockSIMDDoubleUnitTests;\r
 \r
 } // namespace dsp\r
 } // namespace juce\r
index a74860fbd330e2fc7cf95ced19a4d69d915a2839..9cf8258883ef9635ba965b2e4c07dc9cd654d704 100644 (file)
@@ -40,7 +40,7 @@ namespace dsp
     A wrapper around the platform's native SIMD register type.\r
 \r
     This class is only available on SIMD machines. Use JUCE_USE_SIMD to query\r
-    if SIMD is avaialble for your system.\r
+    if SIMD is available for your system.\r
 \r
     SIMDRegister<Type> is a templated class representing the native\r
     vectorized version of FloatingType. SIMDRegister supports all numerical\r
@@ -117,7 +117,7 @@ struct SIMDRegister
     /** Constructs an object from a scalar type by broadcasting it to all elements. */\r
     inline SIMDRegister (Type s) noexcept  { *this = s; }\r
 \r
-    /** Destrutor. */\r
+    /** Destructor. */\r
     inline ~SIMDRegister() noexcept = default;\r
 \r
     //==============================================================================\r
@@ -204,23 +204,23 @@ struct SIMDRegister
     inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator*= (ElementType s) noexcept       { value = CmplxOps::mul (value, CmplxOps::expand (s)); return *this; }\r
 \r
     //==============================================================================\r
-    /** Bit-and the reciver with SIMDRegister v and store the result in the receiver. */\r
+    /** Bit-and the receiver with SIMDRegister v and store the result in the receiver. */\r
     inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator&= (vMaskType v) noexcept         { value = NativeOps::bit_and (value, toVecType (v.value)); return *this; }\r
 \r
-    /** Bit-or the reciver with SIMDRegister v and store the result in the receiver. */\r
+    /** Bit-or the receiver with SIMDRegister v and store the result in the receiver. */\r
     inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator|= (vMaskType v) noexcept         { value = NativeOps::bit_or  (value, toVecType (v.value)); return *this; }\r
 \r
-    /** Bit-xor the reciver with SIMDRegister v and store the result in the receiver. */\r
+    /** Bit-xor the receiver with SIMDRegister v and store the result in the receiver. */\r
     inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator^= (vMaskType v) noexcept         { value = NativeOps::bit_xor (value, toVecType (v.value)); return *this; }\r
 \r
     //==============================================================================\r
-    /** Bit-and each element of the reciver with the scalar s and store the result in the receiver.*/\r
+    /** Bit-and each element of the receiver with the scalar s and store the result in the receiver.*/\r
     inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator&= (MaskType s) noexcept           { value = NativeOps::bit_and (value, toVecType (s)); return *this; }\r
 \r
-    /** Bit-or each element of the reciver with the scalar s and store the result in the receiver.*/\r
+    /** Bit-or each element of the receiver with the scalar s and store the result in the receiver.*/\r
     inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator|= (MaskType s) noexcept           { value = NativeOps::bit_or  (value, toVecType (s)); return *this; }\r
 \r
-    /** Bit-xor each element of the reciver with the scalar s and store the result in the receiver.*/\r
+    /** Bit-xor each element of the receiver with the scalar s and store the result in the receiver.*/\r
     inline SIMDRegister& JUCE_VECTOR_CALLTYPE operator^= (MaskType s) noexcept           { value = NativeOps::bit_xor (value, toVecType (s)); return *this; }\r
 \r
     //==============================================================================\r
@@ -267,10 +267,10 @@ struct SIMDRegister
     inline SIMDRegister JUCE_VECTOR_CALLTYPE operator^ (MaskType s) const noexcept      { return { NativeOps::bit_xor (value, toVecType (s)) }; }\r
 \r
     //==============================================================================\r
-    /** Returns true if all elements-wise comparisons return true. */\r
+    /** Returns true if all element-wise comparisons return true. */\r
     inline bool JUCE_VECTOR_CALLTYPE operator== (SIMDRegister other) const noexcept    { return  NativeOps::allEqual (value, other.value); }\r
 \r
-    /** Returns true if any elements-wise comparisons return false. */\r
+    /** Returns true if any element-wise comparisons return false. */\r
     inline bool JUCE_VECTOR_CALLTYPE operator!= (SIMDRegister other) const noexcept    { return ! (*this == other); }\r
 \r
     /** Returns true if all elements are equal to the scalar. */\r
index 837d586fc8e9681df4f468fec8c4eb4e7304258c..ea2b4fa94c377dddaacd85f32e7972f684ebac98 100644 (file)
@@ -195,7 +195,7 @@ public:
     }\r
 \r
     //==============================================================================\r
-    // Someuseful operations to test\r
+    // Some useful operations to test\r
     struct Addition\r
     {\r
         template <typename typeOne, typename typeTwo>\r
index c2669cfdda076dcac898e51cb369666d6f945cdf..883af17bace54e38902323d871057f9e30e672fd 100644 (file)
@@ -62,7 +62,7 @@ public:
 \r
     /** Performs an in-place forward transform on a block of real data.\r
 \r
-        As the coefficients of the negative frequences (frequencies higher than\r
+        As the coefficients of the negative frequencies (frequencies higher than\r
         N/2 or pi) are the complex conjugate of their positive counterparts,\r
         it may not be necessary to calculate them for your particular application.\r
         You can use dontCalculateNegativeFrequencies to let the FFT\r
index 68abb03ea588f9fa6f8cc11cb2747195a51faf19..515fc153c57f8961e9c69cab598aa112a28030fe 100644 (file)
@@ -36,7 +36,7 @@
 \r
   ID:                 juce_dsp\r
   vendor:             juce\r
-  version:            5.4.5\r
+  version:            5.4.6\r
   name:               JUCE DSP classes\r
   description:        Classes for audio buffer manipulation, digital audio processing, filtering, oversampling, fast math functions etc.\r
   website:            http://www.juce.com/juce\r
index 8aa109d180a4287f68d8329c75b2c0045fbbc81f..ba33d7a7b2426b7fc80382d40c0edf069ee87bcd 100644 (file)
@@ -198,7 +198,7 @@ public:
         with the coefficients of b. After the execution of the algorithm,\r
         the vector b will contain the solution.\r
 \r
-        Returns true if the linear system of euqations was successfully solved.\r
+        Returns true if the linear system of equations was successfully solved.\r
      */\r
     bool solve (Matrix& b) const noexcept;\r
 \r
index f3f302d47d0645851627adedf7b2d3f6ebac398a..7b2e7a8ad75e352caaec3a346851ca87ad6d70e2 100644 (file)
@@ -73,7 +73,7 @@ public:
         @param newValue a value between 0 and 1; higher values increase the resonance and can result in self oscillation! */\r
     void setResonance (Type newValue) noexcept;\r
 \r
-    /** Sets the amound of saturation in the filter.\r
+    /** Sets the amount of saturation in the filter.\r
         @param newValue saturation amount; it can be any number greater than or equal to one. Higher values result in more distortion.*/\r
     void setDrive (Type newValue) noexcept;\r
 \r
index 41b65d5693c8dfca16374f2a6525b2b318ff1f9d..c3bb2da30047ca82a5078d13afdef8e20fd3fe96 100644 (file)
@@ -132,7 +132,7 @@ public:
         auto&& outBlock = context.getOutputBlock();\r
         auto&& inBlock  = context.getInputBlock();\r
 \r
-        // this is an output-only processory\r
+        // this is an output-only processor\r
         jassert (outBlock.getNumSamples() <= static_cast<size_t> (rampBuffer.size()));\r
 \r
         auto len           = outBlock.getNumSamples();\r
index a7b1c8f66b22c5dc4b8ca7347d120a4a48a22353..06cc7298bec64ec8772edfc9e1761b8128273ae8 100644 (file)
@@ -53,13 +53,13 @@ struct Oversampling<SampleType>::OversamplingStage
         buffer.clear();\r
     }\r
 \r
-    dsp::AudioBlock<SampleType> getProcessedSamples (size_t numSamples)\r
+    AudioBlock<SampleType> getProcessedSamples (size_t numSamples)\r
     {\r
-        return dsp::AudioBlock<SampleType> (buffer).getSubBlock (0, numSamples);\r
+        return AudioBlock<SampleType> (buffer).getSubBlock (0, numSamples);\r
     }\r
 \r
-    virtual void processSamplesUp (dsp::AudioBlock<SampleType>&) = 0;\r
-    virtual void processSamplesDown (dsp::AudioBlock<SampleType>&) = 0;\r
+    virtual void processSamplesUp   (const AudioBlock<const SampleType>&) = 0;\r
+    virtual void processSamplesDown (AudioBlock<SampleType>&) = 0;\r
 \r
     AudioBuffer<SampleType> buffer;\r
     size_t numChannels, factor;\r
@@ -83,7 +83,7 @@ struct OversamplingDummy   : public Oversampling<SampleType>::OversamplingStage
         return 0;\r
     }\r
 \r
-    void processSamplesUp (dsp::AudioBlock<SampleType>& inputBlock) override\r
+    void processSamplesUp (const AudioBlock<const SampleType>& inputBlock) override\r
     {\r
         jassert (inputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));\r
         jassert (inputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));\r
@@ -93,7 +93,7 @@ struct OversamplingDummy   : public Oversampling<SampleType>::OversamplingStage
                 inputBlock.getChannelPointer (channel), static_cast<int> (inputBlock.getNumSamples()));\r
     }\r
 \r
-    void processSamplesDown (dsp::AudioBlock<SampleType>& outputBlock) override\r
+    void processSamplesDown (AudioBlock<SampleType>& outputBlock) override\r
     {\r
         jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));\r
         jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));\r
@@ -122,8 +122,8 @@ struct Oversampling2TimesEquirippleFIR  : public Oversampling<SampleType>::Overs
                                      SampleType stopbandAmplitudedBDown)\r
         : ParentType (numChans, 2)\r
     {\r
-        coefficientsUp   = *dsp::FilterDesign<SampleType>::designFIRLowpassHalfBandEquirippleMethod (normalisedTransitionWidthUp,   stopbandAmplitudedBUp);\r
-        coefficientsDown = *dsp::FilterDesign<SampleType>::designFIRLowpassHalfBandEquirippleMethod (normalisedTransitionWidthDown, stopbandAmplitudedBDown);\r
+        coefficientsUp   = *FilterDesign<SampleType>::designFIRLowpassHalfBandEquirippleMethod (normalisedTransitionWidthUp,   stopbandAmplitudedBUp);\r
+        coefficientsDown = *FilterDesign<SampleType>::designFIRLowpassHalfBandEquirippleMethod (normalisedTransitionWidthDown, stopbandAmplitudedBDown);\r
 \r
         auto N = coefficientsUp.getFilterOrder() + 1;\r
         stateUp.setSize (static_cast<int> (this->numChannels), static_cast<int> (N));\r
@@ -155,7 +155,7 @@ struct Oversampling2TimesEquirippleFIR  : public Oversampling<SampleType>::Overs
         position.fill (0);\r
     }\r
 \r
-    void processSamplesUp (dsp::AudioBlock<SampleType>& inputBlock) override\r
+    void processSamplesUp (const AudioBlock<const SampleType>& inputBlock) override\r
     {\r
         jassert (inputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));\r
         jassert (inputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));\r
@@ -195,7 +195,7 @@ struct Oversampling2TimesEquirippleFIR  : public Oversampling<SampleType>::Overs
         }\r
     }\r
 \r
-    void processSamplesDown (dsp::AudioBlock<SampleType>& outputBlock) override\r
+    void processSamplesDown (AudioBlock<SampleType>& outputBlock) override\r
     {\r
         jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));\r
         jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));\r
@@ -248,7 +248,7 @@ struct Oversampling2TimesEquirippleFIR  : public Oversampling<SampleType>::Overs
 \r
 private:\r
     //==============================================================================\r
-    dsp::FIR::Coefficients<SampleType> coefficientsUp, coefficientsDown;\r
+    FIR::Coefficients<SampleType> coefficientsUp, coefficientsDown;\r
     AudioBuffer<SampleType> stateUp, stateDown, stateDown2;\r
     Array<size_t> position;\r
 \r
@@ -274,11 +274,11 @@ struct Oversampling2TimesPolyphaseIIR  : public Oversampling<SampleType>::Oversa
                                     SampleType stopbandAmplitudedBDown)\r
         : ParentType (numChans, 2)\r
     {\r
-        auto structureUp = dsp::FilterDesign<SampleType>::designIIRLowpassHalfBandPolyphaseAllpassMethod (normalisedTransitionWidthUp, stopbandAmplitudedBUp);\r
+        auto structureUp = FilterDesign<SampleType>::designIIRLowpassHalfBandPolyphaseAllpassMethod (normalisedTransitionWidthUp, stopbandAmplitudedBUp);\r
         auto coeffsUp = getCoefficients (structureUp);\r
         latency = static_cast<SampleType> (-(coeffsUp.getPhaseForFrequency (0.0001, 1.0)) / (0.0001 * MathConstants<double>::twoPi));\r
 \r
-        auto structureDown = dsp::FilterDesign<SampleType>::designIIRLowpassHalfBandPolyphaseAllpassMethod (normalisedTransitionWidthDown, stopbandAmplitudedBDown);\r
+        auto structureDown = FilterDesign<SampleType>::designIIRLowpassHalfBandPolyphaseAllpassMethod (normalisedTransitionWidthDown, stopbandAmplitudedBDown);\r
         auto coeffsDown = getCoefficients (structureDown);\r
         latency += static_cast<SampleType> (-(coeffsDown.getPhaseForFrequency (0.0001, 1.0)) / (0.0001 * MathConstants<double>::twoPi));\r
 \r
@@ -313,7 +313,7 @@ struct Oversampling2TimesPolyphaseIIR  : public Oversampling<SampleType>::Oversa
         delayDown.fill (0);\r
     }\r
 \r
-    void processSamplesUp (dsp::AudioBlock<SampleType>& inputBlock) override\r
+    void processSamplesUp (const AudioBlock<const SampleType>& inputBlock) override\r
     {\r
         jassert (inputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));\r
         jassert (inputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));\r
@@ -368,7 +368,7 @@ struct Oversampling2TimesPolyphaseIIR  : public Oversampling<SampleType>::Oversa
         snapToZero (true);\r
     }\r
 \r
-    void processSamplesDown (dsp::AudioBlock<SampleType>& outputBlock) override\r
+    void processSamplesDown (AudioBlock<SampleType>& outputBlock) override\r
     {\r
         jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));\r
         jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));\r
@@ -457,12 +457,12 @@ private:
     /** This function calculates the equivalent high order IIR filter of a given\r
         polyphase cascaded allpass filters structure.\r
     */\r
-    dsp::IIR::Coefficients<SampleType> getCoefficients (typename dsp::FilterDesign<SampleType>::IIRPolyphaseAllpassStructure& structure) const\r
+    IIR::Coefficients<SampleType> getCoefficients (typename FilterDesign<SampleType>::IIRPolyphaseAllpassStructure& structure) const\r
     {\r
         constexpr auto one = static_cast<SampleType> (1.0);\r
 \r
-        dsp::Polynomial<SampleType> numerator1 ({ one }), denominator1 ({ one }),\r
-                                    numerator2 ({ one }), denominator2 ({ one });\r
+        Polynomial<SampleType> numerator1 ({ one }), denominator1 ({ one }),\r
+                               numerator2 ({ one }), denominator2 ({ one });\r
 \r
         for (auto* i : structure.directPath)\r
         {\r
@@ -470,13 +470,13 @@ private:
 \r
             if (i->getFilterOrder() == 1)\r
             {\r
-                numerator1 = numerator1.getProductWith (dsp::Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));\r
-                denominator1 = denominator1.getProductWith (dsp::Polynomial<SampleType> ({ one, coeffs[2] }));\r
+                numerator1   = numerator1  .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));\r
+                denominator1 = denominator1.getProductWith (Polynomial<SampleType> ({ one,       coeffs[2] }));\r
             }\r
             else\r
             {\r
-                numerator1 = numerator1.getProductWith (dsp::Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));\r
-                denominator1 = denominator1.getProductWith (dsp::Polynomial<SampleType> ({ one, coeffs[3], coeffs[4] }));\r
+                numerator1   = numerator1  .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));\r
+                denominator1 = denominator1.getProductWith (Polynomial<SampleType> ({ one,       coeffs[3], coeffs[4] }));\r
             }\r
         }\r
 \r
@@ -486,13 +486,13 @@ private:
 \r
             if (i->getFilterOrder() == 1)\r
             {\r
-                numerator2 = numerator2.getProductWith (dsp::Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));\r
-                denominator2 = denominator2.getProductWith (dsp::Polynomial<SampleType> ({ one, coeffs[2] }));\r
+                numerator2   = numerator2  .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));\r
+                denominator2 = denominator2.getProductWith (Polynomial<SampleType> ({ one,       coeffs[2] }));\r
             }\r
             else\r
             {\r
-                numerator2 = numerator2.getProductWith (dsp::Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));\r
-                denominator2 = denominator2.getProductWith (dsp::Polynomial<SampleType> ({ one, coeffs[3], coeffs[4] }));\r
+                numerator2   = numerator2  .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));\r
+                denominator2 = denominator2.getProductWith (Polynomial<SampleType> ({ one,       coeffs[3], coeffs[4] }));\r
             }\r
         }\r
 \r
@@ -501,7 +501,7 @@ private:
         auto numerator   = numeratorf1.getSumWith (numeratorf2);\r
         auto denominator = denominator1.getProductWith (denominator2);\r
 \r
-        dsp::IIR::Coefficients<SampleType> coeffs;\r
+        IIR::Coefficients<SampleType> coeffs;\r
 \r
         coeffs.coefficients.clear();\r
         auto inversion = one / denominator[0];\r
@@ -677,26 +677,28 @@ void Oversampling<SampleType>::reset() noexcept
 }\r
 \r
 template <typename SampleType>\r
-typename dsp::AudioBlock<SampleType> Oversampling<SampleType>::processSamplesUp (const dsp::AudioBlock<SampleType>& inputBlock) noexcept\r
+AudioBlock<SampleType> Oversampling<SampleType>::processSamplesUp (const AudioBlock<const SampleType>& inputBlock) noexcept\r
 {\r
     jassert (! stages.isEmpty());\r
 \r
     if (! isReady)\r
         return {};\r
 \r
-    auto audioBlock = inputBlock;\r
+    auto* firstStage = stages.getUnchecked (0);\r
+    firstStage->processSamplesUp (inputBlock);\r
+    auto block = firstStage->getProcessedSamples (inputBlock.getNumSamples() * firstStage->factor);\r
 \r
-    for (auto* stage : stages)\r
+    for (int i = 1; i < stages.size(); ++i)\r
     {\r
-        stage->processSamplesUp (audioBlock);\r
-        audioBlock = stage->getProcessedSamples (audioBlock.getNumSamples() * stage->factor);\r
+        stages[i]->processSamplesUp (block);\r
+        block = stages[i]->getProcessedSamples (block.getNumSamples() * stages[i]->factor);\r
     }\r
 \r
-    return audioBlock;\r
+    return block;\r
 }\r
 \r
 template <typename SampleType>\r
-void Oversampling<SampleType>::processSamplesDown (dsp::AudioBlock<SampleType>& outputBlock) noexcept\r
+void Oversampling<SampleType>::processSamplesDown (AudioBlock<SampleType>& outputBlock) noexcept\r
 {\r
     jassert (! stages.isEmpty());\r
 \r
index e4fbb9db09a42779b8b85f087f24e20dbfa2269b..10c715a010c587837145f5ec8ab6338dc91ca254 100644 (file)
@@ -126,14 +126,14 @@ public:
         Don't forget to set the sample rate of that processing to N times the original\r
         sample rate.\r
     */\r
-    dsp::AudioBlock<SampleType> processSamplesUp (const dsp::AudioBlock<SampleType>& inputBlock) noexcept;\r
+    AudioBlock<SampleType> processSamplesUp (const AudioBlock<const SampleType>& inputBlock) noexcept;\r
 \r
     /** Must be called to perform the downsampling, after the upsampling and the\r
         non-linear processing. The output signal is probably delayed by the internal\r
         latency of the whole oversampling behaviour, so don't forget to take this\r
         into account.\r
     */\r
-    void processSamplesDown (dsp::AudioBlock<SampleType>& outputBlock) noexcept;\r
+    void processSamplesDown (AudioBlock<SampleType>& outputBlock) noexcept;\r
 \r
     //==============================================================================\r
     /** Adds a new oversampling stage to the Oversampling class, multiplying the\r
index 7112a8116a6a2cf1350e9defb747569b52046ea8..c900c00c7e5f026f6613fb420b28937dbed49ffe 100644 (file)
@@ -51,7 +51,7 @@ private:
 //==============================================================================\r
 ActionBroadcaster::ActionBroadcaster()\r
 {\r
-    // are you trying to create this object before or after juce has been intialised??\r
+    // are you trying to create this object before or after juce has been initialised??\r
     JUCE_ASSERT_MESSAGE_MANAGER_EXISTS\r
 }\r
 \r
index 3175ad06a4a59af592ddbcc6b8f0dc59b36f7669..f2ddcc5c4ac69c624a5f8a96e46f1398d5cd1938 100644 (file)
 namespace juce\r
 {\r
 \r
+#if JUCE_ANDROID\r
+ extern void acquireMulticastLock();\r
+ extern void releaseMulticastLock();\r
+#endif\r
+\r
 NetworkServiceDiscovery::Advertiser::Advertiser (const String& serviceTypeUID,\r
                                                  const String& serviceDescription,\r
                                                  int broadcastPortToUse, int connectionPort,\r
@@ -73,6 +78,10 @@ void NetworkServiceDiscovery::Advertiser::sendBroadcast()
 NetworkServiceDiscovery::AvailableServiceList::AvailableServiceList (const String& serviceType, int broadcastPort)\r
     : Thread ("Discovery_listen"), serviceTypeUID (serviceType)\r
 {\r
+   #if JUCE_ANDROID\r
+    acquireMulticastLock();\r
+   #endif\r
+\r
     socket.bindToPort (broadcastPort);\r
     startThread (2);\r
 }\r
@@ -81,6 +90,10 @@ NetworkServiceDiscovery::AvailableServiceList::~AvailableServiceList()
 {\r
     socket.shutdown();\r
     stopThread (2000);\r
+\r
+    #if JUCE_ANDROID\r
+     releaseMulticastLock();\r
+    #endif\r
 }\r
 \r
 void NetworkServiceDiscovery::AvailableServiceList::run()\r
index 61ac68ebb19ad55fde5b02b4ac5189ba17cbceb4..5c1fdcd81f91b02c49f94eae101922cb2528bc4e 100644 (file)
@@ -28,6 +28,8 @@ namespace juce
     Contains classes that implement a simple protocol for broadcasting the availability\r
     and location of a discoverable service on the local network, and for maintaining a\r
     list of known services.\r
+\r
+    @tags{Events}\r
 */\r
 struct NetworkServiceDiscovery\r
 {\r
@@ -36,6 +38,8 @@ struct NetworkServiceDiscovery
 \r
         To use, simply create an instance of an Advertiser and it'll broadcast until\r
         you delete it.\r
+\r
+        @tags{Events}\r
     */\r
     struct Advertiser  : private Thread\r
     {\r
@@ -68,7 +72,10 @@ struct NetworkServiceDiscovery
     //==============================================================================\r
     /**\r
         Contains information about a service that has been found on the network.\r
+\r
         @see AvailableServiceList, Advertiser\r
+\r
+        @tags{Events}\r
     */\r
     struct Service\r
     {\r
@@ -87,7 +94,10 @@ struct NetworkServiceDiscovery
         Just create an instance of AvailableServiceList and it will start listening - you\r
         can register a callback with its onChange member to find out when services\r
         appear/disappear, and you can call getServices() to find out the current list.\r
+\r
         @see Service, Advertiser\r
+\r
+        @tags{Events}\r
     */\r
     struct AvailableServiceList  : private Thread,\r
                                    private AsyncUpdater\r
@@ -103,7 +113,7 @@ struct NetworkServiceDiscovery
         /** Destructor */\r
         ~AvailableServiceList() override;\r
 \r
-        /** A lambda that can be set to recieve a callback when the list changes */\r
+        /** A lambda that can be set to receive a callback when the list changes */\r
         std::function<void()> onChange;\r
 \r
         /** Returns a list of the currently known services. */\r
index 078c50dca9f6350e7ac524601caff9dd1d9ead13..316d90b667d7c7296dccc40841cece86360e63d3 100644 (file)
@@ -20,6 +20,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_events\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE message and event handling classes\r
-  description:      Classes for running an application's main event loop and sending/receiving messages, timers, etc.\r
-  website:          http://www.juce.com/juce\r
-  license:          ISC\r
+  ID:                 juce_events\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE message and event handling classes\r
+  description:        Classes for running an application's main event loop and sending/receiving messages, timers, etc.\r
+  website:            http://www.juce.com/juce\r
+  license:            ISC\r
 \r
-  dependencies:     juce_core\r
+  dependencies:       juce_core\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
@@ -50,7 +51,7 @@
 #include <juce_core/juce_core.h>\r
 \r
 //==============================================================================\r
-/** Config: JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK\r
+/** Config: JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK\r
     Will execute your application's suspend method on an iOS background task, giving\r
     you extra time to save your applications state.\r
 */\r
index 78f18aa2d7eef30b75db4b52ec5e57eca28223e1..4a71d16626fb71fdf20285248a920e95f779b8c7 100644 (file)
@@ -34,7 +34,7 @@ void Message::messageCallback()
 \r
 MessageListener::MessageListener() noexcept\r
 {\r
-    // Are you trying to create a messagelistener before or after juce has been intialised??\r
+    // Are you trying to create a messagelistener before or after juce has been initialised??\r
     JUCE_ASSERT_MESSAGE_MANAGER_EXISTS\r
 }\r
 \r
index fd5e1013cd21efb4b216904d473b980b1beaf036..22b2d18951121a613e592d45f49cdebb2d8e129a 100644 (file)
@@ -223,14 +223,14 @@ public:
             If another thread is currently using the MessageManager, this will wait until that\r
             thread releases the lock to the MessageManager.\r
 \r
-            This call will only exit if the lock was accquired by this thread. Calling abort while\r
+            This call will only exit if the lock was acquired by this thread. Calling abort while\r
             a thread is waiting for enter to finish, will have no effect.\r
 \r
             @see exit, abort\r
          */\r
          void enter() const noexcept;\r
 \r
-         /** Attempts to lock the meesage manager and exits if abort is called.\r
+         /** Attempts to lock the message manager and exits if abort is called.\r
 \r
             This method behaves identically to enter, except that it will abort waiting for\r
             the lock if the abort method is called.\r
@@ -270,7 +270,7 @@ public:
                  messageManagerLock.abort();\r
             }\r
 \r
-            @returns false if waiting for a lock was aborted, true if the lock was accquired.\r
+            @returns false if waiting for a lock was aborted, true if the lock was acquired.\r
             @see enter, abort, ScopedTryLock\r
         */\r
         bool tryEnter() const noexcept;\r
@@ -283,7 +283,7 @@ public:
         /** Unblocks a thread which is waiting in tryEnter\r
             Call this method if you want to unblock a thread which is waiting for the\r
             MessageManager lock in tryEnter.\r
-            This method does not have any effetc on a thread waiting for a lock in enter.\r
+            This method does not have any effect on a thread waiting for a lock in enter.\r
             @see tryEnter\r
         */\r
         void abort() const noexcept;\r
index 7287d6c4b61519e5b1b78407bbc1f49f79f7cfbc..49b32b991fe838b26bfa70f804b35758cca05919 100644 (file)
@@ -253,7 +253,7 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMes
     for (;;)\r
     {\r
         if (LinuxErrorHandling::keyboardBreakOccurred)\r
-            JUCEApplicationBase::getInstance()->quit();\r
+            JUCEApplicationBase::quit();\r
 \r
         if (auto* runLoop = InternalRunLoop::getInstanceWithoutCreating())\r
         {\r
index d9eabdf5cddd36ed8486b556f1a0d8ffc742854a..e0f8945a09c8fee0ee61d76ff044ad15ec071969 100644 (file)
@@ -25,81 +25,141 @@ namespace juce
 \r
 extern HWND juce_messageWindowHandle;\r
 \r
+#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client && JucePlugin_Build_Unity\r
+ bool juce_isRunningInUnity();\r
+#endif\r
+\r
+#if JUCE_MODULE_AVAILABLE_juce_gui_extra\r
+ LRESULT juce_offerEventToActiveXControl (::MSG&);\r
+#endif\r
+\r
 using CheckEventBlockedByModalComps = bool (*)(const MSG&);\r
 CheckEventBlockedByModalComps isEventBlockedByModalComps = nullptr;\r
 \r
 using SettingChangeCallbackFunc = void (*)(void);\r
 SettingChangeCallbackFunc settingChangeCallback = nullptr;\r
 \r
-#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client && JucePlugin_Build_Unity\r
- bool juce_isRunningInUnity();\r
-#endif\r
-\r
 //==============================================================================\r
-namespace WindowsMessageHelpers\r
+class InternalMessageQueue\r
 {\r
-    const unsigned int customMessageID = WM_USER + 123;\r
-    const unsigned int broadcastMessageMagicNumber = 0xc403;\r
+public:\r
+    InternalMessageQueue()\r
+    {\r
+        messageWindow = std::make_unique<HiddenMessageWindow> (messageWindowName, (WNDPROC) messageWndProc);\r
+        juce_messageWindowHandle = messageWindow->getHWND();\r
+    }\r
 \r
-    const TCHAR messageWindowName[] = _T("JUCEWindow");\r
-    std::unique_ptr<HiddenMessageWindow> messageWindow;\r
+    ~InternalMessageQueue()\r
+    {\r
+        juce_messageWindowHandle = 0;\r
+        clearSingletonInstance();\r
+    }\r
+\r
+    JUCE_DECLARE_SINGLETON (InternalMessageQueue, false)\r
 \r
-    void dispatchMessageFromLParam (LPARAM lParam)\r
+    //==============================================================================\r
+    void broadcastMessage (const String& message)\r
     {\r
-        if (auto message = reinterpret_cast<MessageManager::MessageBase*> (lParam))\r
-        {\r
-            JUCE_TRY\r
-            {\r
-                message->messageCallback();\r
-            }\r
-            JUCE_CATCH_EXCEPTION\r
+        auto localCopy = message;\r
 \r
-            message->decReferenceCount();\r
+        Array<HWND> windows;\r
+        EnumWindows (&broadcastEnumWindowProc, (LPARAM) &windows);\r
+\r
+        for (int i = windows.size(); --i >= 0;)\r
+        {\r
+            COPYDATASTRUCT data;\r
+            data.dwData = broadcastMessageMagicNumber;\r
+            data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType);\r
+            data.lpData = (void*) localCopy.toUTF32().getAddress();\r
+\r
+            DWORD_PTR result;\r
+            SendMessageTimeout (windows.getUnchecked (i), WM_COPYDATA,\r
+                                (WPARAM) juce_messageWindowHandle,\r
+                                (LPARAM) &data,\r
+                                SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result);\r
         }\r
     }\r
 \r
-    BOOL CALLBACK broadcastEnumWindowProc (HWND hwnd, LPARAM lParam)\r
+    void postMessage (MessageManager::MessageBase* message)\r
     {\r
-        if (hwnd != juce_messageWindowHandle)\r
+        bool shouldTriggerMessageQueueDispatch = false;\r
+\r
         {\r
-            TCHAR windowName[64] = { 0 }; // no need to read longer strings than this\r
-            GetWindowText (hwnd, windowName, 63);\r
+            const ScopedLock sl (lock);\r
 \r
-            if (String (windowName) == messageWindowName)\r
-                reinterpret_cast<Array<HWND>*> (lParam)->add (hwnd);\r
+            shouldTriggerMessageQueueDispatch = messageQueue.isEmpty();\r
+            messageQueue.add (message);\r
         }\r
 \r
-        return TRUE;\r
+        if (! shouldTriggerMessageQueueDispatch)\r
+            return;\r
+\r
+       #if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client && JucePlugin_Build_Unity\r
+        if (juce_isRunningInUnity())\r
+        {\r
+            SendNotifyMessage (juce_messageWindowHandle, customMessageID, 0, 0);\r
+            return;\r
+        }\r
+        #endif\r
+\r
+        PostMessage (juce_messageWindowHandle, customMessageID, 0, 0);\r
     }\r
 \r
-    void handleBroadcastMessage (const COPYDATASTRUCT* data)\r
+    bool dispatchNextMessage (bool returnIfNoPendingMessages)\r
     {\r
-        if (data != nullptr && data->dwData == broadcastMessageMagicNumber)\r
-        {\r
-            struct BroadcastMessage  : public CallbackMessage\r
-            {\r
-                BroadcastMessage (CharPointer_UTF32 text, size_t length) : message (text, length) {}\r
-                void messageCallback() override { MessageManager::getInstance()->deliverBroadcastMessage (message); }\r
+        MSG m;\r
 \r
-                String message;\r
-            };\r
+        if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, PM_NOREMOVE))\r
+            return false;\r
 \r
-            (new BroadcastMessage (CharPointer_UTF32 ((const CharPointer_UTF32::CharType*) data->lpData),\r
-                                   data->cbData / sizeof (CharPointer_UTF32::CharType)))\r
-                ->post();\r
+        if (GetMessage (&m, (HWND) 0, 0, 0) >= 0)\r
+        {\r
+           #if JUCE_MODULE_AVAILABLE_juce_gui_extra\r
+            if (juce_offerEventToActiveXControl (m) != S_FALSE)\r
+                return true;\r
+           #endif\r
+\r
+            if (m.message == customMessageID && m.hwnd == juce_messageWindowHandle)\r
+            {\r
+                dispatchMessages();\r
+            }\r
+            else if (m.message == WM_QUIT)\r
+            {\r
+                if (auto* app = JUCEApplicationBase::getInstance())\r
+                    app->systemRequestedQuit();\r
+            }\r
+            else if (isEventBlockedByModalComps == nullptr || ! isEventBlockedByModalComps (m))\r
+            {\r
+                if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)\r
+                      && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))\r
+                {\r
+                    // if it's someone else's window being clicked on, and the focus is\r
+                    // currently on a juce window, pass the kb focus over..\r
+                    auto currentFocus = GetFocus();\r
+\r
+                    if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))\r
+                        SetFocus (m.hwnd);\r
+                }\r
+\r
+                TranslateMessage (&m);\r
+                DispatchMessage (&m);\r
+            }\r
         }\r
+\r
+        return true;\r
     }\r
 \r
+private:\r
     //==============================================================================\r
-    LRESULT CALLBACK messageWndProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) noexcept\r
+    static LRESULT CALLBACK messageWndProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) noexcept\r
     {\r
         if (h == juce_messageWindowHandle)\r
         {\r
             if (message == customMessageID)\r
             {\r
-                // (These are trapped early in our dispatch loop, but must also be checked\r
-                // here in case some 3rd-party code is running the dispatch loop).\r
-                dispatchMessageFromLParam (lParam);\r
+                if (auto* queue = InternalMessageQueue::getInstanceWithoutCreating())\r
+                    queue->dispatchMessages();\r
+\r
                 return 0;\r
             }\r
 \r
@@ -116,106 +176,125 @@ namespace WindowsMessageHelpers
 \r
         return DefWindowProc (h, message, wParam, lParam);\r
     }\r
-}\r
 \r
-#if JUCE_MODULE_AVAILABLE_juce_gui_extra\r
-LRESULT juce_offerEventToActiveXControl (::MSG&);\r
-#endif\r
+    static BOOL CALLBACK broadcastEnumWindowProc (HWND hwnd, LPARAM lParam)\r
+    {\r
+        if (hwnd != juce_messageWindowHandle)\r
+        {\r
+            TCHAR windowName[64] = { 0 }; // no need to read longer strings than this\r
+            GetWindowText (hwnd, windowName, 63);\r
 \r
-//==============================================================================\r
-bool MessageManager::dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages)\r
-{\r
-    using namespace WindowsMessageHelpers;\r
-    MSG m;\r
+            if (String (windowName) == messageWindowName)\r
+                reinterpret_cast<Array<HWND>*> (lParam)->add (hwnd);\r
+        }\r
 \r
-    if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, PM_NOREMOVE))\r
-        return false;\r
+        return TRUE;\r
+    }\r
 \r
-    if (GetMessage (&m, (HWND) 0, 0, 0) >= 0)\r
+    static void dispatchMessage (MessageManager::MessageBase* message)\r
     {\r
-       #if JUCE_MODULE_AVAILABLE_juce_gui_extra\r
-        if (juce_offerEventToActiveXControl (m) != S_FALSE)\r
-            return true;\r
-       #endif\r
-\r
-        if (m.message == customMessageID && m.hwnd == juce_messageWindowHandle)\r
+        JUCE_TRY\r
         {\r
-            dispatchMessageFromLParam (m.lParam);\r
+            message->messageCallback();\r
         }\r
-        else if (m.message == WM_QUIT)\r
+        JUCE_CATCH_EXCEPTION\r
+\r
+        message->decReferenceCount();\r
+    }\r
+\r
+    static void handleBroadcastMessage (const COPYDATASTRUCT* data)\r
+    {\r
+        if (data != nullptr && data->dwData == broadcastMessageMagicNumber)\r
         {\r
-            if (auto* app = JUCEApplicationBase::getInstance())\r
-                app->systemRequestedQuit();\r
+            struct BroadcastMessage  : public CallbackMessage\r
+            {\r
+                BroadcastMessage (CharPointer_UTF32 text, size_t length) : message (text, length) {}\r
+                void messageCallback() override { MessageManager::getInstance()->deliverBroadcastMessage (message); }\r
+\r
+                String message;\r
+            };\r
+\r
+            (new BroadcastMessage (CharPointer_UTF32 ((const CharPointer_UTF32::CharType*) data->lpData),\r
+                                   data->cbData / sizeof (CharPointer_UTF32::CharType)))\r
+                ->post();\r
         }\r
-        else if (isEventBlockedByModalComps == nullptr || ! isEventBlockedByModalComps (m))\r
+    }\r
+\r
+    void dispatchMessages()\r
+    {\r
+        ReferenceCountedArray<MessageManager::MessageBase> messagesToDispatch;\r
+\r
         {\r
-            if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)\r
-                  && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))\r
-            {\r
-                // if it's someone else's window being clicked on, and the focus is\r
-                // currently on a juce window, pass the kb focus over..\r
-                auto currentFocus = GetFocus();\r
+            const ScopedLock sl (lock);\r
 \r
-                if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))\r
-                    SetFocus (m.hwnd);\r
-            }\r
+            if (messageQueue.isEmpty())\r
+                return;\r
 \r
-            TranslateMessage (&m);\r
-            DispatchMessage (&m);\r
+            messagesToDispatch.swapWith (messageQueue);\r
+        }\r
+\r
+        for (int i = 0; i < messagesToDispatch.size(); ++i)\r
+        {\r
+            auto message = messagesToDispatch.getUnchecked (i);\r
+            message->incReferenceCount();\r
+            dispatchMessage (message.get());\r
         }\r
     }\r
 \r
-    return true;\r
-}\r
+    //==============================================================================\r
+    static constexpr unsigned int customMessageID = WM_USER + 123;\r
+    static constexpr unsigned int broadcastMessageMagicNumber = 0xc403;\r
+    static const TCHAR messageWindowName[];\r
 \r
-bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message)\r
-{\r
-    message->incReferenceCount();\r
+    std::unique_ptr<HiddenMessageWindow> messageWindow;\r
 \r
-   #if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client && JucePlugin_Build_Unity\r
-    if (juce_isRunningInUnity())\r
-        return SendNotifyMessage (juce_messageWindowHandle, WindowsMessageHelpers::customMessageID, 0, (LPARAM) message) != 0;\r
-   #endif\r
+    CriticalSection lock;\r
+    ReferenceCountedArray<MessageManager::MessageBase> messageQueue;\r
 \r
-    return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::customMessageID, 0, (LPARAM) message) != 0;\r
-}\r
+    //==============================================================================\r
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InternalMessageQueue)\r
+};\r
 \r
-void MessageManager::broadcastMessage (const String& value)\r
+JUCE_IMPLEMENT_SINGLETON (InternalMessageQueue)\r
+\r
+const TCHAR InternalMessageQueue::messageWindowName[] = _T("JUCEWindow");\r
+\r
+//==============================================================================\r
+bool MessageManager::dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages)\r
 {\r
-    auto localCopy = value;\r
+    if (auto* queue = InternalMessageQueue::getInstanceWithoutCreating())\r
+        return queue->dispatchNextMessage (returnIfNoPendingMessages);\r
 \r
-    Array<HWND> windows;\r
-    EnumWindows (&WindowsMessageHelpers::broadcastEnumWindowProc, (LPARAM) &windows);\r
+    return false;\r
+}\r
 \r
-    for (int i = windows.size(); --i >= 0;)\r
+bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message)\r
+{\r
+    if (auto* queue = InternalMessageQueue::getInstanceWithoutCreating())\r
     {\r
-        COPYDATASTRUCT data;\r
-        data.dwData = WindowsMessageHelpers::broadcastMessageMagicNumber;\r
-        data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType);\r
-        data.lpData = (void*) localCopy.toUTF32().getAddress();\r
-\r
-        DWORD_PTR result;\r
-        SendMessageTimeout (windows.getUnchecked (i), WM_COPYDATA,\r
-                            (WPARAM) juce_messageWindowHandle,\r
-                            (LPARAM) &data,\r
-                            SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result);\r
+        queue->postMessage (message);\r
+        return true;\r
     }\r
+\r
+    return false;\r
+}\r
+\r
+void MessageManager::broadcastMessage (const String& value)\r
+{\r
+    if (auto* queue = InternalMessageQueue::getInstanceWithoutCreating())\r
+        queue->broadcastMessage (value);\r
 }\r
 \r
 //==============================================================================\r
 void MessageManager::doPlatformSpecificInitialisation()\r
 {\r
     OleInitialize (0);\r
-\r
-    using namespace WindowsMessageHelpers;\r
-    messageWindow.reset (new HiddenMessageWindow (messageWindowName, (WNDPROC) messageWndProc));\r
-    juce_messageWindowHandle = messageWindow->getHWND();\r
+    InternalMessageQueue::getInstance();\r
 }\r
 \r
 void MessageManager::doPlatformSpecificShutdown()\r
 {\r
-    WindowsMessageHelpers::messageWindow = nullptr;\r
-\r
+    InternalMessageQueue::deleteInstance();\r
     OleUninitialize();\r
 }\r
 \r
index 31ab62b6c14a323564758d792b1d981ebb16d2b6..8117e9aee2f701fd374a38d5dde85cb884ea364a 100644 (file)
@@ -284,7 +284,7 @@ public:
     */\r
     Colour withBrightness (float newBrightness) const noexcept;\r
 \r
-    /** Returns a copy of this colour with it hue rotated.\r
+    /** Returns a copy of this colour with its hue rotated.\r
         The new colour's hue is ((this->getHue() + amountToRotate) % 1.0)\r
         @see brighter, darker, withMultipliedBrightness\r
     */\r
index 2b062912052799f6ca448ce41f3ec52a4b4f3513..926157bc133559f25280c6836c6e592ee7275562 100644 (file)
 namespace juce\r
 {\r
 \r
-const Colour Colours::transparentBlack (0);\r
-const Colour Colours::transparentWhite (0x00ffffff);\r
-\r
-const Colour Colours::aliceblue (0xfff0f8ff);\r
-const Colour Colours::antiquewhite (0xfffaebd7);\r
-const Colour Colours::aqua (0xff00ffff);\r
-const Colour Colours::aquamarine (0xff7fffd4);\r
-const Colour Colours::azure (0xfff0ffff);\r
-const Colour Colours::beige (0xfff5f5dc);\r
-const Colour Colours::bisque (0xffffe4c4);\r
-const Colour Colours::black (0xff000000);\r
-const Colour Colours::blanchedalmond (0xffffebcd);\r
-const Colour Colours::blue (0xff0000ff);\r
-const Colour Colours::blueviolet (0xff8a2be2);\r
-const Colour Colours::brown (0xffa52a2a);\r
-const Colour Colours::burlywood (0xffdeb887);\r
-const Colour Colours::cadetblue (0xff5f9ea0);\r
-const Colour Colours::chartreuse (0xff7fff00);\r
-const Colour Colours::chocolate (0xffd2691e);\r
-const Colour Colours::coral (0xffff7f50);\r
-const Colour Colours::cornflowerblue (0xff6495ed);\r
-const Colour Colours::cornsilk (0xfffff8dc);\r
-const Colour Colours::crimson (0xffdc143c);\r
-const Colour Colours::cyan (0xff00ffff);\r
-const Colour Colours::darkblue (0xff00008b);\r
-const Colour Colours::darkcyan (0xff008b8b);\r
-const Colour Colours::darkgoldenrod (0xffb8860b);\r
-const Colour Colours::darkgrey (0xff555555);\r
-const Colour Colours::darkgreen (0xff006400);\r
-const Colour Colours::darkkhaki (0xffbdb76b);\r
-const Colour Colours::darkmagenta (0xff8b008b);\r
-const Colour Colours::darkolivegreen (0xff556b2f);\r
-const Colour Colours::darkorange (0xffff8c00);\r
-const Colour Colours::darkorchid (0xff9932cc);\r
-const Colour Colours::darkred (0xff8b0000);\r
-const Colour Colours::darksalmon (0xffe9967a);\r
-const Colour Colours::darkseagreen (0xff8fbc8f);\r
-const Colour Colours::darkslateblue (0xff483d8b);\r
-const Colour Colours::darkslategrey (0xff2f4f4f);\r
-const Colour Colours::darkturquoise (0xff00ced1);\r
-const Colour Colours::darkviolet (0xff9400d3);\r
-const Colour Colours::deeppink (0xffff1493);\r
-const Colour Colours::deepskyblue (0xff00bfff);\r
-const Colour Colours::dimgrey (0xff696969);\r
-const Colour Colours::dodgerblue (0xff1e90ff);\r
-const Colour Colours::firebrick (0xffb22222);\r
-const Colour Colours::floralwhite (0xfffffaf0);\r
-const Colour Colours::forestgreen (0xff228b22);\r
-const Colour Colours::fuchsia (0xffff00ff);\r
-const Colour Colours::gainsboro (0xffdcdcdc);\r
-const Colour Colours::ghostwhite (0xfff8f8ff);\r
-const Colour Colours::gold (0xffffd700);\r
-const Colour Colours::goldenrod (0xffdaa520);\r
-const Colour Colours::grey (0xff808080);\r
-const Colour Colours::green (0xff008000);\r
-const Colour Colours::greenyellow (0xffadff2f);\r
-const Colour Colours::honeydew (0xfff0fff0);\r
-const Colour Colours::hotpink (0xffff69b4);\r
-const Colour Colours::indianred (0xffcd5c5c);\r
-const Colour Colours::indigo (0xff4b0082);\r
-const Colour Colours::ivory (0xfffffff0);\r
-const Colour Colours::khaki (0xfff0e68c);\r
-const Colour Colours::lavender (0xffe6e6fa);\r
-const Colour Colours::lavenderblush (0xfffff0f5);\r
-const Colour Colours::lawngreen (0xff7cfc00);\r
-const Colour Colours::lemonchiffon (0xfffffacd);\r
-const Colour Colours::lightblue (0xffadd8e6);\r
-const Colour Colours::lightcoral (0xfff08080);\r
-const Colour Colours::lightcyan (0xffe0ffff);\r
-const Colour Colours::lightgoldenrodyellow (0xfffafad2);\r
-const Colour Colours::lightgreen (0xff90ee90);\r
-const Colour Colours::lightgrey (0xffd3d3d3);\r
-const Colour Colours::lightpink (0xffffb6c1);\r
-const Colour Colours::lightsalmon (0xffffa07a);\r
-const Colour Colours::lightseagreen (0xff20b2aa);\r
-const Colour Colours::lightskyblue (0xff87cefa);\r
-const Colour Colours::lightslategrey (0xff778899);\r
-const Colour Colours::lightsteelblue (0xffb0c4de);\r
-const Colour Colours::lightyellow (0xffffffe0);\r
-const Colour Colours::lime (0xff00ff00);\r
-const Colour Colours::limegreen (0xff32cd32);\r
-const Colour Colours::linen (0xfffaf0e6);\r
-const Colour Colours::magenta (0xffff00ff);\r
-const Colour Colours::maroon (0xff800000);\r
-const Colour Colours::mediumaquamarine (0xff66cdaa);\r
-const Colour Colours::mediumblue (0xff0000cd);\r
-const Colour Colours::mediumorchid (0xffba55d3);\r
-const Colour Colours::mediumpurple (0xff9370db);\r
-const Colour Colours::mediumseagreen (0xff3cb371);\r
-const Colour Colours::mediumslateblue (0xff7b68ee);\r
-const Colour Colours::mediumspringgreen (0xff00fa9a);\r
-const Colour Colours::mediumturquoise (0xff48d1cc);\r
-const Colour Colours::mediumvioletred (0xffc71585);\r
-const Colour Colours::midnightblue (0xff191970);\r
-const Colour Colours::mintcream (0xfff5fffa);\r
-const Colour Colours::mistyrose (0xffffe4e1);\r
-const Colour Colours::moccasin (0xffffe4b5);\r
-const Colour Colours::navajowhite (0xffffdead);\r
-const Colour Colours::navy (0xff000080);\r
-const Colour Colours::oldlace (0xfffdf5e6);\r
-const Colour Colours::olive (0xff808000);\r
-const Colour Colours::olivedrab (0xff6b8e23);\r
-const Colour Colours::orange (0xffffa500);\r
-const Colour Colours::orangered (0xffff4500);\r
-const Colour Colours::orchid (0xffda70d6);\r
-const Colour Colours::palegoldenrod (0xffeee8aa);\r
-const Colour Colours::palegreen (0xff98fb98);\r
-const Colour Colours::paleturquoise (0xffafeeee);\r
-const Colour Colours::palevioletred (0xffdb7093);\r
-const Colour Colours::papayawhip (0xffffefd5);\r
-const Colour Colours::peachpuff (0xffffdab9);\r
-const Colour Colours::peru (0xffcd853f);\r
-const Colour Colours::pink (0xffffc0cb);\r
-const Colour Colours::plum (0xffdda0dd);\r
-const Colour Colours::powderblue (0xffb0e0e6);\r
-const Colour Colours::purple (0xff800080);\r
-const Colour Colours::rebeccapurple (0xff663399);\r
-const Colour Colours::red (0xffff0000);\r
-const Colour Colours::rosybrown (0xffbc8f8f);\r
-const Colour Colours::royalblue (0xff4169e1);\r
-const Colour Colours::saddlebrown (0xff8b4513);\r
-const Colour Colours::salmon (0xfffa8072);\r
-const Colour Colours::sandybrown (0xfff4a460);\r
-const Colour Colours::seagreen (0xff2e8b57);\r
-const Colour Colours::seashell (0xfffff5ee);\r
-const Colour Colours::sienna (0xffa0522d);\r
-const Colour Colours::silver (0xffc0c0c0);\r
-const Colour Colours::skyblue (0xff87ceeb);\r
-const Colour Colours::slateblue (0xff6a5acd);\r
-const Colour Colours::slategrey (0xff708090);\r
-const Colour Colours::snow (0xfffffafa);\r
-const Colour Colours::springgreen (0xff00ff7f);\r
-const Colour Colours::steelblue (0xff4682b4);\r
-const Colour Colours::tan (0xffd2b48c);\r
-const Colour Colours::teal (0xff008080);\r
-const Colour Colours::thistle (0xffd8bfd8);\r
-const Colour Colours::tomato (0xffff6347);\r
-const Colour Colours::turquoise (0xff40e0d0);\r
-const Colour Colours::violet (0xffee82ee);\r
-const Colour Colours::wheat (0xfff5deb3);\r
-const Colour Colours::white (0xffffffff);\r
-const Colour Colours::whitesmoke (0xfff5f5f5);\r
-const Colour Colours::yellow (0xffffff00);\r
-const Colour Colours::yellowgreen (0xff9acd32);\r
-\r
 //==============================================================================\r
 Colour Colours::findColourForName (const String& colourName,\r
                                    Colour defaultColour)\r
 {\r
-    static const uint32 presets[] =\r
-    {\r
-        // (first value is the string's hashcode, second is ARGB)\r
+    struct StringHashAndColour { uint32 stringHash, colour; };\r
 \r
-        0x05978fff, 0xff000000, /* black */\r
-        0x06bdcc29, 0xffffffff, /* white */\r
-        0x002e305a, 0xff0000ff, /* blue */\r
-        0x00308adf, 0xff808080, /* grey */\r
-        0x05e0cf03, 0xff008000, /* green */\r
-        0x0001b891, 0xffff0000, /* red */\r
-        0xd43c6474, 0xffffff00, /* yellow */\r
-        0x620886da, 0xfff0f8ff, /* aliceblue */\r
-        0x20a2676a, 0xfffaebd7, /* antiquewhite */\r
-        0x002dcebc, 0xff00ffff, /* aqua */\r
-        0x46bb5f7e, 0xff7fffd4, /* aquamarine */\r
-        0x0590228f, 0xfff0ffff, /* azure */\r
-        0x05947fe4, 0xfff5f5dc, /* beige */\r
-        0xad388e35, 0xffffe4c4, /* bisque */\r
-        0x00674f7e, 0xffffebcd, /* blanchedalmond */\r
-        0x39129959, 0xff8a2be2, /* blueviolet */\r
-        0x059a8136, 0xffa52a2a, /* brown */\r
-        0x89cea8f9, 0xffdeb887, /* burlywood */\r
-        0x0fa260cf, 0xff5f9ea0, /* cadetblue */\r
-        0x6b748956, 0xff7fff00, /* chartreuse */\r
-        0x2903623c, 0xffd2691e, /* chocolate */\r
-        0x05a74431, 0xffff7f50, /* coral */\r
-        0x618d42dd, 0xff6495ed, /* cornflowerblue */\r
-        0xe4b479fd, 0xfffff8dc, /* cornsilk */\r
-        0x3d8c4edf, 0xffdc143c, /* crimson */\r
-        0x002ed323, 0xff00ffff, /* cyan */\r
-        0x67cc74d0, 0xff00008b, /* darkblue */\r
-        0x67cd1799, 0xff008b8b, /* darkcyan */\r
-        0x31bbd168, 0xffb8860b, /* darkgoldenrod */\r
-        0x67cecf55, 0xff555555, /* darkgrey */\r
-        0x920b194d, 0xff006400, /* darkgreen */\r
-        0x923edd4c, 0xffbdb76b, /* darkkhaki */\r
-        0x5c293873, 0xff8b008b, /* darkmagenta */\r
-        0x6b6671fe, 0xff556b2f, /* darkolivegreen */\r
-        0xbcfd2524, 0xffff8c00, /* darkorange */\r
-        0xbcfdf799, 0xff9932cc, /* darkorchid */\r
-        0x55ee0d5b, 0xff8b0000, /* darkred */\r
-        0xc2e5f564, 0xffe9967a, /* darksalmon */\r
-        0x61be858a, 0xff8fbc8f, /* darkseagreen */\r
-        0xc2b0f2bd, 0xff483d8b, /* darkslateblue */\r
-        0xc2b34d42, 0xff2f4f4f, /* darkslategrey */\r
-        0x7cf2b06b, 0xff00ced1, /* darkturquoise */\r
-        0xc8769375, 0xff9400d3, /* darkviolet */\r
-        0x25832862, 0xffff1493, /* deeppink */\r
-        0xfcad568f, 0xff00bfff, /* deepskyblue */\r
-        0x634c8b67, 0xff696969, /* dimgrey */\r
-        0x45c1ce55, 0xff1e90ff, /* dodgerblue */\r
-        0xef19e3cb, 0xffb22222, /* firebrick */\r
-        0xb852b195, 0xfffffaf0, /* floralwhite */\r
-        0xd086fd06, 0xff228b22, /* forestgreen */\r
-        0xe106b6d7, 0xffff00ff, /* fuchsia */\r
-        0x7880d61e, 0xffdcdcdc, /* gainsboro */\r
-        0x2018a2fa, 0xfff8f8ff, /* ghostwhite */\r
-        0x00308060, 0xffffd700, /* gold */\r
-        0xb3b3bc1e, 0xffdaa520, /* goldenrod */\r
-        0xbab8a537, 0xffadff2f, /* greenyellow */\r
-        0xe4cacafb, 0xfff0fff0, /* honeydew */\r
-        0x41892743, 0xffff69b4, /* hotpink */\r
-        0xd5796f1a, 0xffcd5c5c, /* indianred */\r
-        0xb969fed2, 0xff4b0082, /* indigo */\r
-        0x05fef6a9, 0xfffffff0, /* ivory */\r
-        0x06149302, 0xfff0e68c, /* khaki */\r
-        0xad5a05c7, 0xffe6e6fa, /* lavender */\r
-        0x7c4d5b99, 0xfffff0f5, /* lavenderblush */\r
-        0x41cc4377, 0xff7cfc00, /* lawngreen */\r
-        0x195756f0, 0xfffffacd, /* lemonchiffon */\r
-        0x28e4ea70, 0xffadd8e6, /* lightblue */\r
-        0xf3c7ccdb, 0xfff08080, /* lightcoral */\r
-        0x28e58d39, 0xffe0ffff, /* lightcyan */\r
-        0x21234e3c, 0xfffafad2, /* lightgoldenrodyellow */\r
-        0xf40157ad, 0xff90ee90, /* lightgreen */\r
-        0x28e744f5, 0xffd3d3d3, /* lightgrey */\r
-        0x28eb3b8c, 0xffffb6c1, /* lightpink */\r
-        0x9fb78304, 0xffffa07a, /* lightsalmon */\r
-        0x50632b2a, 0xff20b2aa, /* lightseagreen */\r
-        0x68fb7b25, 0xff87cefa, /* lightskyblue */\r
-        0xa8a35ba2, 0xff778899, /* lightslategrey */\r
-        0xa20d484f, 0xffb0c4de, /* lightsteelblue */\r
-        0xaa2cf10a, 0xffffffe0, /* lightyellow */\r
-        0x0032afd5, 0xff00ff00, /* lime */\r
-        0x607bbc4e, 0xff32cd32, /* limegreen */\r
-        0x06234efa, 0xfffaf0e6, /* linen */\r
-        0x316858a9, 0xffff00ff, /* magenta */\r
-        0xbf8ca470, 0xff800000, /* maroon */\r
-        0xbd58e0b3, 0xff66cdaa, /* mediumaquamarine */\r
-        0x967dfd4f, 0xff0000cd, /* mediumblue */\r
-        0x056f5c58, 0xffba55d3, /* mediumorchid */\r
-        0x07556b71, 0xff9370db, /* mediumpurple */\r
-        0x5369b689, 0xff3cb371, /* mediumseagreen */\r
-        0x066be19e, 0xff7b68ee, /* mediumslateblue */\r
-        0x3256b281, 0xff00fa9a, /* mediumspringgreen */\r
-        0xc0ad9f4c, 0xff48d1cc, /* mediumturquoise */\r
-        0x628e63dd, 0xffc71585, /* mediumvioletred */\r
-        0x168eb32a, 0xff191970, /* midnightblue */\r
-        0x4306b960, 0xfff5fffa, /* mintcream */\r
-        0x4cbc0e6b, 0xffffe4e1, /* mistyrose */\r
-        0xd9447d59, 0xffffe4b5, /* moccasin */\r
-        0xe97218a6, 0xffffdead, /* navajowhite */\r
-        0x00337bb6, 0xff000080, /* navy */\r
-        0xadd2d33e, 0xfffdf5e6, /* oldlace */\r
-        0x064ee1db, 0xff808000, /* olive */\r
-        0x9e33a98a, 0xff6b8e23, /* olivedrab */\r
-        0xc3de262e, 0xffffa500, /* orange */\r
-        0x58bebba3, 0xffff4500, /* orangered */\r
-        0xc3def8a3, 0xffda70d6, /* orchid */\r
-        0x28cb4834, 0xffeee8aa, /* palegoldenrod */\r
-        0x3d9dd619, 0xff98fb98, /* palegreen */\r
-        0x74022737, 0xffafeeee, /* paleturquoise */\r
-        0x15e2ebc8, 0xffdb7093, /* palevioletred */\r
-        0x5fd898e2, 0xffffefd5, /* papayawhip */\r
-        0x93e1b776, 0xffffdab9, /* peachpuff */\r
-        0x003472f8, 0xffcd853f, /* peru */\r
-        0x00348176, 0xffffc0cb, /* pink */\r
-        0x00348d94, 0xffdda0dd, /* plum */\r
-        0xd036be93, 0xffb0e0e6, /* powderblue */\r
-        0xc5c507bc, 0xff800080, /* purple */\r
-        0xf381f607, 0xff663399, /* rebeccapurple */\r
-        0xa89d65b3, 0xffbc8f8f, /* rosybrown */\r
-        0xbd9413e1, 0xff4169e1, /* royalblue */\r
-        0xf456044f, 0xff8b4513, /* saddlebrown */\r
-        0xc9c6f66e, 0xfffa8072, /* salmon */\r
-        0x0bb131e1, 0xfff4a460, /* sandybrown */\r
-        0x34636c14, 0xff2e8b57, /* seagreen */\r
-        0x3507fb41, 0xfffff5ee, /* seashell */\r
-        0xca348772, 0xffa0522d, /* sienna */\r
-        0xca37d30d, 0xffc0c0c0, /* silver */\r
-        0x80da74fb, 0xff87ceeb, /* skyblue */\r
-        0x44a8dd73, 0xff6a5acd, /* slateblue */\r
-        0x44ab37f8, 0xff708090, /* slategrey */\r
-        0x0035f183, 0xfffffafa, /* snow */\r
-        0xd5440d16, 0xff00ff7f, /* springgreen */\r
-        0x3e1524a5, 0xff4682b4, /* steelblue */\r
-        0x0001bfa1, 0xffd2b48c, /* tan */\r
-        0x0036425c, 0xff008080, /* teal */\r
-        0xafc8858f, 0xffd8bfd8, /* thistle */\r
-        0xcc41600a, 0xffff6347, /* tomato */\r
-        0xfeea9b21, 0xff40e0d0, /* turquoise */\r
-        0xcf57947f, 0xffee82ee, /* violet */\r
-        0x06bdbae7, 0xfff5deb3, /* wheat */\r
-        0x10802ee6, 0xfff5f5f5, /* whitesmoke */\r
-        0xe1b5130f, 0xff9acd32  /* yellowgreen */\r
+    static const StringHashAndColour presets[]\r
+    {\r
+        { 0x05978fff, 0xff000000 }, /* black */\r
+        { 0x06bdcc29, 0xffffffff }, /* white */\r
+        { 0x002e305a, 0xff0000ff }, /* blue */\r
+        { 0x00308adf, 0xff808080 }, /* grey */\r
+        { 0x05e0cf03, 0xff008000 }, /* green */\r
+        { 0x0001b891, 0xffff0000 }, /* red */\r
+        { 0xd43c6474, 0xffffff00 }, /* yellow */\r
+        { 0x620886da, 0xfff0f8ff }, /* aliceblue */\r
+        { 0x20a2676a, 0xfffaebd7 }, /* antiquewhite */\r
+        { 0x002dcebc, 0xff00ffff }, /* aqua */\r
+        { 0x46bb5f7e, 0xff7fffd4 }, /* aquamarine */\r
+        { 0x0590228f, 0xfff0ffff }, /* azure */\r
+        { 0x05947fe4, 0xfff5f5dc }, /* beige */\r
+        { 0xad388e35, 0xffffe4c4 }, /* bisque */\r
+        { 0x00674f7e, 0xffffebcd }, /* blanchedalmond */\r
+        { 0x39129959, 0xff8a2be2 }, /* blueviolet */\r
+        { 0x059a8136, 0xffa52a2a }, /* brown */\r
+        { 0x89cea8f9, 0xffdeb887 }, /* burlywood */\r
+        { 0x0fa260cf, 0xff5f9ea0 }, /* cadetblue */\r
+        { 0x6b748956, 0xff7fff00 }, /* chartreuse */\r
+        { 0x2903623c, 0xffd2691e }, /* chocolate */\r
+        { 0x05a74431, 0xffff7f50 }, /* coral */\r
+        { 0x618d42dd, 0xff6495ed }, /* cornflowerblue */\r
+        { 0xe4b479fd, 0xfffff8dc }, /* cornsilk */\r
+        { 0x3d8c4edf, 0xffdc143c }, /* crimson */\r
+        { 0x002ed323, 0xff00ffff }, /* cyan */\r
+        { 0x67cc74d0, 0xff00008b }, /* darkblue */\r
+        { 0x67cd1799, 0xff008b8b }, /* darkcyan */\r
+        { 0x31bbd168, 0xffb8860b }, /* darkgoldenrod */\r
+        { 0x67cecf55, 0xff555555 }, /* darkgrey */\r
+        { 0x920b194d, 0xff006400 }, /* darkgreen */\r
+        { 0x923edd4c, 0xffbdb76b }, /* darkkhaki */\r
+        { 0x5c293873, 0xff8b008b }, /* darkmagenta */\r
+        { 0x6b6671fe, 0xff556b2f }, /* darkolivegreen */\r
+        { 0xbcfd2524, 0xffff8c00 }, /* darkorange */\r
+        { 0xbcfdf799, 0xff9932cc }, /* darkorchid */\r
+        { 0x55ee0d5b, 0xff8b0000 }, /* darkred */\r
+        { 0xc2e5f564, 0xffe9967a }, /* darksalmon */\r
+        { 0x61be858a, 0xff8fbc8f }, /* darkseagreen */\r
+        { 0xc2b0f2bd, 0xff483d8b }, /* darkslateblue */\r
+        { 0xc2b34d42, 0xff2f4f4f }, /* darkslategrey */\r
+        { 0x7cf2b06b, 0xff00ced1 }, /* darkturquoise */\r
+        { 0xc8769375, 0xff9400d3 }, /* darkviolet */\r
+        { 0x25832862, 0xffff1493 }, /* deeppink */\r
+        { 0xfcad568f, 0xff00bfff }, /* deepskyblue */\r
+        { 0x634c8b67, 0xff696969 }, /* dimgrey */\r
+        { 0x45c1ce55, 0xff1e90ff }, /* dodgerblue */\r
+        { 0xef19e3cb, 0xffb22222 }, /* firebrick */\r
+        { 0xb852b195, 0xfffffaf0 }, /* floralwhite */\r
+        { 0xd086fd06, 0xff228b22 }, /* forestgreen */\r
+        { 0xe106b6d7, 0xffff00ff }, /* fuchsia */\r
+        { 0x7880d61e, 0xffdcdcdc }, /* gainsboro */\r
+        { 0x2018a2fa, 0xfff8f8ff }, /* ghostwhite */\r
+        { 0x00308060, 0xffffd700 }, /* gold */\r
+        { 0xb3b3bc1e, 0xffdaa520 }, /* goldenrod */\r
+        { 0xbab8a537, 0xffadff2f }, /* greenyellow */\r
+        { 0xe4cacafb, 0xfff0fff0 }, /* honeydew */\r
+        { 0x41892743, 0xffff69b4 }, /* hotpink */\r
+        { 0xd5796f1a, 0xffcd5c5c }, /* indianred */\r
+        { 0xb969fed2, 0xff4b0082 }, /* indigo */\r
+        { 0x05fef6a9, 0xfffffff0 }, /* ivory */\r
+        { 0x06149302, 0xfff0e68c }, /* khaki */\r
+        { 0xad5a05c7, 0xffe6e6fa }, /* lavender */\r
+        { 0x7c4d5b99, 0xfffff0f5 }, /* lavenderblush */\r
+        { 0x41cc4377, 0xff7cfc00 }, /* lawngreen */\r
+        { 0x195756f0, 0xfffffacd }, /* lemonchiffon */\r
+        { 0x28e4ea70, 0xffadd8e6 }, /* lightblue */\r
+        { 0xf3c7ccdb, 0xfff08080 }, /* lightcoral */\r
+        { 0x28e58d39, 0xffe0ffff }, /* lightcyan */\r
+        { 0x21234e3c, 0xfffafad2 }, /* lightgoldenrodyellow */\r
+        { 0xf40157ad, 0xff90ee90 }, /* lightgreen */\r
+        { 0x28e744f5, 0xffd3d3d3 }, /* lightgrey */\r
+        { 0x28eb3b8c, 0xffffb6c1 }, /* lightpink */\r
+        { 0x9fb78304, 0xffffa07a }, /* lightsalmon */\r
+        { 0x50632b2a, 0xff20b2aa }, /* lightseagreen */\r
+        { 0x68fb7b25, 0xff87cefa }, /* lightskyblue */\r
+        { 0xa8a35ba2, 0xff778899 }, /* lightslategrey */\r
+        { 0xa20d484f, 0xffb0c4de }, /* lightsteelblue */\r
+        { 0xaa2cf10a, 0xffffffe0 }, /* lightyellow */\r
+        { 0x0032afd5, 0xff00ff00 }, /* lime */\r
+        { 0x607bbc4e, 0xff32cd32 }, /* limegreen */\r
+        { 0x06234efa, 0xfffaf0e6 }, /* linen */\r
+        { 0x316858a9, 0xffff00ff }, /* magenta */\r
+        { 0xbf8ca470, 0xff800000 }, /* maroon */\r
+        { 0xbd58e0b3, 0xff66cdaa }, /* mediumaquamarine */\r
+        { 0x967dfd4f, 0xff0000cd }, /* mediumblue */\r
+        { 0x056f5c58, 0xffba55d3 }, /* mediumorchid */\r
+        { 0x07556b71, 0xff9370db }, /* mediumpurple */\r
+        { 0x5369b689, 0xff3cb371 }, /* mediumseagreen */\r
+        { 0x066be19e, 0xff7b68ee }, /* mediumslateblue */\r
+        { 0x3256b281, 0xff00fa9a }, /* mediumspringgreen */\r
+        { 0xc0ad9f4c, 0xff48d1cc }, /* mediumturquoise */\r
+        { 0x628e63dd, 0xffc71585 }, /* mediumvioletred */\r
+        { 0x168eb32a, 0xff191970 }, /* midnightblue */\r
+        { 0x4306b960, 0xfff5fffa }, /* mintcream */\r
+        { 0x4cbc0e6b, 0xffffe4e1 }, /* mistyrose */\r
+        { 0xd9447d59, 0xffffe4b5 }, /* moccasin */\r
+        { 0xe97218a6, 0xffffdead }, /* navajowhite */\r
+        { 0x00337bb6, 0xff000080 }, /* navy */\r
+        { 0xadd2d33e, 0xfffdf5e6 }, /* oldlace */\r
+        { 0x064ee1db, 0xff808000 }, /* olive */\r
+        { 0x9e33a98a, 0xff6b8e23 }, /* olivedrab */\r
+        { 0xc3de262e, 0xffffa500 }, /* orange */\r
+        { 0x58bebba3, 0xffff4500 }, /* orangered */\r
+        { 0xc3def8a3, 0xffda70d6 }, /* orchid */\r
+        { 0x28cb4834, 0xffeee8aa }, /* palegoldenrod */\r
+        { 0x3d9dd619, 0xff98fb98 }, /* palegreen */\r
+        { 0x74022737, 0xffafeeee }, /* paleturquoise */\r
+        { 0x15e2ebc8, 0xffdb7093 }, /* palevioletred */\r
+        { 0x5fd898e2, 0xffffefd5 }, /* papayawhip */\r
+        { 0x93e1b776, 0xffffdab9 }, /* peachpuff */\r
+        { 0x003472f8, 0xffcd853f }, /* peru */\r
+        { 0x00348176, 0xffffc0cb }, /* pink */\r
+        { 0x00348d94, 0xffdda0dd }, /* plum */\r
+        { 0xd036be93, 0xffb0e0e6 }, /* powderblue */\r
+        { 0xc5c507bc, 0xff800080 }, /* purple */\r
+        { 0xf381f607, 0xff663399 }, /* rebeccapurple */\r
+        { 0xa89d65b3, 0xffbc8f8f }, /* rosybrown */\r
+        { 0xbd9413e1, 0xff4169e1 }, /* royalblue */\r
+        { 0xf456044f, 0xff8b4513 }, /* saddlebrown */\r
+        { 0xc9c6f66e, 0xfffa8072 }, /* salmon */\r
+        { 0x0bb131e1, 0xfff4a460 }, /* sandybrown */\r
+        { 0x34636c14, 0xff2e8b57 }, /* seagreen */\r
+        { 0x3507fb41, 0xfffff5ee }, /* seashell */\r
+        { 0xca348772, 0xffa0522d }, /* sienna */\r
+        { 0xca37d30d, 0xffc0c0c0 }, /* silver */\r
+        { 0x80da74fb, 0xff87ceeb }, /* skyblue */\r
+        { 0x44a8dd73, 0xff6a5acd }, /* slateblue */\r
+        { 0x44ab37f8, 0xff708090 }, /* slategrey */\r
+        { 0x0035f183, 0xfffffafa }, /* snow */\r
+        { 0xd5440d16, 0xff00ff7f }, /* springgreen */\r
+        { 0x3e1524a5, 0xff4682b4 }, /* steelblue */\r
+        { 0x0001bfa1, 0xffd2b48c }, /* tan */\r
+        { 0x0036425c, 0xff008080 }, /* teal */\r
+        { 0xafc8858f, 0xffd8bfd8 }, /* thistle */\r
+        { 0xcc41600a, 0xffff6347 }, /* tomato */\r
+        { 0xfeea9b21, 0xff40e0d0 }, /* turquoise */\r
+        { 0xcf57947f, 0xffee82ee }, /* violet */\r
+        { 0x06bdbae7, 0xfff5deb3 }, /* wheat */\r
+        { 0x10802ee6, 0xfff5f5f5 }, /* whitesmoke */\r
+        { 0xe1b5130f, 0xff9acd32 }, /* yellowgreen */\r
     };\r
 \r
-    const uint32 hash = (uint32) colourName.trim().toLowerCase().hashCode();\r
+    const auto hash = (uint32) colourName.trim().toLowerCase().hashCode();\r
 \r
-    for (int i = 0; i < numElementsInArray (presets); i += 2)\r
-        if (presets [i] == hash)\r
-            return Colour (presets [i + 1]);\r
+    for (auto entry : presets)\r
+        if (entry.stringHash == hash)\r
+            return Colour (entry.colour);\r
 \r
     return defaultColour;\r
 }\r
index 2acb8d9fa4c3082bbb5fad31ba76fe5ea709276b..370f6b44223ca406e2a89c027d8954426b68c0ba 100644 (file)
@@ -35,59 +35,153 @@ namespace juce
 \r
     @tags{Graphics}\r
 */\r
-class Colours\r
+namespace Colours\r
 {\r
-public:\r
-    static JUCE_API const Colour\r
-\r
-    //==============================================================================\r
-    transparentBlack,   /**< ARGB = 0x00000000 */\r
-    transparentWhite,   /**< ARGB = 0x00ffffff */\r
-\r
-    //==============================================================================\r
-    black,              /**< ARGB = 0xff000000 */\r
-    white,              /**< ARGB = 0xffffffff */\r
-    blue,               /**< ARGB = 0xff0000ff */\r
-    grey,               /**< ARGB = 0xff808080 */\r
-    green,              /**< ARGB = 0xff008000 */\r
-    red,                /**< ARGB = 0xffff0000 */\r
-    yellow,             /**< ARGB = 0xffffff00 */\r
-\r
-    //==============================================================================\r
-    aliceblue,         antiquewhite,       aqua,                   aquamarine,\r
-    azure,             beige,              bisque,                 blanchedalmond,\r
-    blueviolet,        brown,              burlywood,              cadetblue,\r
-    chartreuse,        chocolate,          coral,                  cornflowerblue,\r
-    cornsilk,          crimson,            cyan,                   darkblue,\r
-    darkcyan,          darkgoldenrod,      darkgrey,               darkgreen,\r
-    darkkhaki,         darkmagenta,        darkolivegreen,         darkorange,\r
-    darkorchid,        darkred,            darksalmon,             darkseagreen,\r
-    darkslateblue,     darkslategrey,      darkturquoise,          darkviolet,\r
-    deeppink,          deepskyblue,        dimgrey,                dodgerblue,\r
-    firebrick,         floralwhite,        forestgreen,            fuchsia,\r
-    gainsboro,         ghostwhite,         gold,                   goldenrod,\r
-    greenyellow,       honeydew,           hotpink,                indianred,\r
-    indigo,            ivory,              khaki,                  lavender,\r
-    lavenderblush,     lawngreen,          lemonchiffon,           lightblue,\r
-    lightcoral,        lightcyan,          lightgoldenrodyellow,   lightgreen,\r
-    lightgrey,         lightpink,          lightsalmon,            lightseagreen,\r
-    lightskyblue,      lightslategrey,     lightsteelblue,         lightyellow,\r
-    lime,              limegreen,          linen,                  magenta,\r
-    maroon,            mediumaquamarine,   mediumblue,             mediumorchid,\r
-    mediumpurple,      mediumseagreen,     mediumslateblue,        mediumspringgreen,\r
-    mediumturquoise,   mediumvioletred,    midnightblue,           mintcream,\r
-    mistyrose,         moccasin,           navajowhite,            navy,\r
-    oldlace,           olive,              olivedrab,              orange,\r
-    orangered,         orchid,             palegoldenrod,          palegreen,\r
-    paleturquoise,     palevioletred,      papayawhip,             peachpuff,\r
-    peru,              pink,               plum,                   powderblue,\r
-    purple,            rebeccapurple,      rosybrown,              royalblue,\r
-    saddlebrown,       salmon,             sandybrown,             seagreen,\r
-    seashell,          sienna,             silver,                 skyblue,\r
-    slateblue,         slategrey,          snow,                   springgreen,\r
-    steelblue,         tan,                teal,                   thistle,\r
-    tomato,            turquoise,          violet,                 wheat,\r
-    whitesmoke,        yellowgreen;\r
+\r
+    const Colour transparentBlack     { 0 };\r
+    const Colour transparentWhite     { 0x00ffffff };\r
+\r
+    const Colour aliceblue            { 0xfff0f8ff };\r
+    const Colour antiquewhite         { 0xfffaebd7 };\r
+    const Colour aqua                 { 0xff00ffff };\r
+    const Colour aquamarine           { 0xff7fffd4 };\r
+    const Colour azure                { 0xfff0ffff };\r
+    const Colour beige                { 0xfff5f5dc };\r
+    const Colour bisque               { 0xffffe4c4 };\r
+    const Colour black                { 0xff000000 };\r
+    const Colour blanchedalmond       { 0xffffebcd };\r
+    const Colour blue                 { 0xff0000ff };\r
+    const Colour blueviolet           { 0xff8a2be2 };\r
+    const Colour brown                { 0xffa52a2a };\r
+    const Colour burlywood            { 0xffdeb887 };\r
+    const Colour cadetblue            { 0xff5f9ea0 };\r
+    const Colour chartreuse           { 0xff7fff00 };\r
+    const Colour chocolate            { 0xffd2691e };\r
+    const Colour coral                { 0xffff7f50 };\r
+    const Colour cornflowerblue       { 0xff6495ed };\r
+    const Colour cornsilk             { 0xfffff8dc };\r
+    const Colour crimson              { 0xffdc143c };\r
+    const Colour cyan                 { 0xff00ffff };\r
+    const Colour darkblue             { 0xff00008b };\r
+    const Colour darkcyan             { 0xff008b8b };\r
+    const Colour darkgoldenrod        { 0xffb8860b };\r
+    const Colour darkgrey             { 0xff555555 };\r
+    const Colour darkgreen            { 0xff006400 };\r
+    const Colour darkkhaki            { 0xffbdb76b };\r
+    const Colour darkmagenta          { 0xff8b008b };\r
+    const Colour darkolivegreen       { 0xff556b2f };\r
+    const Colour darkorange           { 0xffff8c00 };\r
+    const Colour darkorchid           { 0xff9932cc };\r
+    const Colour darkred              { 0xff8b0000 };\r
+    const Colour darksalmon           { 0xffe9967a };\r
+    const Colour darkseagreen         { 0xff8fbc8f };\r
+    const Colour darkslateblue        { 0xff483d8b };\r
+    const Colour darkslategrey        { 0xff2f4f4f };\r
+    const Colour darkturquoise        { 0xff00ced1 };\r
+    const Colour darkviolet           { 0xff9400d3 };\r
+    const Colour deeppink             { 0xffff1493 };\r
+    const Colour deepskyblue          { 0xff00bfff };\r
+    const Colour dimgrey              { 0xff696969 };\r
+    const Colour dodgerblue           { 0xff1e90ff };\r
+    const Colour firebrick            { 0xffb22222 };\r
+    const Colour floralwhite          { 0xfffffaf0 };\r
+    const Colour forestgreen          { 0xff228b22 };\r
+    const Colour fuchsia              { 0xffff00ff };\r
+    const Colour gainsboro            { 0xffdcdcdc };\r
+    const Colour ghostwhite           { 0xfff8f8ff };\r
+    const Colour gold                 { 0xffffd700 };\r
+    const Colour goldenrod            { 0xffdaa520 };\r
+    const Colour grey                 { 0xff808080 };\r
+    const Colour green                { 0xff008000 };\r
+    const Colour greenyellow          { 0xffadff2f };\r
+    const Colour honeydew             { 0xfff0fff0 };\r
+    const Colour hotpink              { 0xffff69b4 };\r
+    const Colour indianred            { 0xffcd5c5c };\r
+    const Colour indigo               { 0xff4b0082 };\r
+    const Colour ivory                { 0xfffffff0 };\r
+    const Colour khaki                { 0xfff0e68c };\r
+    const Colour lavender             { 0xffe6e6fa };\r
+    const Colour lavenderblush        { 0xfffff0f5 };\r
+    const Colour lawngreen            { 0xff7cfc00 };\r
+    const Colour lemonchiffon         { 0xfffffacd };\r
+    const Colour lightblue            { 0xffadd8e6 };\r
+    const Colour lightcoral           { 0xfff08080 };\r
+    const Colour lightcyan            { 0xffe0ffff };\r
+    const Colour lightgoldenrodyellow { 0xfffafad2 };\r
+    const Colour lightgreen           { 0xff90ee90 };\r
+    const Colour lightgrey            { 0xffd3d3d3 };\r
+    const Colour lightpink            { 0xffffb6c1 };\r
+    const Colour lightsalmon          { 0xffffa07a };\r
+    const Colour lightseagreen        { 0xff20b2aa };\r
+    const Colour lightskyblue         { 0xff87cefa };\r
+    const Colour lightslategrey       { 0xff778899 };\r
+    const Colour lightsteelblue       { 0xffb0c4de };\r
+    const Colour lightyellow          { 0xffffffe0 };\r
+    const Colour lime                 { 0xff00ff00 };\r
+    const Colour limegreen            { 0xff32cd32 };\r
+    const Colour linen                { 0xfffaf0e6 };\r
+    const Colour magenta              { 0xffff00ff };\r
+    const Colour maroon               { 0xff800000 };\r
+    const Colour mediumaquamarine     { 0xff66cdaa };\r
+    const Colour mediumblue           { 0xff0000cd };\r
+    const Colour mediumorchid         { 0xffba55d3 };\r
+    const Colour mediumpurple         { 0xff9370db };\r
+    const Colour mediumseagreen       { 0xff3cb371 };\r
+    const Colour mediumslateblue      { 0xff7b68ee };\r
+    const Colour mediumspringgreen    { 0xff00fa9a };\r
+    const Colour mediumturquoise      { 0xff48d1cc };\r
+    const Colour mediumvioletred      { 0xffc71585 };\r
+    const Colour midnightblue         { 0xff191970 };\r
+    const Colour mintcream            { 0xfff5fffa };\r
+    const Colour mistyrose            { 0xffffe4e1 };\r
+    const Colour moccasin             { 0xffffe4b5 };\r
+    const Colour navajowhite          { 0xffffdead };\r
+    const Colour navy                 { 0xff000080 };\r
+    const Colour oldlace              { 0xfffdf5e6 };\r
+    const Colour olive                { 0xff808000 };\r
+    const Colour olivedrab            { 0xff6b8e23 };\r
+    const Colour orange               { 0xffffa500 };\r
+    const Colour orangered            { 0xffff4500 };\r
+    const Colour orchid               { 0xffda70d6 };\r
+    const Colour palegoldenrod        { 0xffeee8aa };\r
+    const Colour palegreen            { 0xff98fb98 };\r
+    const Colour paleturquoise        { 0xffafeeee };\r
+    const Colour palevioletred        { 0xffdb7093 };\r
+    const Colour papayawhip           { 0xffffefd5 };\r
+    const Colour peachpuff            { 0xffffdab9 };\r
+    const Colour peru                 { 0xffcd853f };\r
+    const Colour pink                 { 0xffffc0cb };\r
+    const Colour plum                 { 0xffdda0dd };\r
+    const Colour powderblue           { 0xffb0e0e6 };\r
+    const Colour purple               { 0xff800080 };\r
+    const Colour rebeccapurple        { 0xff663399 };\r
+    const Colour red                  { 0xffff0000 };\r
+    const Colour rosybrown            { 0xffbc8f8f };\r
+    const Colour royalblue            { 0xff4169e1 };\r
+    const Colour saddlebrown          { 0xff8b4513 };\r
+    const Colour salmon               { 0xfffa8072 };\r
+    const Colour sandybrown           { 0xfff4a460 };\r
+    const Colour seagreen             { 0xff2e8b57 };\r
+    const Colour seashell             { 0xfffff5ee };\r
+    const Colour sienna               { 0xffa0522d };\r
+    const Colour silver               { 0xffc0c0c0 };\r
+    const Colour skyblue              { 0xff87ceeb };\r
+    const Colour slateblue            { 0xff6a5acd };\r
+    const Colour slategrey            { 0xff708090 };\r
+    const Colour snow                 { 0xfffffafa };\r
+    const Colour springgreen          { 0xff00ff7f };\r
+    const Colour steelblue            { 0xff4682b4 };\r
+    const Colour tan                  { 0xffd2b48c };\r
+    const Colour teal                 { 0xff008080 };\r
+    const Colour thistle              { 0xffd8bfd8 };\r
+    const Colour tomato               { 0xffff6347 };\r
+    const Colour turquoise            { 0xff40e0d0 };\r
+    const Colour violet               { 0xffee82ee };\r
+    const Colour wheat                { 0xfff5deb3 };\r
+    const Colour white                { 0xffffffff };\r
+    const Colour whitesmoke           { 0xfff5f5f5 };\r
+    const Colour yellow               { 0xffffff00 };\r
+    const Colour yellowgreen          { 0xff9acd32 };\r
 \r
     /** Attempts to look up a string in the list of known colour names, and return\r
         the appropriate colour.\r
@@ -96,16 +190,8 @@ public:
         if a match is found, that colour is returned. If no match is found, the\r
         colour passed in as the defaultColour parameter is returned.\r
     */\r
-    static JUCE_API Colour findColourForName (const String& colourName,\r
-                                              Colour defaultColour);\r
-\r
-private:\r
-    //==============================================================================\r
-    // this isn't a class you should ever instantiate - it's just here for the\r
-    // static values in it.\r
-    Colours();\r
-\r
-    JUCE_DECLARE_NON_COPYABLE (Colours)\r
-};\r
+    JUCE_API Colour findColourForName (const String& colourName,\r
+                                       Colour defaultColour);\r
+} // namespace Colours\r
 \r
 } // namespace juce\r
index 95b5f2576e17dfd27481cf422da9ebf845c2d186..e056340751e663b748d2e18f09f804ac8de870d0 100644 (file)
@@ -492,7 +492,7 @@ public:
     /** Draws part of an image, rescaling it to fit in a given target region.\r
 \r
         The specified area of the source image is rescaled and drawn to fill the\r
-        specifed destination rectangle.\r
+        specified destination rectangle.\r
 \r
         Images are composited using the context's current opacity, so if you\r
         don't want it to be drawn semi-transparently, be sure to call setOpacity (1.0f)\r
index 91870c85ea94cec128693fed910432a66f49480c..0b51473870496c874013d59c97b366cca24f909f 100644 (file)
@@ -134,7 +134,7 @@ public:
 \r
         This may also be set to Font::getDefaultSansSerifFontName(), Font::getDefaultSerifFontName(),\r
         or Font::getDefaultMonospacedFontName(), which are not actual platform-specific font family names,\r
-        but are generic font familiy names that are used to represent the various default fonts.\r
+        but are generic font family names that are used to represent the various default fonts.\r
 \r
         If you need to know the exact typeface font family being used, you can call\r
         Font::getTypeface()->getName(), which will give you the platform-specific font family.\r
index de5c1dca8d5c8ff2ba45d177e506ca9cccaa35f7..148c655e3002720bf860c1d029e2e93e60b424fc 100644 (file)
@@ -711,7 +711,7 @@ void GlyphArrangement::draw (const Graphics& g, AffineTransform transform) const
 \r
     for (int i = 0; i < glyphs.size(); ++i)\r
     {\r
-        auto& pg = glyphs.getReference(i);\r
+        auto& pg = glyphs.getReference (i);\r
 \r
         if (pg.font.isUnderlined())\r
             drawGlyphUnderline (g, pg, i, transform);\r
index 8b2444cf6f5b0b2ee8d2646d02627f8de8151b78..2cd8f78f518aecbd2d8a12c5bc0409bbd81988ae 100644 (file)
@@ -222,6 +222,8 @@ void TextLayout::draw (Graphics& g, Rectangle<float> area) const
     auto origin = justification.appliedToRectangle (Rectangle<float> (width, getHeight()), area).getPosition();\r
 \r
     auto& context   = g.getInternalContext();\r
+    context.saveState();\r
+\r
     auto clip       = context.getClipBounds();\r
     auto clipTop    = clip.getY()      - origin.y;\r
     auto clipBottom = clip.getBottom() - origin.y;\r
@@ -257,6 +259,8 @@ void TextLayout::draw (Graphics& g, Rectangle<float> area) const
             }\r
         }\r
     }\r
+\r
+    context.restoreState();\r
 }\r
 \r
 void TextLayout::createLayout (const AttributedString& text, float maxWidth)\r
index f1019a38d037aef2e75002835461f0df34477ddb..663c29c26bfb7ec28e097d54e13bd40d6910da3e 100644 (file)
@@ -119,7 +119,7 @@ public:
     */\r
     virtual bool getOutlineForGlyph (int glyphNumber, Path& path) = 0;\r
 \r
-    /** Returns a new EdgeTable that contains the path for the givem glyph, with the specified transform applied. */\r
+    /** Returns a new EdgeTable that contains the path for the given glyph, with the specified transform applied. */\r
     virtual EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform, float fontHeight);\r
 \r
     /** Returns true if the typeface uses hinting. */\r
index 85427116f8e7d9ca051de78e2d2b6ac5eb1e97bf..06452d49901069614625e8e2b6ed8c23bd3fb9d9 100644 (file)
@@ -270,7 +270,7 @@ public:
     */\r
     float getScaleFactor() const noexcept;\r
 \r
-    /* A ready-to-use identity transform - now depracated.\r
+    /* A ready-to-use identity transform - now deprecated.\r
        @deprecated If you need an identity transform, just use AffineTransform() or {}.\r
     */\r
     JUCE_DEPRECATED_STATIC (static const AffineTransform identity;)\r
index e418dcf6ba3cb089553a8b362420fd69af082fe2..f55e38d126a81fff3b32eeec5c8dd8659f8b215d 100644 (file)
@@ -162,7 +162,7 @@ public:
                 + (bottomLeft - topLeft) * relativePosition.y;\r
     }\r
 \r
-    /** Returns a transformed verstion of the parallelogram. */\r
+    /** Returns a transformed version of the parallelogram. */\r
     Parallelogram transformedBy (const AffineTransform& transform) const noexcept\r
     {\r
         auto p = *this;\r
index 73e728eb2db228cb8990fb44abc600eba2d20361..e0cf526dea0e53b92a6742d1ed6ca86422da3909 100644 (file)
@@ -440,7 +440,7 @@ public:
                             draw a curve clockwise from the 9 o'clock position to the 3 o'clock position via\r
                             12 o'clock, you'd use 1.5*Pi and 2.5*Pi as the start and finish points.\r
         @param startAsNewSubPath    if true, the arc will begin a new subpath from its starting point; if false,\r
-                            it will be added to the current sub-path, continuing from the current postition\r
+                            it will be added to the current sub-path, continuing from the current position\r
 \r
         @see addCentredArc, arcTo, addPieSegment, addEllipse\r
     */\r
@@ -467,7 +467,7 @@ public:
                             draw a curve clockwise from the 9 o'clock position to the 3 o'clock position via\r
                             12 o'clock, you'd use 1.5*Pi and 2.5*Pi as the start and finish points.\r
         @param startAsNewSubPath    if true, the arc will begin a new subpath from its starting point; if false,\r
-                            it will be added to the current sub-path, continuing from the current postition\r
+                            it will be added to the current sub-path, continuing from the current position\r
 \r
         @see addArc, arcTo\r
     */\r
@@ -653,7 +653,7 @@ public:
         @param preserveProportions  if true, it will fit the path into the space without altering its\r
                                     horizontal/vertical scale ratio; if false, it will distort the\r
                                     path to fill the specified ratio both horizontally and vertically\r
-        @param justificationType    if the proportions are preseved, the resultant path may be smaller\r
+        @param justificationType    if the proportions are preserved, the resultant path may be smaller\r
                                     than the available rectangle, so this describes how it should be\r
                                     positioned within the space.\r
         @returns                    an appropriate transformation\r
@@ -671,7 +671,7 @@ public:
         @param preserveProportions  if true, it will fit the path into the space without altering its\r
                                     horizontal/vertical scale ratio; if false, it will distort the\r
                                     path to fill the specified ratio both horizontally and vertically\r
-        @param justificationType    if the proportions are preseved, the resultant path may be smaller\r
+        @param justificationType    if the proportions are preserved, the resultant path may be smaller\r
                                     than the available rectangle, so this describes how it should be\r
                                     positioned within the space.\r
         @returns                    an appropriate transformation\r
index 10d2c36046b384eaf9681071f68122dfbe9ce06e..746a738bfb254b4800f2ea2de3d0cba65893836b 100644 (file)
@@ -336,13 +336,13 @@ public:
 \r
         /** Returns the colour of a given pixel.\r
             For performance reasons, this won't do any bounds-checking on the coordinates, so it's the caller's\r
-            repsonsibility to make sure they're within the image's size.\r
+            responsibility to make sure they're within the image's size.\r
         */\r
         Colour getPixelColour (int x, int y) const noexcept;\r
 \r
         /** Sets the colour of a given pixel.\r
             For performance reasons, this won't do any bounds-checking on the coordinates, so it's the caller's\r
-            repsonsibility to make sure they're within the image's size.\r
+            responsibility to make sure they're within the image's size.\r
         */\r
         void setPixelColour (int x, int y, Colour colour) const noexcept;\r
 \r
index 84369580d89998a25603b9a2385bf49f302b48ce..8383ce40710954e393624ba086d223acf28ec31d 100644 (file)
@@ -39,7 +39,7 @@ class JUCE_API  ImageConvolutionKernel
 {\r
 public:\r
     //==============================================================================\r
-    /** Creates an empty convulution kernel.\r
+    /** Creates an empty convolution kernel.\r
 \r
         @param size     the length of each dimension of the kernel, so e.g. if the size\r
                         is 5, it will create a 5x5 kernel\r
@@ -73,7 +73,7 @@ public:
     /** Multiplies all values in the kernel by a value. */\r
     void rescaleAllValues (float multiplier);\r
 \r
-    /** Intialises the kernel for a gaussian blur.\r
+    /** Initialises the kernel for a gaussian blur.\r
 \r
         @param blurRadius   this may be larger or smaller than the kernel's actual\r
                             size but this will obviously be wasteful or clip at the\r
index 87d08424f9521bd01cec0f81747d353d57caf5ce..39d8ca46c4f9e1d8cd0004df6a1cf7be53d94201 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_graphics\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE graphics classes\r
-  description:      Classes for 2D vector graphics, image loading/saving, font handling, etc.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
-\r
-  dependencies:     juce_events\r
-  OSXFrameworks:    Cocoa QuartzCore\r
-  iOSFrameworks:    CoreGraphics CoreImage CoreText QuartzCore\r
-  linuxPackages:    x11 xinerama xext freetype2\r
+  ID:                 juce_graphics\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE graphics classes\r
+  description:        Classes for 2D vector graphics, image loading/saving, font handling, etc.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
+\r
+  dependencies:       juce_events\r
+  OSXFrameworks:      Cocoa QuartzCore\r
+  iOSFrameworks:      CoreGraphics CoreImage CoreText QuartzCore\r
+  linuxPackages:      x11 xinerama xext freetype2\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 02c69a5aec64cec422a9b3e5397579409419750d..910304d48575debf6e4f09c4728b9dae8e042a14 100644 (file)
@@ -93,7 +93,8 @@ private:
         FillType fillType;\r
         Font font;\r
         CGFontRef fontRef = {};\r
-        AffineTransform fontTransform, inverseFontTransform;\r
+        CGAffineTransform textMatrix = CGAffineTransformIdentity,\r
+                   inverseTextMatrix = CGAffineTransformIdentity;\r
         CGGradientRef gradient = {};\r
     };\r
 \r
index f34002a69d2ea20a506db8ac3e3c0dcca3ddd1f0..3f87574eaaed3f2ee3081cc8f73f955f9a6d103f 100644 (file)
@@ -28,10 +28,13 @@ namespace juce
 {\r
 \r
 //==============================================================================\r
-class CoreGraphicsImage   : public ImagePixelData\r
+// This class has been renamed from CoreGraphicsImage to avoid a symbol\r
+// collision in Pro Tools 2019.12 and possibly 2020 depending on the Pro Tools\r
+// release schedule.\r
+class CoreGraphicsPixelData   : public ImagePixelData\r
 {\r
 public:\r
-    CoreGraphicsImage (const Image::PixelFormat format, int w, int h, bool clearImage)\r
+    CoreGraphicsPixelData (const Image::PixelFormat format, int w, int h, bool clearImage)\r
         : ImagePixelData (format, w, h)\r
     {\r
         pixelStride = format == Image::RGB ? 3 : ((format == Image::ARGB) ? 4 : 1);\r
@@ -57,7 +60,7 @@ public:
         CGColorSpaceRelease (colourSpace);\r
     }\r
 \r
-    ~CoreGraphicsImage() override\r
+    ~CoreGraphicsPixelData() override\r
     {\r
         freeCachedImageRef();\r
         CGContextRelease (context);\r
@@ -86,7 +89,7 @@ public:
 \r
     ImagePixelData::Ptr clone() override\r
     {\r
-        auto im = new CoreGraphicsImage (pixelFormat, width, height, false);\r
+        auto im = new CoreGraphicsPixelData (pixelFormat, width, height, false);\r
         memcpy (im->imageDataHolder->data, imageDataHolder->data, (size_t) (lineStride * height));\r
         return *im;\r
     }\r
@@ -96,7 +99,7 @@ public:
     //==============================================================================\r
     static CGImageRef getCachedImageRef (const Image& juceImage, CGColorSpaceRef colourSpace)\r
     {\r
-        auto cgim = dynamic_cast<CoreGraphicsImage*> (juceImage.getPixelData());\r
+        auto cgim = dynamic_cast<CoreGraphicsPixelData*> (juceImage.getPixelData());\r
 \r
         if (cgim != nullptr && cgim->cachedImageRef != nullptr)\r
         {\r
@@ -127,7 +130,7 @@ public:
         {\r
             auto* imageDataContainer = [](const Image& img) -> HeapBlockContainer::Ptr*\r
             {\r
-                if (auto* cgim = dynamic_cast<CoreGraphicsImage*> (img.getPixelData()))\r
+                if (auto* cgim = dynamic_cast<CoreGraphicsPixelData*> (img.getPixelData()))\r
                     return new HeapBlockContainer::Ptr (cgim->imageDataHolder);\r
 \r
                 return nullptr;\r
@@ -183,12 +186,12 @@ private:
        #endif\r
     }\r
 \r
-    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreGraphicsImage)\r
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreGraphicsPixelData)\r
 };\r
 \r
 ImagePixelData::Ptr NativeImageType::create (Image::PixelFormat format, int width, int height, bool clearImage) const\r
 {\r
-    return *new CoreGraphicsImage (format == Image::RGB ? Image::ARGB : format, width, height, clearImage);\r
+    return *new CoreGraphicsPixelData (format == Image::RGB ? Image::ARGB : format, width, height, clearImage);\r
 }\r
 \r
 //==============================================================================\r
@@ -326,7 +329,7 @@ void CoreGraphicsContext::clipToImageAlpha (const Image& sourceImage, const Affi
         if (sourceImage.getFormat() != Image::SingleChannel)\r
             singleChannelImage = sourceImage.convertedToFormat (Image::SingleChannel);\r
 \r
-        CGImageRef image = CoreGraphicsImage::createImage (singleChannelImage, greyColourSpace, true);\r
+        CGImageRef image = CoreGraphicsPixelData::createImage (singleChannelImage, greyColourSpace, true);\r
 \r
         flip();\r
         auto t = AffineTransform::verticalFlip (sourceImage.getHeight()).followedBy (transform);\r
@@ -383,6 +386,8 @@ void CoreGraphicsContext::restoreState()
     if (auto* top = stateStack.getLast())\r
     {\r
         state.reset (top);\r
+        CGContextSetTextMatrix (context, state->textMatrix);\r
+\r
         stateStack.removeLast (1, false);\r
         lastClipRectIsValid = false;\r
     }\r
@@ -522,7 +527,7 @@ void CoreGraphicsContext::drawImage (const Image& sourceImage, const AffineTrans
 \r
     auto colourSpace = sourceImage.getFormat() == Image::PixelFormat::SingleChannel ? greyColourSpace\r
                                                                                     : rgbColourSpace;\r
-    CGImageRef image = CoreGraphicsImage::getCachedImageRef (sourceImage, colourSpace);\r
+    CGImageRef image = CoreGraphicsPixelData::getCachedImageRef (sourceImage, colourSpace);\r
 \r
     CGContextSaveGState (context);\r
     CGContextSetAlpha (context, state->fillType.getOpacity());\r
@@ -623,20 +628,11 @@ void CoreGraphicsContext::setFont (const Font& newFont)
             CGContextSetFont (context, state->fontRef);\r
             CGContextSetFontSize (context, state->font.getHeight() * osxTypeface->fontHeightToPointsFactor);\r
 \r
-            auto fontTransform = osxTypeface->renderingTransform;\r
-            fontTransform.a *= state->font.getHorizontalScale();\r
-            CGContextSetTextMatrix (context, fontTransform);\r
-\r
-            auto cgTransformToJuceTransform = [](CGAffineTransform& t) -> AffineTransform\r
-            {\r
-                return { (float) t.a, (float) t.c, (float) t.tx,\r
-                         (float) t.b, (float) t.d, (float) t.ty };\r
-            };\r
-\r
-            state->fontTransform = cgTransformToJuceTransform (fontTransform);\r
-            auto inverseFontTransform = CGAffineTransformInvert (fontTransform);\r
-            state->inverseFontTransform = cgTransformToJuceTransform (inverseFontTransform);\r
-        }\r
+            state->textMatrix = osxTypeface->renderingTransform;\r
+            state->textMatrix.a *= state->font.getHorizontalScale();\r
+            CGContextSetTextMatrix (context, state->textMatrix);\r
+            state->inverseTextMatrix = CGAffineTransformInvert (state->textMatrix);\r
+         }\r
     }\r
 }\r
 \r
@@ -649,12 +645,18 @@ void CoreGraphicsContext::drawGlyph (int glyphNumber, const AffineTransform& tra
 {\r
     if (state->fontRef != nullptr && state->fillType.isColour())\r
     {\r
-        if (transform.isOnlyTranslation() && state->fontTransform.isOnlyTranslation())\r
+        auto cgTransformIsOnlyTranslation = [](CGAffineTransform t)\r
+        {\r
+            return t.a == 1.0f && t.d == 1.0f && t.b == 0.0f && t.c == 0.0f;\r
+        };\r
+\r
+        if (transform.isOnlyTranslation() && cgTransformIsOnlyTranslation (state->inverseTextMatrix))\r
         {\r
-            auto t = transform.followedBy (state->inverseFontTransform);\r
+            auto x = transform.mat02 + state->inverseTextMatrix.tx;\r
+            auto y = transform.mat12 + state->inverseTextMatrix.ty;\r
 \r
             CGGlyph glyphs[1] = { (CGGlyph) glyphNumber };\r
-            CGPoint positions[1] = { { t.getTranslationX(), flipHeight - roundToInt (t.getTranslationY()) } };\r
+            CGPoint positions[1] = { { x, flipHeight - roundToInt (y) } };\r
             CGContextShowGlyphsAtPositions (context, glyphs, positions, 1);\r
         }\r
         else\r
@@ -662,9 +664,11 @@ void CoreGraphicsContext::drawGlyph (int glyphNumber, const AffineTransform& tra
             CGContextSaveGState (context);\r
 \r
             flip();\r
-            auto fontTransform = state->fontTransform;\r
-            fontTransform.mat11 = -fontTransform.mat11;\r
-            applyTransform (fontTransform.followedBy (state->inverseFontTransform).followedBy (transform));\r
+            applyTransform (transform);\r
+            CGContextConcatCTM (context, state->inverseTextMatrix);\r
+            auto cgTransform = state->textMatrix;\r
+            cgTransform.d = -cgTransform.d;\r
+            CGContextConcatCTM (context, cgTransform);\r
 \r
             CGGlyph glyphs[1] = { (CGGlyph) glyphNumber };\r
             CGPoint positions[1] = { { 0.0f, 0.0f } };\r
@@ -697,8 +701,7 @@ CoreGraphicsContext::SavedState::SavedState()
 \r
 CoreGraphicsContext::SavedState::SavedState (const SavedState& other)\r
     : fillType (other.fillType), font (other.font), fontRef (other.fontRef),\r
-      fontTransform (other.fontTransform),\r
-      inverseFontTransform (other.inverseFontTransform),\r
+      textMatrix (other.textMatrix), inverseTextMatrix (other.inverseTextMatrix),\r
       gradient (other.gradient)\r
 {\r
     if (gradient != nullptr)\r
@@ -887,8 +890,8 @@ Image juce_loadWithCoreImage (InputStream& input)
                                                        (int) CGImageGetHeight (loadedImage),\r
                                                        hasAlphaChan));\r
 \r
-                auto cgImage = dynamic_cast<CoreGraphicsImage*> (image.getPixelData());\r
-                jassert (cgImage != nullptr); // if USE_COREGRAPHICS_RENDERING is set, the CoreGraphicsImage class should have been used.\r
+                auto cgImage = dynamic_cast<CoreGraphicsPixelData*> (image.getPixelData());\r
+                jassert (cgImage != nullptr); // if USE_COREGRAPHICS_RENDERING is set, the CoreGraphicsPixelData class should have been used.\r
 \r
                 CGContextDrawImage (cgImage->context, convertToCGRect (image.getBounds()), loadedImage);\r
                 CGContextFlush (cgImage->context);\r
@@ -912,7 +915,7 @@ Image juce_loadWithCoreImage (InputStream& input)
 Image juce_createImageFromCIImage (CIImage*, int, int);\r
 Image juce_createImageFromCIImage (CIImage* im, int w, int h)\r
 {\r
-    auto cgImage = new CoreGraphicsImage (Image::ARGB, w, h, false);\r
+    auto cgImage = new CoreGraphicsPixelData (Image::ARGB, w, h, false);\r
 \r
     CIContext* cic = [CIContext contextWithCGContext: cgImage->context options: nil];\r
     [cic drawImage: im inRect: CGRectMake (0, 0, w, h) fromRect: CGRectMake (0, 0, w, h)];\r
@@ -924,12 +927,12 @@ Image juce_createImageFromCIImage (CIImage* im, int w, int h)
 CGImageRef juce_createCoreGraphicsImage (const Image& juceImage, CGColorSpaceRef colourSpace,\r
                                          const bool mustOutliveSource)\r
 {\r
-    return CoreGraphicsImage::createImage (juceImage, colourSpace, mustOutliveSource);\r
+    return CoreGraphicsPixelData::createImage (juceImage, colourSpace, mustOutliveSource);\r
 }\r
 \r
 CGContextRef juce_getImageContext (const Image& image)\r
 {\r
-    if (auto cgi = dynamic_cast<CoreGraphicsImage*> (image.getPixelData()))\r
+    if (auto cgi = dynamic_cast<CoreGraphicsPixelData*> (image.getPixelData()))\r
         return cgi->context;\r
 \r
     jassertfalse;\r
index 6ae7035d04167a26f8fb7deacc46e6644245d601..12b4e25dd96e71594241b6e3d20f9c328f4a56a5 100644 (file)
@@ -276,10 +276,10 @@ namespace CoreTextTypeLayout
 \r
         CTParagraphStyleSetting settings[] =\r
         {\r
-            { kCTParagraphStyleSpecifierAlignment,              sizeof (CTTextAlignment), &ctTextAlignment },\r
-            { kCTParagraphStyleSpecifierLineBreakMode,          sizeof (CTLineBreakMode), &ctLineBreakMode },\r
+            { kCTParagraphStyleSpecifierAlignment,              sizeof (CTTextAlignment),    &ctTextAlignment },\r
+            { kCTParagraphStyleSpecifierLineBreakMode,          sizeof (CTLineBreakMode),    &ctLineBreakMode },\r
             { kCTParagraphStyleSpecifierBaseWritingDirection,   sizeof (CTWritingDirection), &ctWritingDirection},\r
-            { kCTParagraphStyleSpecifierLineSpacingAdjustment,  sizeof (CGFloat),         &ctLineSpacing }\r
+            { kCTParagraphStyleSpecifierLineSpacingAdjustment,  sizeof (CGFloat),            &ctLineSpacing }\r
         };\r
 \r
         auto ctParagraphStyleRef = CTParagraphStyleCreate (settings, (size_t) numElementsInArray (settings));\r
@@ -292,22 +292,35 @@ namespace CoreTextTypeLayout
         return attribString;\r
     }\r
 \r
-    static CTFrameRef createCTFrame (const AttributedString& text, CGRect bounds)\r
+    static CTFramesetterRef createCTFramesetter (const AttributedString& text)\r
     {\r
         auto attribString = createCFAttributedString (text);\r
         auto framesetter = CTFramesetterCreateWithAttributedString (attribString);\r
         CFRelease (attribString);\r
 \r
+        return framesetter;\r
+    }\r
+\r
+    static CTFrameRef createCTFrame (CTFramesetterRef framesetter, CGRect bounds)\r
+    {\r
         auto path = CGPathCreateMutable();\r
         CGPathAddRect (path, nullptr, bounds);\r
 \r
         auto frame = CTFramesetterCreateFrame (framesetter, CFRangeMake (0, 0), path, nullptr);\r
-        CFRelease (framesetter);\r
         CGPathRelease (path);\r
 \r
         return frame;\r
     }\r
 \r
+    static CTFrameRef createCTFrame (const AttributedString& text, CGRect bounds)\r
+    {\r
+        auto framesetter = createCTFramesetter (text);\r
+        auto frame = createCTFrame (framesetter, bounds);\r
+        CFRelease (framesetter);\r
+\r
+        return frame;\r
+    }\r
+\r
     static Range<float> getLineVerticalRange (CTFrameRef frame, CFArrayRef lines, int lineIndex)\r
     {\r
         LineInfo info (frame, (CTLineRef) CFArrayGetValueAtIndex (lines, lineIndex), lineIndex);\r
@@ -335,39 +348,58 @@ namespace CoreTextTypeLayout
     static void drawToCGContext (const AttributedString& text, const Rectangle<float>& area,\r
                                  const CGContextRef& context, float flipHeight)\r
     {\r
-        Rectangle<float> ctFrameArea;\r
-        auto verticalJustification = text.getJustification().getOnlyVerticalFlags();\r
+        auto framesetter = createCTFramesetter (text);\r
 \r
         // Ugly hack to fix a bug in OS X Sierra where the CTFrame needs to be slightly\r
         // larger than the font height - otherwise the CTFrame will be invalid\r
-        if (verticalJustification == Justification::verticallyCentred)\r
-            ctFrameArea = area.withSizeKeepingCentre (area.getWidth(), area.getHeight() * 1.1f);\r
-        else if (verticalJustification == Justification::bottom)\r
-            ctFrameArea = area.withTop (area.getY() - (area.getHeight() * 0.1f));\r
-        else\r
-            ctFrameArea = area.withHeight (area.getHeight() * 1.1f);\r
 \r
-        auto frame = createCTFrame (text, CGRectMake ((CGFloat) ctFrameArea.getX(), flipHeight - (CGFloat) ctFrameArea.getBottom(),\r
-                                                      (CGFloat) ctFrameArea.getWidth(), (CGFloat) ctFrameArea.getHeight()));\r
+        CFRange fitrange;\r
+        auto suggestedSingleLineFrameSize =\r
+            CTFramesetterSuggestFrameSizeWithConstraints (framesetter, CFRangeMake (0, 0), nullptr,\r
+                                                          CGSizeMake (CGFLOAT_MAX, CGFLOAT_MAX), &fitrange);\r
+        auto minCTFrameHeight = (float) suggestedSingleLineFrameSize.height;\r
+\r
+        auto verticalJustification = text.getJustification().getOnlyVerticalFlags();\r
+\r
+        auto ctFrameArea = [area, minCTFrameHeight, verticalJustification]\r
+        {\r
+            if (minCTFrameHeight < area.getHeight())\r
+                return area;\r
+\r
+            if (verticalJustification == Justification::verticallyCentred)\r
+                return area.withSizeKeepingCentre (area.getWidth(), minCTFrameHeight);\r
+\r
+            auto frameArea = area.withHeight (minCTFrameHeight);\r
+\r
+            if (verticalJustification == Justification::bottom)\r
+                return frameArea.withBottomY (area.getBottom());\r
+\r
+            return frameArea;\r
+        }();\r
+\r
+        auto frame = createCTFrame (framesetter, CGRectMake ((CGFloat) ctFrameArea.getX(), flipHeight - (CGFloat) ctFrameArea.getBottom(),\r
+                                                             (CGFloat) ctFrameArea.getWidth(), (CGFloat) ctFrameArea.getHeight()));\r
+        CFRelease (framesetter);\r
+\r
+        auto textMatrix = CGContextGetTextMatrix (context);\r
+        CGContextSaveGState (context);\r
 \r
         if (verticalJustification == Justification::verticallyCentred\r
-             || verticalJustification == Justification::bottom)\r
+         || verticalJustification == Justification::bottom)\r
         {\r
             auto adjust = ctFrameArea.getHeight() - findCTFrameHeight (frame);\r
 \r
             if (verticalJustification == Justification::verticallyCentred)\r
                 adjust *= 0.5f;\r
 \r
-            CGContextSaveGState (context);\r
             CGContextTranslateCTM (context, 0, -adjust);\r
-            CTFrameDraw (frame, context);\r
-            CGContextRestoreGState (context);\r
-        }\r
-        else\r
-        {\r
-            CTFrameDraw (frame, context);\r
         }\r
 \r
+        CTFrameDraw (frame, context);\r
+\r
+        CGContextRestoreGState (context);\r
+        CGContextSetTextMatrix (context, textMatrix);\r
+\r
         CFRelease (frame);\r
     }\r
 \r
index 75a58b90d8b885456a6c18d8f71eaa7c7d731809..3913247b69a21f848e8c2443972963ffb9640529 100644 (file)
@@ -30,12 +30,12 @@ namespace juce
 template <typename Type>\r
 D2D1_RECT_F rectangleToRectF (const Rectangle<Type>& r)\r
 {\r
-    return D2D1::RectF ((float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom());\r
+    return { (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom() };\r
 }\r
 \r
 static D2D1_COLOR_F colourToD2D (Colour c)\r
 {\r
-    return D2D1::ColorF::ColorF (c.getFloatRed(), c.getFloatGreen(), c.getFloatBlue(), c.getFloatAlpha());\r
+    return { c.getFloatRed(), c.getFloatGreen(), c.getFloatBlue(), c.getFloatAlpha() };\r
 }\r
 \r
 static void pathToGeometrySink (const Path& path, ID2D1GeometrySink* sink, const AffineTransform& transform)\r
@@ -48,39 +48,26 @@ static void pathToGeometrySink (const Path& path, ID2D1GeometrySink* sink, const
         {\r
         case Path::Iterator::cubicTo:\r
         {\r
-            D2D1_BEZIER_SEGMENT seg;\r
+            transform.transformPoint (it.x1, it.y1);\r
+            transform.transformPoint (it.x2, it.y2);\r
+            transform.transformPoint (it.x3, it.y3);\r
 \r
-            transform.transformPoint   (it.x1, it.y1);\r
-            seg.point1 = D2D1::Point2F (it.x1, it.y1);\r
-\r
-            transform.transformPoint   (it.x2, it.y2);\r
-            seg.point2 = D2D1::Point2F (it.x2, it.y2);\r
-\r
-            transform.transformPoint   (it.x3, it.y3);\r
-            seg.point3 = D2D1::Point2F (it.x3, it.y3);\r
-\r
-            sink->AddBezier (seg);\r
+            sink->AddBezier ({ { it.x1, it.y1 }, { it.x2, it.y2 }, { it.x3, it.y3 } });\r
             break;\r
         }\r
 \r
         case Path::Iterator::lineTo:\r
         {\r
-            transform.transformPoint     (it.x1, it.y1);\r
-            sink->AddLine (D2D1::Point2F (it.x1, it.y1));\r
+            transform.transformPoint (it.x1, it.y1);\r
+            sink->AddLine ({ it.x1, it.y1 });\r
             break;\r
         }\r
 \r
         case Path::Iterator::quadraticTo:\r
         {\r
-            D2D1_QUADRATIC_BEZIER_SEGMENT seg;\r
-\r
-            transform.transformPoint   (it.x1, it.y1);\r
-            seg.point1 = D2D1::Point2F (it.x1, it.y1);\r
-\r
-            transform.transformPoint   (it.x2, it.y2);\r
-            seg.point2 = D2D1::Point2F (it.x2, it.y2);\r
-\r
-            sink->AddQuadraticBezier (seg);\r
+            transform.transformPoint (it.x1, it.y1);\r
+            transform.transformPoint (it.x2, it.y2);\r
+            sink->AddQuadraticBezier ({ { it.x1, it.y1 }, { it.x2, it.y2 } });\r
             break;\r
         }\r
 \r
@@ -92,8 +79,8 @@ static void pathToGeometrySink (const Path& path, ID2D1GeometrySink* sink, const
 \r
         case Path::Iterator::startNewSubPath:\r
         {\r
-            transform.transformPoint         (it.x1, it.y1);\r
-            sink->BeginFigure (D2D1::Point2F (it.x1, it.y1), D2D1_FIGURE_BEGIN_FILLED);\r
+            transform.transformPoint (it.x1, it.y1);\r
+            sink->BeginFigure ({ it.x1, it.y1 }, D2D1_FIGURE_BEGIN_FILLED);\r
             break;\r
         }\r
         }\r
@@ -102,20 +89,13 @@ static void pathToGeometrySink (const Path& path, ID2D1GeometrySink* sink, const
 \r
 static D2D1::Matrix3x2F transformToMatrix (const AffineTransform& transform)\r
 {\r
-    D2D1::Matrix3x2F matrix;\r
-    matrix._11 = transform.mat00;\r
-    matrix._12 = transform.mat10;\r
-    matrix._21 = transform.mat01;\r
-    matrix._22 = transform.mat11;\r
-    matrix._31 = transform.mat02;\r
-    matrix._32 = transform.mat12;\r
-    return matrix;\r
+    return { transform.mat00, transform.mat10, transform.mat01, transform.mat11, transform.mat02, transform.mat12 };\r
 }\r
 \r
 static D2D1_POINT_2F pointTransformed (int x, int y, const AffineTransform& transform)\r
 {\r
     transform.transformPoint (x, y);\r
-    return D2D1::Point2F ((FLOAT) x, (FLOAT) y);\r
+    return { (FLOAT) x, (FLOAT) y };\r
 }\r
 \r
 static void rectToGeometrySink (const Rectangle<int>& rect, ID2D1GeometrySink* sink, const AffineTransform& transform)\r
@@ -136,7 +116,7 @@ struct Direct2DLowLevelGraphicsContext::Pimpl
         factories->d2dFactory->CreatePathGeometry (&p);\r
 \r
         ComSmartPtr<ID2D1GeometrySink> sink;\r
-        HRESULT hr = p->Open (sink.resetAndGetPointerAddress()); // xxx handle error\r
+        auto hr = p->Open (sink.resetAndGetPointerAddress()); // xxx handle error\r
         sink->SetFillMode (D2D1_FILL_MODE_WINDING);\r
 \r
         for (int i = clipRegion.getNumRectangles(); --i >= 0;)\r
@@ -152,7 +132,7 @@ struct Direct2DLowLevelGraphicsContext::Pimpl
         factories->d2dFactory->CreatePathGeometry (&p);\r
 \r
         ComSmartPtr<ID2D1GeometrySink> sink;\r
-        HRESULT hr = p->Open (sink.resetAndGetPointerAddress());\r
+        auto hr = p->Open (sink.resetAndGetPointerAddress());\r
         sink->SetFillMode (D2D1_FILL_MODE_WINDING); // xxx need to check Path::isUsingNonZeroWinding()\r
 \r
         pathToGeometrySink (path, sink, transform);\r
@@ -188,7 +168,7 @@ public:
         }\r
         else\r
         {\r
-            const D2D1_SIZE_U size (owner.pimpl->renderingTarget->GetPixelSize());\r
+            const auto size = owner.pimpl->renderingTarget->GetPixelSize();\r
             clipRect.setSize (size.width, size.height);\r
             setFill (FillType (Colours::black));\r
         }\r
@@ -214,7 +194,7 @@ public:
     void clipToRectangle (const Rectangle<int>& r)\r
     {\r
         clearClip();\r
-        clipRect = r.toFloat().transformed (transform).getSmallestIntegerContainer();\r
+        clipRect = r.toFloat().transformedBy (transform).getSmallestIntegerContainer();\r
         shouldClipRect = true;\r
         pushClips();\r
     }\r
@@ -284,24 +264,17 @@ public:
         if (bitmapMaskLayer == nullptr)\r
             owner.pimpl->renderingTarget->CreateLayer (bitmapMaskLayer.resetAndGetPointerAddress());\r
 \r
-        D2D1_BRUSH_PROPERTIES brushProps;\r
-        brushProps.opacity = 1;\r
-        brushProps.transform = transformToMatrix (clipTransform);\r
-\r
-        D2D1_BITMAP_BRUSH_PROPERTIES bmProps = D2D1::BitmapBrushProperties (D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP);\r
-\r
-        D2D1_SIZE_U size;\r
-        size.width  = clipImage.getWidth();\r
-        size.height = clipImage.getHeight();\r
-\r
-        D2D1_BITMAP_PROPERTIES bp = D2D1::BitmapProperties();\r
+        D2D1_BRUSH_PROPERTIES brushProps = { 1, transformToMatrix (clipTransform) };\r
+        auto bmProps = D2D1::BitmapBrushProperties (D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP);\r
+        D2D1_SIZE_U size = { (UINT32) clipImage.getWidth(), (UINT32) clipImage.getHeight() };\r
+        auto bp = D2D1::BitmapProperties();\r
 \r
         maskImage = clipImage.convertedToFormat (Image::ARGB);\r
         Image::BitmapData bd (maskImage, Image::BitmapData::readOnly); // xxx should be maskImage?\r
         bp.pixelFormat = owner.pimpl->renderingTarget->GetPixelFormat();\r
         bp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;\r
 \r
-        HRESULT hr = owner.pimpl->renderingTarget->CreateBitmap (size, bd.data, bd.lineStride, bp, maskBitmap.resetAndGetPointerAddress());\r
+        auto hr = owner.pimpl->renderingTarget->CreateBitmap (size, bd.data, bd.lineStride, bp, maskBitmap.resetAndGetPointerAddress());\r
         hr = owner.pimpl->renderingTarget->CreateBitmapBrush (maskBitmap, bmProps, brushProps, bitmapMaskBrush.resetAndGetPointerAddress());\r
 \r
         imageMaskLayerParams = D2D1::LayerParameters();\r
@@ -348,7 +321,7 @@ public:
 \r
         if (shouldClipRectList && !clipsRectList)\r
         {\r
-            D2D1_LAYER_PARAMETERS layerParams = D2D1::LayerParameters();\r
+            auto layerParams = D2D1::LayerParameters();\r
             rectListGeometry->GetBounds (D2D1::IdentityMatrix(), &layerParams.contentBounds);\r
             layerParams.geometricMask = rectListGeometry;\r
             owner.pimpl->renderingTarget->PushLayer (layerParams, rectListLayer);\r
@@ -357,7 +330,7 @@ public:
 \r
         if (shouldClipComplex && !clipsComplex)\r
         {\r
-            D2D1_LAYER_PARAMETERS layerParams = D2D1::LayerParameters();\r
+            auto layerParams = D2D1::LayerParameters();\r
             complexClipGeometry->GetBounds (D2D1::IdentityMatrix(), &layerParams.contentBounds);\r
             layerParams.geometricMask = complexClipGeometry;\r
             owner.pimpl->renderingTarget->PushLayer (layerParams, complexClipLayer);\r
@@ -398,7 +371,7 @@ public:
     {\r
         if (currentFontFace == nullptr)\r
         {\r
-            WindowsDirectWriteTypeface* typeface = dynamic_cast<WindowsDirectWriteTypeface*> (font.getTypeface());\r
+            auto* typeface = dynamic_cast<WindowsDirectWriteTypeface*> (font.getTypeface());\r
             currentFontFace = typeface->getIDWriteFontFace();\r
             fontHeightToEmSizeFactor = typeface->getUnitsToHeightScaleFactor();\r
         }\r
@@ -428,32 +401,26 @@ public:
         {\r
             if (fillType.isColour())\r
             {\r
-                D2D1_COLOR_F colour = colourToD2D (fillType.colour);\r
+                auto colour = colourToD2D (fillType.colour);\r
                 owner.pimpl->colourBrush->SetColor (colour);\r
                 currentBrush = owner.pimpl->colourBrush;\r
             }\r
             else if (fillType.isTiledImage())\r
             {\r
-                D2D1_BRUSH_PROPERTIES brushProps;\r
-                brushProps.opacity = fillType.getOpacity();\r
-                brushProps.transform = transformToMatrix (fillType.transform);\r
-\r
-                D2D1_BITMAP_BRUSH_PROPERTIES bmProps = D2D1::BitmapBrushProperties (D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP);\r
+                D2D1_BRUSH_PROPERTIES brushProps = { fillType.getOpacity(), transformToMatrix (fillType.transform) };\r
+                auto bmProps = D2D1::BitmapBrushProperties (D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP);\r
 \r
                 image = fillType.image;\r
 \r
-                D2D1_SIZE_U size;\r
-                size.width = image.getWidth();\r
-                size.height = image.getHeight();\r
-\r
-                D2D1_BITMAP_PROPERTIES bp = D2D1::BitmapProperties();\r
+                D2D1_SIZE_U size = { (UINT32) image.getWidth(), (UINT32) image.getHeight() };\r
+                auto bp = D2D1::BitmapProperties();\r
 \r
                 this->image = image.convertedToFormat (Image::ARGB);\r
                 Image::BitmapData bd (this->image, Image::BitmapData::readOnly);\r
                 bp.pixelFormat = owner.pimpl->renderingTarget->GetPixelFormat();\r
                 bp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;\r
 \r
-                HRESULT hr = owner.pimpl->renderingTarget->CreateBitmap (size, bd.data, bd.lineStride, bp, bitmap.resetAndGetPointerAddress());\r
+                auto hr = owner.pimpl->renderingTarget->CreateBitmap (size, bd.data, bd.lineStride, bp, bitmap.resetAndGetPointerAddress());\r
                 hr = owner.pimpl->renderingTarget->CreateBitmapBrush (bitmap, bmProps, brushProps, bitmapBrush.resetAndGetPointerAddress());\r
 \r
                 currentBrush = bitmapBrush;\r
@@ -462,9 +429,7 @@ public:
             {\r
                 gradientStops = nullptr;\r
 \r
-                D2D1_BRUSH_PROPERTIES brushProps;\r
-                brushProps.opacity = fillType.getOpacity();\r
-                brushProps.transform = transformToMatrix (fillType.transform.followedBy (transform));\r
+                D2D1_BRUSH_PROPERTIES brushProps = { fillType.getOpacity(), transformToMatrix (fillType.transform.followedBy (transform)) };\r
 \r
                 const int numColors = fillType.gradient->getNumColours();\r
 \r
@@ -482,28 +447,21 @@ public:
                 {\r
                     radialGradient = nullptr;\r
 \r
-                    const Point<float> p1 = fillType.gradient->point1;\r
-                    const Point<float> p2 = fillType.gradient->point2;\r
-                    float r = p1.getDistanceFrom(p2);\r
-\r
-                    D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES props =\r
-                        D2D1::RadialGradientBrushProperties(D2D1::Point2F(p1.x, p1.y),\r
-                            D2D1::Point2F(0, 0),\r
-                            r, r);\r
+                    const auto p1 = fillType.gradient->point1;\r
+                    const auto p2 = fillType.gradient->point2;\r
+                    const auto r = p1.getDistanceFrom(p2);\r
+                    const auto props = D2D1::RadialGradientBrushProperties ({ p1.x, p1.y }, {}, r, r);\r
 \r
-                    owner.pimpl->renderingTarget->CreateRadialGradientBrush(props, brushProps, gradientStops, radialGradient.resetAndGetPointerAddress());\r
+                    owner.pimpl->renderingTarget->CreateRadialGradientBrush (props, brushProps, gradientStops, radialGradient.resetAndGetPointerAddress());\r
                     currentBrush = radialGradient;\r
                 }\r
                 else\r
                 {\r
                     linearGradient = 0;\r
 \r
-                    const Point<float> p1 = fillType.gradient->point1;\r
-                    const Point<float> p2 = fillType.gradient->point2;\r
-\r
-                    D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES props =\r
-                        D2D1::LinearGradientBrushProperties(D2D1::Point2F(p1.x, p1.y),\r
-                            D2D1::Point2F(p2.x, p2.y));\r
+                    const auto p1 = fillType.gradient->point1;\r
+                    const auto p2 = fillType.gradient->point2;\r
+                    const auto props = D2D1::LinearGradientBrushProperties ({ p1.x, p1.y }, { p2.x, p2.y });\r
 \r
                     owner.pimpl->renderingTarget->CreateLinearGradientBrush (props, brushProps, gradientStops, linearGradient.resetAndGetPointerAddress());\r
 \r
@@ -518,7 +476,7 @@ public:
     AffineTransform transform;\r
 \r
     Font font;\r
-    float fontHeightToEmSizeFactor = 1.0;\r
+    float fontHeightToEmSizeFactor = 1.0f;\r
 \r
     IDWriteFontFace* currentFontFace = nullptr;\r
     ComSmartPtr<IDWriteFontFace> localFontFace;\r
@@ -568,12 +526,9 @@ Direct2DLowLevelGraphicsContext::Direct2DLowLevelGraphicsContext (HWND hwnd_)
     D2D1_SIZE_U size = { (UINT32) (windowRect.right - windowRect.left), (UINT32) (windowRect.bottom - windowRect.top) };\r
     bounds.setSize (size.width, size.height);\r
 \r
-    D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties();\r
-    D2D1_HWND_RENDER_TARGET_PROPERTIES propsHwnd = D2D1::HwndRenderTargetProperties (hwnd, size);\r
-\r
     if (pimpl->factories->d2dFactory != nullptr)\r
     {\r
-        HRESULT hr = pimpl->factories->d2dFactory->CreateHwndRenderTarget (props, propsHwnd, pimpl->renderingTarget.resetAndGetPointerAddress());\r
+        auto hr = pimpl->factories->d2dFactory->CreateHwndRenderTarget ({}, { hwnd, size }, pimpl->renderingTarget.resetAndGetPointerAddress());\r
         jassert (SUCCEEDED (hr)); ignoreUnused (hr);\r
         hr = pimpl->renderingTarget->CreateSolidColorBrush (D2D1::ColorF::ColorF (0.0f, 0.0f, 0.0f, 1.0f), pimpl->colourBrush.resetAndGetPointerAddress());\r
     }\r
@@ -608,7 +563,7 @@ void Direct2DLowLevelGraphicsContext::start()
 void Direct2DLowLevelGraphicsContext::end()\r
 {\r
     states.clear();\r
-    currentState = 0;\r
+    currentState = nullptr;\r
     pimpl->renderingTarget->EndDraw();\r
     pimpl->renderingTarget->CheckWindowState();\r
 }\r
@@ -657,13 +612,13 @@ void Direct2DLowLevelGraphicsContext::clipToImageAlpha (const Image& sourceImage
 \r
 bool Direct2DLowLevelGraphicsContext::clipRegionIntersects (const Rectangle<int>& r)\r
 {\r
-    return currentState->clipRect.intersects (r.toFloat().transformed (currentState->transform).getSmallestIntegerContainer());\r
+    return currentState->clipRect.intersects (r.toFloat().transformedBy (currentState->transform).getSmallestIntegerContainer());\r
 }\r
 \r
 Rectangle<int> Direct2DLowLevelGraphicsContext::getClipBounds() const\r
 {\r
     // xxx could this take into account complex clip regions?\r
-    return currentState->clipRect.toFloat().transformed (currentState->transform.inverted()).getSmallestIntegerContainer();\r
+    return currentState->clipRect.toFloat().transformedBy (currentState->transform.inverted()).getSmallestIntegerContainer();\r
 }\r
 \r
 bool Direct2DLowLevelGraphicsContext::isClipEmpty() const\r
@@ -679,7 +634,7 @@ void Direct2DLowLevelGraphicsContext::saveState()
 \r
 void Direct2DLowLevelGraphicsContext::restoreState()\r
 {\r
-        jassert (states.size() > 1); //you should never pop the last state!\r
+    jassert (states.size() > 1); //you should never pop the last state!\r
     states.removeLast (1);\r
     currentState = states.getLast();\r
 }\r
@@ -740,11 +695,8 @@ void Direct2DLowLevelGraphicsContext::drawImage (const Image& image, const Affin
 {\r
     pimpl->renderingTarget->SetTransform (transformToMatrix (transform.followedBy (currentState->transform)));\r
 \r
-    D2D1_SIZE_U size;\r
-    size.width = image.getWidth();\r
-    size.height = image.getHeight();\r
-\r
-    D2D1_BITMAP_PROPERTIES bp = D2D1::BitmapProperties();\r
+    D2D1_SIZE_U size = { (UINT32) image.getWidth(), (UINT32) image.getHeight() };\r
+    auto bp = D2D1::BitmapProperties();\r
 \r
     Image img (image.convertedToFormat (Image::ARGB));\r
     Image::BitmapData bd (img, Image::BitmapData::readOnly);\r
@@ -788,17 +740,15 @@ void Direct2DLowLevelGraphicsContext::drawGlyph (int glyphNumber, const AffineTr
     currentState->createBrush();\r
     currentState->createFont();\r
 \r
-    float hScale = currentState->font.getHorizontalScale();\r
+    auto hScale = currentState->font.getHorizontalScale();\r
 \r
     pimpl->renderingTarget->SetTransform (transformToMatrix (AffineTransform::scale (hScale, 1.0f)\r
                                                                              .followedBy (transform)\r
                                                                              .followedBy (currentState->transform)));\r
 \r
-    const UINT16 glyphIndices = (UINT16) glyphNumber;\r
-    const FLOAT glyphAdvances = 0;\r
-    DWRITE_GLYPH_OFFSET offset;\r
-    offset.advanceOffset = 0;\r
-    offset.ascenderOffset = 0;\r
+    const auto glyphIndices = (UINT16) glyphNumber;\r
+    const auto glyphAdvances = 0.0f;\r
+    DWRITE_GLYPH_OFFSET offset = { 0.0f, 0.0f };\r
 \r
     DWRITE_GLYPH_RUN glyphRun;\r
     glyphRun.fontFace = currentState->currentFontFace;\r
@@ -810,7 +760,7 @@ void Direct2DLowLevelGraphicsContext::drawGlyph (int glyphNumber, const AffineTr
     glyphRun.isSideways = FALSE;\r
     glyphRun.bidiLevel = 0;\r
 \r
-    pimpl->renderingTarget->DrawGlyphRun (D2D1::Point2F (0, 0), &glyphRun, currentState->currentBrush);\r
+    pimpl->renderingTarget->DrawGlyphRun ({}, &glyphRun, currentState->currentBrush);\r
     pimpl->renderingTarget->SetTransform (D2D1::IdentityMatrix());\r
 }\r
 \r
index ea2c67169e08363b7b1340e10af13bb73468bca9..6e8facbcb0da04909de58a9fb8272a94649d6b9d 100644 (file)
@@ -218,6 +218,7 @@ namespace DirectWriteTypeLayout
 \r
         switch (text.getJustification().getOnlyHorizontalFlags())\r
         {\r
+            case 0:\r
             case Justification::left:                   break;\r
             case Justification::right:                  alignment = DWRITE_TEXT_ALIGNMENT_TRAILING; break;\r
             case Justification::horizontallyCentred:    alignment = DWRITE_TEXT_ALIGNMENT_CENTER; break;\r
@@ -241,6 +242,7 @@ namespace DirectWriteTypeLayout
 \r
             switch (text.getJustification().getOnlyHorizontalFlags())\r
             {\r
+                case 0:\r
                 case Justification::left:      alignment = DWRITE_TEXT_ALIGNMENT_TRAILING; break;\r
                 case Justification::right:     alignment = DWRITE_TEXT_ALIGNMENT_LEADING;  break;\r
                 default: break;\r
@@ -301,7 +303,7 @@ namespace DirectWriteTypeLayout
                                                               col.getFloatAlpha()),\r
                                                 d2dBrush.resetAndGetPointerAddress());\r
 \r
-            // We need to call SetDrawingEffect with a legimate brush to get DirectWrite to break text based on colours\r
+            // We need to call SetDrawingEffect with a legitimate brush to get DirectWrite to break text based on colours\r
             textLayout.SetDrawingEffect (d2dBrush, range);\r
         }\r
     }\r
index b5811cbc6cf55312bc61cdfd871f0570c7caf5ff..98ca4be7621a2f487ff99bd649b285d942cb299a 100644 (file)
@@ -54,7 +54,7 @@ public:
         @param buttonName           the text to put in the button (the component's name is also\r
                                     initially set to this string, but these can be changed later\r
                                     using the setName() and setButtonText() methods)\r
-        @param toolTip              an optional string to use as a toolip\r
+        @param toolTip              an optional string to use as a tooltip\r
     */\r
     TextButton (const String& buttonName, const String& toolTip);\r
 \r
index 1a2106a4c3f041cdd516c0c31f6fe577fb4d455e..d7734de4d2e546616a5e849c989ff3a909db316d 100644 (file)
@@ -1845,6 +1845,9 @@ void Component::internalRepaintUnchecked (Rectangle<int> area, bool isEntireComp
                                      : cachedImage->invalidate (area)))\r
                 return;\r
 \r
+        if (area.isEmpty())\r
+            return;\r
+\r
         if (flags.hasHeavyweightPeerFlag)\r
         {\r
             if (auto* peer = getPeer())\r
@@ -1899,12 +1902,10 @@ void Component::paintComponentAndChildren (Graphics& g)
     }\r
     else\r
     {\r
-        g.saveState();\r
+        Graphics::ScopedSaveState ss (g);\r
 \r
         if (! (ComponentHelpers::clipObscuredRegions (*this, g, clipBounds, {}) && g.isClipEmpty()))\r
             paint (g);\r
-\r
-        g.restoreState();\r
     }\r
 \r
     for (int i = 0; i < childComponentList.size(); ++i)\r
@@ -1915,17 +1916,16 @@ void Component::paintComponentAndChildren (Graphics& g)
         {\r
             if (child.affineTransform != nullptr)\r
             {\r
-                g.saveState();\r
+                Graphics::ScopedSaveState ss (g);\r
+\r
                 g.addTransform (*child.affineTransform);\r
 \r
                 if ((child.flags.dontClipGraphicsFlag && ! g.isClipEmpty()) || g.reduceClipRegion (child.getBounds()))\r
                     child.paintWithinParentContext (g);\r
-\r
-                g.restoreState();\r
             }\r
             else if (clipBounds.intersects (child.getBounds()))\r
             {\r
-                g.saveState();\r
+                Graphics::ScopedSaveState ss (g);\r
 \r
                 if (child.flags.dontClipGraphicsFlag)\r
                 {\r
@@ -1949,15 +1949,12 @@ void Component::paintComponentAndChildren (Graphics& g)
                     if (nothingClipped || ! g.isClipEmpty())\r
                         child.paintWithinParentContext (g);\r
                 }\r
-\r
-                g.restoreState();\r
             }\r
         }\r
     }\r
 \r
-    g.saveState();\r
+    Graphics::ScopedSaveState ss (g);\r
     paintOverChildren (g);\r
-    g.restoreState();\r
 }\r
 \r
 void Component::paintEntireComponent (Graphics& g, bool ignoreAlphaLevel)\r
@@ -1989,10 +1986,10 @@ void Component::paintEntireComponent (Graphics& g, bool ignoreAlphaLevel)
             paintComponentAndChildren (g2);\r
         }\r
 \r
-        g.saveState();\r
+        Graphics::ScopedSaveState ss (g);\r
+\r
         g.addTransform (AffineTransform::scale (1.0f / scale));\r
         effect->applyEffect (effectImage, g, scale, ignoreAlphaLevel ? 1.0f : getAlpha());\r
-        g.restoreState();\r
     }\r
     else if (componentTransparency > 0 && ! ignoreAlphaLevel)\r
     {\r
index 7dc3ed03bd766054170c0d339a95c5a7d3657d4a..72d82cf0ad3fb0dedab191ac756133b12941308f 100644 (file)
@@ -54,7 +54,7 @@ public:
     /** Destructor.\r
 \r
         Note that when a component is deleted, any child components it contains are NOT\r
-        automatically deleted. It's your responsibilty to manage their lifespan - you\r
+        automatically deleted. It's your responsibility to manage their lifespan - you\r
         may want to use helper methods like deleteAllChildren(), or less haphazard\r
         approaches like using std::unique_ptrs or normal object aggregation to manage them.\r
 \r
@@ -364,7 +364,7 @@ public:
         a screen coordinate.\r
 \r
         If you've used setTransform() to apply one or more transforms to components, then the source rectangle\r
-        may not actually be rectanglular when converted to the target space, so in that situation this will return\r
+        may not actually be rectangular when converted to the target space, so in that situation this will return\r
         the smallest rectangle that fully contains the transformed area.\r
     */\r
     Rectangle<int> getLocalArea (const Component* sourceComponent,\r
@@ -383,7 +383,7 @@ public:
     /** Converts a rectangle from this component's coordinate space to a screen coordinate.\r
 \r
         If you've used setTransform() to apply one or more transforms to components, then the source rectangle\r
-        may not actually be rectanglular when converted to the target space, so in that situation this will return\r
+        may not actually be rectangular when converted to the target space, so in that situation this will return\r
         the smallest rectangle that fully contains the transformed area.\r
         @see getLocalPoint, localPointToGlobal\r
     */\r
@@ -1384,7 +1384,7 @@ public:
     virtual void enablementChanged();\r
 \r
     //==============================================================================\r
-    /** Returns the component's current transparancy level.\r
+    /** Returns the component's current transparency level.\r
         See setAlpha() for more details.\r
     */\r
     float getAlpha() const noexcept;\r
index e743b2de6d176912fb702ebaae1cdd2197103631..56ac7dfbb77bc99f538e4906e3ce59496421703a 100644 (file)
@@ -123,7 +123,7 @@ public:
     DrawableComposite* getParent() const;\r
 \r
     /** Sets a the clipping region of this drawable using another drawable.\r
-        The drawbale passed in will be deleted when no longer needed.\r
+        The drawable passed in will be deleted when no longer needed.\r
     */\r
     void setClipPath (std::unique_ptr<Drawable> drawableClipPath);\r
 \r
@@ -178,7 +178,7 @@ public:
     static Path parseSVGPath (const String& svgPath);\r
 \r
     //==============================================================================\r
-    /** Returns the area that this drawble covers.\r
+    /** Returns the area that this drawable covers.\r
         The result is expressed in this drawable's own coordinate space, and does not take\r
         into account any transforms that may be applied to the component.\r
     */\r
index 4f3b7ea574e0b0b4711f98f70351c22b14769e99..d425a8930839bece8b37225eff889fd65dddecf0 100644 (file)
@@ -365,18 +365,19 @@ public:
                 if (parseCoordsOrSkip (d, p1, false))\r
                 {\r
                     String num;\r
+                    bool flagValue = false;\r
 \r
                     if (parseNextNumber (d, num, false))\r
                     {\r
-                        const float angle = degreesToRadians (num.getFloatValue());\r
+                        auto angle = degreesToRadians (num.getFloatValue());\r
 \r
-                        if (parseNextNumber (d, num, false))\r
+                        if (parseNextFlag (d, flagValue))\r
                         {\r
-                            const bool largeArc = num.getIntValue() != 0;\r
+                            auto largeArc = flagValue;\r
 \r
-                            if (parseNextNumber (d, num, false))\r
+                            if (parseNextFlag (d, flagValue))\r
                             {\r
-                                const bool sweep = num.getIntValue() != 0;\r
+                                auto sweep = flagValue;\r
 \r
                                 if (parseCoordsOrSkip (d, p2, false))\r
                                 {\r
@@ -1064,7 +1065,7 @@ private:
         if (xml->hasTagName ("use"))\r
             return useText (xml);\r
 \r
-        if (! xml->hasTagName ("text"))\r
+        if (! xml->hasTagName ("text") && ! xml->hasTagNameIgnoringNamespace ("tspan"))\r
             return nullptr;\r
 \r
         Array<float> xCoords, yCoords, dxCoords, dyCoords;\r
@@ -1501,6 +1502,22 @@ private:
         return true;\r
     }\r
 \r
+    static bool parseNextFlag (String::CharPointerType& text, bool& value)\r
+    {\r
+        while (text.isWhitespace() || *text == ',')\r
+            ++text;\r
+\r
+        if (*text != '0' && *text != '1')\r
+            return false;\r
+\r
+        value = *(text++) != '0';\r
+\r
+        while (text.isWhitespace() || *text == ',')\r
+             ++text;\r
+\r
+        return true;\r
+    }\r
+\r
     //==============================================================================\r
     Colour parseColour (const XmlPath& xml, StringRef attributeName, const Colour defaultColour) const\r
     {\r
index 1398f33c34038c98b67f2f849ed92b443bdf039d..c834593fb01632d8fbc9bc845e9b9b3a1b767977 100644 (file)
@@ -222,7 +222,7 @@ public:
         if the user pressed 'ok' rather than cancelling).\r
 \r
         On mobile platforms, the file browser may return a URL instead of a local file.\r
-        Therefore, om mobile platforms, you should call getURLResult() instead.\r
+        Therefore, on mobile platforms, you should call getURLResult() instead.\r
 \r
         If you're using a multiple-file select, then use the getResults() method instead,\r
         to obtain the list of all files chosen.\r
@@ -235,7 +235,7 @@ public:
         browse method.\r
 \r
         On mobile platforms, the file browser may return a URL instead of a local file.\r
-        Therefore, om mobile platforms, you should call getURLResults() instead.\r
+        Therefore, on mobile platforms, you should call getURLResults() instead.\r
 \r
         This array may be empty if no files were chosen, or can contain multiple entries\r
         if multiple files were chosen.\r
@@ -293,7 +293,7 @@ public:
         Note: On iOS this will only return true if you have iCloud permissions\r
         and code-signing enabled in the Projucer and have added iCloud containers\r
         to your app in Apple's online developer portal. Additionally, the user must\r
-        have installed the iCloud app on their device and used the app at leat once.\r
+        have installed the iCloud app on their device and used the app at least once.\r
     */\r
     static bool isPlatformDialogAvailable();\r
 \r
index 1e25368d6120bd4fa932fea788a52094f9ef9113..d5263daff8ba470c388772b07245ad68a9589e60 100644 (file)
@@ -54,7 +54,7 @@ public:
     /** Called to indicate that the user's currently selected file has changed.\r
 \r
         @param newSelectedFile  the newly selected file or directory, which may be\r
-                                a defualt File() object if none is selected.\r
+                                a default File() object if none is selected.\r
     */\r
     virtual void selectedFileChanged (const File& newSelectedFile) = 0;\r
 \r
index e6c0b74afd0f4251d52b3b3b39c993c5db6758ad..304cf049d4bf9cb9c42c7cdb1e5f6e1634a60a1b 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_gui_basics\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE GUI core classes\r
-  description:      Basic user-interface components and related classes.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
+  ID:                 juce_gui_basics\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE GUI core classes\r
+  description:        Basic user-interface components and related classes.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
 \r
-  dependencies:     juce_graphics juce_data_structures\r
-  OSXFrameworks:    Cocoa Carbon QuartzCore\r
-  iOSFrameworks:    UIKit MobileCoreServices\r
-  linuxPackages:    x11 xinerama xext\r
+  dependencies:       juce_graphics juce_data_structures\r
+  OSXFrameworks:      Cocoa Carbon QuartzCore\r
+  iOSFrameworks:      UIKit MobileCoreServices\r
+  linuxPackages:      x11 xinerama xext\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index ae1707d83a88e11568078eda6be0108c36555582..e5f8a0f6b6abf49d5d79b3fb301d70a8d0101f7e 100644 (file)
@@ -146,7 +146,7 @@ namespace KeyPressHelpers
         return 0;\r
     }\r
 \r
-   #if JUCE_MAC\r
+   #if JUCE_MAC || JUCE_IOS\r
     struct OSXSymbolReplacement\r
     {\r
         const char* text;\r
@@ -241,7 +241,7 @@ String KeyPress::getTextDescription() const
         if (mods.isCtrlDown())      desc << "ctrl + ";\r
         if (mods.isShiftDown())     desc << "shift + ";\r
 \r
-       #if JUCE_MAC\r
+       #if JUCE_MAC || JUCE_IOS\r
         if (mods.isAltDown())       desc << "option + ";\r
         if (mods.isCommandDown())   desc << "command + ";\r
        #else\r
@@ -274,7 +274,7 @@ String KeyPress::getTextDescription() const
 \r
 String KeyPress::getTextDescriptionWithIcons() const\r
 {\r
-   #if JUCE_MAC\r
+   #if JUCE_MAC || JUCE_IOS\r
     auto s = getTextDescription();\r
 \r
     for (int i = 0; i < numElementsInArray (KeyPressHelpers::osxSymbols); ++i)\r
index 387c8d8358ec053d6ea5ef02396144522efee528..d9ed4266315fdf3bae3d866ae5ba58c1c789b7f4 100644 (file)
@@ -53,8 +53,8 @@ public:
     /** Creates a KeyPress for a key and some modifiers.\r
 \r
         e.g.\r
-        CTRL+C would be: KeyPress ('c', ModifierKeys::ctrlModifier)\r
-        SHIFT+Escape would be: KeyPress (KeyPress::escapeKey, ModifierKeys::shiftModifier)\r
+        CTRL+C would be: KeyPress ('c', ModifierKeys::ctrlModifier, 0)\r
+        SHIFT+Escape would be: KeyPress (KeyPress::escapeKey, ModifierKeys::shiftModifier, 0)\r
 \r
         @param keyCode      a code that represents the key - this value must be\r
                             one of special constants listed in this class, or an\r
index ed0fff22cc240907dedcb8ef11cfd77176b2a8c4..ba8c813aab05288655d76eda30a796bba6088be2 100644 (file)
@@ -63,7 +63,7 @@ public:
     /** Checks whether the 'command' key flag is set (or 'ctrl' on Windows/Linux).\r
 \r
         This is a platform-agnostic way of checking for the operating system's\r
-        preferred command-key modifier - so on the Mac it tests for the Apple key, on\r
+        preferred command-key modifier - so on the Mac it tests for the cmd key, on\r
         Windows/Linux, it's actually checking for the CTRL key.\r
     */\r
     inline bool isCommandDown() const noexcept          { return testFlags (commandModifier); }\r
@@ -136,7 +136,7 @@ public:
         /** Middle mouse button flag. */\r
         middleButtonModifier                    = 64,\r
 \r
-       #if JUCE_MAC\r
+       #if JUCE_MAC || JUCE_IOS\r
         /** Command key flag - on windows this is the same as the CTRL key flag. */\r
         commandModifier                         = 8,\r
 \r
index bc58337c62846c242850794d894dd845071abff7..9306a1c88e2df2a8c7fb839a4646f1278e204dd6 100644 (file)
@@ -32,6 +32,11 @@ class ComponentAnimator::AnimationTask
 public:\r
     AnimationTask (Component* c) noexcept  : component (c) {}\r
 \r
+    ~AnimationTask()\r
+    {\r
+        proxy.deleteAndZero();\r
+    }\r
+\r
     void reset (const Rectangle<int>& finalBounds,\r
                 float finalAlpha,\r
                 int millisecondsToSpendMoving,\r
@@ -58,17 +63,17 @@ public:
         midSpeed = invTotalDistance;\r
         endSpeed = jmax (0.0, endSpd * invTotalDistance);\r
 \r
+        proxy.deleteAndZero();\r
+\r
         if (useProxyComponent)\r
-            proxy.reset (new ProxyComponent (*component));\r
-        else\r
-            proxy.reset();\r
+            proxy = new ProxyComponent (*component);\r
 \r
         component->setVisible (! useProxyComponent);\r
     }\r
 \r
     bool useTimeslice (const int elapsed)\r
     {\r
-        if (auto* c = proxy != nullptr ? proxy.get()\r
+        if (auto* c = proxy != nullptr ? proxy.getComponent()\r
                                        : component.get())\r
         {\r
             msElapsed += elapsed;\r
@@ -159,7 +164,8 @@ public:
             else\r
                 jassertfalse; // seem to be trying to animate a component that's not visible..\r
 \r
-            auto scale = (float) Desktop::getInstance().getDisplays().findDisplayForRect (getScreenBounds()).scale;\r
+            auto scale = (float) Desktop::getInstance().getDisplays().findDisplayForRect (getScreenBounds()).scale\r
+                           * Component::getApproximateScaleFactorForComponent (&c);\r
 \r
             image = c.createComponentSnapshot (c.getLocalBounds(), false, scale);\r
 \r
@@ -181,7 +187,7 @@ public:
     };\r
 \r
     WeakReference<Component> component;\r
-    std::unique_ptr<Component> proxy;\r
+    Component::SafePointer<Component> proxy;\r
 \r
     Rectangle<int> destination;\r
     double destAlpha;\r
index 685c79fef922a2228ceaabeb60f57b2c3da17523..30ca8151a398225fcbc65d15297b32b70c747c35 100644 (file)
@@ -255,10 +255,13 @@ public:
 \r
     void mouseDrag (const MouseEvent& e) override\r
     {\r
-        ConcertinaPanel& panel = getPanel();\r
-        panel.setLayout (dragStartSizes.withMovedPanel (panel.holders.indexOf (this),\r
-                                                        mouseDownY + e.getDistanceFromDragStartY(),\r
-                                                        panel.getHeight()), false);\r
+        if (e.mouseWasDraggedSinceMouseDown())\r
+        {\r
+            auto& panel = getPanel();\r
+            panel.setLayout (dragStartSizes.withMovedPanel (panel.holders.indexOf (this),\r
+                                                            mouseDownY + e.getDistanceFromDragStartY(),\r
+                                                            panel.getHeight()), false);\r
+        }\r
     }\r
 \r
     void mouseDoubleClick (const MouseEvent&) override\r
index e674a52d33e39d02efc88060e24278ca545c8283..04a10dbb471ce98b7763674350800540fa2a70fb 100644 (file)
@@ -245,7 +245,7 @@ void SidePanel::componentMovedOrResized (Component& component, bool wasMoved, bo
 \r
 Rectangle<int> SidePanel::calculateBoundsInParent (Component& parentComp) const\r
 {\r
-    auto parentBounds = parentComp.getBounds();\r
+    auto parentBounds = parentComp.getLocalBounds();\r
 \r
     if (isOnLeft)\r
     {\r
index d10006cb8f5a7568e14dc31d32b1c7b488782d63..5dd8c25246707f250748f222581c4eba4559cf1a 100644 (file)
@@ -389,7 +389,7 @@ void Viewport::updateVisibleArea()
         auto oldContentBounds = contentComp->getBounds();\r
         contentHolder.setBounds (contentArea);\r
 \r
-        // If the content has changed its size, that might affect our scrollbars, so go round again and re-caclulate..\r
+        // If the content has changed its size, that might affect our scrollbars, so go round again and re-calculate..\r
         if (oldContentBounds == contentComp->getBounds())\r
             break;\r
     }\r
@@ -408,7 +408,6 @@ void Viewport::updateVisibleArea()
     hbar.setRangeLimits (0.0, contentBounds.getWidth());\r
     hbar.setCurrentRange (visibleOrigin.x, contentArea.getWidth());\r
     hbar.setSingleStepSize (singleStepX);\r
-    hbar.cancelPendingUpdate();\r
 \r
     if (canShowHBar && ! hBarVisible)\r
         visibleOrigin.setX (0);\r
@@ -417,7 +416,6 @@ void Viewport::updateVisibleArea()
     vbar.setRangeLimits (0.0, contentBounds.getHeight());\r
     vbar.setCurrentRange (visibleOrigin.y, contentArea.getHeight());\r
     vbar.setSingleStepSize (singleStepY);\r
-    vbar.cancelPendingUpdate();\r
 \r
     if (canShowVBar && ! vBarVisible)\r
         visibleOrigin.setY (0);\r
index d75790179bce6548d4f576bf666894874c73f98f..553bbe0257a371c22dea2fa5397abc7a1b64af44 100644 (file)
@@ -41,7 +41,7 @@ LookAndFeel::LookAndFeel()
     /* if this fails it means you're trying to create a LookAndFeel object before\r
        the static Colours have been initialised. That ain't gonna work. It probably\r
        means that you're using a static LookAndFeel object and that your compiler has\r
-       decided to intialise it before the Colours class.\r
+       decided to initialise it before the Colours class.\r
     */\r
     jassert (Colours::white == Colour (0xffffffff));\r
 \r
index f1471200046865cb08b6094ec71a8c2bf9879b02..1818f73f99f3fd0b4ac8221c5a37bdc8d93b546d 100644 (file)
@@ -774,15 +774,16 @@ void LookAndFeel_V2::drawScrollbar (Graphics& g,
     g.setGradientFill (ColourGradient (Colour (0x10000000), gx1, gy1,\r
                        Colours::transparentBlack, gx2, gy2, false));\r
 \r
-    g.saveState();\r
+    {\r
+        Graphics::ScopedSaveState ss (g);\r
 \r
-    if (isScrollbarVertical)\r
-        g.reduceClipRegion (x + width / 2, y, width, height);\r
-    else\r
-        g.reduceClipRegion (x, y + height / 2, width, height);\r
+        if (isScrollbarVertical)\r
+            g.reduceClipRegion (x + width / 2, y, width, height);\r
+        else\r
+            g.reduceClipRegion (x, y + height / 2, width, height);\r
 \r
-    g.fillPath (thumbPath);\r
-    g.restoreState();\r
+        g.fillPath (thumbPath);\r
+    }\r
 \r
     g.setColour (Colour (0x4c000000));\r
     g.strokePath (thumbPath, PathStrokeType (0.4f));\r
@@ -1735,7 +1736,8 @@ void LookAndFeel_V2::drawResizableFrame (Graphics& g, int w, int h, const Border
         const Rectangle<int> fullSize (0, 0, w, h);\r
         auto centreArea = border.subtractedFrom (fullSize);\r
 \r
-        g.saveState();\r
+        Graphics::ScopedSaveState ss (g);\r
+\r
         g.excludeClipRegion (centreArea);\r
 \r
         g.setColour (Colour (0x50000000));\r
@@ -1743,8 +1745,6 @@ void LookAndFeel_V2::drawResizableFrame (Graphics& g, int w, int h, const Border
 \r
         g.setColour (Colour (0x19000000));\r
         g.drawRect (centreArea.expanded (1, 1));\r
-\r
-        g.restoreState();\r
     }\r
 }\r
 \r
@@ -2834,7 +2834,7 @@ void LookAndFeel_V2::drawBevel (Graphics& g, const int x, const int y, const int
     if (g.clipRegionIntersects (Rectangle<int> (x, y, width, height)))\r
     {\r
         auto& context = g.getInternalContext();\r
-        context.saveState();\r
+        Graphics::ScopedSaveState ss (g);\r
 \r
         for (int i = bevelThickness; --i >= 0;)\r
         {\r
@@ -2850,8 +2850,6 @@ void LookAndFeel_V2::drawBevel (Graphics& g, const int x, const int y, const int
             context.setFill (bottomRightColour.withMultipliedAlpha (op  * 0.75f));\r
             context.fillRect (Rectangle<int> (x + width - i - 1, y + i + 1, 1, height - i * 2 - 2), false);\r
         }\r
-\r
-        context.restoreState();\r
     }\r
 }\r
 \r
@@ -3015,11 +3013,11 @@ void LookAndFeel_V2::drawGlassLozenge (Graphics& g,
 \r
     if (! (flatOnLeft || flatOnTop || flatOnBottom))\r
     {\r
-        g.saveState();\r
+        Graphics::ScopedSaveState ss (g);\r
+\r
         g.setGradientFill (cg);\r
         g.reduceClipRegion (intX, intY, intEdge, intH);\r
         g.fillPath (outline);\r
-        g.restoreState();\r
     }\r
 \r
     if (! (flatOnRight || flatOnTop || flatOnBottom))\r
@@ -3027,11 +3025,11 @@ void LookAndFeel_V2::drawGlassLozenge (Graphics& g,
         cg.point1.setX (x + width - edgeBlurRadius);\r
         cg.point2.setX (x + width);\r
 \r
-        g.saveState();\r
+        Graphics::ScopedSaveState ss (g);\r
+\r
         g.setGradientFill (cg);\r
         g.reduceClipRegion (intX + intW - intEdge, intY, 2 + intEdge, intH);\r
         g.fillPath (outline);\r
-        g.restoreState();\r
     }\r
 \r
     {\r
index cbd79a66a7c3f982ce80784c7dfcc861438f2e26..3e2731791b510b0013a8839705d90c09c79567b7 100644 (file)
@@ -55,10 +55,7 @@ struct HeaderItemComponent  : public PopupMenu::CustomComponent
         setName (name);\r
     }\r
 \r
-    void paint (Graphics& g) override\r
-    {\r
-        getLookAndFeel().drawPopupMenuSectionHeader (g, getLocalBounds(), getName());\r
-    }\r
+    void paint (Graphics& g) override;\r
 \r
     void getIdealSize (int& idealWidth, int& idealHeight) override\r
     {\r
@@ -97,13 +94,7 @@ struct ItemComponent  : public Component
         addMouseListener (&parent, false);\r
     }\r
 \r
-    ~ItemComponent() override\r
-    {\r
-        if (customComp != nullptr)\r
-            setItem (*customComp, nullptr);\r
-\r
-        removeChildComponent (customComp.get());\r
-    }\r
+    ~ItemComponent() override;\r
 \r
     void getIdealSize (int& idealWidth, int& idealHeight, const int standardItemHeight)\r
     {\r
@@ -273,13 +264,7 @@ struct MenuWindow  : public Component
         getMouseState (Desktop::getInstance().getMainMouseSource()); // forces creation of a mouse source watcher for the main mouse\r
     }\r
 \r
-    ~MenuWindow() override\r
-    {\r
-        getActiveWindows().removeFirstMatchingValue (this);\r
-        Desktop::getInstance().removeGlobalMouseListener (this);\r
-        activeSubMenu.reset();\r
-        items.clear();\r
-    }\r
+    ~MenuWindow() override;\r
 \r
     //==============================================================================\r
     void paint (Graphics& g) override\r
@@ -464,7 +449,7 @@ struct MenuWindow  : public Component
 \r
                 if (componentAttachedTo->reallyContains (mousePos, true))\r
                 {\r
-                    postCommandMessage (PopupMenuSettings::dismissCommandId); // dismiss asynchrounously\r
+                    postCommandMessage (PopupMenuSettings::dismissCommandId); // dismiss asynchronously\r
                     return;\r
                 }\r
             }\r
@@ -610,7 +595,7 @@ struct MenuWindow  : public Component
         if (relativeTo != nullptr)\r
             targetPoint = relativeTo->localPointToGlobal (targetPoint);\r
 \r
-        auto parentArea = Desktop::getInstance().getDisplays().findDisplayForPoint (targetPoint)\r
+        auto parentArea = Desktop::getInstance().getDisplays().findDisplayForPoint (targetPoint * scaleFactor)\r
                               #if JUCE_MAC || JUCE_ANDROID\r
                                .userArea;\r
                               #else\r
@@ -1013,14 +998,7 @@ public:
         startTimerHz (20);\r
     }\r
 \r
-    void handleMouseEvent (const MouseEvent& e)\r
-    {\r
-        if (! window.windowIsStillValid())\r
-            return;\r
-\r
-        startTimerHz (20);\r
-        handleMousePosition (e.getScreenPosition());\r
-    }\r
+    void handleMouseEvent (const MouseEvent& e);\r
 \r
     void timerCallback() override\r
     {\r
@@ -1250,11 +1228,7 @@ struct NormalComponentWrapper : public PopupMenu::CustomComponent
         addAndMakeVisible (comp);\r
     }\r
 \r
-    void getIdealSize (int& idealWidth, int& idealHeight) override\r
-    {\r
-        idealWidth = width;\r
-        idealHeight = height;\r
-    }\r
+    void getIdealSize (int& idealWidth, int& idealHeight) override;\r
 \r
     void resized() override\r
     {\r
@@ -1269,6 +1243,44 @@ struct NormalComponentWrapper : public PopupMenu::CustomComponent
 \r
 };\r
 \r
+// The following implementations are outside of the class definitions to avoid spurious\r
+// warning messages when dynamically loading libraries at runtime on macOS\r
+void PopupMenu::HelperClasses::HeaderItemComponent::paint (Graphics& g)\r
+{\r
+    getLookAndFeel().drawPopupMenuSectionHeader (g, getLocalBounds(), getName());\r
+}\r
+\r
+PopupMenu::HelperClasses::ItemComponent::~ItemComponent()\r
+{\r
+    if (customComp != nullptr)\r
+        setItem (*customComp, nullptr);\r
+\r
+    removeChildComponent (customComp.get());\r
+}\r
+\r
+PopupMenu::HelperClasses::MenuWindow::~MenuWindow()\r
+{\r
+    getActiveWindows().removeFirstMatchingValue (this);\r
+    Desktop::getInstance().removeGlobalMouseListener (this);\r
+    activeSubMenu.reset();\r
+    items.clear();\r
+}\r
+\r
+void PopupMenu::HelperClasses::MouseSourceState::handleMouseEvent (const MouseEvent& e)\r
+{\r
+    if (! window.windowIsStillValid())\r
+        return;\r
+\r
+    startTimerHz (20);\r
+    handleMousePosition (e.getScreenPosition());\r
+}\r
+\r
+void PopupMenu::HelperClasses::NormalComponentWrapper::getIdealSize (int& idealWidth, int& idealHeight)\r
+{\r
+    idealWidth = width;\r
+    idealHeight = height;\r
+}\r
+\r
 //==============================================================================\r
 PopupMenu::PopupMenu()\r
 {\r
@@ -1391,6 +1403,12 @@ PopupMenu::Item& PopupMenu::Item::setCustomComponent (ReferenceCountedObjectPtr<
     return *this;\r
 }\r
 \r
+PopupMenu::Item& PopupMenu::Item::setImage (std::unique_ptr<Drawable> newImage) & noexcept\r
+{\r
+    image = std::move (newImage);\r
+    return *this;\r
+}\r
+\r
 PopupMenu::Item&& PopupMenu::Item::setTicked (bool shouldBeTicked) && noexcept\r
 {\r
     isTicked = shouldBeTicked;\r
@@ -1427,6 +1445,12 @@ PopupMenu::Item&& PopupMenu::Item::setCustomComponent (ReferenceCountedObjectPtr
     return std::move (*this);\r
 }\r
 \r
+PopupMenu::Item&& PopupMenu::Item::setImage (std::unique_ptr<Drawable> newImage) && noexcept\r
+{\r
+    image = std::move (newImage);\r
+    return std::move (*this);\r
+}\r
+\r
 void PopupMenu::addItem (Item newItem)\r
 {\r
     // An ID of 0 is used as a return value to indicate that the user\r
index 95c6661f4d9815dfa5dbe5b83ee1db1bf003bfc5..60bedebfb748f5d7237371d6c305d9e35b99f567 100644 (file)
@@ -192,6 +192,8 @@ public:
         Item& setColour (Colour) & noexcept;\r
         /** Sets the customComponent property (and returns a reference to this item to allow chaining). */\r
         Item& setCustomComponent (ReferenceCountedObjectPtr<CustomComponent> customComponent) & noexcept;\r
+        /** Sets the image property (and returns a reference to this item to allow chaining). */\r
+        Item& setImage (std::unique_ptr<Drawable>) & noexcept;\r
 \r
         /** Sets the isTicked flag (and returns a reference to this item to allow chaining). */\r
         Item&& setTicked (bool shouldBeTicked = true) && noexcept;\r
@@ -205,6 +207,8 @@ public:
         Item&& setColour (Colour) && noexcept;\r
         /** Sets the customComponent property (and returns a reference to this item to allow chaining). */\r
         Item&& setCustomComponent (ReferenceCountedObjectPtr<CustomComponent> customComponent) && noexcept;\r
+        /** Sets the image property (and returns a reference to this item to allow chaining). */\r
+        Item&& setImage (std::unique_ptr<Drawable>) && noexcept;\r
     };\r
 \r
     /** Adds an item to the menu.\r
@@ -395,7 +399,7 @@ public:
 \r
     /** Appends a separator to the menu, to help break it up into sections.\r
         The menu class is smart enough not to display separators at the top or bottom\r
-        of the menu, and it will replace mutliple adjacent separators with a single\r
+        of the menu, and it will replace multiple adjacent separators with a single\r
         one, so your code can be quite free and easy about adding these, and it'll\r
         always look ok.\r
     */\r
index eec0c5b2048037ba00ffefefcd00529b5cc841ac..f8e0cb22b0a996848beb4de8a058160ef9a1c131 100644 (file)
@@ -85,7 +85,7 @@ public:
         @param e                    the current mouse-drag event\r
         @param constrainer          an optional constrainer object that should be used\r
                                     to apply limits to the component's position. Pass\r
-                                    null if you don't want to contrain the movement.\r
+                                    null if you don't want to constrain the movement.\r
         @see startDraggingComponent\r
     */\r
     void dragComponent (Component* componentToDrag,\r
index 185dda53c77f96439b5f8c3a6a1067e66ef38bf1..cff272c08d445b90f3840ee35845cefad75e9ad5 100644 (file)
@@ -482,6 +482,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription,
         }\r
     }\r
 \r
+    dragImageComponent->sourceDetails.localPosition = sourceComponent->getLocalPoint (nullptr, lastMouseDown);\r
     dragImageComponent->updateLocation (false, lastMouseDown);\r
 \r
    #if JUCE_WINDOWS\r
index 92a3d0c8ff1c381e6ecd19872e05672830d6ae7e..8ba892c35e7e1085d48bb7f07217e9849fb4816e 100644 (file)
@@ -76,7 +76,7 @@ public:
         dragged.\r
 \r
         @param dragSourceDetails    contains information about the source of the drag operation.\r
-        @returns                    true if this component wants to receive the other callbacks regarging this\r
+        @returns                    true if this component wants to receive the other callbacks regarding this\r
                                     type of object; if it returns false, no other callbacks will be made.\r
     */\r
     virtual bool isInterestedInDragSource (const SourceDetails& dragSourceDetails) = 0;\r
index 709e1f34137a6df4afe8be01211331fd51957aa7..d3bc5597ad91bfbe6a14f6f9a606ace0aba0f914 100644 (file)
@@ -47,7 +47,7 @@ public:
         inside them!\r
 \r
         @param files        the set of (absolute) pathnames of the files that the user is dragging\r
-        @returns            true if this component wants to receive the other callbacks regarging this\r
+        @returns            true if this component wants to receive the other callbacks regarding this\r
                             type of object; if it returns false, no other callbacks will be made.\r
     */\r
     virtual bool isInterestedInFileDrag (const StringArray& files) = 0;\r
index 2010699bbfd6a12908a27b265849aa02d90bff04..e64c75bc303ea2185cfb8a5abf62a867a18f49d7 100644 (file)
@@ -46,7 +46,7 @@ public:
         ParentCursor = 0,               /**< Indicates that the component's parent's cursor should be used. */\r
 \r
         NoCursor,                       /**< An invisible cursor. */\r
-        NormalCursor,                   /**< The stardard arrow cursor. */\r
+        NormalCursor,                   /**< The standard arrow cursor. */\r
 \r
         WaitCursor,                     /**< The normal hourglass or spinning-beachball 'busy' cursor. */\r
         IBeamCursor,                    /**< A vertical I-beam for positioning within text. */\r
index d47a30c8da45f2fe1327cf91939be6679404006d..2af4a9c3e59aa3b40b91b794b75e57dbb1806fb4 100644 (file)
@@ -417,7 +417,7 @@ struct MouseWheelDetails  final
     /** If true, then the wheel has continuous, un-stepped motion. */\r
     bool isSmooth;\r
 \r
-    /** If true, then this event is part of the intertial momentum phase that follows\r
+    /** If true, then this event is part of the inertial momentum phase that follows\r
         the wheel being released. */\r
     bool isInertial;\r
 };\r
index f10f3d000d2b3b1c36de80eb0c7b5009f22f751c..5fd7b2ca395806ff05e2c9a032c7cbe606093386 100644 (file)
@@ -35,7 +35,7 @@ namespace juce
     Each MouseEvent object contains a reference to the MouseInputSource that generated\r
     it. In an environment with a single mouse for input, all events will come from the\r
     same source, but in a multi-touch system, there may be multiple MouseInputSource\r
-    obects active, each representing a stream of events coming from a particular finger.\r
+    objects active, each representing a stream of events coming from a particular finger.\r
 \r
     Events coming from a single MouseInputSource are always sent in a fixed and predictable\r
     order: a mouseMove will never be called without a mouseEnter having been sent beforehand,\r
index 46d29388473acfa540b3c788bedd20da2b88fe34..b1ffd28dadd6d03d9e32bd6bee62c18f515ebb5a 100644 (file)
@@ -47,7 +47,7 @@ public:
         component, so don't do anything time-consuming in here!\r
 \r
         @param text         the text that the user is dragging\r
-        @returns            true if this component wants to receive the other callbacks regarging this\r
+        @returns            true if this component wants to receive the other callbacks regarding this\r
                             type of object; if it returns false, no other callbacks will be made.\r
     */\r
     virtual bool isInterestedInTextDrag (const String& text) = 0;\r
index b985f3d4ade47f66f952ab5fe6109e64ce45a728..6773956c4472d564b6278422d86fe4045abc6a6e 100644 (file)
@@ -30,82 +30,57 @@ namespace juce
 // This byte-code is generated from native/javacore/app/com/roli/juce/JuceSharingContentProvider.java with min sdk version 16\r
 // See juce_core/native/java/README.txt on how to generate this byte-code.\r
 static const uint8 javaJuceSharingContentProvider[] =\r
-{100,101,120,10,48,51,53,0,66,68,79,209,68,153,2,8,5,37,136,73,129,38,235,114,135,129,180,66,79,170,89,247,100,13,0,0,112,0,0,\r
-0,120,86,52,18,0,0,0,0,0,0,0,0,160,12,0,0,77,0,0,0,112,0,0,0,21,0,0,0,164,1,0,0,18,0,0,0,248,1,0,0,5,0,0,0,208,2,0,0,25,0,0,0,\r
-248,2,0,0,3,0,0,0,192,3,0,0,68,9,0,0,32,4,0,0,226,6,0,0,234,6,0,0,237,6,0,0,243,6,0,0,250,6,0,0,253,6,0,0,30,7,0,0,33,7,0,0,37,\r
-7,0,0,42,7,0,0,50,7,0,0,85,7,0,0,118,7,0,0,161,7,0,0,188,7,0,0,221,7,0,0,240,7,0,0,11,8,0,0,46,8,0,0,105,8,0,0,170,8,0,0,214,\r
-8,0,0,250,8,0,0,26,9,0,0,61,9,0,0,81,9,0,0,101,9,0,0,117,9,0,0,139,9,0,0,142,9,0,0,147,9,0,0,151,9,0,0,157,9,0,0,161,9,0,0,166,\r
-9,0,0,172,9,0,0,179,9,0,0,182,9,0,0,203,9,0,0,216,9,0,0,223,9,0,0,236,9,0,0,7,10,0,0,39,10,0,0,68,10,0,0,91,10,0,0,111,10,0,\r
-0,119,10,0,0,126,10,0,0,151,10,0,0,167,10,0,0,176,10,0,0,182,10,0,0,193,10,0,0,201,10,0,0,207,10,0,0,213,10,0,0,229,10,0,0,235,\r
-10,0,0,241,10,0,0,251,10,0,0,4,11,0,0,19,11,0,0,29,11,0,0,35,11,0,0,47,11,0,0,54,11,0,0,62,11,0,0,73,11,0,0,88,11,0,0,99,11,\r
-0,0,105,11,0,0,113,11,0,0,121,11,0,0,126,11,0,0,131,11,0,0,138,11,0,0,1,0,0,0,4,0,0,0,10,0,0,0,11,0,0,0,12,0,0,0,13,0,0,0,14,\r
-0,0,0,15,0,0,0,16,0,0,0,17,0,0,0,18,0,0,0,19,0,0,0,20,0,0,0,21,0,0,0,22,0,0,0,23,0,0,0,24,0,0,0,25,0,0,0,28,0,0,0,36,0,0,0,37,\r
-0,0,0,3,0,0,0,0,0,0,0,96,6,0,0,2,0,0,0,0,0,0,0,108,6,0,0,8,0,0,0,4,0,0,0,120,6,0,0,9,0,0,0,5,0,0,0,128,6,0,0,8,0,0,0,7,0,0,0,\r
-144,6,0,0,6,0,0,0,9,0,0,0,0,0,0,0,8,0,0,0,9,0,0,0,120,6,0,0,7,0,0,0,17,0,0,0,152,6,0,0,28,0,0,0,18,0,0,0,0,0,0,0,29,0,0,0,18,\r
-0,0,0,160,6,0,0,30,0,0,0,18,0,0,0,168,6,0,0,31,0,0,0,18,0,0,0,176,6,0,0,35,0,0,0,18,0,0,0,188,6,0,0,34,0,0,0,18,0,0,0,200,6,\r
-0,0,33,0,0,0,18,0,0,0,212,6,0,0,32,0,0,0,18,0,0,0,220,6,0,0,36,0,0,0,19,0,0,0,0,0,0,0,8,0,0,0,20,0,0,0,120,6,0,0,10,0,1,0,51,0,\r
-0,0,10,0,12,0,71,0,0,0,11,0,1,0,51,0,0,0,11,0,12,0,71,0,0,0,12,0,16,0,54,0,0,0,2,0,8,0,0,0,0,0,4,0,5,0,48,0,0,0,6,0,15,0,0,0,\r
-0,0,6,0,8,0,39,0,0,0,8,0,14,0,0,0,0,0,10,0,13,0,0,0,0,0,10,0,8,0,39,0,0,0,10,0,10,0,41,0,0,0,11,0,12,0,0,0,0,0,11,0,11,0,42,0,\r
-0,0,11,0,9,0,60,0,0,0,12,0,8,0,0,0,0,0,12,0,17,0,43,0,0,0,12,0,2,0,44,0,0,0,12,0,3,0,45,0,0,0,12,0,1,0,46,0,0,0,12,0,17,0,49,0,\r
-0,0,12,0,7,0,50,0,0,0,12,0,4,0,53,0,0,0,12,0,16,0,59,0,0,0,12,0,2,0,61,0,0,0,12,0,6,0,62,0,0,0,12,0,3,0,65,0,0,0,12,0,0,0,72,\r
-0,0,0,16,0,8,0,0,0,0,0,10,0,0,0,17,0,0,0,6,0,0,0,0,0,0,0,5,0,0,0,48,6,0,0,52,12,0,0,0,0,0,0,11,0,0,0,17,0,0,0,8,0,0,0,0,0,0,0,\r
-5,0,0,0,64,6,0,0,75,12,0,0,0,0,0,0,12,0,0,0,17,0,0,0,2,0,0,0,0,0,0,0,5,0,0,0,80,6,0,0,98,12,0,0,0,0,0,0,2,0,0,0,18,12,0,0,24,\r
-12,0,0,2,0,0,0,18,12,0,0,33,12,0,0,1,0,0,0,42,12,0,0,5,0,5,0,2,0,0,0,146,11,0,0,8,0,0,0,91,1,1,0,112,32,2,0,64,0,90,2,0,0,14,\r
-0,3,0,1,0,3,0,0,0,157,11,0,0,9,0,0,0,111,16,3,0,2,0,83,32,0,0,112,48,7,0,2,1,14,0,0,0,6,0,6,0,3,0,0,0,164,11,0,0,8,0,0,0,91,1,\r
-3,0,112,48,4,0,64,5,90,2,2,0,14,0,5,0,3,0,5,0,0,0,176,11,0,0,6,0,0,0,83,32,2,0,112,84,9,0,2,49,14,0,2,0,1,0,1,0,0,0,184,11,0,\r
-0,11,0,0,0,112,16,0,0,1,0,34,0,16,0,112,16,24,0,0,0,91,16,4,0,14,0,0,0,5,0,4,0,0,0,0,0,190,11,0,0,2,0,0,0,18,0,15,0,5,0,3,0,3,\r
-0,1,0,198,11,0,0,12,0,0,0,84,33,4,0,29,1,112,48,12,0,50,4,12,0,30,1,17,0,13,0,30,1,39,0,3,0,0,0,8,0,1,0,1,0,9,0,3,0,2,0,0,0,0,\r
-0,208,11,0,0,2,0,0,0,18,0,17,0,4,0,3,0,0,0,0,0,214,11,0,0,2,0,0,0,18,0,17,0,2,0,1,0,0,0,0,0,221,11,0,0,2,0,0,0,18,16,15,0,5,\r
-0,3,0,3,0,1,0,226,11,0,0,12,0,0,0,84,33,4,0,29,1,112,48,13,0,50,4,12,0,30,1,17,0,13,0,30,1,39,0,3,0,0,0,8,0,1,0,1,0,9,0,6,0,3,\r
-0,3,0,1,0,235,11,0,0,21,0,0,0,84,50,4,0,29,2,112,48,13,0,67,5,12,0,56,0,8,0,110,16,1,0,0,0,12,1,30,2,17,1,18,1,30,2,40,253,13,\r
-1,30,2,39,1,0,0,3,0,0,0,17,0,1,0,1,0,18,0,8,0,6,0,6,0,1,0,253,11,0,0,12,0,0,0,84,33,4,0,29,1,118,6,14,0,2,0,12,0,30,1,17,0,13,\r
-0,30,1,39,0,3,0,0,0,8,0,1,0,1,0,9,0,6,0,5,0,0,0,0,0,9,12,0,0,2,0,0,0,18,0,15,0,32,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44,4,0,0,0,0,\r
-0,0,0,0,0,0,0,0,0,0,56,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,7,0,3,0,17,0,20,0,3,0,0,0,7,0,17,0,20,0,0,0,2,0,0,0,7,0,17,0,5,0,\r
-0,0,7,0,20,0,17,0,20,0,17,0,0,0,2,0,0,0,7,0,3,0,1,0,0,0,7,0,0,0,2,0,0,0,0,0,17,0,1,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,17,0,0,0,4,\r
-0,0,0,12,0,1,0,17,0,0,0,3,0,0,0,12,0,1,0,20,0,0,0,2,0,0,0,17,0,0,0,1,0,0,0,20,0,6,60,105,110,105,116,62,0,1,73,0,4,73,76,76,76,\r
-0,5,73,76,76,76,76,0,1,74,0,31,74,117,99,101,83,104,97,114,105,110,103,67,111,110,116,101,110,116,80,114,111,118,105,100,101,\r
-114,46,106,97,118,97,0,1,76,0,2,76,76,0,3,76,76,76,0,6,76,76,76,76,76,76,0,33,76,97,110,100,114,111,105,100,47,99,111,110,116,\r
-101,110,116,47,67,111,110,116,101,110,116,80,114,111,118,105,100,101,114,59,0,31,76,97,110,100,114,111,105,100,47,99,111,110,\r
-116,101,110,116,47,67,111,110,116,101,110,116,86,97,108,117,101,115,59,0,41,76,97,110,100,114,111,105,100,47,99,111,110,116,\r
-101,110,116,47,114,101,115,47,65,115,115,101,116,70,105,108,101,68,101,115,99,114,105,112,116,111,114,59,0,25,76,97,110,100,114,\r
-111,105,100,47,100,97,116,97,98,97,115,101,47,67,117,114,115,111,114,59,0,31,76,97,110,100,114,111,105,100,47,100,97,116,97,98,\r
-97,115,101,47,77,97,116,114,105,120,67,117,114,115,111,114,59,0,17,76,97,110,100,114,111,105,100,47,110,101,116,47,85,114,105,\r
-59,0,25,76,97,110,100,114,111,105,100,47,111,115,47,70,105,108,101,79,98,115,101,114,118,101,114,59,0,33,76,97,110,100,114,111,\r
-105,100,47,111,115,47,80,97,114,99,101,108,70,105,108,101,68,101,115,99,114,105,112,116,111,114,59,0,57,76,99,111,109,47,114,\r
-111,108,105,47,106,117,99,101,47,74,117,99,101,83,104,97,114,105,110,103,67,111,110,116,101,110,116,80,114,111,118,105,100,101,\r
-114,36,80,114,111,118,105,100,101,114,67,117,114,115,111,114,59,0,63,76,99,111,109,47,114,111,108,105,47,106,117,99,101,47,\r
-74,117,99,101,83,104,97,114,105,110,103,67,111,110,116,101,110,116,80,114,111,118,105,100,101,114,36,80,114,111,118,105,100,101,\r
-114,70,105,108,101,79,98,115,101,114,118,101,114,59,0,42,76,99,111,109,47,114,111,108,105,47,106,117,99,101,47,74,117,99,101,\r
-83,104,97,114,105,110,103,67,111,110,116,101,110,116,80,114,111,118,105,100,101,114,59,0,34,76,100,97,108,118,105,107,47,97,\r
-110,110,111,116,97,116,105,111,110,47,69,110,99,108,111,115,105,110,103,67,108,97,115,115,59,0,30,76,100,97,108,118,105,107,47,\r
-97,110,110,111,116,97,116,105,111,110,47,73,110,110,101,114,67,108,97,115,115,59,0,33,76,100,97,108,118,105,107,47,97,110,110,\r
-111,116,97,116,105,111,110,47,77,101,109,98,101,114,67,108,97,115,115,101,115,59,0,18,76,106,97,118,97,47,108,97,110,103,47,\r
-79,98,106,101,99,116,59,0,18,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,0,14,80,114,111,118,105,100,101,\r
-114,67,117,114,115,111,114,0,20,80,114,111,118,105,100,101,114,70,105,108,101,79,98,115,101,114,118,101,114,0,1,86,0,3,86,73,\r
-76,0,2,86,74,0,4,86,74,73,76,0,2,86,76,0,3,86,76,73,0,4,86,76,74,76,0,5,86,76,74,76,73,0,1,90,0,19,91,76,106,97,118,97,47,108,\r
-97,110,103,47,83,116,114,105,110,103,59,0,11,97,99,99,101,115,115,70,108,97,103,115,0,5,99,108,111,115,101,0,11,99,111,108,117,\r
-109,110,78,97,109,101,115,0,25,99,111,110,116,101,110,116,83,104,97,114,101,114,67,117,114,115,111,114,67,108,111,115,101,100,\r
-0,30,99,111,110,116,101,110,116,83,104,97,114,101,114,70,105,108,101,79,98,115,101,114,118,101,114,69,118,101,110,116,0,27,99,\r
-111,110,116,101,110,116,83,104,97,114,101,114,71,101,116,83,116,114,101,97,109,84,121,112,101,115,0,21,99,111,110,116,101,110,\r
-116,83,104,97,114,101,114,79,112,101,110,70,105,108,101,0,18,99,111,110,116,101,110,116,83,104,97,114,101,114,81,117,101,114,\r
-121,0,6,100,101,108,101,116,101,0,5,101,118,101,110,116,0,23,103,101,116,80,97,114,99,101,108,70,105,108,101,68,101,115,99,114,\r
-105,112,116,111,114,0,14,103,101,116,83,116,114,101,97,109,84,121,112,101,115,0,7,103,101,116,84,121,112,101,0,4,104,111,115,\r
-116,0,9,104,111,115,116,84,111,85,115,101,0,6,105,110,115,101,114,116,0,4,108,111,99,107,0,4,109,97,115,107,0,14,109,105,109,\r
-101,84,121,112,101,70,105,108,116,101,114,0,4,109,111,100,101,0,4,110,97,109,101,0,8,111,110,67,114,101,97,116,101,0,7,111,110,\r
-69,118,101,110,116,0,13,111,112,101,110,65,115,115,101,116,70,105,108,101,0,8,111,112,101,110,70,105,108,101,0,4,112,97,116,\r
-104,0,10,112,114,111,106,101,99,116,105,111,110,0,5,113,117,101,114,121,0,6,114,101,115,117,108,116,0,9,115,101,108,101,99,116,\r
-105,111,110,0,13,115,101,108,101,99,116,105,111,110,65,114,103,115,0,9,115,111,114,116,79,114,100,101,114,0,4,116,104,105,115,\r
-0,6,116,104,105,115,36,48,0,6,117,112,100,97,116,101,0,3,117,114,105,0,3,117,114,108,0,5,118,97,108,117,101,0,6,118,97,108,117,\r
-101,115,0,46,3,72,53,41,7,14,45,61,45,0,55,0,7,14,61,90,0,27,4,72,53,64,56,7,14,45,61,45,0,35,2,48,64,7,14,90,0,15,0,7,14,61,0,\r
-97,3,74,68,69,7,14,0,131,1,2,74,57,7,14,61,105,0,103,1,74,7,14,0,84,2,74,77,7,14,0,68,0,7,14,0,109,2,74,58,7,14,61,105,0,118,\r
-2,74,58,7,14,61,76,3,0,67,5,45,91,75,5,0,0,75,5,75,65,68,69,70,7,14,61,105,0,91,4,74,77,68,69,7,14,0,2,13,1,75,24,12,2,14,2,38,\r
-4,17,58,23,26,2,14,2,38,4,17,58,23,27,2,15,1,75,28,2,24,10,24,11,0,2,2,1,0,2,1,144,32,5,128,128,4,192,8,2,130,2,0,6,1,224,8,\r
-0,2,2,1,2,2,1,144,32,8,129,128,4,132,9,1,130,2,0,10,1,164,9,0,1,4,9,4,2,11,129,128,4,192,9,1,130,2,0,1,130,2,0,1,130,2,0,15,1,\r
-232,9,1,1,252,9,1,1,176,10,1,1,196,10,1,1,216,10,1,1,236,10,1,1,160,11,1,1,232,11,1,1,156,12,0,0,16,0,0,0,0,0,0,0,1,0,0,0,0,\r
-0,0,0,1,0,0,0,77,0,0,0,112,0,0,0,2,0,0,0,21,0,0,0,164,1,0,0,3,0,0,0,18,0,0,0,248,1,0,0,4,0,0,0,5,0,0,0,208,2,0,0,5,0,0,0,25,0,\r
-0,0,248,2,0,0,6,0,0,0,3,0,0,0,192,3,0,0,3,16,0,0,3,0,0,0,32,4,0,0,1,32,0,0,14,0,0,0,64,4,0,0,6,32,0,0,3,0,0,0,48,6,0,0,1,16,\r
-0,0,13,0,0,0,96,6,0,0,2,32,0,0,77,0,0,0,226,6,0,0,3,32,0,0,14,0,0,0,146,11,0,0,4,32,0,0,4,0,0,0,18,12,0,0,0,32,0,0,3,0,0,0,52,\r
-12,0,0,0,16,0,0,1,0,0,0,160,12,0,0,0,0};\r
+{31,139,8,8,96,160,247,93,0,3,74,97,118,97,68,101,120,66,121,116,101,67,111,100,101,46,100,101,120,0,149,151,93,108,20,85,20,\r
+199,207,157,153,157,253,236,178,91,170,20,145,178,229,83,80,216,242,165,96,5,11,45,72,183,91,139,161,52,218,190,56,221,157,148,\r
+129,221,153,101,102,118,133,23,2,106,162,209,196,24,125,64,19,73,48,33,106,140,15,36,26,227,131,49,152,24,163,241,65,77,148,248,\r
+160,209,152,152,24,193,68,227,131,6,37,241,127,63,118,219,173,197,232,194,111,238,185,231,156,123,238,185,231,222,153,206,\r
+148,237,19,137,190,173,219,105,239,208,216,231,67,47,106,177,200,154,39,135,207,172,189,226,63,113,230,173,189,99,175,63,244,\r
+123,185,131,168,70,68,39,38,182,117,146,250,157,79,17,141,146,212,223,4,46,48,34,110,252,3,109,4,237,103,26,209,82,222,71,171,\r
+163,189,132,203,80,156,40,103,16,125,111,18,253,4,126,6,191,129,107,224,58,232,137,18,245,130,53,96,3,216,2,14,131,6,120,25,188,\r
+11,190,1,191,128,100,140,104,19,112,192,235,224,50,184,6,110,193,28,187,192,3,192,6,117,240,52,120,6,60,15,206,130,115,224,\r
+101,240,10,120,3,188,9,222,6,159,128,175,192,183,224,42,136,38,136,214,129,33,48,5,60,240,8,56,5,206,130,87,193,69,240,54,120,\r
+31,124,12,62,5,95,130,31,192,21,240,43,248,19,24,73,162,197,96,57,88,5,242,224,78,176,27,12,131,7,65,9,56,224,56,56,9,78,129,\r
+199,192,83,0,101,37,148,142,16,138,208,37,148,159,176,45,148,6,139,64,6,100,73,238,193,98,208,165,246,229,102,176,4,116,147,\r
+220,143,91,193,106,176,134,228,190,240,223,195,168,189,166,228,10,228,152,154,235,4,100,148,65,236,231,105,165,71,233,233,89,200,\r
+248,47,108,252,23,83,50,247,143,170,60,94,48,229,92,205,3,179,92,201,231,249,62,43,249,53,200,43,148,124,17,242,42,37,191,11,\r
+121,165,146,63,130,220,171,228,47,32,231,148,252,181,41,215,177,120,78,14,93,42,135,4,170,181,85,212,42,69,247,137,122,201,126,\r
+82,245,83,168,214,157,196,215,28,19,99,13,172,176,143,248,154,22,137,190,9,253,58,17,51,45,250,9,81,105,222,74,125,2,255,214,\r
+171,120,36,218,36,109,16,109,156,238,17,241,101,220,20,42,113,187,104,53,186,67,180,58,109,20,45,163,77,202,190,89,180,81,218,\r
+34,90,131,182,171,252,250,213,184,93,162,53,105,183,26,191,71,237,253,1,177,231,49,149,151,172,185,169,106,193,247,171,15,157,\r
+109,50,61,113,94,178,170,70,77,251,0,236,35,202,158,82,118,109,142,253,32,236,211,202,206,245,157,144,187,83,179,114,111,74,\r
+158,201,13,41,238,31,17,250,231,146,114,142,41,198,168,150,211,104,128,38,53,126,66,117,120,242,179,118,46,41,207,137,151,209,\r
+225,127,8,91,89,235,139,146,198,210,34,119,83,248,92,104,197,208,97,53,104,32,50,169,105,136,17,129,149,231,117,49,41,215,121,\r
+8,241,107,227,113,210,54,167,17,139,137,92,222,73,202,181,214,50,60,183,149,168,79,45,195,207,253,84,198,16,59,25,17,167,154,\r
+232,189,164,90,7,246,155,199,229,249,125,152,148,117,24,239,53,104,57,171,245,165,104,139,145,162,30,150,197,222,247,176,117,\r
+34,183,152,152,39,78,186,170,212,103,173,56,89,68,150,119,211,229,57,58,77,100,133,103,86,83,151,153,157,239,251,121,243,117,\r
+252,203,124,166,26,115,37,41,239,233,241,45,24,163,241,49,131,145,20,237,128,159,155,225,51,165,88,143,150,101,157,184,222,118,\r
+189,3,215,117,76,222,227,89,17,167,19,126,188,202,140,174,183,205,221,48,121,5,111,60,119,68,172,33,158,154,173,89,206,160,182,\r
+223,29,243,250,59,230,245,121,55,138,168,89,220,161,186,144,179,226,94,213,148,28,17,109,151,208,102,91,122,93,84,47,218,58,\r
+151,89,209,231,232,170,205,170,216,252,126,202,42,61,151,155,177,179,202,175,139,204,123,28,215,9,119,19,27,38,99,184,88,44,82,\r
+132,95,139,196,10,180,162,80,47,217,135,142,88,190,227,206,12,122,110,104,187,225,65,223,107,56,101,219,223,116,212,106,88,\r
+196,138,164,193,85,231,254,102,81,252,168,183,104,185,101,223,115,202,249,146,28,146,159,55,180,159,86,220,200,101,194,170,212,\r
+237,160,159,214,255,195,193,183,131,252,158,32,176,195,253,78,197,30,178,131,146,239,212,66,15,177,150,182,92,203,86,104,77,\r
+91,129,157,31,172,251,129,215,54,77,203,52,106,133,190,115,162,233,144,109,57,184,118,152,63,236,59,115,195,121,65,158,207,53,\r
+54,29,216,126,131,103,221,59,215,116,208,242,75,118,101,126,50,59,139,37,175,154,247,189,138,147,63,138,210,229,111,92,191,213,\r
+77,161,153,203,189,255,127,104,123,122,27,254,115,128,126,90,89,44,91,149,134,115,44,111,185,174,23,90,161,227,185,249,125,110,\r
+169,226,5,220,187,98,5,216,131,158,5,124,134,93,23,25,75,123,239,2,246,81,187,58,173,28,248,54,118,22,249,41,201,87,44,119,\r
+38,63,54,125,212,46,133,237,186,67,33,207,174,159,210,237,197,160,174,133,86,72,108,130,244,137,97,156,184,137,2,25,19,5,33,225,\r
+236,77,20,113,112,39,138,5,28,92,126,29,38,54,73,139,167,22,152,37,105,149,74,118,16,236,175,88,51,1,69,248,98,109,74,150,\r
+188,74,189,234,222,111,85,237,128,150,170,195,198,171,214,204,101,144,187,149,169,167,205,52,55,173,125,13,168,105,89,155,253,\r
+62,59,196,164,182,85,29,63,89,67,220,155,218,140,99,53,219,229,1,168,179,77,253,64,221,246,79,146,89,182,43,118,104,83,196,22,\r
+97,151,204,216,225,66,39,141,210,51,237,83,68,209,231,18,25,71,188,32,164,56,191,142,123,135,177,66,211,113,145,104,72,70,197,\r
+43,29,35,163,106,5,199,40,93,117,170,54,119,71,212,16,149,53,170,94,25,67,93,84,129,98,158,59,136,184,200,33,234,185,114,113,\r
+29,30,82,110,221,124,240,104,174,192,168,89,225,17,74,212,124,143,239,45,14,0,69,142,203,101,224,118,173,87,144,71,128,229,72,\r
+75,71,75,220,227,163,254,113,212,54,28,243,203,124,246,240,136,19,144,201,175,171,251,200,172,215,202,124,118,189,238,59,252,\r
+82,161,72,131,63,21,200,20,77,64,155,244,3,219,215,71,211,27,119,109,164,187,40,154,222,53,73,203,140,3,219,7,118,72,213,42,173,\r
+111,32,154,158,196,147,24,38,178,244,194,208,190,104,154,30,99,90,97,39,20,14,205,176,2,250,227,90,97,20,205,16,156,168,170,\r
+21,238,22,166,134,20,138,58,254,116,108,156,26,193,147,119,36,50,178,103,104,223,126,97,157,50,10,163,34,150,214,193,70,186,83,\r
+90,90,91,107,100,239,94,114,75,83,88,166,45,98,35,183,106,221,137,238,36,105,26,195,159,238,103,115,145,211,167,141,75,49,237,\r
+81,141,76,246,93,140,171,53,174,142,157,57,109,60,30,103,80,39,216,133,56,49,35,110,104,73,232,46,9,93,147,69,236,199,56,99,127,\r
+129,139,9,198,62,0,95,129,171,224,124,146,177,31,193,75,41,249,110,75,234,89,222,108,155,223,30,252,57,223,252,254,208,105,\r
+246,27,196,160,217,239,16,222,54,191,69,76,154,253,30,209,51,82,230,127,207,88,78,190,75,15,64,54,115,82,207,223,161,88,70,190,\r
+103,139,119,228,156,156,151,127,191,232,202,159,191,243,24,57,57,31,127,47,34,53,86,188,123,101,100,174,252,91,233,111,138,244,\r
+241,33,100,13,0,0,0,0};\r
 \r
 //==============================================================================\r
 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
index 18be24d45dbb8695d57ba37f57498c646e18aab3..7b1d1ec59839132667e6c3e36d54470109d82e7b 100644 (file)
@@ -196,10 +196,6 @@ static const uint8 javaComponentPeerView[] =
  extern void juce_firebaseRemoteMessageSendError (void*, void*);\r
 #endif\r
 \r
-#if JUCE_IN_APP_PURCHASES && JUCE_MODULE_AVAILABLE_juce_product_unlocking\r
- extern void juce_inAppPurchaseCompleted (void*);\r
-#endif\r
-\r
 extern void juce_contentSharingCompleted (int);\r
 \r
 //==============================================================================\r
index da10b2ad35b206166785c6c48538b2b85f134572..f9c26a0df751fed66b7a3dd9461c460b74d0492e 100644 (file)
@@ -164,9 +164,6 @@ private:
 \r
             if (auto* parentController = peer->controller)\r
                 [parentController showViewController: controller.get() sender: parentController];\r
-\r
-            if (peer->view.window != nil)\r
-                peer->view.window.autoresizesSubviews = YES;\r
         }\r
     }\r
 \r
index 4cea7ea053f2067ccc92ed746d2ff6be94e5393c..ed481968ce7045e9ee743b5c0202f978bc2d2cf0 100644 (file)
@@ -144,9 +144,6 @@ private:
 \r
             if (auto* parentController = peer->controller)\r
                 [parentController showViewController: controller.get() sender: parentController];\r
-\r
-            if (peer->view.window != nil)\r
-                peer->view.window.autoresizesSubviews = YES;\r
         }\r
     }\r
 \r
index 9f4b548043ec1d5b9ef9552538a5764da5b735bf..e15f423b2e853421c32761d9b91caab914c78fa2 100644 (file)
@@ -600,7 +600,6 @@ UIViewComponentPeer::UIViewComponentPeer (Component& comp, const int windowStyle
         window.rootViewController = controller;\r
 \r
         window.hidden = true;\r
-        window.autoresizesSubviews = NO;\r
         window.transform = Orientations::getCGTransformFor (Desktop::getInstance().getCurrentOrientation());\r
         window.opaque = component.isOpaque();\r
         window.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent: 0];\r
index c44e331e0b66cde32f227f0f081c884e3aeffde1..51068ad455cada9e7b0835002f9f989e57b3b67c 100644 (file)
@@ -1526,6 +1526,9 @@ public:
         ScopedXLock xlock (display);\r
         XGetInputFocus (display, &focusedWindow, &revert);\r
 \r
+        if (focusedWindow == PointerRoot)\r
+            return false;\r
+\r
         return isParentWindowOf (focusedWindow);\r
     }\r
 \r
index b391fba636ae128777bc9b43dc5d60e35993dcfb..4f7c30c907fbe091e6f712dfb1de50471b67de96 100644 (file)
   ==============================================================================\r
 */\r
 \r
+//==============================================================================\r
+#if defined (MAC_OS_X_VERSION_10_8) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8) \\r
+  && USE_COREGRAPHICS_RENDERING && JUCE_COREGRAPHICS_DRAW_ASYNC\r
+static const juce::Identifier disableAsyncLayerBackedViewIdentifier { "disableAsyncLayerBackedView" };\r
+\r
+void setComponentAsyncLayerBackedViewDisabled (juce::Component& comp, bool shouldDisableAsyncLayerBackedView)\r
+{\r
+    comp.getProperties().set (disableAsyncLayerBackedViewIdentifier, shouldDisableAsyncLayerBackedView);\r
+}\r
+\r
+bool getComponentAsyncLayerBackedViewDisabled (juce::Component& comp)\r
+{\r
+    return comp.getProperties()[disableAsyncLayerBackedViewIdentifier];\r
+}\r
+#endif\r
+\r
+//==============================================================================\r
 namespace juce\r
 {\r
     typedef void (*AppFocusChangeCallback)();\r
@@ -85,6 +102,15 @@ public:
 \r
         [view setPostsFrameChangedNotifications: YES];\r
 \r
+       #if defined (MAC_OS_X_VERSION_10_8) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8) \\r
+        && USE_COREGRAPHICS_RENDERING && JUCE_COREGRAPHICS_DRAW_ASYNC\r
+        if (! getComponentAsyncLayerBackedViewDisabled (component))\r
+        {\r
+            [view setWantsLayer: YES];\r
+            [[view layer] setDrawsAsynchronously: YES];\r
+        }\r
+       #endif\r
+\r
         if (isSharedWindow)\r
         {\r
             window = [viewToAttachTo window];\r
@@ -106,13 +132,11 @@ public:
 \r
             [window setOpaque: component.isOpaque()];\r
 \r
-          #if defined (MAC_OS_X_VERSION_10_14) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14)\r
             if (! [window isOpaque])\r
                 [window setBackgroundColor: [NSColor clearColor]];\r
 \r
-            #if defined (MAC_OS_X_VERSION_10_9) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9)\r
-             [view setAppearance: [NSAppearance appearanceNamed: NSAppearanceNameAqua]];\r
-            #endif\r
+           #if defined (MAC_OS_X_VERSION_10_9) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9)\r
+            [view setAppearance: [NSAppearance appearanceNamed: NSAppearanceNameAqua]];\r
            #endif\r
 \r
             [window setHasShadow: ((windowStyleFlags & windowHasDropShadow) != 0)];\r
@@ -923,7 +947,7 @@ public:
 \r
         // When windows are being resized, artificially throttling high-frequency repaints helps\r
         // to stop the event queue getting clogged, and keeps everything working smoothly.\r
-        // For some reason Logic also needs this throttling to recored parameter events correctly.\r
+        // For some reason Logic also needs this throttling to record parameter events correctly.\r
         if (msSinceLastRepaint < minimumRepaintInterval && shouldThrottleRepaint())\r
         {\r
             startTimer (static_cast<int> (minimumRepaintInterval - msSinceLastRepaint));\r
@@ -991,12 +1015,12 @@ public:
 \r
     bool canBecomeKeyWindow()\r
     {\r
-        return (getStyleFlags() & juce::ComponentPeer::windowIgnoresKeyPresses) == 0;\r
+        return component.isVisible() && (getStyleFlags() & juce::ComponentPeer::windowIgnoresKeyPresses) == 0;\r
     }\r
 \r
     bool canBecomeMainWindow()\r
     {\r
-        return dynamic_cast<ResizableWindow*> (&component) != nullptr;\r
+        return component.isVisible() && dynamic_cast<ResizableWindow*> (&component) != nullptr;\r
     }\r
 \r
     bool worksWhenModal() const\r
@@ -1857,9 +1881,15 @@ private:
     static BOOL becomeFirstResponder (id self, SEL)\r
     {\r
         if (auto* owner = getOwner (self))\r
-            owner->viewFocusGain();\r
+        {\r
+            if (owner->canBecomeKeyWindow())\r
+            {\r
+                owner->viewFocusGain();\r
+                return YES;\r
+            }\r
+        }\r
 \r
-        return YES;\r
+        return NO;\r
     }\r
 \r
     static BOOL resignFirstResponder (id self, SEL)\r
@@ -1975,7 +2005,17 @@ private:
         sendSuperclassMessage (self, @selector (becomeKeyWindow));\r
 \r
         if (auto* owner = getOwner (self))\r
-            owner->becomeKeyWindow();\r
+        {\r
+            if (owner->canBecomeKeyWindow())\r
+            {\r
+                owner->becomeKeyWindow();\r
+                return;\r
+            }\r
+\r
+            // this fixes a bug causing hidden windows to sometimes become visible when the app regains focus\r
+            if (! owner->getComponent().isVisible())\r
+                [(NSWindow*) self orderOut: nil];\r
+        }\r
     }\r
 \r
     static BOOL windowShouldClose (id self, SEL, id /*window*/)\r
index b40684f5df2f248e2cedab9b082e41bac5ca842c..ddc082a903f63790d0d02218632a6a1c1b7e1b13 100644 (file)
@@ -518,8 +518,14 @@ bool juce_areThereAnyAlwaysOnTopWindows()
 static void selectImageForDrawing (const Image& image)\r
 {\r
     [NSGraphicsContext saveGraphicsState];\r
+\r
+   #if (defined (MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10)\r
     [NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithCGContext: juce_getImageContext (image)\r
                                                                                   flipped: false]];\r
+   #else\r
+    [NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort: juce_getImageContext (image)\r
+                                                                                     flipped: false]];\r
+   #endif\r
 }\r
 \r
 static void releaseImageAfterDrawing()\r
index a7ac49cedf5ba62a019ef1ace5585b5e9bcbf188..d708c8604393dda14faf04f0a420adb4e6d4fabc 100644 (file)
@@ -34,7 +34,7 @@ namespace juce
 // the dialog box. This means that the actual native FileChooser HWND may\r
 // not have been created yet when the user deletes JUCE's FileChooser class. If this\r
 // occurs the Win32NativeFileChooser will still have a reference count of 1 and will\r
-// simply delete itself immedietely once the HWND will have been created a while later.\r
+// simply delete itself immediately once the HWND will have been created a while later.\r
 class Win32NativeFileChooser  : public ReferenceCountedObject,\r
                                 private Thread\r
 {\r
index 455ceb3990df7f83370245b310d84da790c8c228..b9c217e8a589eca8ac1e74da85d8ab7380896b06 100644 (file)
@@ -56,7 +56,7 @@ extern void juce_repeatLastProcessPriority();
 extern void juce_checkCurrentlyFocusedTopLevelWindow();  // in juce_TopLevelWindow.cpp\r
 extern bool juce_isRunningInWine();\r
 \r
-typedef bool (*CheckEventBlockedByModalComps) (const MSG&);\r
+using CheckEventBlockedByModalComps = bool (*)(const MSG&);\r
 extern CheckEventBlockedByModalComps isEventBlockedByModalComps;\r
 \r
 static bool shouldDeactivateTitleBar = true;\r
@@ -496,7 +496,7 @@ static double getGlobalDPI()
 #endif\r
 \r
 //==============================================================================\r
-typedef void (*SettingChangeCallbackFunc) (void);\r
+using SettingChangeCallbackFunc = void (*)(void);\r
 extern SettingChangeCallbackFunc settingChangeCallback;\r
 \r
 //==============================================================================\r
@@ -1632,8 +1632,8 @@ public:
             scale = 1.0 / Desktop::getInstance().getDisplays().getMainDisplay().scale;\r
        #endif\r
 \r
-        const RECT r = { roundToInt (area.getX()     * scale), roundToInt (area.getY()      * scale),\r
-                         roundToInt (area.getRight() * scale), roundToInt (area.getBottom() * scale) };\r
+        auto scaled = area.toDouble() * scale;\r
+        auto r = RECTFromRectangle (scaled.getSmallestIntegerContainer());\r
 \r
         InvalidateRect (hwnd, &r, FALSE);\r
     }\r
index d10b56d914ab196b87ee183e0c2b275c1800cc64..b3eeacebec406dcbb66f5447426bb9e490a46cdc 100644 (file)
@@ -55,7 +55,7 @@ public:
                                     These are the values that will be read and written to the\r
                                     valueToControl value. This array must contain the same number of items\r
                                     as the choices array\r
-        @param maxChoices           the maxmimum number of values which can be selected at once. The default of\r
+        @param maxChoices           the maximum number of values which can be selected at once. The default of\r
                                     -1 will not limit the number that can be selected\r
     */\r
     MultiChoicePropertyComponent (const Value& valueToControl,\r
@@ -73,7 +73,7 @@ public:
                                     These are the values that will be read and written to the\r
                                     valueToControl value. This array must contain the same number of items\r
                                     as the choices array\r
-        @param maxChoices           the maxmimum number of values which can be selected at once. The default of\r
+        @param maxChoices           the maximum number of values which can be selected at once. The default of\r
                                     -1 will not limit the number that can be selected\r
     */\r
     MultiChoicePropertyComponent (ValueWithDefault& valueToControl,\r
index 35d2e9d715657a6c5c24d8a071a084f6bcad7457..eeda9c5dc5d0e03e7bde8a1020adb4a39204a96c 100644 (file)
@@ -77,7 +77,7 @@ public:
         The components in the list will be owned by this object and will be automatically\r
         deleted later on when no longer needed.\r
 \r
-        To add properies without them being in a section, use addProperties().\r
+        To add properties without them being in a section, use addProperties().\r
     */\r
     void addSection (const String& sectionTitle,\r
                      const Array<PropertyComponent*>& newPropertyComponents,\r
index cf59fa85742399d1bb3651674fa61b8aea59f300..d20093a70c8a9af31d6f7c42a7ebc1194ba56872 100644 (file)
@@ -83,7 +83,7 @@ void ComboBox::addItem (const String& newItemText, int newItemId)
     // you can't add empty strings to the list..\r
     jassert (newItemText.isNotEmpty());\r
 \r
-    // IDs must be non-zero, as zero is used to indicate a lack of selecion.\r
+    // IDs must be non-zero, as zero is used to indicate a lack of selection.\r
     jassert (newItemId != 0);\r
 \r
     // you shouldn't use duplicate item IDs!\r
@@ -489,6 +489,8 @@ void ComboBox::showPopupIfNotActive()
         // showPopup asynchronously, we are giving the other popups a chance to properly\r
         // close themselves\r
         MessageManager::callAsync ([safePointer]() mutable { if (safePointer != nullptr) safePointer->showPopup(); });\r
+\r
+        repaint();\r
     }\r
 }\r
 \r
index 043eb126ab4c012bdd4dabf40c5d84a928f56536..05876a7ccabbc5e6f2e93cbaf5d82e0eebad13ce 100644 (file)
@@ -240,8 +240,8 @@ public:
 \r
         The text passed-in will be set as the current text regardless of whether\r
         it is one of the items in the list. If the current text isn't one of the\r
-        items, then getSelectedId() will return 0, otherwise it wil return\r
-        the approriate ID.\r
+        items, then getSelectedId() will return 0, otherwise it will return\r
+        the appropriate ID.\r
 \r
         @param newText          the text to select\r
         @param notification     determines the type of change notification that will\r
index 8b9d6b265636ba79b2659d5749c9665608fe84b8..7a723dbb4c323ec0caa351bc0b305e72a288143f 100644 (file)
@@ -107,7 +107,7 @@ public:
     {\r
         notDragging,            /**< Dragging is not active.  */\r
         absoluteDrag,           /**< The dragging corresponds directly to the value that is displayed.  */\r
-        velocityDrag            /**< The dragging value change is relative to the velocity of the mouse mouvement.  */\r
+        velocityDrag            /**< The dragging value change is relative to the velocity of the mouse movement.  */\r
     };\r
 \r
     //==============================================================================\r
index 01057d5109ecd407d69e281786211f59c5868cc8..e9a50b73b8f43c778d83b3dadbe4028a92e187ca 100644 (file)
@@ -194,7 +194,7 @@ public:
 \r
     /** Triggers a re-sort of the table according to the current sort-column.\r
 \r
-        If you modifiy the table's contents, you can call this to signal that the table needs\r
+        If you modify the table's contents, you can call this to signal that the table needs\r
         to be re-sorted.\r
 \r
         (This doesn't do any sorting synchronously - it just asynchronously sends a call to the\r
@@ -229,7 +229,7 @@ public:
 \r
         The index is an index from 0 to the number of columns that are currently visible (hidden\r
         ones are not counted). It returns a rectangle showing the position of the column relative\r
-        to this component's top-left. If the index is out-of-range, an empty rectangle is retrurned.\r
+        to this component's top-left. If the index is out-of-range, an empty rectangle is returned.\r
     */\r
     Rectangle<int> getColumnPosition (int index) const;\r
 \r
@@ -382,7 +382,7 @@ public:
         highlightColourId              = 0x1003830, /**< The colour of the table header background when\r
                                                          the mouse is over or down above the the table\r
                                                          header. It's up to the LookAndFeel to use a\r
-                                                         variant of this colour to destiuish between\r
+                                                         variant of this colour to distinguish between\r
                                                          the down and hover state. */\r
     };\r
 \r
index 734bc5e585f371af1181eb5a4c6e4b22a256b849..3c113a7dfc27aec230edf88e860ae7648a300b52 100644 (file)
@@ -532,7 +532,7 @@ public:
     /** Returns the index of this item in its parent's sub-items. */\r
     int getIndexInParent() const noexcept;\r
 \r
-    /** Returns true if this item is the last of its parent's sub-itens. */\r
+    /** Returns true if this item is the last of its parent's sub-items. */\r
     bool isLastOfSiblings() const noexcept;\r
 \r
     /** Creates a string that can be used to uniquely retrieve this item in the tree.\r
@@ -842,8 +842,8 @@ public:
         linesColourId                  = 0x1000501, /**< The colour to draw the lines with.*/\r
         dragAndDropIndicatorColourId   = 0x1000502, /**< The colour to use for the drag-and-drop target position indicator. */\r
         selectedItemBackgroundColourId = 0x1000503, /**< The colour to use to fill the background of any selected items. */\r
-        oddItemsColourId               = 0x1000504, /**< The colour to use to fill the backround of the odd numbered items. */\r
-        evenItemsColourId              = 0x1000505  /**< The colour to use to fill the backround of the even numbered items. */\r
+        oddItemsColourId               = 0x1000504, /**< The colour to use to fill the background of the odd numbered items. */\r
+        evenItemsColourId              = 0x1000505  /**< The colour to use to fill the background of the even numbered items. */\r
     };\r
 \r
     //==============================================================================\r
index 755d1dc0eefe7706e44b39fda5c6e18900ce6019..a4376f7efe0bc47e26a2cc4afadf8f4ab0eae6a0 100644 (file)
@@ -63,7 +63,7 @@ AlertWindow::~AlertWindow()
     for (auto* t : textBoxes)\r
         t->setWantsKeyboardFocus (false);\r
 \r
-    // Giveaway focus before removing the editors, so that any TextEditor\r
+    // Give away focus before removing the editors, so that any TextEditor\r
     // with focus has a chance to dismiss native keyboard if shown.\r
     if (hasKeyboardFocus (true))\r
         Component::unfocusAllComponents();\r
index 29ec188b5d43c87f9a0b86af577498d29188b8b6..92583f748ae8699c5201a5b2b8a2c11d4e64cea9 100644 (file)
@@ -153,7 +153,7 @@ public:
     //==============================================================================\r
     /** Easy way of quickly showing a dialog box containing a given component.\r
 \r
-        Note: This method has been superceded by the DialogWindow::LaunchOptions structure,\r
+        Note: This method has been superseded by the DialogWindow::LaunchOptions structure,\r
         which does the same job with some extra flexibility. The showDialog method is here\r
         for backwards compatibility, but please use DialogWindow::LaunchOptions in new code.\r
 \r
@@ -199,7 +199,7 @@ public:
    #if JUCE_MODAL_LOOPS_PERMITTED || DOXYGEN\r
     /** Easy way of quickly showing a dialog box containing a given component.\r
 \r
-        Note: This method has been superceded by the DialogWindow::LaunchOptions structure,\r
+        Note: This method has been superseded by the DialogWindow::LaunchOptions structure,\r
         which does the same job with some extra flexibility. The showDialog method is here\r
         for backwards compatibility, but please use DialogWindow::LaunchOptions in new code.\r
 \r
index 473fdcee99a9666a8ddd571962743b5142a15a69..cf1ab85a885f1e0295be7b0ee7250ddadb9eb640 100644 (file)
@@ -159,7 +159,7 @@ public:
         A pointer to the object you pass in will be kept, but it won't be deleted\r
         by this object, so it's the caller's responsibility to manage it.\r
 \r
-        If you pass a nullptr, then no contraints will be placed on the positioning of the window.\r
+        If you pass a nullptr, then no constraints will be placed on the positioning of the window.\r
     */\r
     void setConstrainer (ComponentBoundsConstrainer* newConstrainer);\r
 \r
index 6810abc22a09911810e964e704b6a2a83db48bde..bde976102b8328daf2cd93b4ee4f49030a773450 100644 (file)
@@ -337,7 +337,7 @@ public:
     */\r
     virtual void performPopupMenuAction (int menuItemID);\r
 \r
-    /** Specifies a commmand-manager which the editor will notify whenever the state\r
+    /** Specifies a command-manager which the editor will notify whenever the state\r
         of any of its commands changes.\r
         If you're making use of the editor's ApplicationCommandTarget interface, then\r
         you should also use this to tell it which command manager it should use. Make\r
index a769fba869362dbd568961f1129b774ca1ad0033..4894cb13706761691449f4ec31d64217a748d571 100644 (file)
@@ -36,11 +36,13 @@ namespace juce
     when it goes out of scope.\r
 \r
     If you create one of these before creating a top-level window, the window\r
-    will be DPI unaware and bitmap strectched by the OS on a display with >100%\r
+    will be DPI unaware and bitmap stretched by the OS on a display with >100%\r
     scaling.\r
 \r
     You shouldn't use this unless you really know what you are doing and\r
     are dealing with native HWNDs.\r
+\r
+    @tags{GUI}\r
 */\r
 class JUCE_API  ScopedDPIAwarenessDisabler\r
 {\r
index 223610516720f4a1f5799ad543d263eb62b2840f..705bff9062ed61100fe38bb73de52159b68a539e 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_gui_extra\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE extended GUI classes\r
-  description:      Miscellaneous GUI classes for specialised tasks.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
+  ID:                 juce_gui_extra\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE extended GUI classes\r
+  description:        Miscellaneous GUI classes for specialised tasks.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
 \r
-  dependencies:     juce_gui_basics\r
-  OSXFrameworks:    WebKit\r
+  dependencies:       juce_gui_basics\r
+  OSXFrameworks:      WebKit\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index eaa29f7e0d474e4cb1f5c81c2fd526e8d6333fd5..a3ad36aad401d04a47700cf8627a7899b045e38d 100644 (file)
@@ -70,7 +70,7 @@ public:
         @param position                         the coords of the object to point to\r
         @param message                          the text to display\r
         @param numMillisecondsBeforeRemoving    how long to leave it on the screen before removing itself\r
-                                                from its parent compnent. If this is 0 or less, it\r
+                                                from its parent component. If this is 0 or less, it\r
                                                 will stay there until manually removed.\r
         @param removeWhenMouseClicked           if this is true, the bubble will disappear as soon as a\r
                                                 mouse button is pressed (anywhere on the screen)\r
@@ -93,7 +93,7 @@ public:
         @param component                        the component that you want to point at\r
         @param message                          the text to display\r
         @param numMillisecondsBeforeRemoving    how long to leave it on the screen before removing itself\r
-                                                from its parent compnent. If this is 0 or less, it\r
+                                                from its parent component. If this is 0 or less, it\r
                                                 will stay there until manually removed.\r
         @param removeWhenMouseClicked           if this is true, the bubble will disappear as soon as a\r
                                                 mouse button is pressed (anywhere on the screen)\r
index 976b59822641d8606faf2f2c5035ec6a5404bcc4..5c98a4e6c15977a30adeb57e342e4f428b659e78 100644 (file)
@@ -302,6 +302,85 @@ private:
     JUCE_DECLARE_NON_COPYABLE (SwatchComponent)\r
 };\r
 \r
+//==============================================================================\r
+class ColourSelector::ColourPreviewComp  : public Component\r
+{\r
+public:\r
+    ColourPreviewComp (ColourSelector& cs, bool isEditable)\r
+        : owner (cs)\r
+    {\r
+        colourLabel.setFont (labelFont);\r
+        colourLabel.setJustificationType (Justification::centred);\r
+\r
+        if (isEditable)\r
+        {\r
+            colourLabel.setEditable (true);\r
+\r
+            colourLabel.onEditorShow = [this]\r
+            {\r
+                if (auto* ed = colourLabel.getCurrentTextEditor())\r
+                    ed->setInputRestrictions ((owner.flags & showAlphaChannel) ? 8 : 6, "1234567890ABCDEFabcdef");\r
+            };\r
+\r
+            colourLabel.onEditorHide = [this]\r
+            {\r
+                updateColourIfNecessary (colourLabel.getText());\r
+            };\r
+        }\r
+\r
+        addAndMakeVisible (colourLabel);\r
+    }\r
+\r
+    void updateIfNeeded()\r
+    {\r
+        auto newColour = owner.getCurrentColour();\r
+\r
+        if (currentColour != newColour)\r
+        {\r
+            currentColour = newColour;\r
+            auto textColour = (Colours::white.overlaidWith (currentColour).contrasting());\r
+\r
+            colourLabel.setColour (Label::textColourId,            textColour);\r
+            colourLabel.setColour (Label::textWhenEditingColourId, textColour);\r
+            colourLabel.setText (currentColour.toDisplayString ((owner.flags & showAlphaChannel) != 0), dontSendNotification);\r
+\r
+            labelWidth = labelFont.getStringWidth (colourLabel.getText());\r
+\r
+            repaint();\r
+        }\r
+    }\r
+\r
+    void paint (Graphics& g) override\r
+    {\r
+        g.fillCheckerBoard (getLocalBounds().toFloat(), 10.0f, 10.0f,\r
+                            Colour (0xffdddddd).overlaidWith (currentColour),\r
+                            Colour (0xffffffff).overlaidWith (currentColour));\r
+    }\r
+\r
+    void resized() override\r
+    {\r
+        colourLabel.centreWithSize (labelWidth + 10, (int) labelFont.getHeight() + 10);\r
+    }\r
+\r
+private:\r
+    void updateColourIfNecessary (const String& newColourString)\r
+    {\r
+        auto newColour = Colour::fromString (newColourString);\r
+\r
+        if (newColour != currentColour)\r
+            owner.setCurrentColour (newColour);\r
+    }\r
+\r
+    ColourSelector& owner;\r
+\r
+    Colour currentColour;\r
+    Font labelFont { 14.0f, Font::bold };\r
+    int labelWidth = 0;\r
+    Label colourLabel;\r
+\r
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ColourPreviewComp)\r
+};\r
+\r
 //==============================================================================\r
 ColourSelector::ColourSelector (int sectionsToShow, int edge, int gapAroundColourSpaceComponent)\r
     : colour (Colours::white),\r
@@ -313,6 +392,12 @@ ColourSelector::ColourSelector (int sectionsToShow, int edge, int gapAroundColou
 \r
     updateHSV();\r
 \r
+    if ((flags & showColourAtTop) != 0)\r
+    {\r
+        previewComponent.reset (new ColourPreviewComp (*this, (flags & editableColour) != 0));\r
+        addAndMakeVisible (previewComponent.get());\r
+    }\r
+\r
     if ((flags & showSliders) != 0)\r
     {\r
         sliders[0].reset (new ColourComponentSlider (TRANS ("red")));\r
@@ -418,8 +503,8 @@ void ColourSelector::update (NotificationType notification)
         hueSelector->updateIfNeeded();\r
     }\r
 \r
-    if ((flags & showColourAtTop) != 0)\r
-        repaint (previewArea);\r
+    if (previewComponent != nullptr)\r
+        previewComponent->updateIfNeeded();\r
 \r
     if (notification != dontSendNotification)\r
         sendChangeMessage();\r
@@ -433,20 +518,6 @@ void ColourSelector::paint (Graphics& g)
 {\r
     g.fillAll (findColour (backgroundColourId));\r
 \r
-    if ((flags & showColourAtTop) != 0)\r
-    {\r
-        auto currentColour = getCurrentColour();\r
-\r
-        g.fillCheckerBoard (previewArea.toFloat(), 10.0f, 10.0f,\r
-                            Colour (0xffdddddd).overlaidWith (currentColour),\r
-                            Colour (0xffffffff).overlaidWith (currentColour));\r
-\r
-        g.setColour (Colours::white.overlaidWith (currentColour).contrasting());\r
-        g.setFont (Font (14.0f, Font::bold));\r
-        g.drawText (currentColour.toDisplayString ((flags & showAlphaChannel) != 0),\r
-                    previewArea, Justification::centred, false);\r
-    }\r
-\r
     if ((flags & showSliders) != 0)\r
     {\r
         g.setColour (findColour (labelTextColourId));\r
@@ -475,7 +546,8 @@ void ColourSelector::resized()
     const int sliderSpace = ((flags & showSliders) != 0)  ? jmin (22 * numSliders + edgeGap, proportionOfHeight (0.3f)) : 0;\r
     const int topSpace = ((flags & showColourAtTop) != 0) ? jmin (30 + edgeGap * 2, proportionOfHeight (0.2f)) : edgeGap;\r
 \r
-    previewArea.setBounds (edgeGap, edgeGap, getWidth() - edgeGap * 2, topSpace - edgeGap * 2);\r
+    if (previewComponent != nullptr)\r
+        previewComponent->setBounds (edgeGap, edgeGap, getWidth() - edgeGap * 2, topSpace - edgeGap * 2);\r
 \r
     int y = topSpace;\r
 \r
index fb233ec32a5e3a1e353a2a14fb9b38865362eceb..a7c62fe05b0d7218afd42aa4a3f48c2f927d79ca 100644 (file)
@@ -49,8 +49,9 @@ public:
         showAlphaChannel    = 1 << 0,   /**< if set, the colour's alpha channel can be changed as well as its RGB. */\r
 \r
         showColourAtTop     = 1 << 1,   /**< if set, a swatch of the colour is shown at the top of the component. */\r
-        showSliders         = 1 << 2,   /**< if set, RGB sliders are shown at the bottom of the component. */\r
-        showColourspace     = 1 << 3    /**< if set, a big HSV selector is shown. */\r
+        editableColour      = 1 << 2,   /**< if set, the colour shows at the top of the component is editable. */\r
+        showSliders         = 1 << 3,   /**< if set, RGB sliders are shown at the bottom of the component. */\r
+        showColourspace     = 1 << 4    /**< if set, a big HSV selector is shown. */\r
     };\r
 \r
     //==============================================================================\r
@@ -137,6 +138,7 @@ public:
     // These need to be public otherwise the Projucer's live-build engine will complain\r
     class ColourSpaceView;\r
     class HueSelectorComp;\r
+    class ColourPreviewComp;\r
 \r
 private:\r
     //==============================================================================\r
@@ -147,10 +149,10 @@ private:
     std::unique_ptr<Slider> sliders[4];\r
     std::unique_ptr<ColourSpaceView> colourSpace;\r
     std::unique_ptr<HueSelectorComp> hueSelector;\r
+    std::unique_ptr<ColourPreviewComp> previewComponent;\r
     OwnedArray<SwatchComponent> swatchComponents;\r
     const int flags;\r
     int edgeGap;\r
-    Rectangle<int> previewArea;\r
 \r
     void setHue (float newH);\r
     void setSV (float newS, float newV);\r
index 742486a50c226b7697119a3fca7f1bcace8763b6..4b39f2c8aa0addb28f55ecb09c9b307959cc5930 100644 (file)
@@ -276,7 +276,7 @@ public:
         bool localOnly = true;  /**< Optional: whether or not the notification should bridge to other devices.\r
                                                Available from Android API 20 or above. */\r
 \r
-        bool ongoing = false;   /**< Optional: If true, then it cannot be dismissed by the user and it must be dimissed manually.\r
+        bool ongoing = false;   /**< Optional: If true, then it cannot be dismissed by the user and it must be dismissed manually.\r
                                      Typically used for ongoing background tasks that the user is actively engaged with. To\r
                                      dismiss such notification, you need to call removeDeliveredNotification() or\r
                                      removeAllDeliveredNotifications(). */\r
@@ -389,7 +389,7 @@ public:
     {\r
         using Action = Notification::Action;\r
 \r
-        /** Describes a category of a notification. Each category has a unique idenfifier\r
+        /** Describes a category of a notification. Each category has a unique identifier\r
             and a list of associated actions.\r
             Note that the OS may allow only a limited number of actions to be presented, so\r
             always present most important actions first.\r
@@ -634,7 +634,7 @@ public:
 \r
             @param isLocalNotification If the notification is local\r
             @param notification        The notification\r
-            @param actionIdentifier    A String identifiing the action\r
+            @param actionIdentifier    A String identifying the action\r
             @param optionalResponse    Text response a user inputs for notifications with a text input.\r
                                        Empty for notifications without a text input option.\r
 \r
index 9d77b2cb38887b57e6d608a0906b7a70a7f23c71..69c6500363644e6d70a16cb7a03bbc292b270de8 100644 (file)
@@ -1303,7 +1303,7 @@ struct PushNotifications::Pimpl
                     auto classAsString  = LocalRef<jstring> ((jstring) env->CallObjectMethod (objectClass, JavaClass.getName));\r
 \r
                     // Note: It seems that Firebase delivers values as strings always, so this check is rather unnecessary,\r
-                    //       at least untill they change the behaviour.\r
+                    //       at least until they change the behaviour.\r
                     var value = juceString (classAsString) == "java.lang.Bundle" ? bundleToVar (object) : var (juceString (objectAsString.get()));\r
                     dynamicObject->setProperty (juceString (key.get()), value);\r
                 }\r
@@ -1399,7 +1399,7 @@ struct PushNotifications::Pimpl
             propertiesDynamicObject->setProperty ("titleLocalizationKey",  juceString (titleLocalizationKey.get()));\r
             propertiesDynamicObject->setProperty ("bodyLocalizationArgs",  javaStringArrayToJuce (bodyLocalizationArgs));\r
             propertiesDynamicObject->setProperty ("titleLocalizationArgs", javaStringArrayToJuce (titleLocalizationArgs));\r
-            propertiesDynamicObject->setProperty ("link",                  link.get() == nullptr ? juceString ((jstring) env->CallObjectMethod (link, AndroidUri.toString)) : String());\r
+            propertiesDynamicObject->setProperty ("link",                  link.get() != nullptr ? juceString ((jstring) env->CallObjectMethod (link, AndroidUri.toString)) : String());\r
         }\r
 \r
         n.properties = var (propertiesDynamicObject.get());\r
@@ -1561,7 +1561,7 @@ struct JuceFirebaseInstanceIdService
      DECLARE_JNI_CLASS (InstanceIdService, "com/roli/juce/JuceFirebaseInstanceIdService")\r
     #undef JNI_CLASS_MEMBERS\r
 \r
-    static void JNICALL tokenRefreshed (void* token)\r
+    static void JNICALL tokenRefreshed (JNIEnv*, jobject /*instanceIdService*/, void* token)\r
     {\r
         if (auto* instance = PushNotifications::getInstanceWithoutCreating())\r
             instance->pimpl->notifyListenersTokenRefreshed (juceString (static_cast<jstring> (token)));\r
@@ -1577,9 +1577,9 @@ struct JuceFirebaseMessagingService
 {\r
     #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
      CALLBACK (remoteNotificationReceived,  "firebaseRemoteMessageReceived",  "(Lcom/google/firebase/messaging/RemoteMessage;)V") \\r
-     CALLBACK (remoteMessagesDeleted,  "firebaseRemoteMessagesDeleted",  "()V") \\r
-     CALLBACK (remoteMessageSent,      "firebaseRemoteMessageSent",      "(Ljava/lang/String;)V") \\r
-     CALLBACK (remoteMessageSendError, "firebaseRemoteMessageSendError", "(Ljava/lang/String;Ljava/lang/String;)V")\r
+     CALLBACK (remoteMessagesDeleted,       "firebaseRemoteMessagesDeleted",  "()V") \\r
+     CALLBACK (remoteMessageSent,           "firebaseRemoteMessageSent",      "(Ljava/lang/String;)V") \\r
+     CALLBACK (remoteMessageSendError,      "firebaseRemoteMessageSendError", "(Ljava/lang/String;Ljava/lang/String;)V")\r
 \r
      DECLARE_JNI_CLASS (MessagingService, "com/roli/juce/JuceFirebaseMessagingService")\r
     #undef JNI_CLASS_MEMBERS\r
index 0aa43b6cb846c31c2b35cf2c349c864ac54f1337..5f0aee26c9f6debd334875839521feae19ca9254 100644 (file)
@@ -174,7 +174,7 @@ namespace PushNotificationsDelegateDetails
         }\r
 \r
         // request\r
-        // each notification on iOS 10 needs to have an identifer, otherwise it will not show up\r
+        // each notification on iOS 10 needs to have an identifier, otherwise it will not show up\r
         jassert (n.identifier.isNotEmpty());\r
         UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier: juceStringToNS (n.identifier)\r
                                                                               content: content\r
@@ -300,7 +300,9 @@ namespace PushNotificationsDelegateDetails
         if (n.fireDate != nil)\r
         {\r
             NSDate* dateNow = [NSDate date];\r
-            notif.triggerIntervalSec = [dateNow timeIntervalSinceDate: n.fireDate];\r
+            NSDate* fireDate = n.fireDate;\r
+\r
+            notif.triggerIntervalSec = [dateNow timeIntervalSinceDate: fireDate];\r
         }\r
 \r
         notif.soundToPlay = URL (nsStringToJuce (n.soundName));\r
@@ -841,12 +843,22 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
 \r
     void registeredForRemoteNotifications (NSData* deviceTokenToUse) override\r
     {\r
-        NSString* deviceTokenString = [[[[deviceTokenToUse description]\r
-                                          stringByReplacingOccurrencesOfString: nsStringLiteral ("<") withString: nsStringLiteral ("")]\r
-                                          stringByReplacingOccurrencesOfString: nsStringLiteral (">") withString: nsStringLiteral ("")]\r
-                                          stringByReplacingOccurrencesOfString: nsStringLiteral (" ") withString: nsStringLiteral ("")];\r
+        deviceToken = [deviceTokenToUse]() -> String\r
+        {\r
+            auto length = deviceTokenToUse.length;\r
+\r
+            if (auto* buffer = (const unsigned char*) deviceTokenToUse.bytes)\r
+            {\r
+                NSMutableString* hexString = [NSMutableString stringWithCapacity: (length * 2)];\r
 \r
-        deviceToken = nsStringToJuce (deviceTokenString);\r
+                for (NSUInteger i = 0; i < length; ++i)\r
+                    [hexString appendFormat:@"%02x", buffer[i]];\r
+\r
+                return nsStringToJuce ([hexString copy]);\r
+            }\r
+\r
+            return {};\r
+        }();\r
 \r
         initialised = true;\r
 \r
index c23d8e257df6f14673b7adf40625ac022c447a90..3d017be162b7d6c39147106fab5c4afbd265ba5a 100644 (file)
@@ -151,7 +151,9 @@ namespace PushNotificationsDelegateDetailsOsx
         else\r
         {\r
             NSDate* dateNow = [NSDate date];\r
-            notif.triggerIntervalSec = [dateNow timeIntervalSinceDate: n.deliveryDate];\r
+            NSDate* deliveryDate = n.deliveryDate;\r
+\r
+            notif.triggerIntervalSec = [dateNow timeIntervalSinceDate: deliveryDate];\r
         }\r
 \r
         notif.soundToPlay = URL (nsStringToJuce (n.soundName));\r
@@ -367,7 +369,7 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
         NSRemoteNotificationType types = NSUInteger ((bool) settings.allowBadge);\r
 \r
         if (isAtLeastMountainLion)\r
-            types |= ((bool) settings.allowSound << 1 | (bool) settings.allowAlert << 2);\r
+            types |= (NSUInteger) ((bool) settings.allowSound << 1 | (bool) settings.allowAlert << 2);\r
 \r
         [[NSApplication sharedApplication] registerForRemoteNotificationTypes: types];\r
     }\r
@@ -469,12 +471,22 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
     //PushNotificationsDelegate\r
     void registeredForRemoteNotifications (NSData* deviceTokenToUse) override\r
     {\r
-        auto deviceTokenString = [[[[deviceTokenToUse description]\r
-                                     stringByReplacingOccurrencesOfString: nsStringLiteral ("<") withString: nsStringLiteral ("")]\r
-                                     stringByReplacingOccurrencesOfString: nsStringLiteral (">") withString: nsStringLiteral ("")]\r
-                                     stringByReplacingOccurrencesOfString: nsStringLiteral (" ") withString: nsStringLiteral ("")];\r
+        deviceToken = [deviceTokenToUse]() -> String\r
+        {\r
+            auto length = deviceTokenToUse.length;\r
+\r
+            if (auto* buffer = (const unsigned char*) deviceTokenToUse.bytes)\r
+            {\r
+                NSMutableString* hexString = [NSMutableString stringWithCapacity: (length * 2)];\r
 \r
-        deviceToken = nsStringToJuce (deviceTokenString);\r
+                for (NSUInteger i = 0; i < length; ++i)\r
+                    [hexString appendFormat:@"%02x", buffer[i]];\r
+\r
+                return nsStringToJuce ([hexString copy]);\r
+            }\r
+\r
+            return {};\r
+        }();\r
 \r
         initialised = true;\r
 \r
@@ -520,7 +532,7 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
         }\r
     }\r
 \r
-    bool shouldPresentNotification (NSUserNotification* notification) override { return true; }\r
+    bool shouldPresentNotification (NSUserNotification*) override { return true; }\r
 \r
     void subscribeToTopic (const String& topic)     { ignoreUnused (topic); }\r
     void unsubscribeFromTopic (const String& topic) { ignoreUnused (topic); }\r
index 1a0feedd3fef60981f6e8463dc1cd86c8d8c961a..3086162b0a80c330b4aef9df40a432b7283a1cb1 100644 (file)
 namespace juce\r
 {\r
 \r
+#pragma clang diagnostic push\r
+#pragma clang diagnostic ignored "-Wunguarded-availability"\r
+#if JUCE_CLANG && defined (MAC_OS_X_VERSION_10_14) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_14\r
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"\r
+#endif\r
+\r
 extern NSMenu* createNSMenu (const PopupMenu&, const String& name, int topLevelMenuId,\r
                              int topLevelIndex, bool addDelegate);\r
 \r
-class SystemTrayIconComponent::Pimpl  : private Timer\r
+//==============================================================================\r
+struct StatusItemContainer   : public Timer\r
 {\r
-public:\r
     //==============================================================================\r
-    Pimpl (SystemTrayIconComponent& iconComp, const Image& im)\r
+    StatusItemContainer (SystemTrayIconComponent& iconComp, const Image& im)\r
         : owner (iconComp), statusIcon (imageToNSImage (im))\r
     {\r
-        static ButtonEventForwarderClass cls;\r
-        eventForwarder.reset ([cls.createInstance() init]);\r
-        ButtonEventForwarderClass::setOwner (eventForwarder.get(), this);\r
+    }\r
 \r
-        configureIcon();\r
+    virtual void configureIcon() = 0;\r
+    virtual void setHighlighted (bool shouldHighlight) = 0;\r
 \r
-        statusItem.reset ([[[NSStatusBar systemStatusBar] statusItemWithLength: NSSquareStatusItemLength] retain]);\r
-        auto button = [statusItem.get() button];\r
-        button.image = statusIcon.get();\r
-        button.target = eventForwarder.get();\r
-        button.action = @selector (handleEvent:);\r
-       #if defined (MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12\r
-        [button sendActionOn: NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown | NSEventMaskScrollWheel];\r
-       #else\r
-        [button sendActionOn: NSLeftMouseDownMask | NSRightMouseDownMask | NSScrollWheelMask];\r
-       #endif\r
+    //==============================================================================\r
+    void setIconSize()\r
+    {\r
+        [statusIcon.get() setSize: NSMakeSize (20.0f, 20.0f)];\r
     }\r
 \r
-    //==============================================================================\r
     void updateIcon (const Image& newImage)\r
     {\r
         statusIcon.reset (imageToNSImage (newImage));\r
+        setIconSize();\r
         configureIcon();\r
-        [statusItem.get() button].image = statusIcon.get();\r
-    }\r
-\r
-    void setHighlighted (bool shouldHighlight)\r
-    {\r
-        [[statusItem.get() button] setHighlighted: shouldHighlight];\r
     }\r
 \r
     void showMenu (const PopupMenu& menu)\r
@@ -75,28 +68,64 @@ public:
             setHighlighted (true);\r
             stopTimer();\r
 \r
-            // There's currently no good alternative to this...\r
-           #if JUCE_CLANG && ! (defined (MAC_OS_X_VERSION_10_16) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_16)\r
-            #pragma clang diagnostic push\r
-            #pragma clang diagnostic ignored "-Wdeprecated-declarations"\r
-            #define JUCE_DEPRECATION_IGNORED 1\r
-           #endif\r
-\r
+            // There's currently no good alternative to this.\r
             [statusItem.get() popUpStatusItemMenu: m];\r
 \r
-           #if JUCE_DEPRECATION_IGNORED\r
-            #pragma clang diagnostic pop\r
-            #undef JUCE_DEPRECATION_IGNORED\r
-           #endif\r
-\r
             startTimer (1);\r
         }\r
     }\r
 \r
     //==============================================================================\r
-    NSStatusItem* getStatusItem()\r
+    void timerCallback() override\r
+    {\r
+        stopTimer();\r
+        setHighlighted (false);\r
+    }\r
+\r
+    //==============================================================================\r
+    SystemTrayIconComponent& owner;\r
+\r
+    std::unique_ptr<NSStatusItem, NSObjectDeleter> statusItem;\r
+    std::unique_ptr<NSImage, NSObjectDeleter> statusIcon;\r
+\r
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StatusItemContainer)\r
+};\r
+\r
+//==============================================================================\r
+struct ButtonBasedStatusItem   : public StatusItemContainer\r
+{\r
+    //==============================================================================\r
+    ButtonBasedStatusItem (SystemTrayIconComponent& iconComp, const Image& im)\r
+        : StatusItemContainer (iconComp, im)\r
+    {\r
+        static ButtonEventForwarderClass cls;\r
+        eventForwarder.reset ([cls.createInstance() init]);\r
+        ButtonEventForwarderClass::setOwner (eventForwarder.get(), this);\r
+\r
+        setIconSize();\r
+        configureIcon();\r
+\r
+        statusItem.reset ([[[NSStatusBar systemStatusBar] statusItemWithLength: NSSquareStatusItemLength] retain]);\r
+        auto button = [statusItem.get() button];\r
+        button.image = statusIcon.get();\r
+        button.target = eventForwarder.get();\r
+        button.action = @selector (handleEvent:);\r
+       #if defined (MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12\r
+        [button sendActionOn: NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown | NSEventMaskScrollWheel];\r
+       #else\r
+        [button sendActionOn: NSLeftMouseDownMask | NSRightMouseDownMask | NSScrollWheelMask];\r
+       #endif\r
+    }\r
+\r
+    void configureIcon() override\r
     {\r
-        return statusItem.get();\r
+        [statusIcon.get() setTemplate: true];\r
+        [statusItem.get() button].image = statusIcon.get();\r
+    }\r
+\r
+    void setHighlighted (bool shouldHighlight) override\r
+    {\r
+        [[statusItem.get() button] setHighlighted: shouldHighlight];\r
     }\r
 \r
     //==============================================================================\r
@@ -152,35 +181,21 @@ public:
         }\r
     }\r
 \r
-private:\r
-    //==============================================================================\r
-    void configureIcon()\r
-    {\r
-        [statusIcon.get() setSize: NSMakeSize (20.0f, 20.0f)];\r
-        [statusIcon.get() setTemplate: true];\r
-    }\r
-\r
-    void timerCallback() override\r
-    {\r
-        stopTimer();\r
-        setHighlighted (false);\r
-    }\r
-\r
     //==============================================================================\r
     class ButtonEventForwarderClass   : public ObjCClass<NSObject>\r
     {\r
     public:\r
         ButtonEventForwarderClass() : ObjCClass<NSObject> ("JUCEButtonEventForwarderClass_")\r
         {\r
-            addIvar<Pimpl*> ("owner");\r
+            addIvar<ButtonBasedStatusItem*> ("owner");\r
 \r
             addMethod (@selector (handleEvent:), handleEvent, "v@:@");\r
 \r
             registerClass();\r
         }\r
 \r
-        static Pimpl* getOwner (id self)                { return getIvar<Pimpl*> (self, "owner"); }\r
-        static void setOwner (id self, Pimpl* owner)    { object_setInstanceVariable (self, "owner", owner); }\r
+        static ButtonBasedStatusItem* getOwner (id self)               { return getIvar<ButtonBasedStatusItem*> (self, "owner"); }\r
+        static void setOwner (id self, ButtonBasedStatusItem* owner)   { object_setInstanceVariable (self, "owner", owner); }\r
 \r
     private:\r
         static void handleEvent (id self, SEL, id)\r
@@ -191,14 +206,190 @@ private:
     };\r
 \r
     //==============================================================================\r
-    SystemTrayIconComponent& owner;\r
-    std::unique_ptr<NSStatusItem, NSObjectDeleter> statusItem;\r
     std::unique_ptr<NSObject, NSObjectDeleter> eventForwarder;\r
-    std::unique_ptr<NSImage, NSObjectDeleter> statusIcon;\r
+};\r
 \r
-    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)\r
+//==============================================================================\r
+struct ViewBasedStatusItem   : public StatusItemContainer\r
+{\r
+    //==============================================================================\r
+    ViewBasedStatusItem (SystemTrayIconComponent& iconComp, const Image& im)\r
+        : StatusItemContainer (iconComp, im)\r
+    {\r
+        static SystemTrayViewClass cls;\r
+        view.reset ([cls.createInstance() init]);\r
+        SystemTrayViewClass::setOwner (view.get(), this);\r
+        SystemTrayViewClass::setImage (view.get(), statusIcon.get());\r
+\r
+        setIconSize();\r
+\r
+        statusItem.reset ([[[NSStatusBar systemStatusBar] statusItemWithLength: NSSquareStatusItemLength] retain]);\r
+        [statusItem.get() setView: view.get()];\r
+\r
+        SystemTrayViewClass::frameChanged (view.get(), SEL(), nullptr);\r
+\r
+        [[NSNotificationCenter defaultCenter]  addObserver: view.get()\r
+                                                  selector: @selector (frameChanged:)\r
+                                                      name: NSWindowDidMoveNotification\r
+                                                    object: nil];\r
+    }\r
+\r
+    ~ViewBasedStatusItem() override\r
+    {\r
+        [[NSNotificationCenter defaultCenter] removeObserver: view.get()];\r
+        [[NSStatusBar systemStatusBar] removeStatusItem: statusItem.get()];\r
+        SystemTrayViewClass::setOwner (view.get(), nullptr);\r
+        SystemTrayViewClass::setImage (view.get(), nil);\r
+    }\r
+\r
+    void configureIcon() override\r
+    {\r
+        SystemTrayViewClass::setImage (view.get(), statusIcon.get());\r
+        [statusItem.get() setView: view.get()];\r
+    }\r
+\r
+    void setHighlighted (bool shouldHighlight) override\r
+    {\r
+        isHighlighted = shouldHighlight;\r
+        [view.get() setNeedsDisplay: true];\r
+    }\r
+\r
+    //==============================================================================\r
+    void handleStatusItemAction (NSEvent* e)\r
+    {\r
+        NSEventType type = [e type];\r
+\r
+        const bool isLeft  = (type == NSEventTypeLeftMouseDown  || type == NSEventTypeLeftMouseUp);\r
+        const bool isRight = (type == NSEventTypeRightMouseDown || type == NSEventTypeRightMouseUp);\r
+\r
+        if (owner.isCurrentlyBlockedByAnotherModalComponent())\r
+        {\r
+            if (isLeft || isRight)\r
+                if (auto* current = Component::getCurrentlyModalComponent())\r
+                    current->inputAttemptWhenModal();\r
+        }\r
+        else\r
+        {\r
+            auto eventMods = ComponentPeer::getCurrentModifiersRealtime();\r
+\r
+            if (([e modifierFlags] & NSEventModifierFlagCommand) != 0)\r
+                eventMods = eventMods.withFlags (ModifierKeys::commandModifier);\r
+\r
+            auto now = Time::getCurrentTime();\r
+            auto mouseSource = Desktop::getInstance().getMainMouseSource();\r
+            auto pressure = (float) e.pressure;\r
+\r
+            if (isLeft || isRight)  // Only mouse up is sent by the OS, so simulate a down/up\r
+            {\r
+                setHighlighted (true);\r
+                startTimer (150);\r
+\r
+                owner.mouseDown (MouseEvent (mouseSource, {},\r
+                                             eventMods.withFlags (isLeft ? ModifierKeys::leftButtonModifier\r
+                                                                         : ModifierKeys::rightButtonModifier),\r
+                                             pressure, MouseInputSource::invalidOrientation, MouseInputSource::invalidRotation,\r
+                                             MouseInputSource::invalidTiltX, MouseInputSource::invalidTiltY,\r
+                                             &owner, &owner, now, {}, now, 1, false));\r
+\r
+                owner.mouseUp (MouseEvent (mouseSource, {}, eventMods.withoutMouseButtons(), pressure,\r
+                                           MouseInputSource::invalidOrientation, MouseInputSource::invalidRotation,\r
+                                           MouseInputSource::invalidTiltX, MouseInputSource::invalidTiltY,\r
+                                           &owner, &owner, now, {}, now, 1, false));\r
+            }\r
+            else if (type == NSEventTypeMouseMoved)\r
+            {\r
+                owner.mouseMove (MouseEvent (mouseSource, {}, eventMods, pressure,\r
+                                             MouseInputSource::invalidOrientation, MouseInputSource::invalidRotation,\r
+                                             MouseInputSource::invalidTiltX, MouseInputSource::invalidTiltY,\r
+                                             &owner, &owner, now, {}, now, 1, false));\r
+            }\r
+        }\r
+    }\r
+\r
+    //==============================================================================\r
+    struct SystemTrayViewClass : public ObjCClass<NSControl>\r
+    {\r
+        SystemTrayViewClass()  : ObjCClass<NSControl> ("JUCESystemTrayView_")\r
+        {\r
+            addIvar<ViewBasedStatusItem*> ("owner");\r
+            addIvar<NSImage*> ("image");\r
+\r
+            addMethod (@selector (mouseDown:),      handleEventDown, "v@:@");\r
+            addMethod (@selector (rightMouseDown:), handleEventDown, "v@:@");\r
+            addMethod (@selector (drawRect:),       drawRect,        "v@:@");\r
+            addMethod (@selector (frameChanged:),   frameChanged,    "v@:@");\r
+\r
+            registerClass();\r
+        }\r
+\r
+        static ViewBasedStatusItem* getOwner (id self)               { return getIvar<ViewBasedStatusItem*> (self, "owner"); }\r
+        static NSImage* getImage (id self)                           { return getIvar<NSImage*> (self, "image"); }\r
+        static void setOwner (id self, ViewBasedStatusItem* owner)   { object_setInstanceVariable (self, "owner", owner); }\r
+        static void setImage (id self, NSImage* image)               { object_setInstanceVariable (self, "image", image); }\r
+\r
+        static void frameChanged (id self, SEL, NSNotification*)\r
+        {\r
+            if (auto* owner = getOwner (self))\r
+            {\r
+                NSRect r = [[[owner->statusItem.get() view] window] frame];\r
+                NSRect sr = [[[NSScreen screens] objectAtIndex: 0] frame];\r
+                r.origin.y = sr.size.height - r.origin.y - r.size.height;\r
+                owner->owner.setBounds (convertToRectInt (r));\r
+            }\r
+        }\r
+\r
+    private:\r
+        static void handleEventDown (id self, SEL, NSEvent* e)\r
+        {\r
+            if (auto* owner = getOwner (self))\r
+                owner->handleStatusItemAction (e);\r
+        }\r
+\r
+        static void drawRect (id self, SEL, NSRect)\r
+        {\r
+            NSRect bounds = [self bounds];\r
+\r
+            if (auto* owner = getOwner (self))\r
+                [owner->statusItem.get() drawStatusBarBackgroundInRect: bounds\r
+                                                         withHighlight: owner->isHighlighted];\r
+\r
+            if (NSImage* const im = getImage (self))\r
+            {\r
+                NSSize imageSize = [im size];\r
+\r
+                [im drawInRect: NSMakeRect (bounds.origin.x + ((bounds.size.width  - imageSize.width)  / 2.0f),\r
+                                            bounds.origin.y + ((bounds.size.height - imageSize.height) / 2.0f),\r
+                                            imageSize.width, imageSize.height)\r
+                      fromRect: NSZeroRect\r
+                     operation: NSCompositingOperationSourceOver\r
+                      fraction: 1.0f];\r
+            }\r
+        }\r
+    };\r
+\r
+    //==============================================================================\r
+    std::unique_ptr<NSControl, NSObjectDeleter> view;\r
+    bool isHighlighted = false;\r
 };\r
 \r
+//==============================================================================\r
+class SystemTrayIconComponent::Pimpl\r
+{\r
+public:\r
+    //==============================================================================\r
+    Pimpl (SystemTrayIconComponent& iconComp, const Image& im)\r
+    {\r
+        if (std::floor (NSFoundationVersionNumber) > NSFoundationVersionNumber10_10)\r
+            statusItemHolder = std::make_unique<ButtonBasedStatusItem> (iconComp, im);\r
+        else\r
+            statusItemHolder = std::make_unique<ViewBasedStatusItem> (iconComp, im);\r
+    }\r
+\r
+    //==============================================================================\r
+    std::unique_ptr<StatusItemContainer> statusItemHolder;\r
+\r
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)\r
+};\r
 \r
 //==============================================================================\r
 void SystemTrayIconComponent::setIconImage (const Image&, const Image& templateImage)\r
@@ -208,7 +399,7 @@ void SystemTrayIconComponent::setIconImage (const Image&, const Image& templateI
         if (pimpl == nullptr)\r
             pimpl.reset (new Pimpl (*this, templateImage));\r
         else\r
-            pimpl->updateIcon (templateImage);\r
+            pimpl->statusItemHolder->updateIcon (templateImage);\r
     }\r
     else\r
     {\r
@@ -221,10 +412,10 @@ void SystemTrayIconComponent::setIconTooltip (const String&)
     // xxx not yet implemented!\r
 }\r
 \r
-void SystemTrayIconComponent::setHighlighted (bool highlight)\r
+void SystemTrayIconComponent::setHighlighted (bool shouldHighlight)\r
 {\r
     if (pimpl != nullptr)\r
-        pimpl->setHighlighted (highlight);\r
+        pimpl->statusItemHolder->setHighlighted (shouldHighlight);\r
 }\r
 \r
 void SystemTrayIconComponent::showInfoBubble (const String& /*title*/, const String& /*content*/)\r
@@ -239,13 +430,15 @@ void SystemTrayIconComponent::hideInfoBubble()
 \r
 void* SystemTrayIconComponent::getNativeHandle() const\r
 {\r
-    return pimpl != nullptr ? pimpl->getStatusItem() : nullptr;\r
+    return pimpl != nullptr ? pimpl->statusItemHolder->statusItem.get() : nullptr;\r
 }\r
 \r
 void SystemTrayIconComponent::showDropdownMenu (const PopupMenu& menu)\r
 {\r
     if (pimpl != nullptr)\r
-        pimpl->showMenu (menu);\r
+        pimpl->statusItemHolder->showMenu (menu);\r
 }\r
 \r
+#pragma clang diagnostic pop\r
+\r
 } // namespace juce\r
index e9910736cb62a7a79dc44313c251db6b9c4541ff..afdc0b634a018e2419193fb45f5ee6c7c03c780f 100644 (file)
@@ -87,8 +87,6 @@ public:
     {\r
         if (browser != nullptr)\r
         {\r
-            LPSAFEARRAY sa = nullptr;\r
-\r
             VARIANT headerFlags, frame, postDataVar, headersVar;  // (_variant_t isn't available in all compilers)\r
             VariantInit (&headerFlags);\r
             VariantInit (&frame);\r
@@ -103,7 +101,7 @@ public:
 \r
             if (postData != nullptr && postData->getSize() > 0)\r
             {\r
-                sa = SafeArrayCreateVector (VT_UI1, 0, (ULONG) postData->getSize());\r
+                auto sa = SafeArrayCreateVector (VT_UI1, 0, (ULONG) postData->getSize());\r
 \r
                 if (sa != nullptr)\r
                 {\r
@@ -121,8 +119,13 @@ public:
                         V_VT (&postDataVar2) = VT_ARRAY | VT_UI1;\r
                         V_ARRAY (&postDataVar2) = sa;\r
 \r
+                        sa = nullptr;\r
                         postDataVar = postDataVar2;\r
                     }\r
+                    else\r
+                    {\r
+                        SafeArrayDestroy (sa);\r
+                    }\r
                 }\r
             }\r
 \r
@@ -130,9 +133,6 @@ public:
             browser->Navigate (urlBSTR, &headerFlags, &frame, &postDataVar, &headersVar);\r
             SysFreeString (urlBSTR);\r
 \r
-            if (sa != nullptr)\r
-                SafeArrayDestroy (sa);\r
-\r
             VariantClear (&headerFlags);\r
             VariantClear (&frame);\r
             VariantClear (&postDataVar);\r
@@ -187,7 +187,7 @@ private:
                 *pDispParams->rgvarg[0].pboolVal = VARIANT_FALSE;\r
 \r
                 // IWebBrowser2 also reports http status codes here, we need\r
-                // report only network erros\r
+                // report only network errors\r
                 if (statusCode < 0)\r
                 {\r
                     LPTSTR messageBuffer = nullptr;\r
index 19f67c98c3e8209211b0708b952dc5666745b52b..97e73b1ffba43271d1e9895e3fae120f90f432db 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_opengl\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE OpenGL classes\r
-  description:      Classes for rendering OpenGL in a JUCE window.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
-\r
-  dependencies:     juce_gui_extra\r
-  OSXFrameworks:    OpenGL\r
-  iOSFrameworks:    OpenGLES\r
-  linuxLibs:        GL\r
-  mingwLibs:        opengl32\r
+  ID:                 juce_opengl\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE OpenGL classes\r
+  description:        Classes for rendering OpenGL in a JUCE window.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
+\r
+  dependencies:       juce_gui_extra\r
+  OSXFrameworks:      OpenGL\r
+  iOSFrameworks:      OpenGLES\r
+  linuxLibs:          GL\r
+  mingwLibs:          opengl32\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 24a849b967224fecf43004ce9118159ab0019284..c4fb799ca366667301252b9b665423145bd54b51 100644 (file)
@@ -89,7 +89,7 @@ public:
                 if (context != nil)\r
                 {\r
                     // I'd prefer to put this stuff in the initialiseOnRenderThread() call, but doing\r
-                    // so causes myserious timing-related failures.\r
+                    // so causes mysterious timing-related failures.\r
                     [EAGLContext setCurrentContext: context];\r
                     createGLBuffers();\r
                     deactivateCurrentContext();\r
index 9850c1154af6fdbddc39e0992db23225373ba5be..b6257456be4a3dda5b8387b697b1c0eb35871a83 100644 (file)
@@ -105,7 +105,7 @@ public:
         if (renderThread != nullptr)\r
         {\r
             // make sure everything has finished executing\r
-            destroying.set (1);\r
+            destroying = true;\r
 \r
             if (workQueue.size() > 0)\r
             {\r
@@ -142,6 +142,16 @@ public:
             renderThread->addJob (this, false);\r
     }\r
 \r
+   #if JUCE_MAC\r
+    static CVReturn displayLinkCallback (CVDisplayLinkRef, const CVTimeStamp*, const CVTimeStamp*,\r
+                                         CVOptionFlags, CVOptionFlags*, void* displayLinkContext)\r
+    {\r
+        auto* self = (CachedImage*) displayLinkContext;\r
+        self->renderFrame();\r
+        return kCVReturnSuccess;\r
+    }\r
+   #endif\r
+\r
     //==============================================================================\r
     void paint (Graphics&) override\r
     {\r
@@ -214,7 +224,9 @@ public:
     bool renderFrame()\r
     {\r
         MessageManager::Lock::ScopedTryLockType mmLock (messageManagerLock, false);\r
-        const bool isUpdating = needsUpdate.compareAndSetBool (0, 1);\r
+\r
+        auto isUpdatingTestValue = true;\r
+        auto isUpdating = needsUpdate.compare_exchange_strong (isUpdatingTestValue, false);\r
 \r
         if (context.renderComponents && isUpdating)\r
         {\r
@@ -464,10 +476,14 @@ public:
             if (shouldExit())\r
                 break;\r
 \r
+           #if JUCE_MAC\r
+            repaintEvent.wait (1000);\r
+           #else\r
             if (! renderFrame())\r
                 repaintEvent.wait (5); // failed to render, so avoid a tight fail-loop.\r
             else if (! context.continuousRepaint && ! shouldExit())\r
                 repaintEvent.wait (-1);\r
+           #endif\r
         }\r
 \r
         hasInitialised = false;\r
@@ -519,11 +535,22 @@ public:
         if (context.renderer != nullptr)\r
             context.renderer->newOpenGLContextCreated();\r
 \r
+       #if JUCE_MAC\r
+        CVDisplayLinkCreateWithActiveCGDisplays (&displayLink);\r
+        CVDisplayLinkSetOutputCallback (displayLink, &displayLinkCallback, this);\r
+        CVDisplayLinkStart (displayLink);\r
+       #endif\r
+\r
         return true;\r
     }\r
 \r
     void shutdownOnThread()\r
     {\r
+       #if JUCE_MAC\r
+        CVDisplayLinkStop (displayLink);\r
+        CVDisplayLinkRelease (displayLink);\r
+       #endif\r
+\r
         if (context.renderer != nullptr)\r
             context.renderer->openGLContextClosing();\r
 \r
@@ -588,7 +615,7 @@ public:
 \r
     void execute (OpenGLContext::AsyncWorker::Ptr workerToUse, bool shouldBlock, bool calledFromDestructor = false)\r
     {\r
-        if (calledFromDestructor || destroying.get() == 0)\r
+        if (calledFromDestructor || ! destroying)\r
         {\r
             if (shouldBlock)\r
             {\r
@@ -646,10 +673,12 @@ public:
    #else\r
     bool shadersAvailable = false;\r
    #endif\r
-    bool hasInitialised = false;\r
-    Atomic<int> needsUpdate { 1 }, destroying;\r
+    std::atomic<bool> hasInitialised { false }, needsUpdate { true }, destroying { false };\r
     uint32 lastMMLockReleaseTime = 0;\r
 \r
+   #if JUCE_MAC\r
+    CVDisplayLinkRef displayLink;\r
+   #endif\r
     std::unique_ptr<ThreadPool> renderThread;\r
     ReferenceCountedArray<OpenGLContext::AsyncWorker, CriticalSection> workQueue;\r
     MessageManager::Lock messageManagerLock;\r
index a6871e80e4684add4253be79f9716341ee99c906..c3fda19a63082be5d039cb9aec747d8515a4cb18 100644 (file)
@@ -248,7 +248,7 @@ public:
         This function can only be called if the context is attached to a component.\r
         Otherwise, this function will assert.\r
 \r
-        This function is useful when you need to excute house-keeping tasks such\r
+        This function is useful when you need to execute house-keeping tasks such\r
         as allocating, deallocating textures or framebuffers. As such, the functor\r
         will execute without locking the message thread. Therefore, it is not\r
         intended for any drawing commands or GUI code. Any GUI code should be\r
@@ -273,7 +273,7 @@ public:
     */\r
     unsigned int getFrameBufferID() const noexcept;\r
 \r
-    /** Returns an OS-dependent handle to some kind of underlting OS-provided GL context.\r
+    /** Returns an OS-dependent handle to some kind of underlying OS-provided GL context.\r
 \r
         The exact type of the value returned will depend on the OS and may change\r
         if the implementation changes. If you want to use this, digging around in the\r
index e4edc3d90eb63c6f0577406d98de30e9173eace7..a6d75eae882d7b0c868f70548341c5bd2d25127c 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_osc\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE OSC classes\r
-  description:      Open Sound Control implementation.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
+  ID:                 juce_osc\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE OSC classes\r
+  description:        Open Sound Control implementation.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
 \r
-  dependencies:     juce_core, juce_events\r
+  dependencies:       juce_core, juce_events\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 542bf938297dc15d60564ee586137805fb6343e6..e24f2d5eab1e6e1503c938bfea93c904b4d89fde 100644 (file)
@@ -130,7 +130,7 @@ public:
     bool matches (const OSCAddress& address) const noexcept;\r
 \r
     /** Checks whether the OSCAddressPattern contains any of the allowed OSC\r
-        address patttern wildcards: ?, *, [], {}\r
+        address pattern wildcards: ?, *, [], {}\r
 \r
         @returns true if the OSCAddressPattern contains OSC wildcards, false otherwise.\r
     */\r
index 29a5a0377b6c1eb5cb9bf90bf8f31995ccedb64a..a1e0d3b60d926fad57704a201331987b6d48e255 100644 (file)
@@ -70,7 +70,7 @@ public:
     */\r
     Time toTime() const noexcept;\r
 \r
-    /** Returns true if the OSCTimeTag object has the special value representing "immedately". */\r
+    /** Returns true if the OSCTimeTag object has the special value representing "immediately". */\r
     bool isImmediately() const noexcept;\r
 \r
     /** Returns the raw binary OSC time tag representation. */\r
index ca53510a076aaf634fe0a02c7f7fc41fd19fa6ff..8609cd58ee10a172a5a041e3cef58c706a80f201 100644 (file)
@@ -61,13 +61,11 @@ void InAppPurchases::getProductsInformation (const StringArray& productIdentifie
 }\r
 \r
 void InAppPurchases::purchaseProduct (const String& productIdentifier,\r
-                                      bool isSubscription,\r
-                                      const StringArray& upgradeProductIdentifiers,\r
+                                      const String& upgradeProductIdentifier,\r
                                       bool creditForUnusedSubscription)\r
 {\r
    #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC\r
-    pimpl->purchaseProduct (productIdentifier, isSubscription,\r
-                            upgradeProductIdentifiers, creditForUnusedSubscription);\r
+    pimpl->purchaseProduct (productIdentifier, upgradeProductIdentifier, creditForUnusedSubscription);\r
    #else\r
     Listener::PurchaseInfo purchaseInfo { Purchase { "", productIdentifier, {}, {}, {} }, {} };\r
 \r
index e2bd100c2f5d4a9fe77fa73949884a2da2ae6269..38d2176768fa1c53119ae5834ee0b6e58f8ce2ad 100644 (file)
@@ -200,19 +200,15 @@ public:
 \r
         @param productIdentifier               The product identifier.\r
 \r
-        @param isSubscription                  (Android only) defines if a product a user wants to buy is a subscription or a one-time purchase.\r
-                                               On iOS, type of the product is derived implicitly.\r
-\r
-        @param upgradeOrDowngradeFromSubscriptionsWithProductIdentifiers (Android only) specifies subscriptions that will be replaced by the\r
-                                                                         one being purchased now. Used only when buying a subscription\r
-                                                                         that is an upgrade or downgrade from other ones.\r
+        @param upgradeOrDowngradeFromSubscriptionsWithProductIdentifier (Android only) specifies the subscription that will be replaced by\r
+                                                                        the one being purchased now. Used only when buying a subscription\r
+                                                                        that is an upgrade or downgrade from another.\r
 \r
         @param creditForUnusedSubscription     (Android only) controls whether a user should be credited for any unused subscription time on\r
-                                               the products that are being upgraded or downgraded.\r
+                                               the product that is being upgraded or downgraded.\r
     */\r
     void purchaseProduct (const String& productIdentifier,\r
-                          bool isSubscription,\r
-                          const StringArray& upgradeOrDowngradeFromSubscriptionsWithProductIdentifiers = {},\r
+                          const String& upgradeOrDowngradeFromSubscriptionWithProductIdentifier = {},\r
                           bool creditForUnusedSubscription = true);\r
 \r
     /** Asynchronously asks about a list of products that a user has already bought. Upon completion, Listener::purchasesListReceived()\r
@@ -260,6 +256,22 @@ public:
     /** iOS only: Cancels downloads of hosted content from the store. */\r
     void cancelDownloads (const Array<Download*>& downloads);\r
 \r
+    //==============================================================================\r
+    // On Android, it is no longer necessary to specify whether the product being purchased is a subscription\r
+    // and only a single subscription can be upgraded/downgraded. Use the updated purchaseProduct() method\r
+    // which takes a single String argument.\r
+    JUCE_DEPRECATED_WITH_BODY (void purchaseProduct (const String& productIdentifier,\r
+                                                     bool isSubscription,\r
+                                                     const StringArray& upgradeOrDowngradeFromSubscriptionsWithProductIdentifiers = {},\r
+                                                     bool creditForUnusedSubscription = true),\r
+                               {\r
+\r
+                                   ignoreUnused (isSubscription);\r
+                                   purchaseProduct (productIdentifier,\r
+                                                    upgradeOrDowngradeFromSubscriptionsWithProductIdentifiers[0],\r
+                                                    creditForUnusedSubscription);\r
+                               })\r
+\r
 private:\r
     //==============================================================================\r
    #ifndef DOXYGEN\r
index 35033642d843a2aa8d80b5b29fec39422cbe71b1..4cd5270b134471e23cb1cb5409a3db40230733b9 100644 (file)
@@ -24,6 +24,7 @@
   ==============================================================================\r
 */\r
 \r
+\r
 /*******************************************************************************\r
  The block below describes the properties of this module, and is read by\r
  the Projucer to automatically generate project code that uses it.\r
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_product_unlocking\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE Online marketplace support\r
-  description:      Classes for online product authentication\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
+  ID:                 juce_product_unlocking\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE Online marketplace support\r
+  description:        Classes for online product authentication\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
 \r
-  dependencies:     juce_cryptography juce_core\r
+  dependencies:       juce_cryptography juce_core, juce_events\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
@@ -68,6 +69,7 @@
 //==============================================================================\r
 #include <juce_core/juce_core.h>\r
 #include <juce_cryptography/juce_cryptography.h>\r
+#include <juce_events/juce_events.h>\r
 \r
 #if JUCE_MODULE_AVAILABLE_juce_data_structures\r
  #include <juce_data_structures/juce_data_structures.h>\r
index b3b3d7c0f2cfe6b7dd305be7f7b4cc3d5560ce6a..33a677f74446cc5ef1b2d98ca33eb98e42485ae0 100644 (file)
@@ -27,7 +27,7 @@
 namespace juce\r
 {\r
 \r
-/** Acts as a GUI which asks the user for their details, and calls the approriate\r
+/** Acts as a GUI which asks the user for their details, and calls the appropriate\r
     methods on your OnlineUnlockStatus object to attempt to register the app.\r
 \r
     You should create one of these components and add it to your parent window,\r
diff --git a/modules/juce_product_unlocking/native/javaopt/app/com/roli/juce/JuceBillingClient.java b/modules/juce_product_unlocking/native/javaopt/app/com/roli/juce/JuceBillingClient.java
new file mode 100644 (file)
index 0000000..ad63f5b
--- /dev/null
@@ -0,0 +1,173 @@
+package com.roli.juce;\r
+\r
+import com.android.billingclient.api.*;\r
+\r
+public class JuceBillingClient implements PurchasesUpdatedListener {\r
+    private native void skuDetailsQueryCallback(long host, java.util.List<SkuDetails> skuDetails);\r
+    private native void purchasesListQueryCallback(long host, java.util.List<Purchase> purchases);\r
+    private native void purchaseCompletedCallback(long host, Purchase purchase, int responseCode);\r
+    private native void purchaseConsumedCallback(long host, String productIdentifier, int responseCode);\r
+\r
+    public JuceBillingClient(android.content.Context context, long hostToUse) {\r
+        host = hostToUse;\r
+\r
+        billingClient = BillingClient.newBuilder(context)\r
+                .enablePendingPurchases()\r
+                .setListener(this)\r
+                .build();\r
+\r
+        billingClient.startConnection(null);\r
+    }\r
+\r
+    public void endConnection() {\r
+        billingClient.endConnection();\r
+    }\r
+\r
+    public boolean isReady() {\r
+        return billingClient.isReady();\r
+    }\r
+\r
+    public boolean isBillingSupported() {\r
+        return billingClient.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS).getResponseCode()\r
+                == BillingClient.BillingResponseCode.OK;\r
+    }\r
+\r
+    public void querySkuDetails(final String[] skusToQuery) {\r
+        executeOnBillingClientConnection(new Runnable() {\r
+            @Override\r
+            public void run() {\r
+                final java.util.List<String> skuList = java.util.Arrays.asList(skusToQuery);\r
+\r
+                SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder()\r
+                        .setSkusList(skuList)\r
+                        .setType(BillingClient.SkuType.INAPP);\r
+\r
+                billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {\r
+                    @Override\r
+                    public void onSkuDetailsResponse(BillingResult billingResult, final java.util.List<SkuDetails> inAppSkuDetails) {\r
+                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {\r
+                            SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder()\r
+                                    .setSkusList(skuList)\r
+                                    .setType(BillingClient.SkuType.SUBS);\r
+\r
+                            billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {\r
+                                @Override\r
+                                public void onSkuDetailsResponse(BillingResult billingResult, java.util.List<SkuDetails> subsSkuDetails) {\r
+                                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {\r
+                                        subsSkuDetails.addAll(inAppSkuDetails);\r
+                                        skuDetailsQueryCallback(host, subsSkuDetails);\r
+                                    }\r
+                                }\r
+                            });\r
+                        }\r
+                    }\r
+                });\r
+            }\r
+        });\r
+    }\r
+\r
+    public void launchBillingFlow(final android.app.Activity activity, final BillingFlowParams params) {\r
+        executeOnBillingClientConnection(new Runnable() {\r
+            @Override\r
+            public void run() {\r
+                BillingResult r = billingClient.launchBillingFlow(activity, params);\r
+            }\r
+        });\r
+    }\r
+\r
+    public void queryPurchases() {\r
+        executeOnBillingClientConnection(new Runnable() {\r
+            @Override\r
+            public void run() {\r
+                Purchase.PurchasesResult inAppPurchases = billingClient.queryPurchases(BillingClient.SkuType.INAPP);\r
+                Purchase.PurchasesResult subsPurchases = billingClient.queryPurchases(BillingClient.SkuType.SUBS);\r
+\r
+                if (inAppPurchases.getResponseCode() == BillingClient.BillingResponseCode.OK\r
+                        && subsPurchases.getResponseCode() == BillingClient.BillingResponseCode.OK) {\r
+                    java.util.List<Purchase> purchaseList = inAppPurchases.getPurchasesList();\r
+                    purchaseList.addAll(subsPurchases.getPurchasesList());\r
+\r
+                    purchasesListQueryCallback(host, purchaseList);\r
+                    return;\r
+                }\r
+\r
+                purchasesListQueryCallback(host, null);\r
+            }\r
+        });\r
+    }\r
+\r
+    public void consumePurchase(final String productIdentifier, final String purchaseToken) {\r
+        executeOnBillingClientConnection(new Runnable() {\r
+            @Override\r
+            public void run() {\r
+                ConsumeParams consumeParams = ConsumeParams.newBuilder()\r
+                        .setPurchaseToken(purchaseToken)\r
+                        .build();\r
+\r
+                billingClient.consumeAsync(consumeParams, new ConsumeResponseListener() {\r
+                    @Override\r
+                    public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {\r
+                        purchaseConsumedCallback(host, productIdentifier, billingResult.getResponseCode());\r
+                    }\r
+                });\r
+            }\r
+        });\r
+    }\r
+\r
+    @Override\r
+    public void onPurchasesUpdated(BillingResult result, java.util.List<Purchase> purchases) {\r
+        int responseCode = result.getResponseCode();\r
+\r
+        if (purchases != null) {\r
+            for (Purchase purchase : purchases) {\r
+                handlePurchase(purchase, responseCode);\r
+            }\r
+        } else {\r
+            purchaseCompletedCallback(host, null, responseCode);\r
+        }\r
+    }\r
+\r
+    private void executeOnBillingClientConnection(Runnable runnable) {\r
+        if (billingClient.isReady()) {\r
+            runnable.run();\r
+        } else {\r
+            connectAndExecute(runnable);\r
+        }\r
+    }\r
+\r
+    private void connectAndExecute(final Runnable executeOnSuccess) {\r
+        billingClient.startConnection(new BillingClientStateListener() {\r
+            @Override\r
+            public void onBillingSetupFinished(BillingResult billingResponse) {\r
+                if (billingResponse.getResponseCode() == BillingClient.BillingResponseCode.OK) {\r
+                    if (executeOnSuccess != null) {\r
+                        executeOnSuccess.run();\r
+                    }\r
+                }\r
+            }\r
+\r
+            @Override\r
+            public void onBillingServiceDisconnected() {\r
+            }\r
+        });\r
+    }\r
+\r
+    private void handlePurchase(final Purchase purchase, final int responseCode) {\r
+        purchaseCompletedCallback(host, purchase, responseCode);\r
+\r
+        if (responseCode == BillingClient.BillingResponseCode.OK\r
+                && purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED\r
+                && !purchase.isAcknowledged()) {\r
+            executeOnBillingClientConnection(new Runnable() {\r
+                @Override\r
+                public void run() {\r
+                    AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();\r
+                    billingClient.acknowledgePurchase(acknowledgePurchaseParams, null);\r
+                }\r
+            });\r
+        }\r
+    }\r
+\r
+    private long host = 0;\r
+    private BillingClient billingClient;\r
+}\r
index 9dbb5d032dbefb67a235e7eeb229155a381d5f42..9d2ee8ac33f4e2c0ac4a0f58286523f102c21310 100644 (file)
@@ -28,830 +28,495 @@ namespace juce
 {\r
 \r
 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
-    METHOD (isBillingSupported,      "isBillingSupported",      "(ILjava/lang/String;Ljava/lang/String;)I") \\r
-    METHOD (getSkuDetails,           "getSkuDetails",           "(ILjava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;") \\r
-    METHOD (getBuyIntent,            "getBuyIntent",            "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/os/Bundle;") \\r
-    METHOD (getBuyIntentExtraParams, "getBuyIntentExtraParams", "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;") \\r
-    METHOD (getPurchases,            "getPurchases",            "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/os/Bundle;") \\r
-    METHOD (consumePurchase,         "consumePurchase",         "(ILjava/lang/String;Ljava/lang/String;)I") \\r
-    METHOD (getPurchaseHistory,      "getPurchaseHistory",      "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Bundle;)Landroid/os/Bundle;")\r
-\r
-DECLARE_JNI_CLASS (IInAppBillingService, "com/android/vending/billing/IInAppBillingService")\r
+  METHOD (getSku,               "getSku",               "()Ljava/lang/String;") \\r
+  METHOD (getTitle,             "getTitle",             "()Ljava/lang/String;") \\r
+  METHOD (getDescription,       "getDescription",       "()Ljava/lang/String;") \\r
+  METHOD (getPrice,             "getPrice",             "()Ljava/lang/String;") \\r
+  METHOD (getPriceCurrencyCode, "getPriceCurrencyCode", "()Ljava/lang/String;")\r
+\r
+DECLARE_JNI_CLASS (SkuDetails, "com/android/billingclient/api/SkuDetails")\r
 #undef JNI_CLASS_MEMBERS\r
 \r
 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
-    STATICMETHOD (asInterface,      "asInterface",      "(Landroid/os/IBinder;)Lcom/android/vending/billing/IInAppBillingService;") \\r
+  STATICMETHOD (newBuilder, "newBuilder", "()Lcom/android/billingclient/api/BillingFlowParams$Builder;")\r
 \r
-DECLARE_JNI_CLASS (IInAppBillingServiceStub, "com/android/vending/billing/IInAppBillingService$Stub")\r
+DECLARE_JNI_CLASS (BillingFlowParams, "com/android/billingclient/api/BillingFlowParams")\r
 #undef JNI_CLASS_MEMBERS\r
 \r
-//==============================================================================\r
-struct ServiceConnection  : public AndroidInterfaceImplementer\r
-{\r
-    virtual void onServiceConnected    (jobject component, jobject iBinder) = 0;\r
-    virtual void onServiceDisconnected (jobject component) = 0;\r
-\r
-    jobject invoke (jobject proxy, jobject method, jobjectArray args) override\r
-    {\r
-        auto* env = getEnv();\r
-        auto methodName = juceString ((jstring) env->CallObjectMethod (method, JavaMethod.getName));\r
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
+  METHOD (build,                       "build",                       "()Lcom/android/billingclient/api/BillingFlowParams;")                                             \\r
+  METHOD (setOldSku,                   "setOldSku",                   "(Ljava/lang/String;Ljava/lang/String;)Lcom/android/billingclient/api/BillingFlowParams$Builder;") \\r
+  METHOD (setReplaceSkusProrationMode, "setReplaceSkusProrationMode", "(I)Lcom/android/billingclient/api/BillingFlowParams$Builder;")                                    \\r
+  METHOD (setSkuDetails,               "setSkuDetails",               "(Lcom/android/billingclient/api/SkuDetails;)Lcom/android/billingclient/api/BillingFlowParams$Builder;")\r
 \r
-        if (methodName == "onServiceConnected")\r
-        {\r
-            onServiceConnected (env->GetObjectArrayElement (args, 0),\r
-                                env->GetObjectArrayElement (args, 1));\r
-            return nullptr;\r
-        }\r
+DECLARE_JNI_CLASS (BillingFlowParamsBuilder, "com/android/billingclient/api/BillingFlowParams$Builder")\r
+#undef JNI_CLASS_MEMBERS\r
 \r
-        if (methodName == "onServiceDisconnected")\r
-        {\r
-            onServiceDisconnected (env->GetObjectArrayElement (args, 0));\r
-            return nullptr;\r
-        }\r
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
+  METHOD (getOrderId,       "getOrderId",       "()Ljava/lang/String;") \\r
+  METHOD (getSku,           "getSku",           "()Ljava/lang/String;") \\r
+  METHOD (getPackageName,   "getPackageName",   "()Ljava/lang/String;") \\r
+  METHOD (getPurchaseTime,  "getPurchaseTime",  "()J")                  \\r
+  METHOD (getPurchaseToken, "getPurchaseToken", "()Ljava/lang/String;")\r
 \r
-        return AndroidInterfaceImplementer::invoke (proxy, method, args);\r
-    }\r
-};\r
+DECLARE_JNI_CLASS (AndroidPurchase, "com/android/billingclient/api/Purchase")\r
+#undef JNI_CLASS_MEMBERS\r
 \r
 //==============================================================================\r
-struct InAppPurchases::Pimpl    : private AsyncUpdater,\r
-                                  private ServiceConnection\r
+struct InAppPurchases::Pimpl\r
 {\r
-    Pimpl (InAppPurchases& parent)  : owner (parent)\r
+    Pimpl (InAppPurchases& parent)\r
+        : owner (parent),\r
+          billingClient (LocalRef<jobject> (getEnv()->NewObject (JuceBillingClient,\r
+                                                                 JuceBillingClient.constructor,\r
+                                                                 getAppContext().get(),\r
+                                                                 (jlong) this)))\r
     {\r
-        auto* env = getEnv();\r
-        auto intent = env->NewObject (AndroidIntent, AndroidIntent.constructWithString,\r
-                                      javaString ("com.android.vending.billing.InAppBillingService.BIND").get());\r
-        env->CallObjectMethod (intent, AndroidIntent.setPackage, javaString ("com.android.vending").get());\r
-\r
-        serviceConnection = GlobalRef (CreateJavaInterface (this, "android/content/ServiceConnection"));\r
-\r
-        env->CallBooleanMethod (getCurrentActivity().get(), AndroidContext.bindService, intent,\r
-                                serviceConnection.get(), 1 /*BIND_AUTO_CREATE*/);\r
-\r
-        if (threadPool == nullptr)\r
-            threadPool.reset (new ThreadPool (1));\r
     }\r
 \r
     ~Pimpl()\r
     {\r
-        threadPool = nullptr;\r
-\r
-        if (serviceConnection != nullptr)\r
-        {\r
-            getEnv()->CallVoidMethod (getCurrentActivity().get(), AndroidContext.unbindService, serviceConnection.get());\r
-            serviceConnection.clear();\r
-        }\r
+        getEnv()->CallVoidMethod (billingClient, JuceBillingClient.endConnection);\r
     }\r
 \r
     //==============================================================================\r
-    bool isInAppPurchasesSupported()       { return isInAppPurchasesSupported (inAppBillingService); }\r
+    bool isInAppPurchasesSupported() const\r
+    {\r
+        return isReady() && getEnv()->CallBooleanMethod (billingClient, JuceBillingClient.isBillingSupported);\r
+    }\r
 \r
     void getProductsInformation (const StringArray& productIdentifiers)\r
     {\r
-        auto callback = [this](const Array<InAppPurchases::Product>& products)\r
+        skuDetailsQueryCallbackQueue.emplace ([this] (LocalRef<jobject> skuDetailsList)\r
         {\r
-            const ScopedLock lock (getProductsInformationJobResultsLock);\r
-            getProductsInformationJobResults.insert (0, products);\r
-            triggerAsyncUpdate();\r
-        };\r
+            if (skuDetailsList != nullptr)\r
+            {\r
+                auto* env = getEnv();\r
+                Array<InAppPurchases::Product> products;\r
+\r
+                for (int i = 0; i < env->CallIntMethod (skuDetailsList, JavaList.size); ++i)\r
+                    products.add (buildProduct (LocalRef<jobject> (env->CallObjectMethod (skuDetailsList, JavaList.get, i))));\r
+\r
+                owner.listeners.call ([&] (Listener& l) { l.productsInfoReturned (products); });\r
+            }\r
+        });\r
 \r
-        threadPool->addJob (new GetProductsInformationJob (*this, getPackageName(),\r
-                                                           productIdentifiers, callback), true);\r
+        querySkuDetailsAsync (convertToLowerCase (productIdentifiers));\r
     }\r
 \r
-    void purchaseProduct (const String& productIdentifier, bool isSubscription,\r
-                          const StringArray& subscriptionIdentifiers, bool creditForUnusedSubscription)\r
+    void purchaseProduct (const String& productIdentifier,\r
+                          const String& subscriptionIdentifier,\r
+                          bool creditForUnusedSubscription)\r
     {\r
-        // Upgrading/downgrading only makes sense for subscriptions!\r
-        jassert (subscriptionIdentifiers.isEmpty() || isSubscription);\r
+        skuDetailsQueryCallbackQueue.emplace ([=] (LocalRef<jobject> skuDetailsList)\r
+        {\r
+            if (skuDetailsList != nullptr)\r
+            {\r
+                auto* env = getEnv();\r
 \r
-        auto buyIntentBundle = getBuyIntentBundle (productIdentifier, isSubscription,\r
-                                                   subscriptionIdentifiers, creditForUnusedSubscription);\r
-        auto* env = getEnv();\r
+                if (env->CallIntMethod (skuDetailsList, JavaList.size) > 0)\r
+                {\r
+                    LocalRef<jobject> skuDetails (env->CallObjectMethod (skuDetailsList, JavaList.get, 0));\r
 \r
-        auto responseCodeString = javaString ("RESPONSE_CODE");\r
-        auto responseCode = env->CallIntMethod (buyIntentBundle.get(), AndroidBundle.getInt, responseCodeString.get());\r
+                    if (subscriptionIdentifier.isNotEmpty())\r
+                        changeExistingSubscription (skuDetails, subscriptionIdentifier, creditForUnusedSubscription);\r
+                    else\r
+                        purchaseProductWithSkuDetails (skuDetails);\r
+                }\r
+            }\r
+        });\r
 \r
-        if (responseCode == 0)\r
-        {\r
-            auto buyIntentString = javaString ("BUY_INTENT");\r
-            auto pendingIntent   = LocalRef<jobject> (env->CallObjectMethod (buyIntentBundle.get(), AndroidBundle.getParcelable, buyIntentString.get()));\r
-\r
-            auto  requestCode = 1001;\r
-            auto intentSender    = LocalRef<jobject> (env->CallObjectMethod (pendingIntent.get(), AndroidPendingIntent.getIntentSender));\r
-            auto fillInIntent    = LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructor));\r
-            auto flagsMask       = LocalRef<jobject> (env->CallStaticObjectMethod (JavaInteger, JavaInteger.valueOf, 0));\r
-            auto flagsValues     = LocalRef<jobject> (env->CallStaticObjectMethod (JavaInteger, JavaInteger.valueOf, 0));\r
-            auto extraFlags      = LocalRef<jobject> (env->CallStaticObjectMethod (JavaInteger, JavaInteger.valueOf, 0));\r
-\r
-            env->CallVoidMethod (getCurrentActivity().get(), AndroidActivity.startIntentSenderForResult, intentSender.get(), requestCode,\r
-                                 fillInIntent.get(), flagsMask.get(), flagsValues.get(), extraFlags.get());\r
-        }\r
-        else if (responseCode == 7)\r
-        {\r
-            // Item already bought.\r
-            notifyAboutPurchaseResult ({ {}, productIdentifier, juceString (getPackageName()), {}, {} }, true, statusCodeToUserString (responseCode));\r
-        }\r
+        querySkuDetailsAsync (convertToLowerCase ({ productIdentifier }));\r
     }\r
 \r
     void restoreProductsBoughtList (bool, const juce::String&)\r
     {\r
-        auto callback = [this](const GetProductsBoughtJob::Result& r)\r
+        purchasesListQueryCallbackQueue.emplace ([this] (LocalRef<jobject> purchasesList)\r
         {\r
-            const ScopedLock lock (getProductsBoughtJobResultsLock);\r
-            getProductsBoughtJobResults.insert (0, r);\r
-            triggerAsyncUpdate();\r
-        };\r
+            if (purchasesList != nullptr)\r
+            {\r
+                auto* env = getEnv();\r
+                Array<InAppPurchases::Listener::PurchaseInfo> purchases;\r
+\r
+                for (int i = 0; i < env->CallIntMethod (purchasesList, JavaArrayList.size); ++i)\r
+                {\r
+                    LocalRef<jobject> purchase (env->CallObjectMethod (purchasesList, JavaArrayList.get, i));\r
+                    purchases.add ({ buildPurchase (purchase), {} });\r
+                }\r
+\r
+                owner.listeners.call ([&] (Listener& l) { l.purchasesListRestored (purchases, true, NEEDS_TRANS ("Success")); });\r
+            }\r
+            else\r
+            {\r
+                owner.listeners.call ([&] (Listener& l) { l.purchasesListRestored ({}, false, NEEDS_TRANS ("Failure")); });\r
+            }\r
+        });\r
 \r
-        threadPool->addJob (new GetProductsBoughtJob (*this,\r
-                                                      getPackageName(), callback), true);\r
+        getProductsBoughtAsync();\r
     }\r
 \r
     void consumePurchase (const String& productIdentifier, const String& purchaseToken)\r
     {\r
-        auto callback = [this](const ConsumePurchaseJob::Result& r)\r
+        if (purchaseToken.isEmpty())\r
         {\r
-            const ScopedLock lock (consumePurchaseJobResultsLock);\r
-            consumePurchaseJobResults.insert (0, r);\r
-            triggerAsyncUpdate();\r
-        };\r
+            skuDetailsQueryCallbackQueue.emplace ([=] (LocalRef<jobject> skuDetailsList)\r
+            {\r
+                if (skuDetailsList != nullptr)\r
+                {\r
+                    auto* env = getEnv();\r
+\r
+                    if (env->CallIntMethod (skuDetailsList, JavaList.size) > 0)\r
+                    {\r
+                        LocalRef<jobject> sku (env->CallObjectMethod (skuDetailsList, JavaList.get, 0));\r
+\r
+                        auto token = juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (sku, AndroidPurchase.getSku)));\r
+\r
+                        if (token.isNotEmpty())\r
+                        {\r
+                            consumePurchaseWithToken (productIdentifier, token);\r
+                            return;\r
+                        }\r
+                    }\r
+                }\r
+\r
+                notifyListenersAboutConsume (productIdentifier, false, NEEDS_TRANS ("Item unavailable"));\r
+            });\r
+\r
+            querySkuDetailsAsync (convertToLowerCase ({ productIdentifier }));\r
+        }\r
 \r
-        threadPool->addJob (new ConsumePurchaseJob (*this, getPackageName(), productIdentifier,\r
-                                                    purchaseToken, callback), true);\r
+        consumePurchaseWithToken (productIdentifier, purchaseToken);\r
     }\r
 \r
     //==============================================================================\r
-    void startDownloads  (const Array<Download*>& downloads)\r
+    void startDownloads (const Array<Download*>& downloads)\r
     {\r
         // Not available on this platform.\r
         ignoreUnused (downloads);\r
         jassertfalse;\r
     }\r
 \r
-    void pauseDownloads  (const Array<Download*>& downloads)\r
+    void pauseDownloads (const Array<Download*>& downloads)\r
     {\r
         // Not available on this platform.\r
         ignoreUnused (downloads);\r
         jassertfalse;\r
     }\r
 \r
-    void resumeDownloads  (const Array<Download*>& downloads)\r
+    void resumeDownloads (const Array<Download*>& downloads)\r
     {\r
         // Not available on this platform.\r
         ignoreUnused (downloads);\r
         jassertfalse;\r
     }\r
 \r
-    void cancelDownloads  (const Array<Download*>& downloads)\r
+    void cancelDownloads (const Array<Download*>& downloads)\r
     {\r
         // Not available on this platform.\r
         ignoreUnused (downloads);\r
         jassertfalse;\r
     }\r
 \r
-    //==============================================================================\r
-    LocalRef<jobject> getBuyIntentBundle (const String& productIdentifier, bool isSubscription,\r
-                                          const StringArray& subscriptionIdentifiers, bool creditForUnusedSubscription)\r
+private:\r
+    #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
+      METHOD (constructor,                  "<init>",                     "(Landroid/content/Context;J)V")                                              \\r
+      METHOD (endConnection,                "endConnection",              "()V")                                                                        \\r
+      METHOD (isReady,                      "isReady",                    "()Z")                                                                        \\r
+      METHOD (isBillingSupported,           "isBillingSupported",         "()Z")                                                                        \\r
+      METHOD (querySkuDetails,              "querySkuDetails",            "([Ljava/lang/String;)V")                                                     \\r
+      METHOD (launchBillingFlow,            "launchBillingFlow",          "(Landroid/app/Activity;Lcom/android/billingclient/api/BillingFlowParams;)V") \\r
+      METHOD (queryPurchases,               "queryPurchases",             "()V")                                                                        \\r
+      METHOD (consumePurchase,              "consumePurchase",            "(Ljava/lang/String;Ljava/lang/String;)V")                                    \\r
+                                                                                                                                                        \\r
+      CALLBACK (skuDetailsQueryCallback,    "skuDetailsQueryCallback",    "(JLjava/util/List;)V")                                                       \\r
+      CALLBACK (purchasesListQueryCallback, "purchasesListQueryCallback", "(JLjava/util/List;)V")                                                       \\r
+      CALLBACK (purchaseCompletedCallback,  "purchaseCompletedCallback",  "(JLcom/android/billingclient/api/Purchase;I)V")                              \\r
+      CALLBACK (purchaseConsumedCallback,   "purchaseConsumedCallback",   "(JLjava/lang/String;I)V")\r
+\r
+    DECLARE_JNI_CLASS (JuceBillingClient, "com/roli/juce/JuceBillingClient")\r
+    #undef JNI_CLASS_MEMBERS\r
+\r
+    static void JNICALL skuDetailsQueryCallback (JNIEnv*, jobject, jlong host, jobject skuDetailsList)\r
     {\r
-        auto* env = getEnv();\r
-\r
-        auto skuString         = javaString (productIdentifier);\r
-        auto productTypeString = javaString (isSubscription ? "subs" : "inapp");\r
-        auto devString         = javaString ("");\r
-\r
-        if (subscriptionIdentifiers.isEmpty())\r
-            return LocalRef<jobject> (inAppBillingService.callObjectMethod (IInAppBillingService.getBuyIntent, 3,\r
-                                                                            getPackageName().get(), skuString.get(),\r
-                                                                            productTypeString.get(), devString.get()));\r
-\r
-        auto skuList = LocalRef<jobject> (env->NewObject (JavaArrayList, JavaArrayList.constructor,\r
-                                                          (int) subscriptionIdentifiers.size()));\r
-\r
-        if (skuList.get() == 0)\r
-        {\r
-            jassertfalse;\r
-            return LocalRef<jobject> (0);\r
-        }\r
-\r
-        for (const auto& identifier : subscriptionIdentifiers)\r
-            env->CallBooleanMethod (skuList.get(), JavaArrayList.add, javaString (identifier).get());\r
-\r
-        auto extraParams = LocalRef<jobject> (env->NewObject (AndroidBundle, AndroidBundle.constructor));\r
-\r
-        if (extraParams.get() == 0)\r
-        {\r
-            jassertfalse;\r
-            return LocalRef<jobject> (0);\r
-        }\r
-\r
-        auto skusToReplaceString        = javaString ("skusToReplace");\r
-        auto replaceSkusProrationString = javaString ("replaceSkusProration");\r
+        if (auto* myself = reinterpret_cast<Pimpl*> (host))\r
+            myself->updateSkuDetails (skuDetailsList);\r
+    }\r
 \r
-        env->CallVoidMethod (extraParams.get(), AndroidBundle.putStringArrayList, skusToReplaceString.get(), skuList.get());\r
-        env->CallVoidMethod (extraParams.get(), AndroidBundle.putBoolean, replaceSkusProrationString.get(), creditForUnusedSubscription);\r
+    static void JNICALL purchasesListQueryCallback (JNIEnv*, jobject, jlong host, jobject purchasesList)\r
+    {\r
+        if (auto* myself = reinterpret_cast<Pimpl*> (host))\r
+            myself->updatePurchasesList (purchasesList);\r
+    }\r
 \r
-        return LocalRef<jobject> (inAppBillingService.callObjectMethod (IInAppBillingService.getBuyIntentExtraParams, 6,\r
-                                                                        getPackageName().get(), skuString.get(),\r
-                                                                        productTypeString.get(), devString.get(),\r
-                                                                        extraParams.get()));\r
+    static void JNICALL purchaseCompletedCallback (JNIEnv*, jobject, jlong host, jobject purchase, int responseCode)\r
+    {\r
+        if (auto* myself = reinterpret_cast<Pimpl*> (host))\r
+            myself->purchaseCompleted (purchase, responseCode);\r
     }\r
 \r
-    //==============================================================================\r
-    void notifyAboutPurchaseResult (const InAppPurchases::Purchase& purchase, bool success, const String& statusDescription)\r
+    static void JNICALL purchaseConsumedCallback (JNIEnv*, jobject, jlong host, jstring productIdentifier, int responseCode)\r
     {\r
-        owner.listeners.call ([&] (Listener& l) { l.productPurchaseFinished ({ purchase, {} }, success, statusDescription); });\r
+        if (auto* myself = reinterpret_cast<Pimpl*> (host))\r
+            myself->purchaseConsumed (productIdentifier, responseCode);\r
     }\r
 \r
     //==============================================================================\r
-    bool checkIsReady()\r
+    bool isReady() const\r
     {\r
-        // It may take a few seconds for the in-app purchase service to connect\r
-        for (auto retries = 0; retries < 10 && inAppBillingService.get() == 0; ++retries)\r
-            Thread::sleep (500);\r
-\r
-        return (inAppBillingService.get() != 0);\r
+        return getEnv()->CallBooleanMethod (billingClient, JuceBillingClient.isReady);\r
     }\r
 \r
-    static bool isInAppPurchasesSupported (jobject iapService)\r
+    bool checkIsReady() const\r
     {\r
-        if (iapService != nullptr)\r
+        for (int i = 0; i < 10; ++i)\r
         {\r
-            auto* env = getEnv();\r
-\r
-            auto inAppString = javaString ("inapp");\r
-            auto subsString  = javaString ("subs");\r
-\r
-            if (env->CallIntMethod (iapService, IInAppBillingService.isBillingSupported, 3,\r
-                                    getPackageName().get(), inAppString.get()) != 0)\r
-                return false;\r
+            if (isReady())\r
+                return true;\r
 \r
-            if (env->CallIntMethod (iapService, IInAppBillingService.isBillingSupported, 3,\r
-                                    getPackageName().get(), subsString.get()) != 0)\r
-                return false;\r
-\r
-            return true;\r
+            Thread::sleep (500);\r
         }\r
 \r
-        // Connecting to the in-app purchase server failed! This could have multiple reasons:\r
-        // 1) Your phone/emulator must support the google play store\r
-        // 2) Your phone must be logged into the google play store and be able to receive updates\r
-        // 3) It can take a few seconds after instantiation of the InAppPurchase class for\r
-        //    in-app purchases to be avaialable on Android.\r
         return false;\r
     }\r
 \r
     //==============================================================================\r
-    void onServiceConnected (jobject, jobject iBinder) override\r
+    static StringArray convertToLowerCase (const StringArray& stringsToConvert)\r
     {\r
-        auto* env = getEnv();\r
-\r
-        LocalRef<jobject> iapService (env->CallStaticObjectMethod (IInAppBillingServiceStub,\r
-                                                                   IInAppBillingServiceStub.asInterface,\r
-                                                                   iBinder));\r
+        StringArray lowerCase;\r
 \r
-        if (isInAppPurchasesSupported (iapService))\r
-            inAppBillingService = GlobalRef (iapService);\r
+        for (auto& s : stringsToConvert)\r
+            lowerCase.add (s.toLowerCase());\r
 \r
-        // If you hit this assert, then in-app purchases is not available on your device,\r
-        // most likely due to too old version of Google Play API (hint: update Google Play on the device).\r
-        jassert (isInAppPurchasesSupported());\r
+        return lowerCase;\r
     }\r
 \r
-    void onServiceDisconnected (jobject) override\r
-    {\r
-        inAppBillingService.clear();\r
-    }\r
-\r
-    //==============================================================================\r
-    static LocalRef<jstring> getPackageName()\r
+    void querySkuDetailsAsync (const StringArray& productIdentifiers)\r
     {\r
-        return LocalRef<jstring> ((jstring) (getEnv()->CallObjectMethod (getAppContext().get(), AndroidContext.getPackageName)));\r
-    }\r
-\r
-    //==============================================================================\r
-    struct GetProductsInformationJob  : public ThreadPoolJob\r
-    {\r
-        using Callback = std::function<void(const Array<InAppPurchases::Product>&)>;\r
-\r
-        GetProductsInformationJob (Pimpl& parent,\r
-                                   const LocalRef<jstring>& packageNameToUse,\r
-                                   const StringArray& productIdentifiersToUse,\r
-                                   const Callback& callbackToUse)\r
-            : ThreadPoolJob ("GetProductsInformationJob"),\r
-              owner (parent),\r
-              packageName (LocalRef<jobject> (getEnv()->NewLocalRef (packageNameToUse.get()))),\r
-              productIdentifiers (productIdentifiersToUse),\r
-              callback (callbackToUse)\r
-        {}\r
-\r
-        ThreadPoolJob::JobStatus runJob() override\r
+        Thread::launch ([=]\r
         {\r
-            jassert (callback);\r
-\r
-            if (owner.checkIsReady())\r
-            {\r
-                // Google's Billing API limitation\r
-                auto maxQuerySize = 20;\r
-                auto pi = 0;\r
-\r
-                Array<InAppPurchases::Product> results;\r
-                StringArray identifiersToUse;\r
-\r
-                for (auto i = 0; i < productIdentifiers.size(); ++i)\r
-                {\r
-                    identifiersToUse.add (productIdentifiers[i].toLowerCase());\r
-                    ++pi;\r
+            if (! checkIsReady())\r
+                return;\r
 \r
-                    if (pi == maxQuerySize || i == productIdentifiers.size() - 1)\r
-                    {\r
-                        auto inAppProducts = processRetrievedProducts (queryProductsInformationFromService (identifiersToUse, "inapp"));\r
-                        auto subsProducts  = processRetrievedProducts (queryProductsInformationFromService (identifiersToUse, "subs"));\r
-\r
-                        results.addArray (inAppProducts);\r
-                        results.addArray (subsProducts);\r
-                        identifiersToUse.clear();\r
-                        pi = 0;\r
-                    }\r
-                }\r
-\r
-                if (callback)\r
-                    callback (results);\r
-            }\r
-            else\r
+            MessageManager::callAsync ([=]\r
             {\r
-                if (callback)\r
-                    callback ({});\r
-            }\r
-\r
-            return jobHasFinished;\r
-        }\r
-\r
-    private:\r
-        LocalRef<jobject> queryProductsInformationFromService (const StringArray& productIdentifiersToQuery, const String& productType)\r
-        {\r
-            auto* env = getEnv();\r
-\r
-            auto skuList = LocalRef<jobject> (env->NewObject (JavaArrayList, JavaArrayList.constructor, productIdentifiersToQuery.size()));\r
-\r
-            if (skuList.get() == 0)\r
-                return LocalRef<jobject> (0);\r
-\r
-            for (const auto& pi : productIdentifiersToQuery)\r
-                env->CallBooleanMethod (skuList.get(), JavaArrayList.add, javaString (pi).get());\r
-\r
-            auto querySkus = LocalRef<jobject> (env->NewObject (AndroidBundle, AndroidBundle.constructor));\r
-\r
-            if (querySkus.get() == 0)\r
-                return LocalRef<jobject> (0);\r
-\r
-            auto itemIdListString = javaString ("ITEM_ID_LIST");\r
-\r
-            env->CallVoidMethod (querySkus.get(), AndroidBundle.putStringArrayList, itemIdListString.get(), skuList.get());\r
-\r
-            auto productTypeString = javaString (productType);\r
-\r
-            auto productDetails = LocalRef<jobject> (owner.inAppBillingService.callObjectMethod (IInAppBillingService.getSkuDetails,\r
-                                                                                           3, (jstring) packageName.get(),\r
-                                                                                           productTypeString.get(), querySkus.get()));\r
-\r
-            return productDetails;\r
-        }\r
+                getEnv()->CallVoidMethod (billingClient,\r
+                                          JuceBillingClient.querySkuDetails,\r
+                                          juceStringArrayToJava (productIdentifiers).get());\r
+            });\r
+        });\r
+    }\r
 \r
-        Array<InAppPurchases::Product> processRetrievedProducts (LocalRef<jobject> retrievedProducts)\r
+    void getProductsBoughtAsync()\r
+    {\r
+        Thread::launch ([=]\r
         {\r
-            Array<InAppPurchases::Product> products;\r
+            if (! checkIsReady())\r
+                return;\r
 \r
-            if (owner.checkIsReady())\r
+            MessageManager::callAsync ([=]\r
             {\r
-                auto* env = getEnv();\r
-\r
-                auto responseCodeString = javaString ("RESPONSE_CODE");\r
-\r
-                auto responseCode = env->CallIntMethod (retrievedProducts.get(), AndroidBundle.getInt, responseCodeString.get());\r
-\r
-                if (responseCode == 0)\r
-                {\r
-                    auto detailsListString = javaString ("DETAILS_LIST");\r
-\r
-                    auto responseList = LocalRef<jobject> (env->CallObjectMethod (retrievedProducts.get(), AndroidBundle.getStringArrayList,\r
-                                                                                  detailsListString.get()));\r
-\r
-                    if (responseList != 0)\r
-                    {\r
-                        auto iterator = LocalRef<jobject> (env->CallObjectMethod (responseList.get(), JavaArrayList.iterator));\r
-\r
-                        if (iterator.get() != 0)\r
-                        {\r
-                            for (;;)\r
-                            {\r
-                                if (! env->CallBooleanMethod (iterator, JavaIterator.hasNext))\r
-                                    break;\r
-\r
-                                auto response = juce::LocalRef<jstring> ((jstring)env->CallObjectMethod (iterator, JavaIterator.next));\r
-\r
-                                if (response.get() != 0)\r
-                                {\r
-                                    var responseData = JSON::parse (juceString (response.get()));\r
-\r
-                                    if (DynamicObject* object = responseData.getDynamicObject())\r
-                                    {\r
-                                        NamedValueSet& props = object->getProperties();\r
-\r
-                                        static Identifier productIdIdentifier         ("productId");\r
-                                        static Identifier titleIdentifier             ("title");\r
-                                        static Identifier descriptionIdentifier       ("description");\r
-                                        static Identifier priceIdentifier             ("price");\r
-                                        static Identifier priceCurrencyCodeIdentifier ("price_currency_code");\r
-\r
-                                        var productId         = props[productIdIdentifier];\r
-                                        var title             = props[titleIdentifier];\r
-                                        var description       = props[descriptionIdentifier];\r
-                                        var price             = props[priceIdentifier];\r
-                                        var priceCurrencyCode = props[priceCurrencyCodeIdentifier];\r
-\r
-                                        products.add ( { productId.toString(),\r
-                                                         title.toString(),\r
-                                                         description.toString(),\r
-                                                         price.toString(),\r
-                                                         priceCurrencyCode.toString() } );\r
-                                    }\r
-\r
-                                }\r
-                            }\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-\r
-            return products;\r
-        }\r
-\r
-        Pimpl& owner;\r
-        GlobalRef packageName;\r
-        const StringArray productIdentifiers;\r
-        Callback callback;\r
-    };\r
+                getEnv()->CallVoidMethod (billingClient,\r
+                                          JuceBillingClient.queryPurchases);\r
+            });\r
+        });\r
+    }\r
 \r
     //==============================================================================\r
-    struct GetProductsBoughtJob  : public ThreadPoolJob\r
+    void notifyListenersAboutPurchase (const InAppPurchases::Purchase& purchase, bool success, const String& statusDescription)\r
     {\r
-        struct Result\r
-        {\r
-            bool success = false;\r
-            Array<InAppPurchases::Listener::PurchaseInfo> purchases;\r
-            String statusDescription;\r
-        };\r
-\r
-        using Callback = std::function<void(const Result&)>;\r
-\r
-        GetProductsBoughtJob (Pimpl& parent,\r
-                              const LocalRef<jstring>& packageNameToUse,\r
-                              const Callback& callbackToUse)\r
-            : ThreadPoolJob ("GetProductsBoughtJob"),\r
-              owner (parent),\r
-              packageName (LocalRef<jobject> (getEnv()->NewLocalRef (packageNameToUse.get()))),\r
-              callback (callbackToUse)\r
-        {}\r
-\r
-        ThreadPoolJob::JobStatus runJob() override\r
-        {\r
-            jassert (callback);\r
-\r
-            if (owner.checkIsReady())\r
-            {\r
-                auto inAppPurchases = getProductsBought ("inapp", 0);\r
-                auto subsPurchases  = getProductsBought ("subs", 0);\r
-\r
-                inAppPurchases.addArray (subsPurchases);\r
-\r
-                Array<InAppPurchases::Listener::PurchaseInfo> purchases;\r
-\r
-                for (const auto& purchase : inAppPurchases)\r
-                    purchases.add ({ purchase, {} });\r
-\r
-                if (callback)\r
-                    callback ({true, purchases, "Success"});\r
-            }\r
-            else\r
-            {\r
-                if (callback)\r
-                    callback ({false, {}, "In-App purchases unavailable"});\r
-            }\r
-\r
-            return jobHasFinished;\r
-        }\r
-\r
-    private:\r
-        Array<InAppPurchases::Purchase> getProductsBought (const String& productType, jstring continuationToken)\r
-        {\r
-            Array<InAppPurchases::Purchase> purchases;\r
-            auto* env = getEnv();\r
-\r
-            auto productTypeString = javaString (productType);\r
-            auto ownedItems = LocalRef<jobject> (owner.inAppBillingService.callObjectMethod (IInAppBillingService.getPurchases, 3,\r
-                                                                                       (jstring) packageName.get(), productTypeString.get(),\r
-                                                                                       continuationToken));\r
-\r
-            if (ownedItems.get() != 0)\r
-            {\r
-                auto responseCodeString = javaString ("RESPONSE_CODE");\r
-                auto responseCode = env->CallIntMethod (ownedItems.get(), AndroidBundle.getInt, responseCodeString.get());\r
-\r
-                if (responseCode == 0)\r
-                {\r
-                    auto itemListString          = javaString ("INAPP_PURCHASE_ITEM_LIST");\r
-                    auto dataListString          = javaString ("INAPP_PURCHASE_DATA_LIST");\r
-                    auto signatureListString     = javaString ("INAPP_DATA_SIGNATURE_LIST");\r
-                    auto continuationTokenString = javaString ("INAPP_CONTINUATION_TOKEN");\r
+        owner.listeners.call ([&] (Listener& l) { l.productPurchaseFinished ({ purchase, {} }, success, statusDescription); });\r
+    }\r
 \r
-                    auto ownedSkus            = LocalRef<jobject> (env->CallObjectMethod (ownedItems.get(), AndroidBundle.getStringArrayList, itemListString.get()));\r
-                    auto purchaseDataList     = LocalRef<jobject> (env->CallObjectMethod (ownedItems.get(), AndroidBundle.getStringArrayList, dataListString.get()));\r
-                    auto signatureList        = LocalRef<jobject> (env->CallObjectMethod (ownedItems.get(), AndroidBundle.getStringArrayList, signatureListString.get()));\r
-                    auto newContinuationToken = LocalRef<jstring> ((jstring) env->CallObjectMethod (ownedItems.get(), AndroidBundle.getString, continuationTokenString.get()));\r
+    void notifyListenersAboutConsume (const String& productIdentifier, bool success, const String& statusDescription)\r
+    {\r
+        owner.listeners.call ([&] (Listener& l) { l.productConsumed (productIdentifier, success, statusDescription); });\r
+    }\r
 \r
-                    for (auto i = 0; i < env->CallIntMethod (purchaseDataList.get(), JavaArrayList.size); ++i)\r
-                    {\r
-                        auto sku          = juceString ((jstring) (env->CallObjectMethod (ownedSkus.get(),        JavaArrayList.get, i)));\r
-                        auto purchaseData = juceString ((jstring) (env->CallObjectMethod (purchaseDataList.get(), JavaArrayList.get, i)));\r
-                        auto signature    = juceString ((jstring) (env->CallObjectMethod (signatureList.get(),    JavaArrayList.get, i)));\r
+    LocalRef<jobject> createBillingFlowParamsBuilder (LocalRef<jobject> skuDetails)\r
+    {\r
+        auto* env = getEnv();\r
 \r
-                        var responseData = JSON::parse (purchaseData);\r
+        auto builder = LocalRef<jobject> (env->CallStaticObjectMethod (BillingFlowParams, BillingFlowParams.newBuilder));\r
 \r
-                        if (auto* object = responseData.getDynamicObject())\r
-                        {\r
-                            auto& props = object->getProperties();\r
-\r
-                            static const Identifier orderIdIdentifier       ("orderId"),\r
-                                                    packageNameIdentifier   ("packageName"),\r
-                                                    productIdIdentifier     ("productId"),\r
-                                                    purchaseTimeIdentifier  ("purchaseTime"),\r
-                                                    purchaseTokenIdentifier ("purchaseToken");\r
-\r
-                            var orderId          = props[orderIdIdentifier];\r
-                            var appPackageName   = props[packageNameIdentifier];\r
-                            var productId        = props[productIdIdentifier];\r
-                            var purchaseTime     = props[purchaseTimeIdentifier];\r
-                            var purchaseToken    = props[purchaseTokenIdentifier];\r
-\r
-                            String purchaseTimeString = Time (purchaseTime.toString().getLargeIntValue()).toString (true, true, true, true);\r
-                            purchases.add ({ orderId.toString(), productId.toString(), appPackageName.toString(), purchaseTimeString, purchaseToken.toString() });\r
-                        }\r
-                    }\r
+        return LocalRef<jobject> (env->CallObjectMethod (builder.get(),\r
+                                  BillingFlowParamsBuilder.setSkuDetails,\r
+                                  skuDetails.get()));\r
+    }\r
 \r
-                    if (newContinuationToken.get() != 0)\r
-                        getProductsBought (productType, newContinuationToken.get());\r
-                }\r
-            }\r
+    void launchBillingFlowWithParameters (LocalRef<jobject> params)\r
+    {\r
+        LocalRef<jobject> activity (getCurrentActivity());\r
 \r
-            return purchases;\r
-        }\r
+        if (activity == nullptr)\r
+            activity = getMainActivity();\r
 \r
-        Pimpl& owner;\r
-        GlobalRef packageName;\r
-        Callback callback;\r
-    };\r
+        getEnv()->CallVoidMethod (billingClient,\r
+                                  JuceBillingClient.launchBillingFlow,\r
+                                  activity.get(),\r
+                                  params.get());\r
+    }\r
 \r
-    //==============================================================================\r
-    class ConsumePurchaseJob : public ThreadPoolJob\r
+    void changeExistingSubscription (LocalRef<jobject> skuDetails, const String& subscriptionIdentifier, bool creditForUnusedSubscription)\r
     {\r
-    public:\r
-        struct Result\r
-        {\r
-            bool success = false;\r
-            String productIdentifier;\r
-            String statusDescription;\r
-        };\r
-\r
-        using Callback = std::function<void(const Result&)>;\r
-\r
-        ConsumePurchaseJob (Pimpl& parent,\r
-                            const LocalRef<jstring>& packageNameToUse,\r
-                            const String& productIdentifierToUse,\r
-                            const String& purchaseTokenToUse,\r
-                            const Callback& callbackToUse)\r
-            : ThreadPoolJob ("ConsumePurchaseJob"),\r
-              owner (parent),\r
-              packageName (LocalRef<jobject> (getEnv()->NewLocalRef (packageNameToUse.get()))),\r
-              productIdentifier (productIdentifierToUse),\r
-              purchaseToken (purchaseTokenToUse),\r
-              callback (callbackToUse)\r
-        {}\r
-\r
-        ThreadPoolJob::JobStatus runJob() override\r
+        if (! isReady())\r
         {\r
-            jassert (callback);\r
-\r
-            if (owner.checkIsReady())\r
-            {\r
-                auto token = (! purchaseToken.isEmpty() ? purchaseToken : getPurchaseTokenForProductId (productIdentifier, false, 0));\r
-\r
-                if (token.isEmpty())\r
-                {\r
-                    if (callback)\r
-                        callback ({ false, productIdentifier, NEEDS_TRANS ("Item not owned") });\r
-\r
-                    return jobHasFinished;\r
-                }\r
-\r
-                auto responseCode = owner.inAppBillingService.callIntMethod (IInAppBillingService.consumePurchase, 3,\r
-                                                                       (jstring)packageName.get(), javaString (token).get());\r
-\r
-                if (callback)\r
-                    callback ({ responseCode == 0, productIdentifier, statusCodeToUserString (responseCode) });\r
-            }\r
-            else\r
-            {\r
-                if (callback)\r
-                    callback ({false, {}, "In-App purchases unavailable"});\r
-            }\r
-\r
-            return jobHasFinished;\r
+            notifyListenersAboutPurchase ({}, false, NEEDS_TRANS ("In-App purchases unavailable"));\r
+            return;\r
         }\r
 \r
-    private:\r
-        String getPurchaseTokenForProductId (const String productIdToLookFor, bool isSubscription, jstring continuationToken)\r
+        purchasesListQueryCallbackQueue.emplace ([=] (LocalRef<jobject> purchasesList)\r
         {\r
-            auto productTypeString = javaString (isSubscription ? "subs" : "inapp");\r
-            auto ownedItems = LocalRef<jobject> (owner.inAppBillingService.callObjectMethod (IInAppBillingService.getPurchases, 3,\r
-                                                                                       (jstring) packageName.get(), productTypeString.get(),\r
-                                                                                       continuationToken));\r
-\r
-            if (ownedItems.get() != 0)\r
+            if (purchasesList != nullptr)\r
             {\r
                 auto* env = getEnv();\r
 \r
-                auto responseCodeString = javaString ("RESPONSE_CODE");\r
-                auto responseCode = env->CallIntMethod (ownedItems.get(), AndroidBundle.getInt, responseCodeString.get());\r
-\r
-                if (responseCode == 0)\r
+                for (int i = 0; i < env->CallIntMethod (purchasesList, JavaArrayList.size); ++i)\r
                 {\r
-                    auto dataListString          = javaString ("INAPP_PURCHASE_DATA_LIST");\r
-                    auto continuationTokenString = javaString ("INAPP_CONTINUATION_TOKEN");\r
+                    auto purchase = buildPurchase (LocalRef<jobject> (env->CallObjectMethod (purchasesList.get(), JavaArrayList.get, i)));\r
 \r
-                    auto purchaseDataList     = LocalRef<jobject> (env->CallObjectMethod (ownedItems.get(), AndroidBundle.getStringArrayList, dataListString.get()));\r
-                    auto newContinuationToken = LocalRef<jstring> ((jstring) env->CallObjectMethod (ownedItems.get(), AndroidBundle.getString, continuationTokenString.get()));\r
-\r
-                    for (auto i = 0; i < env->CallIntMethod (purchaseDataList.get(), JavaArrayList.size); ++i)\r
+                    if (purchase.productId == subscriptionIdentifier)\r
                     {\r
-                        auto purchaseData = juceString ((jstring) (env->CallObjectMethod (purchaseDataList.get(), JavaArrayList.get, i)));\r
-\r
-                        var responseData = JSON::parse (purchaseData);\r
+                        auto builder = createBillingFlowParamsBuilder (skuDetails);\r
 \r
-                        if (auto* object = responseData.getDynamicObject())\r
-                        {\r
-                            static const Identifier productIdIdentifier     ("productId"),\r
-                                                    purchaseTokenIdentifier ("purchaseToken");\r
+                        builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(),\r
+                                                                            BillingFlowParamsBuilder.setOldSku,\r
+                                                                            javaString (subscriptionIdentifier).get(),\r
+                                                                            javaString (purchase.purchaseToken).get()));\r
 \r
-                            auto& props = object->getProperties();\r
-                            var productId = props[productIdIdentifier];\r
+                        if (! creditForUnusedSubscription)\r
+                            builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(),\r
+                                                                                BillingFlowParamsBuilder.setReplaceSkusProrationMode,\r
+                                                                                3 /*IMMEDIATE_WITHOUT_PRORATION*/));\r
 \r
-                            if (productId.toString() == productIdToLookFor)\r
-                                return props[purchaseTokenIdentifier].toString();\r
-                        }\r
+                        launchBillingFlowWithParameters (LocalRef<jobject> (env->CallObjectMethod (builder.get(),\r
+                                                                                                   BillingFlowParamsBuilder.build)));\r
                     }\r
-\r
-                    if (newContinuationToken.get() != 0)\r
-                        return getPurchaseTokenForProductId (productIdToLookFor, isSubscription, newContinuationToken.get());\r
                 }\r
             }\r
 \r
-            return {};\r
-        }\r
+            notifyListenersAboutPurchase ({}, false, NEEDS_TRANS ("Unable to get subscription details"));\r
+        });\r
 \r
-        Pimpl& owner;\r
-        GlobalRef packageName;\r
-        const String productIdentifier, purchaseToken;\r
-        Callback callback;\r
-    };\r
+        getProductsBoughtAsync();\r
+    }\r
 \r
-    //==============================================================================\r
-    void handleAsyncUpdate() override\r
+    void purchaseProductWithSkuDetails (LocalRef<jobject> skuDetails)\r
     {\r
+        if (! isReady())\r
         {\r
-            const ScopedLock lock (getProductsInformationJobResultsLock);\r
-\r
-            for (int i = getProductsInformationJobResults.size(); --i >= 0;)\r
-            {\r
-                const auto& result = getProductsInformationJobResults.getReference (i);\r
-\r
-                owner.listeners.call ([&] (Listener& l) { l.productsInfoReturned (result); });\r
-                getProductsInformationJobResults.remove (i);\r
-            }\r
+            notifyListenersAboutPurchase ({}, false, NEEDS_TRANS ("In-App purchases unavailable"));\r
+            return;\r
         }\r
 \r
-        {\r
-            const ScopedLock lock (getProductsBoughtJobResultsLock);\r
-\r
-            for (int i = getProductsBoughtJobResults.size(); --i >= 0;)\r
-            {\r
-                const auto& result = getProductsBoughtJobResults.getReference (i);\r
-\r
-                owner.listeners.call ([&] (Listener& l) { l.purchasesListRestored (result.purchases, result.success, result.statusDescription); });\r
-                getProductsBoughtJobResults.remove (i);\r
-            }\r
-        }\r
+        launchBillingFlowWithParameters (LocalRef<jobject> (getEnv()->CallObjectMethod (createBillingFlowParamsBuilder (skuDetails).get(),\r
+                                                                                        BillingFlowParamsBuilder.build)));\r
+    }\r
 \r
+    void consumePurchaseWithToken (const String& productIdentifier, const String& purchaseToken)\r
+    {\r
+        if (! isReady())\r
         {\r
-            const ScopedLock lock (consumePurchaseJobResultsLock);\r
-\r
-            for (int i = consumePurchaseJobResults.size(); --i >= 0;)\r
-            {\r
-                const auto& result = consumePurchaseJobResults.getReference (i);\r
-\r
-                owner.listeners.call ([&] (Listener& l) { l.productConsumed (result.productIdentifier, result.success, result.statusDescription); });\r
-                consumePurchaseJobResults.remove (i);\r
-            }\r
+            notifyListenersAboutConsume (productIdentifier, false, NEEDS_TRANS ("In-App purchases unavailable"));\r
+            return;\r
         }\r
+\r
+        getEnv()->CallObjectMethod (billingClient,\r
+                                    JuceBillingClient.consumePurchase,\r
+                                    LocalRef<jstring> (javaString (productIdentifier)).get(),\r
+                                    LocalRef<jstring> (javaString (purchaseToken)).get());\r
     }\r
 \r
     //==============================================================================\r
-    void inAppPurchaseCompleted (jobject intentData)\r
+    static InAppPurchases::Purchase buildPurchase (LocalRef<jobject> purchase)\r
     {\r
+        if (purchase == nullptr)\r
+            return {};\r
+\r
         auto* env = getEnv();\r
 \r
-        auto inAppPurchaseDataString  = javaString ("INAPP_PURCHASE_DATA");\r
-        auto inAppDataSignatureString = javaString ("INAPP_DATA_SIGNATURE");\r
-        auto responseCodeString       = javaString ("RESPONSE_CODE");\r
+        return { juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (purchase, AndroidPurchase.getOrderId))),\r
+                 juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (purchase, AndroidPurchase.getSku))),\r
+                 juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (purchase, AndroidPurchase.getPackageName))),\r
+                 Time (env->CallLongMethod (purchase, AndroidPurchase.getPurchaseTime)).toString (true, true, true, true),\r
+                 juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (purchase, AndroidPurchase.getPurchaseToken))) };\r
+    }\r
 \r
-        auto pd  = LocalRef<jstring> ((jstring) env->CallObjectMethod (intentData, AndroidIntent.getStringExtra, inAppPurchaseDataString.get()));\r
-        auto sig = LocalRef<jstring> ((jstring) env->CallObjectMethod (intentData, AndroidIntent.getStringExtra, inAppDataSignatureString.get()));\r
-        auto purchaseDataString  = pd.get()  != 0 ? juceString (pd.get())  : String();\r
-        auto dataSignatureString = sig.get() != 0 ? juceString (sig.get()) : String();\r
+    static InAppPurchases::Product buildProduct (LocalRef<jobject> productSkuDetails)\r
+    {\r
+        if (productSkuDetails == nullptr)\r
+            return {};\r
 \r
-        var responseData = JSON::parse (purchaseDataString);\r
+        auto* env = getEnv();\r
 \r
-        auto responseCode = env->CallIntMethod (intentData, AndroidIntent.getIntExtra, responseCodeString.get());\r
-        auto statusCodeUserString = statusCodeToUserString (responseCode);\r
+        return { juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (productSkuDetails, SkuDetails.getSku))),\r
+                 juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (productSkuDetails, SkuDetails.getTitle))),\r
+                 juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (productSkuDetails, SkuDetails.getDescription))),\r
+                 juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (productSkuDetails, SkuDetails.getPrice))),\r
+                 juceString (LocalRef<jstring> ((jstring) env->CallObjectMethod (productSkuDetails, SkuDetails.getPriceCurrencyCode))) };\r
+    }\r
 \r
-        if (auto* object = responseData.getDynamicObject())\r
+    static String getStatusDescriptionFromResponseCode (int responseCode)\r
+    {\r
+        switch (responseCode)\r
         {\r
-            auto& props = object->getProperties();\r
-\r
-            static const Identifier orderIdIdentifier          ("orderId"),\r
-                                    packageNameIdentifier      ("packageName"),\r
-                                    productIdIdentifier        ("productId"),\r
-                                    purchaseTimeIdentifier     ("purchaseTime"),\r
-                                    purchaseTokenIdentifier    ("purchaseToken"),\r
-                                    developerPayloadIdentifier ("developerPayload");\r
-\r
-            var orderId          = props[orderIdIdentifier];\r
-            var packageName      = props[packageNameIdentifier];\r
-            var productId        = props[productIdIdentifier];\r
-            var purchaseTime     = props[purchaseTimeIdentifier];\r
-            var purchaseToken    = props[purchaseTokenIdentifier];\r
-            var developerPayload = props[developerPayloadIdentifier];\r
-\r
-            auto purchaseTimeString = Time (purchaseTime.toString().getLargeIntValue())\r
-                                        .toString (true, true, true, true);\r
-\r
-            notifyAboutPurchaseResult ({ orderId.toString(), productId.toString(), packageName.toString(),\r
-                                         purchaseTimeString, purchaseToken.toString() },\r
-                                       true, statusCodeUserString);\r
-            return;\r
+            case 0:   return NEEDS_TRANS ("Success");\r
+            case 1:   return NEEDS_TRANS ("Cancelled by user");\r
+            case 2:   return NEEDS_TRANS ("Service unavailable");\r
+            case 3:   return NEEDS_TRANS ("Billing unavailable");\r
+            case 4:   return NEEDS_TRANS ("Item unavailable");\r
+            case 5:   return NEEDS_TRANS ("Internal error");\r
+            case 6:   return NEEDS_TRANS ("Generic error");\r
+            case 7:   return NEEDS_TRANS ("Item already owned");\r
+            case 8:   return NEEDS_TRANS ("Item not owned");\r
+            default:  return NEEDS_TRANS ("Unknown status");\r
         }\r
+    }\r
 \r
-        notifyAboutPurchaseResult ({}, false, statusCodeUserString);\r
+    static bool wasSuccessful (int responseCode)\r
+    {\r
+        return responseCode == 0;\r
     }\r
 \r
-    //==============================================================================\r
-    static String statusCodeToUserString (int statusCode)\r
+    void purchaseCompleted (jobject purchase, int responseCode)\r
     {\r
-        switch (statusCode)\r
-        {\r
-            case 0:  return NEEDS_TRANS ("Success");\r
-            case 1:  return NEEDS_TRANS ("Cancelled by user");\r
-            case 2:  return NEEDS_TRANS ("Service unavailable");\r
-            case 3:  return NEEDS_TRANS ("Billing unavailable");\r
-            case 4:  return NEEDS_TRANS ("Item unavailable");\r
-            case 5:  return NEEDS_TRANS ("Internal error");\r
-            case 6:  return NEEDS_TRANS ("Generic error");\r
-            case 7:  return NEEDS_TRANS ("Item already owned");\r
-            case 8:  return NEEDS_TRANS ("Item not owned");\r
-            default: jassertfalse; return NEEDS_TRANS ("Unknown status");\r
-        }\r
+        notifyListenersAboutPurchase (buildPurchase (LocalRef<jobject> (purchase)),\r
+                                      wasSuccessful (responseCode),\r
+                                      getStatusDescriptionFromResponseCode (responseCode));\r
+    }\r
+\r
+    void purchaseConsumed (jstring productIdentifier, int responseCode)\r
+    {\r
+        notifyListenersAboutConsume (juceString (LocalRef<jstring> (productIdentifier)),\r
+                                     wasSuccessful (responseCode),\r
+                                     getStatusDescriptionFromResponseCode (responseCode));\r
+    }\r
+\r
+    void updateSkuDetails (jobject skuDetailsList)\r
+    {\r
+        jassert (! skuDetailsQueryCallbackQueue.empty());\r
+        skuDetailsQueryCallbackQueue.front() (LocalRef<jobject> (skuDetailsList));\r
+        skuDetailsQueryCallbackQueue.pop();\r
+    }\r
+\r
+    void updatePurchasesList (jobject purchasesList)\r
+    {\r
+        jassert (! purchasesListQueryCallbackQueue.empty());\r
+        purchasesListQueryCallbackQueue.front() (LocalRef<jobject> (purchasesList));\r
+        purchasesListQueryCallbackQueue.pop();\r
     }\r
 \r
     //==============================================================================\r
     InAppPurchases& owner;\r
-    GlobalRef inAppBillingService, serviceConnection;\r
-    std::unique_ptr<ThreadPool> threadPool;\r
+    GlobalRef billingClient;\r
 \r
-    CriticalSection getProductsInformationJobResultsLock,\r
-                    getProductsBoughtJobResultsLock,\r
-                    consumePurchaseJobResultsLock;\r
+    std::queue<std::function<void(LocalRef<jobject>)>> skuDetailsQueryCallbackQueue,\r
+                                                       purchasesListQueryCallbackQueue;\r
 \r
-    Array<Array<InAppPurchases::Product>> getProductsInformationJobResults;\r
-    Array<GetProductsBoughtJob::Result> getProductsBoughtJobResults;\r
-    Array<ConsumePurchaseJob::Result> consumePurchaseJobResults;\r
+    //==============================================================================\r
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)\r
 };\r
 \r
 \r
-//==============================================================================\r
-void juce_inAppPurchaseCompleted (void* intentData)\r
-{\r
-    if (auto* instance = InAppPurchases::getInstance())\r
-        instance->pimpl->inAppPurchaseCompleted (static_cast<jobject> (intentData));\r
-}\r
+InAppPurchases::Pimpl::JuceBillingClient_Class InAppPurchases::Pimpl::JuceBillingClient;\r
 \r
 } // namespace juce\r
index cc25f5ec51ad1a3966c03a04aa10822c9169e4af..3d66bd0600cacf035446e95e0b97b49d2288c793 100644 (file)
@@ -196,7 +196,7 @@ struct InAppPurchases::Pimpl   : public SKDelegateAndPaymentObserver
         [productsRequest start];\r
     }\r
 \r
-    void purchaseProduct (const String& productIdentifier, bool, const StringArray&, bool)\r
+    void purchaseProduct (const String& productIdentifier, const String&, bool)\r
     {\r
         if (! [SKPaymentQueue canMakePayments])\r
         {\r
index dc1fd76092d32015c333890dbd22c7d0db563b24..499c080ab8e3635ae257a724efeec8e2beac16c9 100644 (file)
 \r
  BEGIN_JUCE_MODULE_DECLARATION\r
 \r
-  ID:               juce_video\r
-  vendor:           juce\r
-  version:          5.4.5\r
-  name:             JUCE video playback and capture classes\r
-  description:      Classes for playing video and capturing camera input.\r
-  website:          http://www.juce.com/juce\r
-  license:          GPL/Commercial\r
-\r
-  dependencies:     juce_gui_extra\r
-  OSXFrameworks:    AVKit AVFoundation CoreMedia\r
-  iOSFrameworks:    AVKit AVFoundation CoreMedia\r
+  ID:                 juce_video\r
+  vendor:             juce\r
+  version:            5.4.6\r
+  name:               JUCE video playback and capture classes\r
+  description:        Classes for playing video and capturing camera input.\r
+  website:            http://www.juce.com/juce\r
+  license:            GPL/Commercial\r
+\r
+  dependencies:       juce_gui_extra\r
+  OSXFrameworks:      AVKit AVFoundation CoreMedia\r
+  iOSFrameworks:      AVKit AVFoundation CoreMedia\r
 \r
  END_JUCE_MODULE_DECLARATION\r
 \r
index 2eedb92191fc40b9c2ec101279a9535d07c95863..ae1aa9e594d46f6fff999728998dc3d6a7577da9 100644 (file)
@@ -1608,7 +1608,7 @@ private:
 \r
                 // When exception occurs, CameraCaptureSession.close will never finish, so\r
                 // we should not wait for it. For fatal error an exception does occur, but\r
-                // it is catched internally in Java...\r
+                // it is caught internally in Java...\r
                 if (jniCheckHasExceptionOccurredAndClear() || scopedCameraDevice.fatalErrorOccurred.get())\r
                 {\r
                     JUCE_CAMERA_LOG ("Exception or fatal error occurred while closing Capture Session, closing by force");\r
index edefe326c1c78c2a268eb21ba984827e5d7808f4..18a881cfc4668ed671fd5f5b7b114bf17197f560 100644 (file)
@@ -746,7 +746,7 @@ private:
 \r
                 JUCE_CAMERA_LOG ("Available image codec types: " + typesString);\r
                 JUCE_CAMERA_LOG ("Still image stabilization supported: " + String ((int) stillImageOutput.stillImageStabilizationSupported));\r
-                JUCE_CAMERA_LOG ("Automatically enableds still image stabilization when available: " + String ((int) stillImageOutput.automaticallyEnablesStillImageStabilizationWhenAvailable));\r
+                JUCE_CAMERA_LOG ("Automatically enables still image stabilization when available: " + String ((int) stillImageOutput.automaticallyEnablesStillImageStabilizationWhenAvailable));\r
 \r
                 JUCE_CAMERA_LOG ("Output settings for image output: " + nsStringToJuce ([stillImageOutput.outputSettings description]));\r
             }\r