JUCE breaking changes
=====================
+Version 7.0.2
+=============
+
+Change
+------
+The default macOS and iOS deployment targets set by the Projucer have been
+increased to macOS 10.13 and iOS 11 respectively.
+
+Possible Issues
+---------------
+Projects using the Projucer's default minimum deployment target will have their
+minimum deployment target increased.
+
+Workaround
+----------
+If you need a lower minimum deployment target then you must set this in the
+Projucer's Xcode build configuration settings.
+
+Rationale
+---------
+Xcode 14 no longer supports deployment targets lower than macOS 10.13 and iOS
+11.
+
+
+Change
+------
+The ARA SDK expected by JUCE has been updated to version 2.2.0.
+
+Possible Issues
+---------------
+Builds using earlier versions of the ARA SDK will fail to compile.
+
+Workaround
+----------
+The ARA SDK configured in JUCE must be updated to version 2.2.0.
+
+Rationale
+---------
+Version 2.2.0 is the latest official release of the ARA SDK.
+
+
+Change
+------
+The Thread::startThread (int) and Thread::setPriority (int) methods have been
+removed. A new Thread priority API has been introduced.
+
+Possible Issues
+---------------
+Code will fail to compile.
+
+Workaround
+----------
+Rather than using an integer thread priority you must instead use a value from
+the Thread::Priority enum. Thread::setPriority and Thread::getPriority should
+only be called from the target thread. To start a Thread with a realtime
+performance profile you must call startRealtimeThread.
+
+Rationale
+---------
+Operating systems are moving away from a specific thread priority and towards
+more granular control over which types of cores can be used and things like
+power throttling options. In particular, it is no longer possible to map a 0-10
+integer to a meaningful performance range on macOS ARM using the pthread
+interface. Using a more modern interface grants us access to more runtime
+options, but also changes how we can work with threads. The two most
+significant changes are that we cannot mix operations using the new and old
+interfaces, and that changing a priority using the new interface can only be
+done on the currently running thread.
+
+
+Change
+------
+The constructor of WebBrowserComponent now requires passing in an instance of
+a new Options class instead of a single option boolean. The
+WindowsWebView2WebBrowserComponent class was removed.
+
+Possible Issues
+---------------
+Code using the WebBrowserComponent's boolean parameter to indicate if a
+webpage should be unloaded when the component is hidden, will now fail to
+compile. Additionally, any code using the WindowsWebView2WebBrowserComponent
+class will fail to compile. Code relying on the default value of the
+WebBrowserComponent's constructor are not affected.
+
+Workaround
+----------
+Instead of passing in a single boolean to the WebBrowserComponent's
+constructor you should now set this option via tha
+WebBrowserComponent::Options::withKeepPageLoadedWhenBrowserIsHidden method.
+
+If you were previously using WindowsWebView2WebBrowserComponent to indicate to
+JUCE that you prefer JUCE to use Windows' Webview2 browser backend, you now do
+this by setting the WebBrowserComponent::Options::withBackend method. The
+WebView2Preferences can now be modified with the methods in
+WebBrowserComponent::Options::WinWebView2.
+
+Rationale
+---------
+The old API made adding further options to the WebBrowserComponent cumbersome
+especially as the WindowsWebView2WebBrowserComponent already had a parameter
+very similar to the above Options class, whereas the base class did not use
+such a parameter. Furthermore, using an option to specify the preferred
+browser backend is more intuitive then requiring the user to derive from a
+special class, especially if additional browser backends are added in the
+future.
+
+
+Change
+------
+The function AudioIODeviceCallback::audioDeviceIOCallback() was removed.
+
+Possible Issues
+---------------
+Code overriding audioDeviceIOCallback() will fail to compile.
+
+Workaround
+----------
+Affected classes should override the audioDeviceIOCallbackWithContext() function
+instead.
+
+Rationale
+---------
+The audioDeviceIOCallbackWithContext() function fulfills the same role as
+audioDeviceIOCallback(), it just has an extra parameter. Hence the
+audioDeviceIOCallback() function was superfluous.
+
+
+Change
+------
+The type representing multi-channel audio data has been changed from T** to
+T* const*. Affected classes are AudioIODeviceCallback, AudioBuffer and
+AudioFormatReader.
+
+Possible Issues
+---------------
+Code overriding the affected AudioIODeviceCallback and AudioFormatReader
+functions will fail to compile. Code that interacts with the return value of
+AudioBuffer::getArrayOfReadPointers() and AudioBuffer::getArrayOfWritePointers()
+may fail to compile.
+
+Workaround
+----------
+Functions overriding the affected AudioIODeviceCallback and AudioFormatReader
+members will need to be changed to confirm to the new signature. Type
+declarations related to getArrayOfReadPointers() and getArrayOfWritePointers()
+of AudioBuffer may have to be adjusted.
+
+Rationale
+---------
+While the previous signature permitted it, changing the channel pointers by the
+previously used types was already being considered illegal. The earlier type
+however prevented passing T** values to parameters with type const T**. In some
+places this necessitated the usage of const_cast. The new signature can bind to
+T** values and the awkward casting can be avoided.
+
+
+Change
+------
+The minimum supported C++ standard is now C++17 and the oldest supported
+compilers on Linux are now GCC 7.0 and Clang 6.0.
+
+Possible Issues
+---------------
+Older compilers will no longer be able to compile JUCE.
+
+Workaround
+----------
+No workaround is available.
+
+Rationale
+---------
+This compiler upgrade will allow the use of C++17 within the framework.
+
+
+Change
+------
+Resource forks are no longer generated for Audio Unit plug-ins.
+
+Possible Issues
+---------------
+New builds of JUCE Audio Units may no longer load in old hosts that use the
+Component Manager to discover plug-ins.
+
+Workaround
+----------
+No workaround is available.
+
+Rationale
+---------
+The Component Manager is deprecated in macOS 10.8 and later, so the majority of
+hosts have now implemented support for the new plist-based discovery mechanism.
+The new AudioUnitSDK (https://github.com/apple/AudioUnitSDK) provided by Apple
+to replace the old Core Audio Utility Classes no longer includes the files
+required to generate resource forks.
+
+
+Change
+------
+Previously, the AudioProcessorGraph would call processBlockBypassed on any
+processor for which setBypassed had previously been called. Now, the
+AudioProcessorGraph will now only call processBlockBypassed if those processors
+do not have dedicated bypass parameters.
+
+Possible Issues
+---------------
+Processors with non-functional bypass parameters may not bypass in the same way
+as before.
+
+Workaround
+----------
+For each AudioProcessor owned by a Graph, ensure that either: the processor has
+a working bypass parameter that correctly affects the output of processBlock();
+or, the processor has no bypass parameter, in which case processBlockBypassed()
+will be called as before.
+
+Rationale
+---------
+The documentation for AudioProcessor::getBypassParameter() states that if this
+function returns non-null, then processBlockBypassed() should never be called,
+but the AudioProcessorGraph was breaking this rule. Calling
+processBlockBypassed() on AudioProcessors with bypass parameters is likely to
+result in incorrect or unexpected output if this function is not overridden.
+The new behaviour obeys the contract set out in the AudioProcessor
+documentation.
+
+
Version 7.0.2
=============
cmake_minimum_required(VERSION 3.15)
-project(JUCE VERSION 7.0.2 LANGUAGES C CXX)
+project(JUCE VERSION 7.0.3 LANGUAGES C CXX)
include(CMakeDependentOption)
# ==================================================================================================
# Install configuration
-if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.14")
- set(extra_version_arg ARCH_INDEPENDENT)
-endif()
-
include(CMakePackageConfigHelpers)
write_basic_package_version_file("${JUCE_BINARY_DIR}/JUCEConfigVersion.cmake"
VERSION ${JUCE_VERSION}
"${JUCE_CMAKE_UTILS_DIR}/juce_runtime_arch_detection.cpp"
DESTINATION "${JUCE_INSTALL_DESTINATION}")
-install(EXPORT LV2_HELPER NAMESPACE juce:: DESTINATION "${JUCE_INSTALL_DESTINATION}")
+if("${CMAKE_SOURCE_DIR}" STREQUAL "${JUCE_SOURCE_DIR}")
+ _juce_add_lv2_manifest_helper_target()
+ install(TARGETS juce_lv2_helper EXPORT LV2_HELPER DESTINATION "bin/JUCE-${JUCE_VERSION}")
+ install(EXPORT LV2_HELPER NAMESPACE juce:: DESTINATION "${JUCE_INSTALL_DESTINATION}")
+endif()
+
This file just lists the more notable headline features. For more detailed info\r
about changes and bugfixes please see the git log and BREAKING-CHANGES.txt.\r
\r
+Version 7.0.3\r
+ - Added a unique machine ID\r
+ - Added new threading classes\r
+ - Improved the performance of multiple OpenGL contexts\r
+ - Refactored AudioProcessorGraph\r
+ - Improved AudioDeviceManager sample rate handling \r
+ - Fixed Studio One drawing performance\r
+ - Updated the FLAC library\r
+\r
Version 7.0.2\r
- Fixed accessibility table navigation\r
- Fixed Android file access on older APIs\r
#### Building JUCE Projects
- __macOS/iOS__: Xcode 10.1 (macOS 10.13.6)
-- __Windows__: Windows 8.1 and Visual Studio 2015 Update 3 64-bit
-- __Linux__: g++ 5.0 or Clang 3.4 (for a full list of dependencies, see
+- __Windows__: Windows 8.1 and Visual Studio 2017
+- __Linux__: g++ 7.0 or Clang 6.0 (for a full list of dependencies, see
[here](/docs/Linux%20Dependencies.md)).
- __Android__: Android Studio on Windows, macOS or Linux
#### Deployment Targets
-- __macOS__: macOS 10.7
+- __macOS__: macOS 10.9
- __Windows__: Windows Vista
- __Linux__: Mainstream Linux distributions
- __iOS__: iOS 9.0
- [Oboe](modules/juce_audio_devices/native/oboe/) ([Apache 2.0](modules/juce_audio_devices/native/oboe/LICENSE))
- [FLAC](modules/juce_audio_formats/codecs/flac/) ([BSD](modules/juce_audio_formats/codecs/flac/Flac%20Licence.txt))
- [Ogg Vorbis](modules/juce_audio_formats/codecs/oggvorbis/) ([BSD](modules/juce_audio_formats/codecs/oggvorbis/Ogg%20Vorbis%20Licence.txt))
-- [CoreAudioUtilityClasses](modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/) ([Apple](modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp))
+- [AudioUnitSDK](modules/juce_audio_plugin_client/AU/AudioUnitSDK/) ([Apache 2.0](modules/juce_audio_plugin_client/AU/AudioUnitSDK/LICENSE.txt))
- [AUResources.r](modules/juce_audio_plugin_client/AUResources.r) ([Apple](modules/juce_audio_plugin_client/AUResources.r))
- [LV2](modules/juce_audio_processors/format_types/LV2_SDK/) ([ISC](modules/juce_audio_processors/format_types/LV2_SDK/lv2/COPYING))
- [pslextensions](modules/juce_audio_processors/format_types/pslextensions/ipslcontextinfo.h) ([Public domain](modules/juce_audio_processors/format_types/pslextensions/ipslcontextinfo.h))
## External dependencies
-- ARA SDK 2.1.0
+- ARA SDK 2.2.0
You can download the ARA SDK from Celemony's Github. The command below will recursively clone the
right version into the `ARA_SDK` directory
- git clone --recursive --branch releases/2.1.0 https://github.com/Celemony/ARA_SDK
+ git clone --recursive --branch releases/2.2.0 https://github.com/Celemony/ARA_SDK
## Enabling ARA features in JUCE
## What is supported?
-Currently JUCE supports VoiceOver on macOS and Narrator on Windows. The JUCE
-accessibility API exposes the following to these clients:
+Currently JUCE supports Narrator on Windows, VoiceOver on macOS and iOS, and
+TalkBack on Android. The JUCE accessibility API exposes the following to these
+clients:
- Title, description, and help text for UI elements
- Programmatic access to UI elements and text
build/juce_audio_formats/codecs/flac \
build/juce_audio_formats/codecs/oggvorbis \
build/juce_audio_devices/native \
- build/juce_audio_plugin_client/AU/CoreAudioUtilityClasses \
+ build/juce_audio_plugin_client/AU/AudioUnitSDK \
build/juce_browser_plugin_client/juce_browser_plugin.h \
build/juce_core/native \
build/juce_events/native \
clear();\r
}\r
\r
- void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
- float** outputChannelData, int numOutputChannels,\r
- int numberOfSamples) override\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+ float* const* outputChannelData, int numOutputChannels,\r
+ int numberOfSamples, const AudioIODeviceCallbackContext& context) override\r
{\r
+ ignoreUnused (context);\r
+\r
for (int i = 0; i < numberOfSamples; ++i)\r
{\r
float inputSample = 0;\r
\r
void audioDeviceStopped() override {}\r
\r
- void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
- float** outputChannelData, int numOutputChannels, int numSamples) override\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+ float* const* outputChannelData, int numOutputChannels,\r
+ int numSamples, const AudioIODeviceCallbackContext& context) override\r
{\r
+ ignoreUnused (context);\r
+\r
const ScopedLock sl (lock);\r
\r
if (testIsRunning)\r
// audio setup\r
formatManager.registerBasicFormats();\r
\r
- thread.startThread (3);\r
+ thread.startThread (Thread::Priority::normal);\r
\r
#ifndef JUCE_DEMO_RUNNER\r
RuntimePermissions::request (RuntimePermissions::recordAudio,\r
sampleRate = 0;\r
}\r
\r
- void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
- float** outputChannelData, int numOutputChannels,\r
- int numSamples) override\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+ float* const* outputChannelData, int numOutputChannels,\r
+ int numSamples, const AudioIODeviceCallbackContext& context) override\r
{\r
+ ignoreUnused (context);\r
+\r
const ScopedLock sl (writerLock);\r
\r
if (activeWriter.load() != nullptr && numInputChannels >= thumbnail.getNumChannels())\r
}\r
\r
//==============================================================================\r
- void audioDeviceIOCallback (const float** /*inputChannelData*/, int /*numInputChannels*/,\r
- float** outputChannelData, int numOutputChannels,\r
- int numSamples) override\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+ float* const* outputChannelData, int numOutputChannels,\r
+ int numSamples, const AudioIODeviceCallbackContext& context) override\r
{\r
+ ignoreUnused (inputChannelData, numInputChannels, context);\r
+\r
AudioBuffer<float> buffer (outputChannelData, numOutputChannels, numSamples);\r
buffer.clear();\r
\r
-# Automatically generated makefile, created by the Projucer
+# Automatically generated CMakeLists, created by the Projucer
# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!
cmake_minimum_required(VERSION 3.4.1)
+project(juce_jni_project)
+
set(BINARY_NAME "juce_jni")
set(OBOE_DIR "../../../../../modules/juce_audio_devices/native/oboe")
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/rmsl/juce/JuceActivity"]] [[-DJUCE_CONTENT_SHARING=1]] [[-DJUCE_ANDROID_GL_ES_VERSION_3_0=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.2]] [[-DJUCE_APP_VERSION_HEX=0x70002]])
+add_definitions([[-DJUCE_ANDROID=1]] [[-DJUCE_ANDROID_API_VERSION=23]] [[-DJUCE_PUSH_NOTIFICATIONS=1]] [[-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY="com/rmsl/juce/JuceActivity"]] [[-DJUCE_CONTENT_SHARING=1]] [[-DJUCE_ANDROID_GL_ES_VERSION_3_0=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.3]] [[-DJUCE_APP_VERSION_HEX=0x70003]])
include_directories( AFTER
"../../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src"
enable_language(ASM)
if(JUCE_BUILD_CONFIGURATION MATCHES "DEBUG")
- add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_analytics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_box2d=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1]] [[-DJUCE_MODULE_AVAILABLE_juce_video=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_USE_MP3AUDIOFORMAT=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0]] [[-DJUCE_STRICT_REFCOUNTEDPOINTER=1]] [[-DJUCE_USE_CAMERA=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.2]] [[-DJUCE_APP_VERSION_HEX=0x70002]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
+ add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70003]] [[-DJUCE_MODULE_AVAILABLE_juce_analytics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_box2d=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1]] [[-DJUCE_MODULE_AVAILABLE_juce_video=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_USE_MP3AUDIOFORMAT=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0]] [[-DJUCE_STRICT_REFCOUNTEDPOINTER=1]] [[-DJUCE_USE_CAMERA=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.3]] [[-DJUCE_APP_VERSION_HEX=0x70003]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
elseif(JUCE_BUILD_CONFIGURATION MATCHES "RELEASE")
- add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_analytics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_box2d=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1]] [[-DJUCE_MODULE_AVAILABLE_juce_video=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_USE_MP3AUDIOFORMAT=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0]] [[-DJUCE_STRICT_REFCOUNTEDPOINTER=1]] [[-DJUCE_USE_CAMERA=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.2]] [[-DJUCE_APP_VERSION_HEX=0x70002]] [[-DNDEBUG=1]])
+ add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70003]] [[-DJUCE_MODULE_AVAILABLE_juce_analytics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_box2d=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1]] [[-DJUCE_MODULE_AVAILABLE_juce_video=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_USE_MP3AUDIOFORMAT=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0]] [[-DJUCE_STRICT_REFCOUNTEDPOINTER=1]] [[-DJUCE_USE_CAMERA=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.3]] [[-DJUCE_APP_VERSION_HEX=0x70003]] [[-DNDEBUG=1]])
else()
message( FATAL_ERROR "No matching build-configuration found." )
endif()
"../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
- "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
"../../../../../modules/juce_core/native/juce_mac_Strings.mm"
"../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
"../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+ "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
"../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
"../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
"../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+ "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
"../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
"../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
"../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
"../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
"../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
"../../../../../modules/juce_gui_basics/juce_gui_basics.h"
"../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
- "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
"../../../../../modules/juce_core/native/juce_mac_Strings.mm"
"../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
"../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+ "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
"../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
"../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
"../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+ "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
"../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
"../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
"../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
"../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
"../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
"../../../../../modules/juce_gui_basics/juce_gui_basics.h"
"../../../JuceLibraryCode/JuceHeader.h"
PROPERTIES HEADER_FILE_ONLY TRUE)
-target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
-
if( JUCE_BUILD_CONFIGURATION MATCHES "DEBUG" )
- target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override)
+ target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override "-fsigned-char" )
endif()
if( JUCE_BUILD_CONFIGURATION MATCHES "RELEASE" )
- target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override)
+ target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override "-fsigned-char" )
endif()
find_library(log "log")
apply plugin: 'com.android.application'
android {
- compileSdkVersion 31
+ compileSdkVersion 33
+ namespace "com.rmsl.jucedemorunner"
externalNativeBuild {
cmake {
path "CMakeLists.txt"
defaultConfig {
applicationId "com.rmsl.jucedemorunner"
minSdkVersion 23
- targetSdkVersion 31
+ targetSdkVersion 33
externalNativeBuild {
cmake {
- arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=14", "-DCMAKE_CXX_EXTENSIONS=OFF"
+ arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=17", "-DCMAKE_CXX_EXTENSIONS=OFF"
}
}
}
}
externalNativeBuild {
cmake {
- arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-O0", "-DCMAKE_C_FLAGS_DEBUG=-O0"
+ cFlags "-O0"
+ cppFlags "-O0"
+ arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG"
}
}
dimension "default"
- }
+ }
release_ {
externalNativeBuild {
cmake {
- arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-O3", "-DCMAKE_C_FLAGS_RELEASE=-O3"
+ cFlags "-O3"
+ cppFlags "-O3"
+ arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE"
}
}
dimension "default"
- }
+ }
}
variantFilter { variant ->
<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="7.0.2"
- package="com.rmsl.jucedemorunner">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="7.0.3">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"
android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-feature android:glEsVersion="0x00030000" android:required="true"/>
<application android:label="@string/app_name" android:name="com.rmsl.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false">
- <activity android:name="com.rmsl.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize"
+ <activity android:name="com.rmsl.juce.JuceActivity" android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"
android:exported="true">
<intent-filter>
clear();\r
}\r
\r
- void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
- float** outputChannelData, int numOutputChannels,\r
- int numberOfSamples) override\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+ float* const* outputChannelData, int numOutputChannels,\r
+ int numberOfSamples, const AudioIODeviceCallbackContext& context) override\r
{\r
+ ignoreUnused (context);\r
+\r
for (int i = 0; i < numberOfSamples; ++i)\r
{\r
float inputSample = 0;\r
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.0.0'
+ classpath 'com.android.tools.build:gradle:7.3.0'
}
}
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
\ No newline at end of file
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_box2d=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_USE_MP3AUDIOFORMAT=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_USE_CAMERA=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.2" "-DJUCE_APP_VERSION_HEX=0x70002" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_box2d=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_USE_MP3AUDIOFORMAT=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_USE_CAMERA=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.3" "-DJUCE_APP_VERSION_HEX=0x70003" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -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_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := DemoRunner
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_box2d=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_USE_MP3AUDIOFORMAT=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_USE_CAMERA=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.2" "-DJUCE_APP_VERSION_HEX=0x70002" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_box2d=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_USE_MP3AUDIOFORMAT=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_USE_CAMERA=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.3" "-DJUCE_APP_VERSION_HEX=0x70003" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -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_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := DemoRunner
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
69330F27DD2C71609336C7D2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
DEAD_CODE_STRIPPING = YES;
"NDEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_analytics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_DEMO_RUNNER=1",
"JUCE_UNIT_TESTS=1",
"JUCER_XCODE_MAC_F6D2F4CF=1",
- "JUCE_APP_VERSION=7.0.2",
- "JUCE_APP_VERSION_HEX=0x70002",
+ "JUCE_APP_VERSION=7.0.3",
+ "JUCE_APP_VERSION_HEX=0x70003",
"JucePlugin_Build_VST=0",
"JucePlugin_Build_VST3=0",
"JucePlugin_Build_AU=0",
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
LLVM_LTO = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
B18D059E5616FA729F764229 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
COPY_PHASE_STRIP = NO;
"DEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_analytics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_DEMO_RUNNER=1",
"JUCE_UNIT_TESTS=1",
"JUCER_XCODE_MAC_F6D2F4CF=1",
- "JUCE_APP_VERSION=7.0.2",
- "JUCE_APP_VERSION_HEX=0x70002",
+ "JUCE_APP_VERSION=7.0.3",
+ "JUCE_APP_VERSION_HEX=0x70003",
"JucePlugin_Build_VST=0",
"JucePlugin_Build_VST3=0",
"JucePlugin_Build_AU=0",
INFOPLIST_FILE = Info-App.plist;
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
- MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
<key>CFBundleSignature</key>\r
<string>????</string>\r
<key>CFBundleShortVersionString</key>\r
- <string>7.0.2</string>\r
+ <string>7.0.3</string>\r
<key>CFBundleVersion</key>\r
- <string>7.0.2</string>\r
+ <string>7.0.3</string>\r
<key>NSHumanReadableCopyright</key>\r
<string>Copyright (c) 2020 - Raw Material Software Limited</string>\r
<key>NSHighResolutionCapable</key>\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
#include <windows.h>\r
\r
VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION 7,0,2,0\r
+FILEVERSION 7,0,3,0\r
BEGIN\r
BLOCK "StringFileInfo"\r
BEGIN\r
VALUE "CompanyName", "Raw Material Software Limited\0"\r
VALUE "LegalCopyright", "Copyright (c) 2020 - Raw Material Software Limited\0"\r
VALUE "FileDescription", "DemoRunner\0"\r
- VALUE "FileVersion", "7.0.2\0"\r
+ VALUE "FileVersion", "7.0.3\0"\r
VALUE "ProductName", "DemoRunner\0"\r
- VALUE "ProductVersion", "7.0.2\0"\r
+ VALUE "ProductVersion", "7.0.3\0"\r
END\r
END\r
\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
#include <windows.h>\r
\r
VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION 7,0,2,0\r
+FILEVERSION 7,0,3,0\r
BEGIN\r
BLOCK "StringFileInfo"\r
BEGIN\r
VALUE "CompanyName", "Raw Material Software Limited\0"\r
VALUE "LegalCopyright", "Copyright (c) 2020 - Raw Material Software Limited\0"\r
VALUE "FileDescription", "DemoRunner\0"\r
- VALUE "FileVersion", "7.0.2\0"\r
+ VALUE "FileVersion", "7.0.3\0"\r
VALUE "ProductName", "DemoRunner\0"\r
- VALUE "ProductVersion", "7.0.2\0"\r
+ VALUE "ProductVersion", "7.0.3\0"\r
END\r
END\r
\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
#include <windows.h>\r
\r
VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION 7,0,2,0\r
+FILEVERSION 7,0,3,0\r
BEGIN\r
BLOCK "StringFileInfo"\r
BEGIN\r
VALUE "CompanyName", "Raw Material Software Limited\0"\r
VALUE "LegalCopyright", "Copyright (c) 2020 - Raw Material Software Limited\0"\r
VALUE "FileDescription", "DemoRunner\0"\r
- VALUE "FileVersion", "7.0.2\0"\r
+ VALUE "FileVersion", "7.0.3\0"\r
VALUE "ProductName", "DemoRunner\0"\r
- VALUE "ProductVersion", "7.0.2\0"\r
+ VALUE "ProductVersion", "7.0.3\0"\r
END\r
END\r
\r
07EA85D22270E8EA13CA0BBE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
PRODUCT_NAME = "DemoRunner";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
69330F27DD2C71609336C7D2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
CODE_SIGN_ENTITLEMENTS = "App.entitlements";
"JUCE_CONTENT_SHARING=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_analytics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_DEMO_RUNNER=1",
"JUCE_UNIT_TESTS=1",
"JUCER_XCODE_IPHONE_5BC26AE3=1",
- "JUCE_APP_VERSION=7.0.2",
- "JUCE_APP_VERSION_HEX=0x70002",
+ "JUCE_APP_VERSION=7.0.3",
+ "JUCE_APP_VERSION_HEX=0x70003",
"JucePlugin_Build_VST=0",
"JucePlugin_Build_VST3=0",
"JucePlugin_Build_AU=0",
B18D059E5616FA729F764229 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
CODE_SIGN_ENTITLEMENTS = "App.entitlements";
"JUCE_CONTENT_SHARING=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_analytics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_DEMO_RUNNER=1",
"JUCE_UNIT_TESTS=1",
"JUCER_XCODE_IPHONE_5BC26AE3=1",
- "JUCE_APP_VERSION=7.0.2",
- "JUCE_APP_VERSION_HEX=0x70002",
+ "JUCE_APP_VERSION=7.0.3",
+ "JUCE_APP_VERSION_HEX=0x70003",
"JucePlugin_Build_VST=0",
"JucePlugin_Build_VST3=0",
"JucePlugin_Build_AU=0",
C01EC82F42B640CA1E54AD53 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "DemoRunner";
SDKROOT = iphoneos;
<key>CFBundleSignature</key>\r
<string>????</string>\r
<key>CFBundleShortVersionString</key>\r
- <string>7.0.2</string>\r
+ <string>7.0.3</string>\r
<key>CFBundleVersion</key>\r
- <string>7.0.2</string>\r
+ <string>7.0.3</string>\r
<key>NSHumanReadableCopyright</key>\r
<string>Copyright (c) 2020 - Raw Material Software Limited</string>\r
<key>NSHighResolutionCapable</key>\r
<?xml version="1.0" encoding="UTF-8"?>\r
\r
<JUCERPROJECT name="DemoRunner" projectType="guiapp" defines="JUCE_DEMO_RUNNER=1 JUCE_UNIT_TESTS=1"\r
- bundleIdentifier="com.rmsl.jucedemorunner" version="7.0.2" companyName="Raw Material Software Limited"\r
+ bundleIdentifier="com.rmsl.jucedemorunner" version="7.0.3" companyName="Raw Material Software Limited"\r
companyCopyright="Copyright (c) 2020 - Raw Material Software Limited"\r
companyWebsite="https://www.juce.com/" companyEmail="info@juce.com"\r
id="yj7xMM" reportAppUsage="0" useAppConfig="0" addUsingNamespaceToJuceHeader="1"\r
<ANDROIDSTUDIO targetFolder="Builds/Android" androidMinimumSDK="23" microphonePermissionNeeded="1"\r
androidBluetoothNeeded="1" androidExternalReadNeeded="1" androidExternalWriteNeeded="1"\r
androidEnableContentSharing="1" androidExtraAssetsFolder="../Assets"\r
- smallIcon="YyqWd2" bigIcon="YyqWd2" cameraPermissionNeeded="1"\r
- androidTargetSDK="31">\r
+ smallIcon="YyqWd2" bigIcon="YyqWd2" cameraPermissionNeeded="1">\r
<CONFIGURATIONS>\r
<CONFIGURATION isDebug="1" name="Debug" recommendedWarnings="LLVM"/>\r
<CONFIGURATION isDebug="0" name="Release" recommendedWarnings="LLVM"/>\r
{\r
const char* const projectName = "DemoRunner";\r
const char* const companyName = "Raw Material Software Limited";\r
- const char* const versionString = "7.0.2";\r
- const int versionNumber = 0x70002;\r
+ const char* const versionString = "7.0.3";\r
+ const int versionNumber = 0x70003;\r
}\r
#endif\r
AnimationAppDemo()\r
{\r
setSize (800, 600);\r
- setFramesPerSecond (60);\r
+ setSynchroniseToVBlank (true);\r
}\r
\r
void update() override\r
{\r
setOpaque (true);\r
imageList.setDirectory (File::getSpecialLocation (File::userPicturesDirectory), true, true);\r
- directoryThread.startThread (1);\r
+ directoryThread.startThread (Thread::Priority::background);\r
\r
fileTree.setTitle ("Files");\r
fileTree.addListener (this);\r
setOpaque (true);\r
\r
movieList.setDirectory (File::getSpecialLocation (File::userMoviesDirectory), true, true);\r
- directoryThread.startThread (1);\r
+ directoryThread.startThread (Thread::Priority::background);\r
\r
fileTree.setTitle ("Files");\r
fileTree.addListener (this);\r
\r
#pragma once\r
\r
+#include <ARA_Library/Utilities/ARAPitchInterpretation.h>\r
+#include <ARA_Library/Utilities/ARATimelineConversion.h>\r
+\r
+//==============================================================================\r
+class ARADemoPluginAudioModification : public ARAAudioModification\r
+{\r
+public:\r
+ ARADemoPluginAudioModification (ARAAudioSource* audioSource,\r
+ ARA::ARAAudioModificationHostRef hostRef,\r
+ const ARAAudioModification* optionalModificationToClone)\r
+ : ARAAudioModification (audioSource, hostRef, optionalModificationToClone)\r
+ {\r
+ if (optionalModificationToClone != nullptr)\r
+ dimmed = static_cast<const ARADemoPluginAudioModification*> (optionalModificationToClone)->dimmed;\r
+ }\r
+\r
+ bool isDimmed() const { return dimmed; }\r
+ void setDimmed (bool shouldDim) { dimmed = shouldDim; }\r
+\r
+private:\r
+ bool dimmed = false;\r
+};\r
\r
//==============================================================================\r
struct PreviewState\r
SharedTimeSliceThread()\r
: TimeSliceThread (String (JucePlugin_Name) + " ARA Sample Reading Thread")\r
{\r
- startThread (7); // Above default priority so playback is fluent, but below realtime\r
+ startThread (Priority::high); // Above default priority so playback is fluent, but below realtime\r
}\r
};\r
\r
void writeInto (AudioBuffer<float>& buffer)\r
{\r
if (loopRange.getLength() == 0)\r
+ {\r
buffer.clear();\r
+ return;\r
+ }\r
\r
const auto numChannelsToCopy = std::min (inputBuffer->getNumChannels(), buffer.getNumChannels());\r
\r
int64 pos;\r
};\r
\r
-class OptionalRange\r
-{\r
-public:\r
- using Type = Range<int64>;\r
-\r
- OptionalRange() : valid (false) {}\r
- explicit OptionalRange (Type valueIn) : valid (true), value (std::move (valueIn)) {}\r
-\r
- explicit operator bool() const noexcept { return valid; }\r
-\r
- const auto& operator*() const\r
- {\r
- jassert (valid);\r
- return value;\r
- }\r
-\r
-private:\r
- bool valid;\r
- Type value;\r
-};\r
-\r
//==============================================================================\r
// Returns the modified sample range in the output buffer.\r
-inline OptionalRange readPlaybackRangeIntoBuffer (Range<double> playbackRange,\r
- const ARAPlaybackRegion* playbackRegion,\r
- AudioBuffer<float>& buffer,\r
- const std::function<AudioFormatReader* (ARA::PlugIn::AudioSource*)>& getReader)\r
+inline std::optional<Range<int64>> readPlaybackRangeIntoBuffer (Range<double> playbackRange,\r
+ const ARAPlaybackRegion* playbackRegion,\r
+ AudioBuffer<float>& buffer,\r
+ const std::function<AudioFormatReader* (ARAAudioSource*)>& getReader)\r
{\r
- const auto rangeInAudioModificationTime = playbackRange.movedToStartAt (playbackRange.getStart()\r
- - playbackRegion->getStartInAudioModificationTime());\r
+ const auto rangeInAudioModificationTime = playbackRange - playbackRegion->getStartInPlaybackTime()\r
+ + playbackRegion->getStartInAudioModificationTime();\r
\r
- const auto audioSource = playbackRegion->getAudioModification()->getAudioSource();\r
+ const auto audioModification = playbackRegion->getAudioModification<ARADemoPluginAudioModification>();\r
+ const auto audioSource = audioModification->getAudioSource();\r
const auto audioModificationSampleRate = audioSource->getSampleRate();\r
\r
const Range<int64_t> sampleRangeInAudioModification {\r
\r
const auto inputOffset = jlimit ((int64_t) 0, audioSource->getSampleCount(), sampleRangeInAudioModification.getStart());\r
\r
- const auto outputOffset = -std::min (sampleRangeInAudioModification.getStart(), (int64_t) 0);\r
+ // With the output offset it can always be said of the output buffer, that the zeroth element\r
+ // corresponds to beginning of the playbackRange.\r
+ const auto outputOffset = std::max (-sampleRangeInAudioModification.getStart(), (int64_t) 0);\r
\r
/* TODO: Handle different AudioSource and playback sample rates.\r
\r
}();\r
\r
if (readLength == 0)\r
- return OptionalRange { {} };\r
+ return Range<int64>();\r
\r
auto* reader = getReader (audioSource);\r
\r
if (reader != nullptr && reader->read (&buffer, (int) outputOffset, (int) readLength, inputOffset, true, true))\r
- return OptionalRange { { outputOffset, readLength } };\r
+ {\r
+ if (audioModification->isDimmed())\r
+ buffer.applyGain ((int) outputOffset, (int) readLength, 0.25f);\r
+\r
+ return Range<int64>::withStartAndLength (outputOffset, readLength);\r
+ }\r
\r
return {};\r
}\r
continue;\r
}\r
\r
+ // Apply dim if enabled\r
+ if (playbackRegion->getAudioModification<ARADemoPluginAudioModification>()->isDimmed())\r
+ readBuffer.applyGain (startInBuffer, numSamplesToRead, 0.25f); // dim by about 12 dB\r
+\r
+ // Mix output of all regions\r
if (didRenderAnyRegion)\r
{\r
// Mix local buffer into the output buffer.\r
// We're subclassing here only to provide a proper default c'tor for our shared resource\r
\r
SharedResourcePointer<SharedTimeSliceThread> sharedTimesliceThread;\r
- std::map<ARA::PlugIn::AudioSource*, PossiblyBufferedReader> audioSourceReaders;\r
+ std::map<ARAAudioSource*, PossiblyBufferedReader> audioSourceReaders;\r
bool useBufferedAudioSourceReader = true;\r
int numChannels = 2;\r
double sampleRate = 48000.0;\r
\r
void didAddRegionSequence (ARA::PlugIn::RegionSequence* rs) noexcept override\r
{\r
- auto* sequence = dynamic_cast<ARARegionSequence*> (rs);\r
+ auto* sequence = static_cast<ARARegionSequence*> (rs);\r
sequence->addListener (this);\r
regionSequences.insert (sequence);\r
asyncConfigCallback.startConfigure();\r
if (regionIsAssignedToEditor)\r
{\r
const auto previewTime = previewState->previewTime.load();\r
+ const auto previewDimmed = previewedRegion->getAudioModification<ARADemoPluginAudioModification>()\r
+ ->isDimmed();\r
\r
- if (lastPreviewTime != previewTime || lastPlaybackRegion != previewedRegion)\r
+ if (lastPreviewTime != previewTime\r
+ || lastPlaybackRegion != previewedRegion\r
+ || lastPreviewDimmed != previewDimmed)\r
{\r
Range<double> previewRangeInPlaybackTime { previewTime - 0.25, previewTime + 0.25 };\r
previewBuffer->clear();\r
{\r
lastPreviewTime = previewTime;\r
lastPlaybackRegion = previewedRegion;\r
+ lastPreviewDimmed = previewDimmed;\r
previewLooper = Looper (previewBuffer.get(), *rangeInOutput);\r
}\r
}\r
AsyncConfigurationCallback asyncConfigCallback { [this] { configure(); } };\r
double lastPreviewTime = 0.0;\r
ARAPlaybackRegion* lastPlaybackRegion = nullptr;\r
+ bool lastPreviewDimmed = false;\r
std::unique_ptr<AudioBuffer<float>> previewBuffer;\r
Looper previewLooper;\r
\r
double sampleRate = 48000.0;\r
SharedResourcePointer<SharedTimeSliceThread> timeSliceThread;\r
- std::map<ARA::PlugIn::AudioSource*, std::unique_ptr<BufferingAudioReader>> audioSourceReaders;\r
+ std::map<ARAAudioSource*, std::unique_ptr<BufferingAudioReader>> audioSourceReaders;\r
\r
std::set<ARARegionSequence*> regionSequences;\r
};\r
PreviewState previewState;\r
\r
protected:\r
+ ARAAudioModification* doCreateAudioModification (ARAAudioSource* audioSource,\r
+ ARA::ARAAudioModificationHostRef hostRef,\r
+ const ARAAudioModification* optionalModificationToClone) noexcept override\r
+ {\r
+ return new ARADemoPluginAudioModification (audioSource,\r
+ hostRef,\r
+ static_cast<const ARADemoPluginAudioModification*> (optionalModificationToClone));\r
+ }\r
+\r
ARAPlaybackRenderer* doCreatePlaybackRenderer() noexcept override\r
{\r
return new PlaybackRenderer (getDocumentController());\r
bool doRestoreObjectsFromStream (ARAInputStream& input,\r
const ARARestoreObjectsFilter* filter) noexcept override\r
{\r
- ignoreUnused (input, filter);\r
- return false;\r
+ // Start reading data from the archive, starting with the number of audio modifications in the archive\r
+ const auto numAudioModifications = input.readInt64();\r
+\r
+ // Loop over stored audio modification data\r
+ for (int64 i = 0; i < numAudioModifications; ++i)\r
+ {\r
+ const auto progressVal = (float) i / (float) numAudioModifications;\r
+ getDocumentController()->getHostArchivingController()->notifyDocumentUnarchivingProgress (progressVal);\r
+\r
+ // Read audio modification persistent ID and analysis result from archive\r
+ const String persistentID = input.readString();\r
+ const bool dimmed = input.readBool();\r
+\r
+ // Find audio modification to restore the state to (drop state if not to be loaded)\r
+ auto audioModification = filter->getAudioModificationToRestoreStateWithID<ARADemoPluginAudioModification> (persistentID.getCharPointer());\r
+\r
+ if (audioModification == nullptr)\r
+ continue;\r
+\r
+ const bool dimChanged = (dimmed != audioModification->isDimmed());\r
+ audioModification->setDimmed (dimmed);\r
+\r
+ // If the dim state changed, send a sample content change notification without notifying the host\r
+ if (dimChanged)\r
+ {\r
+ audioModification->notifyContentChanged (ARAContentUpdateScopes::samplesAreAffected(), false);\r
+\r
+ for (auto playbackRegion : audioModification->getPlaybackRegions())\r
+ playbackRegion->notifyContentChanged (ARAContentUpdateScopes::samplesAreAffected(), false);\r
+ }\r
+ }\r
+\r
+ getDocumentController()->getHostArchivingController()->notifyDocumentUnarchivingProgress (1.0f);\r
+\r
+ return ! input.failed();\r
}\r
\r
bool doStoreObjectsToStream (ARAOutputStream& output, const ARAStoreObjectsFilter* filter) noexcept override\r
{\r
- ignoreUnused (output, filter);\r
- return false;\r
+ // This example implementation only deals with audio modification states\r
+ const auto& audioModificationsToPersist { filter->getAudioModificationsToStore<ARADemoPluginAudioModification>() };\r
+\r
+ const auto reportProgress = [archivingController = getDocumentController()->getHostArchivingController()] (float p)\r
+ {\r
+ archivingController->notifyDocumentArchivingProgress (p);\r
+ };\r
+\r
+ const ScopeGuard scope { [&reportProgress] { reportProgress (1.0f); } };\r
+\r
+ // Write the number of audio modifications we are persisting\r
+ const auto numAudioModifications = audioModificationsToPersist.size();\r
+\r
+ if (! output.writeInt64 ((int64) numAudioModifications))\r
+ return false;\r
+\r
+ // For each audio modification to persist, persist its ID followed by whether it's dimmed\r
+ for (size_t i = 0; i < numAudioModifications; ++i)\r
+ {\r
+ // Write persistent ID and dim state\r
+ if (! output.writeString (audioModificationsToPersist[i]->getPersistentID()))\r
+ return false;\r
+\r
+ if (! output.writeBool (audioModificationsToPersist[i]->isDimmed()))\r
+ return false;\r
+\r
+ const auto progressVal = (float) i / (float) numAudioModifications;\r
+ reportProgress (progressVal);\r
+ }\r
+\r
+ return true;\r
}\r
};\r
\r
struct PlayHeadState\r
{\r
- void update (AudioPlayHead* aph)\r
+ void update (const Optional<AudioPlayHead::PositionInfo>& info)\r
{\r
- const auto info = aph->getPosition();\r
-\r
- if (info.hasValue() && info->getIsPlaying())\r
+ if (info.hasValue())\r
{\r
- isPlaying.store (true);\r
- timeInSeconds.store (info->getTimeInSeconds().orFallback (0));\r
+ isPlaying.store (info->getIsPlaying(), std::memory_order_relaxed);\r
+ timeInSeconds.store (info->getTimeInSeconds().orFallback (0), std::memory_order_relaxed);\r
+ isLooping.store (info->getIsLooping(), std::memory_order_relaxed);\r
+ const auto loopPoints = info->getLoopPoints();\r
+\r
+ if (loopPoints.hasValue())\r
+ {\r
+ loopPpqStart = loopPoints->ppqStart;\r
+ loopPpqEnd = loopPoints->ppqEnd;\r
+ }\r
}\r
else\r
{\r
- isPlaying.store (false);\r
+ isPlaying.store (false, std::memory_order_relaxed);\r
+ isLooping.store (false, std::memory_order_relaxed);\r
}\r
}\r
\r
- std::atomic<bool> isPlaying { false };\r
- std::atomic<double> timeInSeconds { 0.0 };\r
+ std::atomic<bool> isPlaying { false },\r
+ isLooping { false };\r
+ std::atomic<double> timeInSeconds { 0.0 },\r
+ loopPpqStart { 0.0 },\r
+ loopPpqEnd { 0.0 };\r
};\r
\r
//==============================================================================\r
//==============================================================================\r
void prepareToPlay (double sampleRate, int samplesPerBlock) override\r
{\r
- playHeadState.isPlaying.store (false);\r
+ playHeadState.update (nullopt);\r
prepareToPlayForARA (sampleRate, samplesPerBlock, getMainBusNumOutputChannels(), getProcessingPrecision());\r
}\r
\r
void releaseResources() override\r
{\r
- playHeadState.isPlaying.store (false);\r
+ playHeadState.update (nullopt);\r
releaseResourcesForARA();\r
}\r
\r
ScopedNoDenormals noDenormals;\r
\r
auto* audioPlayHead = getPlayHead();\r
- playHeadState.update (audioPlayHead);\r
+ playHeadState.update (audioPlayHead->getPosition());\r
\r
if (! processBlockForARA (buffer, isRealtime(), audioPlayHead))\r
processBlockBypassed (buffer, midiMessages);\r
const String getName() const override { return "ARAPluginDemo"; }\r
bool acceptsMidi() const override { return true; }\r
bool producesMidi() const override { return true; }\r
- double getTailLengthSeconds() const override { return 0.0; }\r
+\r
+ double getTailLengthSeconds() const override\r
+ {\r
+ double tail;\r
+ if (getTailLengthSecondsForARA (tail))\r
+ return tail;\r
+\r
+ return 0.0;\r
+ }\r
\r
//==============================================================================\r
int getNumPrograms() override { return 0; }\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARADemoPluginAudioProcessorImpl)\r
};\r
\r
+//==============================================================================\r
+class TimeToViewScaling\r
+{\r
+public:\r
+ class Listener\r
+ {\r
+ public:\r
+ virtual ~Listener() = default;\r
+\r
+ virtual void zoomLevelChanged (double newPixelPerSecond) = 0;\r
+ };\r
+\r
+ void addListener (Listener* l) { listeners.add (l); }\r
+ void removeListener (Listener* l) { listeners.remove (l); }\r
+\r
+ TimeToViewScaling() = default;\r
+\r
+ void zoom (double factor)\r
+ {\r
+ zoomLevelPixelPerSecond = jlimit (minimumZoom, minimumZoom * 32, zoomLevelPixelPerSecond * factor);\r
+ setZoomLevel (zoomLevelPixelPerSecond);\r
+ }\r
+\r
+ void setZoomLevel (double pixelPerSecond)\r
+ {\r
+ zoomLevelPixelPerSecond = pixelPerSecond;\r
+ listeners.call ([this] (Listener& l) { l.zoomLevelChanged (zoomLevelPixelPerSecond); });\r
+ }\r
+\r
+ int getXForTime (double time) const\r
+ {\r
+ return roundToInt (time * zoomLevelPixelPerSecond);\r
+ }\r
+\r
+ double getTimeForX (int x) const\r
+ {\r
+ return x / zoomLevelPixelPerSecond;\r
+ }\r
+\r
+private:\r
+ static constexpr auto minimumZoom = 10.0;\r
+\r
+ double zoomLevelPixelPerSecond = minimumZoom * 4;\r
+ ListenerList<Listener> listeners;\r
+};\r
+\r
+class RulersView : public Component,\r
+ public SettableTooltipClient,\r
+ private Timer,\r
+ private TimeToViewScaling::Listener,\r
+ private ARAMusicalContext::Listener\r
+{\r
+public:\r
+ class CycleMarkerComponent : public Component\r
+ {\r
+ void paint (Graphics& g) override\r
+ {\r
+ g.setColour (Colours::yellow.darker (0.2f));\r
+ const auto bounds = getLocalBounds().toFloat();\r
+ g.drawRoundedRectangle (bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), 6.0f, 2.0f);\r
+ }\r
+ };\r
+\r
+ RulersView (PlayHeadState& playHeadStateIn, TimeToViewScaling& timeToViewScalingIn, ARADocument& document)\r
+ : playHeadState (playHeadStateIn), timeToViewScaling (timeToViewScalingIn), araDocument (document)\r
+ {\r
+ timeToViewScaling.addListener (this);\r
+\r
+ addChildComponent (cycleMarker);\r
+ cycleMarker.setInterceptsMouseClicks (false, false);\r
+\r
+ setTooltip ("Double-click to start playback, click to stop playback or to reposition, drag horizontal range to set cycle.");\r
+\r
+ startTimerHz (30);\r
+ }\r
+\r
+ ~RulersView() override\r
+ {\r
+ stopTimer();\r
+\r
+ timeToViewScaling.removeListener (this);\r
+ selectMusicalContext (nullptr);\r
+ }\r
+\r
+ void paint (Graphics& g) override\r
+ {\r
+ auto drawBounds = g.getClipBounds();\r
+ const auto drawStartTime = timeToViewScaling.getTimeForX (drawBounds.getX());\r
+ const auto drawEndTime = timeToViewScaling.getTimeForX (drawBounds.getRight());\r
+\r
+ const auto bounds = getLocalBounds();\r
+\r
+ g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));\r
+ g.fillRect (bounds);\r
+ g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).contrasting());\r
+ g.drawRect (bounds);\r
+\r
+ const auto rulerHeight = bounds.getHeight() / 3;\r
+ g.drawRect (drawBounds.getX(), rulerHeight, drawBounds.getRight(), rulerHeight);\r
+ g.setFont (Font (12.0f));\r
+\r
+ const int lightLineWidth = 1;\r
+ const int heavyLineWidth = 3;\r
+\r
+ if (selectedMusicalContext != nullptr)\r
+ {\r
+ const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeTempoEntries> tempoReader (selectedMusicalContext);\r
+ const ARA::TempoConverter<decltype (tempoReader)> tempoConverter (tempoReader);\r
+\r
+ // chord ruler: one rect per chord, skipping empty "no chords"\r
+ const auto chordBounds = drawBounds.removeFromTop (rulerHeight);\r
+ const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeSheetChords> chordsReader (selectedMusicalContext);\r
+\r
+ if (tempoReader && chordsReader)\r
+ {\r
+ const ARA::ChordInterpreter interpreter (true);\r
+ for (auto itChord = chordsReader.begin(); itChord != chordsReader.end(); ++itChord)\r
+ {\r
+ if (interpreter.isNoChord (*itChord))\r
+ continue;\r
+\r
+ const auto chordStartTime = (itChord == chordsReader.begin()) ? 0 : tempoConverter.getTimeForQuarter (itChord->position);\r
+\r
+ if (chordStartTime >= drawEndTime)\r
+ break;\r
+\r
+ auto chordRect = chordBounds;\r
+ chordRect.setLeft (timeToViewScaling.getXForTime (chordStartTime));\r
+\r
+ if (std::next (itChord) != chordsReader.end())\r
+ {\r
+ const auto nextChordStartTime = tempoConverter.getTimeForQuarter (std::next (itChord)->position);\r
+\r
+ if (nextChordStartTime < drawStartTime)\r
+ continue;\r
+\r
+ chordRect.setRight (timeToViewScaling.getXForTime (nextChordStartTime));\r
+ }\r
+\r
+ g.drawRect (chordRect);\r
+ g.drawText (convertARAString (interpreter.getNameForChord (*itChord).c_str()),\r
+ chordRect.withTrimmedLeft (2),\r
+ Justification::centredLeft);\r
+ }\r
+ }\r
+\r
+ // beat ruler: evaluates tempo and bar signatures to draw a line for each beat\r
+ const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeBarSignatures> barSignaturesReader (selectedMusicalContext);\r
+\r
+ if (barSignaturesReader)\r
+ {\r
+ const ARA::BarSignaturesConverter<decltype (barSignaturesReader)> barSignaturesConverter (barSignaturesReader);\r
+\r
+ const double beatStart = barSignaturesConverter.getBeatForQuarter (tempoConverter.getQuarterForTime (drawStartTime));\r
+ const double beatEnd = barSignaturesConverter.getBeatForQuarter (tempoConverter.getQuarterForTime (drawEndTime));\r
+ const int endBeat = roundToInt (std::floor (beatEnd));\r
+ RectangleList<int> rects;\r
+\r
+ for (int beat = roundToInt (std::ceil (beatStart)); beat <= endBeat; ++beat)\r
+ {\r
+ const auto quarterPos = barSignaturesConverter.getQuarterForBeat (beat);\r
+ const int x = timeToViewScaling.getXForTime (tempoConverter.getTimeForQuarter (quarterPos));\r
+ const auto barSignature = barSignaturesConverter.getBarSignatureForQuarter (quarterPos);\r
+ const int lineWidth = (quarterPos == barSignature.position) ? heavyLineWidth : lightLineWidth;\r
+ const int beatsSinceBarStart = roundToInt( barSignaturesConverter.getBeatDistanceFromBarStartForQuarter (quarterPos));\r
+ const int lineHeight = (beatsSinceBarStart == 0) ? rulerHeight : rulerHeight / 2;\r
+ rects.addWithoutMerging (Rectangle<int> (x - lineWidth / 2, 2 * rulerHeight - lineHeight, lineWidth, lineHeight));\r
+ }\r
+\r
+ g.fillRectList (rects);\r
+ }\r
+ }\r
+\r
+ // time ruler: one tick for each second\r
+ {\r
+ RectangleList<int> rects;\r
+\r
+ for (auto time = std::floor (drawStartTime); time <= drawEndTime; time += 1.0)\r
+ {\r
+ const int lineWidth = (std::fmod (time, 60.0) <= 0.001) ? heavyLineWidth : lightLineWidth;\r
+ const int lineHeight = (std::fmod (time, 10.0) <= 0.001) ? rulerHeight : rulerHeight / 2;\r
+ rects.addWithoutMerging (Rectangle<int> (timeToViewScaling.getXForTime (time) - lineWidth / 2,\r
+ bounds.getHeight() - lineHeight,\r
+ lineWidth,\r
+ lineHeight));\r
+ }\r
+\r
+ g.fillRectList (rects);\r
+ }\r
+ }\r
+\r
+ void mouseDrag (const MouseEvent& m) override\r
+ {\r
+ isDraggingCycle = true;\r
+\r
+ auto cycleRect = getBounds();\r
+ cycleRect.setLeft (jmin (m.getMouseDownX(), m.x));\r
+ cycleRect.setRight (jmax (m.getMouseDownX(), m.x));\r
+ cycleMarker.setBounds (cycleRect);\r
+ }\r
+\r
+ void mouseUp (const MouseEvent& m) override\r
+ {\r
+ auto playbackController = araDocument.getDocumentController()->getHostPlaybackController();\r
+\r
+ if (playbackController != nullptr)\r
+ {\r
+ const auto startTime = timeToViewScaling.getTimeForX (jmin (m.getMouseDownX(), m.x));\r
+ const auto endTime = timeToViewScaling.getTimeForX (jmax (m.getMouseDownX(), m.x));\r
+\r
+ if (playHeadState.isPlaying.load (std::memory_order_relaxed))\r
+ playbackController->requestStopPlayback();\r
+ else\r
+ playbackController->requestSetPlaybackPosition (startTime);\r
+\r
+ if (isDraggingCycle)\r
+ playbackController->requestSetCycleRange (startTime, endTime - startTime);\r
+ }\r
+\r
+ isDraggingCycle = false;\r
+ }\r
+\r
+ void mouseDoubleClick (const MouseEvent&) override\r
+ {\r
+ if (auto* playbackController = araDocument.getDocumentController()->getHostPlaybackController())\r
+ {\r
+ if (! playHeadState.isPlaying.load (std::memory_order_relaxed))\r
+ playbackController->requestStartPlayback();\r
+ }\r
+ }\r
+\r
+ void selectMusicalContext (ARAMusicalContext* newSelectedMusicalContext)\r
+ {\r
+ if (auto* oldSelection = std::exchange (selectedMusicalContext, newSelectedMusicalContext);\r
+ oldSelection != selectedMusicalContext)\r
+ {\r
+ if (oldSelection != nullptr)\r
+ oldSelection->removeListener (this);\r
+\r
+ if (selectedMusicalContext != nullptr)\r
+ selectedMusicalContext->addListener (this);\r
+\r
+ repaint();\r
+ }\r
+ }\r
+\r
+ void zoomLevelChanged (double) override\r
+ {\r
+ repaint();\r
+ }\r
+\r
+ void doUpdateMusicalContextContent (ARAMusicalContext*, ARAContentUpdateScopes) override\r
+ {\r
+ repaint();\r
+ }\r
+\r
+private:\r
+ void updateCyclePosition()\r
+ {\r
+ if (selectedMusicalContext != nullptr)\r
+ {\r
+ const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeTempoEntries> tempoReader (selectedMusicalContext);\r
+ const ARA::TempoConverter<decltype (tempoReader)> tempoConverter (tempoReader);\r
+\r
+ const auto loopStartTime = tempoConverter.getTimeForQuarter (playHeadState.loopPpqStart.load (std::memory_order_relaxed));\r
+ const auto loopEndTime = tempoConverter.getTimeForQuarter (playHeadState.loopPpqEnd.load (std::memory_order_relaxed));\r
+\r
+ auto cycleRect = getBounds();\r
+ cycleRect.setLeft (timeToViewScaling.getXForTime (loopStartTime));\r
+ cycleRect.setRight (timeToViewScaling.getXForTime (loopEndTime));\r
+ cycleMarker.setVisible (true);\r
+ cycleMarker.setBounds (cycleRect);\r
+ }\r
+ else\r
+ {\r
+ cycleMarker.setVisible (false);\r
+ }\r
+ }\r
+\r
+ void timerCallback() override\r
+ {\r
+ if (! isDraggingCycle)\r
+ updateCyclePosition();\r
+ }\r
+\r
+private:\r
+ PlayHeadState& playHeadState;\r
+ TimeToViewScaling& timeToViewScaling;\r
+ ARADocument& araDocument;\r
+ ARAMusicalContext* selectedMusicalContext = nullptr;\r
+ CycleMarkerComponent cycleMarker;\r
+ bool isDraggingCycle = false;\r
+};\r
+\r
+class RulersHeader : public Component\r
+{\r
+public:\r
+ RulersHeader()\r
+ {\r
+ chordsLabel.setText ("Chords", NotificationType::dontSendNotification);\r
+ addAndMakeVisible (chordsLabel);\r
+\r
+ barsLabel.setText ("Bars", NotificationType::dontSendNotification);\r
+ addAndMakeVisible (barsLabel);\r
+\r
+ timeLabel.setText ("Time", NotificationType::dontSendNotification);\r
+ addAndMakeVisible (timeLabel);\r
+ }\r
+\r
+ void resized() override\r
+ {\r
+ auto bounds = getLocalBounds();\r
+ const auto rulerHeight = bounds.getHeight() / 3;\r
+\r
+ for (auto* label : { &chordsLabel, &barsLabel, &timeLabel })\r
+ label->setBounds (bounds.removeFromTop (rulerHeight));\r
+ }\r
+\r
+ void paint (Graphics& g) override\r
+ {\r
+ auto bounds = getLocalBounds();\r
+ const auto rulerHeight = bounds.getHeight() / 3;\r
+ g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));\r
+ g.fillRect (bounds);\r
+ g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).contrasting());\r
+ g.drawRect (bounds);\r
+ bounds.removeFromTop (rulerHeight);\r
+ g.drawRect (bounds.removeFromTop (rulerHeight));\r
+ }\r
+\r
+private:\r
+ Label chordsLabel, barsLabel, timeLabel;\r
+};\r
+\r
//==============================================================================\r
struct WaveformCache : private ARAAudioSource::Listener\r
{\r
};\r
\r
class PlaybackRegionView : public Component,\r
- public ChangeListener\r
+ public ChangeListener,\r
+ public SettableTooltipClient,\r
+ private ARAAudioSource::Listener,\r
+ private ARAPlaybackRegion::Listener,\r
+ private ARAEditorView::Listener\r
{\r
public:\r
- PlaybackRegionView (ARAPlaybackRegion& region, WaveformCache& cache)\r
- : playbackRegion (region), waveformCache (cache)\r
+ PlaybackRegionView (ARAEditorView& editorView, ARAPlaybackRegion& region, WaveformCache& cache)\r
+ : araEditorView (editorView), playbackRegion (region), waveformCache (cache), previewRegionOverlay (*this)\r
{\r
auto* audioSource = playbackRegion.getAudioModification()->getAudioSource();\r
\r
waveformCache.getOrCreateThumbnail (audioSource).addChangeListener (this);\r
+\r
+ audioSource->addListener (this);\r
+ playbackRegion.addListener (this);\r
+ araEditorView.addListener (this);\r
+ addAndMakeVisible (previewRegionOverlay);\r
+\r
+ setTooltip ("Double-click to toggle dim state of the region, click and hold to prelisten region near click.");\r
}\r
\r
~PlaybackRegionView() override\r
{\r
- waveformCache.getOrCreateThumbnail (playbackRegion.getAudioModification()->getAudioSource())\r
- .removeChangeListener (this);\r
+ auto* audioSource = playbackRegion.getAudioModification()->getAudioSource();\r
+\r
+ audioSource->removeListener (this);\r
+ playbackRegion.removeListener (this);\r
+ araEditorView.removeListener (this);\r
+\r
+ waveformCache.getOrCreateThumbnail (audioSource).removeChangeListener (this);\r
}\r
\r
void mouseDown (const MouseEvent& m) override\r
auto& previewState = ARADocumentControllerSpecialisation::getSpecialisedDocumentController<ARADemoPluginDocumentControllerSpecialisation> (playbackRegion.getDocumentController())->previewState;\r
previewState.previewTime.store (previewTime);\r
previewState.previewedRegion.store (&playbackRegion);\r
+ previewRegionOverlay.update();\r
}\r
\r
void mouseUp (const MouseEvent&) override\r
auto& previewState = ARADocumentControllerSpecialisation::getSpecialisedDocumentController<ARADemoPluginDocumentControllerSpecialisation> (playbackRegion.getDocumentController())->previewState;\r
previewState.previewTime.store (0.0);\r
previewState.previewedRegion.store (nullptr);\r
+ previewRegionOverlay.update();\r
+ }\r
+\r
+ void mouseDoubleClick (const MouseEvent&) override\r
+ {\r
+ // Set the dim flag on our region's audio modification when double-clicked\r
+ auto audioModification = playbackRegion.getAudioModification<ARADemoPluginAudioModification>();\r
+ audioModification->setDimmed (! audioModification->isDimmed());\r
+\r
+ // Send a content change notification for the modification and all associated playback regions\r
+ audioModification->notifyContentChanged (ARAContentUpdateScopes::samplesAreAffected(), true);\r
+ for (auto region : audioModification->getPlaybackRegions())\r
+ region->notifyContentChanged (ARAContentUpdateScopes::samplesAreAffected(), true);\r
}\r
\r
void changeListenerCallback (ChangeBroadcaster*) override\r
repaint();\r
}\r
\r
+ void didEnableAudioSourceSamplesAccess (ARAAudioSource*, bool) override\r
+ {\r
+ repaint();\r
+ }\r
+\r
+ void willUpdatePlaybackRegionProperties (ARAPlaybackRegion*,\r
+ ARAPlaybackRegion::PropertiesPtr newProperties) override\r
+ {\r
+ if (playbackRegion.getName() != newProperties->name\r
+ || playbackRegion.getColor() != newProperties->color)\r
+ {\r
+ repaint();\r
+ }\r
+ }\r
+\r
+ void didUpdatePlaybackRegionContent (ARAPlaybackRegion*, ARAContentUpdateScopes) override\r
+ {\r
+ repaint();\r
+ }\r
+\r
+ void onNewSelection (const ARAViewSelection& viewSelection) override\r
+ {\r
+ const auto& selectedPlaybackRegions = viewSelection.getPlaybackRegions();\r
+ const bool selected = std::find (selectedPlaybackRegions.begin(), selectedPlaybackRegions.end(), &playbackRegion) != selectedPlaybackRegions.end();\r
+ if (selected != isSelected)\r
+ {\r
+ isSelected = selected;\r
+ repaint();\r
+ }\r
+ }\r
+\r
void paint (Graphics& g) override\r
{\r
- g.fillAll (Colours::white.darker());\r
- g.setColour (Colours::darkgrey.darker());\r
- auto& thumbnail = waveformCache.getOrCreateThumbnail (playbackRegion.getAudioModification()->getAudioSource());\r
- thumbnail.drawChannels (g,\r
- getLocalBounds(),\r
- playbackRegion.getStartInAudioModificationTime(),\r
- playbackRegion.getEndInAudioModificationTime(),\r
- 1.0f);\r
- g.setColour (Colours::black);\r
+ g.fillAll (convertOptionalARAColour (playbackRegion.getEffectiveColor(), Colours::black));\r
+\r
+ const auto* audioModification = playbackRegion.getAudioModification<ARADemoPluginAudioModification>();\r
+ g.setColour (audioModification->isDimmed() ? Colours::darkgrey.darker() : Colours::darkgrey.brighter());\r
+\r
+ if (audioModification->getAudioSource()->isSampleAccessEnabled())\r
+ {\r
+ auto& thumbnail = waveformCache.getOrCreateThumbnail (playbackRegion.getAudioModification()->getAudioSource());\r
+ thumbnail.drawChannels (g,\r
+ getLocalBounds(),\r
+ playbackRegion.getStartInAudioModificationTime(),\r
+ playbackRegion.getEndInAudioModificationTime(),\r
+ 1.0f);\r
+ }\r
+ else\r
+ {\r
+ g.setFont (Font (12.0f));\r
+ g.drawText ("Audio Access Disabled", getLocalBounds(), Justification::centred);\r
+ }\r
+\r
+ g.setColour (Colours::white.withMultipliedAlpha (0.9f));\r
+ g.setFont (Font (12.0f));\r
+ g.drawText (convertOptionalARAString (playbackRegion.getEffectiveName()),\r
+ getLocalBounds(),\r
+ Justification::topLeft);\r
+\r
+ if (audioModification->isDimmed())\r
+ g.drawText ("DIMMED", getLocalBounds(), Justification::bottomLeft);\r
+\r
+ g.setColour (isSelected ? Colours::white : Colours::black);\r
g.drawRect (getLocalBounds());\r
}\r
\r
}\r
\r
private:\r
+ class PreviewRegionOverlay : public Component\r
+ {\r
+ static constexpr auto previewLength = 0.5;\r
+\r
+ public:\r
+ PreviewRegionOverlay (PlaybackRegionView& ownerIn) : owner (ownerIn)\r
+ {\r
+ }\r
+\r
+ void update()\r
+ {\r
+ const auto& previewState = owner.getDocumentController()->previewState;\r
+\r
+ if (previewState.previewedRegion.load() == &owner.playbackRegion)\r
+ {\r
+ const auto previewStartTime = previewState.previewTime.load() - owner.playbackRegion.getStartInPlaybackTime();\r
+ const auto pixelPerSecond = owner.getWidth() / owner.playbackRegion.getDurationInPlaybackTime();\r
+\r
+ setBounds (roundToInt ((previewStartTime - previewLength / 2) * pixelPerSecond),\r
+ 0,\r
+ roundToInt (previewLength * pixelPerSecond),\r
+ owner.getHeight());\r
+\r
+ setVisible (true);\r
+ }\r
+ else\r
+ {\r
+ setVisible (false);\r
+ }\r
+\r
+ repaint();\r
+ }\r
+\r
+ void paint (Graphics& g) override\r
+ {\r
+ g.setColour (Colours::yellow.withAlpha (0.5f));\r
+ g.fillRect (getLocalBounds());\r
+ }\r
+\r
+ private:\r
+ PlaybackRegionView& owner;\r
+ };\r
+\r
+ ARADemoPluginDocumentControllerSpecialisation* getDocumentController() const\r
+ {\r
+ return ARADocumentControllerSpecialisation::getSpecialisedDocumentController<ARADemoPluginDocumentControllerSpecialisation> (playbackRegion.getDocumentController());\r
+ }\r
+\r
+ ARAEditorView& araEditorView;\r
ARAPlaybackRegion& playbackRegion;\r
WaveformCache& waveformCache;\r
+ PreviewRegionOverlay previewRegionOverlay;\r
+ bool isSelected = false;\r
};\r
\r
class RegionSequenceView : public Component,\r
- public ARARegionSequence::Listener,\r
public ChangeBroadcaster,\r
+ private TimeToViewScaling::Listener,\r
+ private ARARegionSequence::Listener,\r
private ARAPlaybackRegion::Listener\r
{\r
public:\r
- RegionSequenceView (ARARegionSequence& rs, WaveformCache& cache, double pixelPerSec)\r
- : regionSequence (rs), waveformCache (cache), zoomLevelPixelPerSecond (pixelPerSec)\r
+ RegionSequenceView (ARAEditorView& editorView, TimeToViewScaling& scaling, ARARegionSequence& rs, WaveformCache& cache)\r
+ : araEditorView (editorView), timeToViewScaling (scaling), regionSequence (rs), waveformCache (cache)\r
{\r
regionSequence.addListener (this);\r
\r
createAndAddPlaybackRegionView (playbackRegion);\r
\r
updatePlaybackDuration();\r
+\r
+ timeToViewScaling.addListener (this);\r
}\r
\r
~RegionSequenceView() override\r
{\r
+ timeToViewScaling.removeListener (this);\r
+\r
regionSequence.removeListener (this);\r
\r
for (const auto& it : playbackRegionViews)\r
\r
//==============================================================================\r
// ARA Document change callback overrides\r
+ void willUpdateRegionSequenceProperties (ARARegionSequence*,\r
+ ARARegionSequence::PropertiesPtr newProperties) override\r
+ {\r
+ if (regionSequence.getColor() != newProperties->color)\r
+ {\r
+ for (auto& pbr : playbackRegionViews)\r
+ pbr.second->repaint();\r
+ }\r
+ }\r
+\r
void willRemovePlaybackRegionFromRegionSequence (ARARegionSequence*,\r
ARAPlaybackRegion* playbackRegion) override\r
{\r
updatePlaybackDuration();\r
}\r
\r
- void willUpdatePlaybackRegionProperties (ARAPlaybackRegion*, ARAPlaybackRegion::PropertiesPtr) override\r
+ void didUpdatePlaybackRegionProperties (ARAPlaybackRegion*) override\r
{\r
+ updatePlaybackDuration();\r
}\r
\r
- void didUpdatePlaybackRegionProperties (ARAPlaybackRegion*) override\r
+ void zoomLevelChanged (double) override\r
{\r
- updatePlaybackDuration();\r
+ resized();\r
}\r
\r
void resized() override\r
const auto playbackRegion = pbr.first;\r
pbr.second->setBounds (\r
getLocalBounds()\r
- .withTrimmedLeft (roundToInt (playbackRegion->getStartInPlaybackTime() * zoomLevelPixelPerSecond))\r
- .withWidth (roundToInt (playbackRegion->getDurationInPlaybackTime() * zoomLevelPixelPerSecond)));\r
+ .withTrimmedLeft (timeToViewScaling.getXForTime (playbackRegion->getStartInPlaybackTime()))\r
+ .withWidth (timeToViewScaling.getXForTime (playbackRegion->getDurationInPlaybackTime())));\r
}\r
}\r
\r
return playbackDuration;\r
}\r
\r
- void setZoomLevel (double pixelPerSecond)\r
- {\r
- zoomLevelPixelPerSecond = pixelPerSecond;\r
- resized();\r
- }\r
-\r
private:\r
void createAndAddPlaybackRegionView (ARAPlaybackRegion* playbackRegion)\r
{\r
- playbackRegionViews[playbackRegion] = std::make_unique<PlaybackRegionView> (*playbackRegion, waveformCache);\r
+ playbackRegionViews[playbackRegion] = std::make_unique<PlaybackRegionView> (araEditorView,\r
+ *playbackRegion,\r
+ waveformCache);\r
playbackRegion->addListener (this);\r
addAndMakeVisible (*playbackRegionViews[playbackRegion]);\r
}\r
sendChangeMessage();\r
}\r
\r
+ ARAEditorView& araEditorView;\r
+ TimeToViewScaling& timeToViewScaling;\r
ARARegionSequence& regionSequence;\r
WaveformCache& waveformCache;\r
std::unordered_map<ARAPlaybackRegion*, std::unique_ptr<PlaybackRegionView>> playbackRegionViews;\r
double playbackDuration = 0.0;\r
- double zoomLevelPixelPerSecond;\r
};\r
\r
class ZoomControls : public Component\r
TextButton zoomInButton { "+" }, zoomOutButton { "-" };\r
};\r
\r
-class TrackHeader : public Component\r
+class PlayheadPositionLabel : public Label,\r
+ private Timer\r
{\r
public:\r
- explicit TrackHeader (const ARARegionSequence& regionSequenceIn) : regionSequence (regionSequenceIn)\r
+ PlayheadPositionLabel (PlayHeadState& playHeadStateIn)\r
+ : playHeadState (playHeadStateIn)\r
{\r
- update();\r
+ startTimerHz (30);\r
+ }\r
+\r
+ ~PlayheadPositionLabel() override\r
+ {\r
+ stopTimer();\r
+ }\r
+\r
+ void selectMusicalContext (ARAMusicalContext* newSelectedMusicalContext)\r
+ {\r
+ selectedMusicalContext = newSelectedMusicalContext;\r
+ }\r
+\r
+private:\r
+ void timerCallback() override\r
+ {\r
+ const auto timePosition = playHeadState.timeInSeconds.load (std::memory_order_relaxed);\r
+\r
+ auto text = timeToTimecodeString (timePosition);\r
+\r
+ if (playHeadState.isPlaying.load (std::memory_order_relaxed))\r
+ text += " (playing)";\r
+ else\r
+ text += " (stopped)";\r
+\r
+ if (selectedMusicalContext != nullptr)\r
+ {\r
+ const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeTempoEntries> tempoReader (selectedMusicalContext);\r
+ const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeBarSignatures> barSignaturesReader (selectedMusicalContext);\r
+\r
+ if (tempoReader && barSignaturesReader)\r
+ {\r
+ const ARA::TempoConverter<decltype (tempoReader)> tempoConverter (tempoReader);\r
+ const ARA::BarSignaturesConverter<decltype (barSignaturesReader)> barSignaturesConverter (barSignaturesReader);\r
+ const auto quarterPosition = tempoConverter.getQuarterForTime (timePosition);\r
+ const auto barIndex = barSignaturesConverter.getBarIndexForQuarter (quarterPosition);\r
+ const auto beatDistance = barSignaturesConverter.getBeatDistanceFromBarStartForQuarter (quarterPosition);\r
+ const auto quartersPerBeat = 4.0 / (double) barSignaturesConverter.getBarSignatureForQuarter (quarterPosition).denominator;\r
+ const auto beatIndex = (int) beatDistance;\r
+ const auto tickIndex = juce::roundToInt ((beatDistance - beatIndex) * quartersPerBeat * 960.0);\r
+\r
+ text += newLine;\r
+ text += String::formatted ("bar %d | beat %d | tick %03d", (barIndex >= 0) ? barIndex + 1 : barIndex, beatIndex + 1, tickIndex + 1);\r
+ text += " - ";\r
+\r
+ const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeSheetChords> chordsReader (selectedMusicalContext);\r
+\r
+ if (chordsReader && chordsReader.getEventCount() > 0)\r
+ {\r
+ const auto begin = chordsReader.begin();\r
+ const auto end = chordsReader.end();\r
+ auto it = begin;\r
+\r
+ while (it->position <= quarterPosition && it != end)\r
+ ++it;\r
+\r
+ if (it != begin)\r
+ --it;\r
+\r
+ const ARA::ChordInterpreter interpreter (true);\r
+ text += "chord ";\r
+ text += String (interpreter.getNameForChord (*it));\r
+ }\r
+ else\r
+ {\r
+ text += "(no chords provided)";\r
+ }\r
+ }\r
+ }\r
+\r
+ setText (text, NotificationType::dontSendNotification);\r
+ }\r
+\r
+ // Copied from AudioPluginDemo.h: quick-and-dirty function to format a timecode string\r
+ static String timeToTimecodeString (double seconds)\r
+ {\r
+ auto millisecs = roundToInt (seconds * 1000.0);\r
+ auto absMillisecs = std::abs (millisecs);\r
+\r
+ return String::formatted ("%02d:%02d:%02d.%03d",\r
+ millisecs / 3600000,\r
+ (absMillisecs / 60000) % 60,\r
+ (absMillisecs / 1000) % 60,\r
+ absMillisecs % 1000);\r
+ }\r
+\r
+ PlayHeadState& playHeadState;\r
+ ARAMusicalContext* selectedMusicalContext = nullptr;\r
+};\r
+\r
+class TrackHeader : public Component,\r
+ private ARARegionSequence::Listener,\r
+ private ARAEditorView::Listener\r
+{\r
+public:\r
+ TrackHeader (ARAEditorView& editorView, ARARegionSequence& regionSequenceIn)\r
+ : araEditorView (editorView), regionSequence (regionSequenceIn)\r
+ {\r
+ updateTrackName (regionSequence.getName());\r
+ onNewSelection (araEditorView.getViewSelection());\r
\r
addAndMakeVisible (trackNameLabel);\r
+\r
+ regionSequence.addListener (this);\r
+ araEditorView.addListener (this);\r
+ }\r
+\r
+ ~TrackHeader() override\r
+ {\r
+ araEditorView.removeListener (this);\r
+ regionSequence.removeListener (this);\r
+ }\r
+\r
+ void willUpdateRegionSequenceProperties (ARARegionSequence*, ARARegionSequence::PropertiesPtr newProperties) override\r
+ {\r
+ if (regionSequence.getName() != newProperties->name)\r
+ updateTrackName (newProperties->name);\r
+ if (regionSequence.getColor() != newProperties->color)\r
+ repaint();\r
}\r
\r
void resized() override\r
\r
void paint (Graphics& g) override\r
{\r
- g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));\r
- g.fillRoundedRectangle (getLocalBounds().reduced (2).toType<float>(), 6.0f);\r
- g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).contrasting());\r
- g.drawRoundedRectangle (getLocalBounds().reduced (2).toType<float>(), 6.0f, 1.0f);\r
+ const auto backgroundColour = getLookAndFeel().findColour (ResizableWindow::backgroundColourId);\r
+ g.setColour (isSelected ? backgroundColour.brighter() : backgroundColour);\r
+ g.fillRoundedRectangle (getLocalBounds().reduced (2).toFloat(), 6.0f);\r
+ g.setColour (backgroundColour.contrasting());\r
+ g.drawRoundedRectangle (getLocalBounds().reduced (2).toFloat(), 6.0f, 1.0f);\r
+\r
+ if (auto colour = regionSequence.getColor())\r
+ {\r
+ g.setColour (convertARAColour (colour));\r
+ g.fillRect (getLocalBounds().removeFromTop (16).reduced (6));\r
+ g.fillRect (getLocalBounds().removeFromBottom (16).reduced (6));\r
+ }\r
}\r
\r
-private:\r
- void update()\r
+ void onNewSelection (const ARAViewSelection& viewSelection) override\r
{\r
- const auto getWithDefaultValue =\r
- [] (const ARA::PlugIn::OptionalProperty<ARA::ARAUtf8String>& optional, String defaultValue)\r
- {\r
- if (const ARA::ARAUtf8String value = optional)\r
- return String (value);\r
+ const auto& selectedRegionSequences = viewSelection.getRegionSequences();\r
+ const bool selected = std::find (selectedRegionSequences.begin(), selectedRegionSequences.end(), ®ionSequence) != selectedRegionSequences.end();\r
\r
- return defaultValue;\r
- };\r
+ if (selected != isSelected)\r
+ {\r
+ isSelected = selected;\r
+ repaint();\r
+ }\r
+ }\r
\r
- trackNameLabel.setText (getWithDefaultValue (regionSequence.getName(), "No track name"),\r
+private:\r
+ void updateTrackName (ARA::ARAUtf8String optionalName)\r
+ {\r
+ trackNameLabel.setText (optionalName ? optionalName : "No track name",\r
NotificationType::dontSendNotification);\r
}\r
\r
- const ARARegionSequence& regionSequence;\r
+ ARAEditorView& araEditorView;\r
+ ARARegionSequence& regionSequence;\r
Label trackNameLabel;\r
+ bool isSelected = false;\r
};\r
\r
constexpr auto trackHeight = 60;\r
component->resized();\r
}\r
}\r
-\r
- void setOverlayComponent (Component* component)\r
- {\r
- if (overlayComponent != nullptr && overlayComponent != component)\r
- removeChildComponent (overlayComponent);\r
-\r
- addChildComponent (component);\r
- overlayComponent = component;\r
- }\r
-\r
-private:\r
- Component* overlayComponent = nullptr;\r
};\r
\r
class VerticalLayoutViewport : public Viewport\r
};\r
\r
class OverlayComponent : public Component,\r
- private Timer\r
+ private Timer,\r
+ private TimeToViewScaling::Listener\r
{\r
public:\r
class PlayheadMarkerComponent : public Component\r
{\r
- void paint (Graphics& g) override { g.fillAll (juce::Colours::yellow.darker (0.2f)); }\r
+ void paint (Graphics& g) override { g.fillAll (Colours::yellow.darker (0.2f)); }\r
};\r
\r
- OverlayComponent (PlayHeadState& playHeadStateIn)\r
- : playHeadState (&playHeadStateIn)\r
+ OverlayComponent (PlayHeadState& playHeadStateIn, TimeToViewScaling& timeToViewScalingIn)\r
+ : playHeadState (playHeadStateIn), timeToViewScaling (timeToViewScalingIn)\r
{\r
addChildComponent (playheadMarker);\r
setInterceptsMouseClicks (false, false);\r
startTimerHz (30);\r
+\r
+ timeToViewScaling.addListener (this);\r
}\r
\r
~OverlayComponent() override\r
{\r
+ timeToViewScaling.removeListener (this);\r
+\r
stopTimer();\r
}\r
\r
void resized() override\r
{\r
- doResize();\r
+ updatePlayHeadPosition();\r
}\r
\r
- void setZoomLevel (double pixelPerSecondIn)\r
+ void setHorizontalOffset (int offset)\r
{\r
- pixelPerSecond = pixelPerSecondIn;\r
+ horizontalOffset = offset;\r
}\r
\r
- void setHorizontalOffset (int offset)\r
+ void setSelectedTimeRange (std::optional<ARA::ARAContentTimeRange> timeRange)\r
{\r
- horizontalOffset = offset;\r
+ selectedTimeRange = timeRange;\r
+ repaint();\r
+ }\r
+\r
+ void zoomLevelChanged (double) override\r
+ {\r
+ updatePlayHeadPosition();\r
+ repaint();\r
+ }\r
+\r
+ void paint (Graphics& g) override\r
+ {\r
+ if (selectedTimeRange)\r
+ {\r
+ auto bounds = getLocalBounds();\r
+ bounds.setLeft (timeToViewScaling.getXForTime (selectedTimeRange->start));\r
+ bounds.setRight (timeToViewScaling.getXForTime (selectedTimeRange->start + selectedTimeRange->duration));\r
+ g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).brighter().withAlpha (0.3f));\r
+ g.fillRect (bounds);\r
+ g.setColour (Colours::whitesmoke.withAlpha (0.5f));\r
+ g.drawRect (bounds);\r
+ }\r
}\r
\r
private:\r
- void doResize()\r
+ void updatePlayHeadPosition()\r
{\r
- if (playHeadState->isPlaying.load())\r
+ if (playHeadState.isPlaying.load (std::memory_order_relaxed))\r
{\r
- const auto markerX = playHeadState->timeInSeconds.load() * pixelPerSecond;\r
+ const auto markerX = timeToViewScaling.getXForTime (playHeadState.timeInSeconds.load (std::memory_order_relaxed));\r
const auto playheadLine = getLocalBounds().withTrimmedLeft ((int) (markerX - markerWidth / 2.0) - horizontalOffset)\r
.removeFromLeft ((int) markerWidth);\r
playheadMarker.setVisible (true);\r
\r
void timerCallback() override\r
{\r
- doResize();\r
+ updatePlayHeadPosition();\r
}\r
\r
static constexpr double markerWidth = 2.0;\r
\r
- PlayHeadState* playHeadState;\r
- double pixelPerSecond = 1.0;\r
+ PlayHeadState& playHeadState;\r
+ TimeToViewScaling& timeToViewScaling;\r
int horizontalOffset = 0;\r
+ std::optional<ARA::ARAContentTimeRange> selectedTimeRange;\r
PlayheadMarkerComponent playheadMarker;\r
};\r
\r
class DocumentView : public Component,\r
public ChangeListener,\r
+ public ARAMusicalContext::Listener,\r
private ARADocument::Listener,\r
private ARAEditorView::Listener\r
{\r
public:\r
- explicit DocumentView (ARADocument& document, PlayHeadState& playHeadState)\r
- : araDocument (document),\r
- overlay (playHeadState)\r
+ DocumentView (ARAEditorView& editorView, PlayHeadState& playHeadState)\r
+ : araEditorView (editorView),\r
+ araDocument (*editorView.getDocumentController()->getDocument<ARADocument>()),\r
+ rulersView (playHeadState, timeToViewScaling, araDocument),\r
+ overlay (playHeadState, timeToViewScaling),\r
+ playheadPositionLabel (playHeadState)\r
{\r
- addAndMakeVisible (tracksBackground);\r
+ if (araDocument.getMusicalContexts().size() > 0)\r
+ selectMusicalContext (araDocument.getMusicalContexts().front());\r
+\r
+ addAndMakeVisible (rulersHeader);\r
+\r
+ viewport.content.addAndMakeVisible (rulersView);\r
\r
viewport.onVisibleAreaChanged = [this] (const auto& r)\r
{\r
};\r
\r
addAndMakeVisible (viewport);\r
-\r
- overlay.setZoomLevel (zoomLevelPixelPerSecond);\r
addAndMakeVisible (overlay);\r
+ addAndMakeVisible (playheadPositionLabel);\r
\r
zoomControls.setZoomInCallback ([this] { zoom (2.0); });\r
zoomControls.setZoomOutCallback ([this] { zoom (0.5); });\r
addAndMakeVisible (zoomControls);\r
\r
invalidateRegionSequenceViews();\r
+\r
araDocument.addListener (this);\r
+ araEditorView.addListener (this);\r
}\r
\r
~DocumentView() override\r
{\r
+ araEditorView.removeListener (this);\r
araDocument.removeListener (this);\r
+ selectMusicalContext (nullptr);\r
}\r
\r
//==============================================================================\r
// ARADocument::Listener overrides\r
+ void didAddMusicalContextToDocument (ARADocument*, ARAMusicalContext* musicalContext) override\r
+ {\r
+ if (selectedMusicalContext == nullptr)\r
+ selectMusicalContext (musicalContext);\r
+ }\r
+\r
+ void willDestroyMusicalContext (ARAMusicalContext*) override\r
+ {\r
+ selectMusicalContext (nullptr);\r
+ }\r
+\r
void didReorderRegionSequencesInDocument (ARADocument*) override\r
{\r
invalidateRegionSequenceViews();\r
\r
//==============================================================================\r
// ARAEditorView::Listener overrides\r
- void onNewSelection (const ARA::PlugIn::ViewSelection&) override\r
+ void onNewSelection (const ARAViewSelection& viewSelection) override\r
{\r
+ auto getNewSelectedMusicalContext = [&viewSelection]() -> ARAMusicalContext*\r
+ {\r
+ if (! viewSelection.getRegionSequences().empty())\r
+ return viewSelection.getRegionSequences<ARARegionSequence>().front()->getMusicalContext();\r
+ else if (! viewSelection.getPlaybackRegions().empty())\r
+ return viewSelection.getPlaybackRegions<ARAPlaybackRegion>().front()->getRegionSequence()->getMusicalContext();\r
+\r
+ return nullptr;\r
+ };\r
+\r
+ if (auto* newSelectedMusicalContext = getNewSelectedMusicalContext())\r
+ if (newSelectedMusicalContext != selectedMusicalContext)\r
+ selectMusicalContext (newSelectedMusicalContext);\r
+\r
+ // If no context is used yet and the selection does not yield a new one, the DocumentView\r
+ // uses the first musical context in the document.\r
+\r
+ if (const auto timeRange = viewSelection.getTimeRange())\r
+ overlay.setSelectedTimeRange (*timeRange);\r
+ else\r
+ overlay.setSelectedTimeRange (std::nullopt);\r
}\r
\r
- void onHideRegionSequences (const std::vector<ARARegionSequence*>&) override\r
+ void onHideRegionSequences (const std::vector<ARARegionSequence*>& regionSequences) override\r
{\r
+ hiddenRegionSequences = regionSequences;\r
+ invalidateRegionSequenceViews();\r
}\r
\r
//==============================================================================\r
void resized() override\r
{\r
auto bounds = getLocalBounds();\r
- const auto bottomControlsBounds = bounds.removeFromBottom (40);\r
- const auto headerBounds = bounds.removeFromLeft (headerWidth).reduced (2);\r
\r
- zoomControls.setBounds (bottomControlsBounds);\r
- layOutVertically (headerBounds, trackHeaders, viewportHeightOffset);\r
- tracksBackground.setBounds (bounds);\r
- viewport.setBounds (bounds);\r
- overlay.setBounds (bounds);\r
- }\r
-\r
- //==============================================================================\r
- void setZoomLevel (double pixelPerSecond)\r
- {\r
- zoomLevelPixelPerSecond = pixelPerSecond;\r
+ FlexBox fb;\r
+ fb.justifyContent = FlexBox::JustifyContent::spaceBetween;\r
+ fb.items.add (FlexItem (playheadPositionLabel).withWidth (450.0f).withMinWidth (250.0f));\r
+ fb.items.add (FlexItem (zoomControls).withMinWidth (80.0f));\r
+ fb.performLayout (bounds.removeFromBottom (40));\r
\r
- for (const auto& view : regionSequenceViews)\r
- view.second->setZoomLevel (zoomLevelPixelPerSecond);\r
+ auto headerBounds = bounds.removeFromLeft (headerWidth);\r
+ rulersHeader.setBounds (headerBounds.removeFromTop (trackHeight));\r
+ layOutVertically (headerBounds, trackHeaders, viewportHeightOffset);\r
\r
- overlay.setZoomLevel (zoomLevelPixelPerSecond);\r
+ viewport.setBounds (bounds);\r
+ overlay.setBounds (bounds.reduced (1));\r
\r
- update();\r
+ const auto width = jmax (timeToViewScaling.getXForTime (timelineLength), viewport.getWidth());\r
+ const auto height = (int) (regionSequenceViews.size() + 1) * trackHeight;\r
+ viewport.content.setSize (width, height);\r
+ viewport.content.resized();\r
}\r
\r
+ //==============================================================================\r
static constexpr int headerWidth = 120;\r
\r
private:\r
ARARegionSequence* sequence;\r
};\r
\r
+ void selectMusicalContext (ARAMusicalContext* newSelectedMusicalContext)\r
+ {\r
+ if (auto oldContext = std::exchange (selectedMusicalContext, newSelectedMusicalContext);\r
+ oldContext != selectedMusicalContext)\r
+ {\r
+ if (oldContext != nullptr)\r
+ oldContext->removeListener (this);\r
+\r
+ if (selectedMusicalContext != nullptr)\r
+ selectedMusicalContext->addListener (this);\r
+\r
+ rulersView.selectMusicalContext (selectedMusicalContext);\r
+ playheadPositionLabel.selectMusicalContext (selectedMusicalContext);\r
+ }\r
+ }\r
+\r
void zoom (double factor)\r
{\r
- zoomLevelPixelPerSecond = jlimit (minimumZoom, minimumZoom * 32, zoomLevelPixelPerSecond * factor);\r
- setZoomLevel (zoomLevelPixelPerSecond);\r
+ timeToViewScaling.zoom (factor);\r
+ update();\r
}\r
\r
template <typename T>\r
for (const auto& view : regionSequenceViews)\r
timelineLength = std::max (timelineLength, view.second->getPlaybackDuration());\r
\r
- const Rectangle<int> timelineSize (roundToInt (timelineLength * zoomLevelPixelPerSecond),\r
- (int) regionSequenceViews.size() * trackHeight);\r
- viewport.content.setSize (timelineSize.getWidth(), timelineSize.getHeight());\r
- viewport.content.resized();\r
-\r
resized();\r
}\r
\r
auto& regionSequenceView = insertIntoMap (\r
regionSequenceViews,\r
RegionSequenceViewKey { regionSequence },\r
- std::make_unique<RegionSequenceView> (*regionSequence, waveformCache, zoomLevelPixelPerSecond));\r
+ std::make_unique<RegionSequenceView> (araEditorView, timeToViewScaling, *regionSequence, waveformCache));\r
\r
regionSequenceView.addChangeListener (this);\r
viewport.content.addAndMakeVisible (regionSequenceView);\r
\r
auto& trackHeader = insertIntoMap (trackHeaders,\r
RegionSequenceViewKey { regionSequence },\r
- std::make_unique<TrackHeader> (*regionSequence));\r
+ std::make_unique<TrackHeader> (araEditorView, *regionSequence));\r
\r
addAndMakeVisible (trackHeader);\r
}\r
trackHeaders.clear();\r
\r
for (auto* regionSequence : araDocument.getRegionSequences())\r
- {\r
- addTrackViews (regionSequence);\r
- }\r
+ if (std::find (hiddenRegionSequences.begin(), hiddenRegionSequences.end(), regionSequence) == hiddenRegionSequences.end())\r
+ addTrackViews (regionSequence);\r
\r
update();\r
\r
}\r
}\r
\r
- class TracksBackgroundComponent : public Component\r
- {\r
- void paint (Graphics& g) override\r
- {\r
- g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).brighter());\r
- }\r
- };\r
-\r
- static constexpr auto minimumZoom = 10.0;\r
- static constexpr auto trackHeight = 60;\r
-\r
+ ARAEditorView& araEditorView;\r
ARADocument& araDocument;\r
\r
bool regionSequenceViewsAreValid = false;\r
- double timelineLength = 0;\r
- double zoomLevelPixelPerSecond = minimumZoom * 4;\r
+\r
+ TimeToViewScaling timeToViewScaling;\r
+ double timelineLength = 0.0;\r
+\r
+ ARAMusicalContext* selectedMusicalContext = nullptr;\r
+\r
+ std::vector<ARARegionSequence*> hiddenRegionSequences;\r
\r
WaveformCache waveformCache;\r
- TracksBackgroundComponent tracksBackground;\r
std::map<RegionSequenceViewKey, std::unique_ptr<TrackHeader>> trackHeaders;\r
std::map<RegionSequenceViewKey, std::unique_ptr<RegionSequenceView>> regionSequenceViews;\r
+ RulersHeader rulersHeader;\r
+ RulersView rulersView;\r
VerticalLayoutViewport viewport;\r
OverlayComponent overlay;\r
ZoomControls zoomControls;\r
+ PlayheadPositionLabel playheadPositionLabel;\r
+ TooltipWindow tooltip;\r
\r
int viewportHeightOffset = 0;\r
};\r
AudioProcessorEditorARAExtension (&p)\r
{\r
if (auto* editorView = getARAEditorView())\r
- {\r
- auto* document = ARADocumentControllerSpecialisation::getSpecialisedDocumentController(editorView->getDocumentController())->getDocument();\r
- documentView = std::make_unique<DocumentView> (*document, p.playHeadState );\r
- }\r
+ documentView = std::make_unique<DocumentView> (*editorView, p.playHeadState);\r
\r
addAndMakeVisible (documentView.get());\r
\r
// ARA requires that plugin editors are resizable to support tight integration\r
// into the host UI\r
setResizable (true, false);\r
- setSize (400, 300);\r
+ setSize (800, 300);\r
}\r
\r
//==============================================================================\r
\r
template <typename Func, typename... Items>\r
constexpr void forEach (Func&& func, Items&&... items)\r
- noexcept (noexcept (std::initializer_list<int> { (func (std::forward<Items> (items)), 0)... }))\r
{\r
- (void) std::initializer_list<int> { ((void) func (std::forward<Items> (items)), 0)... };\r
+ (func (std::forward<Items> (items)), ...);\r
}\r
\r
template <typename... Components>\r
&& 1 <= outputs.size()\r
&& std::all_of (outputs.begin(), outputs.end(), [] (const auto& bus)\r
{\r
- return bus == AudioChannelSet::stereo();\r
+ return bus.isDisabled() || bus == AudioChannelSet::stereo();\r
});\r
}\r
\r
template <typename Func>\r
static std::unique_ptr<Command<Proc>> makeCommand (Func&& func)\r
{\r
- using Decayed = typename std::decay<Func>::type;\r
+ using Decayed = std::decay_t<Func>;\r
return std::make_unique<TemplateCommand<Proc, Decayed>> (std::forward<Func> (func));\r
}\r
\r
{\r
purchaseInProgress = false;\r
\r
- for (const auto productId : info.purchase.productIds)\r
+ for (const auto& productId : info.purchase.productIds)\r
{\r
auto idx = findVoiceIndexFromIdentifier (productId);\r
\r
{\r
if (success)\r
{\r
- for (auto& info : infos)\r
+ for (const auto& info : infos)\r
{\r
- for (const auto productId : info.purchase.productIds)\r
+ for (const auto& productId : info.purchase.productIds)\r
{\r
auto idx = findVoiceIndexFromIdentifier (productId);\r
\r
havePricesBeenFetched = true;\r
StringArray identifiers;\r
\r
- for (auto& voiceProduct : voiceProducts)\r
+ for (const auto& voiceProduct : voiceProducts)\r
identifiers.add (voiceProduct.identifier);\r
\r
InAppPurchases::getInstance()->getProductsInformation (identifiers);\r
: BouncingBall (containerComp),\r
Thread ("JUCE Demo Thread")\r
{\r
- // give the threads a random priority, so some will move more\r
- // smoothly than others..\r
- startThread (Random::getSystemRandom().nextInt (3) + 3);\r
+ startThread();\r
}\r
\r
~DemoThread() override\r
<< "Host name: " << SystemStats::getComputerName() << newLine\r
<< "Device type: " << SystemStats::getDeviceDescription() << newLine\r
<< "Manufacturer: " << SystemStats::getDeviceManufacturer() << newLine\r
+ << "Device ID: " << SystemStats::getUniqueDeviceID() << newLine\r
<< "User logon name: " << SystemStats::getLogonName() << newLine\r
<< "Full user name: " << SystemStats::getFullUserName() << newLine\r
<< "User region: " << SystemStats::getUserRegion() << newLine\r
-# Automatically generated makefile, created by the Projucer
+# Automatically generated CMakeLists, created by the Projucer
# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!
cmake_minimum_required(VERSION 3.4.1)
+project(juce_jni_project)
+
set(BINARY_NAME "juce_jni")
set(OBOE_DIR "../../../../../modules/juce_audio_devices/native/oboe")
enable_language(ASM)
if(JUCE_BUILD_CONFIGURATION MATCHES "DEBUG")
- add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
+ add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70003]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
elseif(JUCE_BUILD_CONFIGURATION MATCHES "RELEASE")
- add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
+ add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70003]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
else()
message( FATAL_ERROR "No matching build-configuration found." )
endif()
"../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
- "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
"../../../../../modules/juce_core/native/juce_mac_Strings.mm"
"../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
"../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+ "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
"../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
"../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
"../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+ "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
"../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
"../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
"../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
"../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
"../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
"../../../../../modules/juce_gui_basics/juce_gui_basics.h"
"../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
- "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
"../../../../../modules/juce_core/native/juce_mac_Strings.mm"
"../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
"../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+ "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
"../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
"../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
"../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+ "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
"../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
"../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
"../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
"../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
"../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
"../../../../../modules/juce_gui_basics/juce_gui_basics.h"
"../../../JuceLibraryCode/JuceHeader.h"
PROPERTIES HEADER_FILE_ONLY TRUE)
-target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" [[-mfpu=neon]] [[-mfloat-abi=hard]] [[-ffast-math]] [[-funroll-loops]] [[--param]] [[max-unroll-times=8]] [[-mhard-float]] [[-D_NDK_MATH_NO_SOFTFP=1]] [[-DJUCE_DISABLE_ASSERTIONS=1]] )
-
if( JUCE_BUILD_CONFIGURATION MATCHES "DEBUG" )
- target_compile_options( ${BINARY_NAME} PRIVATE)
+ target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" [[-mfpu=neon]] [[-mfloat-abi=hard]] [[-ffast-math]] [[-funroll-loops]] [[--param]] [[max-unroll-times=8]] [[-mhard-float]] [[-D_NDK_MATH_NO_SOFTFP=1]] [[-DJUCE_DISABLE_ASSERTIONS=1]] )
endif()
if( JUCE_BUILD_CONFIGURATION MATCHES "RELEASE" )
- target_compile_options( ${BINARY_NAME} PRIVATE)
+ target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" [[-mfpu=neon]] [[-mfloat-abi=hard]] [[-ffast-math]] [[-funroll-loops]] [[--param]] [[max-unroll-times=8]] [[-mhard-float]] [[-D_NDK_MATH_NO_SOFTFP=1]] [[-DJUCE_DISABLE_ASSERTIONS=1]] )
endif()
find_library(log "log")
apply plugin: 'com.android.application'
android {
- compileSdkVersion 30
+ compileSdkVersion 33
+ namespace "com.juce.audioperformancetest"
externalNativeBuild {
cmake {
path "CMakeLists.txt"
defaultConfig {
applicationId "com.juce.audioperformancetest"
minSdkVersion 23
- targetSdkVersion 30
+ targetSdkVersion 33
externalNativeBuild {
cmake {
- arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=14", "-DCMAKE_CXX_EXTENSIONS=OFF"
+ arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=17", "-DCMAKE_CXX_EXTENSIONS=OFF"
}
}
}
}
externalNativeBuild {
cmake {
- arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-O0", "-DCMAKE_C_FLAGS_DEBUG=-O0"
+ cFlags "-O0"
+ cppFlags "-O0"
+ arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG"
}
}
dimension "default"
- }
+ }
release_ {
externalNativeBuild {
cmake {
- arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-Ofast", "-DCMAKE_C_FLAGS_RELEASE=-Ofast"
+ cFlags "-Ofast"
+ cppFlags "-Ofast"
+ arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE"
}
}
dimension "default"
- }
+ }
}
variantFilter { variant ->
<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0"
- package="com.juce.audioperformancetest">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"
android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<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.rmsl.juce.JuceApp" android:hardwareAccelerated="false">
- <activity android:name="com.rmsl.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize"
+ <activity android:name="com.rmsl.juce.JuceActivity" android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"
android:exported="true">
<intent-filter>
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.0.0'
+ classpath 'com.android.tools.build:gradle:7.3.0'
}
}
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
\ No newline at end of file
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl 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_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := AudioPerformanceTest
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl 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_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := AudioPerformanceTest
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
19B7C16D592FB25D09022191 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
COPY_PHASE_STRIP = NO;
"DEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
INFOPLIST_FILE = Info-App.plist;
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
- MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_LDFLAGS = "-weak_framework Metal -weak_framework MetalKit";
PRODUCT_BUNDLE_IDENTIFIER = com.juce.AudioPerformanceTest;
B7A6988E30C0A68B01EDC53B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
DEAD_CODE_STRIPPING = YES;
"NDEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
LLVM_LTO = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_LDFLAGS = "-weak_framework Metal -weak_framework MetalKit";
PRODUCT_BUNDLE_IDENTIFIER = com.juce.AudioPerformanceTest;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<WarningLevel>Level4</WarningLevel>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\AudioPerformanceTest.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<WarningLevel>Level4</WarningLevel>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\AudioPerformanceTest.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
19B7C16D592FB25D09022191 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
"JUCE_CONTENT_SHARING=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
B7A6988E30C0A68B01EDC53B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
"JUCE_CONTENT_SHARING=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
B907CDF95622107F20CD7617 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "AudioPerformanceTest";
SDKROOT = iphoneos;
BF82CBDF63CC37CADC61A511 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
PRODUCT_NAME = "AudioPerformanceTest";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
-# Automatically generated makefile, created by the Projucer
+# Automatically generated CMakeLists, created by the Projucer
# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!
cmake_minimum_required(VERSION 3.4.1)
+project(juce_jni_project)
+
set(BINARY_NAME "juce_jni")
set(OBOE_DIR "../../../../../modules/juce_audio_devices/native/oboe")
enable_language(ASM)
if(JUCE_BUILD_CONFIGURATION MATCHES "DEBUG")
- add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_WASAPI=1]] [[-DJUCE_DIRECTSOUND=1]] [[-DJUCE_ALSA=1]] [[-DJUCE_USE_FLAC=0]] [[-DJUCE_USE_OGGVORBIS=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_AU=1]] [[-DJUCE_PLUGINHOST_LADSPA=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_USE_CDREADER=0]] [[-DJUCE_USE_CDBURNER=0]] [[-DJUCE_WEB_BROWSER=0]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
+ add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70003]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_WASAPI=1]] [[-DJUCE_DIRECTSOUND=1]] [[-DJUCE_ALSA=1]] [[-DJUCE_USE_FLAC=0]] [[-DJUCE_USE_OGGVORBIS=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_AU=1]] [[-DJUCE_PLUGINHOST_LADSPA=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_USE_CDREADER=0]] [[-DJUCE_USE_CDBURNER=0]] [[-DJUCE_WEB_BROWSER=0]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
elseif(JUCE_BUILD_CONFIGURATION MATCHES "RELEASE")
- add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_WASAPI=1]] [[-DJUCE_DIRECTSOUND=1]] [[-DJUCE_ALSA=1]] [[-DJUCE_USE_FLAC=0]] [[-DJUCE_USE_OGGVORBIS=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_AU=1]] [[-DJUCE_PLUGINHOST_LADSPA=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_USE_CDREADER=0]] [[-DJUCE_USE_CDBURNER=0]] [[-DJUCE_WEB_BROWSER=0]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
+ add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70003]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_WASAPI=1]] [[-DJUCE_DIRECTSOUND=1]] [[-DJUCE_ALSA=1]] [[-DJUCE_USE_FLAC=0]] [[-DJUCE_USE_OGGVORBIS=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_AU=1]] [[-DJUCE_PLUGINHOST_LADSPA=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_USE_CDREADER=0]] [[-DJUCE_USE_CDBURNER=0]] [[-DJUCE_WEB_BROWSER=0]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
if(NOT (ANDROID_ABI STREQUAL "mips" OR ANDROID_ABI STREQUAL "mips64"))
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -flto")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto")
"../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
- "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
"../../../../../modules/juce_core/native/juce_mac_Strings.mm"
"../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
"../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+ "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
"../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
"../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
"../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+ "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
"../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
"../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
"../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
"../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
"../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
"../../../../../modules/juce_gui_basics/juce_gui_basics.h"
"../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
- "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
"../../../../../modules/juce_core/native/juce_mac_Strings.mm"
"../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
"../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+ "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
"../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
"../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
"../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+ "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
"../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
"../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
"../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
"../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
"../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
"../../../../../modules/juce_gui_basics/juce_gui_basics.h"
"../../../JuceLibraryCode/JuceHeader.h"
PROPERTIES HEADER_FILE_ONLY TRUE)
-target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
-
if( JUCE_BUILD_CONFIGURATION MATCHES "DEBUG" )
- target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override)
+ target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override "-fsigned-char" )
endif()
if( JUCE_BUILD_CONFIGURATION MATCHES "RELEASE" )
- target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override)
+ target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override "-fsigned-char" )
endif()
find_library(log "log")
apply plugin: 'com.android.application'
android {
- compileSdkVersion 30
+ compileSdkVersion 33
+ namespace "com.juce.pluginhost"
externalNativeBuild {
cmake {
path "CMakeLists.txt"
defaultConfig {
applicationId "com.juce.pluginhost"
minSdkVersion 23
- targetSdkVersion 30
+ targetSdkVersion 33
externalNativeBuild {
cmake {
- arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=14", "-DCMAKE_CXX_EXTENSIONS=OFF"
+ arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=17", "-DCMAKE_CXX_EXTENSIONS=OFF"
}
}
}
}
externalNativeBuild {
cmake {
- arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-O0", "-DCMAKE_C_FLAGS_DEBUG=-O0"
+ cFlags "-O0"
+ cppFlags "-O0"
+ arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG"
}
}
dimension "default"
- }
+ }
release_ {
externalNativeBuild {
cmake {
- arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-O3", "-DCMAKE_C_FLAGS_RELEASE=-O3"
+ cFlags "-O3"
+ cppFlags "-O3"
+ arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE"
}
}
dimension "default"
- }
+ }
}
variantFilter { variant ->
<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0"
- package="com.juce.pluginhost">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"
android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-feature android:glEsVersion="0x00030000" android:required="true"/>
<application android:label="@string/app_name" android:name="com.rmsl.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false">
- <activity android:name="com.rmsl.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize"
+ <activity android:name="com.rmsl.juce.JuceActivity" android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"
android:exported="true">
<intent-filter>
clear();\r
}\r
\r
- void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
- float** outputChannelData, int numOutputChannels,\r
- int numberOfSamples) override\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+ float* const* outputChannelData, int numOutputChannels,\r
+ int numberOfSamples, const AudioIODeviceCallbackContext& context) override\r
{\r
+ ignoreUnused (context);\r
+\r
for (int i = 0; i < numberOfSamples; ++i)\r
{\r
float inputSample = 0;\r
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.0.0'
+ classpath 'com.android.tools.build:gradle:7.3.0'
}
}
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
\ No newline at end of file
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_WASAPI=1" "-DJUCE_DIRECTSOUND=1" "-DJUCE_ALSA=1" "-DJUCE_USE_FLAC=0" "-DJUCE_USE_OGGVORBIS=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_AU=1" "-DJUCE_PLUGINHOST_LADSPA=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_USE_CDREADER=0" "-DJUCE_USE_CDBURNER=0" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_WASAPI=1" "-DJUCE_DIRECTSOUND=1" "-DJUCE_ALSA=1" "-DJUCE_USE_FLAC=0" "-DJUCE_USE_OGGVORBIS=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_AU=1" "-DJUCE_PLUGINHOST_LADSPA=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_USE_CDREADER=0" "-DJUCE_USE_CDBURNER=0" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -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_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := AudioPluginHost
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_WASAPI=1" "-DJUCE_DIRECTSOUND=1" "-DJUCE_ALSA=1" "-DJUCE_USE_FLAC=0" "-DJUCE_USE_OGGVORBIS=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_AU=1" "-DJUCE_PLUGINHOST_LADSPA=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_USE_CDREADER=0" "-DJUCE_USE_CDBURNER=0" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_WASAPI=1" "-DJUCE_DIRECTSOUND=1" "-DJUCE_ALSA=1" "-DJUCE_USE_FLAC=0" "-DJUCE_USE_OGGVORBIS=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_AU=1" "-DJUCE_PLUGINHOST_LADSPA=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_USE_CDREADER=0" "-DJUCE_USE_CDBURNER=0" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -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_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := AudioPluginHost
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -Os $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
49453CC5AD9F08D2738464AC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
DEAD_CODE_STRIPPING = YES;
"NDEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
LLVM_LTO = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
C8B793AC1BEFBE7A99BE8352 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
COPY_PHASE_STRIP = NO;
"DEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
INFOPLIST_FILE = Info-App.plist;
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
- MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
49453CC5AD9F08D2738464AC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
"JUCE_CONTENT_SHARING=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
8D1CA827F1EFD443BDCF198A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "Plugin Host";
SDKROOT = iphoneos;
C8B793AC1BEFBE7A99BE8352 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
"JUCE_CONTENT_SHARING=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
C9295196717FABE454A210B7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
PRODUCT_NAME = "Plugin Host";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
}\r
\r
#if JUCE_IOS || JUCE_ANDROID\r
- auto screenBounds = Desktop::getInstance().getDisplays().getTotalBounds (true).toFloat();\r
- auto scaleFactor = jmin ((screenBounds.getWidth() - 50) / getWidth(), (screenBounds.getHeight() - 50) / getHeight());\r
+ const auto screenBounds = Desktop::getInstance().getDisplays().getTotalBounds (true).toFloat();\r
+ const auto scaleFactor = jmin ((screenBounds.getWidth() - 50.0f) / (float) getWidth(),\r
+ (screenBounds.getHeight() - 50.0f) / (float) getHeight());\r
\r
if (scaleFactor < 1.0f)\r
- setSize ((int) (getWidth() * scaleFactor), (int) (getHeight() * scaleFactor));\r
+ {\r
+ setSize ((int) (scaleFactor * (float) getWidth()),\r
+ (int) (scaleFactor * (float) getHeight()));\r
+ }\r
\r
setTopLeftPosition (20, 20);\r
#else\r
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
JUCE_CPPFLAGS_CONSOLEAPP := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_CONSOLEAPP := BinaryBuilder
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs libcurl) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
JUCE_CPPFLAGS_CONSOLEAPP := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_CONSOLEAPP := BinaryBuilder
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -Os $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs libcurl) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
00F18709927DE6070FBA7BD0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
COPY_PHASE_STRIP = NO;
"DEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_core=1",
"JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1",
"JUCE_STANDALONE_APPLICATION=1",
"$(inherited)",
);
INSTALL_PATH = "/usr/bin";
- MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
PRODUCT_BUNDLE_IDENTIFIER = com.juce.binarybuilder;
PRODUCT_NAME = "BinaryBuilder";
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
8A190EF24B99F557190320DA /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
DEAD_CODE_STRIPPING = YES;
"NDEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_core=1",
"JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1",
"JUCE_STANDALONE_APPLICATION=1",
);
INSTALL_PATH = "/usr/bin";
LLVM_LTO = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
PRODUCT_BUNDLE_IDENTIFIER = com.juce.binarybuilder;
PRODUCT_NAME = "BinaryBuilder";
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<WarningLevel>Level4</WarningLevel>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\BinaryBuilder.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<WarningLevel>Level4</WarningLevel>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\BinaryBuilder.exe</OutputFile>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
try_compile(compile_result "${test_bindir}" "${test_file_name}"
OUTPUT_VARIABLE test_build_output_0
- CXX_STANDARD 14
+ CXX_STANDARD 17
CXX_STANDARD_REQUIRED TRUE
CXX_EXTENSIONS FALSE)
try_compile(compile_result "${test_bindir}" "${test_file_name}"
OUTPUT_VARIABLE test_build_output_1
LINK_LIBRARIES atomic
- CXX_STANDARD 14
+ CXX_STANDARD 17
CXX_STANDARD_REQUIRED TRUE
CXX_EXTENSIONS FALSE)
try_compile(compile_result "${test_bindir}" "${test_file_name}"
OUTPUT_VARIABLE test_build_output_2
LINK_LIBRARIES atomic
- CXX_STANDARD 14
+ CXX_STANDARD 17
CXX_STANDARD_REQUIRED TRUE
CXX_EXTENSIONS FALSE)
_juce_add_plugin_definitions("${target_name}" INTERFACE ${format})
_juce_add_standard_defs("${target_name}")
- target_compile_features("${target_name}" INTERFACE cxx_std_14)
+ target_compile_features("${target_name}" INTERFACE cxx_std_17)
add_library("juce::${target_name}" ALIAS "${target_name}")
if(format STREQUAL "AUv3")
_juce_link_frameworks("${target_name}" INTERFACE AudioUnit)
endif()
elseif(format STREQUAL "AU")
+ target_include_directories("${target_name}" INTERFACE "${out_path}/juce_audio_plugin_client/AU")
_juce_link_frameworks("${target_name}" INTERFACE AudioUnit CoreAudioKit)
endif()
endfunction()
_juce_module_sources("${module_path}" "${base_path}" globbed_sources headers)
if(${module_name} STREQUAL "juce_audio_plugin_client")
+ list(REMOVE_ITEM headers "${module_path}/LV2/juce_LV2TurtleDumpProgram.cpp")
+
_juce_get_platform_plugin_kinds(plugin_kinds)
foreach(kind IN LISTS plugin_kinds)
if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
_juce_create_pkgconfig_target(JUCE_CURL_LINUX_DEPS libcurl)
_juce_create_pkgconfig_target(JUCE_BROWSER_LINUX_DEPS webkit2gtk-4.0 gtk+-x11-3.0)
-elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- find_program(JUCE_XCRUN xcrun)
-
- if(NOT JUCE_XCRUN)
- message(WARNING "failed to find xcrun; older resource-based AU plug-ins may not work correctly")
- endif()
endif()
# We set up default/fallback copy dirs here. If you need different copy dirs, use
# ==================================================================================================
-function(_juce_add_au_resource_fork shared_code_target au_target)
- if(NOT JUCE_XCRUN)
- return()
- endif()
-
- get_target_property(product_name ${shared_code_target} JUCE_PRODUCT_NAME)
- get_target_property(module_sources juce::juce_audio_plugin_client_AU INTERFACE_SOURCES)
-
- list(FILTER module_sources INCLUDE REGEX "/juce_audio_plugin_client_AU.r$")
-
- if(NOT module_sources)
- message(FATAL_ERROR "Failed to find AU resource file input")
- endif()
-
- list(GET module_sources 0 au_rez_sources)
-
- get_target_property(juce_library_code ${shared_code_target} JUCE_GENERATED_SOURCES_DIRECTORY)
- # We don't want our AU AppConfig.h to end up on peoples' include paths if we can help it
- set(secret_au_resource_dir "${juce_library_code}/${au_target}/secret")
- set(secret_au_plugindefines "${secret_au_resource_dir}/JucePluginDefines.h")
-
- set(au_rez_output "${secret_au_resource_dir}/${product_name}.rsrc")
-
- target_sources(${au_target} PRIVATE "${au_rez_output}")
- set_source_files_properties("${au_rez_output}" PROPERTIES
- GENERATED TRUE
- MACOSX_PACKAGE_LOCATION Resources)
-
- set(defs_file $<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},JUCE_DEFS_FILE>>)
-
- # Passing all our compile definitions using generator expressions is really painful
- # because some of the definitions have pipes and quotes and dollars and goodness-knows
- # what else that the shell would very much like to claim for itself, thank you very much.
- # CMake definitely knows how to escape all these things, because it's perfectly happy to pass
- # them to compiler invocations, but I have no idea how to get it to escape them
- # in a custom command.
- # In the end, it's simplest to generate a special single-purpose appconfig just for the
- # resource compiler.
- add_custom_command(OUTPUT "${secret_au_plugindefines}"
- COMMAND juce::juceaide auplugindefines "${defs_file}" "${secret_au_plugindefines}"
- DEPENDS "${defs_file}"
- VERBATIM)
-
- add_custom_command(OUTPUT "${au_rez_output}"
- COMMAND "${JUCE_XCRUN}" Rez
- -d "ppc_$ppc" -d "i386_$i386" -d "ppc64_$ppc64" -d "x86_64_$x86_64" -d "arm64_$arm64"
- -I "${secret_au_resource_dir}"
- -I "/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers"
- -I "${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/AudioUnit.framework/Headers"
- -isysroot "${CMAKE_OSX_SYSROOT}"
- "${au_rez_sources}"
- -useDF
- -o "${au_rez_output}"
- DEPENDS "${secret_au_plugindefines}"
- VERBATIM)
-
- set(au_resource_directory "$<TARGET_BUNDLE_DIR:${au_target}>/Contents/Resources")
-endfunction()
-
-# ==================================================================================================
-
# Ideally, we'd check the preprocessor defs on the target to see whether
# JUCE_USE_CURL, JUCE_WEB_BROWSER, or JUCE_IN_APP_PURCHASES have been explicitly turned off,
# and then link libraries as appropriate.
target_sources(${target} PRIVATE "${binary_file_names}")
target_include_directories(${target} INTERFACE ${juce_binary_data_folder})
- target_compile_features(${target} PRIVATE cxx_std_14)
+ target_compile_features(${target} PRIVATE cxx_std_17)
# This fixes an issue where Xcode is unable to find binary data during archive.
if(CMAKE_GENERATOR STREQUAL "Xcode")
get_target_property(active_targets "${shared_code_target}" JUCE_ACTIVE_PLUGIN_TARGETS)
foreach(target IN LISTS active_targets)
+ get_target_property(target_kind "${target}" JUCE_TARGET_KIND_STRING)
+
+ if(target_kind STREQUAL "App")
+ continue()
+ endif()
+
get_target_property(source "${target}" JUCE_PLUGIN_ARTEFACT_FILE)
if(source)
# ==================================================================================================
+function(_juce_add_lv2_manifest_helper_target)
+ if(TARGET juce_lv2_helper)
+ return()
+ endif()
+
+ get_target_property(module_path juce::juce_audio_plugin_client INTERFACE_JUCE_MODULE_PATH)
+ set(source "${module_path}/juce_audio_plugin_client/LV2/juce_LV2TurtleDumpProgram.cpp")
+ add_executable(juce_lv2_helper "${source}")
+ add_executable(juce::juce_lv2_helper ALIAS juce_lv2_helper)
+ target_compile_features(juce_lv2_helper PRIVATE cxx_std_14)
+ set_target_properties(juce_lv2_helper PROPERTIES BUILD_WITH_INSTALL_RPATH ON)
+ target_link_libraries(juce_lv2_helper PRIVATE ${CMAKE_DL_LIBS})
+endfunction()
+
+# ==================================================================================================
+
function(_juce_set_plugin_target_properties shared_code_target kind)
set(target_name ${shared_code_target}_${kind})
get_target_property(products_folder ${target_name} LIBRARY_OUTPUT_DIRECTORY)
set(product_name $<TARGET_PROPERTY:${shared_code_target},JUCE_PRODUCT_NAME>)
- if(kind STREQUAL "VST3")
+ if(kind STREQUAL "Standalone")
+ get_target_property(is_bundle "${target_name}" BUNDLE)
+
+ if(is_bundle)
+ set_target_properties("${target_name}" PROPERTIES JUCE_PLUGIN_ARTEFACT_FILE "$<TARGET_BUNDLE_DIR:${target_name}>")
+ else()
+ set_target_properties("${target_name}" PROPERTIES JUCE_PLUGIN_ARTEFACT_FILE "$<TARGET_FILE:${target_name}>")
+ endif()
+ elseif(kind STREQUAL "VST3")
set_target_properties(${target_name} PROPERTIES
BUNDLE_EXTENSION vst3
PREFIX ""
set(output_path "${products_folder}/${product_name}.lv2")
set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${output_path}")
+ _juce_add_lv2_manifest_helper_target()
+
add_custom_command(TARGET ${target_name} POST_BUILD
- COMMAND juce::juce_lv2_helper "$<TARGET_FILE:${target_name}>"
+ COMMAND juce_lv2_helper "$<TARGET_FILE:${target_name}>"
VERBATIM)
_juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_LV2_COPY_DIR)
_juce_configure_app_bundle(${target} ${target}_Standalone)
endif()
- if(TARGET ${target}_AU)
- _juce_add_au_resource_fork(${target} ${target}_AU)
- endif()
-
if(TARGET ${target}_AAX)
target_link_libraries(${target}_AAX PRIVATE juce_aax_sdk)
endif()
\r
ID: juce_build_tools\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\r
name: JUCE Build Tools\r
description: Classes for generating intermediate files for JUCE projects.\r
website: http://www.juce.com/juce\r
else()
# If we're building using the NDK, the gradle wrapper will try to inject its own compiler using
# environment variables, which is unfortunate because we really don't want to cross-compile
- # juceaide. If you really want to set the compilers for juceaide, pass the appropriate
- # CMAKE_<lang>_COMPILER flags when configuring CMake.
+ # juceaide.
+ # Similarly, when cross-compiling from Linux->Windows (e.g. using
+ # Fedora's mingw64-cmake command), the environment might be configured
+ # for cross-compiling, and we'll need to attempt to put it back to the
+ # host settings in order to build an executable that can run on the host
+ # machine.
if(CMAKE_CROSSCOMPILING)
+ unset(ENV{ADDR2LINE})
+ unset(ENV{AR})
unset(ENV{ASM})
+ unset(ENV{AS})
unset(ENV{CC})
+ unset(ENV{CPP})
+ unset(ENV{CXXFILT})
unset(ENV{CXX})
+ unset(ENV{DLLTOOL})
+ unset(ENV{DLLWRAP})
+ unset(ENV{ELFEDIT})
+ unset(ENV{GCC})
+ unset(ENV{GCOV_DUMP})
+ unset(ENV{GCOV_TOOL})
+ unset(ENV{GCOV})
+ unset(ENV{GPROF})
+ unset(ENV{GXX})
+ unset(ENV{LDFLAGS})
+ unset(ENV{LD_BFD})
+ unset(ENV{LD})
+ unset(ENV{LTO_DUMP})
+ unset(ENV{NM})
+ unset(ENV{OBJCOPY})
+ unset(ENV{OBJDUMP})
+ unset(ENV{PKG_CONFIG_LIBDIR})
+ unset(ENV{PKG_CONFIG})
+ unset(ENV{RANLIB})
+ unset(ENV{RC})
+ unset(ENV{READELF})
+ unset(ENV{SIZE})
+ unset(ENV{STRINGS})
+ unset(ENV{STRIP})
+ unset(ENV{WIDL})
+ unset(ENV{WINDMC})
+ unset(ENV{WINDRES})
+
+ if(DEFINED ENV{PATH_ORIG})
+ set(ENV{PATH} "$ENV{PATH_ORIG}")
+ endif()
else()
# When building with clang-cl in Clion on Windows for an x64 target, the ABI detection phase
# of the inner build can fail unless we pass through these flags too
juce::ArgumentList argumentList { arguments.front(),\r
juce::StringArray (arguments.data() + 1, (int) arguments.size() - 1) };\r
\r
- using Fn = std::add_lvalue_reference<decltype (writeBinaryData)>::type;\r
+ using Fn = int (*) (juce::ArgumentList&&);\r
\r
const std::unordered_map<juce::String, Fn> commands\r
{\r
-# Automatically generated makefile, created by the Projucer
+# Automatically generated CMakeLists, created by the Projucer
# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!
cmake_minimum_required(VERSION 3.4.1)
+project(juce_jni_project)
+
set(BINARY_NAME "juce_jni")
set(OBOE_DIR "../../../../../modules/juce_audio_devices/native/oboe")
enable_language(ASM)
if(JUCE_BUILD_CONFIGURATION MATCHES "DEBUG")
- add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEBUG=0]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
+ add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70003]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEBUG=0]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
elseif(JUCE_BUILD_CONFIGURATION MATCHES "RELEASE")
- add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
+ add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70003]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
else()
message( FATAL_ERROR "No matching build-configuration found." )
endif()
"../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
- "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
"../../../../../modules/juce_core/native/juce_mac_Strings.mm"
"../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
"../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+ "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
"../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
"../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
"../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+ "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
"../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
"../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
"../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
"../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
"../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
"../../../../../modules/juce_gui_basics/juce_gui_basics.h"
"../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
"../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
- "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
"../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
"../../../../../modules/juce_core/native/juce_mac_Strings.mm"
"../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
"../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+ "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
"../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
"../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
"../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
"../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+ "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
"../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
"../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
"../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
"../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
"../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+ "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
"../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
"../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
"../../../../../modules/juce_gui_basics/juce_gui_basics.h"
"../../../JuceLibraryCode/JuceHeader.h"
PROPERTIES HEADER_FILE_ONLY TRUE)
-target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
-
if( JUCE_BUILD_CONFIGURATION MATCHES "DEBUG" )
- target_compile_options( ${BINARY_NAME} PRIVATE)
+ target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
endif()
if( JUCE_BUILD_CONFIGURATION MATCHES "RELEASE" )
- target_compile_options( ${BINARY_NAME} PRIVATE)
+ target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
endif()
find_library(log "log")
apply plugin: 'com.android.application'
android {
- compileSdkVersion 30
+ compileSdkVersion 33
+ namespace "com.juce.networkgraphicsdemo"
externalNativeBuild {
cmake {
path "CMakeLists.txt"
defaultConfig {
applicationId "com.juce.networkgraphicsdemo"
minSdkVersion 16
- targetSdkVersion 30
+ targetSdkVersion 33
externalNativeBuild {
cmake {
- arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-16", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=14", "-DCMAKE_CXX_EXTENSIONS=OFF"
+ arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-16", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=17", "-DCMAKE_CXX_EXTENSIONS=OFF"
}
}
}
}
externalNativeBuild {
cmake {
- arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-Ofast", "-DCMAKE_C_FLAGS_DEBUG=-Ofast"
+ cFlags "-Ofast"
+ cppFlags "-Ofast"
+ arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG"
}
}
dimension "default"
- }
+ }
release_ {
externalNativeBuild {
cmake {
- arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-O3", "-DCMAKE_C_FLAGS_RELEASE=-O3"
+ cFlags "-O3"
+ cppFlags "-O3"
+ arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE"
}
}
dimension "default"
- }
+ }
}
variantFilter { variant ->
<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0"
- package="com.juce.networkgraphicsdemo">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"
android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
<application android:label="@string/app_name" android:name="com.rmsl.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false">
- <activity android:name="com.rmsl.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize"
+ <activity android:name="com.rmsl.juce.JuceActivity" android:configChanges="keyboardHidden|orientation|screenSize"
android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"
android:exported="true">
<intent-filter>
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.0.0'
+ classpath 'com.android.tools.build:gradle:7.3.0'
}
}
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
\ No newline at end of file
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl 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_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := JUCE\ Network\ Graphics\ Demo
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl 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_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := JUCE\ Network\ Graphics\ Demo
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
2E06386CE7CCA5FF76819BFF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
DEAD_CODE_STRIPPING = YES;
"NDEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
LLVM_LTO = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_LDFLAGS = "-weak_framework Metal -weak_framework MetalKit";
PRODUCT_BUNDLE_IDENTIFIER = com.juce.NetworkGraphicsDemo;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
EE7498599191DDC73ECB55B0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
COPY_PHASE_STRIP = NO;
"DEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
INFOPLIST_FILE = Info-App.plist;
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_LDFLAGS = "-weak_framework Metal -weak_framework MetalKit";
PRODUCT_BUNDLE_IDENTIFIER = com.juce.NetworkGraphicsDemo;
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<WarningLevel>Level4</WarningLevel>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\JUCE Network Graphics Demo.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<WarningLevel>Level4</WarningLevel>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\JUCE Network Graphics Demo.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
2E06386CE7CCA5FF76819BFF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
"JUCE_CONTENT_SHARING=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
3BF0365A560ACD4FD24D40CE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "JUCE Network Graphics Demo";
SDKROOT = iphoneos;
9C6D2FD441D79104734762A5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
PRODUCT_NAME = "JUCE Network Graphics Demo";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
EE7498599191DDC73ECB55B0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
"JUCE_CONTENT_SHARING=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
<EXPORTFORMATS>\r
<XCODE_MAC targetFolder="Builds/MacOSX" bigIcon="Ww6bQw" applicationCategory="public.app-category.developer-tools">\r
<CONFIGURATIONS>\r
- <CONFIGURATION name="Debug" osxCompatibility="10.9 SDK" isDebug="1" targetName="JUCE Network Graphics Demo"\r
- macOSDeploymentTarget="10.9"/>\r
- <CONFIGURATION name="Release" osxCompatibility="10.9 SDK" isDebug="0" targetName="JUCE Network Graphics Demo"\r
- macOSDeploymentTarget="10.9"/>\r
+ <CONFIGURATION name="Debug" isDebug="1" targetName="JUCE Network Graphics Demo"/>\r
+ <CONFIGURATION name="Release" isDebug="0" targetName="JUCE Network Graphics Demo"/>\r
</CONFIGURATIONS>\r
<MODULEPATHS>\r
<MODULEPATH id="juce_core" path="../../modules"/>\r
androidCpp11="1" targetFolder="Builds/Android" bigIcon="Ww6bQw"\r
gradleToolchainVersion="3.6">\r
<CONFIGURATIONS>\r
- <CONFIGURATION name="Debug" isDebug="1" optimisation="6"\r
- targetName="JUCE Network Graphics Demo" defines="JUCE_DEBUG=0"/>\r
+ <CONFIGURATION name="Debug" isDebug="1" optimisation="6" targetName="JUCE Network Graphics Demo"\r
+ defines="JUCE_DEBUG=0"/>\r
<CONFIGURATION name="Release" isDebug="0" targetName="JUCE Network Graphics Demo"/>\r
</CONFIGURATIONS>\r
<MODULEPATHS>\r
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_build_tools=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_LOG_ASSERTIONS=1" "-DJUCE_USE_CURL=1" "-DJUCE_LOAD_CURL_SYMBOLS_LAZILY=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.2" "-DJUCE_APP_VERSION_HEX=0x70002" $(shell $(PKG_CONFIG) --cflags freetype2) -pthread -I../../JuceLibraryCode -I../../../Build -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_build_tools=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_LOG_ASSERTIONS=1" "-DJUCE_USE_CURL=1" "-DJUCE_LOAD_CURL_SYMBOLS_LAZILY=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.3" "-DJUCE_APP_VERSION_HEX=0x70003" $(shell $(PKG_CONFIG) --cflags freetype2) -pthread -I../../JuceLibraryCode -I../../../Build -I../../../../modules $(CPPFLAGS)
JUCE_CPPFLAGS_APP := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := Projucer
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs freetype2) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_build_tools=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_LOG_ASSERTIONS=1" "-DJUCE_USE_CURL=1" "-DJUCE_LOAD_CURL_SYMBOLS_LAZILY=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.2" "-DJUCE_APP_VERSION_HEX=0x70002" $(shell $(PKG_CONFIG) --cflags freetype2) -pthread -I../../JuceLibraryCode -I../../../Build -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_build_tools=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_LOG_ASSERTIONS=1" "-DJUCE_USE_CURL=1" "-DJUCE_LOAD_CURL_SYMBOLS_LAZILY=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.3" "-DJUCE_APP_VERSION_HEX=0x70003" $(shell $(PKG_CONFIG) --cflags freetype2) -pthread -I../../JuceLibraryCode -I../../../Build -I../../../../modules $(CPPFLAGS)
JUCE_CPPFLAGS_APP := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_APP := Projucer
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs freetype2) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
<key>CFBundleSignature</key>\r
<string>????</string>\r
<key>CFBundleShortVersionString</key>\r
- <string>7.0.2</string>\r
+ <string>7.0.3</string>\r
<key>CFBundleVersion</key>\r
- <string>7.0.2</string>\r
+ <string>7.0.3</string>\r
<key>NSHumanReadableCopyright</key>\r
<string>Raw Material Software Limited</string>\r
<key>NSHighResolutionCapable</key>\r
0BC15DC2E5FE5ECFFB398D49 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
DEAD_CODE_STRIPPING = YES;
"NDEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_build_tools=1",
"JUCE_MODULE_AVAILABLE_juce_core=1",
"JUCE_MODULE_AVAILABLE_juce_cryptography=1",
"JUCE_WEB_BROWSER=0",
"JUCE_STANDALONE_APPLICATION=1",
"JUCER_XCODE_MAC_F6D2F4CF=1",
- "JUCE_APP_VERSION=7.0.2",
- "JUCE_APP_VERSION_HEX=0x70002",
+ "JUCE_APP_VERSION=7.0.3",
+ "JUCE_APP_VERSION_HEX=0x70003",
"JucePlugin_Build_VST=0",
"JucePlugin_Build_VST3=0",
"JucePlugin_Build_AU=0",
INFOPLIST_FILE = Info-App.plist;
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
- MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../Build $(SRCROOT)/../../../../modules";
OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
0CC6C439D038EDA0D7F10DF0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
COPY_PHASE_STRIP = NO;
"DEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_build_tools=1",
"JUCE_MODULE_AVAILABLE_juce_core=1",
"JUCE_MODULE_AVAILABLE_juce_cryptography=1",
"JUCE_WEB_BROWSER=0",
"JUCE_STANDALONE_APPLICATION=1",
"JUCER_XCODE_MAC_F6D2F4CF=1",
- "JUCE_APP_VERSION=7.0.2",
- "JUCE_APP_VERSION_HEX=0x70002",
+ "JUCE_APP_VERSION=7.0.3",
+ "JUCE_APP_VERSION_HEX=0x70003",
"JucePlugin_Build_VST=0",
"JucePlugin_Build_VST3=0",
"JucePlugin_Build_AU=0",
INFOPLIST_FILE = Info-App.plist;
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
- MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../Build $(SRCROOT)/../../../../modules";
OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
#include <windows.h>\r
\r
VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION 7,0,2,0\r
+FILEVERSION 7,0,3,0\r
BEGIN\r
BLOCK "StringFileInfo"\r
BEGIN\r
VALUE "CompanyName", "Raw Material Software Limited\0"\r
VALUE "LegalCopyright", "Raw Material Software Limited\0"\r
VALUE "FileDescription", "Projucer\0"\r
- VALUE "FileVersion", "7.0.2\0"\r
+ VALUE "FileVersion", "7.0.3\0"\r
VALUE "ProductName", "Projucer\0"\r
- VALUE "ProductVersion", "7.0.2\0"\r
+ VALUE "ProductVersion", "7.0.3\0"\r
END\r
END\r
\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
#include <windows.h>\r
\r
VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION 7,0,2,0\r
+FILEVERSION 7,0,3,0\r
BEGIN\r
BLOCK "StringFileInfo"\r
BEGIN\r
VALUE "CompanyName", "Raw Material Software Limited\0"\r
VALUE "LegalCopyright", "Raw Material Software Limited\0"\r
VALUE "FileDescription", "Projucer\0"\r
- VALUE "FileVersion", "7.0.2\0"\r
+ VALUE "FileVersion", "7.0.3\0"\r
VALUE "ProductName", "Projucer\0"\r
- VALUE "ProductVersion", "7.0.2\0"\r
+ VALUE "ProductVersion", "7.0.3\0"\r
END\r
END\r
\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.3;JUCE_APP_VERSION_HEX=0x70003;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
#include <windows.h>\r
\r
VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION 7,0,2,0\r
+FILEVERSION 7,0,3,0\r
BEGIN\r
BLOCK "StringFileInfo"\r
BEGIN\r
VALUE "CompanyName", "Raw Material Software Limited\0"\r
VALUE "LegalCopyright", "Raw Material Software Limited\0"\r
VALUE "FileDescription", "Projucer\0"\r
- VALUE "FileVersion", "7.0.2\0"\r
+ VALUE "FileVersion", "7.0.3\0"\r
VALUE "ProductName", "Projucer\0"\r
- VALUE "ProductVersion", "7.0.2\0"\r
+ VALUE "ProductVersion", "7.0.3\0"\r
END\r
END\r
\r
juce_generate_juce_header(Projucer)
-# This is to work around a bug with how cmake computes language standard flags with
-# target_compile_features
-set_target_properties(Projucer PROPERTIES CXX_STANDARD 11)
-
target_sources(Projucer PRIVATE
Source/Application/jucer_AutoUpdater.cpp
Source/Application/jucer_CommandLine.cpp
{\r
const char* const projectName = "Projucer";\r
const char* const companyName = "Raw Material Software Limited";\r
- const char* const versionString = "7.0.2";\r
- const int versionNumber = 0x70002;\r
+ const char* const versionString = "7.0.3";\r
+ const int versionNumber = 0x70003;\r
}\r
#endif\r
<?xml version="1.0" encoding="UTF-8"?>\r
\r
<JUCERPROJECT id="M70qfTRRk" name="Projucer" projectType="guiapp" juceFolder="../../juce"\r
- version="7.0.2" bundleIdentifier="com.juce.theprojucer" splashScreenColour="Dark"\r
+ version="7.0.3" bundleIdentifier="com.juce.theprojucer" splashScreenColour="Dark"\r
displaySplashScreen="0" reportAppUsage="0" companyName="Raw Material Software Limited"\r
companyCopyright="Raw Material Software Limited" useAppConfig="0"\r
addUsingNamespaceToJuceHeader="1" jucerFormatVersion="1">\r
applicationCategory="public.app-category.developer-tools">\r
<CONFIGURATIONS>\r
<CONFIGURATION name="Debug" isDebug="1" targetName="Projucer" cppLibType="libc++"\r
- recommendedWarnings="LLVM" macOSDeploymentTarget="10.12"/>\r
+ recommendedWarnings="LLVM"/>\r
<CONFIGURATION name="Release" isDebug="0" targetName="Projucer" cppLibType="libc++"\r
- linkTimeOptimisation="0" recommendedWarnings="LLVM" macOSDeploymentTarget="10.12"/>\r
+ linkTimeOptimisation="0" recommendedWarnings="LLVM"/>\r
</CONFIGURATIONS>\r
<MODULEPATHS>\r
<MODULEPATH id="juce_gui_extra" path="../../modules"/>\r
if (! isThreadRunning())\r
{\r
backgroundCheck = background;\r
- startThread (3);\r
+ startThread (Priority::low);\r
}\r
}\r
\r
: ThreadWithProgressWindow ("Downloading New Version", true, true),\r
asset (a), targetFolder (t), completionCallback (std::move (cb))\r
{\r
- launchThread (3);\r
+ launchThread (Priority::low);\r
}\r
\r
private:\r
p.pos [numPoints - 1] = p.pos [oldNumPoints - 1];\r
p.pos [numPoints - 1].getRectangleDouble (x, y, w, h, parentArea, owner->getDocument()->getComponentLayout());\r
\r
- const int index = owner->points.indexOf (this);\r
+ const int index = owner->indexOfPoint (this);\r
\r
- if (PathPoint* lastPoint = owner->points [index - 1])\r
+ if (PathPoint* lastPoint = owner->getPoint (index - 1))\r
{\r
lastPoint->pos [lastPoint->getNumPoints() - 1]\r
.getRectangleDouble (lastX, lastY, w, h, parentArea, owner->getDocument()->getComponentLayout());\r
if (multipleSelected)\r
return;\r
\r
- auto index = owner->points.indexOf (this);\r
+ auto index = owner->indexOfPoint (this);\r
jassert (index >= 0);\r
\r
switch (type)\r
\r
void PathPoint::deleteFromPath()\r
{\r
- owner->deletePoint (owner->points.indexOf (this), true);\r
+ owner->deletePoint (owner->indexOfPoint (this), true);\r
}\r
\r
//==============================================================================\r
setSize (11, 11);\r
setRepaintsOnMouseActivity (true);\r
\r
- selected = routine->getSelectedPoints().isSelected (path_->points [index]);\r
+ selected = routine->getSelectedPoints().isSelected (path_->getPoint (index));\r
routine->getSelectedPoints().addChangeListener (this);\r
}\r
\r
dragX = getX() + getWidth() / 2;\r
dragY = getY() + getHeight() / 2;\r
\r
- mouseDownSelectStatus = routine->getSelectedPoints().addToSelectionOnMouseDown (path->points [index], e.mods);\r
+ mouseDownSelectStatus = routine->getSelectedPoints().addToSelectionOnMouseDown (path->getPoint (index), e.mods);\r
\r
owner->getDocument()->beginTransaction();\r
}\r
\r
void PathPointComponent::mouseUp (const MouseEvent& e)\r
{\r
- routine->getSelectedPoints().addToSelectionOnMouseUp (path->points [index],\r
+ routine->getSelectedPoints().addToSelectionOnMouseUp (path->getPoint (index),\r
e.mods, dragging,\r
mouseDownSelectStatus);\r
}\r
{\r
ElementSiblingComponent::changeListenerCallback (source);\r
\r
- const bool nowSelected = routine->getSelectedPoints().isSelected (path->points [index]);\r
+ const bool nowSelected = routine->getSelectedPoints().isSelected (path->getPoint (index));\r
\r
if (nowSelected != selected)\r
{\r
//==============================================================================\r
void setInitialBounds (int parentWidth, int parentHeight) override;\r
Rectangle<int> getCurrentBounds (const Rectangle<int>& parentArea) const override;\r
- void setCurrentBounds (const Rectangle<int>& b, const Rectangle<int>& parentArea, const bool undoable) override;\r
+ void setCurrentBounds (const Rectangle<int>& b, const Rectangle<int>& parentArea, bool undoable) override;\r
\r
//==============================================================================\r
bool getPoint (int index, int pointNumber, double& x, double& y, const Rectangle<int>& parentArea) const;\r
- void movePoint (int index, int pointNumber, double newX, double newY, const Rectangle<int>& parentArea, const bool undoable);\r
+ void movePoint (int index, int pointNumber, double newX, double newY, const Rectangle<int>& parentArea, bool undoable);\r
\r
RelativePositionedRectangle getPoint (int index, int pointNumber) const;\r
- void setPoint (int index, int pointNumber, const RelativePositionedRectangle& newPoint, const bool undoable);\r
+ void setPoint (int index, int pointNumber, const RelativePositionedRectangle& newPoint, bool undoable);\r
\r
int getNumPoints() const noexcept { return points.size(); }\r
PathPoint* getPoint (int index) const noexcept { return points [index]; }\r
- int indexOfPoint (PathPoint* const p) const noexcept { return points.indexOf (p); }\r
+ int indexOfPoint (const PathPoint* p) const noexcept { return points.indexOf (p); }\r
\r
- PathPoint* addPoint (int pointIndexToAddItAfter, const bool undoable);\r
- void deletePoint (int pointIndex, const bool undoable);\r
+ PathPoint* addPoint (int pointIndexToAddItAfter, bool undoable);\r
+ void deletePoint (int pointIndex, bool undoable);\r
\r
void pointListChanged();\r
\r
\r
//==============================================================================\r
bool isSubpathClosed (int pointIndex) const;\r
- void setSubpathClosed (int pointIndex, const bool closed, const bool undoable);\r
+ void setSubpathClosed (int pointIndex, bool closed, bool undoable);\r
\r
bool isNonZeroWinding() const noexcept { return nonZeroWinding; }\r
- void setNonZeroWinding (const bool nonZero, const bool undoable);\r
+ void setNonZeroWinding (bool nonZero, bool undoable);\r
\r
//==============================================================================\r
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override;\r
void changed() override;\r
\r
private:\r
- friend class PathPoint;\r
- friend class PathPointComponent;\r
OwnedArray<PathPoint> points;\r
bool nonZeroWinding;\r
mutable Path path;\r
\r
void perform (UndoableAction* action, const String& actionName);\r
\r
+ void moveComponentZOrder (int oldIndex, int newIndex);\r
+\r
private:\r
JucerDocument* document;\r
OwnedArray<Component> components;\r
int nextCompUID;\r
\r
String getUnusedMemberName (String nameRoot, Component* comp) const;\r
-\r
- friend class FrontBackCompAction;\r
- friend class DeleteCompAction;\r
- void moveComponentZOrder (int oldIndex, int newIndex);\r
};\r
\r
void positionToCode (const RelativePositionedRectangle& position,\r
\r
//==============================================================================\r
int getNumElements() const noexcept { return elements.size(); }\r
- PaintElement* getElement (const int index) const noexcept { return elements [index]; }\r
+ PaintElement* getElement (int index) const noexcept { return elements [index]; }\r
int indexOfElement (PaintElement* e) const noexcept { return elements.indexOf (e); }\r
bool containsElement (PaintElement* e) const noexcept { return elements.contains (e); }\r
\r
//==============================================================================\r
void clear();\r
- PaintElement* addElementFromXml (const XmlElement& xml, const int index, const bool undoable);\r
- PaintElement* addNewElement (PaintElement* elementToCopy, const int index, const bool undoable);\r
- void removeElement (PaintElement* element, const bool undoable);\r
+ PaintElement* addElementFromXml (const XmlElement& xml, int index, bool undoable);\r
+ PaintElement* addNewElement (PaintElement* elementToCopy, int index, bool undoable);\r
+ void removeElement (PaintElement* element, bool undoable);\r
\r
- void elementToFront (PaintElement* element, const bool undoable);\r
- void elementToBack (PaintElement* element, const bool undoable);\r
+ void elementToFront (PaintElement* element, bool undoable);\r
+ void elementToBack (PaintElement* element, bool undoable);\r
\r
- const Colour getBackgroundColour() const noexcept { return backgroundColour; }\r
+ Colour getBackgroundColour() const noexcept { return backgroundColour; }\r
void setBackgroundColour (Colour newColour) noexcept;\r
\r
- void fillWithBackground (Graphics& g, const bool drawOpaqueBackground);\r
+ void fillWithBackground (Graphics& g, bool drawOpaqueBackground);\r
void drawElements (Graphics& g, const Rectangle<int>& relativeTo);\r
\r
void dropImageAt (const File& f, int x, int y);\r
void applyCustomPaintSnippets (StringArray&);\r
\r
//==============================================================================\r
+ void moveElementZOrder (int oldIndex, int newIndex);\r
+\r
private:\r
OwnedArray<PaintElement> elements;\r
SelectedItemSet <PaintElement*> selectedElements;\r
JucerDocument* document;\r
\r
Colour backgroundColour;\r
-\r
- friend class DeleteElementAction;\r
- friend class FrontOrBackElementAction;\r
- void moveElementZOrder (int oldIndex, int newIndex);\r
};\r
findPanel = (1 << 2)\r
};\r
\r
- JUCE_NODISCARD AdditionalComponents with (Type t)\r
+ [[nodiscard]] AdditionalComponents with (Type t)\r
{\r
auto copy = *this;\r
copy.componentTypes |= t;\r
}\r
}\r
\r
- if (highestLanguageStandard >= 14)\r
+ if (highestLanguageStandard >= 17)\r
{\r
cppStandardValue = highestLanguageStandard;\r
return true;\r
\r
void Project::updateDeprecatedProjectSettings()\r
{\r
- if (cppStandardValue.get().toString() == "11")\r
- cppStandardValue.resetToDefault();\r
+ for (const auto& version : { "11", "14" })\r
+ {\r
+ if (cppStandardValue.get().toString() == version)\r
+ {\r
+ cppStandardValue.resetToDefault();\r
+ break;\r
+ }\r
+ }\r
\r
for (ExporterIterator exporter (*this); exporter.next();)\r
exporter->updateDeprecatedSettings();\r
useAppConfigValue.referTo (projectRoot, Ids::useAppConfig, getUndoManager(), true);\r
addUsingNamespaceToJuceHeader.referTo (projectRoot, Ids::addUsingNamespaceToJuceHeader, getUndoManager(), true);\r
\r
- cppStandardValue.referTo (projectRoot, Ids::cppLanguageStandard, getUndoManager(), "14");\r
+ cppStandardValue.referTo (projectRoot, Ids::cppLanguageStandard, getUndoManager(), "17");\r
\r
headerSearchPathsValue.referTo (projectRoot, Ids::headerPath, getUndoManager());\r
preprocessorDefsValue.referTo (projectRoot, Ids::defines, getUndoManager());\r
bool Project::Item::shouldSkipPCH() const { return isModuleCode() || state [Ids::skipPCH]; }\r
\r
Value Project::Item::getCompilerFlagSchemeValue() { return state.getPropertyAsValue (Ids::compilerFlagScheme, getUndoManager()); }\r
-String Project::Item::getCompilerFlagSchemeString() const { return state [Ids::compilerFlagScheme]; }\r
+\r
+String Project::Item::getCompilerFlagSchemeString() const { return state[Ids::compilerFlagScheme]; }\r
\r
void Project::Item::setCompilerFlagScheme (const String& scheme)\r
{\r
bool shouldDisplaySplashScreen() const { return displaySplashScreenValue.get(); }\r
String getSplashScreenColourString() const { return splashScreenColourValue.get(); }\r
\r
- static StringArray getCppStandardStrings() { return { "C++14", "C++17", "C++20", "Use Latest" }; }\r
- static Array<var> getCppStandardVars() { return { "14", "17", "20", "latest" }; }\r
+ static StringArray getCppStandardStrings() { return { "C++17", "C++20", "Use Latest" }; }\r
+ static Array<var> getCppStandardVars() { return { "17", "20", "latest" }; }\r
\r
static String getLatestNumberedCppStandardString()\r
{\r
androidGradleSettingsContent (settings, Ids::androidGradleSettingsContent, getUndoManager()),\r
androidVersionCode (settings, Ids::androidVersionCode, getUndoManager(), "1"),\r
androidMinimumSDK (settings, Ids::androidMinimumSDK, getUndoManager(), "16"),\r
- androidTargetSDK (settings, Ids::androidTargetSDK, getUndoManager(), "30"),\r
+ androidTargetSDK (settings, Ids::androidTargetSDK, getUndoManager(), "33"),\r
androidTheme (settings, Ids::androidTheme, getUndoManager()),\r
androidExtraAssetsFolder (settings, Ids::androidExtraAssetsFolder, getUndoManager()),\r
androidOboeRepositoryPath (settings, Ids::androidOboeRepositoryPath, getUndoManager()),\r
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(), "7.0.2"),\r
+ gradleVersion (settings, Ids::gradleVersion, getUndoManager(), "7.5.1"),\r
gradleToolchain (settings, Ids::gradleToolchain, getUndoManager(), "clang"),\r
- androidPluginVersion (settings, Ids::androidPluginVersion, getUndoManager(), "7.0.0"),\r
+ androidPluginVersion (settings, Ids::androidPluginVersion, getUndoManager(), "7.3.0"),\r
AndroidExecutable (getAppSettings().getStoredPath (Ids::androidStudioExePath, TargetOS::getThisOS()).get().toString())\r
{\r
name = getDisplayName();\r
{\r
mo.setNewLineString (getNewLineString());\r
\r
- mo << "# Automatically generated makefile, created by the Projucer" << newLine\r
+ mo << "# Automatically generated CMakeLists, created by the Projucer" << newLine\r
<< "# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine\r
+ << newLine\r
+ << "cmake_minimum_required(VERSION 3.4.1)" << newLine\r
+ << newLine\r
+ << "project(juce_jni_project)" << newLine\r
<< newLine;\r
\r
- mo << "cmake_minimum_required(VERSION 3.4.1)" << newLine << newLine;\r
-\r
if (! isLibrary())\r
mo << "set(BINARY_NAME \"juce_jni\")" << newLine << newLine;\r
\r
mo << ")" << newLine << newLine;\r
}\r
\r
- auto cfgExtraLinkerFlags = getExtraLinkerFlagsString();\r
- if (cfgExtraLinkerFlags.isNotEmpty())\r
- {\r
- mo << "set( JUCE_LDFLAGS \"" << cfgExtraLinkerFlags.replace ("\"", "\\\"") << "\")" << newLine;\r
- mo << "set( CMAKE_SHARED_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} ${JUCE_LDFLAGS}\")" << newLine << newLine;\r
- }\r
-\r
mo << "enable_language(ASM)" << newLine << newLine;\r
\r
const auto userLibraries = getUserLibraries();\r
if (cfgDefines.size() > 0)\r
mo << " add_definitions(" << getEscapedPreprocessorDefs (cfgDefines).joinIntoString (" ") << ")" << newLine;\r
\r
+ const auto cfgExtraLinkerFlags = cfg.getAllLinkerFlagsString();\r
+\r
+ if (cfgExtraLinkerFlags.isNotEmpty())\r
+ {\r
+ mo << " set( JUCE_LDFLAGS \"" << cfgExtraLinkerFlags.replace ("\"", "\\\"") << "\" )" << newLine\r
+ << " set( CMAKE_SHARED_LINKER_FLAGS \"${CMAKE_SHARED_LINKER_FLAGS} ${JUCE_LDFLAGS}\" )" << newLine << newLine;\r
+ }\r
+\r
writeCmakePathLines (mo, " ", "include_directories( AFTER", cfgHeaderPaths);\r
\r
if (userLibraries.size() > 0)\r
mo << newLine;\r
}\r
\r
- auto flags = getProjectCompilerFlags();\r
-\r
- if (flags.size() > 0)\r
- mo << "target_compile_options( ${BINARY_NAME} PRIVATE " << flags.joinIntoString (" ") << " )" << newLine << newLine;\r
-\r
for (ConstConfigIterator config (*this); config.next();)\r
{\r
auto& cfg = dynamic_cast<const AndroidBuildConfiguration&> (*config);\r
\r
- mo << "if( JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg.getProductFlavourCMakeIdentifier() << "\" )" << newLine;\r
- mo << " target_compile_options( ${BINARY_NAME} PRIVATE";\r
+ mo << "if( JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg.getProductFlavourCMakeIdentifier() << "\" )" << newLine\r
+ << " target_compile_options( ${BINARY_NAME} PRIVATE";\r
\r
- auto recommendedFlags = cfg.getRecommendedCompilerWarningFlags();\r
+ const auto recommendedFlags = cfg.getRecommendedCompilerWarningFlags();\r
\r
for (auto& recommendedFlagsType : { recommendedFlags.common, recommendedFlags.cpp })\r
for (auto& flag : recommendedFlagsType)\r
mo << " " << flag;\r
\r
- mo << ")" << newLine;\r
- mo << "endif()" << newLine << newLine;\r
+ const auto flags = getConfigCompilerFlags (cfg);\r
+\r
+ if (! flags.isEmpty())\r
+ mo << " " << flags.joinIntoString (" ");\r
+\r
+ mo << " )" << newLine\r
+ << "endif()" << newLine\r
+ << newLine;\r
}\r
\r
auto libraries = getAndroidLibraries();\r
\r
mo << "android {" << newLine;\r
mo << " compileSdkVersion " << static_cast<int> (androidTargetSDK.get()) << newLine;\r
+ mo << " namespace " << project.getBundleIdentifierString().toLowerCase().quoted() << newLine;\r
mo << " externalNativeBuild {" << newLine;\r
mo << " cmake {" << newLine;\r
mo << " path \"CMakeLists.txt\"" << newLine;\r
\r
if (cfg.getArchitectures().isNotEmpty())\r
{\r
- mo << " ndk {" << newLine;\r
- mo << " abiFilters " << toGradleList (StringArray::fromTokens (cfg.getArchitectures(), " ", "")) << newLine;\r
- mo << " }" << newLine;\r
+ mo << " ndk {" << newLine\r
+ << " abiFilters " << toGradleList (StringArray::fromTokens (cfg.getArchitectures(), " ", "")) << newLine\r
+ << " }" << newLine;\r
}\r
\r
- mo << " externalNativeBuild {" << newLine;\r
- mo << " cmake {" << newLine;\r
+ mo << " externalNativeBuild {" << newLine\r
+ << " cmake {" << newLine;\r
\r
if (getProject().getProjectType().isStaticLibrary())\r
mo << " targets \"" << getNativeModuleBinaryName (cfg) << "\"" << newLine;\r
\r
- mo << " arguments "\r
- << "\"-DJUCE_BUILD_CONFIGURATION=" << cfg.getProductFlavourCMakeIdentifier() << "\"";\r
-\r
- mo << ", \"-DCMAKE_CXX_FLAGS_" << (cfg.isDebug() ? "DEBUG" : "RELEASE")\r
- << "=-O" << cfg.getGCCOptimisationFlag();\r
-\r
- mo << "\""\r
- << ", \"-DCMAKE_C_FLAGS_" << (cfg.isDebug() ? "DEBUG" : "RELEASE")\r
- << "=-O" << cfg.getGCCOptimisationFlag()\r
- << "\"" << newLine;\r
-\r
- mo << " }" << newLine;\r
- mo << " }" << newLine << newLine;\r
- mo << " dimension \"default\"" << newLine;\r
- mo << " }" << newLine;\r
+ mo << " cFlags \"-O" << cfg.getGCCOptimisationFlag() << "\"" << newLine\r
+ << " cppFlags \"-O" << cfg.getGCCOptimisationFlag() << "\"" << newLine\r
+ << " arguments \"-DJUCE_BUILD_CONFIGURATION=" << cfg.getProductFlavourCMakeIdentifier() << "\"" << newLine\r
+ << " }" << newLine\r
+ << " }" << newLine\r
+ << newLine\r
+ << " dimension \"default\"" << newLine\r
+ << " }" << newLine;\r
}\r
\r
mo << " }" << newLine;\r
}\r
\r
//==============================================================================\r
- void addCompileUnits (const Project::Item& projectItem, MemoryOutputStream& mo,\r
- Array<build_tools::RelativePath>& excludeFromBuild, Array<std::pair<build_tools::RelativePath, String>>& extraCompilerFlags) const\r
+ void addCompileUnits (const Project::Item& projectItem,\r
+ MemoryOutputStream& mo,\r
+ Array<build_tools::RelativePath>& excludeFromBuild,\r
+ Array<std::pair<build_tools::RelativePath, String>>& extraCompilerFlags) const\r
{\r
if (projectItem.isGroup())\r
{\r
}\r
else\r
{\r
- auto extraFlags = compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get().toString();\r
+ auto extraFlags = getCompilerFlagsForProjectItem (projectItem);\r
\r
if (extraFlags.isNotEmpty())\r
extraCompilerFlags.add ({ file, extraFlags });\r
}\r
}\r
\r
- void addCompileUnits (MemoryOutputStream& mo, Array<build_tools::RelativePath>& excludeFromBuild,\r
+ void addCompileUnits (MemoryOutputStream& mo,\r
+ Array<build_tools::RelativePath>& excludeFromBuild,\r
Array<std::pair<build_tools::RelativePath, String>>& extraCompilerFlags) const\r
{\r
for (int i = 0; i < getAllGroups().size(); ++i)\r
return cFlags;\r
}\r
\r
- StringArray getProjectCompilerFlags() const\r
+ StringArray getConfigCompilerFlags (const BuildConfiguration& config) const\r
{\r
auto cFlags = getAndroidCompilerFlags();\r
- cFlags.addArray (getEscapedFlags (StringArray::fromTokens (getExtraCompilerFlagsString(), true)));\r
+ cFlags.addArray (getEscapedFlags (StringArray::fromTokens (config.getAllCompilerFlagsString(), true)));\r
return cFlags;\r
}\r
\r
setAttributeIfNotPresent (*manifest, "xmlns:android", "http://schemas.android.com/apk/res/android");\r
setAttributeIfNotPresent (*manifest, "android:versionCode", androidVersionCode.get());\r
setAttributeIfNotPresent (*manifest, "android:versionName", project.getVersionString());\r
- setAttributeIfNotPresent (*manifest, "package", project.getBundleIdentifierString().toLowerCase());\r
\r
return manifest;\r
}\r
auto* act = getOrCreateChildWithName (application, "activity");\r
\r
setAttributeIfNotPresent (*act, "android:name", getActivityClassString());\r
- setAttributeIfNotPresent (*act, "android:label", "@string/app_name");\r
\r
if (! act->hasAttribute ("android:configChanges"))\r
act->setAttribute ("android:configChanges", "keyboardHidden|orientation|screenSize");\r
if (config.isDebug())\r
flags.add ("-g");\r
\r
- flags.addTokens (replacePreprocessorTokens (config, getExtraCompilerFlagsString()).trim(),\r
+ flags.addTokens (replacePreprocessorTokens (config, config.getAllCompilerFlagsString()).trim(),\r
" \n", "\"'");\r
\r
if (config.exporter.isLinux())\r
if (config.isLinkTimeOptimisationEnabled())\r
flags.add ("-flto");\r
\r
- flags.addTokens (replacePreprocessorTokens (config, getExtraLinkerFlagsString()).trim(), " \n", "\"'");\r
+ flags.addTokens (replacePreprocessorTokens (config, config.getAllLinkerFlagsString()).trim(), " \n", "\"'");\r
\r
if (config.exporter.isLinux())\r
{\r
\r
if (projectItem.shouldBeCompiled())\r
{\r
- auto extraCompilerFlags = compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get().toString();\r
+ auto extraCompilerFlags = getCompilerFlagsForProjectItem (projectItem);\r
\r
if (extraCompilerFlags.isNotEmpty())\r
{\r
String getWindowsTargetPlatformVersion() const { return targetPlatformVersion.get(); }\r
\r
//==============================================================================\r
- void addToolsetProperty (PropertyListBuilder& props, const char** names, const var* values, int num)\r
+ void addToolsetProperty (PropertyListBuilder& props, std::initializer_list<const char*> valueStrings)\r
{\r
- props.add (new ChoicePropertyComponent (platformToolsetValue, "Platform Toolset",\r
- StringArray (names, num), { values, num }),\r
- "Specifies the version of the platform toolset that will be used when building this project.");\r
+ StringArray names;\r
+ Array<var> values;\r
+\r
+ for (const auto& valueString : valueStrings)\r
+ {\r
+ names.add (valueString);\r
+ values.add (valueString);\r
+ }\r
+\r
+ props.add (new ChoicePropertyComponent (platformToolsetValue, "Platform Toolset", names, values),\r
+ "Specifies the version of the platform toolset that will be used when building this project.\n"\r
+ "In order to use the ClangCL toolset, you must first install the \"C++ Clang Tools for Windows\" "\r
+ "package using the Visual Studio Installer.");\r
}\r
\r
void create (const OwnedArray<LibraryModule>&) const override\r
multiProcessorCompilationValue (config, Ids::multiProcessorCompilation, getUndoManager(), true),\r
intermediatesPathValue (config, Ids::intermediatesPath, getUndoManager()),\r
characterSetValue (config, Ids::characterSet, getUndoManager()),\r
- architectureTypeValue (config, Ids::winArchitecture, getUndoManager(), get64BitArchName()),\r
+ architectureTypeValue (config, Ids::winArchitecture, getUndoManager(), getIntel64BitArchName()),\r
fastMathValue (config, Ids::fastMath, getUndoManager()),\r
debugInformationFormatValue (config, Ids::debugInformationFormat, getUndoManager(), isDebug() ? "ProgramDatabase" : "None"),\r
pluginBinaryCopyStepValue (config, Ids::enablePluginBinaryCopyStep, getUndoManager(), false),\r
String getUnityPluginBinaryLocationString() const { return unityPluginBinaryLocation.get(); }\r
String getIntermediatesPathString() const { return intermediatesPathValue.get(); }\r
String getCharacterSetString() const { return characterSetValue.get(); }\r
- String get64BitArchName() const { return "x64"; }\r
- String get32BitArchName() const { return "Win32"; }\r
+ String getIntel64BitArchName() const { return "x64"; }\r
+ String getIntel32BitArchName() const { return "Win32"; }\r
+ String getArm64BitArchName() const { return "ARM64"; }\r
+ String getArm32BitArchName() const { return "ARM"; }\r
String getArchitectureString() const { return architectureTypeValue.get(); }\r
String getDebugInformationFormatString() const { return debugInformationFormatValue.get(); }\r
\r
bool shouldLinkIncremental() const { return enableIncrementalLinkingValue.get(); }\r
bool isUsingRuntimeLibDLL() const { return useRuntimeLibDLLValue.get(); }\r
bool shouldUseMultiProcessorCompilation() const { return multiProcessorCompilationValue.get(); }\r
- bool is64Bit() const { return getArchitectureString() == get64BitArchName(); }\r
bool isFastMathEnabled() const { return fastMathValue.get(); }\r
bool isPluginBinaryCopyStepEnabled() const { return pluginBinaryCopyStepValue.get(); }\r
\r
//==============================================================================\r
String createMSVCConfigName() const\r
{\r
- return getName() + "|" + (is64Bit() ? "x64" : "Win32");\r
+ return getName() + "|" + getArchitectureString();\r
}\r
\r
String getOutputFilename (const String& suffix,\r
addVisualStudioPluginInstallPathProperties (props);\r
\r
props.add (new ChoicePropertyComponent (architectureTypeValue, "Architecture",\r
- { get32BitArchName(), get64BitArchName() },\r
- { get32BitArchName(), get64BitArchName() }),\r
- "Whether to use a 32-bit or 64-bit architecture.");\r
-\r
+ { getIntel32BitArchName(), getIntel64BitArchName(), getArm32BitArchName(), getArm64BitArchName() },\r
+ { getIntel32BitArchName(), getIntel64BitArchName(), getArm32BitArchName(), getArm64BitArchName() }),\r
+ "Which Windows architecture to use.");\r
\r
props.add (new ChoicePropertyComponentWithEnablement (debugInformationFormatValue,\r
isDebug() ? isDebugValue : generateDebugSymbolsValue,\r
\r
void setPluginBinaryCopyLocationDefaults()\r
{\r
- vstBinaryLocation.setDefault ((is64Bit() ? "%ProgramW6432%" : "%programfiles(x86)%") + String ("\\Steinberg\\Vstplugins"));\r
+ const auto [programsFolderPath, commonsFolderPath] = [&]() -> std::tuple<String, String>\r
+ {\r
+ static const std::map<String, std::tuple<String, String>> options\r
+ {\r
+ { "Win32", { "%programfiles(x86)%", "%CommonProgramFiles(x86)%" } },\r
+ { "x64", { "%ProgramW6432%", "%CommonProgramW6432%" } },\r
+ { "ARM", { "%programfiles(arm)%", "%CommonProgramFiles(arm)%" } },\r
+ { "ARM64", { "%ProgramW6432%", "%CommonProgramW6432%" } }\r
+ };\r
+\r
+ if (const auto iter = options.find (getArchitectureString()); iter != options.cend())\r
+ return iter->second;\r
\r
- auto prefix = is64Bit() ? "%CommonProgramW6432%"\r
- : "%CommonProgramFiles(x86)%";\r
+ jassertfalse;\r
+ return { "%programfiles%", "%CommonProgramFiles%" };\r
+ }();\r
\r
- vst3BinaryLocation.setDefault (prefix + String ("\\VST3"));\r
- aaxBinaryLocation.setDefault (prefix + String ("\\Avid\\Audio\\Plug-Ins"));\r
+ vstBinaryLocation.setDefault (programsFolderPath + String ("\\Steinberg\\Vstplugins"));\r
+ vst3BinaryLocation.setDefault (commonsFolderPath + String ("\\VST3"));\r
+ aaxBinaryLocation.setDefault (commonsFolderPath + String ("\\Avid\\Audio\\Plug-Ins"));\r
lv2BinaryLocation.setDefault ("%APPDATA%\\LV2");\r
}\r
\r
auto* e = configsGroup->createNewChildElement ("ProjectConfiguration");\r
e->setAttribute ("Include", config.createMSVCConfigName());\r
e->createNewChildElement ("Configuration")->addTextElement (config.getName());\r
- e->createNewChildElement ("Platform")->addTextElement (config.is64Bit() ? config.get64BitArchName()\r
- : config.get32BitArchName());\r
+ e->createNewChildElement ("Platform")->addTextElement (config.getArchitectureString());\r
}\r
}\r
\r
if (config.isFastMathEnabled())\r
cl->createNewChildElement ("FloatingPointModel")->addTextElement ("Fast");\r
\r
- auto extraFlags = getOwner().replacePreprocessorTokens (config, getOwner().getExtraCompilerFlagsString()).trim();\r
+ auto extraFlags = getOwner().replacePreprocessorTokens (config, config.getAllCompilerFlagsString()).trim();\r
+\r
if (extraFlags.isNotEmpty())\r
cl->createNewChildElement ("AdditionalOptions")->addTextElement (extraFlags + " %(AdditionalOptions)");\r
\r
link->createNewChildElement ("ProgramDatabaseFile")->addTextElement (pdbFilename);\r
link->createNewChildElement ("SubSystem")->addTextElement (type == ConsoleApp || type == LV2TurtleProgram ? "Console" : "Windows");\r
\r
- if (! config.is64Bit())\r
+ if (config.getArchitectureString() == "Win32")\r
link->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");\r
\r
if (isUsingEditAndContinue)\r
if (additionalDependencies.isNotEmpty())\r
link->createNewChildElement ("AdditionalDependencies")->addTextElement (additionalDependencies);\r
\r
- auto extraLinkerOptions = getOwner().getExtraLinkerFlagsString();\r
+ auto extraLinkerOptions = config.getAllLinkerFlagsString();\r
if (extraLinkerOptions.isNotEmpty())\r
link->createNewChildElement ("AdditionalOptions")->addTextElement (getOwner().replacePreprocessorTokens (config, extraLinkerOptions).trim()\r
+ " %(AdditionalOptions)");\r
build_tools::RelativePath::buildTargetFolder).toWindowsStyle());\r
}\r
\r
- if (getTargetFileType() == staticLibrary && ! config.is64Bit())\r
+ if (getTargetFileType() == staticLibrary && config.getArchitectureString() == "Win32")\r
{\r
auto* lib = group->createNewChildElement ("Lib");\r
lib->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");\r
\r
if (projectItem.shouldBeCompiled())\r
{\r
- auto extraCompilerFlags = owner.compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get().toString();\r
+ auto extraCompilerFlags = getOwner().getCompilerFlagsForProjectItem (projectItem);\r
\r
if (shouldAddBigobjFlag (path))\r
{\r
auto outputFilename = config.getOutputFilename (".aaxplugin", true, type);\r
auto bundleDir = getOwner().getOutDirFile (config, outputFilename);\r
auto bundleContents = bundleDir + "\\Contents";\r
- auto archDir = bundleContents + String ("\\") + (config.is64Bit() ? "x64" : "Win32");\r
+ auto archDir = bundleContents + String ("\\") + config.getArchitectureString();\r
auto executablePath = archDir + String ("\\") + outputFilename;\r
\r
auto pkgScript = String ("copy /Y ") + getOutputFilePath (config).quoted() + String (" ") + executablePath.quoted() + String ("\r\ncall ")\r
\r
auto bundleDir = getOwner().getOutDirFile (config, config.getOutputFilename (".aaxplugin", false, type));\r
auto bundleContents = bundleDir + "\\Contents";\r
- auto archDir = bundleContents + String ("\\") + (config.is64Bit() ? "x64" : "Win32");\r
+ auto archDir = bundleContents + String ("\\") + config.getArchitectureString();\r
\r
for (auto& folder : StringArray { bundleDir, bundleContents, archDir })\r
script += String ("if not exist \"") + folder + String ("\" mkdir \"") + folder + String ("\"\r\n");\r
\r
void createExporterProperties (PropertyListBuilder& props) override\r
{\r
- static const char* toolsetNames[] = { "v140", "v140_xp", "v141", "v141_xp" };\r
- const var toolsets[] = { "v140", "v140_xp", "v141", "v141_xp" };\r
- addToolsetProperty (props, toolsetNames, toolsets, numElementsInArray (toolsets));\r
-\r
+ addToolsetProperty (props, { "v140", "v140_xp", "v141", "v141_xp" });\r
MSVCProjectExporterBase::createExporterProperties (props);\r
}\r
\r
\r
void createExporterProperties (PropertyListBuilder& props) override\r
{\r
- static const char* toolsetNames[] = { "v140", "v140_xp", "v141", "v141_xp", "v142" };\r
- const var toolsets[] = { "v140", "v140_xp", "v141", "v141_xp", "v142" };\r
- addToolsetProperty (props, toolsetNames, toolsets, numElementsInArray (toolsets));\r
-\r
+ addToolsetProperty (props, { "v140", "v140_xp", "v141", "v141_xp", "v142", "ClangCL" });\r
MSVCProjectExporterBase::createExporterProperties (props);\r
}\r
\r
\r
void createExporterProperties (PropertyListBuilder& props) override\r
{\r
- static const char* toolsetNames[] = { "v140", "v140_xp", "v141", "v141_xp", "v142", "v143" };\r
- const var toolsets[] = { "v140", "v140_xp", "v141", "v141_xp", "v142", "v143" };\r
- addToolsetProperty (props, toolsetNames, toolsets, numElementsInArray (toolsets));\r
-\r
+ addToolsetProperty (props, { "v140", "v140_xp", "v141", "v141_xp", "v142", "v143", "ClangCL" });\r
MSVCProjectExporterBase::createExporterProperties (props);\r
}\r
\r
\r
s.add ("JUCE_TARGET_" + getTargetVarName() + String (" := ") + escapeQuotesAndSpaces (targetName));\r
\r
+ if (type == LV2PlugIn)\r
+ s.add ("JUCE_LV2_FULL_PATH := $(JUCE_OUTDIR)/$(JUCE_TARGET_LV2_PLUGIN)");\r
+\r
if (config.isPluginBinaryCopyStepEnabled()\r
&& (type == VST3PlugIn || type == VSTPlugIn || type == UnityPlugIn || type == LV2PlugIn))\r
{\r
else if (type == LV2PlugIn)\r
{\r
s.add ("JUCE_LV2DESTDIR := " + config.getLV2BinaryLocationString());\r
- s.add ("JUCE_LV2_FULL_PATH := $(JUCE_OUTDIR)/$(JUCE_TARGET_LV2_PLUGIN)");\r
s.add (copyCmd + "$(JUCE_LV2DIR) $(JUCE_LV2DESTDIR)");\r
}\r
}\r
return String (getName()).toUpperCase().replaceCharacter (L' ', L'_');\r
}\r
\r
- void writeObjects (OutputStream& out, const Array<std::pair<File, String>>& filesToCompile) const\r
+ void writeObjects (OutputStream& out, const std::vector<std::pair<build_tools::RelativePath, String>>& filesToCompile) const\r
{\r
out << "OBJECTS_" + getTargetVarName() + String (" := \\") << newLine;\r
\r
for (auto& f : filesToCompile)\r
- out << " $(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor ({ f.first, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder }))\r
+ out << " $(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor (f.first))\r
<< " \\" << newLine;\r
\r
out << newLine;\r
}\r
\r
- void addFiles (OutputStream& out, const Array<std::pair<File, String>>& filesToCompile)\r
+ void addFiles (OutputStream& out, const std::vector<std::pair<build_tools::RelativePath, String>>& filesToCompile)\r
{\r
auto cppflagsVarName = "JUCE_CPPFLAGS_" + getTargetVarName();\r
auto cflagsVarName = "JUCE_CFLAGS_" + getTargetVarName();\r
\r
- for (auto& f : filesToCompile)\r
+ for (auto& [path, flags] : filesToCompile)\r
{\r
- build_tools::RelativePath relativePath (f.first, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder);\r
-\r
- out << "$(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor (relativePath)) << ": " << escapeQuotesAndSpaces (relativePath.toUnixStyle()) << newLine\r
- << "\t-$(V_AT)mkdir -p $(JUCE_OBJDIR)" << newLine\r
- << "\t@echo \"Compiling " << relativePath.getFileName() << "\"" << newLine\r
- << (relativePath.hasFileExtension ("c;s;S") ? "\t$(V_AT)$(CC) $(JUCE_CFLAGS) " : "\t$(V_AT)$(CXX) $(JUCE_CXXFLAGS) ")\r
+ out << "$(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor (path)) << ": " << escapeQuotesAndSpaces (path.toUnixStyle()) << newLine\r
+ << "\t-$(V_AT)mkdir -p $(JUCE_OBJDIR)" << newLine\r
+ << "\t@echo \"Compiling " << path.getFileName() << "\"" << newLine\r
+ << (path.hasFileExtension ("c;s;S") ? "\t$(V_AT)$(CC) $(JUCE_CFLAGS) " : "\t$(V_AT)$(CXX) $(JUCE_CXXFLAGS) ")\r
<< "$(" << cppflagsVarName << ") $(" << cflagsVarName << ")"\r
- << (f.second.isNotEmpty() ? " $(" + owner.getCompilerFlagSchemeVariableName (f.second) + ")" : "") << " -o \"$@\" -c \"$<\"" << newLine\r
+ << (flags.isNotEmpty() ? " $(" + owner.getCompilerFlagSchemeVariableName (flags) + ")" : "") << " -o \"$@\" -c \"$<\"" << newLine\r
<< newLine;\r
}\r
}\r
\r
if (type == VST3PlugIn)\r
{\r
- out << "\t-$(V_AT)mkdir -p $(JUCE_VST3DESTDIR)" << newLine\r
- << "\t-$(V_AT)cp -R $(JUCE_COPYCMD_VST3)" << newLine;\r
+ out << "\t-$(V_AT)[ ! \"$(JUCE_VST3DESTDIR)\" ] || (mkdir -p $(JUCE_VST3DESTDIR) && cp -R $(JUCE_COPYCMD_VST3))" << newLine;\r
}\r
else if (type == VSTPlugIn)\r
{\r
- out << "\t-$(V_AT)mkdir -p $(JUCE_VSTDESTDIR)" << newLine\r
- << "\t-$(V_AT)cp -R $(JUCE_COPYCMD_VST)" << newLine;\r
+ out << "\t-$(V_AT)[ ! \"$(JUCE_VSTDESTDIR)\" ] || (mkdir -p $(JUCE_VSTDESTDIR) && cp -R $(JUCE_COPYCMD_VST))" << newLine;\r
}\r
else if (type == UnityPlugIn)\r
{\r
build_tools::RelativePath::projectFolder);\r
\r
out << "\t-$(V_AT)cp " + scriptPath.toUnixStyle() + " $(JUCE_OUTDIR)/$(JUCE_UNITYDIR)" << newLine\r
- << "\t-$(V_AT)mkdir -p $(JUCE_UNITYDESTDIR)" << newLine\r
- << "\t-$(V_AT)cp -R $(JUCE_COPYCMD_UNITY_PLUGIN)" << newLine;\r
+ << "\t-$(V_AT)[ ! \"$(JUCE_UNITYDESTDIR)\" ] || (mkdir -p $(JUCE_UNITYDESTDIR) && cp -R $(JUCE_COPYCMD_UNITY_PLUGIN))" << newLine;\r
}\r
else if (type == LV2PlugIn)\r
{\r
- out << "\t$(V_AT) $(JUCE_OUTDIR)/$(JUCE_TARGET_LV2_MANIFEST_HELPER) "\r
- "$(abspath $(JUCE_LV2_FULL_PATH))" << newLine\r
- << "\t-$(V_AT)mkdir -p $(JUCE_LV2DESTDIR)" << newLine\r
- << "\t-$(V_AT)cp -R $(JUCE_COPYCMD_LV2_PLUGIN)" << newLine;\r
+ out << "\t$(V_AT) $(JUCE_OUTDIR)/$(JUCE_TARGET_LV2_MANIFEST_HELPER) $(abspath $(JUCE_LV2_FULL_PATH))" << newLine\r
+ << "\t-$(V_AT)[ ! \"$(JUCE_LV2DESTDIR)\" ] || (mkdir -p $(JUCE_LV2DESTDIR) && cp -R $(JUCE_COPYCMD_LV2_PLUGIN))" << newLine;\r
}\r
\r
out << newLine;\r
for (auto& recommended : config.getRecommendedCompilerWarningFlags().common)\r
result.add (recommended);\r
\r
- auto extra = replacePreprocessorTokens (config, getExtraCompilerFlagsString()).trim();\r
+ auto extra = replacePreprocessorTokens (config, config.getAllCompilerFlagsString()).trim();\r
\r
if (extra.isNotEmpty())\r
result.add (extra);\r
if (config.isLinkTimeOptimisationEnabled())\r
result.add ("-flto");\r
\r
- auto extraFlags = getExtraLinkerFlagsString().trim();\r
+ const auto extraFlags = config.getAllLinkerFlagsString().trim();\r
\r
if (extraFlags.isNotEmpty())\r
result.add (replacePreprocessorTokens (config, extraFlags));\r
\r
static String getCompilerFlagSchemeVariableName (const String& schemeName) { return "JUCE_COMPILERFLAGSCHEME_" + schemeName; }\r
\r
- void findAllFilesToCompile (const Project::Item& projectItem, Array<std::pair<File, String>>& results) const\r
+ std::vector<std::pair<File, String>> findAllFilesToCompile (const Project::Item& projectItem) const\r
{\r
+ std::vector<std::pair<File, String>> results;\r
+\r
if (projectItem.isGroup())\r
{\r
for (int i = 0; i < projectItem.getNumChildren(); ++i)\r
- findAllFilesToCompile (projectItem.getChild (i), results);\r
+ {\r
+ auto inner = findAllFilesToCompile (projectItem.getChild (i));\r
+ results.insert (results.end(),\r
+ std::make_move_iterator (inner.cbegin()),\r
+ std::make_move_iterator (inner.cend()));\r
+ }\r
}\r
else\r
{\r
if (shouldFileBeCompiledByDefault (f))\r
{\r
auto scheme = projectItem.getCompilerFlagSchemeString();\r
- auto flags = compilerFlagSchemesMap[scheme].get().toString();\r
+ auto flags = getCompilerFlagsForProjectItem (projectItem);\r
\r
if (scheme.isNotEmpty() && flags.isNotEmpty())\r
- results.add ({ f, scheme });\r
+ results.emplace_back (f, scheme);\r
else\r
- results.add ({ f, {} });\r
+ results.emplace_back (f, String{});\r
}\r
}\r
}\r
+\r
+ return results;\r
}\r
\r
- void writeCompilerFlagSchemes (OutputStream& out, const Array<std::pair<File, String>>& filesToCompile) const\r
+ void writeCompilerFlagSchemes (OutputStream& out, const std::vector<std::pair<File, String>>& filesToCompile) const\r
{\r
StringArray schemesToWrite;\r
\r
for (ConstConfigIterator config (*this); config.next();)\r
writeConfig (out, dynamic_cast<const MakeBuildConfiguration&> (*config));\r
\r
- Array<std::pair<File, String>> filesToCompile;\r
+ std::vector<std::pair<File, String>> filesToCompile;\r
\r
for (int i = 0; i < getAllGroups().size(); ++i)\r
- findAllFilesToCompile (getAllGroups().getReference (i), filesToCompile);\r
+ {\r
+ auto group = findAllFilesToCompile (getAllGroups().getReference (i));\r
+ filesToCompile.insert (filesToCompile.end(),\r
+ std::make_move_iterator (group.cbegin()),\r
+ std::make_move_iterator (group.cend()));\r
+ }\r
\r
writeCompilerFlagSchemes (out, filesToCompile);\r
\r
- auto getFilesForTarget = [this] (const Array<std::pair<File, String>>& files,\r
- MakefileTarget* target,\r
- const Project& p) -> Array<std::pair<File, String>>\r
+ const auto getFilesForTarget = [this] (const std::vector<std::pair<File, String>>& files,\r
+ MakefileTarget* target,\r
+ const Project& p)\r
{\r
- Array<std::pair<File, String>> targetFiles;\r
+ std::vector<std::pair<build_tools::RelativePath, String>> targetFiles;\r
\r
auto targetType = (p.isAudioPluginProject() ? target->type : MakefileTarget::SharedCodeTarget);\r
\r
- for (auto& f : files)\r
- if (p.getTargetTypeFromFilePath (f.first, true) == targetType)\r
- targetFiles.add (f);\r
+ for (auto& [path, flags] : files)\r
+ {\r
+ if (p.getTargetTypeFromFilePath (path, true) == targetType)\r
+ {\r
+ targetFiles.emplace_back (build_tools::RelativePath { path,\r
+ getTargetFolder(),\r
+ build_tools::RelativePath::buildTargetFolder },\r
+ flags);\r
+ }\r
+ }\r
\r
if (targetType == MakefileTarget::LV2TurtleProgram)\r
- targetFiles.add ({ project.resolveFilename (getLV2TurtleDumpProgramSource().toUnixStyle()), {} });\r
+ {\r
+ targetFiles.emplace_back (getLV2TurtleDumpProgramSource().rebased (projectFolder,\r
+ getTargetFolder(),\r
+ build_tools::RelativePath::buildTargetFolder),\r
+ String{});\r
+ }\r
\r
return targetFiles;\r
};\r
"added separated by a semicolon. The App Groups Capability setting must be enabled for this setting to have any effect.");\r
\r
props.add (new ChoicePropertyComponent (keepCustomXcodeSchemesValue, "Keep Custom Xcode Schemes"),\r
- "Enable this to keep any Xcode schemes you have created for debugging or running, e.g. to launch a plug-in in"\r
+ "Enable this to keep any Xcode schemes you have created for debugging or running, e.g. to launch a plug-in in "\r
"various hosts. If disabled, all schemes are replaced by a default set.");\r
\r
props.add (new ChoicePropertyComponent (useHeaderMapValue, "USE_HEADERMAP"),\r
: BuildConfiguration (p, t, e),\r
iOS (isIOS),\r
macOSBaseSDK (config, Ids::macOSBaseSDK, getUndoManager()),\r
- macOSDeploymentTarget (config, Ids::macOSDeploymentTarget, getUndoManager(), "10.11"),\r
+ macOSDeploymentTarget (config, Ids::macOSDeploymentTarget, getUndoManager(), "10.13"),\r
macOSArchitecture (config, Ids::osxArchitecture, getUndoManager(), macOSArch_Default),\r
iosBaseSDK (config, Ids::iosBaseSDK, getUndoManager()),\r
- iosDeploymentTarget (config, Ids::iosDeploymentTarget, getUndoManager(), "9.3"),\r
+ iosDeploymentTarget (config, Ids::iosDeploymentTarget, getUndoManager(), "11.0"),\r
customXcodeFlags (config, Ids::customXcodeFlags, getUndoManager()),\r
plistPreprocessorDefinitions (config, Ids::plistPreprocessorDefinitions, getUndoManager()),\r
codeSignIdentity (config, Ids::codeSigningIdentity, getUndoManager()),\r
"The version of the macOS SDK to link against." + sdkInfoString + "10.11.");\r
\r
props.add (new TextPropertyComponent (macOSDeploymentTarget, "macOS Deployment Target", 8, false),\r
- "The minimum version of macOS to target." + sdkInfoString + "10.7.");\r
+ "The minimum version of macOS to target." + sdkInfoString + "10.9.");\r
\r
props.add (new ChoicePropertyComponent (macOSArchitecture, "macOS Architecture",\r
{ "Native architecture of build machine", "Standard 32-bit", "Standard 32/64-bit", "Standard 64-bit" },\r
struct XcodeTarget : build_tools::ProjectType::Target\r
{\r
//==============================================================================\r
- XcodeTarget (build_tools::ProjectType::Target::Type targetType, const XcodeProjectExporter& exporter)\r
+ XcodeTarget (Type targetType, const XcodeProjectExporter& exporter)\r
: Target (targetType),\r
owner (exporter)\r
{\r
for (const auto& xcodeFlags : { XcodeWarningFlags { recommendedWarnings.common, "OTHER_CFLAGS" },\r
XcodeWarningFlags { recommendedWarnings.cpp, "OTHER_CPLUSPLUSFLAGS" } })\r
{\r
- auto flags = (xcodeFlags.flags.joinIntoString (" ")\r
- + " " + owner.getExtraCompilerFlagsString()).trim();\r
- flags = owner.replacePreprocessorTokens (config, flags);\r
+ const auto flags = owner.replacePreprocessorTokens (config,\r
+ (xcodeFlags.flags.joinIntoString (" ")\r
+ + " "\r
+ + config.getAllCompilerFlagsString()).trim());\r
\r
if (flags.isNotEmpty())\r
s.set (xcodeFlags.variable, flags.quoted());\r
s.set ("GCC_VERSION", gccVersion);\r
s.set ("CLANG_LINK_OBJC_RUNTIME", "NO");\r
\r
- auto codeSigningIdentity = owner.getCodeSigningIdentity (config);\r
- s.set (owner.iOS ? "\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\"" : "CODE_SIGN_IDENTITY",\r
- codeSigningIdentity.quoted());\r
+ owner.addCodeSigningIdentity (config, s);\r
\r
- if (codeSigningIdentity.isNotEmpty())\r
+ if (owner.getCodeSigningIdentity (config).isNotEmpty())\r
{\r
s.set ("PROVISIONING_PROFILE_SPECIFIER", "\"\"");\r
\r
s.set ("CODE_SIGN_ENTITLEMENTS", getEntitlementsFilename().quoted());\r
\r
{\r
- auto cppStandard = owner.project.getCppStandardString();\r
+ const auto cppStandard = [&]() -> String\r
+ {\r
+ if (owner.project.getCppStandardString() == "latest")\r
+ return owner.project.getLatestNumberedCppStandardString();\r
\r
- if (cppStandard == "latest")\r
- cppStandard = owner.project.getLatestNumberedCppStandardString();\r
+ return owner.project.getCppStandardString();\r
+ }();\r
\r
s.set ("CLANG_CXX_LANGUAGE_STANDARD", (String (owner.shouldUseGNUExtensions() ? "gnu++"\r
: "c++") + cppStandard).quoted());\r
flags.add (getLinkerFlagForLib (l));\r
}\r
\r
- flags.add (owner.replacePreprocessorTokens (config, owner.getExtraLinkerFlagsString()));\r
+ flags.add (owner.replacePreprocessorTokens (config, config.getAllLinkerFlagsString()));\r
flags = getCleanedStringArray (flags);\r
}\r
\r
StringArray paths (owner.extraSearchPaths);\r
paths.addArray (config.getHeaderSearchPaths());\r
\r
- if (owner.project.getEnabledModules().isModuleEnabled ("juce_audio_plugin_client"))\r
+ constexpr auto audioPluginClient = "juce_audio_plugin_client";\r
+\r
+ if (owner.project.getEnabledModules().isModuleEnabled (audioPluginClient))\r
{\r
- // Needed to compile .r files\r
- paths.add (owner.getModuleFolderRelativeToProject ("juce_audio_plugin_client")\r
- .rebased (owner.projectFolder, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder)\r
+ paths.add (owner.getModuleFolderRelativeToProject (audioPluginClient)\r
+ .getChildFile ("AU")\r
+ .rebased (owner.projectFolder,\r
+ owner.getTargetFolder(),\r
+ build_tools::RelativePath::buildTargetFolder)\r
.toUnixStyle());\r
}\r
\r
\r
if (target->type == XcodeTarget::LV2PlugIn)\r
{\r
- auto script = "set -e\n\"$CONFIGURATION_BUILD_DIR/../"\r
+ // When building LV2 plugins on Arm macs, we need to load and run the plugin bundle\r
+ // during a post-build step in order to generate the plugin's supporting files. Arm\r
+ // macs will only load shared libraries if they are signed, but Xcode runs its\r
+ // signing step after any post-build scripts. As a workaround, we check whether the\r
+ // plugin is signed and generate an adhoc certificate if necessary, before running\r
+ // the manifest-generator.\r
+ auto script = "set -e\n"\r
+ "xcrun codesign --verify \"$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME\" "\r
+ "|| xcrun codesign -s - \"$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME\"\n"\r
+ "\"$CONFIGURATION_BUILD_DIR/../"\r
+ Project::getLV2FileWriterName()\r
+ "\" \"$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME\"\n";\r
\r
return config.getCodeSignIdentityString();\r
}\r
\r
+ void addCodeSigningIdentity (const XcodeBuildConfiguration& config, StringPairArray& result) const\r
+ {\r
+ if (const auto codeSigningIdentity = getCodeSigningIdentity (config); codeSigningIdentity.isNotEmpty())\r
+ result.set (iOS ? "\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\"" : "CODE_SIGN_IDENTITY",\r
+ codeSigningIdentity.quoted());\r
+ }\r
+\r
StringPairArray getProjectSettings (const XcodeBuildConfiguration& config) const\r
{\r
StringPairArray s;\r
s.set ("ONLY_ACTIVE_ARCH", "YES");\r
}\r
\r
- s.set (iOS ? "\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\"" : "CODE_SIGN_IDENTITY",\r
- getCodeSigningIdentity (config).quoted());\r
+ addCodeSigningIdentity (config, s);\r
\r
if (iOS)\r
{\r
xcodeTarget = getTargetOfType (project.getTargetTypeFromFilePath (projectItem.getFile(), false));\r
\r
return addFile (FileOptions().withRelativePath (path)\r
- .withCompilerFlags (compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get())\r
+ .withCompilerFlags (getCompilerFlagsForProjectItem (projectItem))\r
.withCompilationEnabled (projectItem.shouldBeCompiled())\r
.withAddToBinaryResourcesEnabled (projectItem.shouldBeAddedToBinaryResources())\r
.withAddToXcodeResourcesEnabled (projectItem.shouldBeAddedToXcodeResources())\r
sourceString);\r
}\r
\r
+String ProjectExporter::getCompilerFlagsForProjectItem (const Project::Item& projectItem) const\r
+{\r
+ if (auto buildConfigurationForFile = getBuildConfigurationWithName (projectItem.getCompilerFlagSchemeString()))\r
+ return buildConfigurationForFile->getAllCompilerFlagsString();\r
+\r
+ return {};\r
+}\r
+\r
void ProjectExporter::copyMainGroupFromProject()\r
{\r
jassert (itemGroups.size() == 0);\r
return createBuildConfig (getConfigurations().getChild (index));\r
}\r
\r
-bool ProjectExporter::hasConfigurationNamed (const String& nameToFind) const\r
+std::optional<ValueTree> ProjectExporter::getConfigurationWithName (const String& nameToFind) const\r
{\r
auto configs = getConfigurations();\r
for (int i = configs.getNumChildren(); --i >= 0;)\r
- if (configs.getChild(i) [Ids::name].toString() == nameToFind)\r
- return true;\r
+ {\r
+ auto config = configs.getChild (i);\r
\r
- return false;\r
+ if (config[Ids::name].toString() == nameToFind)\r
+ return config;\r
+ }\r
+\r
+ return {};\r
+}\r
+\r
+ProjectExporter::BuildConfiguration::Ptr ProjectExporter::getBuildConfigurationWithName (const String& nameToFind) const\r
+{\r
+ if (auto config = getConfigurationWithName (nameToFind))\r
+ return createBuildConfig (*config);\r
+\r
+ return nullptr;\r
}\r
\r
String ProjectExporter::getUniqueConfigName (String nm) const\r
nameRoot = nameRoot.trim();\r
\r
int suffix = 2;\r
- while (hasConfigurationNamed (name))\r
+ while (getConfigurationWithName (name).has_value())\r
nm = nameRoot + " " + String (suffix++);\r
\r
return nm;\r
librarySearchPathValue (config, Ids::libraryPath, getUndoManager()),\r
userNotesValue (config, Ids::userNotes, getUndoManager()),\r
usePrecompiledHeaderFileValue (config, Ids::usePrecompiledHeaderFile, getUndoManager(), false),\r
- precompiledHeaderFileValue (config, Ids::precompiledHeaderFile, getUndoManager())\r
+ precompiledHeaderFileValue (config, Ids::precompiledHeaderFile, getUndoManager()),\r
+ configCompilerFlagsValue (config, Ids::extraCompilerFlags, getUndoManager()),\r
+ configLinkerFlagsValue (config, Ids::extraLinkerFlags, getUndoManager())\r
{\r
auto& llvmFlags = recommendedCompilerWarningFlags[CompilerNames::llvm] = BuildConfiguration::CompilerWarningFlags::getRecommendedForGCCAndLLVM();\r
- llvmFlags.common.addArray ({\r
- "-Wshorten-64-to-32", "-Wconversion", "-Wint-conversion",\r
- "-Wconditional-uninitialized", "-Wconstant-conversion", "-Wbool-conversion",\r
- "-Wextra-semi", "-Wshift-sign-overflow",\r
- "-Wshadow-all", "-Wnullable-to-nonnull-conversion",\r
- "-Wmissing-prototypes"\r
- });\r
- llvmFlags.cpp.addArray ({\r
- "-Wunused-private-field", "-Winconsistent-missing-destructor-override"\r
- });\r
- llvmFlags.objc.addArray ({\r
- "-Wunguarded-availability", "-Wunguarded-availability-new"\r
- });\r
+ llvmFlags.common.addArray ({ "-Wshorten-64-to-32", "-Wconversion", "-Wint-conversion",\r
+ "-Wconditional-uninitialized", "-Wconstant-conversion", "-Wbool-conversion",\r
+ "-Wextra-semi", "-Wshift-sign-overflow",\r
+ "-Wshadow-all", "-Wnullable-to-nonnull-conversion",\r
+ "-Wmissing-prototypes" });\r
+ llvmFlags.cpp.addArray ({ "-Wunused-private-field", "-Winconsistent-missing-destructor-override" });\r
+ llvmFlags.objc.addArray ({ "-Wunguarded-availability", "-Wunguarded-availability-new" });\r
\r
auto& gccFlags = recommendedCompilerWarningFlags[CompilerNames::gcc] = BuildConfiguration::CompilerWarningFlags::getRecommendedForGCCAndLLVM();\r
- gccFlags.common.addArray ({\r
- "-Wextra", "-Wsign-compare", "-Wno-implicit-fallthrough", "-Wno-maybe-uninitialized",\r
- "-Wredundant-decls", "-Wno-strict-overflow",\r
- "-Wshadow"\r
- });\r
-}\r
-\r
-ProjectExporter::BuildConfiguration::~BuildConfiguration()\r
-{\r
+ gccFlags.common.addArray ({ "-Wextra", "-Wsign-compare", "-Wno-implicit-fallthrough", "-Wno-maybe-uninitialized",\r
+ "-Wredundant-decls", "-Wno-strict-overflow", "-Wshadow" });\r
}\r
\r
String ProjectExporter::BuildConfiguration::getGCCOptimisationFlag() const\r
"Extra preprocessor definitions. Use the form \"NAME1=value NAME2=value\", using whitespace, commas, or "\r
"new-lines to separate the items - to include a space or comma in a definition, precede it with a backslash.");\r
\r
+ props.add (new TextPropertyComponent (configCompilerFlagsValue, "Configuration-specific Compiler Flags", 8192, true),\r
+ "Compiler flags that are only to be used in this configuration.");\r
+\r
+ props.add (new TextPropertyComponent (configLinkerFlagsValue, "Configuration-specific Linker Flags", 8192, true),\r
+ "Linker flags that are only to be used in this configuration.");\r
+\r
props.add (new ChoicePropertyComponent (linkTimeOptimisationValue, "Link-Time Optimisation"),\r
"Enable this to perform link-time code optimisation. This is recommended for release builds.");\r
\r
{\r
public:\r
ProjectExporter (Project&, const ValueTree& settings);\r
- virtual ~ProjectExporter() override = default;\r
\r
//==============================================================================\r
struct ExporterTypeInfo\r
Value getTargetLocationValue() { return targetLocationValue.getPropertyAsValue(); }\r
String getTargetLocationString() const { return targetLocationValue.get(); }\r
\r
- String getExtraCompilerFlagsString() const { return extraCompilerFlagsValue.get().toString().replaceCharacters ("\r\n", " "); }\r
- String getExtraLinkerFlagsString() const { return extraLinkerFlagsValue.get().toString().replaceCharacters ("\r\n", " "); }\r
-\r
StringArray getExternalLibrariesStringArray() const { return getSearchPathsFromString (externalLibrariesValue.get().toString()); }\r
String getExternalLibrariesString() const { return getExternalLibrariesStringArray().joinIntoString (";"); }\r
\r
{\r
public:\r
BuildConfiguration (Project& project, const ValueTree& configNode, const ProjectExporter&);\r
- ~BuildConfiguration();\r
\r
using Ptr = ReferenceCountedObjectPtr<BuildConfiguration>;\r
\r
bool shouldUsePrecompiledHeaderFile() const { return usePrecompiledHeaderFileValue.get(); }\r
String getPrecompiledHeaderFileContent() const;\r
\r
+ String getAllCompilerFlagsString() const { return (exporter.extraCompilerFlagsValue.get().toString() + " " + configCompilerFlagsValue.get().toString()).replaceCharacters ("\r\n", " ").trim(); }\r
+ String getAllLinkerFlagsString() const { return (exporter.extraLinkerFlagsValue .get().toString() + " " + configLinkerFlagsValue .get().toString()).replaceCharacters ("\r\n", " ").trim(); }\r
+\r
//==============================================================================\r
Value getValue (const Identifier& nm) { return config.getPropertyAsValue (nm, getUndoManager()); }\r
UndoManager* getUndoManager() const { return project.getUndoManagerFor (config); }\r
protected:\r
ValueTreePropertyWithDefault isDebugValue, configNameValue, targetNameValue, targetBinaryPathValue, recommendedWarningsValue, optimisationLevelValue,\r
linkTimeOptimisationValue, ppDefinesValue, headerSearchPathValue, librarySearchPathValue, userNotesValue,\r
- usePrecompiledHeaderFileValue, precompiledHeaderFileValue;\r
+ usePrecompiledHeaderFileValue, precompiledHeaderFileValue, configCompilerFlagsValue, configLinkerFlagsValue;\r
\r
private:\r
std::map<String, CompilerWarningFlags> recommendedCompilerWarningFlags;\r
\r
void addNewConfigurationFromExisting (const BuildConfiguration& configToCopy);\r
void addNewConfiguration (bool isDebugConfig);\r
- bool hasConfigurationNamed (const String& name) const;\r
String getUniqueConfigName (String name) const;\r
\r
String getExternalLibraryFlags (const BuildConfiguration& config) const;\r
\r
int getNumConfigurations() const;\r
BuildConfiguration::Ptr getConfiguration (int index) const;\r
+ std::optional<ValueTree> getConfigurationWithName (const String& nameToFind) const;\r
+ BuildConfiguration::Ptr getBuildConfigurationWithName (const String& nameToFind) const;\r
\r
ValueTree getConfigurations() const;\r
virtual void createDefaultConfigs();\r
return false;\r
}\r
\r
+ String getCompilerFlagsForProjectItem (const Project::Item& projectItem) const;\r
+\r
protected:\r
//==============================================================================\r
String name;\r
\r
private:\r
class ItemSelectionTimer;\r
- friend class ItemSelectionTimer;\r
std::unique_ptr<Timer> delayedSelectionTimer;\r
\r
void invokeShowDocument();\r
\r
private:\r
struct DotButton;\r
- friend struct DotButton;\r
\r
struct PageInfo\r
{\r
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
JUCE_CPPFLAGS_CONSOLEAPP := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_CONSOLEAPP := UnitTestRunner
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
TARGET_ARCH :=
endif
- JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+ JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70003" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
JUCE_CPPFLAGS_CONSOLEAPP := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
JUCE_TARGET_CONSOLEAPP := UnitTestRunner
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
- JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+ JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
962CC7E0A536C3F56DBE1F8F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
DEAD_CODE_STRIPPING = YES;
"NDEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_analytics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
);
INSTALL_PATH = "/usr/bin";
LLVM_LTO = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.10;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_IDENTITY = "";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = NO;
A81C9C5D3696F83D5E8CFE11 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
- CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
COPY_PHASE_STRIP = NO;
"DEBUG=1",
"JUCE_DISPLAY_SPLASH_SCREEN=0",
"JUCE_USE_DARK_SPLASH_SCREEN=1",
- "JUCE_PROJUCER_VERSION=0x70002",
+ "JUCE_PROJUCER_VERSION=0x70003",
"JUCE_MODULE_AVAILABLE_juce_analytics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
"JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
"$(inherited)",
);
INSTALL_PATH = "/usr/bin";
- MACOSX_DEPLOYMENT_TARGET = 10.10;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
<TreatWarningAsError>true</TreatWarningAsError>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
<TreatWarningAsError>true</TreatWarningAsError>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
<TreatWarningAsError>true</TreatWarningAsError>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
<TreatWarningAsError>true</TreatWarningAsError>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
<TreatWarningAsError>true</TreatWarningAsError>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
<TreatWarningAsError>true</TreatWarningAsError>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
<EXPORTFORMATS>\r
<XCODE_MAC targetFolder="Builds/MacOSX" applicationCategory="public.app-category.developer-tools">\r
<CONFIGURATIONS>\r
- <CONFIGURATION name="Debug" osxCompatibility="10.10 SDK" isDebug="1" targetName="UnitTestRunner"\r
- recommendedWarnings="LLVM" macOSDeploymentTarget="10.10"/>\r
- <CONFIGURATION name="Release" osxCompatibility="10.10 SDK" isDebug="0" targetName="UnitTestRunner"\r
- recommendedWarnings="LLVM" macOSDeploymentTarget="10.10"/>\r
+ <CONFIGURATION name="Debug" isDebug="1" targetName="UnitTestRunner"\r
+ recommendedWarnings="LLVM"/>\r
+ <CONFIGURATION name="Release" isDebug="0" targetName="UnitTestRunner"\r
+ recommendedWarnings="LLVM"/>\r
</CONFIGURATIONS>\r
<MODULEPATHS>\r
<MODULEPATH id="juce_core" path="../../modules"/>\r
<Optimization>Disabled</Optimization>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<WarningLevel>Level4</WarningLevel>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\juce_dll.lib</OutputFile>\r
<ClCompile>\r
<Optimization>Full</Optimization>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>NotUsing</PrecompiledHeader>\r
<WarningLevel>Level4</WarningLevel>\r
<SuppressStartupBanner>true</SuppressStartupBanner>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
- <LanguageStandard>stdcpp14</LanguageStandard>\r
+ <LanguageStandard>stdcpp17</LanguageStandard>\r
</ClCompile>\r
<ResourceCompile>\r
<AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
- <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70003;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
</ResourceCompile>\r
<Link>\r
<OutputFile>$(OutDir)\juce_dll.lib</OutputFile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <ExcludedFromBuild>true</ExcludedFromBuild>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<ExcludedFromBuild>true</ExcludedFromBuild>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClCompile>\r
+ <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClCompile>\r
<ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClCompile>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
- <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
<Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+ <Filter>JUCE Modules\juce_core\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
<Filter>JUCE Modules\juce_core\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
<Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
<Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
</ClInclude>\r
+ <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+ <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+ </ClInclude>\r
<ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
<Filter>JUCE Modules\juce_gui_basics</Filter>\r
</ClInclude>\r
juce_osc
juce_product_unlocking
juce_video)
-
-add_subdirectory(juce_audio_plugin_client)
\r
ID: juce_analytics\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_gui_basics\r
\r
double getEffectiveRate() const { return pulldown ? (double) base / 1.001 : (double) base; }\r
\r
/** Returns a copy of this object with the specified base rate. */\r
- JUCE_NODISCARD FrameRate withBaseRate (int x) const { return with (&FrameRate::base, x); }\r
+ [[nodiscard]] FrameRate withBaseRate (int x) const { return with (&FrameRate::base, x); }\r
\r
/** Returns a copy of this object with drop frames enabled or disabled, as specified. */\r
- JUCE_NODISCARD FrameRate withDrop (bool x = true) const { return with (&FrameRate::drop, x); }\r
+ [[nodiscard]] FrameRate withDrop (bool x = true) const { return with (&FrameRate::drop, x); }\r
\r
/** Returns a copy of this object with pulldown enabled or disabled, as specified. */\r
- JUCE_NODISCARD FrameRate withPullDown (bool x = true) const { return with (&FrameRate::pulldown, x); }\r
+ [[nodiscard]] FrameRate withPullDown (bool x = true) const { return with (&FrameRate::pulldown, x); }\r
\r
/** Returns true if this instance is equal to other. */\r
bool operator== (const FrameRate& other) const\r
/** Adds a number of samples to the pointer's position. */\r
Pointer& operator+= (int samplesToJump) noexcept { this->advanceDataBy (data, samplesToJump); return *this; }\r
\r
+ /** Returns a new pointer with the specified offset from this pointer's position. */\r
+ Pointer operator+ (int samplesToJump) const { return Pointer { *this } += samplesToJump; }\r
+\r
/** Writes a stream of samples into this pointer from another pointer.\r
This will copy the specified number of samples, converting between formats appropriately.\r
*/\r
{\r
using ElementType = std::remove_pointer_t<decltype (DataFormat::data)>;\r
using ChannelType = std::conditional_t<IsConst, const ElementType*, ElementType*>;\r
- using DataType = std::conditional_t<IsInterleaved, ChannelType, ChannelType*>;\r
+ using DataType = std::conditional_t<IsInterleaved, ChannelType, ChannelType const*>;\r
using PointerType = Pointer<DataFormat,\r
Endianness,\r
std::conditional_t<IsInterleaved, Interleaved, NonInterleaved>,\r
Don't modify any of the pointers that are returned, and bear in mind that\r
these will become invalid if the buffer is resized.\r
*/\r
- const Type** getArrayOfReadPointers() const noexcept { return const_cast<const Type**> (channels); }\r
+ const Type* const* getArrayOfReadPointers() const noexcept { return channels; }\r
\r
/** Returns an array of pointers to the channels in the buffer.\r
\r
\r
@see setNotClear\r
*/\r
- Type** getArrayOfWritePointers() noexcept { isClear = false; return channels; }\r
+ Type* const* getArrayOfWritePointers() noexcept { isClear = false; return channels; }\r
\r
//==============================================================================\r
/** Changes the buffer's size or number of channels.\r
@param newNumSamples the number of samples to use - this must correspond to the\r
size of the arrays passed in\r
*/\r
- void setDataToReferTo (Type** dataToReferTo,\r
+ void setDataToReferTo (Type* const* dataToReferTo,\r
int newNumChannels,\r
int newStartSample,\r
int newNumSamples)\r
@param newNumSamples the number of samples to use - this must correspond to the\r
size of the arrays passed in\r
*/\r
- void setDataToReferTo (Type** dataToReferTo,\r
+ void setDataToReferTo (Type* const* dataToReferTo,\r
int newNumChannels,\r
int newNumSamples)\r
{\r
jassert (size >= 0);\r
\r
auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*);\r
- auto requiredSampleAlignment = std::alignment_of<Type>::value;\r
+ auto requiredSampleAlignment = std::alignment_of_v<Type>;\r
size_t alignmentOverflow = channelListSize % requiredSampleAlignment;\r
\r
if (alignmentOverflow != 0)\r
intptr_t JUCE_CALLTYPE FloatVectorOperations::getFpStatusRegister() noexcept\r
{\r
intptr_t fpsr = 0;\r
- #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS\r
+ #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS\r
fpsr = static_cast<intptr_t> (_mm_getcsr());\r
- #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON\r
- #if defined(__arm64__) || defined(__aarch64__)\r
+ #elif (JUCE_64BIT && JUCE_ARM) || JUCE_USE_ARM_NEON\r
+ #if _MSC_VER\r
+ // _control87 returns static values for x86 bits that don't exist on arm\r
+ // to emulate x86 behaviour. We are only ever interested in de-normal bits\r
+ // so mask out only those.\r
+ fpsr = (intptr_t) (_control87 (0, 0) & _MCW_DN);\r
+ #else\r
+ #if JUCE_64BIT\r
asm volatile("mrs %0, fpcr"\r
: "=r"(fpsr));\r
#elif JUCE_USE_ARM_NEON\r
asm volatile("vmrs %0, fpscr"\r
: "=r"(fpsr));\r
#endif\r
- #else\r
- #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))\r
+ #endif\r
+ #else\r
+ #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))\r
jassertfalse; // No support for getting the floating point status register for your platform\r
- #endif\r
#endif\r
+ #endif\r
\r
return fpsr;\r
}\r
\r
void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister (intptr_t fpsr) noexcept\r
{\r
- #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS\r
+ #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS\r
// the volatile keyword here is needed to workaround a bug in AppleClang 13.0\r
// which aggressively optimises away the variable otherwise\r
volatile auto fpsr_w = static_cast<uint32_t> (fpsr);\r
_mm_setcsr (fpsr_w);\r
- #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON\r
- #if defined(__arm64__) || defined(__aarch64__)\r
+ #elif (JUCE_64BIT && JUCE_ARM) || JUCE_USE_ARM_NEON\r
+ #if _MSC_VER\r
+ _control87 ((unsigned int) fpsr, _MCW_DN);\r
+ #else\r
+ #if JUCE_64BIT\r
asm volatile("msr fpcr, %0"\r
:\r
: "ri"(fpsr));\r
:\r
: "ri"(fpsr));\r
#endif\r
- #else\r
- #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))\r
+ #endif\r
+ #else\r
+ #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))\r
jassertfalse; // No support for getting the floating point status register for your platform\r
- #endif\r
- ignoreUnused (fpsr);\r
#endif\r
+ ignoreUnused (fpsr);\r
+ #endif\r
}\r
\r
void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnable) noexcept\r
{\r
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+ #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
#if JUCE_USE_SSE_INTRINSICS\r
intptr_t mask = _MM_FLUSH_ZERO_MASK;\r
#else /*JUCE_USE_ARM_NEON*/\r
#endif\r
setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldEnable ? mask : 0));\r
#else\r
- #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))\r
+ #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))\r
jassertfalse; // No support for flush to zero mode on your platform\r
#endif\r
ignoreUnused (shouldEnable);\r
\r
void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool shouldDisable) noexcept\r
{\r
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+ #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
#if JUCE_USE_SSE_INTRINSICS\r
intptr_t mask = 0x8040;\r
#else /*JUCE_USE_ARM_NEON*/\r
#else\r
ignoreUnused (shouldDisable);\r
\r
- #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))\r
+ #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))\r
jassertfalse; // No support for disable denormals mode on your platform\r
#endif\r
#endif\r
\r
bool JUCE_CALLTYPE FloatVectorOperations::areDenormalsDisabled() noexcept\r
{\r
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+ #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
#if JUCE_USE_SSE_INTRINSICS\r
intptr_t mask = 0x8040;\r
#else /*JUCE_USE_ARM_NEON*/\r
\r
ScopedNoDenormals::ScopedNoDenormals() noexcept\r
{\r
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+ #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
#if JUCE_USE_SSE_INTRINSICS\r
intptr_t mask = 0x8040;\r
#else /*JUCE_USE_ARM_NEON*/\r
\r
ScopedNoDenormals::~ScopedNoDenormals() noexcept\r
{\r
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+ #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
FloatVectorOperations::setFpStatusRegister (fpsr);\r
#endif\r
}\r
~ScopedNoDenormals() noexcept;\r
\r
private:\r
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined (__arm64__) || defined (__aarch64__))\r
+ #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
intptr_t fpsr;\r
#endif\r
};\r
\r
ID: juce_audio_basics\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_core\r
OSXFrameworks: Accelerate\r
The packet must be well-formed for member functions to work correctly.\r
\r
Specifically, the constructor argument must be the beginning of a region of\r
- uint32_t that contains at least `getNumWordsForMessageType(*ddata)` items,\r
+ uint32_t that contains at least `getNumWordsForMessageType(*data)` items,\r
where `data` is the constructor argument.\r
\r
NOTE: Instances of this class do not own the memory that they point to!\r
\r
#if JUCE_WINDOWS && ! JUCE_MINGW\r
#define JUCE_CHECKED_ITERATOR(msg, size) \\r
- stdext::checked_array_iterator<typename std::remove_reference<decltype (msg)>::type> ((msg), (size_t) (size))\r
+ stdext::checked_array_iterator<std::remove_reference_t<decltype (msg)>> ((msg), (size_t) (size))\r
#else\r
#define JUCE_CHECKED_ITERATOR(msg, size) (msg)\r
#endif\r
public:\r
Packet() = default;\r
\r
- template <size_t w = numWords, typename std::enable_if<w == 1, int>::type = 0>\r
+ template <size_t w = numWords, std::enable_if_t<w == 1, int> = 0>\r
Packet (uint32_t a)\r
: contents { { a } }\r
{\r
jassert (Utils::getNumWordsForMessageType (a) == 1);\r
}\r
\r
- template <size_t w = numWords, typename std::enable_if<w == 2, int>::type = 0>\r
+ template <size_t w = numWords, std::enable_if_t<w == 2, int> = 0>\r
Packet (uint32_t a, uint32_t b)\r
: contents { { a, b } }\r
{\r
jassert (Utils::getNumWordsForMessageType (a) == 2);\r
}\r
\r
- template <size_t w = numWords, typename std::enable_if<w == 3, int>::type = 0>\r
+ template <size_t w = numWords, std::enable_if_t<w == 3, int> = 0>\r
Packet (uint32_t a, uint32_t b, uint32_t c)\r
: contents { { a, b, c } }\r
{\r
jassert (Utils::getNumWordsForMessageType (a) == 3);\r
}\r
\r
- template <size_t w = numWords, typename std::enable_if<w == 4, int>::type = 0>\r
+ template <size_t w = numWords, std::enable_if_t<w == 4, int> = 0>\r
Packet (uint32_t a, uint32_t b, uint32_t c, uint32_t d)\r
: contents { { a, b, c, d } }\r
{\r
jassert (Utils::getNumWordsForMessageType (a) == 4);\r
}\r
\r
- template <size_t w, typename std::enable_if<w == numWords, int>::type = 0>\r
+ template <size_t w, std::enable_if_t<w == numWords, int> = 0>\r
explicit Packet (const std::array<uint32_t, w>& fullPacket)\r
: contents (fullPacket)\r
{\r
MPESynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase\r
MPESynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase\r
\r
+ // All major OSes use double-locking so this will be lock- and wait-free as long as stealLock is not\r
+ // contended. This is always the case if you do not call findVoiceToSteal on multiple threads at\r
+ // the same time.\r
+ const ScopedLock sl (stealLock);\r
+\r
// this is a list of voices we can steal, sorted by how long they've been running\r
- Array<MPESynthesiserVoice*> usableVoices;\r
- usableVoices.ensureStorageAllocated (voices.size());\r
+ usableVoicesToStealArray.clear();\r
\r
for (auto* voice : voices)\r
{\r
jassert (voice->isActive()); // We wouldn't be here otherwise\r
\r
- usableVoices.add (voice);\r
+ usableVoicesToStealArray.add (voice);\r
\r
// NB: Using a functor rather than a lambda here due to scare-stories about\r
// compilers generating code containing heap allocations..\r
bool operator() (const MPESynthesiserVoice* a, const MPESynthesiserVoice* b) const noexcept { return a->noteOnTime < b->noteOnTime; }\r
};\r
\r
- std::sort (usableVoices.begin(), usableVoices.end(), Sorter());\r
+ std::sort (usableVoicesToStealArray.begin(), usableVoicesToStealArray.end(), Sorter());\r
\r
if (! voice->isPlayingButReleased()) // Don't protect released notes\r
{\r
// If we want to re-use the voice to trigger a new note,\r
// then The oldest note that's playing the same note number is ideal.\r
if (noteToStealVoiceFor.isValid())\r
- for (auto* voice : usableVoices)\r
+ for (auto* voice : usableVoicesToStealArray)\r
if (voice->getCurrentlyPlayingNote().initialNote == noteToStealVoiceFor.initialNote)\r
return voice;\r
\r
// Oldest voice that has been released (no finger on it and not held by sustain pedal)\r
- for (auto* voice : usableVoices)\r
+ for (auto* voice : usableVoicesToStealArray)\r
if (voice != low && voice != top && voice->isPlayingButReleased())\r
return voice;\r
\r
// Oldest voice that doesn't have a finger on it:\r
- for (auto* voice : usableVoices)\r
+ for (auto* voice : usableVoicesToStealArray)\r
if (voice != low && voice != top\r
&& voice->getCurrentlyPlayingNote().keyState != MPENote::keyDown\r
&& voice->getCurrentlyPlayingNote().keyState != MPENote::keyDownAndSustained)\r
return voice;\r
\r
// Oldest voice that isn't protected\r
- for (auto* voice : usableVoices)\r
+ for (auto* voice : usableVoicesToStealArray)\r
if (voice != low && voice != top)\r
return voice;\r
\r
//==============================================================================\r
void MPESynthesiser::addVoice (MPESynthesiserVoice* const newVoice)\r
{\r
- const ScopedLock sl (voicesLock);\r
- newVoice->setCurrentSampleRate (getSampleRate());\r
- voices.add (newVoice);\r
+ {\r
+ const ScopedLock sl (voicesLock);\r
+ newVoice->setCurrentSampleRate (getSampleRate());\r
+ voices.add (newVoice);\r
+ }\r
+\r
+ {\r
+ const ScopedLock sl (stealLock);\r
+ usableVoicesToStealArray.ensureStorageAllocated (voices.size() + 1);\r
+ }\r
}\r
\r
void MPESynthesiser::clearVoices()\r
//==============================================================================\r
std::atomic<bool> shouldStealVoices { false };\r
uint32 lastNoteOnCounter = 0;\r
+ mutable CriticalSection stealLock;\r
+ mutable Array<MPESynthesiserVoice*> usableVoicesToStealArray;\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESynthesiser)\r
};\r
\r
SynthesiserVoice* Synthesiser::addVoice (SynthesiserVoice* const newVoice)\r
{\r
- const ScopedLock sl (lock);\r
- newVoice->setCurrentPlaybackSampleRate (sampleRate);\r
- return voices.add (newVoice);\r
+ SynthesiserVoice* voice;\r
+\r
+ {\r
+ const ScopedLock sl (lock);\r
+ newVoice->setCurrentPlaybackSampleRate (sampleRate);\r
+ voice = voices.add (newVoice);\r
+ }\r
+\r
+ {\r
+ const ScopedLock sl (stealLock);\r
+ usableVoicesToStealArray.ensureStorageAllocated (voices.size() + 1);\r
+ }\r
+\r
+ return voice;\r
}\r
\r
void Synthesiser::removeVoice (const int index)\r
SynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase\r
SynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase\r
\r
+ // All major OSes use double-locking so this will be lock- and wait-free as long as the lock is not\r
+ // contended. This is always the case if you do not call findVoiceToSteal on multiple threads at\r
+ // the same time.\r
+ const ScopedLock sl (stealLock);\r
+\r
// this is a list of voices we can steal, sorted by how long they've been running\r
- Array<SynthesiserVoice*> usableVoices;\r
- usableVoices.ensureStorageAllocated (voices.size());\r
+ usableVoicesToStealArray.clear();\r
\r
for (auto* voice : voices)\r
{\r
{\r
jassert (voice->isVoiceActive()); // We wouldn't be here otherwise\r
\r
- usableVoices.add (voice);\r
+ usableVoicesToStealArray.add (voice);\r
\r
// NB: Using a functor rather than a lambda here due to scare-stories about\r
// compilers generating code containing heap allocations..\r
bool operator() (const SynthesiserVoice* a, const SynthesiserVoice* b) const noexcept { return a->wasStartedBefore (*b); }\r
};\r
\r
- std::sort (usableVoices.begin(), usableVoices.end(), Sorter());\r
+ std::sort (usableVoicesToStealArray.begin(), usableVoicesToStealArray.end(), Sorter());\r
\r
if (! voice->isPlayingButReleased()) // Don't protect released notes\r
{\r
top = nullptr;\r
\r
// The oldest note that's playing with the target pitch is ideal..\r
- for (auto* voice : usableVoices)\r
+ for (auto* voice : usableVoicesToStealArray)\r
if (voice->getCurrentlyPlayingNote() == midiNoteNumber)\r
return voice;\r
\r
// Oldest voice that has been released (no finger on it and not held by sustain pedal)\r
- for (auto* voice : usableVoices)\r
+ for (auto* voice : usableVoicesToStealArray)\r
if (voice != low && voice != top && voice->isPlayingButReleased())\r
return voice;\r
\r
// Oldest voice that doesn't have a finger on it:\r
- for (auto* voice : usableVoices)\r
+ for (auto* voice : usableVoicesToStealArray)\r
if (voice != low && voice != top && ! voice->isKeyDown())\r
return voice;\r
\r
// Oldest voice that isn't protected\r
- for (auto* voice : usableVoices)\r
+ for (auto* voice : usableVoicesToStealArray)\r
if (voice != low && voice != top)\r
return voice;\r
\r
bool subBlockSubdivisionIsStrict = false;\r
bool shouldStealNotes = true;\r
BigInteger sustainPedalsDown;\r
+ mutable CriticalSection stealLock;\r
+ mutable Array<SynthesiserVoice*> usableVoicesToStealArray;\r
\r
template <typename floatType>\r
void processNextBlock (AudioBuffer<floatType>&, const MidiBuffer&, int startSample, int numSamples);\r
template <class InterpolatorTraits, int memorySize>\r
class JUCE_API GenericInterpolator\r
{\r
+ static auto processReplacingCallback()\r
+ {\r
+ return [] (auto, auto newValue) { return newValue; };\r
+ }\r
+\r
+ static auto processAddingCallback (float gain)\r
+ {\r
+ return [gain] (auto oldValue, auto newValue) { return oldValue + gain * newValue; };\r
+ }\r
+\r
public:\r
GenericInterpolator() noexcept { reset(); }\r
\r
float* outputSamples,\r
int numOutputSamplesToProduce) noexcept\r
{\r
- return interpolate (speedRatio, inputSamples, outputSamples, numOutputSamplesToProduce);\r
+ return interpolateImpl (speedRatio,\r
+ inputSamples,\r
+ outputSamples,\r
+ numOutputSamplesToProduce,\r
+ processReplacingCallback());\r
}\r
\r
/** Resamples a stream of samples.\r
int numInputSamplesAvailable,\r
int wrapAround) noexcept\r
{\r
- return interpolate (speedRatio, inputSamples, outputSamples,\r
- numOutputSamplesToProduce, numInputSamplesAvailable, wrapAround);\r
+ return interpolateImpl (speedRatio,\r
+ inputSamples,\r
+ outputSamples,\r
+ numOutputSamplesToProduce,\r
+ numInputSamplesAvailable,\r
+ wrapAround,\r
+ processReplacingCallback());\r
}\r
\r
/** Resamples a stream of samples, adding the results to the output data\r
int numOutputSamplesToProduce,\r
float gain) noexcept\r
{\r
- return interpolateAdding (speedRatio, inputSamples, outputSamples, numOutputSamplesToProduce, gain);\r
+ return interpolateImpl (speedRatio,\r
+ inputSamples,\r
+ outputSamples,\r
+ numOutputSamplesToProduce,\r
+ processAddingCallback (gain));\r
}\r
\r
/** Resamples a stream of samples, adding the results to the output data\r
int wrapAround,\r
float gain) noexcept\r
{\r
- return interpolateAdding (speedRatio, inputSamples, outputSamples,\r
- numOutputSamplesToProduce, numInputSamplesAvailable, wrapAround, gain);\r
+ return interpolateImpl (speedRatio,\r
+ inputSamples,\r
+ outputSamples,\r
+ numOutputSamplesToProduce,\r
+ numInputSamplesAvailable,\r
+ wrapAround,\r
+ processAddingCallback (gain));\r
}\r
\r
private:\r
}\r
\r
//==============================================================================\r
- int interpolate (double speedRatio,\r
- const float* input,\r
- float* output,\r
- int numOutputSamplesToProduce) noexcept\r
- {\r
- auto pos = subSamplePos;\r
- int numUsed = 0;\r
-\r
- while (numOutputSamplesToProduce > 0)\r
- {\r
- while (pos >= 1.0)\r
- {\r
- pushInterpolationSample (input[numUsed++]);\r
- pos -= 1.0;\r
- }\r
-\r
- *output++ = InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);\r
- pos += speedRatio;\r
- --numOutputSamplesToProduce;\r
- }\r
-\r
- subSamplePos = pos;\r
- return numUsed;\r
- }\r
-\r
- int interpolate (double speedRatio,\r
- const float* input, float* output,\r
- int numOutputSamplesToProduce,\r
- int numInputSamplesAvailable,\r
- int wrap) noexcept\r
+ template <typename Process>\r
+ int interpolateImpl (double speedRatio,\r
+ const float* input,\r
+ float* output,\r
+ int numOutputSamplesToProduce,\r
+ int numInputSamplesAvailable,\r
+ int wrap,\r
+ Process process)\r
{\r
auto originalIn = input;\r
- auto pos = subSamplePos;\r
bool exceeded = false;\r
\r
- if (speedRatio < 1.0)\r
+ const auto pushSample = [&]\r
{\r
- for (int i = numOutputSamplesToProduce; --i >= 0;)\r
+ if (exceeded)\r
{\r
- if (pos >= 1.0)\r
- {\r
- if (exceeded)\r
- {\r
- pushInterpolationSample (0.0f);\r
- }\r
- else\r
- {\r
- pushInterpolationSample (*input++);\r
-\r
- if (--numInputSamplesAvailable <= 0)\r
- {\r
- if (wrap > 0)\r
- {\r
- input -= wrap;\r
- numInputSamplesAvailable += wrap;\r
- }\r
- else\r
- {\r
- exceeded = true;\r
- }\r
- }\r
- }\r
-\r
- pos -= 1.0;\r
- }\r
-\r
- *output++ = InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);\r
- pos += speedRatio;\r
+ pushInterpolationSample (0.0);\r
}\r
- }\r
- else\r
- {\r
- for (int i = numOutputSamplesToProduce; --i >= 0;)\r
+ else\r
{\r
- while (pos < speedRatio)\r
+ pushInterpolationSample (*input++);\r
+\r
+ if (--numInputSamplesAvailable <= 0)\r
{\r
- if (exceeded)\r
+ if (wrap > 0)\r
{\r
- pushInterpolationSample (0);\r
+ input -= wrap;\r
+ numInputSamplesAvailable += wrap;\r
}\r
else\r
{\r
- pushInterpolationSample (*input++);\r
-\r
- if (--numInputSamplesAvailable <= 0)\r
- {\r
- if (wrap > 0)\r
- {\r
- input -= wrap;\r
- numInputSamplesAvailable += wrap;\r
- }\r
- else\r
- {\r
- exceeded = true;\r
- }\r
- }\r
+ exceeded = true;\r
}\r
-\r
- pos += 1.0;\r
}\r
-\r
- pos -= speedRatio;\r
- *output++ = InterpolatorTraits::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos), indexBuffer);\r
}\r
- }\r
+ };\r
\r
- subSamplePos = pos;\r
+ interpolateImpl (speedRatio,\r
+ output,\r
+ numOutputSamplesToProduce,\r
+ process,\r
+ pushSample);\r
\r
if (wrap == 0)\r
return (int) (input - originalIn);\r
return ((int) (input - originalIn) + wrap) % wrap;\r
}\r
\r
- int interpolateAdding (double speedRatio,\r
- const float* input,\r
- float* output,\r
- int numOutputSamplesToProduce,\r
- int numInputSamplesAvailable,\r
- int wrap,\r
- float gain) noexcept\r
+ template <typename Process>\r
+ int interpolateImpl (double speedRatio,\r
+ const float* input,\r
+ float* output,\r
+ int numOutputSamplesToProduce,\r
+ Process process)\r
{\r
- auto originalIn = input;\r
- auto pos = subSamplePos;\r
- bool exceeded = false;\r
-\r
- if (speedRatio < 1.0)\r
- {\r
- for (int i = numOutputSamplesToProduce; --i >= 0;)\r
- {\r
- if (pos >= 1.0)\r
- {\r
- if (exceeded)\r
- {\r
- pushInterpolationSample (0.0);\r
- }\r
- else\r
- {\r
- pushInterpolationSample (*input++);\r
-\r
- if (--numInputSamplesAvailable <= 0)\r
- {\r
- if (wrap > 0)\r
- {\r
- input -= wrap;\r
- numInputSamplesAvailable += wrap;\r
- }\r
- else\r
- {\r
- numInputSamplesAvailable = true;\r
- }\r
- }\r
- }\r
-\r
- pos -= 1.0;\r
- }\r
-\r
- *output++ += gain * InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);\r
- pos += speedRatio;\r
- }\r
- }\r
- else\r
- {\r
- for (int i = numOutputSamplesToProduce; --i >= 0;)\r
- {\r
- while (pos < speedRatio)\r
- {\r
- if (exceeded)\r
- {\r
- pushInterpolationSample (0.0);\r
- }\r
- else\r
- {\r
- pushInterpolationSample (*input++);\r
-\r
- if (--numInputSamplesAvailable <= 0)\r
- {\r
- if (wrap > 0)\r
- {\r
- input -= wrap;\r
- numInputSamplesAvailable += wrap;\r
- }\r
- else\r
- {\r
- exceeded = true;\r
- }\r
- }\r
- }\r
-\r
- pos += 1.0;\r
- }\r
-\r
- pos -= speedRatio;\r
- *output++ += gain * InterpolatorTraits::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos), indexBuffer);\r
- }\r
- }\r
-\r
- subSamplePos = pos;\r
+ int numUsed = 0;\r
\r
- if (wrap == 0)\r
- return (int) (input - originalIn);\r
+ interpolateImpl (speedRatio,\r
+ output,\r
+ numOutputSamplesToProduce,\r
+ process,\r
+ [this, input, &numUsed] { pushInterpolationSample (input[numUsed++]); });\r
\r
- return ((int) (input - originalIn) + wrap) % wrap;\r
+ return numUsed;\r
}\r
\r
- int interpolateAdding (double speedRatio,\r
- const float* input,\r
- float* output,\r
- int numOutputSamplesToProduce,\r
- float gain) noexcept\r
+ template <typename Process, typename PushSample>\r
+ void interpolateImpl (double speedRatio,\r
+ float* output,\r
+ int numOutputSamplesToProduce,\r
+ Process process,\r
+ PushSample pushSample)\r
{\r
auto pos = subSamplePos;\r
- int numUsed = 0;\r
\r
- while (numOutputSamplesToProduce > 0)\r
+ for (auto i = 0; i < numOutputSamplesToProduce; ++i)\r
{\r
while (pos >= 1.0)\r
{\r
- pushInterpolationSample (input[numUsed++]);\r
+ pushSample();\r
pos -= 1.0;\r
}\r
\r
- *output++ += gain * InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);\r
+ *output = process (*output, InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer));\r
+ ++output;\r
pos += speedRatio;\r
- --numOutputSamplesToProduce;\r
}\r
\r
subSamplePos = pos;\r
- return numUsed;\r
}\r
\r
//==============================================================================\r
//==============================================================================\r
/** Constructor. */\r
SmoothedValue() noexcept\r
- : SmoothedValue ((FloatType) (std::is_same<SmoothingType, ValueSmoothingTypes::Linear>::value ? 0 : 1))\r
+ : SmoothedValue ((FloatType) (std::is_same_v<SmoothingType, ValueSmoothingTypes::Linear> ? 0 : 1))\r
{\r
}\r
\r
SmoothedValue (FloatType initialValue) noexcept\r
{\r
// Multiplicative smoothed values cannot ever reach 0!\r
- jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value && initialValue == 0));\r
+ jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && initialValue == 0));\r
\r
// Visual Studio can't handle base class initialisation with CRTP\r
this->currentValue = initialValue;\r
}\r
\r
// Multiplicative smoothed values cannot ever reach 0!\r
- jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value && newValue == 0));\r
+ jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && newValue == 0));\r
\r
this->target = newValue;\r
this->countdown = stepsToTarget;\r
\r
private:\r
//==============================================================================\r
- template <typename T>\r
- using LinearVoid = typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Linear>::value, void>::type;\r
-\r
- template <typename T>\r
- using MultiplicativeVoid = typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Multiplicative>::value, void>::type;\r
-\r
- //==============================================================================\r
- template <typename T = SmoothingType>\r
- LinearVoid<T> setStepSize() noexcept\r
- {\r
- step = (this->target - this->currentValue) / (FloatType) this->countdown;\r
- }\r
-\r
template <typename T = SmoothingType>\r
- MultiplicativeVoid<T> setStepSize()\r
+ void setStepSize() noexcept\r
{\r
- step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / (FloatType) this->countdown);\r
+ if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)\r
+ {\r
+ step = (this->target - this->currentValue) / (FloatType) this->countdown;\r
+ }\r
+ else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)\r
+ {\r
+ step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / (FloatType) this->countdown);\r
+ }\r
}\r
\r
//==============================================================================\r
template <typename T = SmoothingType>\r
- LinearVoid<T> setNextValue() noexcept\r
+ void setNextValue() noexcept\r
{\r
- this->currentValue += step;\r
- }\r
-\r
- template <typename T = SmoothingType>\r
- MultiplicativeVoid<T> setNextValue() noexcept\r
- {\r
- this->currentValue *= step;\r
+ if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)\r
+ {\r
+ this->currentValue += step;\r
+ }\r
+ else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)\r
+ {\r
+ this->currentValue *= step;\r
+ }\r
}\r
\r
//==============================================================================\r
template <typename T = SmoothingType>\r
- LinearVoid<T> skipCurrentValue (int numSamples) noexcept\r
+ void skipCurrentValue (int numSamples) noexcept\r
{\r
- this->currentValue += step * (FloatType) numSamples;\r
- }\r
-\r
- template <typename T = SmoothingType>\r
- MultiplicativeVoid<T> skipCurrentValue (int numSamples)\r
- {\r
- this->currentValue *= (FloatType) std::pow (step, numSamples);\r
+ if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)\r
+ {\r
+ this->currentValue += step * (FloatType) numSamples;\r
+ }\r
+ else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)\r
+ {\r
+ this->currentValue *= (FloatType) std::pow (step, numSamples);\r
+ }\r
}\r
\r
//==============================================================================\r
CallbackHandler (AudioDeviceManager& adm) noexcept : owner (adm) {}\r
\r
private:\r
- void audioDeviceIOCallbackWithContext (const float** ins,\r
+ void audioDeviceIOCallbackWithContext (const float* const* ins,\r
int numIns,\r
- float** outs,\r
+ float* const* outs,\r
int numOuts,\r
int numSamples,\r
const AudioIODeviceCallbackContext& context) override\r
\r
void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const\r
{\r
+ enum class Direction { out, in };\r
+\r
if (auto* type = getCurrentDeviceTypeObject())\r
{\r
- for (const auto isInput : { false, true })\r
+ // We avoid selecting a device pair that doesn't share a matching sample rate, if possible.\r
+ // If not, other parts of the AudioDeviceManager and AudioIODevice classes should generate\r
+ // an appropriate error message when opening or starting these devices.\r
+ const auto getDevicesToTestForMatchingSampleRate = [&setup, type, this] (Direction dir)\r
{\r
- const auto numChannelsNeeded = isInput ? numInputChansNeeded : numOutputChansNeeded;\r
+ const auto isInput = dir == Direction::in;\r
const auto info = getSetupInfo (setup, isInput);\r
\r
- if (numChannelsNeeded > 0 && info.name.isEmpty())\r
- info.name = type->getDeviceNames (isInput) [type->getDefaultDeviceIndex (isInput)];\r
+ if (! info.name.isEmpty())\r
+ return StringArray { info.name };\r
+\r
+ const auto numChannelsNeeded = isInput ? numInputChansNeeded : numOutputChansNeeded;\r
+ auto deviceNames = numChannelsNeeded > 0 ? type->getDeviceNames (isInput) : StringArray {};\r
+ deviceNames.move (type->getDefaultDeviceIndex (isInput), 0);\r
+\r
+ return deviceNames;\r
+ };\r
+\r
+ std::map<std::pair<Direction, String>, Array<double>> sampleRatesCache;\r
+\r
+ const auto getSupportedSampleRates = [&sampleRatesCache, type] (Direction dir, const String& deviceName)\r
+ {\r
+ const auto key = std::make_pair (dir, deviceName);\r
+\r
+ auto& entry = [&]() -> auto&\r
+ {\r
+ auto it = sampleRatesCache.find (key);\r
+\r
+ if (it != sampleRatesCache.end())\r
+ return it->second;\r
+\r
+ auto& elem = sampleRatesCache[key];\r
+ auto tempDevice = rawToUniquePtr (type->createDevice ((dir == Direction::in) ? "" : deviceName,\r
+ (dir == Direction::in) ? deviceName : ""));\r
+ if (tempDevice != nullptr)\r
+ elem = tempDevice->getAvailableSampleRates();\r
+\r
+ return elem;\r
+ }();\r
+\r
+ return entry;\r
+ };\r
+\r
+ const auto validate = [&getSupportedSampleRates] (const String& outputDeviceName, const String& inputDeviceName)\r
+ {\r
+ jassert (! outputDeviceName.isEmpty() && ! inputDeviceName.isEmpty());\r
+\r
+ const auto outputSampleRates = getSupportedSampleRates (Direction::out, outputDeviceName);\r
+ const auto inputSampleRates = getSupportedSampleRates (Direction::in, inputDeviceName);\r
+\r
+ return std::any_of (inputSampleRates.begin(),\r
+ inputSampleRates.end(),\r
+ [&] (auto inputSampleRate) { return outputSampleRates.contains (inputSampleRate); });\r
+ };\r
+\r
+ auto outputsToTest = getDevicesToTestForMatchingSampleRate (Direction::out);\r
+ auto inputsToTest = getDevicesToTestForMatchingSampleRate (Direction::in);\r
+\r
+ // We set default device names, so in case no in-out pair passes the validation, we still\r
+ // produce the same result as before\r
+ if (setup.outputDeviceName.isEmpty() && ! outputsToTest.isEmpty())\r
+ setup.outputDeviceName = outputsToTest[0];\r
+\r
+ if (setup.inputDeviceName.isEmpty() && ! inputsToTest.isEmpty())\r
+ setup.inputDeviceName = inputsToTest[0];\r
+\r
+ // We check all possible in-out pairs until the first validation pass. If no pair passes we\r
+ // leave the setup unchanged.\r
+ for (const auto& out : outputsToTest)\r
+ {\r
+ for (const auto& in : inputsToTest)\r
+ {\r
+ if (validate (out, in))\r
+ {\r
+ setup.outputDeviceName = out;\r
+ setup.inputDeviceName = in;\r
+\r
+ return;\r
+ }\r
+ }\r
}\r
}\r
}\r
currentDeviceType = currentAudioDevice->getTypeName();\r
\r
currentAudioDevice->start (callbackHandler.get());\r
+\r
+ error = currentAudioDevice->getLastError();\r
+ }\r
+\r
+ if (error.isEmpty())\r
+ {\r
updateCurrentSetup();\r
\r
for (int i = 0; i < availableDeviceTypes.size(); ++i)\r
}\r
}\r
\r
-void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData,\r
+void AudioDeviceManager::audioDeviceIOCallbackInt (const float* const* inputChannelData,\r
int numInputChannels,\r
- float** outputChannelData,\r
+ float* const* outputChannelData,\r
int numOutputChannels,\r
int numSamples,\r
const AudioIODeviceCallbackContext& context)\r
numSamples,\r
context);\r
\r
- auto** tempChans = tempBuffer.getArrayOfWritePointers();\r
+ auto* const* tempChans = tempBuffer.getArrayOfWritePointers();\r
\r
for (int i = callbacks.size(); --i > 0;)\r
{\r
testSound.reset();\r
}\r
\r
- outputLevelGetter->updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);\r
+ outputLevelGetter->updateLevel (outputChannelData, numOutputChannels, numSamples);\r
}\r
\r
void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device)\r
std::function<void()> stopped;\r
std::function<void()> error;\r
\r
- void audioDeviceIOCallback (const float**, int, float**, int, int) override { NullCheckedInvocation::invoke (callback); }\r
- void audioDeviceAboutToStart (AudioIODevice*) override { NullCheckedInvocation::invoke (aboutToStart); }\r
- void audioDeviceStopped() override { NullCheckedInvocation::invoke (stopped); }\r
- void audioDeviceError (const String&) override { NullCheckedInvocation::invoke (error); }\r
+ void audioDeviceIOCallbackWithContext (const float* const*,\r
+ int,\r
+ float* const*,\r
+ int,\r
+ int,\r
+ const AudioIODeviceCallbackContext&) override\r
+ {\r
+ NullCheckedInvocation::invoke (callback);\r
+ }\r
+\r
+ void audioDeviceAboutToStart (AudioIODevice*) override { NullCheckedInvocation::invoke (aboutToStart); }\r
+ void audioDeviceStopped() override { NullCheckedInvocation::invoke (stopped); }\r
+ void audioDeviceError (const String&) override { NullCheckedInvocation::invoke (error); }\r
};\r
\r
void initialiseManager (AudioDeviceManager& manager)\r
class CallbackHandler;\r
std::unique_ptr<CallbackHandler> callbackHandler;\r
\r
- void audioDeviceIOCallbackInt (const float** inputChannelData,\r
+ void audioDeviceIOCallbackInt (const float* const* inputChannelData,\r
int totalNumInputChannels,\r
- float** outputChannelData,\r
+ float* const* outputChannelData,\r
int totalNumOutputChannels,\r
int numSamples,\r
const AudioIODeviceCallbackContext& context);\r
One of these is passed to an AudioIODevice object to stream the audio data\r
in and out.\r
\r
- The AudioIODevice will repeatedly call this class's audioDeviceIOCallback()\r
+ The AudioIODevice will repeatedly call this class's audioDeviceIOCallbackWithContext()\r
method on its own high-priority audio thread, when it needs to send or receive\r
the next block of data.\r
\r
processing into several smaller callbacks to ensure higher audio\r
performance. So make sure your code can cope with reasonable\r
changes in the buffer size from one callback to the next.\r
+ @param context Additional information that may be passed to the\r
+ AudioIODeviceCallback.\r
*/\r
- virtual void audioDeviceIOCallback (const float** inputChannelData,\r
- int numInputChannels,\r
- float** outputChannelData,\r
- int numOutputChannels,\r
- int numSamples)\r
- {\r
- ignoreUnused (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples);\r
- }\r
-\r
- /** The same as audioDeviceIOCallback(), but with an additional context argument.\r
-\r
- The default implementation of this function will call audioDeviceIOCallback(),\r
- but you can override this function if you need to make use of the context information.\r
- */\r
- virtual void audioDeviceIOCallbackWithContext (const float** inputChannelData,\r
+ virtual void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
int numInputChannels,\r
- float** outputChannelData,\r
+ float* const* outputChannelData,\r
int numOutputChannels,\r
int numSamples,\r
const AudioIODeviceCallbackContext& context)\r
{\r
- audioDeviceIOCallback (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples);\r
- ignoreUnused (context);\r
+ ignoreUnused (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples, context);\r
}\r
\r
/** Called to indicate that the device is about to start calling back.\r
\r
ID: juce_audio_devices\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_audio_basics, juce_events\r
OSXFrameworks: CoreAudio CoreMIDI AudioToolbox\r
\r
void MidiOutput::startBackgroundThread()\r
{\r
- startThread (9);\r
+ startThread (Priority::high);\r
}\r
\r
void MidiOutput::stopBackgroundThread()\r
if (inputDevice != nullptr)\r
env->CallVoidMethod (inputDevice, AudioRecord.startRecording);\r
\r
- startThread (8);\r
+ startThread (Priority::high);\r
}\r
else\r
{\r
}\r
}\r
\r
- void process (const float** inputChannelData, int numInputChannels,\r
- float** outputChannelData, int numOutputChannels, int32_t numFrames)\r
+ void process (const float* const* inputChannelData, int numInputChannels,\r
+ float* const* outputChannelData, int numOutputChannels, int32_t numFrames)\r
{\r
if (auto* cb = callback.exchange (nullptr))\r
{\r
if ((int) numFrames > channelData.getFloatBufferSize())\r
channelData.setFloatBufferSize ((int) numFrames);\r
\r
- float** const inputData = channelData.audioData.getArrayOfWritePointers();\r
- float** const outputData = inputData + channelData.inputs->numActiveChannels;\r
+ float* const* const inputData = channelData.audioData.getArrayOfWritePointers();\r
+ float* const* const outputData = inputData + channelData.inputs->numActiveChannels;\r
\r
if (useInput)\r
{\r
if (outputDevice != nullptr && JUCE_ALSA_FAILED (snd_pcm_prepare (outputDevice->handle)))\r
return;\r
\r
- startThread (9);\r
+ startThread (Priority::high);\r
\r
int count = 1000;\r
\r
if (callback != nullptr)\r
{\r
if ((numActiveInChans + numActiveOutChans) > 0)\r
- callback->audioDeviceIOCallbackWithContext (const_cast<const float**> (inChans.getData()),\r
+ callback->audioDeviceIOCallbackWithContext (inChans.getData(),\r
numActiveInChans,\r
outChans,\r
numActiveOutChans,\r
#endif\r
\r
//==============================================================================\r
-struct AsyncRestarter\r
+class ManagedAudioBufferList : public AudioBufferList\r
{\r
- virtual ~AsyncRestarter() = default;\r
- virtual void restartAsync() = 0;\r
-};\r
+public:\r
+ struct Deleter\r
+ {\r
+ void operator() (ManagedAudioBufferList* p) const\r
+ {\r
+ if (p != nullptr)\r
+ p->~ManagedAudioBufferList();\r
\r
-struct SystemVol\r
-{\r
- SystemVol (AudioObjectPropertySelector selector) noexcept\r
- : outputDeviceID (kAudioObjectUnknown)\r
+ delete[] reinterpret_cast<std::byte*> (p);\r
+ }\r
+ };\r
+\r
+ using Ref = std::unique_ptr<ManagedAudioBufferList, Deleter>;\r
+\r
+ //==============================================================================\r
+ static Ref create (std::size_t numBuffers)\r
{\r
- addr.mScope = kAudioObjectPropertyScopeGlobal;\r
- addr.mElement = juceAudioObjectPropertyElementMain;\r
- addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;\r
+ static_assert (alignof (ManagedAudioBufferList) <= alignof (std::max_align_t));\r
\r
- if (AudioObjectHasProperty (kAudioObjectSystemObject, &addr))\r
- {\r
- UInt32 deviceIDSize = sizeof (outputDeviceID);\r
- OSStatus status = AudioObjectGetPropertyData (kAudioObjectSystemObject, &addr, 0, nullptr, &deviceIDSize, &outputDeviceID);\r
+ if (std::unique_ptr<std::byte[]> storage { new std::byte[storageSizeForNumBuffers (numBuffers)] })\r
+ return Ref { new (storage.release()) ManagedAudioBufferList (numBuffers) };\r
\r
- if (status == noErr)\r
- {\r
- addr.mElement = juceAudioObjectPropertyElementMain;\r
- addr.mSelector = selector;\r
- addr.mScope = kAudioDevicePropertyScopeOutput;\r
+ return nullptr;\r
+ }\r
\r
- if (! AudioObjectHasProperty (outputDeviceID, &addr))\r
- outputDeviceID = kAudioObjectUnknown;\r
- }\r
- }\r
+ //==============================================================================\r
+ static std::size_t storageSizeForNumBuffers (std::size_t numBuffers) noexcept\r
+ {\r
+ return audioBufferListHeaderSize + (numBuffers * sizeof (::AudioBuffer));\r
}\r
\r
- float getGain() const noexcept\r
+ static std::size_t numBuffersForStorageSize (std::size_t bytes) noexcept\r
{\r
- Float32 gain = 0;\r
+ bytes -= audioBufferListHeaderSize;\r
\r
- if (outputDeviceID != kAudioObjectUnknown)\r
- {\r
- UInt32 size = sizeof (gain);\r
- AudioObjectGetPropertyData (outputDeviceID, &addr, 0, nullptr, &size, &gain);\r
- }\r
+ // storage size ends between to buffers in AudioBufferList\r
+ jassert ((bytes % sizeof (::AudioBuffer)) == 0);\r
\r
- return (float) gain;\r
+ return bytes / sizeof (::AudioBuffer);\r
}\r
\r
- bool setGain (float gain) const noexcept\r
+private:\r
+ // Do not call the base constructor here as this will zero-initialize the first buffer,\r
+ // for which no storage may be available though (when numBuffers == 0).\r
+ explicit ManagedAudioBufferList (std::size_t numBuffers)\r
+ {\r
+ mNumberBuffers = static_cast<UInt32> (numBuffers);\r
+ }\r
+\r
+ static constexpr auto audioBufferListHeaderSize = sizeof (AudioBufferList) - sizeof (::AudioBuffer);\r
+\r
+ JUCE_DECLARE_NON_COPYABLE (ManagedAudioBufferList)\r
+ JUCE_DECLARE_NON_MOVEABLE (ManagedAudioBufferList)\r
+};\r
+\r
+//==============================================================================\r
+struct IgnoreUnused\r
+{\r
+ template <typename... Ts>\r
+ void operator() (Ts&&...) const {}\r
+};\r
+\r
+template <typename T>\r
+static auto getDataPtrAndSize (T& t)\r
+{\r
+ static_assert (std::is_pod_v<T>);\r
+ return std::make_tuple (&t, (UInt32) sizeof (T));\r
+}\r
+\r
+static auto getDataPtrAndSize (ManagedAudioBufferList::Ref& t)\r
+{\r
+ const auto size = t.get() != nullptr\r
+ ? ManagedAudioBufferList::storageSizeForNumBuffers (t->mNumberBuffers)\r
+ : 0;\r
+ return std::make_tuple (t.get(), (UInt32) size);\r
+}\r
+\r
+//==============================================================================\r
+[[nodiscard]] static bool audioObjectHasProperty (AudioObjectID objectID, const AudioObjectPropertyAddress address)\r
+{\r
+ return objectID != kAudioObjectUnknown && AudioObjectHasProperty (objectID, &address);\r
+}\r
+\r
+template <typename T, typename OnError = IgnoreUnused>\r
+[[nodiscard]] static auto audioObjectGetProperty (AudioObjectID objectID,\r
+ const AudioObjectPropertyAddress address,\r
+ OnError&& onError = {})\r
+{\r
+ using Result = std::conditional_t<std::is_same_v<T, AudioBufferList>, ManagedAudioBufferList::Ref, std::optional<T>>;\r
+\r
+ if (! audioObjectHasProperty (objectID, address))\r
+ return Result{};\r
+\r
+ auto result = [&]\r
{\r
- if (outputDeviceID != kAudioObjectUnknown && canSetVolume())\r
+ if constexpr (std::is_same_v<T, AudioBufferList>)\r
{\r
- Float32 newVolume = gain;\r
- UInt32 size = sizeof (newVolume);\r
+ UInt32 size{};\r
\r
- return AudioObjectSetPropertyData (outputDeviceID, &addr, 0, nullptr, size, &newVolume) == noErr;\r
+ if (auto status = AudioObjectGetPropertyDataSize (objectID, &address, 0, nullptr, &size); status != noErr)\r
+ {\r
+ onError (status);\r
+ return Result{};\r
+ }\r
+\r
+ return ManagedAudioBufferList::create (ManagedAudioBufferList::numBuffersForStorageSize (size));\r
}\r
+ else\r
+ {\r
+ return T{};\r
+ }\r
+ }();\r
+\r
+ auto [ptr, size] = getDataPtrAndSize (result);\r
+\r
+ if (size == 0)\r
+ return Result{};\r
+\r
+ if (auto status = AudioObjectGetPropertyData (objectID, &address, 0, nullptr, &size, ptr); status != noErr)\r
+ {\r
+ onError (status);\r
+ return Result{};\r
+ }\r
\r
+ return Result { std::move (result) };\r
+}\r
+\r
+template <typename T, typename OnError = IgnoreUnused>\r
+static bool audioObjectSetProperty (AudioObjectID objectID,\r
+ const AudioObjectPropertyAddress address,\r
+ const T value,\r
+ OnError&& onError = {})\r
+{\r
+ if (! audioObjectHasProperty (objectID, address))\r
+ return false;\r
+\r
+ Boolean isSettable = NO;\r
+ if (auto status = AudioObjectIsPropertySettable (objectID, &address, &isSettable); status != noErr)\r
+ {\r
+ onError (status);\r
return false;\r
}\r
\r
- bool isMuted() const noexcept\r
+ if (! isSettable)\r
+ return false;\r
+\r
+ if (auto status = AudioObjectSetPropertyData (objectID, &address, 0, nullptr, static_cast<UInt32> (sizeof (T)), &value); status != noErr)\r
{\r
- UInt32 muted = 0;\r
+ onError (status);\r
+ return false;\r
+ }\r
\r
- if (outputDeviceID != kAudioObjectUnknown)\r
- {\r
- UInt32 size = sizeof (muted);\r
- AudioObjectGetPropertyData (outputDeviceID, &addr, 0, nullptr, &size, &muted);\r
- }\r
+ return true;\r
+}\r
+\r
+template <typename T, typename OnError = IgnoreUnused>\r
+[[nodiscard]] static std::vector<T> audioObjectGetProperties (AudioObjectID objectID,\r
+ const AudioObjectPropertyAddress address,\r
+ OnError&& onError = {})\r
+{\r
+ if (! audioObjectHasProperty (objectID, address))\r
+ return {};\r
\r
- return muted != 0;\r
+ UInt32 size{};\r
+\r
+ if (auto status = AudioObjectGetPropertyDataSize (objectID, &address, 0, nullptr, &size); status != noErr)\r
+ {\r
+ onError (status);\r
+ return {};\r
}\r
\r
- bool setMuted (bool mute) const noexcept\r
+ // If this is hit, the number of results is not integral, and the following\r
+ // AudioObjectGetPropertyData will probably write past the end of the result buffer.\r
+ jassert ((size % sizeof (T)) == 0);\r
+ std::vector<T> result (size / sizeof (T));\r
+\r
+ if (auto status = AudioObjectGetPropertyData (objectID, &address, 0, nullptr, &size, result.data()); status != noErr)\r
{\r
- if (outputDeviceID != kAudioObjectUnknown && canSetVolume())\r
- {\r
- UInt32 newMute = mute ? 1 : 0;\r
- UInt32 size = sizeof (newMute);\r
+ onError (status);\r
+ return {};\r
+ }\r
\r
- return AudioObjectSetPropertyData (outputDeviceID, &addr, 0, nullptr, size, &newMute) == noErr;\r
- }\r
+ return result;\r
+}\r
\r
- return false;\r
+//==============================================================================\r
+struct AsyncRestarter\r
+{\r
+ virtual ~AsyncRestarter() = default;\r
+ virtual void restartAsync() = 0;\r
+};\r
+\r
+struct SystemVol\r
+{\r
+ explicit SystemVol (AudioObjectPropertySelector selector) noexcept\r
+ : outputDeviceID (audioObjectGetProperty<AudioDeviceID> (kAudioObjectSystemObject, { kAudioHardwarePropertyDefaultOutputDevice,\r
+ kAudioObjectPropertyScopeGlobal,\r
+ juceAudioObjectPropertyElementMain }).value_or (kAudioObjectUnknown)),\r
+ addr { selector, kAudioDevicePropertyScopeOutput, juceAudioObjectPropertyElementMain }\r
+ {}\r
+\r
+ float getGain() const noexcept\r
+ {\r
+ return audioObjectGetProperty<Float32> (outputDeviceID, addr).value_or (0.0f);\r
}\r
\r
-private:\r
- AudioDeviceID outputDeviceID;\r
- AudioObjectPropertyAddress addr;\r
+ bool setGain (float gain) const noexcept\r
+ {\r
+ return audioObjectSetProperty (outputDeviceID, addr, static_cast<Float32> (gain));\r
+ }\r
\r
- bool canSetVolume() const noexcept\r
+ bool isMuted() const noexcept\r
+ {\r
+ return audioObjectGetProperty<UInt32> (outputDeviceID, addr).value_or (0) != 0;\r
+ }\r
+\r
+ bool setMuted (bool mute) const noexcept\r
{\r
- Boolean isSettable = NO;\r
- return AudioObjectIsPropertySettable (outputDeviceID, &addr, &isSettable) == noErr && isSettable;\r
+ return audioObjectSetProperty (outputDeviceID, addr, static_cast<UInt32> (mute ? 1 : 0));\r
}\r
+\r
+private:\r
+ AudioDeviceID outputDeviceID;\r
+ AudioObjectPropertyAddress addr;\r
};\r
\r
JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
class CoreAudioInternal : private Timer,\r
private AsyncUpdater\r
{\r
+private:\r
+ // members with deduced return types need to be defined before they\r
+ // are used, so define it here. decltype doesn't help as you can't\r
+ // capture anything in lambdas inside a decltype context.\r
+ auto err2log() const { return [this] (OSStatus err) { OK (err); }; }\r
+\r
public:\r
- CoreAudioInternal (CoreAudioIODevice& d, AudioDeviceID id, bool input, bool output)\r
+ CoreAudioInternal (CoreAudioIODevice& d, AudioDeviceID id, bool hasInput, bool hasOutput)\r
: owner (d),\r
deviceID (id),\r
- isInputDevice (input),\r
- isOutputDevice (output)\r
+ inStream (hasInput ? new Stream (true, *this, {}) : nullptr),\r
+ outStream (hasOutput ? new Stream (false, *this, {}) : nullptr)\r
{\r
jassert (deviceID != 0);\r
\r
updateDetailsFromDevice();\r
JUCE_COREAUDIOLOG ("Creating CoreAudioInternal\n"\r
- << (isInputDevice ? (" inputDeviceId " + String (deviceID) + "\n") : "")\r
- << (isOutputDevice ? (" outputDeviceId " + String (deviceID) + "\n") : "")\r
+ << (inStream != nullptr ? (" inputDeviceId " + String (deviceID) + "\n") : "")\r
+ << (outStream != nullptr ? (" outputDeviceId " + String (deviceID) + "\n") : "")\r
<< getDeviceDetails().joinIntoString ("\n "));\r
\r
AudioObjectPropertyAddress pa;\r
stop (false);\r
}\r
\r
+ auto getStreams() const { return std::array<Stream*, 2> { { inStream.get(), outStream.get() } }; }\r
+\r
void allocateTempBuffers()\r
{\r
auto tempBufSize = bufferSize + 4;\r
- audioBuffer.calloc ((numInputChans + numOutputChans) * tempBufSize);\r
\r
- tempInputBuffers.calloc (numInputChans + 2);\r
- tempOutputBuffers.calloc (numOutputChans + 2);\r
+ auto streams = getStreams();\r
+ const auto total = std::accumulate (streams.begin(), streams.end(), 0,\r
+ [] (int n, const auto& s) { return n + (s != nullptr ? s->channels : 0); });\r
+ audioBuffer.calloc (total * tempBufSize);\r
\r
- int count = 0;\r
- for (int i = 0; i < numInputChans; ++i) tempInputBuffers[i] = audioBuffer + count++ * tempBufSize;\r
- for (int i = 0; i < numOutputChans; ++i) tempOutputBuffers[i] = audioBuffer + count++ * tempBufSize;\r
+ auto channels = 0;\r
+ for (auto* stream : streams)\r
+ channels += stream != nullptr ? stream->allocateTempBuffers (tempBufSize, channels, audioBuffer) : 0;\r
}\r
\r
struct CallbackDetailsForChannel\r
int dataStrideSamples;\r
};\r
\r
- // returns the number of actual available channels\r
- StringArray getChannelInfo (bool input, Array<CallbackDetailsForChannel>& newChannelInfo) const\r
- {\r
- StringArray newNames;\r
- int chanNum = 0;\r
- UInt32 size;\r
-\r
- AudioObjectPropertyAddress pa;\r
- pa.mSelector = kAudioDevicePropertyStreamConfiguration;\r
- pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
-\r
- if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size)))\r
- {\r
- HeapBlock<AudioBufferList> bufList;\r
- bufList.calloc (size, 1);\r
-\r
- if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, bufList)))\r
- {\r
- const int numStreams = (int) bufList->mNumberBuffers;\r
-\r
- for (int i = 0; i < numStreams; ++i)\r
- {\r
- auto& b = bufList->mBuffers[i];\r
-\r
- for (unsigned int j = 0; j < b.mNumberChannels; ++j)\r
- {\r
- String name;\r
- NSString* nameNSString = nil;\r
- size = sizeof (nameNSString);\r
-\r
- pa.mSelector = kAudioObjectPropertyElementName;\r
- pa.mElement = (AudioObjectPropertyElement) chanNum + 1;\r
-\r
- if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &nameNSString) == noErr)\r
- {\r
- name = nsStringToJuce (nameNSString);\r
- [nameNSString release];\r
- }\r
-\r
- if ((input ? activeInputChans : activeOutputChans) [chanNum])\r
- {\r
- CallbackDetailsForChannel info = { i, (int) j, (int) b.mNumberChannels };\r
- newChannelInfo.add (info);\r
- }\r
-\r
- if (name.isEmpty())\r
- name << (input ? "Input " : "Output ") << (chanNum + 1);\r
-\r
- newNames.add (name);\r
- ++chanNum;\r
- }\r
- }\r
- }\r
- }\r
-\r
- return newNames;\r
- }\r
-\r
Array<double> getSampleRatesFromDevice() const\r
{\r
Array<double> newSampleRates;\r
\r
- AudioObjectPropertyAddress pa;\r
- pa.mScope = kAudioObjectPropertyScopeWildcard;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- pa.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;\r
- UInt32 size = 0;\r
-\r
- if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size)))\r
+ if (auto ranges = audioObjectGetProperties<AudioValueRange> (deviceID,\r
+ { kAudioDevicePropertyAvailableNominalSampleRates,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain },\r
+ err2log()); ! ranges.empty())\r
{\r
- HeapBlock<AudioValueRange> ranges;\r
- ranges.calloc (size, 1);\r
-\r
- if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ranges)))\r
+ for (const auto rate : SampleRateHelpers::getAllSampleRates())\r
{\r
- for (const auto rate : SampleRateHelpers::getAllSampleRates())\r
+ for (auto range = ranges.rbegin(); range != ranges.rend(); ++range)\r
{\r
- for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;)\r
+ if (range->mMinimum - 2 <= rate && rate <= range->mMaximum + 2)\r
{\r
- if (ranges[j].mMinimum - 2 <= rate && rate <= ranges[j].mMaximum + 2)\r
- {\r
- newSampleRates.add (rate);\r
- break;\r
- }\r
+ newSampleRates.add (rate);\r
+ break;\r
}\r
}\r
}\r
{\r
Array<int> newBufferSizes;\r
\r
- AudioObjectPropertyAddress pa;\r
- pa.mScope = kAudioObjectPropertyScopeWildcard;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- pa.mSelector = kAudioDevicePropertyBufferFrameSizeRange;\r
- UInt32 size = 0;\r
-\r
- if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size)))\r
+ if (auto ranges = audioObjectGetProperties<AudioValueRange> (deviceID, { kAudioDevicePropertyBufferFrameSizeRange,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain },\r
+ err2log()); ! ranges.empty())\r
{\r
- HeapBlock<AudioValueRange> ranges;\r
- ranges.calloc (size, 1);\r
+ newBufferSizes.add ((int) (ranges[0].mMinimum + 15) & ~15);\r
\r
- if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ranges)))\r
+ for (int i = 32; i <= 2048; i += 32)\r
{\r
- newBufferSizes.add ((int) (ranges[0].mMinimum + 15) & ~15);\r
-\r
- for (int i = 32; i <= 2048; i += 32)\r
+ for (auto range = ranges.rbegin(); range != ranges.rend(); ++range)\r
{\r
- for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;)\r
+ if (i >= range->mMinimum && i <= range->mMaximum)\r
{\r
- if (i >= ranges[j].mMinimum && i <= ranges[j].mMaximum)\r
- {\r
- newBufferSizes.addIfNotAlreadyThere (i);\r
- break;\r
- }\r
+ newBufferSizes.addIfNotAlreadyThere (i);\r
+ break;\r
}\r
}\r
-\r
- if (bufferSize > 0)\r
- newBufferSizes.addIfNotAlreadyThere (bufferSize);\r
}\r
+\r
+ if (bufferSize > 0)\r
+ newBufferSizes.addIfNotAlreadyThere (bufferSize);\r
}\r
\r
if (newBufferSizes.isEmpty() && bufferSize > 0)\r
return newBufferSizes;\r
}\r
\r
- int getLatencyFromDevice (AudioObjectPropertyScope scope) const\r
- {\r
- UInt32 latency = 0;\r
- UInt32 size = sizeof (latency);\r
- AudioObjectPropertyAddress pa;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- pa.mSelector = kAudioDevicePropertyLatency;\r
- pa.mScope = scope;\r
- AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &latency);\r
-\r
- UInt32 safetyOffset = 0;\r
- size = sizeof (safetyOffset);\r
- pa.mSelector = kAudioDevicePropertySafetyOffset;\r
- AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &safetyOffset);\r
-\r
- return (int) (latency + safetyOffset);\r
- }\r
-\r
- int getBitDepthFromDevice (AudioObjectPropertyScope scope) const\r
- {\r
- AudioObjectPropertyAddress pa;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- pa.mSelector = kAudioStreamPropertyPhysicalFormat;\r
- pa.mScope = scope;\r
-\r
- AudioStreamBasicDescription asbd;\r
- UInt32 size = sizeof (asbd);\r
-\r
- if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &asbd)))\r
- return (int) asbd.mBitsPerChannel;\r
-\r
- return 0;\r
- }\r
-\r
int getFrameSizeFromDevice() const\r
{\r
- AudioObjectPropertyAddress pa;\r
- pa.mScope = kAudioObjectPropertyScopeWildcard;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- pa.mSelector = kAudioDevicePropertyBufferFrameSize;\r
-\r
- UInt32 framesPerBuf = (UInt32) bufferSize;\r
- UInt32 size = sizeof (framesPerBuf);\r
- AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &framesPerBuf);\r
- return (int) framesPerBuf;\r
+ return static_cast<int> (audioObjectGetProperty<UInt32> (deviceID, { kAudioDevicePropertyBufferFrameSize,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain }).value_or (0));\r
}\r
\r
bool isDeviceAlive() const\r
{\r
- AudioObjectPropertyAddress pa;\r
- pa.mScope = kAudioObjectPropertyScopeWildcard;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- pa.mSelector = kAudioDevicePropertyDeviceIsAlive;\r
-\r
- UInt32 isAlive = 0;\r
- UInt32 size = sizeof (isAlive);\r
return deviceID != 0\r
- && OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &isAlive))\r
- && isAlive != 0;\r
+ && audioObjectGetProperty<UInt32> (deviceID, { kAudioDevicePropertyDeviceIsAlive,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain }, err2log()).value_or (0) != 0;\r
}\r
\r
- bool updateDetailsFromDevice()\r
+ bool updateDetailsFromDevice (const BigInteger& activeIns, const BigInteger& activeOuts)\r
{\r
stopTimer();\r
\r
auto newBufferSizes = getBufferSizesFromDevice();\r
auto newSampleRates = getSampleRatesFromDevice();\r
\r
- auto newInputLatency = getLatencyFromDevice (kAudioDevicePropertyScopeInput);\r
- auto newOutputLatency = getLatencyFromDevice (kAudioDevicePropertyScopeOutput);\r
-\r
- Array<CallbackDetailsForChannel> newInChans, newOutChans;\r
- auto newInNames = isInputDevice ? getChannelInfo (true, newInChans) : StringArray();\r
- auto newOutNames = isOutputDevice ? getChannelInfo (false, newOutChans) : StringArray();\r
+ auto newInput = rawToUniquePtr (inStream != nullptr ? new Stream (true, *this, activeIns) : nullptr);\r
+ auto newOutput = rawToUniquePtr (outStream != nullptr ? new Stream (false, *this, activeOuts) : nullptr);\r
\r
- auto inputBitDepth = isInputDevice ? getBitDepthFromDevice (kAudioDevicePropertyScopeInput) : 0;\r
- auto outputBitDepth = isOutputDevice ? getBitDepthFromDevice (kAudioDevicePropertyScopeOutput) : 0;\r
- auto newBitDepth = jmax (inputBitDepth, outputBitDepth);\r
+ auto newBitDepth = jmax (getBitDepth (newInput), getBitDepth (newOutput));\r
\r
{\r
const ScopedLock sl (callbackLock);\r
if (newSampleRate > 0)\r
sampleRate = newSampleRate;\r
\r
- inputLatency = newInputLatency;\r
- outputLatency = newOutputLatency;\r
bufferSize = newBufferSize;\r
\r
sampleRates.swapWith (newSampleRates);\r
bufferSizes.swapWith (newBufferSizes);\r
\r
- inChanNames.swapWith (newInNames);\r
- outChanNames.swapWith (newOutNames);\r
-\r
- inputChannelInfo.swapWith (newInChans);\r
- outputChannelInfo.swapWith (newOutChans);\r
-\r
- numInputChans = inputChannelInfo.size();\r
- numOutputChans = outputChannelInfo.size();\r
+ std::swap (inStream, newInput);\r
+ std::swap (outStream, newOutput);\r
\r
allocateTempBuffers();\r
}\r
return true;\r
}\r
\r
+ bool updateDetailsFromDevice()\r
+ {\r
+ return updateDetailsFromDevice (getActiveChannels (inStream), getActiveChannels (outStream));\r
+ }\r
+\r
StringArray getDeviceDetails()\r
{\r
StringArray result;\r
result.add (availableBufferSizes);\r
result.add ("Buffer size: " + String (bufferSize));\r
result.add ("Bit depth: " + String (bitDepth));\r
- result.add ("Input latency: " + String (inputLatency));\r
- result.add ("Output latency: " + String (outputLatency));\r
- result.add ("Input channel names: " + inChanNames.joinIntoString (" "));\r
- result.add ("Output channel names: " + outChanNames.joinIntoString (" "));\r
+ result.add ("Input latency: " + String (getLatency (inStream)));\r
+ result.add ("Output latency: " + String (getLatency (outStream)));\r
+ result.add ("Input channel names: " + getChannelNames (inStream));\r
+ result.add ("Output channel names: " + getChannelNames (outStream));\r
\r
return result;\r
}\r
\r
+ static auto getScope (bool input)\r
+ {\r
+ return input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
+ }\r
+\r
//==============================================================================\r
StringArray getSources (bool input)\r
{\r
StringArray s;\r
- HeapBlock<OSType> types;\r
- auto num = getAllDataSourcesForDevice (deviceID, types);\r
+ auto types = audioObjectGetProperties<OSType> (deviceID, { kAudioDevicePropertyDataSources,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain });\r
\r
- for (int i = 0; i < num; ++i)\r
+ for (auto type : types)\r
{\r
AudioValueTranslation avt;\r
char buffer[256];\r
\r
- avt.mInputData = &(types[i]);\r
+ avt.mInputData = &type;\r
avt.mInputDataSize = sizeof (UInt32);\r
avt.mOutputData = buffer;\r
avt.mOutputDataSize = 256;\r
\r
AudioObjectPropertyAddress pa;\r
pa.mSelector = kAudioDevicePropertyDataSourceNameForID;\r
- pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
+ pa.mScope = getScope (input);\r
pa.mElement = juceAudioObjectPropertyElementMain;\r
\r
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &transSize, &avt)))\r
\r
int getCurrentSourceIndex (bool input) const\r
{\r
- OSType currentSourceID = 0;\r
- UInt32 size = sizeof (currentSourceID);\r
- int result = -1;\r
-\r
- AudioObjectPropertyAddress pa;\r
- pa.mSelector = kAudioDevicePropertyDataSource;\r
- pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
-\r
if (deviceID != 0)\r
{\r
- if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ¤tSourceID)))\r
+ if (auto currentSourceID = audioObjectGetProperty<OSType> (deviceID, { kAudioDevicePropertyDataSource,\r
+ getScope (input),\r
+ juceAudioObjectPropertyElementMain }, err2log()))\r
{\r
- HeapBlock<OSType> types;\r
- auto num = getAllDataSourcesForDevice (deviceID, types);\r
+ auto types = audioObjectGetProperties<OSType> (deviceID, { kAudioDevicePropertyDataSources,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain });\r
\r
- for (int i = 0; i < num; ++i)\r
- {\r
- if (types[num] == currentSourceID)\r
- {\r
- result = i;\r
- break;\r
- }\r
- }\r
+ if (auto it = std::find (types.begin(), types.end(), *currentSourceID); it != types.end())\r
+ return static_cast<int> (std::distance (types.begin(), it));\r
}\r
}\r
\r
- return result;\r
+ return -1;\r
}\r
\r
void setCurrentSourceIndex (int index, bool input)\r
{\r
if (deviceID != 0)\r
{\r
- HeapBlock<OSType> types;\r
- auto num = getAllDataSourcesForDevice (deviceID, types);\r
+ auto types = audioObjectGetProperties<OSType> (deviceID, { kAudioDevicePropertyDataSources,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain });\r
\r
- if (isPositiveAndBelow (index, num))\r
+ if (isPositiveAndBelow (index, static_cast<int> (types.size())))\r
{\r
- AudioObjectPropertyAddress pa;\r
- pa.mSelector = kAudioDevicePropertyDataSource;\r
- pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
-\r
- OSType typeId = types[index];\r
-\r
- OK (AudioObjectSetPropertyData (deviceID, &pa, 0, nullptr, sizeof (typeId), &typeId));\r
+ audioObjectSetProperty<OSType> (deviceID, { kAudioDevicePropertyDataSource,\r
+ getScope (input),\r
+ juceAudioObjectPropertyElementMain },\r
+ types[static_cast<std::size_t> (index)], err2log());\r
}\r
}\r
}\r
\r
double getNominalSampleRate() const\r
{\r
- AudioObjectPropertyAddress pa;\r
- pa.mSelector = kAudioDevicePropertyNominalSampleRate;\r
- pa.mScope = kAudioObjectPropertyScopeGlobal;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- Float64 sr = 0;\r
- UInt32 size = (UInt32) sizeof (sr);\r
- return OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &sr)) ? (double) sr : 0.0;\r
+ return static_cast<double> (audioObjectGetProperty <Float64> (deviceID, { kAudioDevicePropertyNominalSampleRate,\r
+ kAudioObjectPropertyScopeGlobal,\r
+ juceAudioObjectPropertyElementMain },\r
+ err2log()).value_or (0.0));\r
}\r
\r
bool setNominalSampleRate (double newSampleRate) const\r
if (std::abs (getNominalSampleRate() - newSampleRate) < 1.0)\r
return true;\r
\r
- AudioObjectPropertyAddress pa;\r
- pa.mSelector = kAudioDevicePropertyNominalSampleRate;\r
- pa.mScope = kAudioObjectPropertyScopeGlobal;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- Float64 sr = newSampleRate;\r
- return OK (AudioObjectSetPropertyData (deviceID, &pa, 0, nullptr, sizeof (sr), &sr));\r
+ return audioObjectSetProperty (deviceID, { kAudioDevicePropertyNominalSampleRate,\r
+ kAudioObjectPropertyScopeGlobal,\r
+ juceAudioObjectPropertyElementMain },\r
+ static_cast<Float64> (newSampleRate), err2log());\r
}\r
\r
//==============================================================================\r
- String reopen (const BigInteger& inputChannels,\r
- const BigInteger& outputChannels,\r
- double newSampleRate, int bufferSizeSamples)\r
+ String reopen (const BigInteger& ins, const BigInteger& outs, double newSampleRate, int bufferSizeSamples)\r
{\r
- String error;\r
callbacksAllowed = false;\r
+ const ScopeGuard scope { [&] { callbacksAllowed = true; } };\r
+\r
stopTimer();\r
\r
stop (false);\r
\r
- updateDetailsFromDevice();\r
-\r
- activeInputChans = inputChannels;\r
- activeInputChans.setRange (inChanNames.size(),\r
- activeInputChans.getHighestBit() + 1 - inChanNames.size(),\r
- false);\r
-\r
- activeOutputChans = outputChannels;\r
- activeOutputChans.setRange (outChanNames.size(),\r
- activeOutputChans.getHighestBit() + 1 - outChanNames.size(),\r
- false);\r
-\r
- numInputChans = activeInputChans.countNumberOfSetBits();\r
- numOutputChans = activeOutputChans.countNumberOfSetBits();\r
-\r
if (! setNominalSampleRate (newSampleRate))\r
{\r
- updateDetailsFromDevice();\r
- error = "Couldn't change sample rate";\r
+ updateDetailsFromDevice (ins, outs);\r
+ return "Couldn't change sample rate";\r
}\r
- else\r
+\r
+ if (! audioObjectSetProperty (deviceID, { kAudioDevicePropertyBufferFrameSize,\r
+ kAudioObjectPropertyScopeGlobal,\r
+ juceAudioObjectPropertyElementMain },\r
+ static_cast<UInt32> (bufferSizeSamples), err2log()))\r
{\r
- // change buffer size\r
- AudioObjectPropertyAddress pa;\r
- pa.mSelector = kAudioDevicePropertyBufferFrameSize;\r
- pa.mScope = kAudioObjectPropertyScopeGlobal;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- UInt32 framesPerBuf = (UInt32) bufferSizeSamples;\r
+ updateDetailsFromDevice (ins, outs);\r
+ return "Couldn't change buffer size";\r
+ }\r
\r
- if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, nullptr, sizeof (framesPerBuf), &framesPerBuf)))\r
- {\r
- updateDetailsFromDevice();\r
- error = "Couldn't change buffer size";\r
- }\r
- else\r
- {\r
- // Annoyingly, after changing the rate and buffer size, some devices fail to\r
- // correctly report their new settings until some random time in the future, so\r
- // after calling updateDetailsFromDevice, we need to manually bodge these values\r
- // to make sure we're using the correct numbers..\r
- updateDetailsFromDevice();\r
- sampleRate = newSampleRate;\r
- bufferSize = bufferSizeSamples;\r
+ // Annoyingly, after changing the rate and buffer size, some devices fail to\r
+ // correctly report their new settings until some random time in the future, so\r
+ // after calling updateDetailsFromDevice, we need to manually bodge these values\r
+ // to make sure we're using the correct numbers..\r
+ updateDetailsFromDevice (ins, outs);\r
+ sampleRate = newSampleRate;\r
+ bufferSize = bufferSizeSamples;\r
\r
- if (sampleRates.size() == 0)\r
- error = "Device has no available sample-rates";\r
- else if (bufferSizes.size() == 0)\r
- error = "Device has no available buffer-sizes";\r
- }\r
- }\r
+ if (sampleRates.size() == 0)\r
+ return "Device has no available sample-rates";\r
+\r
+ if (bufferSizes.size() == 0)\r
+ return "Device has no available buffer-sizes";\r
\r
- callbacksAllowed = true;\r
- return error;\r
+ return {};\r
}\r
\r
bool start (AudioIODeviceCallback* callbackToNotify)\r
callback->audioDeviceAboutToStart (&owner);\r
}\r
\r
- if (! started)\r
+ for (auto* stream : getStreams())\r
+ if (stream != nullptr)\r
+ stream->previousSampleTime = invalidSampleTime;\r
+\r
+ owner.hadDiscontinuity = false;\r
+\r
+ if (scopedProcID.get() == nullptr && deviceID != 0)\r
{\r
- if (deviceID != 0)\r
+ scopedProcID = [&self = *this,\r
+ &lock = callbackLock,\r
+ nextProcID = ScopedAudioDeviceIOProcID { *this, deviceID, audioIOProc },\r
+ deviceID = deviceID]() mutable -> ScopedAudioDeviceIOProcID\r
{\r
- if (OK (AudioDeviceCreateIOProcID (deviceID, audioIOProc, this, &audioProcID)))\r
+ // It *looks* like AudioDeviceStart may start the audio callback running, and then\r
+ // immediately lock an internal mutex.\r
+ // The same mutex is locked before calling the audioIOProc.\r
+ // If we get very unlucky, then we can end up with thread A taking the callbackLock\r
+ // and calling AudioDeviceStart, followed by thread B taking the CoreAudio lock\r
+ // and calling into audioIOProc, which waits on the callbackLock. When thread A\r
+ // continues it attempts to take the CoreAudio lock, and the program deadlocks.\r
+\r
+ if (auto* procID = nextProcID.get())\r
{\r
- if (OK (AudioDeviceStart (deviceID, audioProcID)))\r
- {\r
- started = true;\r
- }\r
- else\r
- {\r
- OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID));\r
- audioProcID = {};\r
- }\r
+ const ScopedUnlock su (lock);\r
+\r
+ if (self.OK (AudioDeviceStart (deviceID, procID)))\r
+ return std::move (nextProcID);\r
}\r
- }\r
+\r
+ return {};\r
+ }();\r
}\r
\r
- playing = started && callback != nullptr;\r
+ playing = scopedProcID.get() != nullptr && callback != nullptr;\r
\r
- return started;\r
+ return scopedProcID.get() != nullptr;\r
}\r
\r
AudioIODeviceCallback* stop (bool leaveInterruptRunning)\r
\r
auto result = std::exchange (callback, nullptr);\r
\r
- if (started && (deviceID != 0) && ! leaveInterruptRunning)\r
+ if (scopedProcID.get() != nullptr && (deviceID != 0) && ! leaveInterruptRunning)\r
{\r
audioDeviceStopPending = true;\r
\r
Thread::sleep (50);\r
}\r
\r
- OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID));\r
- audioProcID = {};\r
- started = false;\r
+ scopedProcID = {};\r
playing = false;\r
}\r
\r
double getSampleRate() const { return sampleRate; }\r
int getBufferSize() const { return bufferSize; }\r
\r
- void audioCallback (const AudioTimeStamp* timeStamp,\r
+ void audioCallback (const AudioTimeStamp* inputTimestamp,\r
+ const AudioTimeStamp* outputTimestamp,\r
const AudioBufferList* inInputData,\r
AudioBufferList* outOutputData)\r
{\r
\r
if (audioDeviceStopPending)\r
{\r
- if (OK (AudioDeviceStop (deviceID, audioProcID)))\r
+ if (OK (AudioDeviceStop (deviceID, scopedProcID.get())))\r
audioDeviceStopPending = false;\r
\r
return;\r
}\r
\r
+ const auto numInputChans = getChannels (inStream);\r
+ const auto numOutputChans = getChannels (outStream);\r
+\r
if (callback != nullptr)\r
{\r
for (int i = numInputChans; --i >= 0;)\r
{\r
- auto& info = inputChannelInfo.getReference(i);\r
- auto dest = tempInputBuffers[i];\r
+ auto& info = inStream->channelInfo.getReference (i);\r
+ auto dest = inStream->tempBuffers[i];\r
auto src = ((const float*) inInputData->mBuffers[info.streamNum].mData) + info.dataOffsetSamples;\r
auto stride = info.dataStrideSamples;\r
\r
}\r
}\r
\r
+ for (auto* stream : getStreams())\r
+ if (stream != nullptr)\r
+ owner.hadDiscontinuity |= stream->checkTimestampsForDiscontinuity (stream == inStream.get() ? inputTimestamp\r
+ : outputTimestamp);\r
+\r
+ const auto* timeStamp = numOutputChans > 0 ? outputTimestamp : inputTimestamp;\r
const auto nanos = timeStamp != nullptr ? timeConversions.hostTimeToNanos (timeStamp->mHostTime) : 0;\r
\r
- callback->audioDeviceIOCallbackWithContext (const_cast<const float**> (tempInputBuffers.get()),\r
- numInputChans,\r
- tempOutputBuffers,\r
- numOutputChans,\r
+ callback->audioDeviceIOCallbackWithContext (getTempBuffers (inStream), numInputChans,\r
+ getTempBuffers (outStream), numOutputChans,\r
bufferSize,\r
{ timeStamp != nullptr ? &nanos : nullptr });\r
\r
for (int i = numOutputChans; --i >= 0;)\r
{\r
- auto& info = outputChannelInfo.getReference (i);\r
- auto src = tempOutputBuffers[i];\r
+ auto& info = outStream->channelInfo.getReference (i);\r
+ auto src = outStream->tempBuffers[i];\r
auto dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) + info.dataOffsetSamples;\r
auto stride = info.dataStrideSamples;\r
\r
zeromem (outOutputData->mBuffers[i].mData,\r
outOutputData->mBuffers[i].mDataByteSize);\r
}\r
+\r
+ for (auto* stream : getStreams())\r
+ if (stream != nullptr)\r
+ stream->previousSampleTime += static_cast<Float64> (bufferSize);\r
}\r
\r
// called by callbacks (possibly off the main thread)\r
bool isPlaying() const { return playing.load(); }\r
\r
//==============================================================================\r
+ struct Stream\r
+ {\r
+ Stream (bool isInput, CoreAudioInternal& parent, const BigInteger& activeRequested)\r
+ : input (isInput),\r
+ latency (getLatencyFromDevice (isInput, parent)),\r
+ bitDepth (getBitDepthFromDevice (isInput, parent)),\r
+ chanNames (getChannelNames (isInput, parent)),\r
+ activeChans ([&activeRequested, clearFrom = chanNames.size()]\r
+ {\r
+ auto result = activeRequested;\r
+ result.setRange (clearFrom, result.getHighestBit() + 1 - clearFrom, false);\r
+ return result;\r
+ }()),\r
+ channelInfo (getChannelInfos (isInput, parent, activeChans)),\r
+ channels (static_cast<int> (channelInfo.size()))\r
+ {}\r
+\r
+ int allocateTempBuffers (int tempBufSize, int channelCount, HeapBlock<float>& buffer)\r
+ {\r
+ tempBuffers.calloc (channels + 2);\r
+\r
+ for (int i = 0; i < channels; ++i)\r
+ tempBuffers[i] = buffer + channelCount++ * tempBufSize;\r
+\r
+ return channels;\r
+ }\r
+\r
+ template <typename Visitor>\r
+ static auto visitChannels (bool isInput, CoreAudioInternal& parent, Visitor&& visitor)\r
+ {\r
+ struct Args { int stream, channelIdx, chanNum, streamChannels; };\r
+ using VisitorResultType = typename std::invoke_result_t<Visitor, const Args&>::value_type;\r
+ Array<VisitorResultType> result;\r
+ int chanNum = 0;\r
+\r
+ if (auto bufList = audioObjectGetProperty<AudioBufferList> (parent.deviceID, { kAudioDevicePropertyStreamConfiguration,\r
+ getScope (isInput),\r
+ juceAudioObjectPropertyElementMain }, parent.err2log()))\r
+ {\r
+ const int numStreams = static_cast<int> (bufList->mNumberBuffers);\r
+\r
+ for (int i = 0; i < numStreams; ++i)\r
+ {\r
+ auto& b = bufList->mBuffers[i];\r
+\r
+ for (unsigned int j = 0; j < b.mNumberChannels; ++j)\r
+ {\r
+ // Passing an anonymous struct ensures that callback can't confuse the argument order\r
+ if (auto opt = visitor (Args { i, static_cast<int> (j), chanNum++, static_cast<int> (b.mNumberChannels) }))\r
+ result.add (std::move (*opt));\r
+ }\r
+ }\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ static Array<CallbackDetailsForChannel> getChannelInfos (bool isInput, CoreAudioInternal& parent, const BigInteger& active)\r
+ {\r
+ return visitChannels (isInput, parent,\r
+ [&] (const auto& args) -> std::optional<CallbackDetailsForChannel>\r
+ {\r
+ if (! active[args.chanNum])\r
+ return {};\r
+\r
+ return CallbackDetailsForChannel { args.stream, args.channelIdx, args.streamChannels };\r
+ });\r
+ }\r
+\r
+ static StringArray getChannelNames (bool isInput, CoreAudioInternal& parent)\r
+ {\r
+ auto names = visitChannels (isInput, parent,\r
+ [&] (const auto& args) -> std::optional<String>\r
+ {\r
+ String name;\r
+ const auto element = static_cast<AudioObjectPropertyElement> (args.chanNum + 1);\r
+\r
+ if (auto nameNSString = audioObjectGetProperty<NSString*> (parent.deviceID, { kAudioObjectPropertyElementName,\r
+ getScope (isInput),\r
+ element }).value_or (nullptr))\r
+ {\r
+ name = nsStringToJuce (nameNSString);\r
+ [nameNSString release];\r
+ }\r
+\r
+ if (name.isEmpty())\r
+ name << (isInput ? "Input " : "Output ") << (args.chanNum + 1);\r
+\r
+ return name;\r
+ });\r
+\r
+ return { names };\r
+ }\r
+\r
+ static int getBitDepthFromDevice (bool isInput, CoreAudioInternal& parent)\r
+ {\r
+ return static_cast<int> (audioObjectGetProperty<AudioStreamBasicDescription> (parent.deviceID, { kAudioStreamPropertyPhysicalFormat,\r
+ getScope (isInput),\r
+ juceAudioObjectPropertyElementMain }, parent.err2log())\r
+ .value_or (AudioStreamBasicDescription{}).mBitsPerChannel);\r
+ }\r
+\r
+ static int getLatencyFromDevice (bool isInput, CoreAudioInternal& parent)\r
+ {\r
+ const auto scope = getScope (isInput);\r
+\r
+ const auto deviceLatency = audioObjectGetProperty<UInt32> (parent.deviceID, { kAudioDevicePropertyLatency,\r
+ scope,\r
+ juceAudioObjectPropertyElementMain }).value_or (0);\r
+\r
+ const auto safetyOffset = audioObjectGetProperty<UInt32> (parent.deviceID, { kAudioDevicePropertySafetyOffset,\r
+ scope,\r
+ juceAudioObjectPropertyElementMain }).value_or (0);\r
+\r
+ const auto framesInBuffer = audioObjectGetProperty<UInt32> (parent.deviceID, { kAudioDevicePropertyBufferFrameSize,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain }).value_or (0);\r
+\r
+ UInt32 streamLatency = 0;\r
+\r
+ if (auto streams = audioObjectGetProperties<AudioStreamID> (parent.deviceID, { kAudioDevicePropertyStreams,\r
+ scope,\r
+ juceAudioObjectPropertyElementMain }); ! streams.empty())\r
+ streamLatency = audioObjectGetProperty<UInt32> (streams.front(), { kAudioStreamPropertyLatency,\r
+ scope,\r
+ juceAudioObjectPropertyElementMain }).value_or (0);\r
+\r
+ return static_cast<int> (deviceLatency + safetyOffset + framesInBuffer + streamLatency);\r
+ }\r
+\r
+ bool checkTimestampsForDiscontinuity (const AudioTimeStamp* timestamp) noexcept\r
+ {\r
+ if (channels > 0)\r
+ {\r
+ jassert (timestamp == nullptr || (((timestamp->mFlags & kAudioTimeStampSampleTimeValid) != 0)\r
+ && ((timestamp->mFlags & kAudioTimeStampHostTimeValid) != 0)));\r
+\r
+ if (previousSampleTime == invalidSampleTime)\r
+ previousSampleTime = timestamp != nullptr ? timestamp->mSampleTime : 0.0;\r
+\r
+ if (timestamp != nullptr && std::fabs (previousSampleTime - timestamp->mSampleTime) >= 1.0)\r
+ {\r
+ previousSampleTime = timestamp->mSampleTime;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //==============================================================================\r
+ const bool input;\r
+ const int latency;\r
+ const int bitDepth;\r
+ const StringArray chanNames;\r
+ const BigInteger activeChans;\r
+ const Array<CallbackDetailsForChannel> channelInfo;\r
+ const int channels = 0;\r
+ Float64 previousSampleTime;\r
+\r
+ HeapBlock<float*> tempBuffers;\r
+\r
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Stream)\r
+ };\r
+\r
+ template <typename Callback>\r
+ static auto getWithDefault (const std::unique_ptr<Stream>& ptr, Callback&& callback)\r
+ {\r
+ return ptr != nullptr ? callback (*ptr) : decltype (callback (*ptr)) {};\r
+ }\r
+\r
+ template <typename Value>\r
+ static auto getWithDefault (const std::unique_ptr<Stream>& ptr, Value (Stream::* member))\r
+ {\r
+ return getWithDefault (ptr, [&] (Stream& s) { return s.*member; });\r
+ }\r
+\r
+ static int getLatency (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::latency); }\r
+ static int getBitDepth (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::bitDepth); }\r
+ static int getChannels (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::channels); }\r
+ static int getNumChannelNames (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::chanNames).size(); }\r
+ static String getChannelNames (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::chanNames).joinIntoString (" "); }\r
+ static BigInteger getActiveChannels (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::activeChans); }\r
+ static float** getTempBuffers (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, [] (auto& s) { return s.tempBuffers.get(); }); }\r
+\r
+ //==============================================================================\r
+ static constexpr Float64 invalidSampleTime = std::numeric_limits<Float64>::max();\r
+\r
CoreAudioIODevice& owner;\r
- int inputLatency = 0;\r
- int outputLatency = 0;\r
int bitDepth = 32;\r
int xruns = 0;\r
- BigInteger activeInputChans, activeOutputChans;\r
- StringArray inChanNames, outChanNames;\r
Array<double> sampleRates;\r
Array<int> bufferSizes;\r
- AudioDeviceIOProcID audioProcID = {};\r
+ AudioDeviceID deviceID;\r
+ std::unique_ptr<Stream> inStream, outStream;\r
+\r
+private:\r
+ class ScopedAudioDeviceIOProcID\r
+ {\r
+ public:\r
+ ScopedAudioDeviceIOProcID() = default;\r
+\r
+ ScopedAudioDeviceIOProcID (CoreAudioInternal& coreAudio, AudioDeviceID d, AudioDeviceIOProc audioIOProc)\r
+ : deviceID (d)\r
+ {\r
+ if (! coreAudio.OK (AudioDeviceCreateIOProcID (deviceID, audioIOProc, &coreAudio, &proc)))\r
+ proc = {};\r
+ }\r
+\r
+ ~ScopedAudioDeviceIOProcID() noexcept\r
+ {\r
+ if (proc != AudioDeviceIOProcID{})\r
+ AudioDeviceDestroyIOProcID (deviceID, proc);\r
+ }\r
+\r
+ ScopedAudioDeviceIOProcID (ScopedAudioDeviceIOProcID&& other) noexcept\r
+ {\r
+ swap (other);\r
+ }\r
+\r
+ ScopedAudioDeviceIOProcID& operator= (ScopedAudioDeviceIOProcID&& other) noexcept\r
+ {\r
+ ScopedAudioDeviceIOProcID { std::move (other) }.swap (*this);\r
+ return *this;\r
+ }\r
+\r
+ AudioDeviceIOProcID get() const { return proc; }\r
+\r
+ private:\r
+ void swap (ScopedAudioDeviceIOProcID& other) noexcept\r
+ {\r
+ std::swap (other.deviceID, deviceID);\r
+ std::swap (other.proc, proc);\r
+ }\r
\r
-private:\r
+ AudioDeviceID deviceID = {};\r
+ AudioDeviceIOProcID proc = {};\r
+ };\r
+\r
+ //==============================================================================\r
+ ScopedAudioDeviceIOProcID scopedProcID;\r
CoreAudioTimeConversions timeConversions;\r
AudioIODeviceCallback* callback = nullptr;\r
CriticalSection callbackLock;\r
- AudioDeviceID deviceID;\r
- bool started = false, audioDeviceStopPending = false;\r
+ bool audioDeviceStopPending = false;\r
std::atomic<bool> playing { false };\r
double sampleRate = 0;\r
int bufferSize = 0;\r
HeapBlock<float> audioBuffer;\r
- int numInputChans = 0;\r
- int numOutputChans = 0;\r
Atomic<int> callbacksAllowed { 1 };\r
- const bool isInputDevice, isOutputDevice;\r
-\r
- Array<CallbackDetailsForChannel> inputChannelInfo, outputChannelInfo;\r
- HeapBlock<float*> tempInputBuffers, tempOutputBuffers;\r
\r
//==============================================================================\r
void timerCallback() override\r
}\r
\r
static OSStatus audioIOProc (AudioDeviceID /*inDevice*/,\r
- const AudioTimeStamp* inNow,\r
+ [[maybe_unused]] const AudioTimeStamp* inNow,\r
const AudioBufferList* inInputData,\r
- const AudioTimeStamp* /*inInputTime*/,\r
+ const AudioTimeStamp* inInputTime,\r
AudioBufferList* outOutputData,\r
- const AudioTimeStamp* /*inOutputTime*/,\r
+ const AudioTimeStamp* inOutputTime,\r
void* device)\r
{\r
- static_cast<CoreAudioInternal*> (device)->audioCallback (inNow, inInputData, outOutputData);\r
+ static_cast<CoreAudioInternal*> (device)->audioCallback (inInputTime, inOutputTime, inInputData, outOutputData);\r
return noErr;\r
}\r
\r
}\r
\r
//==============================================================================\r
- static int getAllDataSourcesForDevice (AudioDeviceID deviceID, HeapBlock<OSType>& types)\r
- {\r
- AudioObjectPropertyAddress pa;\r
- pa.mSelector = kAudioDevicePropertyDataSources;\r
- pa.mScope = kAudioObjectPropertyScopeWildcard;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
- UInt32 size = 0;\r
-\r
- if (deviceID != 0\r
- && AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size) == noErr)\r
- {\r
- types.calloc (size, 1);\r
-\r
- if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, types) == noErr)\r
- return size / (int) sizeof (OSType);\r
- }\r
-\r
- return 0;\r
- }\r
-\r
bool OK (const OSStatus errorCode) const\r
{\r
if (errorCode == noErr)\r
AudioObjectRemovePropertyListener (kAudioObjectSystemObject, &pa, hardwareListenerProc, internal.get());\r
}\r
\r
- StringArray getOutputChannelNames() override { return internal->outChanNames; }\r
- StringArray getInputChannelNames() override { return internal->inChanNames; }\r
+ StringArray getOutputChannelNames() override { return internal->outStream != nullptr ? internal->outStream->chanNames : StringArray(); }\r
+ StringArray getInputChannelNames() override { return internal->inStream != nullptr ? internal->inStream ->chanNames : StringArray(); }\r
\r
bool isOpen() override { return isOpen_; }\r
\r
int getCurrentBufferSizeSamples() override { return internal->getBufferSize(); }\r
int getXRunCount() const noexcept override { return internal->xruns; }\r
\r
+ int getIndexOfDevice (bool asInput) const { return asInput ? inputIndex : outputIndex; }\r
+\r
int getDefaultBufferSize() override\r
{\r
int best = 0;\r
\r
for (int i = 0; best < 512 && i < internal->bufferSizes.size(); ++i)\r
- best = internal->bufferSizes.getUnchecked(i);\r
+ best = internal->bufferSizes.getUnchecked (i);\r
\r
if (best == 0)\r
best = 512;\r
internal->stop (false);\r
}\r
\r
- BigInteger getActiveOutputChannels() const override { return internal->activeOutputChans; }\r
- BigInteger getActiveInputChannels() const override { return internal->activeInputChans; }\r
-\r
- int getOutputLatencyInSamples() override\r
- {\r
- // this seems like a good guess at getting the latency right - comparing\r
- // this with a round-trip measurement, it gets it to within a few millisecs\r
- // for the built-in mac soundcard\r
- return internal->outputLatency;\r
- }\r
-\r
- int getInputLatencyInSamples() override\r
- {\r
- return internal->inputLatency;\r
- }\r
+ BigInteger getActiveOutputChannels() const override { return CoreAudioInternal::getActiveChannels (internal->outStream); }\r
+ BigInteger getActiveInputChannels() const override { return CoreAudioInternal::getActiveChannels (internal->inStream); }\r
+ int getOutputLatencyInSamples() override { return CoreAudioInternal::getLatency (internal->outStream); }\r
+ int getInputLatencyInSamples() override { return CoreAudioInternal::getLatency (internal->inStream); }\r
\r
void start (AudioIODeviceCallback* callback) override\r
{\r
\r
WeakReference<CoreAudioIODeviceType> deviceType;\r
int inputIndex, outputIndex;\r
+ bool hadDiscontinuity;\r
\r
private:\r
std::unique_ptr<CoreAudioInternal> internal;\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreAudioIODevice)\r
};\r
\r
+\r
//==============================================================================\r
class AudioIODeviceCombiner : public AudioIODevice,\r
private AsyncRestarter,\r
- private Thread,\r
private Timer\r
{\r
public:\r
- AudioIODeviceCombiner (const String& deviceName, CoreAudioIODeviceType* deviceType)\r
+ AudioIODeviceCombiner (const String& deviceName, CoreAudioIODeviceType* deviceType,\r
+ std::unique_ptr<CoreAudioIODevice>&& inputDevice,\r
+ std::unique_ptr<CoreAudioIODevice>&& outputDevice)\r
: AudioIODevice (deviceName, "CoreAudio"),\r
- Thread (deviceName),\r
- owner (deviceType)\r
+ owner (deviceType),\r
+ currentSampleRate (inputDevice->getCurrentSampleRate()),\r
+ currentBufferSize (inputDevice->getCurrentBufferSizeSamples()),\r
+ inputWrapper (*this, std::move (inputDevice), true),\r
+ outputWrapper (*this, std::move (outputDevice), false)\r
{\r
+ if (getAvailableSampleRates().isEmpty())\r
+ lastError = TRANS("The input and output devices don't share a common sample rate!");\r
}\r
\r
~AudioIODeviceCombiner() override\r
{\r
close();\r
- devices.clear();\r
- }\r
-\r
- void addDevice (std::unique_ptr<CoreAudioIODevice> device, bool useInputs, bool useOutputs)\r
- {\r
- jassert (device != nullptr);\r
- jassert (! isOpen());\r
- jassert (! device->isOpen());\r
- auto* devicePtr = device.get();\r
-\r
- devices.add (std::make_unique<DeviceWrapper> (*this, std::move (device), useInputs, useOutputs));\r
-\r
- if (currentSampleRate == 0)\r
- currentSampleRate = devicePtr->getCurrentSampleRate();\r
-\r
- if (currentBufferSize == 0)\r
- currentBufferSize = devicePtr->getCurrentBufferSizeSamples();\r
- }\r
-\r
- Array<AudioIODevice*> getDevices() const\r
- {\r
- Array<AudioIODevice*> devs;\r
-\r
- for (auto* d : devices)\r
- devs.add (d->device.get());\r
-\r
- return devs;\r
- }\r
-\r
- StringArray getOutputChannelNames() override\r
- {\r
- StringArray names;\r
-\r
- for (auto* d : devices)\r
- names.addArray (d->getOutputChannelNames());\r
-\r
- names.appendNumbersToDuplicates (false, true);\r
- return names;\r
}\r
\r
- StringArray getInputChannelNames() override\r
- {\r
- StringArray names;\r
-\r
- for (auto* d : devices)\r
- names.addArray (d->getInputChannelNames());\r
+ auto getDeviceWrappers() { return std::array< DeviceWrapper*, 2> { { &inputWrapper, &outputWrapper } }; }\r
+ auto getDeviceWrappers() const { return std::array<const DeviceWrapper*, 2> { { &inputWrapper, &outputWrapper } }; }\r
\r
- names.appendNumbersToDuplicates (false, true);\r
- return names;\r
- }\r
+ StringArray getOutputChannelNames() override { return outputWrapper.getChannelNames(); }\r
+ StringArray getInputChannelNames() override { return inputWrapper .getChannelNames(); }\r
+ BigInteger getActiveOutputChannels() const override { return outputWrapper.getActiveChannels(); }\r
+ BigInteger getActiveInputChannels() const override { return inputWrapper .getActiveChannels(); }\r
\r
Array<double> getAvailableSampleRates() override\r
{\r
Array<double> commonRates;\r
bool first = true;\r
\r
- for (auto* d : devices)\r
+ for (auto& d : getDeviceWrappers())\r
{\r
- auto rates = d->device->getAvailableSampleRates();\r
+ auto rates = d->getAvailableSampleRates();\r
\r
if (first)\r
{\r
Array<int> commonSizes;\r
bool first = true;\r
\r
- for (auto* d : devices)\r
+ for (auto& d : getDeviceWrappers())\r
{\r
- auto sizes = d->device->getAvailableBufferSizes();\r
+ auto sizes = d->getAvailableBufferSizes();\r
\r
if (first)\r
{\r
{\r
int depth = 32;\r
\r
- for (auto* d : devices)\r
- depth = jmin (depth, d->device->getCurrentBitDepth());\r
+ for (auto& d : getDeviceWrappers())\r
+ depth = jmin (depth, d->getCurrentBitDepth());\r
\r
return depth;\r
}\r
{\r
int size = 0;\r
\r
- for (auto* d : devices)\r
- size = jmax (size, d->device->getDefaultBufferSize());\r
+ for (auto& d : getDeviceWrappers())\r
+ size = jmax (size, d->getDefaultBufferSize());\r
\r
return size;\r
}\r
auto rates = getAvailableSampleRates();\r
\r
for (int i = 0; i < rates.size() && sampleRate < 44100.0; ++i)\r
- sampleRate = rates.getUnchecked(i);\r
+ sampleRate = rates.getUnchecked (i);\r
}\r
\r
currentSampleRate = sampleRate;\r
currentBufferSize = bufferSize;\r
+ targetLatency = bufferSize;\r
\r
- const int fifoSize = bufferSize * 3 + 1;\r
- int totalInputChanIndex = 0, totalOutputChanIndex = 0;\r
- int chanIndex = 0;\r
-\r
- for (auto* d : devices)\r
+ for (auto& d : getDeviceWrappers())\r
{\r
- BigInteger ins (inputChannels >> totalInputChanIndex);\r
- BigInteger outs (outputChannels >> totalOutputChanIndex);\r
-\r
- int numIns = d->getInputChannelNames().size();\r
- int numOuts = d->getOutputChannelNames().size();\r
-\r
- totalInputChanIndex += numIns;\r
- totalOutputChanIndex += numOuts;\r
-\r
- String err = d->open (ins, outs, sampleRate, bufferSize,\r
- chanIndex, fifoSize);\r
+ auto err = d->open ( d->isInput() ? inputChannels : BigInteger(),\r
+ ! d->isInput() ? outputChannels : BigInteger(),\r
+ sampleRate, bufferSize);\r
\r
if (err.isNotEmpty())\r
{\r
return err;\r
}\r
\r
- chanIndex += d->numInputChans + d->numOutputChans;\r
+ targetLatency += d->getLatencyInSamples();\r
}\r
\r
- fifos.setSize (chanIndex, fifoSize);\r
- fifoReadPointers = fifos.getArrayOfReadPointers();\r
- fifoWritePointers = fifos.getArrayOfWritePointers();\r
- fifos.clear();\r
- startThread (9);\r
- threadInitialised.wait();\r
+ const auto numOuts = outputWrapper.getChannelNames().size();\r
+\r
+ fifo.setSize (numOuts, targetLatency + (bufferSize * 2));\r
+ scratchBuffer.setSize (numOuts, bufferSize);\r
\r
return {};\r
}\r
void close() override\r
{\r
stop();\r
- stopThread (10000);\r
- fifos.clear();\r
+ fifo.clear();\r
active = false;\r
\r
- for (auto* d : devices)\r
+ for (auto& d : getDeviceWrappers())\r
d->close();\r
}\r
\r
auto newSampleRate = sampleRateRequested;\r
auto newBufferSize = bufferSizeRequested;\r
\r
- for (auto* d : devices)\r
+ for (auto& d : getDeviceWrappers())\r
{\r
auto deviceSampleRate = d->getCurrentSampleRate();\r
\r
if (! getAvailableSampleRates().contains (deviceSampleRate))\r
return;\r
\r
- for (auto* d2 : devices)\r
- if (d2 != d)\r
+ for (auto& d2 : getDeviceWrappers())\r
+ if (&d2 != &d)\r
d2->setCurrentSampleRate (deviceSampleRate);\r
\r
newSampleRate = deviceSampleRate;\r
}\r
}\r
\r
- for (auto* d : devices)\r
+ for (auto& d : getDeviceWrappers())\r
{\r
auto deviceBufferSize = d->getCurrentBufferSizeSamples();\r
\r
startTimer (100);\r
}\r
\r
- BigInteger getActiveOutputChannels() const override\r
- {\r
- BigInteger chans;\r
- int start = 0;\r
-\r
- for (auto* d : devices)\r
- {\r
- auto numChans = d->getOutputChannelNames().size();\r
-\r
- if (numChans > 0)\r
- {\r
- chans |= (d->device->getActiveOutputChannels() << start);\r
- start += numChans;\r
- }\r
- }\r
-\r
- return chans;\r
- }\r
-\r
- BigInteger getActiveInputChannels() const override\r
- {\r
- BigInteger chans;\r
- int start = 0;\r
-\r
- for (auto* d : devices)\r
- {\r
- auto numChans = d->getInputChannelNames().size();\r
-\r
- if (numChans > 0)\r
- {\r
- chans |= (d->device->getActiveInputChannels() << start);\r
- start += numChans;\r
- }\r
- }\r
-\r
- return chans;\r
- }\r
-\r
int getOutputLatencyInSamples() override\r
{\r
- int lat = 0;\r
-\r
- for (auto* d : devices)\r
- lat = jmax (lat, d->device->getOutputLatencyInSamples());\r
-\r
- return lat + currentBufferSize * 2;\r
+ return targetLatency - getInputLatencyInSamples();\r
}\r
\r
int getInputLatencyInSamples() override\r
{\r
- int lat = 0;\r
-\r
- for (auto* d : devices)\r
- lat = jmax (lat, d->device->getInputLatencyInSamples());\r
-\r
- return lat + currentBufferSize * 2;\r
+ return inputWrapper.getLatencyInSamples();\r
}\r
\r
void start (AudioIODeviceCallback* newCallback) override\r
if (shouldStart)\r
{\r
stop();\r
- fifos.clear();\r
+ fifo.clear();\r
+ reset();\r
\r
- for (auto* d : devices)\r
- d->start();\r
+ {\r
+ ScopedErrorForwarder forwarder (*this, newCallback);\r
+\r
+ for (auto& d : getDeviceWrappers())\r
+ d->start (d);\r
\r
- if (newCallback != nullptr)\r
- newCallback->audioDeviceAboutToStart (this);\r
+ if (! forwarder.encounteredError() && newCallback != nullptr)\r
+ newCallback->audioDeviceAboutToStart (this);\r
+ else if (lastError.isEmpty())\r
+ lastError = TRANS("Failed to initialise all requested devices.");\r
+ }\r
\r
const ScopedLock sl (callbackLock);\r
previousCallback = callback = newCallback;\r
return lastError;\r
}\r
\r
+ int getXRunCount() const noexcept override\r
+ {\r
+ return xruns.load();\r
+ }\r
+\r
private:\r
+ static constexpr auto invalidSampleTime = std::numeric_limits<std::uint64_t>::max();\r
+\r
WeakReference<CoreAudioIODeviceType> owner;\r
CriticalSection callbackLock;\r
AudioIODeviceCallback* callback = nullptr;\r
int currentBufferSize = 0;\r
bool active = false;\r
String lastError;\r
- AudioBuffer<float> fifos;\r
- const float** fifoReadPointers = nullptr;\r
- float** fifoWritePointers = nullptr;\r
- WaitableEvent threadInitialised;\r
+ AudioSampleBuffer fifo, scratchBuffer;\r
CriticalSection closeLock;\r
+ int targetLatency = 0;\r
+ std::atomic<int> xruns { -1 };\r
\r
BigInteger inputChannelsRequested, outputChannelsRequested;\r
double sampleRateRequested = 44100;\r
int bufferSizeRequested = 512;\r
\r
- void run() override\r
- {\r
- auto numSamples = currentBufferSize;\r
-\r
- AudioBuffer<float> buffer (fifos.getNumChannels(), numSamples);\r
- buffer.clear();\r
-\r
- Array<const float*> inputChans;\r
- Array<float*> outputChans;\r
-\r
- for (auto* d : devices)\r
- {\r
- for (int j = 0; j < d->numInputChans; ++j) inputChans.add (buffer.getReadPointer (d->inputIndex + j));\r
- for (int j = 0; j < d->numOutputChans; ++j) outputChans.add (buffer.getWritePointer (d->outputIndex + j));\r
- }\r
-\r
- auto numInputChans = inputChans.size();\r
- auto numOutputChans = outputChans.size();\r
-\r
- inputChans.add (nullptr);\r
- outputChans.add (nullptr);\r
-\r
- auto blockSizeMs = jmax (1, (int) (1000 * numSamples / currentSampleRate));\r
-\r
- jassert (numInputChans + numOutputChans == buffer.getNumChannels());\r
-\r
- threadInitialised.signal();\r
-\r
- while (! threadShouldExit())\r
- {\r
- readInput (buffer, numSamples, blockSizeMs);\r
-\r
- bool didCallback = true;\r
-\r
- {\r
- const ScopedLock sl (callbackLock);\r
-\r
- if (callback != nullptr)\r
- callback->audioDeviceIOCallbackWithContext ((const float**) inputChans.getRawDataPointer(),\r
- numInputChans,\r
- outputChans.getRawDataPointer(),\r
- numOutputChans,\r
- numSamples,\r
- {}); // Can't predict when the next output callback will happen\r
- else\r
- didCallback = false;\r
- }\r
-\r
- if (didCallback)\r
- {\r
- pushOutputData (buffer, numSamples, blockSizeMs);\r
- }\r
- else\r
- {\r
- for (int i = 0; i < numOutputChans; ++i)\r
- FloatVectorOperations::clear (outputChans[i], numSamples);\r
-\r
- reset();\r
- }\r
- }\r
- }\r
-\r
void timerCallback() override\r
{\r
stopTimer();\r
std::swap (callback, lastCallback);\r
}\r
\r
- for (auto* d : devices)\r
- d->device->stopInternal();\r
+ for (auto& d : getDeviceWrappers())\r
+ d->stopInternal();\r
\r
if (lastCallback != nullptr)\r
{\r
\r
void reset()\r
{\r
- for (auto* d : devices)\r
+ xruns.store (0);\r
+ fifo.clear();\r
+ scratchBuffer.clear();\r
+\r
+ for (auto& d : getDeviceWrappers())\r
d->reset();\r
}\r
\r
- void underrun()\r
+ // AbstractFifo cannot be used here for two reasons:\r
+ // 1) We use absolute timestamps as the fifo's read/write positions. This not only makes the code\r
+ // more readable (especially when checking for underruns/overflows) but also simplifies the\r
+ // initial setup when actual latency is not known yet until both callbacks have fired.\r
+ // 2) AbstractFifo doesn't have the necessary mechanics to recover from underrun/overflow conditions\r
+ // in a lock-free and data-race free way. It's great if you don't care (i.e. overwrite and/or\r
+ // read stale data) or can abort the operation entirely, but this is not the case here. We\r
+ // need bespoke underrun/overflow handling here which fits this use-case.\r
+ template <typename Callback>\r
+ void accessFifo (const uint64_t startPos, const int numChannels, const int numItems, Callback&& operateOnRange)\r
{\r
+ const auto fifoSize = fifo.getNumSamples();\r
+ auto fifoPos = static_cast<int> (startPos % static_cast<std::uint64_t> (fifoSize));\r
+\r
+ for (int pos = 0; pos < numItems;)\r
+ {\r
+ const auto max = std::min (numItems - pos, fifoSize - fifoPos);\r
+\r
+ struct Args { int fifoPos, inputPos, nItems, channel; };\r
+\r
+ for (auto ch = 0; ch < numChannels; ++ch)\r
+ operateOnRange (Args { fifoPos, pos, max, ch });\r
+\r
+ fifoPos = (fifoPos + max) % fifoSize;\r
+ pos += max;\r
+ }\r
}\r
\r
- void readInput (AudioBuffer<float>& buffer, const int numSamples, const int blockSizeMs)\r
+ void inputAudioCallback (const float* const* channels, int numChannels, int n, const AudioIODeviceCallbackContext& context) noexcept\r
{\r
- for (auto* d : devices)\r
- d->done = (d->numInputChans == 0 || d->isWaitingForInput);\r
-\r
- float totalWaitTimeMs = blockSizeMs * 5.0f;\r
- constexpr int numReadAttempts = 6;\r
- auto sumPower2s = [] (int maxPower) { return (1 << (maxPower + 1)) - 1; };\r
- float waitTime = totalWaitTimeMs / (float) sumPower2s (numReadAttempts - 2);\r
+ auto& writePos = inputWrapper.sampleTime;\r
\r
- for (int numReadAttemptsRemaining = numReadAttempts;;)\r
{\r
- bool anySamplesRemaining = false;\r
+ ScopedLock lock (callbackLock);\r
\r
- for (auto* d : devices)\r
+ if (callback != nullptr)\r
{\r
- if (! d->done)\r
- {\r
- if (d->isInputReady (numSamples))\r
- {\r
- d->readInput (buffer, numSamples);\r
- d->done = true;\r
- }\r
- else\r
- {\r
- anySamplesRemaining = true;\r
- }\r
- }\r
+ const auto numActiveOutputChannels = outputWrapper.getActiveChannels().countNumberOfSetBits();\r
+ jassert (numActiveOutputChannels <= scratchBuffer.getNumChannels());\r
+\r
+ callback->audioDeviceIOCallbackWithContext (channels,\r
+ numChannels,\r
+ scratchBuffer.getArrayOfWritePointers(),\r
+ numActiveOutputChannels,\r
+ n,\r
+ context);\r
+ }\r
+ else\r
+ {\r
+ scratchBuffer.clear();\r
}\r
+ }\r
\r
- if (! anySamplesRemaining)\r
- return;\r
+ auto currentWritePos = writePos.load();\r
\r
- if (--numReadAttemptsRemaining == 0)\r
- break;\r
+ writePos.compare_exchange_strong (currentWritePos, currentWritePos + static_cast<std::uint64_t> (n));\r
\r
- wait (jmax (1, roundToInt (waitTime)));\r
- waitTime *= 2.0f;\r
+ if (currentWritePos == invalidSampleTime)\r
+ return;\r
+\r
+ const auto readPos = outputWrapper.sampleTime.load();\r
+\r
+ // check for fifo overflow\r
+ if (readPos != invalidSampleTime)\r
+ {\r
+ // write will overlap previous read\r
+ if (readPos > currentWritePos || (currentWritePos + static_cast<std::uint64_t> (n) - readPos) > static_cast<std::uint64_t> (fifo.getNumSamples()))\r
+ {\r
+ xrun();\r
+ return;\r
+ }\r
}\r
\r
- for (auto* d : devices)\r
- if (! d->done)\r
- for (int i = 0; i < d->numInputChans; ++i)\r
- buffer.clear (d->inputIndex + i, 0, numSamples);\r
+ accessFifo (currentWritePos, scratchBuffer.getNumChannels(), n, [&] (const auto& args)\r
+ {\r
+ FloatVectorOperations::copy (fifo.getWritePointer (args.channel, args.fifoPos),\r
+ scratchBuffer.getReadPointer (args.channel, args.inputPos),\r
+ args.nItems);\r
+ });\r
}\r
\r
- void pushOutputData (AudioBuffer<float>& buffer, const int numSamples, const int blockSizeMs)\r
+ void outputAudioCallback (float* const* channels, int numChannels, int n) noexcept\r
{\r
- for (auto* d : devices)\r
- d->done = (d->numOutputChans == 0);\r
+ auto& readPos = outputWrapper.sampleTime;\r
+ auto currentReadPos = readPos.load();\r
\r
- for (int tries = 5;;)\r
- {\r
- bool anyRemaining = false;\r
+ if (currentReadPos == invalidSampleTime)\r
+ return;\r
\r
- for (auto* d : devices)\r
+ const auto writePos = inputWrapper.sampleTime.load();\r
+\r
+ // check for fifo underrun\r
+ if (writePos != invalidSampleTime)\r
+ {\r
+ if ((currentReadPos + static_cast<std::uint64_t> (n)) > writePos)\r
{\r
- if (! d->done)\r
- {\r
- if (d->isOutputReady (numSamples))\r
- {\r
- d->pushOutputData (buffer, numSamples);\r
- d->done = true;\r
- }\r
- else\r
- {\r
- anyRemaining = true;\r
- }\r
- }\r
+ xrun();\r
+ return;\r
}\r
+ }\r
\r
- if ((! anyRemaining) || --tries == 0)\r
- return;\r
+ accessFifo (currentReadPos, numChannels, n, [&] (const auto& args)\r
+ {\r
+ FloatVectorOperations::copy (channels[args.channel] + args.inputPos,\r
+ fifo.getReadPointer (args.channel, args.fifoPos),\r
+ args.nItems);\r
+ });\r
\r
- wait (blockSizeMs);\r
- }\r
+ // use compare exchange here as we need to avoid the case\r
+ // where we overwrite readPos being equal to invalidSampleTime\r
+ readPos.compare_exchange_strong (currentReadPos, currentReadPos + static_cast<std::uint64_t> (n));\r
+ }\r
+\r
+ void xrun() noexcept\r
+ {\r
+ for (auto& d : getDeviceWrappers())\r
+ d->sampleTime.store (invalidSampleTime);\r
+\r
+ ++xruns;\r
}\r
\r
void handleAudioDeviceAboutToStart (AudioIODevice* device)\r
currentSampleRate = newSampleRate;\r
bool anySampleRateChanges = false;\r
\r
- for (auto* d : devices)\r
+ for (auto& d : getDeviceWrappers())\r
{\r
if (d->getCurrentSampleRate() != currentSampleRate)\r
{\r
void handleAudioDeviceError (const String& errorMessage) { shutdown (errorMessage.isNotEmpty() ? errorMessage : String ("unknown")); }\r
\r
//==============================================================================\r
- struct DeviceWrapper : private AudioIODeviceCallback\r
+ struct DeviceWrapper : public AudioIODeviceCallback\r
{\r
- DeviceWrapper (AudioIODeviceCombiner& cd, std::unique_ptr<CoreAudioIODevice> d, bool useIns, bool useOuts)\r
+ DeviceWrapper (AudioIODeviceCombiner& cd, std::unique_ptr<CoreAudioIODevice> d, bool shouldBeInput)\r
: owner (cd), device (std::move (d)),\r
- useInputs (useIns), useOutputs (useOuts)\r
+ input (shouldBeInput)\r
{\r
device->setAsyncRestarter (&owner);\r
}\r
\r
~DeviceWrapper() override\r
- {\r
- close();\r
- }\r
-\r
- String open (const BigInteger& inputChannels, const BigInteger& outputChannels,\r
- double sampleRate, int bufferSize, int channelIndex, int fifoSize)\r
- {\r
- inputFifo.setTotalSize (fifoSize);\r
- outputFifo.setTotalSize (fifoSize);\r
- inputFifo.reset();\r
- outputFifo.reset();\r
-\r
- auto err = device->open (useInputs ? inputChannels : BigInteger(),\r
- useOutputs ? outputChannels : BigInteger(),\r
- sampleRate, bufferSize);\r
-\r
- numInputChans = useInputs ? device->getActiveInputChannels().countNumberOfSetBits() : 0;\r
- numOutputChans = useOutputs ? device->getActiveOutputChannels().countNumberOfSetBits() : 0;\r
-\r
- isWaitingForInput = numInputChans > 0;\r
-\r
- inputIndex = channelIndex;\r
- outputIndex = channelIndex + numInputChans;\r
-\r
- return err;\r
- }\r
-\r
- void close()\r
{\r
device->close();\r
}\r
\r
- void start()\r
+ void reset()\r
{\r
- reset();\r
- device->start (this);\r
+ sampleTime.store (invalidSampleTime);\r
}\r
\r
- void reset()\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
+ int numInputChannels,\r
+ float* const* outputChannelData,\r
+ int numOutputChannels,\r
+ int numSamples,\r
+ const AudioIODeviceCallbackContext& context) override\r
{\r
- inputFifo.reset();\r
- outputFifo.reset();\r
- }\r
+ if (std::exchange (device->hadDiscontinuity, false))\r
+ owner.xrun();\r
\r
- StringArray getOutputChannelNames() const { return useOutputs ? device->getOutputChannelNames() : StringArray(); }\r
- StringArray getInputChannelNames() const { return useInputs ? device->getInputChannelNames() : StringArray(); }\r
+ updateSampleTimeFromContext (context);\r
\r
- bool isInputReady (int numSamples) const noexcept\r
- {\r
- return numInputChans == 0 || inputFifo.getNumReady() >= numSamples;\r
+ if (input)\r
+ owner.inputAudioCallback (inputChannelData, numInputChannels, numSamples, context);\r
+ else\r
+ owner.outputAudioCallback (outputChannelData, numOutputChannels, numSamples);\r
}\r
\r
- void readInput (AudioBuffer<float>& destBuffer, int numSamples)\r
+ void audioDeviceAboutToStart (AudioIODevice* d) override { owner.handleAudioDeviceAboutToStart (d); }\r
+ void audioDeviceStopped() override { owner.handleAudioDeviceStopped(); }\r
+ void audioDeviceError (const String& errorMessage) override { owner.handleAudioDeviceError (errorMessage); }\r
+\r
+ bool setCurrentSampleRate (double newSampleRate) { return device->setCurrentSampleRate (newSampleRate); }\r
+ StringArray getChannelNames() const { return input ? device->getInputChannelNames() : device->getOutputChannelNames(); }\r
+ BigInteger getActiveChannels() const { return input ? device->getActiveInputChannels() : device->getActiveOutputChannels(); }\r
+ int getLatencyInSamples() const { return input ? device->getInputLatencyInSamples() : device->getOutputLatencyInSamples(); }\r
+ int getIndexOfDevice (bool asInput) const { return device->getIndexOfDevice (asInput); }\r
+ double getCurrentSampleRate() const { return device->getCurrentSampleRate(); }\r
+ int getCurrentBufferSizeSamples() const { return device->getCurrentBufferSizeSamples(); }\r
+ Array<double> getAvailableSampleRates() const { return device->getAvailableSampleRates(); }\r
+ Array<int> getAvailableBufferSizes() const { return device->getAvailableBufferSizes(); }\r
+ int getCurrentBitDepth() const { return device->getCurrentBitDepth(); }\r
+ int getDefaultBufferSize() const { return device->getDefaultBufferSize(); }\r
+ void start (AudioIODeviceCallback* callbackToNotify) const { return device->start (callbackToNotify); }\r
+ AudioIODeviceCallback* stopInternal() const { return device->stopInternal(); }\r
+ void close() const { return device->close(); }\r
+\r
+ String open (const BigInteger& inputChannels, const BigInteger& outputChannels, double sampleRate, int bufferSizeSamples) const\r
{\r
- if (numInputChans == 0)\r
- return;\r
-\r
- int start1, size1, start2, size2;\r
- inputFifo.prepareToRead (numSamples, start1, size1, start2, size2);\r
-\r
- for (int i = 0; i < numInputChans; ++i)\r
- {\r
- auto index = inputIndex + i;\r
- auto dest = destBuffer.getWritePointer (index);\r
- auto src = owner.fifoReadPointers[index];\r
-\r
- if (size1 > 0) FloatVectorOperations::copy (dest, src + start1, size1);\r
- if (size2 > 0) FloatVectorOperations::copy (dest + size1, src + start2, size2);\r
- }\r
-\r
- inputFifo.finishedRead (size1 + size2);\r
+ return device->open (inputChannels, outputChannels, sampleRate, bufferSizeSamples);\r
}\r
\r
- bool isOutputReady (int numSamples) const noexcept\r
+ std::uint64_t nsToSampleTime (std::uint64_t ns) const noexcept\r
{\r
- return numOutputChans == 0 || outputFifo.getFreeSpace() >= numSamples;\r
+ return static_cast<std::uint64_t> (std::round (static_cast<double> (ns) * owner.currentSampleRate * 1e-9));\r
}\r
\r
- void pushOutputData (AudioBuffer<float>& srcBuffer, int numSamples)\r
+ void updateSampleTimeFromContext (const AudioIODeviceCallbackContext& context) noexcept\r
{\r
- if (numOutputChans == 0)\r
- return;\r
-\r
- int start1, size1, start2, size2;\r
- outputFifo.prepareToWrite (numSamples, start1, size1, start2, size2);\r
+ auto callbackSampleTime = context.hostTimeNs != nullptr ? nsToSampleTime (*context.hostTimeNs) : 0;\r
\r
- for (int i = 0; i < numOutputChans; ++i)\r
- {\r
- auto index = outputIndex + i;\r
- auto dest = owner.fifoWritePointers[index];\r
- auto src = srcBuffer.getReadPointer (index);\r
+ if (input)\r
+ callbackSampleTime += static_cast<std::uint64_t> (owner.targetLatency);\r
\r
- if (size1 > 0) FloatVectorOperations::copy (dest + start1, src, size1);\r
- if (size2 > 0) FloatVectorOperations::copy (dest + start2, src + size1, size2);\r
- }\r
+ auto copy = invalidSampleTime;\r
\r
- outputFifo.finishedWrite (size1 + size2);\r
+ if (sampleTime.compare_exchange_strong (copy, callbackSampleTime) && (! input))\r
+ owner.fifo.clear();\r
}\r
\r
- void audioDeviceIOCallbackWithContext (const float** inputChannelData,\r
- int numInputChannels,\r
- float** outputChannelData,\r
- int numOutputChannels,\r
- int numSamples,\r
- const AudioIODeviceCallbackContext&) override\r
- {\r
- if (numInputChannels > 0)\r
- {\r
- isWaitingForInput = false;\r
-\r
- int start1, size1, start2, size2;\r
- inputFifo.prepareToWrite (numSamples, start1, size1, start2, size2);\r
-\r
- if (size1 + size2 < numSamples)\r
- {\r
- inputFifo.reset();\r
- inputFifo.prepareToWrite (numSamples, start1, size1, start2, size2);\r
- }\r
-\r
- for (int i = 0; i < numInputChannels; ++i)\r
- {\r
- auto dest = owner.fifoWritePointers[inputIndex + i];\r
- auto src = inputChannelData[i];\r
+ bool isInput() const { return input; }\r
\r
- if (size1 > 0) FloatVectorOperations::copy (dest + start1, src, size1);\r
- if (size2 > 0) FloatVectorOperations::copy (dest + start2, src + size1, size2);\r
- }\r
+ std::atomic<std::uint64_t> sampleTime { invalidSampleTime };\r
\r
- auto totalSize = size1 + size2;\r
- inputFifo.finishedWrite (totalSize);\r
+ private:\r
\r
- if (numSamples > totalSize)\r
- {\r
- auto samplesRemaining = numSamples - totalSize;\r
+ //==============================================================================\r
+ AudioIODeviceCombiner& owner;\r
+ std::unique_ptr<CoreAudioIODevice> device;\r
+ const bool input;\r
\r
- for (int i = 0; i < numInputChans; ++i)\r
- FloatVectorOperations::clear (owner.fifoWritePointers[inputIndex + i] + totalSize, samplesRemaining);\r
+ //==============================================================================\r
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DeviceWrapper)\r
+ };\r
\r
- owner.underrun();\r
- }\r
- }\r
+ /* If the current AudioIODeviceCombiner::callback is nullptr, it sets itself as the callback\r
+ and forwards error related callbacks to the provided callback\r
+ */\r
+ class ScopedErrorForwarder : public AudioIODeviceCallback\r
+ {\r
+ public:\r
+ ScopedErrorForwarder (AudioIODeviceCombiner& ownerIn, AudioIODeviceCallback* cb)\r
+ : owner (ownerIn),\r
+ target (cb)\r
+ {\r
+ const ScopedLock sl (owner.callbackLock);\r
\r
- if (numOutputChannels > 0)\r
- {\r
- int start1, size1, start2, size2;\r
- outputFifo.prepareToRead (numSamples, start1, size1, start2, size2);\r
+ if (owner.callback == nullptr)\r
+ owner.callback = this;\r
+ }\r
\r
- if (size1 + size2 < numSamples)\r
- {\r
- Thread::sleep (1);\r
- outputFifo.prepareToRead (numSamples, start1, size1, start2, size2);\r
- }\r
+ ~ScopedErrorForwarder() override\r
+ {\r
+ const ScopedLock sl (owner.callbackLock);\r
\r
- for (int i = 0; i < numOutputChannels; ++i)\r
- {\r
- auto dest = outputChannelData[i];\r
- auto src = owner.fifoReadPointers[outputIndex + i];\r
+ if (owner.callback == this)\r
+ owner.callback = nullptr;\r
+ }\r
\r
- if (size1 > 0) FloatVectorOperations::copy (dest, src + start1, size1);\r
- if (size2 > 0) FloatVectorOperations::copy (dest + size1, src + start2, size2);\r
- }\r
+ // We only want to be notified about error conditions when the owner's callback is nullptr.\r
+ // This class shouldn't be relied on for forwarding this call.\r
+ void audioDeviceAboutToStart (AudioIODevice*) override {}\r
\r
- auto totalSize = size1 + size2;\r
- outputFifo.finishedRead (totalSize);\r
+ void audioDeviceStopped() override\r
+ {\r
+ if (target != nullptr)\r
+ target->audioDeviceStopped();\r
\r
- if (numSamples > totalSize)\r
- {\r
- auto samplesRemaining = numSamples - totalSize;\r
+ error = true;\r
+ }\r
\r
- for (int i = 0; i < numOutputChannels; ++i)\r
- FloatVectorOperations::clear (outputChannelData[i] + totalSize, samplesRemaining);\r
+ void audioDeviceError (const String& errorMessage) override\r
+ {\r
+ owner.lastError = errorMessage;\r
\r
- owner.underrun();\r
- }\r
- }\r
+ if (target != nullptr)\r
+ target->audioDeviceError (errorMessage);\r
\r
- owner.notify();\r
+ error = true;\r
}\r
\r
- double getCurrentSampleRate() { return device->getCurrentSampleRate(); }\r
- bool setCurrentSampleRate (double newSampleRate) { return device->setCurrentSampleRate (newSampleRate); }\r
- int getCurrentBufferSizeSamples() { return device->getCurrentBufferSizeSamples(); }\r
-\r
- void audioDeviceAboutToStart (AudioIODevice* d) override { owner.handleAudioDeviceAboutToStart (d); }\r
- void audioDeviceStopped() override { owner.handleAudioDeviceStopped(); }\r
- void audioDeviceError (const String& errorMessage) override { owner.handleAudioDeviceError (errorMessage); }\r
+ bool encounteredError() const { return error; }\r
\r
+ private:\r
AudioIODeviceCombiner& owner;\r
- std::unique_ptr<CoreAudioIODevice> device;\r
- int inputIndex = 0, numInputChans = 0, outputIndex = 0, numOutputChans = 0;\r
- bool useInputs = false, useOutputs = false;\r
- std::atomic<bool> isWaitingForInput { false };\r
- AbstractFifo inputFifo { 32 }, outputFifo { 32 };\r
- bool done = false;\r
-\r
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DeviceWrapper)\r
+ AudioIODeviceCallback* target;\r
+ bool error = false;\r
};\r
\r
- OwnedArray<DeviceWrapper> devices;\r
+ DeviceWrapper inputWrapper, outputWrapper;\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioIODeviceCombiner)\r
};\r
inputIds.clear();\r
outputIds.clear();\r
\r
- UInt32 size;\r
-\r
- AudioObjectPropertyAddress pa;\r
- pa.mSelector = kAudioHardwarePropertyDevices;\r
- pa.mScope = kAudioObjectPropertyScopeWildcard;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
+ auto audioDevices = audioObjectGetProperties<AudioDeviceID> (kAudioObjectSystemObject, { kAudioHardwarePropertyDevices,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain });\r
\r
- if (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, nullptr, &size) == noErr)\r
+ for (const auto audioDevice : audioDevices)\r
{\r
- HeapBlock<AudioDeviceID> devs;\r
- devs.calloc (size, 1);\r
-\r
- if (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, nullptr, &size, devs) == noErr)\r
+ if (const auto optionalName = audioObjectGetProperty<CFStringRef> (audioDevice, { kAudioDevicePropertyDeviceNameCFString,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain }))\r
{\r
- auto num = (int) size / (int) sizeof (AudioDeviceID);\r
-\r
- for (int i = 0; i < num; ++i)\r
+ if (const CFUniquePtr<CFStringRef> name { *optionalName })\r
{\r
- char name[1024];\r
- size = sizeof (name);\r
- pa.mSelector = kAudioDevicePropertyDeviceName;\r
+ const auto nameString = String::fromCFString (name.get());\r
+\r
+ if (const auto numIns = getNumChannels (audioDevice, true); numIns > 0)\r
+ {\r
+ inputDeviceNames.add (nameString);\r
+ inputIds.add (audioDevice);\r
+ }\r
\r
- if (AudioObjectGetPropertyData (devs[i], &pa, 0, nullptr, &size, name) == noErr)\r
+ if (const auto numOuts = getNumChannels (audioDevice, false); numOuts > 0)\r
{\r
- auto nameString = String::fromUTF8 (name, (int) strlen (name));\r
- auto numIns = getNumChannels (devs[i], true);\r
- auto numOuts = getNumChannels (devs[i], false);\r
-\r
- if (numIns > 0)\r
- {\r
- inputDeviceNames.add (nameString);\r
- inputIds.add (devs[i]);\r
- }\r
-\r
- if (numOuts > 0)\r
- {\r
- outputDeviceNames.add (nameString);\r
- outputIds.add (devs[i]);\r
- }\r
+ outputDeviceNames.add (nameString);\r
+ outputIds.add (audioDevice);\r
}\r
}\r
}\r
{\r
jassert (hasScanned); // need to call scanForDevices() before doing this\r
\r
- AudioDeviceID deviceID;\r
- UInt32 size = sizeof (deviceID);\r
-\r
// if they're asking for any input channels at all, use the default input, so we\r
// get the built-in mic rather than the built-in output with no inputs..\r
\r
AudioObjectPropertyAddress pa;\r
- pa.mSelector = forInput ? kAudioHardwarePropertyDefaultInputDevice\r
- : kAudioHardwarePropertyDefaultOutputDevice;\r
+ auto selector = forInput ? kAudioHardwarePropertyDefaultInputDevice\r
+ : kAudioHardwarePropertyDefaultOutputDevice;\r
pa.mScope = kAudioObjectPropertyScopeWildcard;\r
pa.mElement = juceAudioObjectPropertyElementMain;\r
\r
- if (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, nullptr, &size, &deviceID) == noErr)\r
+ if (auto deviceID = audioObjectGetProperty<AudioDeviceID> (kAudioObjectSystemObject, { selector,\r
+ kAudioObjectPropertyScopeWildcard,\r
+ juceAudioObjectPropertyElementMain }))\r
{\r
- if (forInput)\r
- {\r
- for (int i = inputIds.size(); --i >= 0;)\r
- if (inputIds[i] == deviceID)\r
- return i;\r
- }\r
- else\r
- {\r
- for (int i = outputIds.size(); --i >= 0;)\r
- if (outputIds[i] == deviceID)\r
- return i;\r
- }\r
+ auto& ids = forInput ? inputIds : outputIds;\r
+\r
+ if (auto it = std::find (ids.begin(), ids.end(), deviceID); it != ids.end())\r
+ return static_cast<int> (std::distance (ids.begin(), it));\r
}\r
\r
return 0;\r
jassert (hasScanned); // need to call scanForDevices() before doing this\r
\r
if (auto* d = dynamic_cast<CoreAudioIODevice*> (device))\r
- return asInput ? d->inputIndex\r
- : d->outputIndex;\r
+ return d->getIndexOfDevice (asInput);\r
\r
if (auto* d = dynamic_cast<AudioIODeviceCombiner*> (device))\r
- {\r
- for (auto* dev : d->getDevices())\r
- {\r
- auto index = getIndexOfDevice (dev, asInput);\r
-\r
- if (index >= 0)\r
+ for (auto* dev : d->getDeviceWrappers())\r
+ if (const auto index = dev->getIndexOfDevice (asInput); index >= 0)\r
return index;\r
- }\r
- }\r
\r
return -1;\r
}\r
if (in == nullptr) return out.release();\r
if (out == nullptr) return in.release();\r
\r
- auto combo = std::make_unique<AudioIODeviceCombiner> (combinedName, this);\r
- combo->addDevice (std::move (in), true, false);\r
- combo->addDevice (std::move (out), false, true);\r
+ auto combo = std::make_unique<AudioIODeviceCombiner> (combinedName, this, std::move (in), std::move (out));\r
return combo.release();\r
}\r
\r
static int getNumChannels (AudioDeviceID deviceID, bool input)\r
{\r
int total = 0;\r
- UInt32 size;\r
-\r
- AudioObjectPropertyAddress pa;\r
- pa.mSelector = kAudioDevicePropertyStreamConfiguration;\r
- pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
- pa.mElement = juceAudioObjectPropertyElementMain;\r
\r
- if (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size) == noErr)\r
+ if (auto bufList = audioObjectGetProperty<AudioBufferList> (deviceID, { kAudioDevicePropertyStreamConfiguration,\r
+ CoreAudioInternal::getScope (input),\r
+ juceAudioObjectPropertyElementMain }))\r
{\r
- HeapBlock<AudioBufferList> bufList;\r
- bufList.calloc (size, 1);\r
+ auto numStreams = (int) bufList->mNumberBuffers;\r
\r
- if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, bufList) == noErr)\r
- {\r
- auto numStreams = (int) bufList->mNumberBuffers;\r
-\r
- for (int i = 0; i < numStreams; ++i)\r
- total += bufList->mBuffers[i].mNumberChannels;\r
- }\r
+ for (int i = 0; i < numStreams; ++i)\r
+ total += bufList->mBuffers[i].mNumberChannels;\r
}\r
\r
return total;\r
: u32InputHandler (std::make_unique<ump::U32ToBytestreamHandler> (input, callback))\r
{}\r
\r
- void dispatch (const MIDIEventList& list, double time) const\r
+ void dispatch (const MIDIEventList* list, double time) const\r
{\r
- auto* packet = &list.packet[0];\r
+ auto* packet = list->packet;\r
\r
- for (uint32_t i = 0; i < list.numPackets; ++i)\r
+ for (uint32_t i = 0; i < list->numPackets; ++i)\r
{\r
static_assert (sizeof (uint32_t) == sizeof (UInt32)\r
&& alignof (uint32_t) == alignof (UInt32),\r
: bytestreamInputHandler (std::make_unique<ump::BytestreamToBytestreamHandler> (input, callback))\r
{}\r
\r
- void dispatch (const MIDIPacketList& list, double time) const\r
+ void dispatch (const MIDIPacketList* list, double time) const\r
{\r
- auto* packet = &list.packet[0];\r
+ auto* packet = list->packet;\r
\r
- for (unsigned int i = 0; i < list.numPackets; ++i)\r
+ for (unsigned int i = 0; i < list->numPackets; ++i)\r
{\r
auto len = readUnaligned<decltype (packet->length)> (&(packet->length));\r
bytestreamInputHandler->pushMidiData (packet->data, len, time);\r
: newReceiver (input, callback), oldReceiver (input, callback)\r
{}\r
\r
- void dispatch (const MIDIEventList& list, double time) const\r
+ void dispatch (const MIDIEventList* list, double time) const\r
{\r
newReceiver.dispatch (list, time);\r
}\r
\r
- void dispatch (const MIDIPacketList& list, double time) const\r
+ void dispatch (const MIDIPacketList* list, double time) const\r
{\r
oldReceiver.dispatch (list, time);\r
}\r
}\r
\r
template <typename EventList>\r
- void handlePackets (const EventList& list)\r
+ void handlePackets (const EventList* list)\r
{\r
const auto time = Time::getMillisecondCounterHiRes() * 0.001;\r
\r
\r
static void newMidiInputProc (const MIDIEventList* list, void* readProcRefCon, void*)\r
{\r
- static_cast<MidiPortAndCallback*> (readProcRefCon)->handlePackets (*list);\r
+ static_cast<MidiPortAndCallback*> (readProcRefCon)->handlePackets (list);\r
}\r
};\r
#endif\r
private:\r
static void oldMidiInputProc (const MIDIPacketList* list, void* readProcRefCon, void*)\r
{\r
- static_cast<MidiPortAndCallback*> (readProcRefCon)->handlePackets (*list);\r
+ static_cast<MidiPortAndCallback*> (readProcRefCon)->handlePackets (list);\r
}\r
};\r
#endif\r
openDevice();\r
}\r
\r
- ~ASIOAudioIODevice()\r
+ ~ASIOAudioIODevice() override\r
{\r
for (int i = 0; i < maxNumASIODevices; ++i)\r
if (currentASIODev[i] == this)\r
\r
// Get error message if init() failed, or if it's a buggy Denon driver,\r
// which returns true from init() even when it fails.\r
- if ((! initOk) || getName().containsIgnoreCase ("denon dj"))\r
+ if ((! initOk) || getName().containsIgnoreCase ("denon dj asio"))\r
driverError = getLastDriverError();\r
\r
if ((! initOk) && driverError.isEmpty())\r
inputFormat[i].convertToFloat (infos[i].buffers[bufferIndex], inBuffers[i], samps);\r
}\r
\r
- currentCallback->audioDeviceIOCallbackWithContext (const_cast<const float**> (inBuffers.getData()),\r
+ currentCallback->audioDeviceIOCallbackWithContext (inBuffers.getData(),\r
numActiveInputChans,\r
outBuffers,\r
numActiveOutputChans,\r
for (int i = 0; i < inChans.size(); ++i)\r
inChans.getUnchecked(i)->synchronisePosition();\r
\r
- startThread (9);\r
+ startThread (Priority::highest);\r
sleep (10);\r
\r
notify();\r
namespace juce\r
{\r
\r
+template <typename T>\r
+class CheckedReference\r
+{\r
+public:\r
+ template <typename Ptr>\r
+ friend auto createCheckedReference (Ptr*);\r
+\r
+ void clear()\r
+ {\r
+ std::lock_guard lock { mutex };\r
+ ptr = nullptr;\r
+ }\r
+\r
+ template <typename Callback>\r
+ void access (Callback&& callback)\r
+ {\r
+ std::lock_guard lock { mutex };\r
+ callback (ptr);\r
+ }\r
+\r
+private:\r
+ explicit CheckedReference (T* ptrIn) : ptr (ptrIn) {}\r
+\r
+ T* ptr;\r
+ std::mutex mutex;\r
+};\r
+\r
+template <typename Ptr>\r
+auto createCheckedReference (Ptr* ptrIn)\r
+{\r
+ return std::shared_ptr<CheckedReference<Ptr>> { new CheckedReference<Ptr> (ptrIn) };\r
+}\r
+\r
class MidiInput::Pimpl\r
{\r
public:\r
};\r
\r
//==============================================================================\r
- template <typename COMFactoryType, typename COMInterfaceType, typename COMType>\r
- struct OpenMidiPortThread : public Thread\r
+ template <typename COMType, typename COMFactoryType, typename COMInterfaceType>\r
+ static void openMidiPortThread (String threadName,\r
+ String midiDeviceID,\r
+ ComSmartPtr<COMFactoryType>& comFactory,\r
+ ComSmartPtr<COMInterfaceType>& comPort)\r
{\r
- OpenMidiPortThread (String threadName, String midiDeviceID,\r
- ComSmartPtr<COMFactoryType>& comFactory,\r
- ComSmartPtr<COMInterfaceType>& comPort)\r
- : Thread (threadName),\r
- deviceID (midiDeviceID),\r
- factory (comFactory),\r
- port (comPort)\r
- {\r
- }\r
-\r
- ~OpenMidiPortThread()\r
+ std::thread { [&]\r
{\r
- stopThread (2000);\r
- }\r
+ Thread::setCurrentThreadName (threadName);\r
\r
- void run() override\r
- {\r
- WinRTWrapper::ScopedHString hDeviceId (deviceID);\r
+ const WinRTWrapper::ScopedHString hDeviceId { midiDeviceID };\r
ComSmartPtr<IAsyncOperation<COMType*>> asyncOp;\r
- auto hr = factory->FromIdAsync (hDeviceId.get(), asyncOp.resetAndGetPointerAddress());\r
+ const auto hr = comFactory->FromIdAsync (hDeviceId.get(), asyncOp.resetAndGetPointerAddress());\r
\r
if (FAILED (hr))\r
return;\r
\r
- hr = asyncOp->put_Completed (Callback<IAsyncOperationCompletedHandler<COMType*>> (\r
- [this] (IAsyncOperation<COMType*>* asyncOpPtr, AsyncStatus)\r
- {\r
- if (asyncOpPtr == nullptr)\r
- return E_ABORT;\r
+ std::promise<ComSmartPtr<COMInterfaceType>> promise;\r
+ auto future = promise.get_future();\r
\r
- auto hr = asyncOpPtr->GetResults (port.resetAndGetPointerAddress());\r
+ auto callback = [p = std::move (promise)] (IAsyncOperation<COMType*>* asyncOpPtr, AsyncStatus) mutable\r
+ {\r
+ if (asyncOpPtr == nullptr)\r
+ {\r
+ p.set_value (nullptr);\r
+ return E_ABORT;\r
+ }\r
\r
- if (FAILED (hr))\r
- return hr;\r
+ ComSmartPtr<COMInterfaceType> result;\r
+ const auto hr = asyncOpPtr->GetResults (result.resetAndGetPointerAddress());\r
\r
- portOpened.signal();\r
- return S_OK;\r
- }\r
- ).Get());\r
+ if (FAILED (hr))\r
+ {\r
+ p.set_value (nullptr);\r
+ return hr;\r
+ }\r
\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
+ p.set_value (std::move (result));\r
+ return S_OK;\r
+ };\r
\r
- const String deviceID;\r
- ComSmartPtr<COMFactoryType>& factory;\r
- ComSmartPtr<COMInterfaceType>& port;\r
- WaitableEvent portOpened { true };\r
- };\r
+ const auto ir = asyncOp->put_Completed (Callback<IAsyncOperationCompletedHandler<COMType*>> (std::move (callback)).Get());\r
+\r
+ if (FAILED (ir))\r
+ return;\r
+\r
+ if (future.wait_for (std::chrono::milliseconds (2000)) == std::future_status::ready)\r
+ comPort = future.get();\r
+ } }.join();\r
+ }\r
\r
//==============================================================================\r
template <typename MIDIIOStaticsType, typename MIDIPort>\r
inputDevice (input),\r
callback (cb)\r
{\r
- OpenMidiPortThread<IMidiInPortStatics, IMidiInPort, MidiInPort> portThread ("Open WinRT MIDI input port",\r
- deviceInfo.deviceID,\r
- service.midiInFactory,\r
- midiPort);\r
- portThread.startThread();\r
- portThread.waitForThreadToExit (-1);\r
+ openMidiPortThread<MidiInPort> ("Open WinRT MIDI input port", deviceInfo.deviceID, service.midiInFactory, midiPort);\r
\r
if (midiPort == nullptr)\r
{\r
\r
auto hr = midiPort->add_MessageReceived (\r
Callback<ITypedEventHandler<MidiInPort*, MidiMessageReceivedEventArgs*>> (\r
- [this] (IMidiInPort*, IMidiMessageReceivedEventArgs* args) { return midiInMessageReceived (args); }\r
+ [self = checkedReference] (IMidiInPort*, IMidiMessageReceivedEventArgs* args)\r
+ {\r
+ HRESULT hr = S_OK;\r
+\r
+ self->access ([&hr, args] (auto* ptr)\r
+ {\r
+ if (ptr != nullptr)\r
+ hr = ptr->midiInMessageReceived (args);\r
+ });\r
+\r
+ return hr;\r
+ }\r
).Get(),\r
&midiInMessageToken);\r
\r
\r
~WinRTInputWrapper()\r
{\r
+ checkedReference->clear();\r
disconnect();\r
}\r
\r
double startTime = 0;\r
bool isStarted = false;\r
\r
+ std::shared_ptr<CheckedReference<WinRTInputWrapper>> checkedReference = createCheckedReference (this);\r
+\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WinRTInputWrapper);\r
};\r
\r
WinRTOutputWrapper (WinRTMidiService& service, const String& deviceIdentifier)\r
: WinRTIOWrapper <IMidiOutPortStatics, IMidiOutPort> (*service.bleDeviceWatcher, *service.outputDeviceWatcher, deviceIdentifier)\r
{\r
- OpenMidiPortThread<IMidiOutPortStatics, IMidiOutPort, IMidiOutPort> portThread ("Open WinRT MIDI output port",\r
- deviceInfo.deviceID,\r
- service.midiOutFactory,\r
- midiPort);\r
- portThread.startThread();\r
- portThread.waitForThreadToExit (-1);\r
+ openMidiPortThread<IMidiOutPort> ("Open WinRT MIDI output port", deviceInfo.deviceID, service.midiOutFactory, midiPort);\r
\r
if (midiPort == nullptr)\r
throw std::runtime_error ("Timed out waiting for midi output port creation");\r
if (tempClient == nullptr)\r
return;\r
\r
- WAVEFORMATEXTENSIBLE format;\r
+ auto format = getClientMixFormat (tempClient);\r
\r
- if (! getClientMixFormat (tempClient, format))\r
+ if (! format)\r
return;\r
\r
- actualNumChannels = numChannels = format.Format.nChannels;\r
- defaultSampleRate = format.Format.nSamplesPerSec;\r
+ defaultNumChannels = maxNumChannels = format->Format.nChannels;\r
+ defaultSampleRate = format->Format.nSamplesPerSec;\r
rates.addUsingDefaultSort (defaultSampleRate);\r
- mixFormatChannelMask = format.dwChannelMask;\r
+ defaultFormatChannelMask = format->dwChannelMask;\r
\r
if (isExclusiveMode (deviceMode))\r
- findSupportedFormat (tempClient, defaultSampleRate, mixFormatChannelMask, format);\r
+ if (auto optFormat = findSupportedFormat (tempClient, defaultNumChannels, defaultSampleRate))\r
+ format = optFormat;\r
\r
- querySupportedBufferSizes (format, tempClient);\r
- querySupportedSampleRates (format, tempClient);\r
+ querySupportedBufferSizes (*format, tempClient);\r
+ querySupportedSampleRates (*format, tempClient);\r
+ maxNumChannels = queryMaxNumChannels (tempClient);\r
}\r
\r
virtual ~WASAPIDeviceBase()\r
{\r
sampleRate = newSampleRate;\r
channels = newChannels;\r
- channels.setRange (actualNumChannels, channels.getHighestBit() + 1 - actualNumChannels, false);\r
+ channels.setRange (maxNumChannels, channels.getHighestBit() + 1 - maxNumChannels, false);\r
numChannels = channels.getHighestBit() + 1;\r
\r
if (numChannels == 0)\r
WASAPIDeviceMode deviceMode;\r
\r
double sampleRate = 0, defaultSampleRate = 0;\r
- int numChannels = 0, actualNumChannels = 0;\r
+ int numChannels = 0, actualNumChannels = 0, maxNumChannels = 0, defaultNumChannels = 0;\r
int minBufferSize = 0, defaultBufferSize = 0, latencySamples = 0;\r
int lowLatencyBufferSizeMultiple = 0, lowLatencyMaxBufferSize = 0;\r
- DWORD mixFormatChannelMask = 0;\r
+ DWORD defaultFormatChannelMask = 0;\r
Array<double> rates;\r
HANDLE clientEvent = {};\r
BigInteger channels;\r
return newClient;\r
}\r
\r
- static bool getClientMixFormat (ComSmartPtr<IAudioClient>& client, WAVEFORMATEXTENSIBLE& format)\r
+ static std::optional<WAVEFORMATEXTENSIBLE> getClientMixFormat (ComSmartPtr<IAudioClient>& client)\r
{\r
WAVEFORMATEX* mixFormat = nullptr;\r
\r
if (! check (client->GetMixFormat (&mixFormat)))\r
- return false;\r
+ return {};\r
+\r
+ WAVEFORMATEXTENSIBLE format;\r
\r
copyWavFormat (format, mixFormat);\r
CoTaskMemFree (mixFormat);\r
\r
- return true;\r
+ return format;\r
}\r
\r
//==============================================================================\r
int bytesPerSampleContainer;\r
};\r
\r
- bool tryFormat (const AudioSampleFormat sampleFormat, IAudioClient* clientToUse, double newSampleRate,\r
- DWORD newMixFormatChannelMask, WAVEFORMATEXTENSIBLE& format) const\r
+ static constexpr AudioSampleFormat formatsToTry[] =\r
+ {\r
+ { true, 32, 4 },\r
+ { false, 32, 4 },\r
+ { false, 24, 4 },\r
+ { false, 24, 3 },\r
+ { false, 20, 4 },\r
+ { false, 20, 3 },\r
+ { false, 16, 2 }\r
+ };\r
+\r
+ static std::optional<WAVEFORMATEXTENSIBLE> tryFormat (const AudioSampleFormat sampleFormat, IAudioClient* clientToUse,\r
+ WASAPIDeviceMode mode, int newNumChannels, double newSampleRate,\r
+ DWORD newMixFormatChannelMask)\r
{\r
+ WAVEFORMATEXTENSIBLE format;\r
zerostruct (format);\r
\r
- if (numChannels <= 2 && sampleFormat.bitsPerSampleToTry <= 16)\r
+ if (newNumChannels <= 2 && sampleFormat.bitsPerSampleToTry <= 16)\r
{\r
format.Format.wFormatTag = WAVE_FORMAT_PCM;\r
}\r
}\r
\r
format.Format.nSamplesPerSec = (DWORD) newSampleRate;\r
- format.Format.nChannels = (WORD) numChannels;\r
+ format.Format.nChannels = (WORD) newNumChannels;\r
format.Format.wBitsPerSample = (WORD) (8 * sampleFormat.bytesPerSampleContainer);\r
format.Samples.wValidBitsPerSample = (WORD) (sampleFormat.bitsPerSampleToTry);\r
format.Format.nBlockAlign = (WORD) (format.Format.nChannels * format.Format.wBitsPerSample / 8);\r
\r
WAVEFORMATEX* nearestFormat = nullptr;\r
\r
- HRESULT hr = clientToUse->IsFormatSupported (isExclusiveMode (deviceMode) ? AUDCLNT_SHAREMODE_EXCLUSIVE\r
- : AUDCLNT_SHAREMODE_SHARED,\r
+ HRESULT hr = clientToUse->IsFormatSupported (isExclusiveMode (mode) ? AUDCLNT_SHAREMODE_EXCLUSIVE\r
+ : AUDCLNT_SHAREMODE_SHARED,\r
(WAVEFORMATEX*) &format,\r
- isExclusiveMode (deviceMode) ? nullptr\r
+ isExclusiveMode (mode) ? nullptr\r
: &nearestFormat);\r
logFailure (hr);\r
\r
- auto supportsSRC = supportsSampleRateConversion (deviceMode);\r
+ auto supportsSRC = supportsSampleRateConversion (mode);\r
\r
if (hr == S_FALSE\r
&& nearestFormat != nullptr\r
}\r
\r
CoTaskMemFree (nearestFormat);\r
- return hr == S_OK;\r
+\r
+ if (hr != S_OK)\r
+ return {};\r
+\r
+ return format;\r
}\r
\r
- bool findSupportedFormat (IAudioClient* clientToUse, double newSampleRate,\r
- DWORD newMixFormatChannelMask, WAVEFORMATEXTENSIBLE& format) const\r
+ std::optional<WAVEFORMATEXTENSIBLE> findSupportedFormat (IAudioClient* clientToUse, int newNumChannels, double newSampleRate) const\r
{\r
- static const AudioSampleFormat formats[] =\r
+ for (auto ch = newNumChannels; ch <= maxNumChannels; ++ch)\r
{\r
- { true, 32, 4 },\r
- { false, 32, 4 },\r
- { false, 24, 4 },\r
- { false, 24, 3 },\r
- { false, 20, 4 },\r
- { false, 20, 3 },\r
- { false, 16, 2 }\r
- };\r
+ auto maskWithLowestNBitsSet = static_cast<DWORD> ((1 << ch) - 1);\r
+ auto mixFormatChannelMask = (ch == defaultNumChannels ? defaultFormatChannelMask : maskWithLowestNBitsSet);\r
\r
- for (int i = 0; i < numElementsInArray (formats); ++i)\r
- if (tryFormat (formats[i], clientToUse, newSampleRate, newMixFormatChannelMask, format))\r
- return true;\r
+ for (auto const& sampleFormat: formatsToTry)\r
+ if (auto format = tryFormat (sampleFormat, clientToUse, deviceMode, ch, newSampleRate, mixFormatChannelMask))\r
+ return format;\r
+ }\r
\r
- return false;\r
+ return {};\r
+ }\r
+\r
+ int queryMaxNumChannels (IAudioClient* clientToUse) const\r
+ {\r
+ static constexpr auto maxNumChannelsToQuery = static_cast<int> (AudioChannelSet::maxChannelsOfNamedLayout);\r
+ const auto fallbackNumChannels = defaultNumChannels;\r
+\r
+ if (fallbackNumChannels >= maxNumChannelsToQuery)\r
+ return fallbackNumChannels;\r
+\r
+ auto result = fallbackNumChannels;\r
+\r
+ for (auto ch = maxNumChannelsToQuery; ch > result; --ch)\r
+ {\r
+ auto channelMask = static_cast<DWORD> ((1 << ch) - 1);\r
+\r
+ for (auto rate : rates)\r
+ for (auto const& sampleFormat: formatsToTry)\r
+ if (auto format = tryFormat (sampleFormat, clientToUse, deviceMode, ch, rate, channelMask))\r
+ result = jmax (static_cast<int> (format->Format.nChannels), result);\r
+ }\r
+\r
+ return result;\r
}\r
\r
DWORD getStreamFlags()\r
\r
bool tryInitialisingWithBufferSize (int bufferSizeSamples)\r
{\r
- WAVEFORMATEXTENSIBLE format;\r
\r
- if (findSupportedFormat (client, sampleRate, mixFormatChannelMask, format))\r
+ if (auto format = findSupportedFormat (client, numChannels, sampleRate))\r
{\r
- auto isInitialised = isLowLatencyMode (deviceMode) ? initialiseLowLatencyClient (bufferSizeSamples, format)\r
- : initialiseStandardClient (bufferSizeSamples, format);\r
+ auto isInitialised = isLowLatencyMode (deviceMode) ? initialiseLowLatencyClient (bufferSizeSamples, *format)\r
+ : initialiseStandardClient (bufferSizeSamples, *format);\r
\r
if (isInitialised)\r
{\r
- actualNumChannels = format.Format.nChannels;\r
- const bool isFloat = format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;\r
- bytesPerSample = format.Format.wBitsPerSample / 8;\r
- bytesPerFrame = format.Format.nBlockAlign;\r
+ actualNumChannels = format->Format.nChannels;\r
+ const bool isFloat = format->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;\r
+ bytesPerSample = format->Format.wBitsPerSample / 8;\r
+ bytesPerFrame = format->Format.nBlockAlign;\r
\r
updateFormat (isFloat);\r
\r
StringArray outChannels;\r
\r
if (outputDevice != nullptr)\r
- for (int i = 1; i <= outputDevice->actualNumChannels; ++i)\r
+ for (int i = 1; i <= outputDevice->maxNumChannels; ++i)\r
outChannels.add ("Output channel " + String (i));\r
\r
return outChannels;\r
StringArray inChannels;\r
\r
if (inputDevice != nullptr)\r
- for (int i = 1; i <= inputDevice->actualNumChannels; ++i)\r
+ for (int i = 1; i <= inputDevice->maxNumChannels; ++i)\r
inChannels.add ("Input channel " + String (i));\r
\r
return inChannels;\r
shouldShutdown = false;\r
deviceSampleRateChanged = false;\r
\r
- startThread (8);\r
+ startThread (Priority::high);\r
Thread::sleep (5);\r
\r
if (inputDevice != nullptr && inputDevice->client != nullptr)\r
const ScopedTryLock sl (startStopLock);\r
\r
if (sl.isLocked() && isStarted)\r
- callback->audioDeviceIOCallbackWithContext (const_cast<const float**> (inputBuffers),\r
+ callback->audioDeviceIOCallbackWithContext (inputBuffers,\r
numInputBuffers,\r
outputBuffers,\r
numOutputBuffers,\r
{\r
// Note that this function is handed the input device so it can check for the event and make sure\r
// the input reservoir is filled up correctly even when bufferSize > device actualBufferSize\r
- outputDevice->copyBuffers (const_cast<const float**> (outputBuffers), numOutputBuffers, bufferSize, inputDevice.get(), *this);\r
+ outputDevice->copyBuffers (outputBuffers, numOutputBuffers, bufferSize, inputDevice.get(), *this);\r
\r
if (outputDevice->sampleRateHasChanged)\r
{\r
gain = newGain;\r
}\r
\r
-void AudioSourcePlayer::audioDeviceIOCallback (const float** inputChannelData,\r
- int totalNumInputChannels,\r
- float** outputChannelData,\r
- int totalNumOutputChannels,\r
- int numSamples)\r
+void AudioSourcePlayer::audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
+ int totalNumInputChannels,\r
+ float* const* outputChannelData,\r
+ int totalNumOutputChannels,\r
+ int numSamples,\r
+ const AudioIODeviceCallbackContext& context)\r
{\r
+ ignoreUnused (context);\r
+\r
// these should have been prepared by audioDeviceAboutToStart()...\r
jassert (sampleRate > 0 && bufferSize > 0);\r
\r
float getGain() const noexcept { return gain; }\r
\r
//==============================================================================\r
- /** Implementation of the AudioIODeviceCallback method. */\r
- void audioDeviceIOCallback (const float** inputChannelData,\r
- int totalNumInputChannels,\r
- float** outputChannelData,\r
- int totalNumOutputChannels,\r
- int numSamples) override;\r
+ /** Implementation of the AudioIODeviceCallbackWithContext method. */\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
+ int totalNumInputChannels,\r
+ float* const* outputChannelData,\r
+ int totalNumOutputChannels,\r
+ int numSamples,\r
+ const AudioIODeviceCallbackContext& context) override;\r
\r
/** Implementation of the AudioIODeviceCallback method. */\r
void audioDeviceAboutToStart (AudioIODevice* device) override;\r
}\r
\r
//==============================================================================\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
{\r
}\r
\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
}\r
\r
//==============================================================================\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
{\r
#if JUCE_INCLUDE_FLAC_CODE || ! defined (JUCE_INCLUDE_FLAC_CODE)\r
\r
- #undef VERSION\r
- #define VERSION "1.3.1"\r
+ #undef PACKAGE_VERSION\r
+ #define PACKAGE_VERSION "1.3.4"\r
\r
#define FLAC__NO_DLL 1\r
\r
#define FLAC__HAS_X86INTRIN 1\r
#endif\r
\r
- #undef __STDC_LIMIT_MACROS\r
- #define __STDC_LIMIT_MACROS 1\r
#define flac_max jmax\r
#define flac_min jmin\r
- #undef DEBUG // (some flac code dumps debug trace if the app defines this macro)\r
+\r
+ #pragma push_macro ("DEBUG")\r
+ #pragma push_macro ("NDEBUG")\r
+ #undef DEBUG // (some flac code dumps debug trace if the app defines this macro)\r
+\r
+ #ifndef NDEBUG\r
+ #define NDEBUG // (some flac code prints cpu info if this isn't defined)\r
+ #endif\r
+\r
#include "flac/all.h"\r
#include "flac/libFLAC/bitmath.c"\r
#include "flac/libFLAC/bitreader.c"\r
#include "flac/libFLAC/stream_encoder.c"\r
#include "flac/libFLAC/stream_encoder_framing.c"\r
#include "flac/libFLAC/window_flac.c"\r
- #undef VERSION\r
+\r
+ #pragma pop_macro ("DEBUG")\r
+ #pragma pop_macro ("NDEBUG")\r
+\r
+ #undef PACKAGE_VERSION\r
\r
JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
JUCE_END_IGNORE_WARNINGS_MSVC\r
reservoir.setSize ((int) numChannels, 2 * (int) info.max_blocksize, false, false, true);\r
}\r
\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
if (! ok)\r
}\r
}\r
\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
if (destSamples == nullptr)\r
}\r
\r
const int numToCopy = jmin (decodedEnd - decodedStart, numSamples);\r
- float* const* const dst = reinterpret_cast<float**> (destSamples);\r
+ float* const* const dst = reinterpret_cast<float* const*> (destSamples);\r
memcpy (dst[0] + startOffsetInDestBuffer, decoded0 + decodedStart, (size_t) numToCopy * sizeof (float));\r
\r
if (numDestChannels > 1 && dst[1] != nullptr)\r
}\r
\r
//==============================================================================\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
const auto getBufferedRange = [this] { return bufferedRange; };\r
}\r
\r
//==============================================================================\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
{\r
}\r
\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
wmSyncReader->Close();\r
}\r
\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
if (sampleRate <= 0)\r
invalidate();\r
}\r
\r
-bool ARAAudioSourceReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool ARAAudioSourceReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples)\r
{\r
const auto destSize = (bitsPerSample / 8) * (size_t) numSamples;\r
playbackRenderer.reset();\r
}\r
\r
-bool ARAPlaybackRegionReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool ARAPlaybackRegionReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples)\r
{\r
bool success = false;\r
\r
~ARAAudioSourceReader() override;\r
\r
- bool readSamples (int** destSamples,\r
+ bool readSamples (int* const* destSamples,\r
int numDestChannels,\r
int startOffsetInDestBuffer,\r
int64 startSampleInFile,\r
*/\r
void invalidate();\r
\r
- bool readSamples (int** destSamples,\r
+ bool readSamples (int* const* destSamples,\r
int numDestChannels,\r
int startOffsetInDestBuffer,\r
int64 startSampleInFile,\r
if (numSamplesToRead <= 0)\r
return true;\r
\r
- if (! readSamples (const_cast<int**> (destChannels),\r
+ if (! readSamples (destChannels,\r
jmin ((int) numChannels, numDestChannels), startOffsetInDestBuffer,\r
startSampleInSource, numSamplesToRead))\r
return false;\r
to begin reading. This value is guaranteed to be >= 0.\r
@param numSamples the number of samples to read\r
*/\r
- virtual bool readSamples (int** destChannels,\r
+ virtual bool readSamples (int* const* destChannels,\r
int numDestChannels,\r
int startOffsetInDestBuffer,\r
int64 startSampleInFile,\r
/** Used by AudioFormatReader subclasses to clear any parts of the data blocks that lie\r
beyond the end of their available length.\r
*/\r
- static void clearSamplesBeyondAvailableLength (int** destChannels, int numDestChannels,\r
+ static void clearSamplesBeyondAvailableLength (int* const* destChannels, int numDestChannels,\r
int startOffsetInDestBuffer, int64 startSampleInFile,\r
int& numSamples, int64 fileLengthInSamples)\r
{\r
}\r
\r
//==============================================================================\r
-bool AudioSubsectionReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool AudioSubsectionReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples)\r
{\r
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
\r
\r
//==============================================================================\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override;\r
\r
void readMaxLevels (int64 startSample, int64 numSamples,\r
timeoutMs = timeoutMilliseconds;\r
}\r
\r
-bool BufferingAudioReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool BufferingAudioReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples)\r
{\r
auto startTime = Time::getMillisecondCounter();\r
numChannels = (unsigned int) buffer.getNumChannels();\r
}\r
\r
- bool readSamples (int** destChannels, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destChannels, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override\r
{\r
clearSamplesBeyondAvailableLength (destChannels, numDestChannels, startOffsetInDestBuffer,\r
void runTest() override\r
{\r
TimeSliceThread timeSlice ("TestBackgroundThread");\r
- timeSlice.startThread (5);\r
+ timeSlice.startThread (Thread::Priority::normal);\r
\r
beginTest ("Timeout");\r
{\r
numChannels = 2;\r
}\r
\r
- bool readSamples (int**, int, int, int64, int) override\r
+ bool readSamples (int* const*, int, int, int64, int) override\r
{\r
Thread::sleep (100);\r
return true;\r
void setReadTimeout (int timeoutMilliseconds) noexcept;\r
\r
//==============================================================================\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override;\r
\r
private:\r
\r
ID: juce_audio_formats\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_audio_basics\r
OSXFrameworks: CoreAudio CoreMIDI QuartzCore AudioToolbox\r
"-Wzero-as-null-pointer-constant",\r
"-Winconsistent-missing-destructor-override",\r
"-Wfour-char-constants",\r
- "-Wtautological-overlap-compare")\r
+ "-Wtautological-overlap-compare",\r
+ "-Wdeprecated-declarations")\r
\r
#include <AAX_Version.h>\r
\r
}\r
\r
const auto effectiveRate = info.getFrameRate().hasValue() ? info.getFrameRate()->getEffectiveRate() : 0.0;\r
- info.setEditOriginTime (effectiveRate != 0.0 ? makeOptional (offset / effectiveRate) : nullopt);\r
+ info.setEditOriginTime (makeOptional (effectiveRate != 0.0 ? offset / effectiveRate : offset));\r
\r
return info;\r
}\r
\r
if (details.parameterInfoChanged)\r
{\r
- auto numParameters = juceParameters.getNumParameters();\r
-\r
- for (int i = 0; i < numParameters; ++i)\r
- {\r
- if (auto* p = mParameterManager.GetParameterByID (getAAXParamIDFromJuceIndex (i)))\r
- {\r
- auto newName = juceParameters.getParamForIndex (i)->getName (31);\r
-\r
- if (p->Name() != newName.toRawUTF8())\r
- p->SetName (AAX_CString (newName.toRawUTF8()));\r
- }\r
- }\r
+ for (const auto* param : juceParameters)\r
+ if (auto* aaxParam = mParameterManager.GetParameterByID (getAAXParamIDFromJuceIndex (param->getParameterIndex())))\r
+ syncParameterAttributes (aaxParam, param);\r
}\r
\r
if (details.latencyChanged)\r
return defaultLayout;\r
}\r
\r
+ void syncParameterAttributes (AAX_IParameter* aaxParam, const AudioProcessorParameter* juceParam)\r
+ {\r
+ if (juceParam == nullptr)\r
+ return;\r
+\r
+ {\r
+ auto newName = juceParam->getName (31);\r
+\r
+ if (aaxParam->Name() != newName.toRawUTF8())\r
+ aaxParam->SetName (AAX_CString (newName.toRawUTF8()));\r
+ }\r
+\r
+ {\r
+ auto newType = juceParam->isDiscrete() ? AAX_eParameterType_Discrete : AAX_eParameterType_Continuous;\r
+\r
+ if (aaxParam->GetType() != newType)\r
+ aaxParam->SetType (newType);\r
+ }\r
+\r
+ {\r
+ auto newNumSteps = static_cast<uint32_t> (juceParam->getNumSteps());\r
+\r
+ if (aaxParam->GetNumberOfSteps() != newNumSteps)\r
+ aaxParam->SetNumberOfSteps (newNumSteps);\r
+ }\r
+\r
+ {\r
+ auto defaultValue = juceParam->getDefaultValue();\r
+\r
+ if (! approximatelyEqual (static_cast<float> (aaxParam->GetNormalizedDefaultValue()), defaultValue))\r
+ aaxParam->SetNormalizedDefaultValue (defaultValue);\r
+ }\r
+ }\r
+\r
//==============================================================================\r
ScopedJuceInitialiser_GUI libraryInitialiser;\r
\r
#include <ARA_Library/PlugIn/ARAPlug.cpp>\r
#include <ARA_Library/Dispatch/ARAPlugInDispatch.cpp>\r
#include <ARA_Library/Utilities/ARAPitchInterpretation.cpp>\r
+#include <ARA_Library/Utilities/ARAChannelArrangement.cpp>\r
\r
JUCE_END_IGNORE_WARNINGS_MSVC\r
JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+++ /dev/null
-/*
- File: AUResources.r
- Abstract: AUResources.r
- Version: 1.1
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
- Inc. ("Apple") in consideration of your agreement to the following
- terms, and your use, installation, modification or redistribution of
- this Apple software constitutes acceptance of these terms. If you do
- not agree with these terms, please do not use, install, modify or
- redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and
- subject to these terms, Apple grants you a personal, non-exclusive
- license, under Apple's copyrights in this original Apple software (the
- "Apple Software"), to use, reproduce, modify and redistribute the Apple
- Software, with or without modifications, in source and/or binary forms;
- provided that if you redistribute the Apple Software in its entirety and
- without modifications, you must retain this notice and the following
- text and disclaimers in all such redistributions of the Apple Software.
- Neither the name, trademarks, service marks or logos of Apple Inc. may
- be used to endorse or promote products derived from the Apple Software
- without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or
- implied, are granted by Apple herein, including but not limited to any
- patent rights that may be infringed by your derivative works or by other
- works in which the Apple Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE
- MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
- THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
- OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
- MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
- AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
- STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-
- Copyright (C) 2014 Apple Inc. All Rights Reserved.
-
-*/
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// AUResources.r
-//
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-/* sample macro definitions -- all of these symbols must be defined
-#define RES_ID kHALOutputResID
-#define COMP_TYPE kAudioUnitComponentType
-#define COMP_SUBTYPE kAudioUnitOutputSubType
-#define COMP_MANUF kAudioUnitAudioHardwareOutputSubSubType
-#define VERSION 0x00010000
-#define NAME "AudioHALOutput"
-#define DESCRIPTION "Audio hardware output AudioUnit"
-#define ENTRY_POINT "AUHALEntry"
-*/
-#define UseExtendedThingResource 1
-
-#include <CoreServices/CoreServices.r>
-
-// this is a define used to indicate that a component has no static data that would mean
-// that no more than one instance could be open at a time - never been true for AUs
-#ifndef cmpThreadSafeOnMac
-#define cmpThreadSafeOnMac 0x10000000
-#endif
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-resource 'STR ' (RES_ID, purgeable) {
- NAME
-};
-
-resource 'STR ' (RES_ID + 1, purgeable) {
- DESCRIPTION
-};
-
-resource 'dlle' (RES_ID) {
- ENTRY_POINT
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-resource 'thng' (RES_ID, NAME) {
- COMP_TYPE,
- COMP_SUBTYPE,
- COMP_MANUF,
- 0, 0, 0, 0, // no 68K
- 'STR ', RES_ID,
- 'STR ', RES_ID + 1,
- 0, 0, /* icon */
- VERSION,
- componentHasMultiplePlatforms | componentDoAutoVersion,
- 0,
- {
- #if defined(ppc_YES)
- cmpThreadSafeOnMac,
- 'dlle', RES_ID, platformPowerPCNativeEntryPoint
- #define NeedLeadingComma 1
- #endif
- #if defined(ppc64_YES)
- #if defined(NeedLeadingComma)
- ,
- #endif
- cmpThreadSafeOnMac,
- 'dlle', RES_ID, platformPowerPC64NativeEntryPoint
- #define NeedLeadingComma 1
- #endif
- #if defined(i386_YES)
- #if defined(NeedLeadingComma)
- ,
- #endif
- cmpThreadSafeOnMac,
- 'dlle', RES_ID, platformIA32NativeEntryPoint
- #define NeedLeadingComma 1
- #endif
- #if defined(x86_64_YES)
- #if defined(NeedLeadingComma)
- ,
- #endif
- cmpThreadSafeOnMac,
- 'dlle', RES_ID, 8
- #define NeedLeadingComma 1
- #endif
- // JUCE CHANGE STARTS HERE
- #if defined(arm64_YES)
- #if defined(NeedLeadingComma)
- ,
- #endif
- cmpThreadSafeOnMac,
- 'dlle', RES_ID, 9
- #define NeedLeadingComma 1
- #endif
- // JUCE CHANGE ENDS HERE
- }
-};
-
-#undef RES_ID
-#undef COMP_TYPE
-#undef COMP_SUBTYPE
-#undef COMP_MANUF
-#undef VERSION
-#undef NAME
-#undef DESCRIPTION
-#undef ENTRY_POINT
-#undef NeedLeadingComma
+++ /dev/null
-# ==============================================================================
-#
-# This file is part of the JUCE library.
-# Copyright (c) 2022 - Raw Material Software Limited
-#
-# JUCE is an open source library subject to commercial or open-source
-# licensing.
-#
-# By using JUCE, you agree to the terms of both the JUCE 7 End-User License
-# Agreement and JUCE Privacy Policy.
-#
-# End User License Agreement: www.juce.com/juce-7-licence
-# Privacy Policy: www.juce.com/juce-privacy-policy
-#
-# Or: You may also use this code under the terms of the GPL v3 (see
-# www.gnu.org/licenses).
-#
-# JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
-# EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
-# DISCLAIMED.
-#
-# ==============================================================================
-
-add_executable(juce_lv2_helper LV2/juce_LV2TurtleDumpProgram.cpp)
-add_executable(juce::juce_lv2_helper ALIAS juce_lv2_helper)
-target_compile_features(juce_lv2_helper PRIVATE cxx_std_14)
-set_target_properties(juce_lv2_helper PROPERTIES BUILD_WITH_INSTALL_RPATH ON)
-target_link_libraries(juce_lv2_helper PRIVATE ${CMAKE_DL_LIBS})
-install(TARGETS juce_lv2_helper EXPORT LV2_HELPER DESTINATION "bin/JUCE-${JUCE_VERSION}")
==============================================================================\r
*/\r
\r
+#include <cstdint>\r
+#include <cstdio>\r
+\r
#ifdef _WIN32\r
#include <windows.h>\r
+ #include <tchar.h>\r
HMODULE dlopen (const char* filename, int) { return LoadLibrary (filename); }\r
FARPROC dlsym (HMODULE handle, const char* name) { return GetProcAddress (handle, name); }\r
+ void printError()\r
+ {\r
+ constexpr DWORD numElements = 256;\r
+ TCHAR messageBuffer[numElements]{};\r
+\r
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\r
+ nullptr,\r
+ GetLastError(),\r
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),\r
+ messageBuffer,\r
+ numElements - 1,\r
+ nullptr);\r
+\r
+ _tprintf ("%s", messageBuffer);\r
+ }\r
enum { RTLD_LAZY = 0 };\r
#else\r
#include <dlfcn.h>\r
+ void printError() { printf ("%s\n", dlerror()); }\r
#endif\r
\r
-#include <cstdint>\r
-\r
-// Replicating some of the LV2 header here so that we don't have to set up any\r
+// Replicating part of the LV2 header here so that we don't have to set up any\r
// custom include paths for this file.\r
// Normally this would be a bad idea, but the LV2 API has to keep these definitions\r
// in order to remain backwards-compatible.\r
};\r
\r
if (auto* handle = dlopen (libraryPath, RTLD_LAZY))\r
+ {\r
if (auto* getDescriptor = reinterpret_cast<const LV2_Descriptor* (*) (uint32_t)> (dlsym (handle, "lv2_descriptor")))\r
if (auto* descriptor = getDescriptor (0))\r
if (auto* extensionData = descriptor->extension_data)\r
if (auto* recallFeature = reinterpret_cast<const RecallFeature*> (extensionData ("https://lv2-extensions.juce.com/turtle_recall")))\r
if (auto* doRecall = recallFeature->doRecall)\r
return doRecall (libraryPath);\r
+ }\r
+ else\r
+ {\r
+ printError();\r
+ }\r
\r
return 1;\r
}\r
template<typename UnaryFunction>\r
static void iterateAudioBuffer (AudioBuffer<float>& ab, UnaryFunction fn)\r
{\r
- float** sampleData = ab.getArrayOfWritePointers();\r
+ float* const* sampleData = ab.getArrayOfWritePointers();\r
\r
for (int c = ab.getNumChannels(); --c >= 0;)\r
for (int s = ab.getNumSamples(); --s >= 0;)\r
const auto processor = LV2PluginInstance::createProcessorInstance();\r
const File absolutePath { CharPointer_UTF8 { libraryPath } };\r
\r
- processor->enableAllBuses();\r
+ const auto writers = { writeManifestTtl, writeDspTtl, writeUiTtl };\r
\r
- for (auto* fn : { writeManifestTtl, writeDspTtl, writeUiTtl })\r
+ const auto wroteSuccessfully = [&processor, &absolutePath] (auto* fn)\r
{\r
const auto result = fn (*processor, absolutePath);\r
\r
- if (result.wasOk())\r
- continue;\r
+ if (! result.wasOk())\r
+ std::cerr << result.getErrorMessage() << '\n';\r
\r
- std::cerr << result.getErrorMessage() << '\n';\r
- return 1;\r
- }\r
+ return result.wasOk();\r
+ };\r
\r
- return 0;\r
+ return std::all_of (writers.begin(), writers.end(), wroteSuccessfully) ? 0 : 1;\r
};\r
\r
private:\r
\r
On some platforms (such as iOS 10), the expected buffer size reported in\r
audioDeviceAboutToStart may be smaller than the blocks passed to\r
- audioDeviceIOCallback. This can lead to out-of-bounds reads if the render\r
+ audioDeviceIOCallbackWithContext. This can lead to out-of-bounds reads if the render\r
callback depends on additional buffers which were initialised using the\r
smaller size.\r
\r
inner.audioDeviceAboutToStart (device);\r
}\r
\r
- void audioDeviceIOCallbackWithContext (const float** inputChannelData,\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
int numInputChannels,\r
- float** outputChannelData,\r
+ float* const* outputChannelData,\r
int numOutputChannels,\r
int numSamples,\r
const AudioIODeviceCallbackContext& context) override\r
};\r
\r
//==============================================================================\r
- void audioDeviceIOCallbackWithContext (const float** inputChannelData,\r
+ void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
int numInputChannels,\r
- float** outputChannelData,\r
+ float* const* outputChannelData,\r
int numOutputChannels,\r
int numSamples,\r
const AudioIODeviceCallbackContext& context) override\r
}\r
\r
//==============================================================================\r
-namespace UnityCallbacks\r
+static UnityAudioEffectDefinition getEffectDefinition()\r
{\r
- static int UNITY_INTERFACE_API createCallback (UnityAudioEffectState* state)\r
+ const auto wrapper = std::make_unique<AudioProcessorUnityWrapper> (true);\r
+ const String originalName { JucePlugin_Name };\r
+ const auto name = (! originalName.startsWithIgnoreCase ("audioplugin") ? "audioplugin_" : "") + originalName;\r
+\r
+ UnityAudioEffectDefinition result{};\r
+ name.copyToUTF8 (result.name, (size_t) numElementsInArray (result.name));\r
+\r
+ result.structSize = sizeof (UnityAudioEffectDefinition);\r
+ result.parameterStructSize = sizeof (UnityAudioParameterDefinition);\r
+\r
+ result.apiVersion = UNITY_AUDIO_PLUGIN_API_VERSION;\r
+ result.pluginVersion = JucePlugin_VersionCode;\r
+\r
+ // effects must set this to 0, generators > 0\r
+ result.channels = (wrapper->getNumInputChannels() != 0 ? 0\r
+ : static_cast<uint32> (wrapper->getNumOutputChannels()));\r
+\r
+ wrapper->declareParameters (result);\r
+\r
+ result.create = [] (UnityAudioEffectState* state)\r
{\r
auto* pluginInstance = new AudioProcessorUnityWrapper (false);\r
pluginInstance->create (state);\r
onWrapperCreation (pluginInstance);\r
\r
return 0;\r
- }\r
+ };\r
\r
- static int UNITY_INTERFACE_API releaseCallback (UnityAudioEffectState* state)\r
+ result.release = [] (UnityAudioEffectState* state)\r
{\r
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
pluginInstance->release();\r
shutdownJuce_GUI();\r
\r
return 0;\r
- }\r
+ };\r
\r
- static int UNITY_INTERFACE_API resetCallback (UnityAudioEffectState* state)\r
+ result.reset = [] (UnityAudioEffectState* state)\r
{\r
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
pluginInstance->reset();\r
\r
return 0;\r
- }\r
+ };\r
\r
- static int UNITY_INTERFACE_API setPositionCallback (UnityAudioEffectState* state, unsigned int pos)\r
+ result.setPosition = [] (UnityAudioEffectState* state, unsigned int pos)\r
{\r
ignoreUnused (state, pos);\r
\r
return 0;\r
- }\r
+ };\r
+\r
+ result.process = [] (UnityAudioEffectState* state,\r
+ float* inBuffer,\r
+ float* outBuffer,\r
+ unsigned int bufferSize,\r
+ int numInChannels,\r
+ int numOutChannels)\r
+ {\r
+ auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
+\r
+ if (pluginInstance != nullptr)\r
+ {\r
+ auto isPlaying = ((state->flags & stateIsPlaying) != 0);\r
+ auto isMuted = ((state->flags & stateIsMuted) != 0);\r
+ auto isPaused = ((state->flags & stateIsPaused) != 0);\r
\r
- static int UNITY_INTERFACE_API setFloatParameterCallback (UnityAudioEffectState* state, int index, float value)\r
+ const auto bypassed = ! isPlaying || (isMuted || isPaused);\r
+ pluginInstance->process (inBuffer, outBuffer, static_cast<int> (bufferSize), numInChannels, numOutChannels, bypassed);\r
+ }\r
+ else\r
+ {\r
+ FloatVectorOperations::clear (outBuffer, static_cast<int> (bufferSize) * numOutChannels);\r
+ }\r
+\r
+ return 0;\r
+ };\r
+\r
+ result.setFloatParameter = [] (UnityAudioEffectState* state, int index, float value)\r
{\r
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
pluginInstance->setParameter (index, value);\r
\r
return 0;\r
- }\r
+ };\r
\r
- static int UNITY_INTERFACE_API getFloatParameterCallback (UnityAudioEffectState* state, int index, float* value, char* valueStr)\r
+ result.getFloatParameter = [] (UnityAudioEffectState* state, int index, float* value, char* valueStr)\r
{\r
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
*value = pluginInstance->getParameter (index);\r
pluginInstance->getParameterString (index).copyToUTF8 (valueStr, 15);\r
\r
return 0;\r
- }\r
+ };\r
\r
- static int UNITY_INTERFACE_API getFloatBufferCallback (UnityAudioEffectState* state, const char* name, float* buffer, int numSamples)\r
+ result.getFloatBuffer = [] (UnityAudioEffectState* state, const char* kind, float* buffer, int numSamples)\r
{\r
ignoreUnused (numSamples);\r
\r
- auto nameStr = String (name);\r
+ const StringRef kindStr { kind };\r
\r
- if (nameStr == "Editor")\r
+ if (kindStr == StringRef ("Editor"))\r
{\r
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
\r
buffer[0] = pluginInstance->hasEditor() ? 1.0f : 0.0f;\r
}\r
- else if (nameStr == "ID")\r
+ else if (kindStr == StringRef ("ID"))\r
{\r
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
\r
\r
return 0;\r
}\r
- else if (nameStr == "Size")\r
+ else if (kindStr == StringRef ("Size"))\r
{\r
auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
\r
}\r
\r
return 0;\r
- }\r
-\r
- static int UNITY_INTERFACE_API processCallback (UnityAudioEffectState* state, float* inBuffer, float* outBuffer,\r
- unsigned int bufferSize, int numInChannels, int numOutChannels)\r
- {\r
- auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
-\r
- if (pluginInstance != nullptr)\r
- {\r
- auto isPlaying = ((state->flags & stateIsPlaying) != 0);\r
- auto isMuted = ((state->flags & stateIsMuted) != 0);\r
- auto isPaused = ((state->flags & stateIsPaused) != 0);\r
-\r
- const auto bypassed = ! isPlaying || (isMuted || isPaused);\r
- pluginInstance->process (inBuffer, outBuffer, static_cast<int> (bufferSize), numInChannels, numOutChannels, bypassed);\r
- }\r
- else\r
- {\r
- FloatVectorOperations::clear (outBuffer, static_cast<int> (bufferSize) * numOutChannels);\r
- }\r
-\r
- return 0;\r
- }\r
-}\r
-\r
-//==============================================================================\r
-static void declareEffect (UnityAudioEffectDefinition& definition)\r
-{\r
- memset (&definition, 0, sizeof (definition));\r
-\r
- std::unique_ptr<AudioProcessorUnityWrapper> wrapper = std::make_unique<AudioProcessorUnityWrapper> (true);\r
-\r
- String name (JucePlugin_Name);\r
- if (! name.startsWithIgnoreCase ("audioplugin"))\r
- name = "audioplugin_" + name;\r
-\r
- name.copyToUTF8 (definition.name, (size_t) numElementsInArray (definition.name));\r
-\r
- definition.structSize = sizeof (UnityAudioEffectDefinition);\r
- definition.parameterStructSize = sizeof (UnityAudioParameterDefinition);\r
-\r
- definition.apiVersion = UNITY_AUDIO_PLUGIN_API_VERSION;\r
- definition.pluginVersion = JucePlugin_VersionCode;\r
+ };\r
\r
- // effects must set this to 0, generators > 0\r
- definition.channels = (wrapper->getNumInputChannels() != 0 ? 0\r
- : static_cast<uint32> (wrapper->getNumOutputChannels()));\r
-\r
- wrapper->declareParameters (definition);\r
-\r
- definition.create = UnityCallbacks::createCallback;\r
- definition.release = UnityCallbacks::releaseCallback;\r
- definition.reset = UnityCallbacks::resetCallback;\r
- definition.setPosition = UnityCallbacks::setPositionCallback;\r
- definition.process = UnityCallbacks::processCallback;\r
- definition.setFloatParameter = UnityCallbacks::setFloatParameterCallback;\r
- definition.getFloatParameter = UnityCallbacks::getFloatParameterCallback;\r
- definition.getFloatBuffer = UnityCallbacks::getFloatBufferCallback;\r
+ return result;\r
}\r
\r
} // namespace juce\r
\r
+// From reading the example code, it seems that the triple indirection indicates\r
+// an out-value of an array of pointers. That is, after calling this function, definitionsPtr\r
+// should point to a pre-existing/static array of pointer-to-effect-definition.\r
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API UnityGetAudioEffectDefinitions (UnityAudioEffectDefinition*** definitionsPtr)\r
{\r
if (juce::getWrapperMap().size() == 0)\r
juce::initialiseJuce_GUI();\r
\r
- static bool hasInitialised = false;\r
-\r
- if (! hasInitialised)\r
+ static std::once_flag flag;\r
+ std::call_once (flag, []\r
{\r
juce::PluginHostType::jucePlugInClientCurrentWrapperType = juce::AudioProcessor::wrapperType_Unity;\r
juce::juce_createUnityPeerFn = juce::createUnityPeer;\r
+ });\r
\r
- hasInitialised = true;\r
- }\r
-\r
- auto* definition = new UnityAudioEffectDefinition();\r
- juce::declareEffect (*definition);\r
-\r
- *definitionsPtr = &definition;\r
+ static auto definition = juce::getEffectDefinition();\r
+ static UnityAudioEffectDefinition* definitions[] { &definition };\r
+ *definitionsPtr = definitions;\r
\r
return 1;\r
}\r
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion",\r
"-Wshadow",\r
"-Wdeprecated-register",\r
+ "-Wdeprecated-declarations",\r
"-Wunused-parameter",\r
"-Wdeprecated-writable-strings",\r
"-Wnon-virtual-dtor",\r
// before that happens.\r
X11Symbols::getInstance()->xFlush (display);\r
#elif JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
- checkHostWindowScaleFactor();\r
+ checkHostWindowScaleFactor (true);\r
startTimer (500);\r
#endif\r
#elif JUCE_MAC\r
}\r
\r
#if JUCE_WIN_PER_MONITOR_DPI_AWARE\r
- void checkHostWindowScaleFactor()\r
+ void checkHostWindowScaleFactor (bool force = false)\r
{\r
auto hostWindowScale = (float) getScaleFactorForWindow ((HostWindowType) hostWindow);\r
\r
- if (hostWindowScale > 0.0f && ! approximatelyEqual (hostWindowScale, wrapper.editorScaleFactor))\r
- wrapper.handleSetContentScaleFactor (hostWindowScale);\r
+ if (force || (hostWindowScale > 0.0f && ! approximatelyEqual (hostWindowScale, wrapper.editorScaleFactor)))\r
+ wrapper.handleSetContentScaleFactor (hostWindowScale, force);\r
}\r
\r
void timerCallback() override\r
return 0;\r
}\r
\r
- pointer_sized_int handleSetContentScaleFactor (float scale)\r
+ pointer_sized_int handleSetContentScaleFactor (float scale, bool force = false)\r
{\r
checkWhetherMessageThreadIsCorrect();\r
#if JUCE_LINUX || JUCE_BSD\r
#endif\r
\r
#if ! JUCE_MAC\r
- if (! approximatelyEqual (scale, editorScaleFactor))\r
+ if (force || ! approximatelyEqual (scale, editorScaleFactor))\r
{\r
editorScaleFactor = scale;\r
\r
}\r
\r
#else\r
- ignoreUnused (scale);\r
+ ignoreUnused (scale, force);\r
#endif\r
\r
return 1;\r
{\r
info.id = Vst::kRootUnitId;\r
info.parentUnitId = Vst::kNoParentUnitId;\r
- info.programListId = Vst::kNoProgramListId;\r
+ info.programListId = getProgramListCount() > 0\r
+ ? static_cast<Vst::ProgramListID> (programParamID)\r
+ : Vst::kNoProgramListId;\r
\r
- toString128 (info.name, TRANS("Root Unit"));\r
+ toString128 (info.name, TRANS ("Root Unit"));\r
\r
return kResultTrue;\r
}\r
info.id = static_cast<Vst::ProgramListID> (programParamID);\r
info.programCount = static_cast<Steinberg::int32> (audioProcessor->getNumPrograms());\r
\r
- toString128 (info.name, TRANS("Factory Presets"));\r
+ toString128 (info.name, TRANS ("Factory Presets"));\r
\r
return kResultTrue;\r
}\r
\r
tresult PLUGIN_API getUnitByBus (Vst::MediaType, Vst::BusDirection, Steinberg::int32, Steinberg::int32, Vst::UnitID& unitId) override\r
{\r
- zerostruct (unitId);\r
- return kNotImplemented;\r
+ unitId = Vst::kRootUnitId;\r
+ return kResultOk;\r
}\r
\r
//==============================================================================\r
if (audioProcessor != nullptr)\r
return audioProcessor->getUnitInfo (unitIndex, info);\r
\r
+ jassertfalse;\r
if (unitIndex == 0)\r
{\r
info.id = Vst::kRootUnitId;\r
info.parentUnitId = Vst::kNoParentUnitId;\r
info.programListId = Vst::kNoProgramListId;\r
\r
- toString128 (info.name, TRANS("Root Unit"));\r
+ toString128 (info.name, TRANS ("Root Unit"));\r
\r
return kResultTrue;\r
}\r
\r
- jassertfalse;\r
zerostruct (info);\r
return kResultFalse;\r
}\r
#if JUCE_MAC\r
if (getHostType().type == PluginHostType::SteinbergCubase10)\r
cubase10Workaround.reset (new Cubase10WindowResizeWorkaround (*this));\r
- #else\r
- if (! approximatelyEqual (editorScaleFactor, ec.lastScaleFactorReceived))\r
- setContentScaleFactor (ec.lastScaleFactorReceived);\r
#endif\r
}\r
\r
createContentWrapperComponentIfNeeded();\r
\r
#if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD\r
+ // If the plugin was last opened at a particular scale, try to reapply that scale here.\r
+ // Note that we do this during attach(), rather than in JuceVST3Editor(). During the\r
+ // constructor, we don't have a host plugFrame, so\r
+ // ContentWrapperComponent::resizeHostWindow() won't do anything, and the content\r
+ // wrapper component will be left at the wrong size.\r
+ applyScaleFactor (StoredScaleFactor{}.withInternal (owner->lastScaleFactorReceived));\r
+\r
+ // Check the host scale factor *before* calling addToDesktop, so that the initial\r
+ // window size during addToDesktop is correct for the current platform scale factor.\r
+ #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
+ component->checkHostWindowScaleFactor();\r
+ #endif\r
+\r
component->setOpaque (true);\r
component->addToDesktop (0, (void*) systemWindow);\r
component->setVisible (true);\r
\r
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
- component->checkHostWindowScaleFactor();\r
component->startTimer (500);\r
#endif\r
\r
return kResultFalse;\r
}\r
\r
- tresult PLUGIN_API setContentScaleFactor (Steinberg::IPlugViewContentScaleSupport::ScaleFactor factor) override\r
+ tresult PLUGIN_API setContentScaleFactor (const Steinberg::IPlugViewContentScaleSupport::ScaleFactor factor) override\r
{\r
#if ! JUCE_MAC\r
- if (! approximatelyEqual ((float) factor, editorScaleFactor))\r
+ const auto scaleToApply = [&]\r
{\r
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
// Cubase 10 only sends integer scale factors, so correct this for fractional scales\r
- if (getHostType().type == PluginHostType::SteinbergCubase10)\r
- {\r
- auto hostWindowScale = (Steinberg::IPlugViewContentScaleSupport::ScaleFactor) getScaleFactorForWindow ((HWND) systemWindow);\r
+ if (getHostType().type != PluginHostType::SteinbergCubase10)\r
+ return factor;\r
\r
- if (hostWindowScale > 0.0 && ! approximatelyEqual (factor, hostWindowScale))\r
- factor = hostWindowScale;\r
- }\r
- #endif\r
+ const auto hostWindowScale = (Steinberg::IPlugViewContentScaleSupport::ScaleFactor) getScaleFactorForWindow (static_cast<HWND> (systemWindow));\r
\r
- editorScaleFactor = (float) factor;\r
+ if (hostWindowScale <= 0.0 || approximatelyEqual (factor, hostWindowScale))\r
+ return factor;\r
\r
- if (owner != nullptr)\r
- owner->lastScaleFactorReceived = editorScaleFactor;\r
+ return hostWindowScale;\r
+ #else\r
+ return factor;\r
+ #endif\r
+ }();\r
\r
- if (component != nullptr)\r
- {\r
- #if JUCE_LINUX || JUCE_BSD\r
- const MessageManagerLock mmLock;\r
- #endif\r
- component->setEditorScaleFactor (editorScaleFactor);\r
- }\r
- }\r
+ applyScaleFactor (scaleFactor.withHost (scaleToApply));\r
\r
return kResultTrue;\r
#else\r
\r
pluginEditor->setHostContext (editorHostContext.get());\r
#if ! JUCE_MAC\r
- pluginEditor->setScaleFactor (owner.editorScaleFactor);\r
+ pluginEditor->setScaleFactor (owner.scaleFactor.get());\r
#endif\r
\r
addAndMakeVisible (pluginEditor.get());\r
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
void checkHostWindowScaleFactor()\r
{\r
- auto hostWindowScale = (float) getScaleFactorForWindow ((HWND) owner.systemWindow);\r
+ const auto estimatedScale = (float) getScaleFactorForWindow (static_cast<HWND> (owner.systemWindow));\r
\r
- if (hostWindowScale > 0.0 && ! approximatelyEqual (hostWindowScale, owner.editorScaleFactor))\r
- owner.setContentScaleFactor (hostWindowScale);\r
+ if (estimatedScale > 0.0)\r
+ owner.applyScaleFactor (owner.scaleFactor.withInternal (estimatedScale));\r
}\r
\r
void timerCallback() override\r
\r
std::unique_ptr<Cubase10WindowResizeWorkaround> cubase10Workaround;\r
#else\r
- float editorScaleFactor = 1.0f;\r
+ class StoredScaleFactor\r
+ {\r
+ public:\r
+ StoredScaleFactor withHost (float x) const { return withMember (*this, &StoredScaleFactor::host, x); }\r
+ StoredScaleFactor withInternal (float x) const { return withMember (*this, &StoredScaleFactor::internal, x); }\r
+ float get() const { return host.value_or (internal); }\r
+\r
+ private:\r
+ std::optional<float> host;\r
+ float internal = 1.0f;\r
+ };\r
+\r
+ void applyScaleFactor (const StoredScaleFactor newFactor)\r
+ {\r
+ const auto previous = std::exchange (scaleFactor, newFactor).get();\r
+\r
+ if (previous == scaleFactor.get())\r
+ return;\r
+\r
+ if (owner != nullptr)\r
+ owner->lastScaleFactorReceived = scaleFactor.get();\r
+\r
+ if (component != nullptr)\r
+ {\r
+ #if JUCE_LINUX || JUCE_BSD\r
+ const MessageManagerLock mmLock;\r
+ #endif\r
+ component->setEditorScaleFactor (scaleFactor.get());\r
+ }\r
+ }\r
+\r
+ StoredScaleFactor scaleFactor;\r
\r
#if JUCE_WINDOWS\r
WindowsHooks hooks;\r
if (numIns > numInputBuses || numOuts > numOutputBuses)\r
return false;\r
\r
- auto requested = pluginInstance->getBusesLayout();\r
+ // see the following documentation to understand the correct way to react to this callback\r
+ // https://steinbergmedia.github.io/vst3_doc/vstinterfaces/classSteinberg_1_1Vst_1_1IAudioProcessor.html#ad3bc7bac3fd3b194122669be2a1ecc42\r
\r
- for (int i = 0; i < numIns; ++i)\r
- requested.getChannelSet (true, i) = getChannelSetForSpeakerArrangement (inputs[i]);\r
+ const auto requestedLayout = [&]\r
+ {\r
+ auto result = pluginInstance->getBusesLayout();\r
+\r
+ for (int i = 0; i < numIns; ++i)\r
+ result.getChannelSet (true, i) = getChannelSetForSpeakerArrangement (inputs[i]);\r
\r
- for (int i = 0; i < numOuts; ++i)\r
- requested.getChannelSet (false, i) = getChannelSetForSpeakerArrangement (outputs[i]);\r
+ for (int i = 0; i < numOuts; ++i)\r
+ result.getChannelSet (false, i) = getChannelSetForSpeakerArrangement (outputs[i]);\r
+\r
+ return result;\r
+ }();\r
\r
#ifdef JucePlugin_PreferredChannelConfigurations\r
short configs[][2] = { JucePlugin_PreferredChannelConfigurations };\r
- if (! AudioProcessor::containsLayout (requested, configs))\r
+ if (! AudioProcessor::containsLayout (requestedLayout, configs))\r
return kResultFalse;\r
#endif\r
\r
- if (! pluginInstance->setBusesLayoutWithoutEnabling (requested))\r
- return kResultFalse;\r
+ if (pluginInstance->checkBusesLayoutSupported (requestedLayout))\r
+ {\r
+ if (! pluginInstance->setBusesLayoutWithoutEnabling (requestedLayout))\r
+ return kResultFalse;\r
\r
- bufferMapper.updateFromProcessor (*pluginInstance);\r
- return kResultTrue;\r
+ bufferMapper.updateFromProcessor (*pluginInstance);\r
+ return kResultTrue;\r
+ }\r
+\r
+ // apply layout changes in reverse order as Steinberg says we should prioritize main buses\r
+ const auto nextBest = [this, numInputBuses, numOutputBuses, &requestedLayout]\r
+ {\r
+ auto layout = pluginInstance->getBusesLayout();\r
+\r
+ for (auto busIdx = jmax (numInputBuses, numOutputBuses) - 1; busIdx >= 0; --busIdx)\r
+ for (const auto isInput : { true, false })\r
+ if (auto* bus = pluginInstance->getBus (isInput, busIdx))\r
+ bus->isLayoutSupported (requestedLayout.getChannelSet (isInput, busIdx), &layout);\r
+\r
+ return layout;\r
+ }();\r
+\r
+ if (pluginInstance->setBusesLayoutWithoutEnabling (nextBest))\r
+ bufferMapper.updateFromProcessor (*pluginInstance);\r
+\r
+ return kResultFalse;\r
}\r
\r
tresult PLUGIN_API getBusArrangement (Vst::BusDirection dir, Steinberg::int32 index, Vst::SpeakerArrangement& arr) override\r
{\r
jassert (pluginInstance != nullptr);\r
\r
- auto numParamsChanged = paramChanges.getParameterCount();\r
+ struct ParamChangeInfo\r
+ {\r
+ Steinberg::int32 offsetSamples = 0;\r
+ double value = 0.0;\r
+ };\r
+\r
+ const auto getPointFromQueue = [] (Steinberg::Vst::IParamValueQueue* queue, Steinberg::int32 index)\r
+ {\r
+ ParamChangeInfo result;\r
+ return queue->getPoint (index, result.offsetSamples, result.value) == kResultTrue\r
+ ? makeOptional (result)\r
+ : nullopt;\r
+ };\r
+\r
+ const auto numParamsChanged = paramChanges.getParameterCount();\r
\r
for (Steinberg::int32 i = 0; i < numParamsChanged; ++i)\r
{\r
if (auto* paramQueue = paramChanges.getParameterData (i))\r
{\r
- auto numPoints = paramQueue->getPointCount();\r
-\r
- Steinberg::int32 offsetSamples = 0;\r
- double value = 0.0;\r
+ const auto vstParamID = paramQueue->getParameterId();\r
+ const auto numPoints = paramQueue->getPointCount();\r
\r
- if (paramQueue->getPoint (numPoints - 1, offsetSamples, value) == kResultTrue)\r
+ #if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS\r
+ if (juceVST3EditController != nullptr && juceVST3EditController->isMidiControllerParamID (vstParamID))\r
{\r
- auto vstParamID = paramQueue->getParameterId();\r
-\r
- #if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS\r
- if (juceVST3EditController != nullptr && juceVST3EditController->isMidiControllerParamID (vstParamID))\r
- addParameterChangeToMidiBuffer (offsetSamples, vstParamID, value);\r
- else\r
- #endif\r
+ for (Steinberg::int32 point = 0; point < numPoints; ++point)\r
{\r
- if (auto* param = comPluginInstance->getParamForVSTParamID (vstParamID))\r
- setValueAndNotifyIfChanged (*param, (float) value);\r
+ if (const auto change = getPointFromQueue (paramQueue, point))\r
+ addParameterChangeToMidiBuffer (change->offsetSamples, vstParamID, change->value);\r
}\r
}\r
+ else\r
+ #endif\r
+ if (const auto change = getPointFromQueue (paramQueue, numPoints - 1))\r
+ {\r
+ if (auto* param = comPluginInstance->getParamForVSTParamID (vstParamID))\r
+ setValueAndNotifyIfChanged (*param, (float) change->value);\r
+ }\r
}\r
}\r
}\r
\r
ID: juce_audio_plugin_client\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\r
name: JUCE audio plugin wrapper classes\r
description: Classes for building VST, VST3, AU, AUv3 and AAX plugins.\r
website: http://www.juce.com/juce\r
license: GPL/Commercial\r
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_audio_processors\r
\r
+++ /dev/null
-/*\r
- ==============================================================================\r
-\r
- This file is part of the JUCE library.\r
- Copyright (c) 2022 - Raw Material Software Limited\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 7 End-User License\r
- Agreement and JUCE Privacy Policy.\r
-\r
- End User License Agreement: www.juce.com/juce-7-licence\r
- Privacy Policy: www.juce.com/juce-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
-#define UseExtendedThingResource 1\r
-#include <AudioUnit.r>\r
-\r
-//==============================================================================\r
-/* The JucePluginDefines file should be a file in your project, containing info to describe the\r
- plugin's name, type, etc. The Projucer will generate this file automatically for you.\r
-\r
- You may need to adjust the include path of your project to make sure it can be\r
- found by this include statement. (Don't hack this file to change the include path)\r
-*/\r
-#include "JucePluginDefines.h"\r
-\r
-\r
-//==============================================================================\r
-// component resources for Audio Unit\r
-#define RES_ID 1000\r
-#define COMP_TYPE JucePlugin_AUMainType\r
-#define COMP_SUBTYPE JucePlugin_AUSubType\r
-#define COMP_MANUF JucePlugin_AUManufacturerCode\r
-#define VERSION JucePlugin_VersionCode\r
-#define NAME JucePlugin_Manufacturer ": " JucePlugin_Name\r
-#define DESCRIPTION JucePlugin_Desc\r
-#define ENTRY_POINT JucePlugin_AUExportPrefixQuoted "Entry"\r
-\r
-#include "AUResources.r"\r
#define verify_noerr(errorCode) __Verify_noErr(errorCode)\r
#endif\r
\r
-#include "AU/CoreAudioUtilityClasses/AUBase.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUBuffer.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUDispatch.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUInputElement.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUMIDIBase.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUOutputBase.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUOutputElement.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUScopeElement.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAAUParameter.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAMutex.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAVectorUnit.cpp"\r
-#include "AU/CoreAudioUtilityClasses/ComponentBase.cpp"\r
-#include "AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp"\r
+#if ! defined (MAC_OS_VERSION_11_0) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_11_0\r
+// These constants are only defined in the macOS 11+ SDKs\r
+\r
+enum MIDICVStatus : unsigned int\r
+{\r
+ kMIDICVStatusNoteOff = 0x8,\r
+ kMIDICVStatusNoteOn = 0x9,\r
+ kMIDICVStatusPolyPressure = 0xA,\r
+ kMIDICVStatusControlChange = 0xB,\r
+ kMIDICVStatusProgramChange = 0xC,\r
+ kMIDICVStatusChannelPressure = 0xD,\r
+ kMIDICVStatusPitchBend = 0xE,\r
+ kMIDICVStatusRegisteredPNC = 0x0,\r
+ kMIDICVStatusAssignablePNC = 0x1,\r
+ kMIDICVStatusRegisteredControl = 0x2,\r
+ kMIDICVStatusAssignableControl = 0x3,\r
+ kMIDICVStatusRelRegisteredControl = 0x4,\r
+ kMIDICVStatusRelAssignableControl = 0x5,\r
+ kMIDICVStatusPerNotePitchBend = 0x6,\r
+ kMIDICVStatusPerNoteMgmt = 0xF\r
+};\r
+\r
+#endif\r
+\r
+#include "AU/AudioUnitSDK/AUBase.cpp"\r
+#include "AU/AudioUnitSDK/AUBuffer.cpp"\r
+#include "AU/AudioUnitSDK/AUBufferAllocator.cpp"\r
+#include "AU/AudioUnitSDK/AUEffectBase.cpp"\r
+#include "AU/AudioUnitSDK/AUInputElement.cpp"\r
+#include "AU/AudioUnitSDK/AUMIDIBase.cpp"\r
+#include "AU/AudioUnitSDK/AUMIDIEffectBase.cpp"\r
+#include "AU/AudioUnitSDK/AUOutputElement.cpp"\r
+#include "AU/AudioUnitSDK/AUPlugInDispatch.cpp"\r
+#include "AU/AudioUnitSDK/AUScopeElement.cpp"\r
+#include "AU/AudioUnitSDK/ComponentBase.cpp"\r
+#include "AU/AudioUnitSDK/MusicDeviceBase.cpp"\r
\r
#undef verify\r
#undef verify_noerr\r
\r
#if JUCE_LINUX || JUCE_BSD\r
\r
-#include <thread>\r
-\r
namespace juce\r
{\r
\r
bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages);\r
\r
/** @internal */\r
-class MessageThread\r
+class MessageThread : public Thread\r
{\r
public:\r
- MessageThread()\r
+ MessageThread() : Thread ("JUCE Plugin Message Thread")\r
{\r
start();\r
}\r
\r
- ~MessageThread()\r
+ ~MessageThread() override\r
{\r
MessageManager::getInstance()->stopDispatchLoop();\r
stop();\r
\r
void start()\r
{\r
- if (isRunning())\r
- stop();\r
-\r
- shouldExit = false;\r
-\r
- thread = std::thread { [this]\r
- {\r
- Thread::setCurrentThreadPriority (7);\r
- Thread::setCurrentThreadName ("JUCE Plugin Message Thread");\r
-\r
- MessageManager::getInstance()->setCurrentThreadAsMessageThread();\r
- XWindowSystem::getInstance();\r
+ startThread (Priority::high);\r
\r
- threadInitialised.signal();\r
-\r
- for (;;)\r
- {\r
- if (! dispatchNextMessageOnSystemQueue (true))\r
- Thread::sleep (1);\r
-\r
- if (shouldExit)\r
- break;\r
- }\r
- } };\r
-\r
- threadInitialised.wait();\r
+ // Wait for setCurrentThreadAsMessageThread() and getInstance to be executed\r
+ // before leaving this method\r
+ threadInitialised.wait (10000);\r
}\r
\r
void stop()\r
{\r
- if (! isRunning())\r
- return;\r
-\r
- shouldExit = true;\r
- thread.join();\r
+ signalThreadShouldExit();\r
+ stopThread (-1);\r
}\r
\r
- bool isRunning() const noexcept { return thread.joinable(); }\r
+ bool isRunning() const noexcept { return isThreadRunning(); }\r
\r
-private:\r
- WaitableEvent threadInitialised;\r
- std::thread thread;\r
+ void run() override\r
+ {\r
+ MessageManager::getInstance()->setCurrentThreadAsMessageThread();\r
+ XWindowSystem::getInstance();\r
\r
- std::atomic<bool> shouldExit { false };\r
+ threadInitialised.signal();\r
\r
+ while (! threadShouldExit())\r
+ {\r
+ if (! dispatchNextMessageOnSystemQueue (true))\r
+ Thread::sleep (1);\r
+ }\r
+ }\r
+\r
+private:\r
+ WaitableEvent threadInitialised;\r
JUCE_DECLARE_NON_MOVEABLE (MessageThread)\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MessageThread)\r
};\r
#define LILV_DEFAULT_LV2_PATH \\r
"%APPDATA%\\LV2" LILV_PATH_SEP \\r
"%COMMONPROGRAMFILES%\\LV2"\r
- #elif JUCE_LINUX || JUCE_ANDROID\r
+ #elif JUCE_LINUX || JUCE_BSD || JUCE_ANDROID\r
#define LILV_DEFAULT_LV2_PATH \\r
"~/.lv2" LILV_PATH_SEP \\r
"/usr/lib/lv2" LILV_PATH_SEP \\r
return false;\r
\r
// did anything actually change\r
- if (layoutHasChanged)\r
- {\r
- bool success = (AudioUnitInitialize (audioUnit) == noErr);\r
+ if (! layoutHasChanged)\r
+ return true;\r
\r
- // Some plug-ins require the LayoutTag to be set after initialization\r
- if (success)\r
- success = syncBusLayouts (layouts, true, layoutHasChanged);\r
+ // Some plug-ins require the LayoutTag to be set after initialization\r
+ const auto success = (AudioUnitInitialize (audioUnit) == noErr)\r
+ && syncBusLayouts (layouts, true, layoutHasChanged);\r
\r
- AudioUnitUninitialize (audioUnit);\r
+ AudioUnitUninitialize (audioUnit);\r
\r
- if (! success)\r
- // make sure that the layout is back to it's original state\r
- syncBusLayouts (getBusesLayout(), false, layoutHasChanged);\r
-\r
- return success;\r
- }\r
+ if (! success)\r
+ // make sure that the layout is back to its original state\r
+ syncBusLayouts (getBusesLayout(), false, layoutHasChanged);\r
\r
- return true;\r
+ return success;\r
}\r
\r
//==============================================================================\r
if (p != nullptr) *p = value;\r
}\r
\r
- OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const\r
+ /* If the AudioPlayHead is available, and has valid PositionInfo, this will return the result\r
+ of calling the specified getter on that PositionInfo. Otherwise, this will return a\r
+ default-constructed instance of the same type.\r
+\r
+ For getters that return an Optional, this function will return a nullopt if the playhead or\r
+ position info is invalid.\r
+\r
+ For getters that return a bool, this function will return false if the playhead or position\r
+ info is invalid.\r
+ */\r
+ template <typename Result>\r
+ Result getFromPlayHead (Result (AudioPlayHead::PositionInfo::* member)() const) const\r
{\r
if (auto* ph = getPlayHead())\r
- {\r
if (const auto pos = ph->getPosition())\r
- {\r
- setIfNotNull (outCurrentBeat, pos->getPpqPosition().orFallback (0.0));\r
- setIfNotNull (outCurrentTempo, pos->getBpm().orFallback (0.0));\r
- return noErr;\r
- }\r
- }\r
+ return ((*pos).*member)();\r
\r
- setIfNotNull (outCurrentBeat, 0);\r
- setIfNotNull (outCurrentTempo, 120.0);\r
+ return {};\r
+ }\r
+\r
+ OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const\r
+ {\r
+ setIfNotNull (outCurrentBeat, getFromPlayHead (&AudioPlayHead::PositionInfo::getPpqPosition).orFallback (0));\r
+ setIfNotNull (outCurrentTempo, getFromPlayHead (&AudioPlayHead::PositionInfo::getBpm).orFallback (120.0));\r
return noErr;\r
}\r
\r
OSStatus getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat, Float32* outTimeSig_Numerator,\r
UInt32* outTimeSig_Denominator, Float64* outCurrentMeasureDownBeat) const\r
{\r
- if (auto* ph = getPlayHead())\r
- {\r
- if (const auto pos = ph->getPosition())\r
- {\r
- const auto signature = pos->getTimeSignature().orFallback (AudioPlayHead::TimeSignature{});\r
- setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0); //xxx\r
- setIfNotNull (outTimeSig_Numerator, (UInt32) signature.numerator);\r
- setIfNotNull (outTimeSig_Denominator, (UInt32) signature.denominator);\r
- setIfNotNull (outCurrentMeasureDownBeat, pos->getPpqPositionOfLastBarStart().orFallback (0.0)); //xxx wrong\r
- return noErr;\r
- }\r
- }\r
+ setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0); //xxx\r
+ setIfNotNull (outCurrentMeasureDownBeat, getFromPlayHead (&AudioPlayHead::PositionInfo::getPpqPositionOfLastBarStart).orFallback (0.0));\r
+\r
+ const auto signature = getFromPlayHead (&AudioPlayHead::PositionInfo::getTimeSignature).orFallback (AudioPlayHead::TimeSignature{});\r
+ setIfNotNull (outTimeSig_Numerator, (UInt32) signature.numerator);\r
+ setIfNotNull (outTimeSig_Denominator, (UInt32) signature.denominator);\r
\r
- setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0);\r
- setIfNotNull (outTimeSig_Numerator, (UInt32) 4);\r
- setIfNotNull (outTimeSig_Denominator, (UInt32) 4);\r
- setIfNotNull (outCurrentMeasureDownBeat, 0);\r
return noErr;\r
}\r
\r
Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling,\r
Float64* outCycleStartBeat, Float64* outCycleEndBeat)\r
{\r
- if (auto* ph = getPlayHead())\r
- {\r
- AudioPlayHead::CurrentPositionInfo result;\r
-\r
- if (ph->getCurrentPosition (result))\r
- {\r
- setIfNotNull (outIsPlaying, result.isPlaying);\r
-\r
- if (outTransportStateChanged != nullptr)\r
- {\r
- *outTransportStateChanged = result.isPlaying != wasPlaying;\r
- wasPlaying = result.isPlaying;\r
- }\r
+ const auto nowPlaying = getFromPlayHead (&AudioPlayHead::PositionInfo::getIsPlaying);\r
+ setIfNotNull (outIsPlaying, nowPlaying);\r
+ setIfNotNull (outTransportStateChanged, std::exchange (wasPlaying, nowPlaying) != nowPlaying);\r
+ setIfNotNull (outCurrentSampleInTimeLine, getFromPlayHead (&AudioPlayHead::PositionInfo::getTimeInSamples).orFallback (0));\r
+ setIfNotNull (outIsCycling, getFromPlayHead (&AudioPlayHead::PositionInfo::getIsLooping));\r
\r
- setIfNotNull (outCurrentSampleInTimeLine, result.timeInSamples);\r
- setIfNotNull (outIsCycling, result.isLooping);\r
- setIfNotNull (outCycleStartBeat, result.ppqLoopStart);\r
- setIfNotNull (outCycleEndBeat, result.ppqLoopEnd);\r
- return noErr;\r
- }\r
- }\r
+ const auto loopPoints = getFromPlayHead (&AudioPlayHead::PositionInfo::getLoopPoints).orFallback (AudioPlayHead::LoopPoints{});\r
+ setIfNotNull (outCycleStartBeat, loopPoints.ppqStart);\r
+ setIfNotNull (outCycleEndBeat, loopPoints.ppqEnd);\r
\r
- setIfNotNull (outIsPlaying, false);\r
- setIfNotNull (outTransportStateChanged, false);\r
- setIfNotNull (outCurrentSampleInTimeLine, 0);\r
- setIfNotNull (outIsCycling, false);\r
- setIfNotNull (outCycleStartBeat, 0.0);\r
- setIfNotNull (outCycleEndBeat, 0.0);\r
return noErr;\r
}\r
\r
CriticalSection* workMutex;\r
};\r
\r
-template <typename Trivial, std::enable_if_t<std::is_trivial<Trivial>::value, int> = 0>\r
+template <typename Trivial>\r
static auto toChars (Trivial value)\r
{\r
+ static_assert (std::is_trivial_v<Trivial>);\r
std::array<char, sizeof (Trivial)> result;\r
writeUnaligned (result.data(), value);\r
return result;\r
class WorkQueue\r
{\r
public:\r
- static_assert (std::is_trivial<Context>::value, "Context must be copyable as bytes");\r
+ static_assert (std::is_trivial_v<Context>, "Context must be copyable as bytes");\r
\r
explicit WorkQueue (int size)\r
: fifo (size), data (static_cast<size_t> (size)) {}\r
public:\r
World() : world (lilv_world_new()) {}\r
\r
- void loadAll() { lilv_world_load_all (world.get()); }\r
+ void loadAllFromPaths (const NodeString& paths)\r
+ {\r
+ lilv_world_set_option (world.get(), LILV_OPTION_LV2_PATH, paths.get());\r
+ lilv_world_load_all (world.get());\r
+ }\r
+\r
void loadBundle (const NodeUri& uri) { lilv_world_load_bundle (world.get(), uri.get()); }\r
void unloadBundle (const NodeUri& uri) { lilv_world_unload_bundle (world.get(), uri.get()); }\r
\r
// In this case, we find the closest label by searching the midpoints of the scale\r
// point values.\r
const auto index = std::distance (midPoints.begin(),\r
- std::lower_bound (midPoints.begin(), midPoints.end(), normalisedValue));\r
+ std::lower_bound (midPoints.begin(), midPoints.end(), denormalised));\r
jassert (isPositiveAndBelow (index, info.scalePoints.size()));\r
return info.scalePoints[(size_t) index].label;\r
}\r
return {};\r
\r
std::vector<float> result;\r
+ result.reserve (set.size() - 1);\r
\r
for (auto it = std::next (set.begin()); it != set.end(); ++it)\r
result.push_back ((std::prev (it)->value + it->value) * 0.5f);\r
\r
union Data\r
{\r
- static_assert (std::is_trivial<PortBacking>::value, "PortBacking must be trivial");\r
- static_assert (std::is_trivial<PatchBacking>::value, "PatchBacking must be trivial");\r
+ static_assert (std::is_trivial_v<PortBacking>, "PortBacking must be trivial");\r
+ static_assert (std::is_trivial_v<PatchBacking>, "PatchBacking must be trivial");\r
\r
explicit Data (PortBacking p) : port (p) {}\r
explicit Data (PatchBacking p) : patch (p) {}\r
public:\r
Pimpl()\r
{\r
- world->loadAll();\r
+ loadAllPluginsFromPaths (getDefaultLocationsToSearch());\r
\r
const auto tempFile = lv2ResourceFolder.getFile();\r
\r
return findPluginByUri (description.fileOrIdentifier) != nullptr;\r
}\r
\r
- StringArray searchPathsForPlugins (const FileSearchPath&, bool, bool)\r
+ StringArray searchPathsForPlugins (const FileSearchPath& paths, bool, bool)\r
{\r
- world->loadAll();\r
+ loadAllPluginsFromPaths (paths);\r
\r
StringArray result;\r
\r
return result;\r
}\r
\r
- FileSearchPath getDefaultLocationsToSearch() { return {}; }\r
+ FileSearchPath getDefaultLocationsToSearch()\r
+ {\r
+ #if JUCE_MAC\r
+ return { "~/Library/Audio/Plug-Ins/LV2;"\r
+ "~/.lv2;"\r
+ "/usr/local/lib/lv2;"\r
+ "/usr/lib/lv2;"\r
+ "/Library/Audio/Plug-Ins/LV2;" };\r
+ #elif JUCE_WINDOWS\r
+ return { "%APPDATA%\\LV2;"\r
+ "%COMMONPROGRAMFILES%\\LV2" };\r
+ #else\r
+ #if JUCE_64BIT\r
+ if (File ("/usr/lib64/lv2").exists() || File ("/usr/local/lib64/lv2").exists())\r
+ return { "~/.lv2;"\r
+ "/usr/lib64/lv2;"\r
+ "/usr/local/lib64/lv2" };\r
+ #endif\r
+\r
+ return { "~/.lv2;"\r
+ "/usr/lib/lv2;"\r
+ "/usr/local/lib/lv2" };\r
+ #endif\r
+ }\r
\r
const LilvUI* findEmbeddableUi (const lv2_host::Uis* pluginUis, std::true_type)\r
{\r
}\r
\r
private:\r
+ void loadAllPluginsFromPaths (const FileSearchPath& path)\r
+ {\r
+ const auto joined = path.toStringWithSeparator (LILV_PATH_SEP);\r
+ world->loadAllFromPaths (world->newString (joined.toRawUTF8()));\r
+ }\r
+\r
struct Free { void operator() (char* ptr) const noexcept { free (ptr); } };\r
using StringPtr = std::unique_ptr<char, Free>;\r
\r
extern "C"\r
{\r
\r
+#include <math.h>\r
+\r
#define is_windows_path serd_is_windows_path\r
\r
#include "serd/src/base64.c"\r
#include "serd/src/env.c"\r
#include "serd/src/n3.c"\r
#undef TRY\r
+\r
+// node.c will replace isnan and isinf with _isnan and _finite if the former symbols are undefined.\r
+// MinGW declares these as normal functions rather than as preprocessor definitions, causing the build to fail.\r
+#if defined (_WIN32) && defined (__GNUC__)\r
+\r
+namespace Utils\r
+{\r
+ inline int _isnan (double x) noexcept { return isnan (x); }\r
+ inline int _finite (double x) noexcept { return ! isinf (x); }\r
+} // namespace Utils\r
+\r
+using namespace Utils;\r
+#endif\r
+\r
#include "serd/src/node.c"\r
#include "serd/src/reader.c"\r
#include "serd/src/string.c"\r
const auto anyChannelIsNull = std::any_of (busPtr, busPtr + it->numChannels, [] (auto* ptr) { return ptr == nullptr; });\r
\r
// Null channels are allowed if the bus is inactive\r
- if ((mapIterator->isHostActive() && anyChannelIsNull) || ((int) mapIterator->size() != it->numChannels))\r
+ if (mapIterator->isHostActive() && (anyChannelIsNull || (int) mapIterator->size() != it->numChannels))\r
return false;\r
}\r
\r
\r
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-copy-dtor",\r
"-Wnon-virtual-dtor",\r
+ "-Wdeprecated",\r
"-Wreorder",\r
"-Wunsequenced",\r
"-Wint-to-pointer-cast",\r
const auto iter = attributes.find (attr);\r
\r
if (iter != attributes.end())\r
- iter->second = Attribute (std::move (value));\r
+ iter->second = Attribute (std::forward<Value> (value));\r
else\r
- attributes.emplace (attr, Attribute (std::move (value)));\r
+ attributes.emplace (attr, Attribute (std::forward<Value> (value)));\r
\r
return kResultTrue;\r
}\r
\r
using namespace Vst;\r
\r
+ // If the plugin has already been activated (prepareToPlay has been called twice without\r
+ // a matching releaseResources call) deactivate it so that the speaker layout and bus\r
+ // activation can be updated safely.\r
+ deactivate();\r
+\r
ProcessSetup setup;\r
setup.symbolicSampleSize = isUsingDoublePrecision() ? kSample64 : kSample32;\r
setup.maxSamplesPerBlock = estimatedSamplesPerBlock;\r
void releaseResources() override\r
{\r
const SpinLock::ScopedLockType lock (processMutex);\r
-\r
- if (! isActive)\r
- return; // Avoids redundantly calling things like setActive\r
-\r
- isActive = false;\r
-\r
- if (processor != nullptr)\r
- warnOnFailureIfImplemented (processor->setProcessing (false));\r
-\r
- if (holder->component != nullptr)\r
- warnOnFailure (holder->component->setActive (false));\r
-\r
- setStateForAllMidiBuses (false);\r
+ deactivate();\r
}\r
\r
bool supportsDoublePrecisionProcessing() const override\r
}\r
\r
private:\r
+ void deactivate()\r
+ {\r
+ if (! isActive)\r
+ return;\r
+\r
+ isActive = false;\r
+\r
+ if (processor != nullptr)\r
+ warnOnFailureIfImplemented (processor->setProcessing (false));\r
+\r
+ if (holder->component != nullptr)\r
+ warnOnFailure (holder->component->setActive (false));\r
+\r
+ setStateForAllMidiBuses (false);\r
+ }\r
+\r
//==============================================================================\r
#if JUCE_LINUX || JUCE_BSD\r
SharedResourcePointer<RunLoop> runLoop;\r
#ifndef WM_APPCOMMAND\r
#define WM_APPCOMMAND 0x0319\r
#endif\r
-\r
- extern "C" void _fpreset();\r
- extern "C" void _clearfp();\r
#elif ! JUCE_WINDOWS\r
static void _fpreset() {}\r
static void _clearfp() {}\r
if (auto hGlob = LoadResource (dllModule, res))\r
{\r
auto* data = static_cast<const char*> (LockResource (hGlob));\r
- return String::fromUTF8 (data, SizeofResource (dllModule, res));\r
+ return String::fromUTF8 (data, (int) SizeofResource (dllModule, res));\r
}\r
}\r
}\r
\r
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)\r
\r
+class TempChannelPointers\r
+{\r
+public:\r
+ template <typename T>\r
+ auto getArrayOfModifiableWritePointers (AudioBuffer<T>& buffer)\r
+ {\r
+ auto& pointers = getPointers (Tag<T>{});\r
+\r
+ jassert (buffer.getNumChannels() <= static_cast<int> (pointers.capacity()));\r
+ pointers.resize (jmax (pointers.size(), (size_t) buffer.getNumChannels()));\r
+\r
+ std::copy (buffer.getArrayOfWritePointers(),\r
+ buffer.getArrayOfWritePointers() + buffer.getNumChannels(),\r
+ pointers.begin());\r
+\r
+ return pointers.data();\r
+ }\r
+\r
+private:\r
+ template <typename> struct Tag {};\r
+\r
+ auto& getPointers (Tag<float>) { return floatPointers; }\r
+ auto& getPointers (Tag<double>) { return doublePointers; }\r
+\r
+ std::vector<float*> floatPointers { 128 };\r
+ std::vector<double*> doublePointers { 128 };\r
+};\r
+\r
//==============================================================================\r
struct VSTPluginInstance final : public AudioPluginInstance,\r
private Timer,\r
bool lastProcessBlockCallWasBypass = false, vstSupportsBypass = false;\r
mutable StringArray programNames;\r
AudioBuffer<float> outOfPlaceBuffer;\r
+ TempChannelPointers tempChannelPointers[2];\r
\r
CriticalSection midiInLock;\r
MidiBuffer incomingMidi;\r
{\r
if ((vstEffect->flags & Vst2::effFlagsCanReplacing) != 0)\r
{\r
- vstEffect->processReplacing (vstEffect, buffer.getArrayOfWritePointers(),\r
- buffer.getArrayOfWritePointers(), sampleFrames);\r
+ vstEffect->processReplacing (vstEffect, tempChannelPointers[0].getArrayOfModifiableWritePointers (buffer),\r
+ tempChannelPointers[1].getArrayOfModifiableWritePointers (buffer), sampleFrames);\r
}\r
else\r
{\r
outOfPlaceBuffer.setSize (vstEffect->numOutputs, sampleFrames);\r
outOfPlaceBuffer.clear();\r
\r
- vstEffect->process (vstEffect, buffer.getArrayOfWritePointers(),\r
- outOfPlaceBuffer.getArrayOfWritePointers(), sampleFrames);\r
+ vstEffect->process (vstEffect, tempChannelPointers[0].getArrayOfModifiableWritePointers (buffer),\r
+ tempChannelPointers[1].getArrayOfModifiableWritePointers (outOfPlaceBuffer), sampleFrames);\r
\r
for (int i = vstEffect->numOutputs; --i >= 0;)\r
buffer.copyFrom (i, 0, outOfPlaceBuffer.getReadPointer (i), sampleFrames);\r
\r
inline void invokeProcessFunction (AudioBuffer<double>& buffer, int32 sampleFrames)\r
{\r
- vstEffect->processDoubleReplacing (vstEffect, buffer.getArrayOfWritePointers(),\r
- buffer.getArrayOfWritePointers(), sampleFrames);\r
+ vstEffect->processDoubleReplacing (vstEffect, tempChannelPointers[0].getArrayOfModifiableWritePointers (buffer),\r
+ tempChannelPointers[1].getArrayOfModifiableWritePointers (buffer), sampleFrames);\r
}\r
\r
//==============================================================================\r
pluginWantsKeys = (dispatch (Vst2::effKeysRequired, 0, 0, nullptr, 0) == 0);\r
\r
#if JUCE_WINDOWS\r
- originalWndProc = 0;\r
+ originalWndProc = nullptr;\r
auto* pluginHWND = getPluginHWND();\r
\r
- if (pluginHWND == 0)\r
+ if (pluginHWND == nullptr)\r
{\r
isOpen = false;\r
setSize (300, 150);\r
{\r
ScopedThreadDPIAwarenessSetter threadDpiAwarenessSetter { pluginHWND };\r
\r
- SetWindowPos (pluginHWND, 0,\r
+ SetWindowPos (pluginHWND, nullptr,\r
0, 0, rw, rh,\r
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);\r
\r
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4244)\r
auto* pluginHWND = getPluginHWND();\r
\r
- if (originalWndProc != 0 && pluginHWND != 0 && IsWindow (pluginHWND))\r
+ if (originalWndProc != nullptr && pluginHWND != nullptr && IsWindow (pluginHWND))\r
SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) originalWndProc);\r
JUCE_END_IGNORE_WARNINGS_MSVC\r
\r
- originalWndProc = 0;\r
+ originalWndProc = nullptr;\r
#elif JUCE_LINUX || JUCE_BSD\r
pluginWindow = 0;\r
#endif\r
\r
bool VSTPluginInstance::updateSizeFromEditor (int w, int h)\r
{\r
+ #if ! JUCE_IOS && ! JUCE_ANDROID\r
if (auto* editor = dynamic_cast<VSTPluginWindow*> (getActiveEditor()))\r
return editor->updateSizeFromEditor (w, h);\r
+ #endif\r
\r
return false;\r
}\r
\r
ID: juce_audio_processors\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_gui_extra, juce_audio_basics\r
OSXFrameworks: CoreAudio CoreMIDI AudioToolbox\r
@param set The AudioChannelSet which is to be probed.\r
@param currentLayout If non-null, pretend that the current layout of the AudioProcessor is\r
currentLayout. On exit, currentLayout will be modified to\r
- to represent the buses layouts of the AudioProcessor as if the layout\r
+ represent the buses layouts of the AudioProcessor as if the layout\r
of the receiver had been successfully changed. This is useful as changing\r
the layout of the receiver may change the bus layout of other buses.\r
\r
\r
void addBus (bool isInput, const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true);\r
\r
- JUCE_NODISCARD BusesProperties withInput (const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true) const;\r
- JUCE_NODISCARD BusesProperties withOutput (const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true) const;\r
+ [[nodiscard]] BusesProperties withInput (const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true) const;\r
+ [[nodiscard]] BusesProperties withOutput (const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true) const;\r
};\r
\r
/** Callback to query if adding/removing buses currently possible.\r
==============================================================================\r
*/\r
\r
+// Implementation notes:\r
+// On macOS, calling AudioUnitInitialize will internally call AudioObjectGetPropertyData, which\r
+// takes a mutex.\r
+// This same mutex is taken on the audio thread, before calling the audio device's IO callback.\r
+// This is a property of the CoreAudio implementation - we can't remove or interact directly\r
+// with these locks in JUCE.\r
+//\r
+// AudioProcessor instances expect that their callback lock will be taken before calling\r
+// processBlock or processBlockBypassed.\r
+// This means that, to avoid deadlocks, we *always* need to make sure that the CoreAudio mutex\r
+// is locked before taking the callback lock.\r
+// Given that we can't interact with the CoreAudio mutex directly, on the main thread we can't\r
+// call any function that might internally interact with CoreAudio while the callback lock is\r
+// taken.\r
+// In particular, be careful not to call `prepareToPlay` on a hosted AudioUnit from the main\r
+// thread while the callback lock is taken.\r
+// The graph implementation currently makes sure to call prepareToPlay on the main thread,\r
+// without taking the graph's callback lock.\r
+\r
namespace juce\r
{\r
\r
-static void updateOnMessageThread (AsyncUpdater& updater)\r
+/* Provides a comparison function for various types that have an associated NodeID,\r
+ for use with equal_range, lower_bound etc.\r
+*/\r
+class ImplicitNode\r
{\r
- if (MessageManager::getInstance()->isThisTheMessageThread())\r
- updater.handleAsyncUpdate();\r
- else\r
- updater.triggerAsyncUpdate();\r
-}\r
+public:\r
+ using Node = AudioProcessorGraph::Node;\r
+ using NodeID = AudioProcessorGraph::NodeID;\r
+ using NodeAndChannel = AudioProcessorGraph::NodeAndChannel;\r
+\r
+ ImplicitNode (NodeID x) : node (x) {}\r
+ ImplicitNode (NodeAndChannel x) : ImplicitNode (x.nodeID) {}\r
+ ImplicitNode (const Node* x) : ImplicitNode (x->nodeID) {}\r
+ ImplicitNode (const std::pair<const NodeAndChannel, std::set<NodeAndChannel>>& x) : ImplicitNode (x.first) {}\r
+\r
+ /* This is the comparison function. */\r
+ static bool compare (ImplicitNode a, ImplicitNode b) { return a.node < b.node; }\r
+\r
+private:\r
+ NodeID node;\r
+};\r
+\r
+//==============================================================================\r
+/* A copyable type holding all the nodes, and allowing fast lookup by id. */\r
+class Nodes\r
+{\r
+public:\r
+ using Node = AudioProcessorGraph::Node;\r
+ using NodeID = AudioProcessorGraph::NodeID;\r
+\r
+ const ReferenceCountedArray<Node>& getNodes() const { return array; }\r
+\r
+ Node::Ptr getNodeForId (NodeID nodeID) const\r
+ {\r
+ const auto iter = std::lower_bound (array.begin(), array.end(), nodeID, ImplicitNode::compare);\r
+ return iter != array.end() && (*iter)->nodeID == nodeID ? *iter : nullptr;\r
+ }\r
+\r
+ Node::Ptr addNode (std::unique_ptr<AudioProcessor> newProcessor, const NodeID nodeID)\r
+ {\r
+ if (newProcessor == nullptr)\r
+ {\r
+ // Cannot add a null audio processor!\r
+ jassertfalse;\r
+ return {};\r
+ }\r
+\r
+ if (std::any_of (array.begin(),\r
+ array.end(),\r
+ [&] (auto* n) { return n->getProcessor() == newProcessor.get(); }))\r
+ {\r
+ // This audio processor has already been added to the graph!\r
+ jassertfalse;\r
+ return {};\r
+ }\r
+\r
+ const auto iter = std::lower_bound (array.begin(), array.end(), nodeID, ImplicitNode::compare);\r
+\r
+ if (iter != array.end() && (*iter)->nodeID == nodeID)\r
+ {\r
+ // This nodeID has already been used for a node in the graph!\r
+ jassertfalse;\r
+ return {};\r
+ }\r
+\r
+ return array.insert ((int) std::distance (array.begin(), iter),\r
+ new Node { nodeID, std::move (newProcessor) });\r
+ }\r
+\r
+ Node::Ptr removeNode (NodeID nodeID)\r
+ {\r
+ const auto iter = std::lower_bound (array.begin(), array.end(), nodeID, ImplicitNode::compare);\r
+ return iter != array.end() && (*iter)->nodeID == nodeID\r
+ ? array.removeAndReturn ((int) std::distance (array.begin(), iter))\r
+ : nullptr;\r
+ }\r
+\r
+ bool operator== (const Nodes& other) const { return array == other.array; }\r
+ bool operator!= (const Nodes& other) const { return array != other.array; }\r
+\r
+private:\r
+ ReferenceCountedArray<Node> array;\r
+};\r
+\r
+//==============================================================================\r
+/* A value type holding a full set of graph connections. */\r
+class Connections\r
+{\r
+public:\r
+ using Node = AudioProcessorGraph::Node;\r
+ using NodeID = AudioProcessorGraph::NodeID;\r
+ using Connection = AudioProcessorGraph::Connection;\r
+ using NodeAndChannel = AudioProcessorGraph::NodeAndChannel;\r
+\r
+ static constexpr auto midiChannelIndex = AudioProcessorGraph::midiChannelIndex;\r
+\r
+ bool addConnection (const Nodes& n, const Connection& c)\r
+ {\r
+ if (! canConnect (n, c))\r
+ return false;\r
+\r
+ sourcesForDestination[c.destination].insert (c.source);\r
+ jassert (isConnected (c));\r
+ return true;\r
+ }\r
+\r
+ bool removeConnection (const Connection& c)\r
+ {\r
+ const auto iter = sourcesForDestination.find (c.destination);\r
+ return iter != sourcesForDestination.cend() && iter->second.erase (c.source) == 1;\r
+ }\r
+\r
+ bool removeIllegalConnections (const Nodes& n)\r
+ {\r
+ auto anyRemoved = false;\r
+\r
+ for (auto& dest : sourcesForDestination)\r
+ {\r
+ const auto initialSize = dest.second.size();\r
+ dest.second = removeIllegalConnections (n, std::move (dest.second), dest.first);\r
+ anyRemoved |= (dest.second.size() != initialSize);\r
+ }\r
+\r
+ return anyRemoved;\r
+ }\r
+\r
+ bool disconnectNode (NodeID n)\r
+ {\r
+ const auto matchingDestinations = getMatchingDestinations (n);\r
+ auto result = matchingDestinations.first != matchingDestinations.second;\r
+ sourcesForDestination.erase (matchingDestinations.first, matchingDestinations.second);\r
+\r
+ for (auto& pair : sourcesForDestination)\r
+ {\r
+ const auto range = std::equal_range (pair.second.cbegin(), pair.second.cend(), n, ImplicitNode::compare);\r
+ result |= range.first != range.second;\r
+ pair.second.erase (range.first, range.second);\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ static bool isConnectionLegal (const Nodes& n, Connection c)\r
+ {\r
+ const auto source = n.getNodeForId (c.source .nodeID);\r
+ const auto dest = n.getNodeForId (c.destination.nodeID);\r
+\r
+ const auto sourceChannel = c.source .channelIndex;\r
+ const auto destChannel = c.destination.channelIndex;\r
+\r
+ const auto sourceIsMIDI = AudioProcessorGraph::midiChannelIndex == sourceChannel;\r
+ const auto destIsMIDI = AudioProcessorGraph::midiChannelIndex == destChannel;\r
+\r
+ return sourceChannel >= 0\r
+ && destChannel >= 0\r
+ && source != dest\r
+ && sourceIsMIDI == destIsMIDI\r
+ && source != nullptr\r
+ && (sourceIsMIDI\r
+ ? source->getProcessor()->producesMidi()\r
+ : sourceChannel < source->getProcessor()->getTotalNumOutputChannels())\r
+ && dest != nullptr\r
+ && (destIsMIDI\r
+ ? dest->getProcessor()->acceptsMidi()\r
+ : destChannel < dest->getProcessor()->getTotalNumInputChannels());\r
+ }\r
+\r
+ bool canConnect (const Nodes& n, Connection c) const\r
+ {\r
+ return isConnectionLegal (n, c) && ! isConnected (c);\r
+ }\r
+\r
+ bool isConnected (Connection c) const\r
+ {\r
+ const auto iter = sourcesForDestination.find (c.destination);\r
+\r
+ return iter != sourcesForDestination.cend()\r
+ && iter->second.find (c.source) != iter->second.cend();\r
+ }\r
+\r
+ bool isConnected (NodeID srcID, NodeID destID) const\r
+ {\r
+ const auto matchingDestinations = getMatchingDestinations (destID);\r
+\r
+ return std::any_of (matchingDestinations.first, matchingDestinations.second, [srcID] (const auto& pair)\r
+ {\r
+ const auto iter = std::lower_bound (pair.second.cbegin(), pair.second.cend(), srcID, ImplicitNode::compare);\r
+ return iter != pair.second.cend() && iter->nodeID == srcID;\r
+ });\r
+ }\r
+\r
+ std::set<NodeID> getSourceNodesForDestination (NodeID destID) const\r
+ {\r
+ const auto matchingDestinations = getMatchingDestinations (destID);\r
+\r
+ std::set<NodeID> result;\r
+ std::for_each (matchingDestinations.first, matchingDestinations.second, [&] (const auto& pair)\r
+ {\r
+ for (const auto& source : pair.second)\r
+ result.insert (source.nodeID);\r
+ });\r
+ return result;\r
+ }\r
+\r
+ std::set<NodeAndChannel> getSourcesForDestination (const NodeAndChannel& p) const\r
+ {\r
+ const auto iter = sourcesForDestination.find (p);\r
+ return iter != sourcesForDestination.cend() ? iter->second : std::set<NodeAndChannel>{};\r
+ }\r
+\r
+ std::vector<Connection> getConnections() const\r
+ {\r
+ std::vector<Connection> result;\r
+\r
+ for (auto& pair : sourcesForDestination)\r
+ for (const auto& source : pair.second)\r
+ result.emplace_back (source, pair.first);\r
+\r
+ std::sort (result.begin(), result.end());\r
+ result.erase (std::unique (result.begin(), result.end()), result.end());\r
+ return result;\r
+ }\r
+\r
+ bool isAnInputTo (NodeID source, NodeID dest) const\r
+ {\r
+ return getConnectedRecursive (source, dest, {}).found;\r
+ }\r
+\r
+ bool operator== (const Connections& other) const { return sourcesForDestination == other.sourcesForDestination; }\r
+ bool operator!= (const Connections& other) const { return sourcesForDestination != other.sourcesForDestination; }\r
+\r
+private:\r
+ using Map = std::map<NodeAndChannel, std::set<NodeAndChannel>>;\r
+\r
+ struct SearchState\r
+ {\r
+ std::set<NodeID> visited;\r
+ bool found = false;\r
+ };\r
+\r
+ SearchState getConnectedRecursive (NodeID source, NodeID dest, SearchState state) const\r
+ {\r
+ state.visited.insert (dest);\r
+\r
+ for (const auto& s : getSourceNodesForDestination (dest))\r
+ {\r
+ if (state.found || s == source)\r
+ return { std::move (state.visited), true };\r
+\r
+ if (state.visited.find (s) == state.visited.cend())\r
+ state = getConnectedRecursive (source, s, std::move (state));\r
+ }\r
+\r
+ return state;\r
+ }\r
+\r
+ static std::set<NodeAndChannel> removeIllegalConnections (const Nodes& nodes,\r
+ std::set<NodeAndChannel> sources,\r
+ NodeAndChannel destination)\r
+ {\r
+ for (auto source = sources.cbegin(); source != sources.cend();)\r
+ {\r
+ if (! isConnectionLegal (nodes, { *source, destination }))\r
+ source = sources.erase (source);\r
+ else\r
+ ++source;\r
+ }\r
+\r
+ return sources;\r
+ }\r
+\r
+ std::pair<Map::const_iterator, Map::const_iterator> getMatchingDestinations (NodeID destID) const\r
+ {\r
+ return std::equal_range (sourcesForDestination.cbegin(), sourcesForDestination.cend(), destID, ImplicitNode::compare);\r
+ }\r
+\r
+ Map sourcesForDestination;\r
+};\r
+\r
+//==============================================================================\r
+/* Settings used to prepare a node for playback. */\r
+struct PrepareSettings\r
+{\r
+ using ProcessingPrecision = AudioProcessorGraph::ProcessingPrecision;\r
+\r
+ ProcessingPrecision precision = ProcessingPrecision::singlePrecision;\r
+ double sampleRate = 0.0;\r
+ int blockSize = 0;\r
+\r
+ auto tie() const noexcept { return std::tie (precision, sampleRate, blockSize); }\r
\r
+ bool operator== (const PrepareSettings& other) const { return tie() == other.tie(); }\r
+ bool operator!= (const PrepareSettings& other) const { return tie() != other.tie(); }\r
+};\r
+\r
+//==============================================================================\r
+/* Keeps track of the PrepareSettings applied to each node. */\r
+class NodeStates\r
+{\r
+public:\r
+ using Node = AudioProcessorGraph::Node;\r
+ using NodeID = AudioProcessorGraph::NodeID;\r
+\r
+ /* Called from prepareToPlay and releaseResources with the PrepareSettings that should be\r
+ used next time the graph is rebuilt.\r
+ */\r
+ void setState (Optional<PrepareSettings> newSettings)\r
+ {\r
+ const std::lock_guard<std::mutex> lock (mutex);\r
+ next = newSettings;\r
+ }\r
+\r
+ /* Call from the audio thread only. */\r
+ Optional<PrepareSettings> getLastRequestedSettings() const { return next; }\r
+\r
+ /* Call from the main thread only!\r
+\r
+ Called after updating the graph topology to prepare any currently-unprepared nodes.\r
+\r
+ To ensure that all nodes are initialised with the same sample rate, buffer size, etc. as\r
+ the enclosing graph, we must ensure that any operation that uses these details (preparing\r
+ individual nodes) is synchronized with prepare-to-play and release-resources on the\r
+ enclosing graph.\r
+\r
+ If the new PrepareSettings are different to the last-seen settings, all nodes will\r
+ be prepared/unprepared as necessary. If the PrepareSettings have not changed, then only\r
+ new nodes will be prepared/unprepared.\r
+\r
+ Returns the settings that were applied to the nodes.\r
+ */\r
+ Optional<PrepareSettings> applySettings (const Nodes& n)\r
+ {\r
+ const auto settingsChanged = [this]\r
+ {\r
+ const std::lock_guard<std::mutex> lock (mutex);\r
+ const auto result = current != next;\r
+ current = next;\r
+ return result;\r
+ }();\r
+\r
+ // It may look like releaseResources and prepareToPlay could race with calls to processBlock\r
+ // here, because applySettings is called from the main thread, processBlock is called from\r
+ // the audio thread (normally), and there's no explicit mutex ensuring that the calls don't\r
+ // overlap.\r
+ // However, it is part of the AudioProcessor contract that users shall not call\r
+ // processBlock, prepareToPlay, and/or releaseResources concurrently. That is, there's an\r
+ // implied mutex synchronising these functions on each AudioProcessor.\r
+ //\r
+ // Inside processBlock, we always ensure that the current RenderSequence's PrepareSettings\r
+ // match the graph's settings before attempting to call processBlock on any of the graph\r
+ // nodes; as a result, it's impossible to start calling processBlock on a node on the audio\r
+ // thread while a render sequence rebuild (including prepareToPlay/releaseResources calls)\r
+ // is already in progress here.\r
+ //\r
+ // Due to the implied mutex between prepareToPlay/releaseResources/processBlock, it's also\r
+ // impossible to receive new PrepareSettings and to start a new RenderSequence rebuild while\r
+ // a processBlock call is in progress.\r
+\r
+ if (settingsChanged)\r
+ {\r
+ for (const auto& node : n.getNodes())\r
+ node->getProcessor()->releaseResources();\r
+\r
+ preparedNodes.clear();\r
+ }\r
+\r
+ if (current.hasValue())\r
+ {\r
+ for (const auto& node : n.getNodes())\r
+ {\r
+ if (preparedNodes.find (node->nodeID) != preparedNodes.cend())\r
+ continue;\r
+\r
+ preparedNodes.insert (node->nodeID);\r
+\r
+ node->getProcessor()->setProcessingPrecision (node->getProcessor()->supportsDoublePrecisionProcessing() ? current->precision\r
+ : AudioProcessor::singlePrecision);\r
+ node->getProcessor()->setRateAndBufferSizeDetails (current->sampleRate, current->blockSize);\r
+ node->getProcessor()->prepareToPlay (current->sampleRate, current->blockSize);\r
+ }\r
+ }\r
+\r
+ return current;\r
+ }\r
+\r
+private:\r
+ std::mutex mutex;\r
+ std::set<NodeID> preparedNodes;\r
+ Optional<PrepareSettings> current, next;\r
+};\r
+\r
+//==============================================================================\r
template <typename FloatType>\r
struct GraphRenderSequence\r
{\r
+ using Node = AudioProcessorGraph::Node;\r
+\r
struct Context\r
{\r
- FloatType** audioBuffers;\r
+ FloatType* const* audioBuffers;\r
MidiBuffer* midiBuffers;\r
AudioPlayHead* audioPlayHead;\r
int numSamples;\r
{\r
const Context context { renderingBuffer.getArrayOfWritePointers(), midiBuffers.begin(), audioPlayHead, numSamples };\r
\r
- for (auto* op : renderOps)\r
- op->perform (context);\r
+ for (const auto& op : renderOps)\r
+ op (context);\r
}\r
\r
for (int i = 0; i < buffer.getNumChannels(); ++i)\r
\r
void addClearChannelOp (int index)\r
{\r
- createOp ([=] (const Context& c) { FloatVectorOperations::clear (c.audioBuffers[index], c.numSamples); });\r
+ renderOps.push_back ([=] (const Context& c) { FloatVectorOperations::clear (c.audioBuffers[index], c.numSamples); });\r
}\r
\r
void addCopyChannelOp (int srcIndex, int dstIndex)\r
{\r
- createOp ([=] (const Context& c) { FloatVectorOperations::copy (c.audioBuffers[dstIndex],\r
- c.audioBuffers[srcIndex],\r
- c.numSamples); });\r
+ renderOps.push_back ([=] (const Context& c) { FloatVectorOperations::copy (c.audioBuffers[dstIndex], c.audioBuffers[srcIndex], c.numSamples); });\r
}\r
\r
void addAddChannelOp (int srcIndex, int dstIndex)\r
{\r
- createOp ([=] (const Context& c) { FloatVectorOperations::add (c.audioBuffers[dstIndex],\r
- c.audioBuffers[srcIndex],\r
- c.numSamples); });\r
+ renderOps.push_back ([=] (const Context& c) { FloatVectorOperations::add (c.audioBuffers[dstIndex], c.audioBuffers[srcIndex], c.numSamples); });\r
}\r
\r
void addClearMidiBufferOp (int index)\r
{\r
- createOp ([=] (const Context& c) { c.midiBuffers[index].clear(); });\r
+ renderOps.push_back ([=] (const Context& c) { c.midiBuffers[index].clear(); });\r
}\r
\r
void addCopyMidiBufferOp (int srcIndex, int dstIndex)\r
{\r
- createOp ([=] (const Context& c) { c.midiBuffers[dstIndex] = c.midiBuffers[srcIndex]; });\r
+ renderOps.push_back ([=] (const Context& c) { c.midiBuffers[dstIndex] = c.midiBuffers[srcIndex]; });\r
}\r
\r
void addAddMidiBufferOp (int srcIndex, int dstIndex)\r
{\r
- createOp ([=] (const Context& c) { c.midiBuffers[dstIndex].addEvents (c.midiBuffers[srcIndex],\r
- 0, c.numSamples, 0); });\r
+ renderOps.push_back ([=] (const Context& c) { c.midiBuffers[dstIndex].addEvents (c.midiBuffers[srcIndex], 0, c.numSamples, 0); });\r
}\r
\r
void addDelayChannelOp (int chan, int delaySize)\r
{\r
- renderOps.add (new DelayChannelOp (chan, delaySize));\r
+ renderOps.push_back (DelayChannelOp { chan, delaySize });\r
}\r
\r
- void addProcessOp (const AudioProcessorGraph::Node::Ptr& node,\r
- const Array<int>& audioChannelsUsed, int totalNumChans, int midiBuffer)\r
+ void addProcessOp (const Node::Ptr& node,\r
+ const Array<int>& audioChannelsUsed,\r
+ int totalNumChans,\r
+ int midiBuffer)\r
{\r
- renderOps.add (new ProcessOp (node, audioChannelsUsed, totalNumChans, midiBuffer));\r
+ renderOps.push_back (ProcessOp { node, audioChannelsUsed, totalNumChans, midiBuffer });\r
}\r
\r
void prepareBuffers (int blockSize)\r
\r
private:\r
//==============================================================================\r
- struct RenderingOp\r
- {\r
- RenderingOp() noexcept {}\r
- virtual ~RenderingOp() {}\r
- virtual void perform (const Context&) = 0;\r
-\r
- JUCE_LEAK_DETECTOR (RenderingOp)\r
- };\r
-\r
- OwnedArray<RenderingOp> renderOps;\r
-\r
- //==============================================================================\r
- template <typename LambdaType,\r
- std::enable_if_t<std::is_rvalue_reference<LambdaType&&>::value, int> = 0>\r
- void createOp (LambdaType&& fn)\r
- {\r
- struct LambdaOp : public RenderingOp\r
- {\r
- LambdaOp (LambdaType&& f) : function (std::forward<LambdaType> (f)) {}\r
- void perform (const Context& c) override { function (c); }\r
-\r
- LambdaType function;\r
- };\r
-\r
- renderOps.add (new LambdaOp (std::forward<LambdaType> (fn)));\r
- }\r
+ std::vector<std::function<void (const Context&)>> renderOps;\r
\r
//==============================================================================\r
- struct DelayChannelOp : public RenderingOp\r
+ struct DelayChannelOp\r
{\r
DelayChannelOp (int chan, int delaySize)\r
- : channel (chan),\r
- bufferSize (delaySize + 1),\r
+ : buffer ((size_t) (delaySize + 1), (FloatType) 0),\r
+ channel (chan),\r
writeIndex (delaySize)\r
{\r
- buffer.calloc ((size_t) bufferSize);\r
}\r
\r
- void perform (const Context& c) override\r
+ void operator() (const Context& c)\r
{\r
auto* data = c.audioBuffers[channel];\r
\r
for (int i = c.numSamples; --i >= 0;)\r
{\r
- buffer[writeIndex] = *data;\r
- *data++ = buffer[readIndex];\r
+ buffer[(size_t) writeIndex] = *data;\r
+ *data++ = buffer[(size_t) readIndex];\r
\r
- if (++readIndex >= bufferSize) readIndex = 0;\r
- if (++writeIndex >= bufferSize) writeIndex = 0;\r
+ if (++readIndex >= (int) buffer.size()) readIndex = 0;\r
+ if (++writeIndex >= (int) buffer.size()) writeIndex = 0;\r
}\r
}\r
\r
- HeapBlock<FloatType> buffer;\r
- const int channel, bufferSize;\r
+ std::vector<FloatType> buffer;\r
+ const int channel;\r
int readIndex = 0, writeIndex;\r
-\r
- JUCE_DECLARE_NON_COPYABLE (DelayChannelOp)\r
};\r
\r
//==============================================================================\r
- struct ProcessOp : public RenderingOp\r
+ struct ProcessOp\r
{\r
- ProcessOp (const AudioProcessorGraph::Node::Ptr& n,\r
+ ProcessOp (const Node::Ptr& n,\r
const Array<int>& audioChannelsUsed,\r
int totalNumChans, int midiBuffer)\r
: node (n),\r
processor (*n->getProcessor()),\r
audioChannelsToUse (audioChannelsUsed),\r
- totalChans (jmax (1, totalNumChans)),\r
+ audioChannels ((size_t) jmax (1, totalNumChans), nullptr),\r
midiBufferToUse (midiBuffer)\r
{\r
- audioChannels.calloc ((size_t) totalChans);\r
-\r
- while (audioChannelsToUse.size() < totalChans)\r
+ while (audioChannelsToUse.size() < (int) audioChannels.size())\r
audioChannelsToUse.add (0);\r
}\r
\r
- void perform (const Context& c) override\r
+ void operator() (const Context& c)\r
{\r
processor.setPlayHead (c.audioPlayHead);\r
\r
- for (int i = 0; i < totalChans; ++i)\r
- audioChannels[i] = c.audioBuffers[audioChannelsToUse.getUnchecked (i)];\r
+ for (size_t i = 0; i < audioChannels.size(); ++i)\r
+ audioChannels[i] = c.audioBuffers[audioChannelsToUse.getUnchecked ((int) i)];\r
\r
auto numAudioChannels = [this]\r
{\r
if (proc->getTotalNumInputChannels() == 0 && proc->getTotalNumOutputChannels() == 0)\r
return 0;\r
\r
- return totalChans;\r
+ return (int) audioChannels.size();\r
}();\r
\r
- AudioBuffer<FloatType> buffer (audioChannels, numAudioChannels, c.numSamples);\r
+ AudioBuffer<FloatType> buffer { audioChannels.data(), numAudioChannels, c.numSamples };\r
\r
const ScopedLock lock (processor.getCallbackLock());\r
\r
callProcess (buffer, c.midiBuffers[midiBufferToUse]);\r
}\r
\r
- void callProcess (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)\r
+ void callProcess (AudioBuffer<float>& buffer, MidiBuffer& midi)\r
{\r
if (processor.isUsingDoublePrecision())\r
{\r
tempBufferDouble.makeCopyOf (buffer, true);\r
-\r
- if (node->isBypassed())\r
- node->processBlockBypassed (tempBufferDouble, midiMessages);\r
- else\r
- node->processBlock (tempBufferDouble, midiMessages);\r
-\r
+ process (*node, tempBufferDouble, midi);\r
buffer.makeCopyOf (tempBufferDouble, true);\r
}\r
else\r
{\r
- if (node->isBypassed())\r
- node->processBlockBypassed (buffer, midiMessages);\r
- else\r
- node->processBlock (buffer, midiMessages);\r
+ process (*node, buffer, midi);\r
}\r
}\r
\r
- void callProcess (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)\r
+ void callProcess (AudioBuffer<double>& buffer, MidiBuffer& midi)\r
{\r
if (processor.isUsingDoublePrecision())\r
{\r
- if (node->isBypassed())\r
- node->processBlockBypassed (buffer, midiMessages);\r
- else\r
- node->processBlock (buffer, midiMessages);\r
+ process (*node, buffer, midi);\r
}\r
else\r
{\r
tempBufferFloat.makeCopyOf (buffer, true);\r
-\r
- if (node->isBypassed())\r
- node->processBlockBypassed (tempBufferFloat, midiMessages);\r
- else\r
- node->processBlock (tempBufferFloat, midiMessages);\r
-\r
+ process (*node, tempBufferFloat, midi);\r
buffer.makeCopyOf (tempBufferFloat, true);\r
}\r
}\r
\r
- const AudioProcessorGraph::Node::Ptr node;\r
+ template <typename Value>\r
+ static void process (const Node& node, AudioBuffer<Value>& audio, MidiBuffer& midi)\r
+ {\r
+ if (node.isBypassed() && node.getProcessor()->getBypassParameter() == nullptr)\r
+ node.getProcessor()->processBlockBypassed (audio, midi);\r
+ else\r
+ node.getProcessor()->processBlock (audio, midi);\r
+ }\r
+\r
+ const Node::Ptr node;\r
AudioProcessor& processor;\r
\r
Array<int> audioChannelsToUse;\r
- HeapBlock<FloatType*> audioChannels;\r
+ std::vector<FloatType*> audioChannels;\r
AudioBuffer<float> tempBufferFloat, tempBufferDouble;\r
- const int totalChans, midiBufferToUse;\r
-\r
- JUCE_DECLARE_NON_COPYABLE (ProcessOp)\r
+ const int midiBufferToUse;\r
};\r
};\r
\r
//==============================================================================\r
-//==============================================================================\r
-template <typename RenderSequence>\r
-struct RenderSequenceBuilder\r
+class RenderSequenceBuilder\r
{\r
- RenderSequenceBuilder (AudioProcessorGraph& g, RenderSequence& s)\r
- : graph (g), sequence (s), orderedNodes (createOrderedNodeList (graph))\r
+public:\r
+ using Node = AudioProcessorGraph::Node;\r
+ using NodeID = AudioProcessorGraph::NodeID;\r
+ using Connection = AudioProcessorGraph::Connection;\r
+ using NodeAndChannel = AudioProcessorGraph::NodeAndChannel;\r
+\r
+ static constexpr auto midiChannelIndex = AudioProcessorGraph::midiChannelIndex;\r
+\r
+ template <typename RenderSequence>\r
+ static auto build (const Nodes& n, const Connections& c)\r
{\r
- audioBuffers.add (AssignedBuffer::createReadOnlyEmpty()); // first buffer is read-only zeros\r
- midiBuffers .add (AssignedBuffer::createReadOnlyEmpty());\r
+ RenderSequence sequence;\r
+ const RenderSequenceBuilder builder (n, c, sequence);\r
\r
- for (int i = 0; i < orderedNodes.size(); ++i)\r
+ struct SequenceAndLatency\r
{\r
- createRenderingOpsForNode (*orderedNodes.getUnchecked(i), i);\r
- markAnyUnusedBuffersAsFree (audioBuffers, i);\r
- markAnyUnusedBuffersAsFree (midiBuffers, i);\r
- }\r
-\r
- graph.setLatencySamples (totalLatency);\r
+ RenderSequence sequence;\r
+ int latencySamples = 0;\r
+ };\r
\r
- s.numBuffersNeeded = audioBuffers.size();\r
- s.numMidiBuffersNeeded = midiBuffers.size();\r
+ return SequenceAndLatency { std::move (sequence), builder.totalLatency };\r
}\r
\r
+private:\r
//==============================================================================\r
- using Node = AudioProcessorGraph::Node;\r
- using NodeID = AudioProcessorGraph::NodeID;\r
-\r
- AudioProcessorGraph& graph;\r
- RenderSequence& sequence;\r
-\r
const Array<Node*> orderedNodes;\r
\r
struct AssignedBuffer\r
{\r
- AudioProcessorGraph::NodeAndChannel channel;\r
+ NodeAndChannel channel;\r
\r
static AssignedBuffer createReadOnlyEmpty() noexcept { return { { zeroNodeID(), 0 } }; }\r
static AssignedBuffer createFree() noexcept { return { { freeNodeID(), 0 } }; }\r
\r
enum { readOnlyEmptyBufferIndex = 0 };\r
\r
- struct Delay\r
- {\r
- NodeID nodeID;\r
- int delay;\r
- };\r
-\r
HashMap<uint32, int> delays;\r
int totalLatency = 0;\r
\r
return delays[nodeID.uid];\r
}\r
\r
- int getInputLatencyForNode (NodeID nodeID) const\r
+ int getInputLatencyForNode (const Connections& c, NodeID nodeID) const\r
{\r
- int maxLatency = 0;\r
-\r
- for (auto&& c : graph.getConnections())\r
- if (c.destination.nodeID == nodeID)\r
- maxLatency = jmax (maxLatency, getNodeDelay (c.source.nodeID));\r
-\r
- return maxLatency;\r
+ const auto sources = c.getSourceNodesForDestination (nodeID);\r
+ return std::accumulate (sources.cbegin(), sources.cend(), 0, [this] (auto acc, auto source)\r
+ {\r
+ return jmax (acc, this->getNodeDelay (source));\r
+ });\r
}\r
\r
//==============================================================================\r
- static void getAllParentsOfNode (const Node* child,\r
- std::unordered_set<Node*>& parents,\r
- const std::unordered_map<Node*, std::unordered_set<Node*>>& otherParents)\r
+ void getAllParentsOfNode (const NodeID& child,\r
+ std::set<NodeID>& parents,\r
+ const std::map<NodeID, std::set<NodeID>>& otherParents,\r
+ const Connections& c)\r
{\r
- for (auto&& i : child->inputs)\r
+ for (const auto& parentNode : c.getSourceNodesForDestination (child))\r
{\r
- auto* parentNode = i.otherNode;\r
-\r
if (parentNode == child)\r
continue;\r
\r
if (parents.insert (parentNode).second)\r
{\r
- auto parentParents = otherParents.find (parentNode);\r
+ const auto parentParents = otherParents.find (parentNode);\r
\r
if (parentParents != otherParents.end())\r
{\r
continue;\r
}\r
\r
- getAllParentsOfNode (i.otherNode, parents, otherParents);\r
+ getAllParentsOfNode (parentNode, parents, otherParents, c);\r
}\r
}\r
}\r
\r
- static auto createOrderedNodeList (const AudioProcessorGraph& graph)\r
+ Array<Node*> createOrderedNodeList (const Nodes& n, const Connections& c)\r
{\r
Array<Node*> result;\r
\r
- std::unordered_map<Node*, std::unordered_set<Node*>> nodeParents;\r
+ std::map<NodeID, std::set<NodeID>> nodeParents;\r
\r
- for (auto* node : graph.getNodes())\r
+ for (auto& node : n.getNodes())\r
{\r
+ const auto nodeID = node->nodeID;\r
int insertionIndex = 0;\r
\r
for (; insertionIndex < result.size(); ++insertionIndex)\r
{\r
- auto& parents = nodeParents[result.getUnchecked (insertionIndex)];\r
+ auto& parents = nodeParents[result.getUnchecked (insertionIndex)->nodeID];\r
\r
- if (parents.find (node) != parents.end())\r
+ if (parents.find (nodeID) != parents.end())\r
break;\r
}\r
\r
result.insert (insertionIndex, node);\r
- getAllParentsOfNode (node, nodeParents[node], nodeParents);\r
+ getAllParentsOfNode (nodeID, nodeParents[node->nodeID], nodeParents, c);\r
}\r
\r
return result;\r
}\r
\r
- int findBufferForInputAudioChannel (Node& node, const int inputChan,\r
- const int ourRenderingIndex, const int maxLatency)\r
+ //==============================================================================\r
+ template <typename RenderSequence>\r
+ int findBufferForInputAudioChannel (const Connections& c,\r
+ RenderSequence& sequence,\r
+ Node& node,\r
+ const int inputChan,\r
+ const int ourRenderingIndex,\r
+ const int maxLatency)\r
{\r
auto& processor = *node.getProcessor();\r
auto numOuts = processor.getTotalNumOutputChannels();\r
\r
- auto sources = getSourcesForChannel (node, inputChan);\r
+ auto sources = c.getSourcesForDestination ({ node.nodeID, inputChan });\r
\r
// Handle an unconnected input channel...\r
- if (sources.isEmpty())\r
+ if (sources.empty())\r
{\r
if (inputChan >= numOuts)\r
return readOnlyEmptyBufferIndex;\r
if (sources.size() == 1)\r
{\r
// channel with a straightforward single input..\r
- auto src = sources.getUnchecked(0);\r
+ auto src = *sources.begin();\r
\r
int bufIndex = getBufferContaining (src);\r
\r
jassert (bufIndex >= 0);\r
}\r
\r
- if (inputChan < numOuts\r
- && isBufferNeededLater (ourRenderingIndex, inputChan, src))\r
+ if (inputChan < numOuts && isBufferNeededLater (c, ourRenderingIndex, inputChan, src))\r
{\r
// can't mess up this channel because it's needed later by another node,\r
// so we need to use a copy of it..\r
int reusableInputIndex = -1;\r
int bufIndex = -1;\r
\r
- for (int i = 0; i < sources.size(); ++i)\r
{\r
- auto src = sources.getReference(i);\r
- auto sourceBufIndex = getBufferContaining (src);\r
-\r
- if (sourceBufIndex >= 0 && ! isBufferNeededLater (ourRenderingIndex, inputChan, src))\r
+ auto i = 0;\r
+ for (const auto& src : sources)\r
{\r
- // we've found one of our input chans that can be re-used..\r
- reusableInputIndex = i;\r
- bufIndex = sourceBufIndex;\r
+ auto sourceBufIndex = getBufferContaining (src);\r
+\r
+ if (sourceBufIndex >= 0 && ! isBufferNeededLater (c, ourRenderingIndex, inputChan, src))\r
+ {\r
+ // we've found one of our input chans that can be re-used..\r
+ reusableInputIndex = i;\r
+ bufIndex = sourceBufIndex;\r
\r
- auto nodeDelay = getNodeDelay (src.nodeID);\r
+ auto nodeDelay = getNodeDelay (src.nodeID);\r
\r
- if (nodeDelay < maxLatency)\r
- sequence.addDelayChannelOp (bufIndex, maxLatency - nodeDelay);\r
+ if (nodeDelay < maxLatency)\r
+ sequence.addDelayChannelOp (bufIndex, maxLatency - nodeDelay);\r
\r
- break;\r
+ break;\r
+ }\r
+\r
+ ++i;\r
}\r
}\r
\r
\r
audioBuffers.getReference (bufIndex).setAssignedToNonExistentNode();\r
\r
- auto srcIndex = getBufferContaining (sources.getFirst());\r
+ auto srcIndex = getBufferContaining (*sources.begin());\r
\r
if (srcIndex < 0)\r
sequence.addClearChannelOp (bufIndex); // if not found, this is probably a feedback loop\r
sequence.addCopyChannelOp (srcIndex, bufIndex);\r
\r
reusableInputIndex = 0;\r
- auto nodeDelay = getNodeDelay (sources.getFirst().nodeID);\r
+ auto nodeDelay = getNodeDelay (sources.begin()->nodeID);\r
\r
if (nodeDelay < maxLatency)\r
sequence.addDelayChannelOp (bufIndex, maxLatency - nodeDelay);\r
}\r
\r
- for (int i = 0; i < sources.size(); ++i)\r
{\r
- if (i != reusableInputIndex)\r
+ auto i = 0;\r
+ for (const auto& src : sources)\r
{\r
- auto src = sources.getReference(i);\r
- int srcIndex = getBufferContaining (src);\r
-\r
- if (srcIndex >= 0)\r
+ if (i != reusableInputIndex)\r
{\r
- auto nodeDelay = getNodeDelay (src.nodeID);\r
+ int srcIndex = getBufferContaining (src);\r
\r
- if (nodeDelay < maxLatency)\r
+ if (srcIndex >= 0)\r
{\r
- if (! isBufferNeededLater (ourRenderingIndex, inputChan, src))\r
- {\r
- sequence.addDelayChannelOp (srcIndex, maxLatency - nodeDelay);\r
- }\r
- else // buffer is reused elsewhere, can't be delayed\r
+ auto nodeDelay = getNodeDelay (src.nodeID);\r
+\r
+ if (nodeDelay < maxLatency)\r
{\r
- auto bufferToDelay = getFreeBuffer (audioBuffers);\r
- sequence.addCopyChannelOp (srcIndex, bufferToDelay);\r
- sequence.addDelayChannelOp (bufferToDelay, maxLatency - nodeDelay);\r
- srcIndex = bufferToDelay;\r
+ if (! isBufferNeededLater (c, ourRenderingIndex, inputChan, src))\r
+ {\r
+ sequence.addDelayChannelOp (srcIndex, maxLatency - nodeDelay);\r
+ }\r
+ else // buffer is reused elsewhere, can't be delayed\r
+ {\r
+ auto bufferToDelay = getFreeBuffer (audioBuffers);\r
+ sequence.addCopyChannelOp (srcIndex, bufferToDelay);\r
+ sequence.addDelayChannelOp (bufferToDelay, maxLatency - nodeDelay);\r
+ srcIndex = bufferToDelay;\r
+ }\r
}\r
- }\r
\r
- sequence.addAddChannelOp (srcIndex, bufIndex);\r
+ sequence.addAddChannelOp (srcIndex, bufIndex);\r
+ }\r
}\r
+\r
+ ++i;\r
}\r
}\r
\r
return bufIndex;\r
}\r
\r
- int findBufferForInputMidiChannel (Node& node, int ourRenderingIndex)\r
+ template <typename RenderSequence>\r
+ int findBufferForInputMidiChannel (const Connections& c,\r
+ RenderSequence& sequence,\r
+ Node& node,\r
+ int ourRenderingIndex)\r
{\r
auto& processor = *node.getProcessor();\r
- auto sources = getSourcesForChannel (node, AudioProcessorGraph::midiChannelIndex);\r
+ auto sources = c.getSourcesForDestination ({ node.nodeID, midiChannelIndex });\r
\r
// No midi inputs..\r
- if (sources.isEmpty())\r
+ if (sources.empty())\r
{\r
auto midiBufferToUse = getFreeBuffer (midiBuffers); // need to pick a buffer even if the processor doesn't use midi\r
\r
// One midi input..\r
if (sources.size() == 1)\r
{\r
- auto src = sources.getReference (0);\r
+ auto src = *sources.begin();\r
auto midiBufferToUse = getBufferContaining (src);\r
\r
if (midiBufferToUse >= 0)\r
{\r
- if (isBufferNeededLater (ourRenderingIndex, AudioProcessorGraph::midiChannelIndex, src))\r
+ if (isBufferNeededLater (c, ourRenderingIndex, midiChannelIndex, src))\r
{\r
// can't mess up this channel because it's needed later by another node, so we\r
// need to use a copy of it..\r
int midiBufferToUse = -1;\r
int reusableInputIndex = -1;\r
\r
- for (int i = 0; i < sources.size(); ++i)\r
{\r
- auto src = sources.getReference (i);\r
- auto sourceBufIndex = getBufferContaining (src);\r
-\r
- if (sourceBufIndex >= 0\r
- && ! isBufferNeededLater (ourRenderingIndex, AudioProcessorGraph::midiChannelIndex, src))\r
+ auto i = 0;\r
+ for (const auto& src : sources)\r
{\r
- // we've found one of our input buffers that can be re-used..\r
- reusableInputIndex = i;\r
- midiBufferToUse = sourceBufIndex;\r
- break;\r
+ auto sourceBufIndex = getBufferContaining (src);\r
+\r
+ if (sourceBufIndex >= 0\r
+ && ! isBufferNeededLater (c, ourRenderingIndex, midiChannelIndex, src))\r
+ {\r
+ // we've found one of our input buffers that can be re-used..\r
+ reusableInputIndex = i;\r
+ midiBufferToUse = sourceBufIndex;\r
+ break;\r
+ }\r
+\r
+ ++i;\r
}\r
}\r
\r
midiBufferToUse = getFreeBuffer (midiBuffers);\r
jassert (midiBufferToUse >= 0);\r
\r
- auto srcIndex = getBufferContaining (sources.getUnchecked(0));\r
+ auto srcIndex = getBufferContaining (*sources.begin());\r
\r
if (srcIndex >= 0)\r
sequence.addCopyMidiBufferOp (srcIndex, midiBufferToUse);\r
reusableInputIndex = 0;\r
}\r
\r
- for (int i = 0; i < sources.size(); ++i)\r
{\r
- if (i != reusableInputIndex)\r
+ auto i = 0;\r
+ for (const auto& src : sources)\r
{\r
- auto srcIndex = getBufferContaining (sources.getUnchecked(i));\r
+ if (i != reusableInputIndex)\r
+ {\r
+ auto srcIndex = getBufferContaining (src);\r
+\r
+ if (srcIndex >= 0)\r
+ sequence.addAddMidiBufferOp (srcIndex, midiBufferToUse);\r
+ }\r
\r
- if (srcIndex >= 0)\r
- sequence.addAddMidiBufferOp (srcIndex, midiBufferToUse);\r
+ ++i;\r
}\r
}\r
\r
return midiBufferToUse;\r
}\r
\r
- void createRenderingOpsForNode (Node& node, const int ourRenderingIndex)\r
+ template <typename RenderSequence>\r
+ void createRenderingOpsForNode (const Connections& c,\r
+ RenderSequence& sequence,\r
+ Node& node,\r
+ const int ourRenderingIndex)\r
{\r
auto& processor = *node.getProcessor();\r
auto numIns = processor.getTotalNumInputChannels();\r
auto totalChans = jmax (numIns, numOuts);\r
\r
Array<int> audioChannelsToUse;\r
- auto maxLatency = getInputLatencyForNode (node.nodeID);\r
+ auto maxLatency = getInputLatencyForNode (c, node.nodeID);\r
\r
for (int inputChan = 0; inputChan < numIns; ++inputChan)\r
{\r
// get a list of all the inputs to this node\r
- auto index = findBufferForInputAudioChannel (node, inputChan, ourRenderingIndex, maxLatency);\r
+ auto index = findBufferForInputAudioChannel (c,\r
+ sequence,\r
+ node,\r
+ inputChan,\r
+ ourRenderingIndex,\r
+ maxLatency);\r
jassert (index >= 0);\r
\r
audioChannelsToUse.add (index);\r
audioBuffers.getReference (index).channel = { node.nodeID, outputChan };\r
}\r
\r
- auto midiBufferToUse = findBufferForInputMidiChannel (node, ourRenderingIndex);\r
+ auto midiBufferToUse = findBufferForInputMidiChannel (c, sequence, node, ourRenderingIndex);\r
\r
if (processor.producesMidi())\r
- midiBuffers.getReference (midiBufferToUse).channel = { node.nodeID, AudioProcessorGraph::midiChannelIndex };\r
+ midiBuffers.getReference (midiBufferToUse).channel = { node.nodeID, midiChannelIndex };\r
\r
delays.set (node.nodeID.uid, maxLatency + processor.getLatencySamples());\r
\r
}\r
\r
//==============================================================================\r
- Array<AudioProcessorGraph::NodeAndChannel> getSourcesForChannel (Node& node, int inputChannelIndex)\r
- {\r
- Array<AudioProcessorGraph::NodeAndChannel> results;\r
- AudioProcessorGraph::NodeAndChannel nc { node.nodeID, inputChannelIndex };\r
-\r
- for (auto&& c : graph.getConnections())\r
- if (c.destination == nc)\r
- results.add (c.source);\r
-\r
- return results;\r
- }\r
-\r
static int getFreeBuffer (Array<AssignedBuffer>& buffers)\r
{\r
for (int i = 1; i < buffers.size(); ++i)\r
return buffers.size() - 1;\r
}\r
\r
- int getBufferContaining (AudioProcessorGraph::NodeAndChannel output) const noexcept\r
+ int getBufferContaining (NodeAndChannel output) const noexcept\r
{\r
int i = 0;\r
\r
return -1;\r
}\r
\r
- void markAnyUnusedBuffersAsFree (Array<AssignedBuffer>& buffers, const int stepIndex)\r
+ void markAnyUnusedBuffersAsFree (const Connections& c,\r
+ Array<AssignedBuffer>& buffers,\r
+ const int stepIndex)\r
{\r
for (auto& b : buffers)\r
- if (b.isAssigned() && ! isBufferNeededLater (stepIndex, -1, b.channel))\r
+ if (b.isAssigned() && ! isBufferNeededLater (c, stepIndex, -1, b.channel))\r
b.setFree();\r
}\r
\r
- bool isBufferNeededLater (int stepIndexToSearchFrom,\r
+ bool isBufferNeededLater (const Connections& c,\r
+ int stepIndexToSearchFrom,\r
int inputChannelOfIndexToIgnore,\r
- AudioProcessorGraph::NodeAndChannel output) const\r
+ NodeAndChannel output) const\r
{\r
while (stepIndexToSearchFrom < orderedNodes.size())\r
{\r
\r
if (output.isMIDI())\r
{\r
- if (inputChannelOfIndexToIgnore != AudioProcessorGraph::midiChannelIndex\r
- && graph.isConnected ({ { output.nodeID, AudioProcessorGraph::midiChannelIndex },\r
- { node->nodeID, AudioProcessorGraph::midiChannelIndex } }))\r
+ if (inputChannelOfIndexToIgnore != midiChannelIndex\r
+ && c.isConnected ({ { output.nodeID, midiChannelIndex },\r
+ { node->nodeID, midiChannelIndex } }))\r
return true;\r
}\r
else\r
{\r
for (int i = 0; i < node->getProcessor()->getTotalNumInputChannels(); ++i)\r
- if (i != inputChannelOfIndexToIgnore && graph.isConnected ({ output, { node->nodeID, i } }))\r
+ if (i != inputChannelOfIndexToIgnore && c.isConnected ({ output, { node->nodeID, i } }))\r
return true;\r
}\r
\r
return false;\r
}\r
\r
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RenderSequenceBuilder)\r
+ template <typename RenderSequence>\r
+ RenderSequenceBuilder (const Nodes& n, const Connections& c, RenderSequence& sequence)\r
+ : orderedNodes (createOrderedNodeList (n, c))\r
+ {\r
+ audioBuffers.add (AssignedBuffer::createReadOnlyEmpty()); // first buffer is read-only zeros\r
+ midiBuffers .add (AssignedBuffer::createReadOnlyEmpty());\r
+\r
+ for (int i = 0; i < orderedNodes.size(); ++i)\r
+ {\r
+ createRenderingOpsForNode (c, sequence, *orderedNodes.getUnchecked (i), i);\r
+ markAnyUnusedBuffersAsFree (c, audioBuffers, i);\r
+ markAnyUnusedBuffersAsFree (c, midiBuffers, i);\r
+ }\r
+\r
+ sequence.numBuffersNeeded = audioBuffers.size();\r
+ sequence.numMidiBuffersNeeded = midiBuffers.size();\r
+ }\r
};\r
\r
//==============================================================================\r
-AudioProcessorGraph::Connection::Connection (NodeAndChannel src, NodeAndChannel dst) noexcept\r
- : source (src), destination (dst)\r
+/* A full graph of audio processors, ready to process at a particular sample rate, block size,\r
+ and precision.\r
+\r
+ Instances of this class will be created on the main thread, and then passed over to the audio\r
+ thread for processing.\r
+*/\r
+class RenderSequence\r
{\r
-}\r
+public:\r
+ using AudioGraphIOProcessor = AudioProcessorGraph::AudioGraphIOProcessor;\r
\r
-bool AudioProcessorGraph::Connection::operator== (const Connection& other) const noexcept\r
-{\r
- return source == other.source && destination == other.destination;\r
-}\r
-\r
-bool AudioProcessorGraph::Connection::operator!= (const Connection& c) const noexcept\r
-{\r
- return ! operator== (c);\r
-}\r
-\r
-bool AudioProcessorGraph::Connection::operator< (const Connection& other) const noexcept\r
-{\r
- if (source.nodeID != other.source.nodeID)\r
- return source.nodeID < other.source.nodeID;\r
-\r
- if (destination.nodeID != other.destination.nodeID)\r
- return destination.nodeID < other.destination.nodeID;\r
-\r
- if (source.channelIndex != other.source.channelIndex)\r
- return source.channelIndex < other.source.channelIndex;\r
-\r
- return destination.channelIndex < other.destination.channelIndex;\r
-}\r
-\r
-//==============================================================================\r
-AudioProcessorGraph::Node::Node (NodeID n, std::unique_ptr<AudioProcessor> p) noexcept\r
- : nodeID (n), processor (std::move (p))\r
-{\r
- jassert (processor != nullptr);\r
-}\r
-\r
-void AudioProcessorGraph::Node::prepare (double newSampleRate, int newBlockSize,\r
- AudioProcessorGraph* graph, ProcessingPrecision precision)\r
-{\r
- const ScopedLock lock (processorLock);\r
-\r
- if (! isPrepared)\r
+ RenderSequence (PrepareSettings s, const Nodes& n, const Connections& c)\r
+ : RenderSequence (s,\r
+ RenderSequenceBuilder::build<GraphRenderSequence<float>> (n, c),\r
+ RenderSequenceBuilder::build<GraphRenderSequence<double>> (n, c))\r
{\r
- setParentGraph (graph);\r
-\r
- // try to align the precision of the processor and the graph\r
- processor->setProcessingPrecision (processor->supportsDoublePrecisionProcessing() ? precision\r
- : singlePrecision);\r
-\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
+ void process (AudioBuffer<float>& audio, MidiBuffer& midi, AudioPlayHead* playHead)\r
{\r
- isPrepared = false;\r
- processor->releaseResources();\r
+ renderSequenceF.perform (audio, midi, playHead);\r
}\r
-}\r
\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
+ void process (AudioBuffer<double>& audio, MidiBuffer& midi, AudioPlayHead* playHead)\r
+ {\r
+ renderSequenceD.perform (audio, midi, playHead);\r
+ }\r
\r
-bool AudioProcessorGraph::Node::Connection::operator== (const Connection& other) const noexcept\r
-{\r
- return otherNode == other.otherNode\r
- && thisChannel == other.thisChannel\r
- && otherChannel == other.otherChannel;\r
-}\r
+ void processIO (AudioGraphIOProcessor& io, AudioBuffer<float>& audio, MidiBuffer& midi)\r
+ {\r
+ processIOBlock (io, renderSequenceF, audio, midi);\r
+ }\r
\r
-//==============================================================================\r
-bool AudioProcessorGraph::Node::isBypassed() const noexcept\r
-{\r
- if (processor != nullptr)\r
+ void processIO (AudioGraphIOProcessor& io, AudioBuffer<double>& audio, MidiBuffer& midi)\r
{\r
- if (auto* bypassParam = processor->getBypassParameter())\r
- return (bypassParam->getValue() != 0.0f);\r
+ processIOBlock (io, renderSequenceD, audio, midi);\r
}\r
\r
- return bypassed;\r
-}\r
+ int getLatencySamples() const { return latencySamples; }\r
+ PrepareSettings getSettings() const { return settings; }\r
\r
-void AudioProcessorGraph::Node::setBypassed (bool shouldBeBypassed) noexcept\r
-{\r
- if (processor != nullptr)\r
+private:\r
+ template <typename FloatType, typename SequenceType>\r
+ static void processIOBlock (AudioGraphIOProcessor& io,\r
+ SequenceType& sequence,\r
+ AudioBuffer<FloatType>& buffer,\r
+ MidiBuffer& midiMessages)\r
{\r
- if (auto* bypassParam = processor->getBypassParameter())\r
- bypassParam->setValueNotifyingHost (shouldBeBypassed ? 1.0f : 0.0f);\r
- }\r
+ switch (io.getType())\r
+ {\r
+ case AudioGraphIOProcessor::audioOutputNode:\r
+ {\r
+ auto&& currentAudioOutputBuffer = sequence.currentAudioOutputBuffer;\r
\r
- bypassed = shouldBeBypassed;\r
-}\r
+ for (int i = jmin (currentAudioOutputBuffer.getNumChannels(), buffer.getNumChannels()); --i >= 0;)\r
+ currentAudioOutputBuffer.addFrom (i, 0, buffer, i, 0, buffer.getNumSamples());\r
\r
-//==============================================================================\r
-struct AudioProcessorGraph::RenderSequenceFloat : public GraphRenderSequence<float> {};\r
-struct AudioProcessorGraph::RenderSequenceDouble : public GraphRenderSequence<double> {};\r
+ break;\r
+ }\r
\r
-//==============================================================================\r
-AudioProcessorGraph::AudioProcessorGraph()\r
-{\r
-}\r
+ case AudioGraphIOProcessor::audioInputNode:\r
+ {\r
+ auto* currentInputBuffer = sequence.currentAudioInputBuffer;\r
\r
-AudioProcessorGraph::~AudioProcessorGraph()\r
-{\r
- cancelPendingUpdate();\r
- clearRenderingSequence();\r
- clear();\r
-}\r
+ for (int i = jmin (currentInputBuffer->getNumChannels(), buffer.getNumChannels()); --i >= 0;)\r
+ buffer.copyFrom (i, 0, *currentInputBuffer, i, 0, buffer.getNumSamples());\r
\r
-const String AudioProcessorGraph::getName() const\r
-{\r
- return "Audio Graph";\r
-}\r
+ break;\r
+ }\r
\r
-//==============================================================================\r
-void AudioProcessorGraph::topologyChanged()\r
-{\r
- sendChangeMessage();\r
+ case AudioGraphIOProcessor::midiOutputNode:\r
+ sequence.currentMidiOutputBuffer.addEvents (midiMessages, 0, buffer.getNumSamples(), 0);\r
+ break;\r
\r
- if (isPrepared)\r
- updateOnMessageThread (*this);\r
-}\r
+ case AudioGraphIOProcessor::midiInputNode:\r
+ midiMessages.addEvents (*sequence.currentMidiInputBuffer, 0, buffer.getNumSamples(), 0);\r
+ break;\r
\r
-void AudioProcessorGraph::clear()\r
-{\r
- const ScopedLock sl (getCallbackLock());\r
+ default:\r
+ break;\r
+ }\r
+ }\r
\r
- if (nodes.isEmpty())\r
- return;\r
+ template <typename Float, typename Double>\r
+ RenderSequence (PrepareSettings s, Float f, Double d)\r
+ : settings (s),\r
+ renderSequenceF (std::move (f.sequence)),\r
+ renderSequenceD (std::move (d.sequence)),\r
+ latencySamples (f.latencySamples)\r
+ {\r
+ jassert (f.latencySamples == d.latencySamples);\r
\r
- nodes.clear();\r
- topologyChanged();\r
-}\r
+ renderSequenceF.prepareBuffers (settings.blockSize);\r
+ renderSequenceD.prepareBuffers (settings.blockSize);\r
+ }\r
\r
-AudioProcessorGraph::Node* AudioProcessorGraph::getNodeForId (NodeID nodeID) const\r
-{\r
- for (auto* n : nodes)\r
- if (n->nodeID == nodeID)\r
- return n;\r
+ PrepareSettings settings;\r
+ GraphRenderSequence<float> renderSequenceF;\r
+ GraphRenderSequence<double> renderSequenceD;\r
+ int latencySamples = 0;\r
+};\r
\r
- return {};\r
-}\r
+//==============================================================================\r
+/* Facilitates wait-free render-sequence updates.\r
\r
-AudioProcessorGraph::Node::Ptr AudioProcessorGraph::addNode (std::unique_ptr<AudioProcessor> newProcessor, NodeID nodeID)\r
+ Topology updates always happen on the main thread (or synchronised with the main thread).\r
+ After updating the graph, the 'baked' graph is passed to RenderSequenceExchange::set.\r
+ At the top of the audio callback, RenderSequenceExchange::updateAudioThreadState will\r
+ attempt to install the most-recently-baked graph, if there's one waiting.\r
+*/\r
+class RenderSequenceExchange : private Timer\r
{\r
- if (newProcessor == nullptr || newProcessor.get() == this)\r
+public:\r
+ RenderSequenceExchange()\r
{\r
- jassertfalse;\r
- return {};\r
+ startTimer (500);\r
}\r
\r
- if (nodeID == NodeID())\r
- nodeID.uid = ++(lastNodeID.uid);\r
-\r
- for (auto* n : nodes)\r
+ ~RenderSequenceExchange() override\r
{\r
- if (n->getProcessor() == newProcessor.get() || n->nodeID == nodeID)\r
- {\r
- jassertfalse; // Cannot add two copies of the same processor, or duplicate node IDs!\r
- return {};\r
- }\r
+ stopTimer();\r
}\r
\r
- if (lastNodeID < nodeID)\r
- lastNodeID = nodeID;\r
-\r
- newProcessor->setPlayHead (getPlayHead());\r
-\r
- Node::Ptr n (new Node (nodeID, std::move (newProcessor)));\r
-\r
+ void set (std::unique_ptr<RenderSequence>&& next)\r
{\r
- const ScopedLock sl (getCallbackLock());\r
- nodes.add (n.get());\r
+ const SpinLock::ScopedLockType lock (mutex);\r
+ mainThreadState = std::move (next);\r
+ isNew = true;\r
}\r
\r
- n->setParentGraph (this);\r
- topologyChanged();\r
- return n;\r
-}\r
-\r
-AudioProcessorGraph::Node::Ptr AudioProcessorGraph::removeNode (NodeID nodeId)\r
-{\r
- const ScopedLock sl (getCallbackLock());\r
-\r
- for (int i = nodes.size(); --i >= 0;)\r
+ /** Call from the audio thread only. */\r
+ void updateAudioThreadState()\r
{\r
- if (nodes.getUnchecked (i)->nodeID == nodeId)\r
+ const SpinLock::ScopedTryLockType lock (mutex);\r
+\r
+ if (lock.isLocked() && isNew)\r
{\r
- disconnectNode (nodeId);\r
- auto node = nodes.removeAndReturn (i);\r
- topologyChanged();\r
- return node;\r
+ // Swap pointers rather than assigning to avoid calling delete here\r
+ std::swap (mainThreadState, audioThreadState);\r
+ isNew = false;\r
}\r
}\r
\r
- return {};\r
-}\r
+ /** Call from the audio thread only. */\r
+ RenderSequence* getAudioThreadState() const { return audioThreadState.get(); }\r
\r
-AudioProcessorGraph::Node::Ptr AudioProcessorGraph::removeNode (Node* node)\r
-{\r
- if (node != nullptr)\r
- return removeNode (node->nodeID);\r
+private:\r
+ void timerCallback() override\r
+ {\r
+ const SpinLock::ScopedLockType lock (mutex);\r
\r
- jassertfalse;\r
- return {};\r
-}\r
+ if (! isNew)\r
+ mainThreadState.reset();\r
+ }\r
+\r
+ SpinLock mutex;\r
+ std::unique_ptr<RenderSequence> mainThreadState, audioThreadState;\r
+ bool isNew = false;\r
+};\r
\r
//==============================================================================\r
-void AudioProcessorGraph::getNodeConnections (Node& node, std::vector<Connection>& connections)\r
+AudioProcessorGraph::Connection::Connection (NodeAndChannel src, NodeAndChannel dst) noexcept\r
+ : source (src), destination (dst)\r
{\r
- for (auto& i : node.inputs)\r
- connections.push_back ({ { i.otherNode->nodeID, i.otherChannel }, { node.nodeID, i.thisChannel } });\r
-\r
- for (auto& o : node.outputs)\r
- connections.push_back ({ { node.nodeID, o.thisChannel }, { o.otherNode->nodeID, o.otherChannel } });\r
}\r
\r
-std::vector<AudioProcessorGraph::Connection> AudioProcessorGraph::getConnections() const\r
+bool AudioProcessorGraph::Connection::operator== (const Connection& other) const noexcept\r
{\r
- std::vector<Connection> connections;\r
-\r
- for (auto& n : nodes)\r
- getNodeConnections (*n, connections);\r
-\r
- std::sort (connections.begin(), connections.end());\r
- auto last = std::unique (connections.begin(), connections.end());\r
- connections.erase (last, connections.end());\r
-\r
- return connections;\r
+ return source == other.source && destination == other.destination;\r
}\r
\r
-bool AudioProcessorGraph::isConnected (Node* source, int sourceChannel, Node* dest, int destChannel) const noexcept\r
+bool AudioProcessorGraph::Connection::operator!= (const Connection& c) const noexcept\r
{\r
- for (auto& o : source->outputs)\r
- if (o.otherNode == dest && o.thisChannel == sourceChannel && o.otherChannel == destChannel)\r
- return true;\r
-\r
- return false;\r
+ return ! operator== (c);\r
}\r
\r
-bool AudioProcessorGraph::isConnected (const Connection& c) const noexcept\r
+bool AudioProcessorGraph::Connection::operator< (const Connection& other) const noexcept\r
{\r
- if (auto* source = getNodeForId (c.source.nodeID))\r
- if (auto* dest = getNodeForId (c.destination.nodeID))\r
- return isConnected (source, c.source.channelIndex,\r
- dest, c.destination.channelIndex);\r
-\r
- return false;\r
+ const auto tie = [] (auto& x)\r
+ {\r
+ return std::tie (x.source.nodeID,\r
+ x.destination.nodeID,\r
+ x.source.channelIndex,\r
+ x.destination.channelIndex);\r
+ };\r
+ return tie (*this) < tie (other);\r
}\r
\r
-bool AudioProcessorGraph::isConnected (NodeID srcID, NodeID destID) const noexcept\r
+//==============================================================================\r
+class AudioProcessorGraph::Pimpl : private AsyncUpdater\r
{\r
- if (auto* source = getNodeForId (srcID))\r
- if (auto* dest = getNodeForId (destID))\r
- for (auto& out : source->outputs)\r
- if (out.otherNode == dest)\r
- return true;\r
-\r
- return false;\r
-}\r
+public:\r
+ explicit Pimpl (AudioProcessorGraph& o) : owner (&o) {}\r
\r
-bool AudioProcessorGraph::isAnInputTo (Node& src, Node& dst) const noexcept\r
-{\r
- jassert (nodes.contains (&src));\r
- jassert (nodes.contains (&dst));\r
+ ~Pimpl() override\r
+ {\r
+ cancelPendingUpdate();\r
+ clear (UpdateKind::sync);\r
+ }\r
\r
- return isAnInputTo (src, dst, nodes.size());\r
-}\r
+ const auto& getNodes() const { return nodes.getNodes(); }\r
\r
-bool AudioProcessorGraph::isAnInputTo (Node& src, Node& dst, int recursionCheck) const noexcept\r
-{\r
- for (auto&& i : dst.inputs)\r
- if (i.otherNode == &src)\r
- return true;\r
+ void clear (UpdateKind updateKind)\r
+ {\r
+ if (getNodes().isEmpty())\r
+ return;\r
\r
- if (recursionCheck > 0)\r
- for (auto&& i : dst.inputs)\r
- if (isAnInputTo (src, *i.otherNode, recursionCheck - 1))\r
- return true;\r
+ nodes = Nodes{};\r
+ connections = Connections{};\r
+ topologyChanged (updateKind);\r
+ }\r
\r
- return false;\r
-}\r
+ auto getNodeForId (NodeID nodeID) const\r
+ {\r
+ return nodes.getNodeForId (nodeID);\r
+ }\r
\r
-bool AudioProcessorGraph::canConnect (Node* source, int sourceChannel, Node* dest, int destChannel) const noexcept\r
-{\r
- bool sourceIsMIDI = sourceChannel == midiChannelIndex;\r
- bool destIsMIDI = destChannel == midiChannelIndex;\r
+ Node::Ptr addNode (std::unique_ptr<AudioProcessor> newProcessor,\r
+ const NodeID nodeID,\r
+ UpdateKind updateKind)\r
+ {\r
+ if (newProcessor.get() == owner)\r
+ {\r
+ jassertfalse;\r
+ return nullptr;\r
+ }\r
\r
- if (sourceChannel < 0\r
- || destChannel < 0\r
- || source == dest\r
- || sourceIsMIDI != destIsMIDI)\r
- return false;\r
+ const auto idToUse = nodeID == NodeID() ? NodeID { ++(lastNodeID.uid) } : nodeID;\r
\r
- if (source == nullptr\r
- || (! sourceIsMIDI && sourceChannel >= source->processor->getTotalNumOutputChannels())\r
- || (sourceIsMIDI && ! source->processor->producesMidi()))\r
- return false;\r
+ auto added = nodes.addNode (std::move (newProcessor), idToUse);\r
\r
- if (dest == nullptr\r
- || (! destIsMIDI && destChannel >= dest->processor->getTotalNumInputChannels())\r
- || (destIsMIDI && ! dest->processor->acceptsMidi()))\r
- return false;\r
+ if (added == nullptr)\r
+ return nullptr;\r
\r
- return ! isConnected (source, sourceChannel, dest, destChannel);\r
-}\r
+ if (lastNodeID < idToUse)\r
+ lastNodeID = idToUse;\r
\r
-bool AudioProcessorGraph::canConnect (const Connection& c) const\r
-{\r
- if (auto* source = getNodeForId (c.source.nodeID))\r
- if (auto* dest = getNodeForId (c.destination.nodeID))\r
- return canConnect (source, c.source.channelIndex,\r
- dest, c.destination.channelIndex);\r
+ if (auto* ioProc = dynamic_cast<AudioGraphIOProcessor*> (added->getProcessor()))\r
+ ioProc->setParentGraph (owner);\r
\r
- return false;\r
-}\r
+ topologyChanged (updateKind);\r
+ return added;\r
+ }\r
\r
-bool AudioProcessorGraph::addConnection (const Connection& c)\r
-{\r
- if (auto* source = getNodeForId (c.source.nodeID))\r
+ Node::Ptr removeNode (NodeID nodeID, UpdateKind updateKind)\r
{\r
- if (auto* dest = getNodeForId (c.destination.nodeID))\r
- {\r
- auto sourceChan = c.source.channelIndex;\r
- auto destChan = c.destination.channelIndex;\r
-\r
- if (canConnect (source, sourceChan, dest, destChan))\r
- {\r
- source->outputs.add ({ dest, destChan, sourceChan });\r
- dest->inputs.add ({ source, sourceChan, destChan });\r
- jassert (isConnected (c));\r
- topologyChanged();\r
- return true;\r
- }\r
- }\r
+ connections.disconnectNode (nodeID);\r
+ auto result = nodes.removeNode (nodeID);\r
+ topologyChanged (updateKind);\r
+ return result;\r
}\r
\r
- return false;\r
-}\r
-\r
-bool AudioProcessorGraph::removeConnection (const Connection& c)\r
-{\r
- if (auto* source = getNodeForId (c.source.nodeID))\r
+ std::vector<Connection> getConnections() const\r
{\r
- if (auto* dest = getNodeForId (c.destination.nodeID))\r
- {\r
- auto sourceChan = c.source.channelIndex;\r
- auto destChan = c.destination.channelIndex;\r
-\r
- if (isConnected (source, sourceChan, dest, destChan))\r
- {\r
- source->outputs.removeAllInstancesOf ({ dest, destChan, sourceChan });\r
- dest->inputs.removeAllInstancesOf ({ source, sourceChan, destChan });\r
- topologyChanged();\r
- return true;\r
- }\r
- }\r
+ return connections.getConnections();\r
}\r
\r
- return false;\r
-}\r
-\r
-bool AudioProcessorGraph::disconnectNode (NodeID nodeID)\r
-{\r
- if (auto* node = getNodeForId (nodeID))\r
+ bool isConnected (const Connection& c) const\r
{\r
- std::vector<Connection> connections;\r
- getNodeConnections (*node, connections);\r
-\r
- if (! connections.empty())\r
- {\r
- for (auto c : connections)\r
- removeConnection (c);\r
+ return connections.isConnected (c);\r
+ }\r
\r
- return true;\r
- }\r
+ bool isConnected (NodeID srcID, NodeID destID) const\r
+ {\r
+ return connections.isConnected (srcID, destID);\r
}\r
\r
- return false;\r
-}\r
+ bool isAnInputTo (const Node& src, const Node& dst) const\r
+ {\r
+ return isAnInputTo (src.nodeID, dst.nodeID);\r
+ }\r
\r
-bool AudioProcessorGraph::isLegal (Node* source, int sourceChannel, Node* dest, int destChannel) const noexcept\r
-{\r
- return (sourceChannel == midiChannelIndex ? source->processor->producesMidi()\r
- : isPositiveAndBelow (sourceChannel, source->processor->getTotalNumOutputChannels()))\r
- && (destChannel == midiChannelIndex ? dest->processor->acceptsMidi()\r
- : isPositiveAndBelow (destChannel, dest->processor->getTotalNumInputChannels()));\r
-}\r
+ bool isAnInputTo (NodeID src, NodeID dst) const\r
+ {\r
+ return connections.isAnInputTo (src, dst);\r
+ }\r
\r
-bool AudioProcessorGraph::isConnectionLegal (const Connection& c) const\r
-{\r
- if (auto* source = getNodeForId (c.source.nodeID))\r
- if (auto* dest = getNodeForId (c.destination.nodeID))\r
- return isLegal (source, c.source.channelIndex, dest, c.destination.channelIndex);\r
+ bool canConnect (const Connection& c) const\r
+ {\r
+ return connections.canConnect (nodes, c);\r
+ }\r
\r
- return false;\r
-}\r
+ bool addConnection (const Connection& c, UpdateKind updateKind)\r
+ {\r
+ if (! connections.addConnection (nodes, c))\r
+ return false;\r
\r
-bool AudioProcessorGraph::removeIllegalConnections()\r
-{\r
- bool anyRemoved = false;\r
+ jassert (isConnected (c));\r
+ topologyChanged (updateKind);\r
+ return true;\r
+ }\r
\r
- for (auto* node : nodes)\r
+ bool removeConnection (const Connection& c, UpdateKind updateKind)\r
{\r
- std::vector<Connection> connections;\r
- getNodeConnections (*node, connections);\r
+ if (! connections.removeConnection (c))\r
+ return false;\r
\r
- for (auto c : connections)\r
- if (! isConnectionLegal (c))\r
- anyRemoved = removeConnection (c) || anyRemoved;\r
+ topologyChanged (updateKind);\r
+ return true;\r
}\r
\r
- return anyRemoved;\r
-}\r
+ bool disconnectNode (NodeID nodeID, UpdateKind updateKind)\r
+ {\r
+ if (! connections.disconnectNode (nodeID))\r
+ return false;\r
\r
-//==============================================================================\r
-void AudioProcessorGraph::clearRenderingSequence()\r
-{\r
- std::unique_ptr<RenderSequenceFloat> oldSequenceF;\r
- std::unique_ptr<RenderSequenceDouble> oldSequenceD;\r
+ topologyChanged (updateKind);\r
+ return true;\r
+ }\r
\r
+ bool isConnectionLegal (const Connection& c) const\r
{\r
- const ScopedLock sl (getCallbackLock());\r
- std::swap (renderSequenceFloat, oldSequenceF);\r
- std::swap (renderSequenceDouble, oldSequenceD);\r
+ return connections.isConnectionLegal (nodes, c);\r
}\r
-}\r
\r
-bool AudioProcessorGraph::anyNodesNeedPreparing() const noexcept\r
-{\r
- for (auto* node : nodes)\r
- if (! node->isPrepared)\r
- return true;\r
+ bool removeIllegalConnections (UpdateKind updateKind)\r
+ {\r
+ const auto result = connections.removeIllegalConnections (nodes);\r
+ topologyChanged (updateKind);\r
+ return result;\r
+ }\r
\r
- return false;\r
-}\r
+ //==============================================================================\r
+ void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock)\r
+ {\r
+ owner->setRateAndBufferSizeDetails (sampleRate, estimatedSamplesPerBlock);\r
\r
-void AudioProcessorGraph::buildRenderingSequence()\r
-{\r
- auto newSequenceF = std::make_unique<RenderSequenceFloat>();\r
- auto newSequenceD = std::make_unique<RenderSequenceDouble>();\r
+ PrepareSettings settings;\r
+ settings.precision = owner->getProcessingPrecision();\r
+ settings.sampleRate = sampleRate;\r
+ settings.blockSize = estimatedSamplesPerBlock;\r
\r
- RenderSequenceBuilder<RenderSequenceFloat> builderF (*this, *newSequenceF);\r
- RenderSequenceBuilder<RenderSequenceDouble> builderD (*this, *newSequenceD);\r
+ nodeStates.setState (settings);\r
\r
- const ScopedLock sl (getCallbackLock());\r
+ topologyChanged (UpdateKind::sync);\r
+ }\r
\r
- const auto currentBlockSize = getBlockSize();\r
- newSequenceF->prepareBuffers (currentBlockSize);\r
- newSequenceD->prepareBuffers (currentBlockSize);\r
+ void releaseResources()\r
+ {\r
+ nodeStates.setState (nullopt);\r
+ topologyChanged (UpdateKind::sync);\r
+ }\r
\r
- if (anyNodesNeedPreparing())\r
+ void reset()\r
{\r
- renderSequenceFloat.reset();\r
- renderSequenceDouble.reset();\r
+ for (auto* n : getNodes())\r
+ n->getProcessor()->reset();\r
+ }\r
\r
- for (auto* node : nodes)\r
- node->prepare (getSampleRate(), currentBlockSize, this, getProcessingPrecision());\r
+ void setNonRealtime (bool isProcessingNonRealtime)\r
+ {\r
+ for (auto* n : getNodes())\r
+ n->getProcessor()->setNonRealtime (isProcessingNonRealtime);\r
}\r
\r
- isPrepared = 1;\r
+ template <typename Value>\r
+ void processBlock (AudioBuffer<Value>& audio, MidiBuffer& midi, AudioPlayHead* playHead)\r
+ {\r
+ renderSequenceExchange.updateAudioThreadState();\r
\r
- std::swap (renderSequenceFloat, newSequenceF);\r
- std::swap (renderSequenceDouble, newSequenceD);\r
-}\r
+ if (renderSequenceExchange.getAudioThreadState() == nullptr && MessageManager::getInstance()->isThisTheMessageThread())\r
+ handleAsyncUpdate();\r
\r
-void AudioProcessorGraph::handleAsyncUpdate()\r
-{\r
- buildRenderingSequence();\r
-}\r
+ if (owner->isNonRealtime())\r
+ {\r
+ while (renderSequenceExchange.getAudioThreadState() == nullptr)\r
+ {\r
+ Thread::sleep (1);\r
+ renderSequenceExchange.updateAudioThreadState();\r
+ }\r
+ }\r
\r
-//==============================================================================\r
-void AudioProcessorGraph::prepareToPlay (double sampleRate, int estimatedSamplesPerBlock)\r
-{\r
- {\r
- const ScopedLock sl (getCallbackLock());\r
- setRateAndBufferSizeDetails (sampleRate, estimatedSamplesPerBlock);\r
+ auto* state = renderSequenceExchange.getAudioThreadState();\r
\r
- const auto newPrepareSettings = [&]\r
+ // Only process if the graph has the correct blockSize, sampleRate etc.\r
+ if (state != nullptr && state->getSettings() == nodeStates.getLastRequestedSettings())\r
{\r
- PrepareSettings settings;\r
- settings.precision = getProcessingPrecision();\r
- settings.sampleRate = sampleRate;\r
- settings.blockSize = estimatedSamplesPerBlock;\r
- settings.valid = true;\r
- return settings;\r
- }();\r
-\r
- if (prepareSettings != newPrepareSettings)\r
+ state->process (audio, midi, playHead);\r
+ }\r
+ else\r
{\r
- unprepare();\r
- prepareSettings = newPrepareSettings;\r
+ audio.clear();\r
+ midi.clear();\r
}\r
}\r
\r
- clearRenderingSequence();\r
-\r
- updateOnMessageThread (*this);\r
-}\r
-\r
-bool AudioProcessorGraph::supportsDoublePrecisionProcessing() const\r
-{\r
- return true;\r
-}\r
-\r
-void AudioProcessorGraph::unprepare()\r
-{\r
- prepareSettings.valid = false;\r
-\r
- isPrepared = 0;\r
-\r
- for (auto* n : nodes)\r
- n->unprepare();\r
-}\r
-\r
-void AudioProcessorGraph::releaseResources()\r
-{\r
- const ScopedLock sl (getCallbackLock());\r
-\r
- cancelPendingUpdate();\r
-\r
- unprepare();\r
-\r
- if (renderSequenceFloat != nullptr)\r
- renderSequenceFloat->releaseBuffers();\r
+ /* Call from the audio thread only. */\r
+ auto* getAudioThreadState() const { return renderSequenceExchange.getAudioThreadState(); }\r
\r
- if (renderSequenceDouble != nullptr)\r
- renderSequenceDouble->releaseBuffers();\r
-}\r
-\r
-void AudioProcessorGraph::reset()\r
-{\r
- const ScopedLock sl (getCallbackLock());\r
+private:\r
+ void topologyChanged (UpdateKind updateKind)\r
+ {\r
+ owner->sendChangeMessage();\r
\r
- for (auto* n : nodes)\r
- n->getProcessor()->reset();\r
-}\r
+ if (updateKind == UpdateKind::sync && MessageManager::getInstance()->isThisTheMessageThread())\r
+ handleAsyncUpdate();\r
+ else\r
+ triggerAsyncUpdate();\r
+ }\r
\r
-void AudioProcessorGraph::setNonRealtime (bool isProcessingNonRealtime) noexcept\r
-{\r
- const ScopedLock sl (getCallbackLock());\r
+ void handleAsyncUpdate() override\r
+ {\r
+ if (const auto newSettings = nodeStates.applySettings (nodes))\r
+ {\r
+ auto sequence = std::make_unique<RenderSequence> (*newSettings, nodes, connections);\r
+ owner->setLatencySamples (sequence->getLatencySamples());\r
+ renderSequenceExchange.set (std::move (sequence));\r
+ }\r
+ else\r
+ {\r
+ renderSequenceExchange.set (nullptr);\r
+ }\r
+ }\r
\r
- AudioProcessor::setNonRealtime (isProcessingNonRealtime);\r
+ AudioProcessorGraph* owner = nullptr;\r
+ Nodes nodes;\r
+ Connections connections;\r
+ NodeStates nodeStates;\r
+ RenderSequenceExchange renderSequenceExchange;\r
+ NodeID lastNodeID;\r
+};\r
\r
- for (auto* n : nodes)\r
- n->getProcessor()->setNonRealtime (isProcessingNonRealtime);\r
-}\r
+//==============================================================================\r
+AudioProcessorGraph::AudioProcessorGraph() : pimpl (std::make_unique<Pimpl> (*this)) {}\r
+AudioProcessorGraph::~AudioProcessorGraph() = default;\r
\r
+const String AudioProcessorGraph::getName() const { return "Audio Graph"; }\r
+bool AudioProcessorGraph::supportsDoublePrecisionProcessing() const { return true; }\r
double AudioProcessorGraph::getTailLengthSeconds() const { return 0; }\r
bool AudioProcessorGraph::acceptsMidi() const { return true; }\r
bool AudioProcessorGraph::producesMidi() const { return true; }\r
void AudioProcessorGraph::getStateInformation (MemoryBlock&) {}\r
void AudioProcessorGraph::setStateInformation (const void*, int) {}\r
\r
-template <typename FloatType, typename SequenceType>\r
-static void processBlockForBuffer (AudioBuffer<FloatType>& buffer, MidiBuffer& midiMessages,\r
- AudioProcessorGraph& graph,\r
- std::unique_ptr<SequenceType>& renderSequence,\r
- std::atomic<bool>& isPrepared)\r
-{\r
- if (graph.isNonRealtime())\r
- {\r
- while (! isPrepared)\r
- Thread::sleep (1);\r
-\r
- const ScopedLock sl (graph.getCallbackLock());\r
-\r
- if (renderSequence != nullptr)\r
- renderSequence->perform (buffer, midiMessages, graph.getPlayHead());\r
- }\r
- else\r
- {\r
- const ScopedLock sl (graph.getCallbackLock());\r
-\r
- if (isPrepared)\r
- {\r
- if (renderSequence != nullptr)\r
- renderSequence->perform (buffer, midiMessages, graph.getPlayHead());\r
- }\r
- else\r
- {\r
- buffer.clear();\r
- midiMessages.clear();\r
- }\r
- }\r
+void AudioProcessorGraph::processBlock (AudioBuffer<float>& audio, MidiBuffer& midi) { return pimpl->processBlock (audio, midi, getPlayHead()); }\r
+void AudioProcessorGraph::processBlock (AudioBuffer<double>& audio, MidiBuffer& midi) { return pimpl->processBlock (audio, midi, getPlayHead()); }\r
+std::vector<AudioProcessorGraph::Connection> AudioProcessorGraph::getConnections() const { return pimpl->getConnections(); }\r
+bool AudioProcessorGraph::addConnection (const Connection& c, UpdateKind updateKind) { return pimpl->addConnection (c, updateKind); }\r
+bool AudioProcessorGraph::removeConnection (const Connection& c, UpdateKind updateKind) { return pimpl->removeConnection (c, updateKind); }\r
+void AudioProcessorGraph::prepareToPlay (double sampleRate, int estimatedSamplesPerBlock) { return pimpl->prepareToPlay (sampleRate, estimatedSamplesPerBlock); }\r
+void AudioProcessorGraph::clear (UpdateKind updateKind) { return pimpl->clear (updateKind); }\r
+const ReferenceCountedArray<AudioProcessorGraph::Node>& AudioProcessorGraph::getNodes() const noexcept { return pimpl->getNodes(); }\r
+AudioProcessorGraph::Node* AudioProcessorGraph::getNodeForId (NodeID x) const { return pimpl->getNodeForId (x).get(); }\r
+bool AudioProcessorGraph::disconnectNode (NodeID nodeID, UpdateKind updateKind) { return pimpl->disconnectNode (nodeID, updateKind); }\r
+void AudioProcessorGraph::releaseResources() { return pimpl->releaseResources(); }\r
+bool AudioProcessorGraph::removeIllegalConnections (UpdateKind updateKind) { return pimpl->removeIllegalConnections (updateKind); }\r
+void AudioProcessorGraph::reset() { return pimpl->reset(); }\r
+bool AudioProcessorGraph::canConnect (const Connection& c) const { return pimpl->canConnect (c); }\r
+bool AudioProcessorGraph::isConnected (const Connection& c) const noexcept { return pimpl->isConnected (c); }\r
+bool AudioProcessorGraph::isConnected (NodeID a, NodeID b) const noexcept { return pimpl->isConnected (a, b); }\r
+bool AudioProcessorGraph::isConnectionLegal (const Connection& c) const { return pimpl->isConnectionLegal (c); }\r
+bool AudioProcessorGraph::isAnInputTo (const Node& source, const Node& destination) const noexcept { return pimpl->isAnInputTo (source, destination); }\r
+bool AudioProcessorGraph::isAnInputTo (NodeID source, NodeID destination) const noexcept { return pimpl->isAnInputTo (source, destination); }\r
+\r
+AudioProcessorGraph::Node::Ptr AudioProcessorGraph::addNode (std::unique_ptr<AudioProcessor> newProcessor,\r
+ NodeID nodeId,\r
+ UpdateKind updateKind)\r
+{\r
+ return pimpl->addNode (std::move (newProcessor), nodeId, updateKind);\r
}\r
\r
-void AudioProcessorGraph::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)\r
+void AudioProcessorGraph::setNonRealtime (bool isProcessingNonRealtime) noexcept\r
{\r
- if ((! isPrepared) && MessageManager::getInstance()->isThisTheMessageThread())\r
- handleAsyncUpdate();\r
+ AudioProcessor::setNonRealtime (isProcessingNonRealtime);\r
+ pimpl->setNonRealtime (isProcessingNonRealtime);\r
+}\r
\r
- processBlockForBuffer<float> (buffer, midiMessages, *this, renderSequenceFloat, isPrepared);\r
+AudioProcessorGraph::Node::Ptr AudioProcessorGraph::removeNode (NodeID nodeID, UpdateKind updateKind)\r
+{\r
+ return pimpl->removeNode (nodeID, updateKind);\r
}\r
\r
-void AudioProcessorGraph::processBlock (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)\r
+AudioProcessorGraph::Node::Ptr AudioProcessorGraph::removeNode (Node* node, UpdateKind updateKind)\r
{\r
- if ((! isPrepared) && MessageManager::getInstance()->isThisTheMessageThread())\r
- handleAsyncUpdate();\r
+ if (node != nullptr)\r
+ return removeNode (node->nodeID, updateKind);\r
\r
- processBlockForBuffer<double> (buffer, midiMessages, *this, renderSequenceDouble, isPrepared);\r
+ jassertfalse;\r
+ return {};\r
}\r
\r
//==============================================================================\r
{\r
}\r
\r
-AudioProcessorGraph::AudioGraphIOProcessor::~AudioGraphIOProcessor()\r
-{\r
-}\r
+AudioProcessorGraph::AudioGraphIOProcessor::~AudioGraphIOProcessor() = default;\r
\r
const String AudioProcessorGraph::AudioGraphIOProcessor::getName() const\r
{\r
return true;\r
}\r
\r
-template <typename FloatType, typename SequenceType>\r
-static void processIOBlock (AudioProcessorGraph::AudioGraphIOProcessor& io, SequenceType& sequence,\r
- AudioBuffer<FloatType>& buffer, MidiBuffer& midiMessages)\r
-{\r
- switch (io.getType())\r
- {\r
- case AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode:\r
- {\r
- auto&& currentAudioOutputBuffer = sequence.currentAudioOutputBuffer;\r
-\r
- for (int i = jmin (currentAudioOutputBuffer.getNumChannels(), buffer.getNumChannels()); --i >= 0;)\r
- currentAudioOutputBuffer.addFrom (i, 0, buffer, i, 0, buffer.getNumSamples());\r
-\r
- break;\r
- }\r
-\r
- case AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode:\r
- {\r
- auto* currentInputBuffer = sequence.currentAudioInputBuffer;\r
-\r
- for (int i = jmin (currentInputBuffer->getNumChannels(), buffer.getNumChannels()); --i >= 0;)\r
- buffer.copyFrom (i, 0, *currentInputBuffer, i, 0, buffer.getNumSamples());\r
-\r
- break;\r
- }\r
-\r
- case AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode:\r
- sequence.currentMidiOutputBuffer.addEvents (midiMessages, 0, buffer.getNumSamples(), 0);\r
- break;\r
-\r
- case AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode:\r
- midiMessages.addEvents (*sequence.currentMidiInputBuffer, 0, buffer.getNumSamples(), 0);\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-}\r
-\r
void AudioProcessorGraph::AudioGraphIOProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)\r
{\r
jassert (graph != nullptr);\r
- processIOBlock (*this, *graph->renderSequenceFloat, buffer, midiMessages);\r
+\r
+ if (auto* state = graph->pimpl->getAudioThreadState())\r
+ state->processIO (*this, buffer, midiMessages);\r
}\r
\r
void AudioProcessorGraph::AudioGraphIOProcessor::processBlock (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)\r
{\r
jassert (graph != nullptr);\r
- processIOBlock (*this, *graph->renderSequenceDouble, buffer, midiMessages);\r
+\r
+ if (auto* state = graph->pimpl->getAudioThreadState())\r
+ state->processIO (*this, buffer, midiMessages);\r
}\r
\r
double AudioProcessorGraph::AudioGraphIOProcessor::getTailLengthSeconds() const\r
}\r
}\r
\r
+//==============================================================================\r
+//==============================================================================\r
+#if JUCE_UNIT_TESTS\r
+\r
+class AudioProcessorGraphTests : public UnitTest\r
+{\r
+public:\r
+ AudioProcessorGraphTests()\r
+ : UnitTest ("AudioProcessorGraph", UnitTestCategories::audioProcessors) {}\r
+\r
+ void runTest() override\r
+ {\r
+ const auto midiChannel = AudioProcessorGraph::midiChannelIndex;\r
+\r
+ beginTest ("isConnected returns true when two nodes are connected");\r
+ {\r
+ AudioProcessorGraph graph;\r
+ const auto nodeA = graph.addNode (BasicProcessor::make ({}, MidiIn::no, MidiOut::yes))->nodeID;\r
+ const auto nodeB = graph.addNode (BasicProcessor::make ({}, MidiIn::yes, MidiOut::no))->nodeID;\r
+\r
+ expect (graph.canConnect ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+ expect (! graph.canConnect ({ { nodeB, midiChannel }, { nodeA, midiChannel } }));\r
+ expect (! graph.canConnect ({ { nodeA, midiChannel }, { nodeA, midiChannel } }));\r
+ expect (! graph.canConnect ({ { nodeB, midiChannel }, { nodeB, midiChannel } }));\r
+\r
+ expect (graph.getConnections().empty());\r
+ expect (! graph.isConnected ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+ expect (! graph.isConnected (nodeA, nodeB));\r
+\r
+ expect (graph.addConnection ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+\r
+ expect (graph.getConnections().size() == 1);\r
+ expect (graph.isConnected ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+ expect (graph.isConnected (nodeA, nodeB));\r
+\r
+ expect (graph.disconnectNode (nodeA));\r
+\r
+ expect (graph.getConnections().empty());\r
+ expect (! graph.isConnected ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+ expect (! graph.isConnected (nodeA, nodeB));\r
+ }\r
+\r
+ beginTest ("graph lookups work with a large number of connections");\r
+ {\r
+ AudioProcessorGraph graph;\r
+\r
+ std::vector<AudioProcessorGraph::NodeID> nodeIDs;\r
+\r
+ constexpr auto numNodes = 100;\r
+\r
+ for (auto i = 0; i < numNodes; ++i)\r
+ {\r
+ nodeIDs.push_back (graph.addNode (BasicProcessor::make (BasicProcessor::getStereoProperties(),\r
+ MidiIn::yes,\r
+ MidiOut::yes))->nodeID);\r
+ }\r
+\r
+ for (auto it = nodeIDs.begin(); it != std::prev (nodeIDs.end()); ++it)\r
+ {\r
+ expect (graph.addConnection ({ { it[0], 0 }, { it[1], 0 } }));\r
+ expect (graph.addConnection ({ { it[0], 1 }, { it[1], 1 } }));\r
+ }\r
+\r
+ // Check whether isConnected reports correct results when called\r
+ // with both connections and nodes\r
+ for (auto it = nodeIDs.begin(); it != std::prev (nodeIDs.end()); ++it)\r
+ {\r
+ expect (graph.isConnected ({ { it[0], 0 }, { it[1], 0 } }));\r
+ expect (graph.isConnected ({ { it[0], 1 }, { it[1], 1 } }));\r
+ expect (graph.isConnected (it[0], it[1]));\r
+ }\r
+\r
+ const auto& nodes = graph.getNodes();\r
+\r
+ expect (! graph.isAnInputTo (*nodes[0], *nodes[0]));\r
+\r
+ // Check whether isAnInputTo behaves correctly for a non-cyclic graph\r
+ for (auto it = std::next (nodes.begin()); it != std::prev (nodes.end()); ++it)\r
+ {\r
+ expect (! graph.isAnInputTo (**it, **it));\r
+\r
+ expect (graph.isAnInputTo (*nodes[0], **it));\r
+ expect (! graph.isAnInputTo (**it, *nodes[0]));\r
+\r
+ expect (graph.isAnInputTo (**it, *nodes[nodes.size() - 1]));\r
+ expect (! graph.isAnInputTo (*nodes[nodes.size() - 1], **it));\r
+ }\r
+\r
+ // Make the graph cyclic\r
+ graph.addConnection ({ { nodeIDs.back(), 0 }, { nodeIDs.front(), 0 } });\r
+ graph.addConnection ({ { nodeIDs.back(), 1 }, { nodeIDs.front(), 1 } });\r
+\r
+ // Check whether isAnInputTo behaves correctly for a cyclic graph\r
+ for (const auto* node : graph.getNodes())\r
+ {\r
+ expect (graph.isAnInputTo (*node, *node));\r
+\r
+ expect (graph.isAnInputTo (*nodes[0], *node));\r
+ expect (graph.isAnInputTo (*node, *nodes[0]));\r
+\r
+ expect (graph.isAnInputTo (*node, *nodes[nodes.size() - 1]));\r
+ expect (graph.isAnInputTo (*nodes[nodes.size() - 1], *node));\r
+ }\r
+ }\r
+ }\r
+\r
+private:\r
+ enum class MidiIn { no, yes };\r
+ enum class MidiOut { no, yes };\r
+\r
+ class BasicProcessor : public AudioProcessor\r
+ {\r
+ public:\r
+ explicit BasicProcessor (const AudioProcessor::BusesProperties& layout, MidiIn mIn, MidiOut mOut)\r
+ : AudioProcessor (layout), midiIn (mIn), midiOut (mOut) {}\r
+\r
+ const String getName() const override { return "Basic Processor"; }\r
+ double getTailLengthSeconds() const override { return {}; }\r
+ bool acceptsMidi() const override { return midiIn == MidiIn ::yes; }\r
+ bool producesMidi() const override { return midiOut == MidiOut::yes; }\r
+ AudioProcessorEditor* createEditor() override { return {}; }\r
+ bool hasEditor() const override { return {}; }\r
+ int getNumPrograms() override { return 1; }\r
+ int getCurrentProgram() override { return {}; }\r
+ void setCurrentProgram (int) override {}\r
+ const String getProgramName (int) override { return {}; }\r
+ void changeProgramName (int, const String&) override {}\r
+ void getStateInformation (juce::MemoryBlock&) override {}\r
+ void setStateInformation (const void*, int) override {}\r
+ void prepareToPlay (double, int) override {}\r
+ void releaseResources() override {}\r
+ void processBlock (AudioBuffer<float>&, MidiBuffer&) override {}\r
+ bool supportsDoublePrecisionProcessing() const override { return true; }\r
+ bool isMidiEffect() const override { return {}; }\r
+ void reset() override {}\r
+ void setNonRealtime (bool) noexcept override {}\r
+\r
+ using AudioProcessor::processBlock;\r
+\r
+ static std::unique_ptr<AudioProcessor> make (const BusesProperties& layout,\r
+ MidiIn midiIn,\r
+ MidiOut midiOut)\r
+ {\r
+ return std::make_unique<BasicProcessor> (layout, midiIn, midiOut);\r
+ }\r
+\r
+ static BusesProperties getStereoProperties()\r
+ {\r
+ return BusesProperties().withInput ("in", AudioChannelSet::stereo())\r
+ .withOutput ("out", AudioChannelSet::stereo());\r
+ }\r
+\r
+ private:\r
+ MidiIn midiIn;\r
+ MidiOut midiOut;\r
+ };\r
+};\r
+\r
+static AudioProcessorGraphTests audioProcessorGraphTests;\r
+\r
+#endif\r
+\r
} // namespace juce\r
@tags{Audio}\r
*/\r
class JUCE_API AudioProcessorGraph : public AudioProcessor,\r
- public ChangeBroadcaster,\r
- private AsyncUpdater\r
+ public ChangeBroadcaster\r
{\r
public:\r
//==============================================================================\r
/**\r
Represents an input or output channel of a node in an AudioProcessorGraph.\r
*/\r
- struct NodeAndChannel\r
+ class NodeAndChannel\r
{\r
+ auto tie() const { return std::tie (nodeID, channelIndex); }\r
+\r
+ public:\r
NodeID nodeID;\r
int channelIndex;\r
\r
bool isMIDI() const noexcept { return channelIndex == midiChannelIndex; }\r
\r
- bool operator== (const NodeAndChannel& other) const noexcept { return nodeID == other.nodeID && channelIndex == other.channelIndex; }\r
- bool operator!= (const NodeAndChannel& other) const noexcept { return ! operator== (other); }\r
+ bool operator== (const NodeAndChannel& other) const noexcept { return tie() == other.tie(); }\r
+ bool operator!= (const NodeAndChannel& other) const noexcept { return tie() != other.tie(); }\r
+ bool operator< (const NodeAndChannel& other) const noexcept { return tie() < other.tie(); }\r
};\r
\r
//==============================================================================\r
\r
//==============================================================================\r
/** Returns if the node is bypassed or not. */\r
- bool isBypassed() const noexcept;\r
+ bool isBypassed() const noexcept\r
+ {\r
+ if (processor != nullptr)\r
+ {\r
+ if (auto* bypassParam = processor->getBypassParameter())\r
+ return (bypassParam->getValue() != 0.0f);\r
+ }\r
+\r
+ return bypassed;\r
+ }\r
\r
/** Tell this node to bypass processing. */\r
- void setBypassed (bool shouldBeBypassed) noexcept;\r
+ void setBypassed (bool shouldBeBypassed) noexcept\r
+ {\r
+ if (processor != nullptr)\r
+ {\r
+ if (auto* bypassParam = processor->getBypassParameter())\r
+ bypassParam->setValueNotifyingHost (shouldBeBypassed ? 1.0f : 0.0f);\r
+ }\r
+\r
+ bypassed = shouldBeBypassed;\r
+ }\r
\r
//==============================================================================\r
/** A convenient typedef for referring to a pointer to a node object. */\r
using Ptr = ReferenceCountedObjectPtr<Node>;\r
\r
- private:\r
- //==============================================================================\r
- friend class AudioProcessorGraph;\r
- template <typename Float>\r
- friend struct GraphRenderSequence;\r
- template <typename Float>\r
- friend struct RenderSequenceBuilder;\r
-\r
- struct Connection\r
- {\r
- Node* otherNode;\r
- int otherChannel, thisChannel;\r
+ /** @internal\r
\r
- bool operator== (const Connection&) const noexcept;\r
- };\r
-\r
- std::unique_ptr<AudioProcessor> processor;\r
- Array<Connection> inputs, outputs;\r
- bool isPrepared = false;\r
- std::atomic<bool> bypassed { false };\r
-\r
- Node (NodeID, std::unique_ptr<AudioProcessor>) noexcept;\r
-\r
- void setParentGraph (AudioProcessorGraph*) const;\r
- void prepare (double newSampleRate, int newBlockSize, AudioProcessorGraph*, ProcessingPrecision);\r
- void unprepare();\r
-\r
- template <typename Sample>\r
- void callProcessFunction (AudioBuffer<Sample>& audio,\r
- MidiBuffer& midi,\r
- void (AudioProcessor::* function) (AudioBuffer<Sample>&, MidiBuffer&))\r
- {\r
- const ScopedLock lock (processorLock);\r
- (processor.get()->*function) (audio, midi);\r
- }\r
+ Returns true if setBypassed(true) was called on this node.\r
+ This behaviour is different from isBypassed(), which may additionally return true if\r
+ the node has a bypass parameter that is not set to 0.\r
+ */\r
+ bool userRequestedBypass() const { return bypassed; }\r
\r
- template <typename Sample>\r
- void processBlock (AudioBuffer<Sample>& audio, MidiBuffer& midi)\r
- {\r
- callProcessFunction (audio, midi, &AudioProcessor::processBlock);\r
- }\r
+ /** @internal\r
\r
- template <typename Sample>\r
- void processBlockBypassed (AudioBuffer<Sample>& audio, MidiBuffer& midi)\r
+ To create a new node, use AudioProcessorGraph::addNode.\r
+ */\r
+ Node (NodeID n, std::unique_ptr<AudioProcessor> p) noexcept\r
+ : nodeID (n), processor (std::move (p))\r
{\r
- callProcessFunction (audio, midi, &AudioProcessor::processBlockBypassed);\r
+ jassert (processor != nullptr);\r
}\r
\r
- CriticalSection processorLock;\r
+ private:\r
+ //==============================================================================\r
+ std::unique_ptr<AudioProcessor> processor;\r
+ std::atomic<bool> bypassed { false };\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Node)\r
};\r
NodeAndChannel destination { {}, 0 };\r
};\r
\r
+ //==============================================================================\r
+ /** Indicates how the graph should be updated after a change.\r
+\r
+ If you need to make lots of changes to a graph (e.g. lots of separate calls\r
+ to addNode, addConnection etc.) you can avoid rebuilding the graph on each\r
+ change by using the async update kind.\r
+ */\r
+ enum class UpdateKind\r
+ {\r
+ sync, ///< Indicates that the graph should be rebuilt immediately after modification.\r
+ async ///< Indicates that the graph rebuild should be deferred.\r
+ };\r
+\r
//==============================================================================\r
/** Deletes all nodes and connections from this graph.\r
Any processor objects in the graph will be deleted.\r
*/\r
- void clear();\r
+ void clear (UpdateKind = UpdateKind::sync);\r
\r
/** Returns the array of nodes in the graph. */\r
- const ReferenceCountedArray<Node>& getNodes() const noexcept { return nodes; }\r
+ const ReferenceCountedArray<Node>& getNodes() const noexcept;\r
\r
/** Returns the number of nodes in the graph. */\r
- int getNumNodes() const noexcept { return nodes.size(); }\r
+ int getNumNodes() const noexcept { return getNodes().size(); }\r
\r
/** Returns a pointer to one of the nodes in the graph.\r
This will return nullptr if the index is out of range.\r
@see getNodeForId\r
*/\r
- Node::Ptr getNode (int index) const noexcept { return nodes[index]; }\r
+ Node::Ptr getNode (int index) const noexcept { return getNodes()[index]; }\r
\r
/** Searches the graph for a node with the given ID number and returns it.\r
If no such node was found, this returns nullptr.\r
\r
If this succeeds, it returns a pointer to the newly-created node.\r
*/\r
- Node::Ptr addNode (std::unique_ptr<AudioProcessor> newProcessor, NodeID nodeId = {});\r
+ Node::Ptr addNode (std::unique_ptr<AudioProcessor> newProcessor, NodeID nodeId = {}, UpdateKind = UpdateKind::sync);\r
\r
/** Deletes a node within the graph which has the specified ID.\r
This will also delete any connections that are attached to this node.\r
*/\r
- Node::Ptr removeNode (NodeID);\r
+ Node::Ptr removeNode (NodeID, UpdateKind = UpdateKind::sync);\r
\r
/** Deletes a node within the graph.\r
This will also delete any connections that are attached to this node.\r
*/\r
- Node::Ptr removeNode (Node*);\r
+ Node::Ptr removeNode (Node*, UpdateKind = UpdateKind::sync);\r
\r
/** Returns the list of connections in the graph. */\r
std::vector<Connection> getConnections() const;\r
/** Does a recursive check to see if there's a direct or indirect series of connections\r
between these two nodes.\r
*/\r
- bool isAnInputTo (Node& source, Node& destination) const noexcept;\r
+ bool isAnInputTo (const Node& source, const Node& destination) const noexcept;\r
+\r
+ /** Does a recursive check to see if there's a direct or indirect series of connections\r
+ between these two nodes.\r
+ */\r
+ bool isAnInputTo (NodeID source, NodeID destination) const noexcept;\r
\r
/** Returns true if it would be legal to connect the specified points. */\r
bool canConnect (const Connection&) const;\r
If this isn't allowed (e.g. because you're trying to connect a midi channel\r
to an audio one or other such nonsense), then it'll return false.\r
*/\r
- bool addConnection (const Connection&);\r
+ bool addConnection (const Connection&, UpdateKind = UpdateKind::sync);\r
\r
/** Deletes the given connection. */\r
- bool removeConnection (const Connection&);\r
+ bool removeConnection (const Connection&, UpdateKind = UpdateKind::sync);\r
\r
/** Removes all connections from the specified node. */\r
- bool disconnectNode (NodeID);\r
+ bool disconnectNode (NodeID, UpdateKind = UpdateKind::sync);\r
\r
/** Returns true if the given connection's channel numbers map on to valid\r
channels at each end.\r
This might be useful if some of the processors are doing things like changing\r
their channel counts, which could render some connections obsolete.\r
*/\r
- bool removeIllegalConnections();\r
+ bool removeIllegalConnections (UpdateKind = UpdateKind::sync);\r
\r
//==============================================================================\r
/** A special type of AudioProcessor that can live inside an AudioProcessorGraph\r
void setStateInformation (const void* data, int sizeInBytes) override;\r
\r
private:\r
- struct PrepareSettings\r
- {\r
- ProcessingPrecision precision = ProcessingPrecision::singlePrecision;\r
- double sampleRate = 0.0;\r
- int blockSize = 0;\r
- bool valid = false;\r
-\r
- using Tied = std::tuple<const ProcessingPrecision&,\r
- const double&,\r
- const int&,\r
- const bool&>;\r
-\r
- Tied tie() const noexcept { return std::tie (precision, sampleRate, blockSize, valid); }\r
-\r
- bool operator== (const PrepareSettings& other) const noexcept { return tie() == other.tie(); }\r
- bool operator!= (const PrepareSettings& other) const noexcept { return tie() != other.tie(); }\r
- };\r
-\r
- //==============================================================================\r
- ReferenceCountedArray<Node> nodes;\r
- NodeID lastNodeID = {};\r
-\r
- struct RenderSequenceFloat;\r
- struct RenderSequenceDouble;\r
- std::unique_ptr<RenderSequenceFloat> renderSequenceFloat;\r
- std::unique_ptr<RenderSequenceDouble> renderSequenceDouble;\r
-\r
- PrepareSettings prepareSettings;\r
-\r
- friend class AudioGraphIOProcessor;\r
-\r
- std::atomic<bool> isPrepared { false };\r
-\r
- void topologyChanged();\r
- void unprepare();\r
- void handleAsyncUpdate() override;\r
- void clearRenderingSequence();\r
- void buildRenderingSequence();\r
- bool anyNodesNeedPreparing() const noexcept;\r
- bool isConnected (Node* src, int sourceChannel, Node* dest, int destChannel) const noexcept;\r
- bool isAnInputTo (Node& src, Node& dst, int recursionCheck) const noexcept;\r
- bool canConnect (Node* src, int sourceChannel, Node* dest, int destChannel) const noexcept;\r
- bool isLegal (Node* src, int sourceChannel, Node* dest, int destChannel) const noexcept;\r
- static void getNodeConnections (Node&, std::vector<Connection>&);\r
+ class Pimpl;\r
+ std::unique_ptr<Pimpl> pimpl;\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorGraph)\r
};\r
\r
@see latencyChanged\r
*/\r
- JUCE_NODISCARD ChangeDetails withLatencyChanged (bool b) const noexcept { return with (&ChangeDetails::latencyChanged, b); }\r
+ [[nodiscard]] ChangeDetails withLatencyChanged (bool b) const noexcept { return with (&ChangeDetails::latencyChanged, b); }\r
\r
/** Indicates that some attributes of the AudioProcessor's parameters have changed.\r
\r
\r
@see parameterInfoChanged\r
*/\r
- JUCE_NODISCARD ChangeDetails withParameterInfoChanged (bool b) const noexcept { return with (&ChangeDetails::parameterInfoChanged, b); }\r
+ [[nodiscard]] ChangeDetails withParameterInfoChanged (bool b) const noexcept { return with (&ChangeDetails::parameterInfoChanged, b); }\r
\r
/** Indicates that the loaded program has changed.\r
\r
\r
@see programChanged\r
*/\r
- JUCE_NODISCARD ChangeDetails withProgramChanged (bool b) const noexcept { return with (&ChangeDetails::programChanged, b); }\r
+ [[nodiscard]] ChangeDetails withProgramChanged (bool b) const noexcept { return with (&ChangeDetails::programChanged, b); }\r
\r
/** Indicates that the plugin state has changed (but not its parameters!).\r
\r
\r
@see nonParameterStateChanged\r
*/\r
- JUCE_NODISCARD ChangeDetails withNonParameterStateChanged (bool b) const noexcept { return with (&ChangeDetails::nonParameterStateChanged, b); }\r
+ [[nodiscard]] ChangeDetails withNonParameterStateChanged (bool b) const noexcept { return with (&ChangeDetails::nonParameterStateChanged, b); }\r
\r
/** Returns the default set of flags that will be used when\r
AudioProcessor::updateHostDisplay() is called with no arguments.\r
template <typename SpecialisationType>\r
static const ARA::ARAFactory* createARAFactory()\r
{\r
- static_assert (std::is_base_of<ARADocumentControllerSpecialisation, SpecialisationType>::value,\r
+ static_assert (std::is_base_of_v<ARADocumentControllerSpecialisation, SpecialisationType>,\r
"DocumentController specialization types must inherit from ARADocumentControllerSpecialisation");\r
return ARA::PlugIn::PlugInEntry::getPlugInEntry<FactoryConfig<SpecialisationType>>()->getFactory();\r
}\r
};\r
\r
//==============================================================================\r
-/** Base class for a renderer fulfilling the ARAEditorView role as described in the ARA SDK.\r
+/** Base class for fulfilling the ARAEditorView role as described in the ARA SDK.\r
\r
Instances of this class are constructed by the DocumentController. If you are subclassing\r
ARAEditorView, make sure to call the base class implementation of overridden functions.\r
/** Called when the editor view's selection changes.\r
@param viewSelection The current selection state\r
*/\r
- virtual void onNewSelection (const ARA::PlugIn::ViewSelection& viewSelection)\r
+ virtual void onNewSelection (const ARAViewSelection& viewSelection)\r
{\r
ignoreUnused (viewSelection);\r
}\r
using Category = AudioProcessorParameter::Category;\r
\r
/** An optional label for the parameter's value */\r
- JUCE_NODISCARD auto withLabel (String x) const { return withMember (*this, &This::label, std::move (x)); }\r
+ [[nodiscard]] auto withLabel (String x) const { return withMember (*this, &This::label, std::move (x)); }\r
\r
/** The semantics of this parameter */\r
- JUCE_NODISCARD auto withCategory (Category x) const { return withMember (*this, &This::category, std::move (x)); }\r
+ [[nodiscard]] auto withCategory (Category x) const { return withMember (*this, &This::category, std::move (x)); }\r
\r
/** @see AudioProcessorParameter::isMetaParameter() */\r
- JUCE_NODISCARD auto withMeta (bool x) const { return withMember (*this, &This::meta, std::move (x)); }\r
+ [[nodiscard]] auto withMeta (bool x) const { return withMember (*this, &This::meta, std::move (x)); }\r
\r
/** @see AudioProcessorParameter::isAutomatable() */\r
- JUCE_NODISCARD auto withAutomatable (bool x) const { return withMember (*this, &This::automatable, std::move (x)); }\r
+ [[nodiscard]] auto withAutomatable (bool x) const { return withMember (*this, &This::automatable, std::move (x)); }\r
\r
/** @see AudioProcessorParameter::isOrientationInverted() */\r
- JUCE_NODISCARD auto withInverted (bool x) const { return withMember (*this, &This::inverted, std::move (x)); }\r
+ [[nodiscard]] auto withInverted (bool x) const { return withMember (*this, &This::inverted, std::move (x)); }\r
\r
/** An optional label for the parameter's value */\r
- JUCE_NODISCARD auto getLabel() const { return label; }\r
+ [[nodiscard]] auto getLabel() const { return label; }\r
\r
/** The semantics of this parameter */\r
- JUCE_NODISCARD auto getCategory() const { return category; }\r
+ [[nodiscard]] auto getCategory() const { return category; }\r
\r
/** @see AudioProcessorParameter::isMetaParameter() */\r
- JUCE_NODISCARD auto getMeta() const { return meta; }\r
+ [[nodiscard]] auto getMeta() const { return meta; }\r
\r
/** @see AudioProcessorParameter::isAutomatable() */\r
- JUCE_NODISCARD auto getAutomatable() const { return automatable; }\r
+ [[nodiscard]] auto getAutomatable() const { return automatable; }\r
\r
/** @see AudioProcessorParameter::isOrientationInverted() */\r
- JUCE_NODISCARD auto getInverted() const { return inverted; }\r
+ [[nodiscard]] auto getInverted() const { return inverted; }\r
\r
private:\r
String label;\r
}\r
}\r
\r
- state->processor.addParameterGroup (move (group));\r
+ state->processor.addParameterGroup (std::move (group));\r
}\r
\r
AudioProcessorValueTreeState* state;\r
\r
public:\r
/** @see RangedAudioParameterAttributes::withStringFromValueFunction() */\r
- JUCE_NODISCARD auto withStringFromValueFunction (StringFromValue x) const { return withMember (*this, &This::attributes, attributes.withStringFromValueFunction (std::move (x))); }\r
+ [[nodiscard]] auto withStringFromValueFunction (StringFromValue x) const { return withMember (*this, &This::attributes, attributes.withStringFromValueFunction (std::move (x))); }\r
/** @see RangedAudioParameterAttributes::withValueFromStringFunction() */\r
- JUCE_NODISCARD auto withValueFromStringFunction (ValueFromString x) const { return withMember (*this, &This::attributes, attributes.withValueFromStringFunction (std::move (x))); }\r
+ [[nodiscard]] auto withValueFromStringFunction (ValueFromString x) const { return withMember (*this, &This::attributes, attributes.withValueFromStringFunction (std::move (x))); }\r
/** @see RangedAudioParameterAttributes::withLabel() */\r
- JUCE_NODISCARD auto withLabel (String x) const { return withMember (*this, &This::attributes, attributes.withLabel (std::move (x))); }\r
+ [[nodiscard]] auto withLabel (String x) const { return withMember (*this, &This::attributes, attributes.withLabel (std::move (x))); }\r
/** @see RangedAudioParameterAttributes::withCategory() */\r
- JUCE_NODISCARD auto withCategory (Category x) const { return withMember (*this, &This::attributes, attributes.withCategory (std::move (x))); }\r
+ [[nodiscard]] auto withCategory (Category x) const { return withMember (*this, &This::attributes, attributes.withCategory (std::move (x))); }\r
/** @see RangedAudioParameterAttributes::withMeta() */\r
- JUCE_NODISCARD auto withMeta (bool x) const { return withMember (*this, &This::attributes, attributes.withMeta (std::move (x))); }\r
+ [[nodiscard]] auto withMeta (bool x) const { return withMember (*this, &This::attributes, attributes.withMeta (std::move (x))); }\r
/** @see RangedAudioParameterAttributes::withAutomatable() */\r
- JUCE_NODISCARD auto withAutomatable (bool x) const { return withMember (*this, &This::attributes, attributes.withAutomatable (std::move (x))); }\r
+ [[nodiscard]] auto withAutomatable (bool x) const { return withMember (*this, &This::attributes, attributes.withAutomatable (std::move (x))); }\r
/** @see RangedAudioParameterAttributes::withInverted() */\r
- JUCE_NODISCARD auto withInverted (bool x) const { return withMember (*this, &This::attributes, attributes.withInverted (std::move (x))); }\r
+ [[nodiscard]] auto withInverted (bool x) const { return withMember (*this, &This::attributes, attributes.withInverted (std::move (x))); }\r
\r
/** Pass 'true' if this parameter has discrete steps, or 'false' if the parameter is continuous.\r
\r
Using an AudioParameterChoice or AudioParameterInt might be a better choice than setting this flag.\r
*/\r
- JUCE_NODISCARD auto withDiscrete (bool x) const { return withMember (*this, &This::discrete, std::move (x)); }\r
+ [[nodiscard]] auto withDiscrete (bool x) const { return withMember (*this, &This::discrete, std::move (x)); }\r
\r
/** Pass 'true' if this parameter only has two valid states.\r
\r
Using an AudioParameterBool might be a better choice than setting this flag.\r
*/\r
- JUCE_NODISCARD auto withBoolean (bool x) const { return withMember (*this, &This::boolean, std::move (x)); }\r
+ [[nodiscard]] auto withBoolean (bool x) const { return withMember (*this, &This::boolean, std::move (x)); }\r
\r
/** @returns all attributes that might also apply to an AudioParameterFloat */\r
- JUCE_NODISCARD const auto& getAudioParameterFloatAttributes() const { return attributes; }\r
+ [[nodiscard]] const auto& getAudioParameterFloatAttributes() const { return attributes; }\r
/** @returns 'true' if this parameter has discrete steps, or 'false' if the parameter is continuous. */\r
- JUCE_NODISCARD const auto& getDiscrete() const { return discrete; }\r
+ [[nodiscard]] const auto& getDiscrete() const { return discrete; }\r
/** @returns 'true' if this parameter only has two valid states. */\r
- JUCE_NODISCARD const auto& getBoolean() const { return boolean; }\r
+ [[nodiscard]] const auto& getBoolean() const { return boolean; }\r
\r
private:\r
AudioParameterFloatAttributes attributes;\r
valueRange,\r
defaultParameterValue,\r
AudioProcessorValueTreeStateParameterAttributes().withLabel (labelText)\r
- .withStringFromValueFunction ([valueToTextFunction] (float v, int) { return valueToTextFunction (v); })\r
+ .withStringFromValueFunction (adaptSignature (std::move (valueToTextFunction)))\r
.withValueFromStringFunction (std::move (textToValueFunction))\r
.withMeta (isMetaParameter)\r
.withAutomatable (isAutomatableParameter)\r
bool isBoolean() const override;\r
\r
private:\r
+ static std::function<String (float, int)> adaptSignature (std::function<String (float)> func)\r
+ {\r
+ if (func == nullptr)\r
+ return nullptr;\r
+\r
+ return [func = std::move (func)] (float v, int) { return func (v); };\r
+ }\r
+\r
void valueChanged (float) override;\r
\r
std::function<void()> onValueChanged;\r
using ValueFromString = std::function<Value (const String&)>;\r
\r
/** An optional lambda function that converts a non-normalised value to a string with a maximum length. This may be used by hosts to display the parameter's value. */\r
- JUCE_NODISCARD auto withStringFromValueFunction (StringFromValue x) const { return withMember (asDerived(), &Derived::stringFromValue, std::move (x)); }\r
+ [[nodiscard]] auto withStringFromValueFunction (StringFromValue x) const { return withMember (asDerived(), &Derived::stringFromValue, std::move (x)); }\r
\r
/** An optional lambda function that parses a string and converts it into a non-normalised value. Some hosts use this to allow users to type in parameter values. */\r
- JUCE_NODISCARD auto withValueFromStringFunction (ValueFromString x) const { return withMember (asDerived(), &Derived::valueFromString, std::move (x)); }\r
+ [[nodiscard]] auto withValueFromStringFunction (ValueFromString x) const { return withMember (asDerived(), &Derived::valueFromString, std::move (x)); }\r
\r
/** See AudioProcessorParameterWithIDAttributes::withLabel() */\r
- JUCE_NODISCARD auto withLabel (String x) const { return withMember (asDerived(), &Derived::attributes, attributes.withLabel (std::move (x))); }\r
+ [[nodiscard]] auto withLabel (String x) const { return withMember (asDerived(), &Derived::attributes, attributes.withLabel (std::move (x))); }\r
\r
/** See AudioProcessorParameterWithIDAttributes::withCategory() */\r
- JUCE_NODISCARD auto withCategory (Category x) const { return withMember (asDerived(), &Derived::attributes, attributes.withCategory (std::move (x))); }\r
+ [[nodiscard]] auto withCategory (Category x) const { return withMember (asDerived(), &Derived::attributes, attributes.withCategory (std::move (x))); }\r
\r
/** See AudioProcessorParameter::isMetaParameter() */\r
- JUCE_NODISCARD auto withMeta (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withMeta (std::move (x))); }\r
+ [[nodiscard]] auto withMeta (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withMeta (std::move (x))); }\r
\r
/** See AudioProcessorParameter::isAutomatable() */\r
- JUCE_NODISCARD auto withAutomatable (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withAutomatable (std::move (x))); }\r
+ [[nodiscard]] auto withAutomatable (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withAutomatable (std::move (x))); }\r
\r
/** See AudioProcessorParameter::isOrientationInverted() */\r
- JUCE_NODISCARD auto withInverted (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withInverted (std::move (x))); }\r
+ [[nodiscard]] auto withInverted (bool x) const { return withMember (asDerived(), &Derived::attributes, attributes.withInverted (std::move (x))); }\r
\r
/** An optional lambda function that converts a non-normalised value to a string with a maximum length. This may be used by hosts to display the parameter's value. */\r
- JUCE_NODISCARD const auto& getStringFromValueFunction() const { return stringFromValue; }\r
+ [[nodiscard]] const auto& getStringFromValueFunction() const { return stringFromValue; }\r
\r
/** An optional lambda function that parses a string and converts it into a non-normalised value. Some hosts use this to allow users to type in parameter values. */\r
- JUCE_NODISCARD const auto& getValueFromStringFunction() const { return valueFromString; }\r
+ [[nodiscard]] const auto& getValueFromStringFunction() const { return valueFromString; }\r
\r
/** Gets attributes that would also apply to an AudioProcessorParameterWithID */\r
- JUCE_NODISCARD const auto& getAudioProcessorParameterWithIDAttributes() const { return attributes; }\r
+ [[nodiscard]] const auto& getAudioProcessorParameterWithIDAttributes() const { return attributes; }\r
\r
private:\r
auto& asDerived() const { return *static_cast<const Derived*> (this); }\r
~AudioCDReader() override;\r
\r
/** Implementation of the AudioFormatReader method. */\r
- bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+ bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples) override;\r
\r
/** Checks whether the CD has been removed from the drive. */\r
int8 values[2];\r
};\r
\r
+\r
+//==============================================================================\r
+template <typename T>\r
+class AudioBufferReader : public AudioFormatReader\r
+{\r
+public:\r
+ AudioBufferReader (const AudioBuffer<T>* bufferIn, double rate)\r
+ : AudioFormatReader (nullptr, "AudioBuffer"), buffer (bufferIn)\r
+ {\r
+ sampleRate = rate;\r
+ bitsPerSample = 32;\r
+ lengthInSamples = buffer->getNumSamples();\r
+ numChannels = (unsigned int) buffer->getNumChannels();\r
+ usesFloatingPointData = std::is_floating_point_v<T>;\r
+ }\r
+\r
+ bool readSamples (int* const* destChannels,\r
+ int numDestChannels,\r
+ int startOffsetInDestBuffer,\r
+ int64 startSampleInFile,\r
+ int numSamples) override\r
+ {\r
+ clearSamplesBeyondAvailableLength (destChannels, numDestChannels, startOffsetInDestBuffer,\r
+ startSampleInFile, numSamples, lengthInSamples);\r
+\r
+ const auto numAvailableSamples = (int) ((int64) buffer->getNumSamples() - startSampleInFile);\r
+ const auto numSamplesToCopy = std::clamp (numAvailableSamples, 0, numSamples);\r
+\r
+ if (numSamplesToCopy == 0)\r
+ return true;\r
+\r
+ for (int i = 0; i < numDestChannels; ++i)\r
+ {\r
+ if (void* targetChannel = destChannels[i])\r
+ {\r
+ const auto dest = DestType (targetChannel) + startOffsetInDestBuffer;\r
+\r
+ if (i < buffer->getNumChannels())\r
+ dest.convertSamples (SourceType (buffer->getReadPointer (i) + startSampleInFile), numSamplesToCopy);\r
+ else\r
+ dest.clearSamples (numSamples);\r
+ }\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+private:\r
+ using SourceNumericalType =\r
+ std::conditional_t<std::is_same_v<T, int>, AudioData::Int32,\r
+ std::conditional_t<std::is_same_v<T, float>, AudioData::Float32, void>>;\r
+\r
+ using DestinationNumericalType = std::conditional_t<std::is_floating_point_v<T>, AudioData::Float32, AudioData::Int32>;\r
+\r
+ using DestType = AudioData::Pointer<DestinationNumericalType, AudioData::LittleEndian, AudioData::NonInterleaved, AudioData::NonConst>;\r
+ using SourceType = AudioData::Pointer<SourceNumericalType, AudioData::LittleEndian, AudioData::NonInterleaved, AudioData::Const>;\r
+\r
+ const AudioBuffer<T>* buffer;\r
+};\r
+\r
//==============================================================================\r
class AudioThumbnail::LevelDataSource : public TimeSliceClient\r
{\r
setDataSource (new LevelDataSource (*this, newReader, hash));\r
}\r
\r
+void AudioThumbnail::setSource (const AudioBuffer<float>* newSource, double rate, int64 hash)\r
+{\r
+ setReader (new AudioBufferReader<float> (newSource, rate), hash);\r
+}\r
+\r
+void AudioThumbnail::setSource (const AudioBuffer<int>* newSource, double rate, int64 hash)\r
+{\r
+ setReader (new AudioBufferReader<int> (newSource, rate), hash);\r
+}\r
+\r
int64 AudioThumbnail::getHashCode() const\r
{\r
return source == nullptr ? 0 : source->hashCode;\r
*/\r
void setReader (AudioFormatReader* newReader, int64 hashCode) override;\r
\r
+ /** Sets an AudioBuffer as the source for the thumbnail.\r
+\r
+ The buffer contents aren't copied and you must ensure that the lifetime of the buffer is\r
+ valid for as long as the AudioThumbnail uses it as its source. Calling this function will\r
+ start reading the audio in a background thread (unless the hash code can be looked-up\r
+ successfully in the thumbnail cache).\r
+ */\r
+ void setSource (const AudioBuffer<float>* newSource, double sampleRate, int64 hashCode);\r
+\r
+ /** Same as the other setSource() overload except for int data. */\r
+ void setSource (const AudioBuffer<int>* newSource, double sampleRate, int64 hashCode);\r
+\r
/** Resets the thumbnail, ready for adding data with the specified format.\r
If you're going to generate a thumbnail yourself, call this before using addBlock()\r
to add the data.\r
maxNumThumbsToStore (maxNumThumbs)\r
{\r
jassert (maxNumThumbsToStore > 0);\r
- thread.startThread (2);\r
+ thread.startThread (Thread::Priority::low);\r
}\r
\r
AudioThumbnailCache::~AudioThumbnailCache()\r
c->clear();\r
}\r
\r
-void AudioVisualiserComponent::pushBuffer (const float** d, int numChannels, int num)\r
+void AudioVisualiserComponent::pushBuffer (const float* const* d, int numChannels, int num)\r
{\r
numChannels = jmin (numChannels, channels.size());\r
\r
The number of channels provided here is expected to match the number of channels\r
that this AudioVisualiserComponent has been told to use.\r
*/\r
- void pushBuffer (const float** channelData, int numChannels, int numSamples);\r
+ void pushBuffer (const float* const* channelData, int numChannels, int numSamples);\r
\r
/** Pushes a single sample (per channel).\r
The number of channels provided here is expected to match the number of channels\r
\r
//==============================================================================\r
/** Sets the note-on velocity, or "strike", value that will be used when triggering new notes. */\r
- void setVelocity (float newVelocity) { velocity = jlimit (newVelocity, 0.0f, 1.0f); }\r
+ void setVelocity (float newVelocity) { velocity = jlimit (0.0f, 1.0f, newVelocity); }\r
\r
/** Sets the pressure value that will be used for new notes. */\r
- void setPressure (float newPressure) { pressure = jlimit (newPressure, 0.0f, 1.0f); }\r
+ void setPressure (float newPressure) { pressure = jlimit (0.0f, 1.0f, newPressure); }\r
\r
/** Sets the note-off velocity, or "lift", value that will be used when notes are released. */\r
- void setLift (float newLift) { lift = jlimit (newLift, 0.0f, 1.0f); }\r
+ void setLift (float newLift) { lift = jlimit (0.0f, 1.0f, newLift); }\r
\r
/** Use this to enable the mouse source pressure to be used for the initial note-on\r
velocity, or "strike", value if the mouse source supports it.\r
\r
ID: juce_audio_utils\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_audio_processors, juce_audio_formats, juce_audio_devices\r
OSXFrameworks: CoreAudioKit DiscRecording\r
{\r
}\r
\r
-bool AudioCDReader::readSamples (int**, int, int,\r
+bool AudioCDReader::readSamples (int* const*, int, int,\r
int64, int)\r
{\r
return false;\r
}\r
}\r
\r
-bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool AudioCDReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples)\r
{\r
while (numSamples > 0)\r
delete device;\r
}\r
\r
-bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool AudioCDReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
int64 startSampleInFile, int numSamples)\r
{\r
using namespace CDReaderHelpers;\r
struct ChannelInfo\r
{\r
ChannelInfo() = default;\r
- ChannelInfo (Value** dataIn, int numChannelsIn)\r
+ ChannelInfo (Value* const* dataIn, int numChannelsIn)\r
: data (dataIn), numChannels (numChannelsIn) {}\r
\r
- Value** data = nullptr;\r
+ Value* const* data = nullptr;\r
int numChannels = 0;\r
};\r
\r
\r
for (auto i = processorOuts; i < processorIns; ++i)\r
{\r
- channels[totalNumChans] = tempBuffer.getWritePointer (i - outs.numChannels);\r
+ channels[totalNumChans] = tempBuffer.getWritePointer (i - processorOuts);\r
prepareInputChannel (i);\r
++totalNumChans;\r
}\r
}\r
\r
//==============================================================================\r
-void AudioProcessorPlayer::audioDeviceIOCallbackWithContext (const float** const inputChannelData,\r
+void AudioProcessorPlayer::audioDeviceIOCallbackWithContext (const float* const* const inputChannelData,\r
const int numInputChannels,\r
- float** const outputChannelData,\r
+ float* const* const outputChannelData,\r
const int numOutputChannels,\r
const int numSamples,\r
const AudioIODeviceCallbackContext& context)\r
sampleCount (sampleCountIn),\r
seconds ((double) sampleCountIn / sampleRateIn)\r
{\r
- processor.setPlayHead (this);\r
+ if (useThisPlayhead)\r
+ processor.setPlayHead (this);\r
}\r
\r
~PlayHead() override\r
{\r
- processor.setPlayHead (nullptr);\r
+ if (useThisPlayhead)\r
+ processor.setPlayHead (nullptr);\r
}\r
\r
private:\r
Optional<uint64_t> hostTimeNs;\r
uint64_t sampleCount;\r
double seconds;\r
+ bool useThisPlayhead = processor.getPlayHead() == nullptr;\r
};\r
\r
PlayHead playHead { *processor,\r
\r
//==============================================================================\r
/** @internal */\r
- void audioDeviceIOCallbackWithContext (const float**, int, float**, int, int, const AudioIODeviceCallbackContext&) override;\r
+ void audioDeviceIOCallbackWithContext (const float* const*, int, float* const*, int, int, const AudioIODeviceCallbackContext&) override;\r
/** @internal */\r
void audioDeviceAboutToStart (AudioIODevice*) override;\r
/** @internal */\r
}\r
\r
//==============================================================================\r
-void SoundPlayer::audioDeviceIOCallback (const float** inputChannelData,\r
- int numInputChannels,\r
- float** outputChannelData,\r
- int numOutputChannels,\r
- int numSamples)\r
+void SoundPlayer::audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
+ int numInputChannels,\r
+ float* const* outputChannelData,\r
+ int numOutputChannels,\r
+ int numSamples,\r
+ const AudioIODeviceCallbackContext& context)\r
{\r
- player.audioDeviceIOCallback (inputChannelData, numInputChannels,\r
- outputChannelData, numOutputChannels,\r
- numSamples);\r
+ player.audioDeviceIOCallbackWithContext (inputChannelData, numInputChannels,\r
+ outputChannelData, numOutputChannels,\r
+ numSamples, context);\r
}\r
\r
void SoundPlayer::audioDeviceAboutToStart (AudioIODevice* device)\r
\r
//==============================================================================\r
/** @internal */\r
- void audioDeviceIOCallback (const float**, int, float**, int, int) override;\r
+ void audioDeviceIOCallbackWithContext (const float* const*, int, float* const*, int, int, const AudioIODeviceCallbackContext&) override;\r
/** @internal */\r
void audioDeviceAboutToStart (AudioIODevice*) override;\r
/** @internal */\r
\r
ID: juce_box2d\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_graphics\r
\r
@see add\r
*/\r
template <class OtherArrayType>\r
- typename std::enable_if<! std::is_pointer<OtherArrayType>::value, void>::type\r
+ std::enable_if_t<! std::is_pointer_v<OtherArrayType>, void>\r
addArray (const OtherArrayType& arrayToAddFrom,\r
int startIndex,\r
int numElementsToAdd = -1)\r
using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType;\r
\r
#if ! (defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__))\r
- static_assert (std::is_trivially_copyable<CopyableType>::value,\r
+ static_assert (std::is_trivially_copyable_v<CopyableType>,\r
"Test TriviallyCopyableType is not trivially copyable");\r
- static_assert (! std::is_trivially_copyable<NoncopyableType>::value,\r
+ static_assert (! std::is_trivially_copyable_v<NoncopyableType>,\r
"Test NonTriviallyCopyableType is trivially copyable");\r
#endif\r
\r
using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type;\r
\r
template <class OtherElementType, class OtherCriticalSection>\r
- using AllowConversion = typename std::enable_if<! std::is_same<std::tuple<ElementType, TypeOfCriticalSectionToUse>,\r
- std::tuple<OtherElementType, OtherCriticalSection>>::value>::type;\r
+ using AllowConversion = std::enable_if_t<! std::is_same_v<std::tuple<ElementType, TypeOfCriticalSectionToUse>,\r
+ std::tuple<OtherElementType, OtherCriticalSection>>>;\r
\r
public:\r
//==============================================================================\r
}\r
\r
template <class OtherArrayType>\r
- typename std::enable_if<! std::is_pointer<OtherArrayType>::value, int>::type\r
+ std::enable_if_t<! std::is_pointer_v<OtherArrayType>, int>\r
addArray (const OtherArrayType& arrayToAddFrom,\r
int startIndex, int numElementsToAdd = -1)\r
{\r
\r
private:\r
//==============================================================================\r
- template <typename T>\r
#if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)\r
- using IsTriviallyCopyable = std::is_scalar<T>;\r
+ static constexpr auto isTriviallyCopyable = std::is_scalar_v<ElementType>;\r
#else\r
- using IsTriviallyCopyable = std::is_trivially_copyable<T>;\r
+ static constexpr auto isTriviallyCopyable = std::is_trivially_copyable_v<ElementType>;\r
#endif\r
\r
- template <typename T>\r
- using TriviallyCopyableVoid = typename std::enable_if<IsTriviallyCopyable<T>::value, void>::type;\r
-\r
- template <typename T>\r
- using NonTriviallyCopyableVoid = typename std::enable_if<! IsTriviallyCopyable<T>::value, void>::type;\r
-\r
//==============================================================================\r
- template <typename T = ElementType>\r
- TriviallyCopyableVoid<T> addArrayInternal (const ElementType* otherElements, int numElements)\r
- {\r
- if (numElements > 0)\r
- memcpy (elements + numUsed, otherElements, (size_t) numElements * sizeof (ElementType));\r
- }\r
-\r
- template <typename Type, typename T = ElementType>\r
- TriviallyCopyableVoid<T> addArrayInternal (const Type* otherElements, int numElements)\r
- {\r
- auto* start = elements + numUsed;\r
-\r
- while (--numElements >= 0)\r
- new (start++) ElementType (*(otherElements++));\r
- }\r
-\r
- template <typename Type, typename T = ElementType>\r
- NonTriviallyCopyableVoid<T> addArrayInternal (const Type* otherElements, int numElements)\r
+ template <typename Type>\r
+ void addArrayInternal (const Type* otherElements, int numElements)\r
{\r
- auto* start = elements + numUsed;\r
+ if constexpr (isTriviallyCopyable && std::is_same_v<Type, ElementType>)\r
+ {\r
+ if (numElements > 0)\r
+ memcpy (elements + numUsed, otherElements, (size_t) numElements * sizeof (ElementType));\r
+ }\r
+ else\r
+ {\r
+ auto* start = elements + numUsed;\r
\r
- while (--numElements >= 0)\r
- new (start++) ElementType (*(otherElements++));\r
+ while (--numElements >= 0)\r
+ new (start++) ElementType (*(otherElements++));\r
+ }\r
}\r
\r
//==============================================================================\r
- template <typename T = ElementType>\r
- TriviallyCopyableVoid<T> setAllocatedSizeInternal (int numElements)\r
+ void setAllocatedSizeInternal (int numElements)\r
{\r
- elements.realloc ((size_t) numElements);\r
- }\r
-\r
- template <typename T = ElementType>\r
- NonTriviallyCopyableVoid<T> setAllocatedSizeInternal (int numElements)\r
- {\r
- HeapBlock<ElementType> newElements (numElements);\r
-\r
- for (int i = 0; i < numUsed; ++i)\r
+ if constexpr (isTriviallyCopyable)\r
{\r
- new (newElements + i) ElementType (std::move (elements[i]));\r
- elements[i].~ElementType();\r
+ elements.realloc ((size_t) numElements);\r
}\r
+ else\r
+ {\r
+ HeapBlock<ElementType> newElements (numElements);\r
+\r
+ for (int i = 0; i < numUsed; ++i)\r
+ {\r
+ new (newElements + i) ElementType (std::move (elements[i]));\r
+ elements[i].~ElementType();\r
+ }\r
\r
- elements = std::move (newElements);\r
+ elements = std::move (newElements);\r
+ }\r
}\r
\r
//==============================================================================\r
return elements + indexToInsertAt;\r
}\r
\r
- template <typename T = ElementType>\r
- TriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements)\r
- {\r
- auto* start = elements + indexToInsertAt;\r
- auto numElementsToShift = numUsed - indexToInsertAt;\r
- memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType));\r
- }\r
-\r
- template <typename T = ElementType>\r
- NonTriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements)\r
+ void createInsertSpaceInternal (int indexToInsertAt, int numElements)\r
{\r
- auto* end = elements + numUsed;\r
- auto* newEnd = end + numElements;\r
- auto numElementsToShift = numUsed - indexToInsertAt;\r
-\r
- for (int i = 0; i < numElementsToShift; ++i)\r
+ if constexpr (isTriviallyCopyable)\r
{\r
- new (--newEnd) ElementType (std::move (*(--end)));\r
- end->~ElementType();\r
+ auto* start = elements + indexToInsertAt;\r
+ auto numElementsToShift = numUsed - indexToInsertAt;\r
+ memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType));\r
}\r
- }\r
-\r
- //==============================================================================\r
- template <typename T = ElementType>\r
- TriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)\r
- {\r
- auto* start = elements + indexToRemoveAt;\r
- auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);\r
- memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType));\r
- }\r
-\r
- template <typename T = ElementType>\r
- NonTriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)\r
- {\r
- auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);\r
- auto* destination = elements + indexToRemoveAt;\r
- auto* source = destination + numElementsToRemove;\r
-\r
- for (int i = 0; i < numElementsToShift; ++i)\r
- moveAssignElement (destination++, std::move (*(source++)));\r
+ else\r
+ {\r
+ auto* end = elements + numUsed;\r
+ auto* newEnd = end + numElements;\r
+ auto numElementsToShift = numUsed - indexToInsertAt;\r
\r
- for (int i = 0; i < numElementsToRemove; ++i)\r
- (destination++)->~ElementType();\r
+ for (int i = 0; i < numElementsToShift; ++i)\r
+ {\r
+ new (--newEnd) ElementType (std::move (*(--end)));\r
+ end->~ElementType();\r
+ }\r
+ }\r
}\r
\r
//==============================================================================\r
- template <typename T = ElementType>\r
- TriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept\r
+ void removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)\r
{\r
- char tempCopy[sizeof (ElementType)];\r
- memcpy (tempCopy, elements + currentIndex, sizeof (ElementType));\r
-\r
- if (newIndex > currentIndex)\r
+ if constexpr (isTriviallyCopyable)\r
{\r
- memmove (elements + currentIndex,\r
- elements + currentIndex + 1,\r
- (size_t) (newIndex - currentIndex) * sizeof (ElementType));\r
+ auto* start = elements + indexToRemoveAt;\r
+ auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);\r
+ memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType));\r
}\r
else\r
{\r
- memmove (elements + newIndex + 1,\r
- elements + newIndex,\r
- (size_t) (currentIndex - newIndex) * sizeof (ElementType));\r
- }\r
+ auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);\r
+ auto* destination = elements + indexToRemoveAt;\r
+ auto* source = destination + numElementsToRemove;\r
\r
- memcpy (elements + newIndex, tempCopy, sizeof (ElementType));\r
+ for (int i = 0; i < numElementsToShift; ++i)\r
+ moveAssignElement (destination++, std::move (*(source++)));\r
+\r
+ for (int i = 0; i < numElementsToRemove; ++i)\r
+ (destination++)->~ElementType();\r
+ }\r
}\r
\r
- template <typename T = ElementType>\r
- NonTriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept\r
+ //==============================================================================\r
+ void moveInternal (int currentIndex, int newIndex) noexcept\r
{\r
- auto* e = elements + currentIndex;\r
- ElementType tempCopy (std::move (*e));\r
- auto delta = newIndex - currentIndex;\r
-\r
- if (delta > 0)\r
+ if constexpr (isTriviallyCopyable)\r
{\r
- for (int i = 0; i < delta; ++i)\r
+ char tempCopy[sizeof (ElementType)];\r
+ memcpy (tempCopy, elements + currentIndex, sizeof (ElementType));\r
+\r
+ if (newIndex > currentIndex)\r
{\r
- moveAssignElement (e, std::move (*(e + 1)));\r
- ++e;\r
+ memmove (elements + currentIndex,\r
+ elements + currentIndex + 1,\r
+ (size_t) (newIndex - currentIndex) * sizeof (ElementType));\r
}\r
+ else\r
+ {\r
+ memmove (elements + newIndex + 1,\r
+ elements + newIndex,\r
+ (size_t) (currentIndex - newIndex) * sizeof (ElementType));\r
+ }\r
+\r
+ memcpy (elements + newIndex, tempCopy, sizeof (ElementType));\r
}\r
else\r
{\r
- for (int i = 0; i < -delta; ++i)\r
+ auto* e = elements + currentIndex;\r
+ ElementType tempCopy (std::move (*e));\r
+ auto delta = newIndex - currentIndex;\r
+\r
+ if (delta > 0)\r
{\r
- moveAssignElement (e, std::move (*(e - 1)));\r
- --e;\r
+ for (int i = 0; i < delta; ++i)\r
+ {\r
+ moveAssignElement (e, std::move (*(e + 1)));\r
+ ++e;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for (int i = 0; i < -delta; ++i)\r
+ {\r
+ moveAssignElement (e, std::move (*(e - 1)));\r
+ --e;\r
+ }\r
}\r
- }\r
\r
- moveAssignElement (e, std::move (tempCopy));\r
+ moveAssignElement (e, std::move (tempCopy));\r
+ }\r
}\r
\r
//==============================================================================\r
}\r
\r
//==============================================================================\r
- template <typename T = ElementType>\r
- typename std::enable_if<std::is_move_assignable<T>::value, void>::type\r
- moveAssignElement (ElementType* destination, ElementType&& source)\r
+ void moveAssignElement (ElementType* destination, ElementType&& source)\r
{\r
- *destination = std::move (source);\r
- }\r
-\r
- template <typename T = ElementType>\r
- typename std::enable_if<! std::is_move_assignable<T>::value, void>::type\r
- moveAssignElement (ElementType* destination, ElementType&& source)\r
- {\r
- destination->~ElementType();\r
- new (destination) ElementType (std::move (source));\r
+ if constexpr (std::is_move_assignable_v<ElementType>)\r
+ {\r
+ *destination = std::move (source);\r
+ }\r
+ else\r
+ {\r
+ destination->~ElementType();\r
+ new (destination) ElementType (std::move (source));\r
+ }\r
}\r
\r
void checkSourceIsNotAMember (const ElementType& element)\r
namespace juce\r
{\r
\r
-namespace detail\r
-{\r
-namespace adlSwap\r
-{\r
-using std::swap;\r
-\r
-template <typename T>\r
-constexpr auto isNothrowSwappable = noexcept (swap (std::declval<T&>(), std::declval<T&>()));\r
-} // namespace adlSwap\r
-} // namespace detail\r
-\r
-/** A type representing the null state of an Optional.\r
- Similar to std::nullopt_t.\r
-*/\r
-struct Nullopt\r
-{\r
- explicit constexpr Nullopt (int) {}\r
-};\r
-\r
-/** An object that can be used when constructing and comparing Optional instances.\r
- Similar to std::nullopt.\r
-*/\r
-constexpr Nullopt nullopt { 0 };\r
+using Nullopt = std::nullopt_t;\r
+constexpr auto nullopt = std::nullopt;\r
\r
// Without this, our tests can emit "unreachable code" warnings during\r
// link time code generation.\r
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702)\r
\r
+#define JUCE_OPTIONAL_OPERATORS X(==) X(!=) X(<) X(<=) X(>) X(>=)\r
+\r
/**\r
A simple optional type.\r
\r
- Has similar (not necessarily identical!) semantics to std::optional.\r
+ In new code, you should probably prefer using std::optional directly.\r
\r
This is intended to stand-in for std::optional while JUCE's minimum\r
supported language standard is lower than C++17. When the minimum language\r
template <typename Value>\r
class Optional\r
{\r
- template <typename T, typename U>\r
- struct NotConstructibleFromSimilarType\r
- {\r
- static constexpr auto value = ! std::is_constructible<T, Optional<U>&>::value\r
- && ! std::is_constructible<T, const Optional<U>&>::value\r
- && ! std::is_constructible<T, Optional<U>&&>::value\r
- && ! std::is_constructible<T, const Optional<U>&&>::value\r
- && ! std::is_convertible<Optional<U>&, T>::value\r
- && ! std::is_convertible<const Optional<U>&, T>::value\r
- && ! std::is_convertible<Optional<U>&&, T>::value\r
- && ! std::is_convertible<const Optional<U>&&, T>::value;\r
- };\r
-\r
- template <typename T, typename U>\r
- using OptionalCopyConstructorEnabled = std::enable_if_t<std::is_constructible<T, const U&>::value && NotConstructibleFromSimilarType<T, U>::value>;\r
-\r
- template <typename T, typename U>\r
- using OptionalMoveConstructorEnabled = std::enable_if_t<std::is_constructible<T, U&&>::value && NotConstructibleFromSimilarType<T, U>::value>;\r
-\r
- template <typename T, typename U>\r
- static auto notAssignableFromSimilarType = NotConstructibleFromSimilarType<T, U>::value\r
- && ! std::is_assignable<T&, Optional<U>&>::value\r
- && ! std::is_assignable<T&, const Optional<U>&>::value\r
- && ! std::is_assignable<T&, Optional<U>&&>::value\r
- && ! std::is_assignable<T&, const Optional<U>&&>::value;\r
-\r
- template <typename T, typename U>\r
- using OptionalCopyAssignmentEnabled = std::enable_if_t<std::is_constructible<T, const U&>::value\r
- && std::is_assignable<T&, const U&>::value\r
- && NotConstructibleFromSimilarType<T, U>::value>;\r
-\r
- template <typename T, typename U>\r
- using OptionalMoveAssignmentEnabled = std::enable_if_t<std::is_constructible<T, U>::value\r
- && std::is_nothrow_assignable<T&, U>::value\r
- && NotConstructibleFromSimilarType<T, U>::value>;\r
+ template <typename> struct IsOptional : std::false_type {};\r
+ template <typename T> struct IsOptional<Optional<T>> : std::true_type {};\r
\r
public:\r
- Optional() : placeholder() {}\r
-\r
- Optional (Nullopt) noexcept : placeholder() {}\r
-\r
- template <typename U = Value,\r
- typename = std::enable_if_t<std::is_constructible<Value, U&&>::value\r
- && ! std::is_same<std::decay_t<U>, Optional>::value>>\r
- Optional (U&& value) noexcept (noexcept (Value (std::forward<U> (value))))\r
- : storage (std::forward<U> (value)), valid (true)\r
- {\r
- }\r
-\r
- Optional (Optional&& other) noexcept (noexcept (std::declval<Optional>().constructFrom (other)))\r
- : placeholder()\r
- {\r
- constructFrom (other);\r
- }\r
+ Optional() = default;\r
+ Optional (const Optional&) = default;\r
+ Optional (Optional&&) = default;\r
+ Optional& operator= (const Optional&) = default;\r
+ Optional& operator= (Optional&&) = default;\r
\r
- Optional (const Optional& other)\r
- : placeholder(), valid (other.valid)\r
- {\r
- if (valid)\r
- new (&storage) Value (*other);\r
- }\r
+ Optional (Nullopt) noexcept {}\r
\r
- template <typename Other, typename = OptionalMoveConstructorEnabled<Value, Other>>\r
- Optional (Optional<Other>&& other) noexcept (noexcept (std::declval<Optional>().constructFrom (other)))\r
- : placeholder()\r
- {\r
- constructFrom (other);\r
- }\r
+ template <typename Head, typename... Tail, std::enable_if_t<! IsOptional<std::decay_t<Head>>::value, int> = 0>\r
+ Optional (Head&& head, Tail&&... tail)\r
+ noexcept (std::is_nothrow_constructible_v<std::optional<Value>, Head, Tail...>)\r
+ : opt (std::forward<Head> (head), std::forward<Tail> (tail)...) {}\r
\r
- template <typename Other, typename = OptionalCopyConstructorEnabled<Value, Other>>\r
+ template <typename Other>\r
Optional (const Optional<Other>& other)\r
- : placeholder(), valid (other.hasValue())\r
- {\r
- if (valid)\r
- new (&storage) Value (*other);\r
- }\r
+ noexcept (std::is_nothrow_constructible_v<std::optional<Value>, const std::optional<Other>&>)\r
+ : opt (other.opt) {}\r
\r
- Optional& operator= (Nullopt) noexcept\r
- {\r
- reset();\r
- return *this;\r
- }\r
+ template <typename Other>\r
+ Optional (Optional<Other>&& other)\r
+ noexcept (std::is_nothrow_constructible_v<std::optional<Value>, std::optional<Other>&&>)\r
+ : opt (std::move (other.opt)) {}\r
\r
- template <typename U = Value,\r
- typename = std::enable_if_t<std::is_nothrow_move_constructible<U>::value\r
- && std::is_nothrow_move_assignable<U>::value>>\r
- Optional& operator= (Optional&& other) noexcept (noexcept (std::declval<Optional>().assign (std::declval<Optional&>())))\r
+ template <typename Other, std::enable_if_t<! IsOptional<std::decay_t<Other>>::value, int> = 0>\r
+ Optional& operator= (Other&& other)\r
+ noexcept (std::is_nothrow_assignable_v<std::optional<Value>, Other>)\r
{\r
- assign (other);\r
+ opt = std::forward<Other> (other);\r
return *this;\r
}\r
\r
- template <typename U = Value,\r
- typename = std::enable_if_t<! std::is_same<std::decay_t<U>, Optional>::value\r
- && std::is_constructible<Value, U>::value\r
- && std::is_assignable<Value&, U>::value\r
- && (! std::is_scalar<Value>::value || ! std::is_same<std::decay_t<U>, Value>::value)>>\r
- Optional& operator= (U&& value)\r
+ template <typename Other>\r
+ Optional& operator= (const Optional<Other>& other)\r
+ noexcept (std::is_nothrow_assignable_v<std::optional<Value>, const std::optional<Other>&>)\r
{\r
- if (valid)\r
- **this = std::forward<U> (value);\r
- else\r
- new (&storage) Value (std::forward<U> (value));\r
-\r
- valid = true;\r
+ opt = other.opt;\r
return *this;\r
}\r
\r
- /** Maintains the strong exception safety guarantee. */\r
- Optional& operator= (const Optional& other)\r
+ template <typename Other>\r
+ Optional& operator= (Optional<Other>&& other)\r
+ noexcept (std::is_nothrow_assignable_v<std::optional<Value>, std::optional<Other>&&>)\r
{\r
- auto copy = other;\r
- assign (copy);\r
+ opt = std::move (other.opt);\r
return *this;\r
}\r
\r
- template <typename Other, typename = OptionalMoveAssignmentEnabled<Value, Other>>\r
- Optional& operator= (Optional<Other>&& other) noexcept (noexcept (std::declval<Optional>().assign (other)))\r
+ template <typename... Other>\r
+ auto& emplace (Other&&... other)\r
{\r
- assign (other);\r
- return *this;\r
+ return opt.emplace (std::forward<Other> (other)...);\r
}\r
\r
- /** Maintains the strong exception safety guarantee. */\r
- template <typename Other, typename = OptionalCopyAssignmentEnabled<Value, Other>>\r
- Optional& operator= (const Optional<Other>& other)\r
+ void reset() noexcept\r
{\r
- auto copy = other;\r
- assign (copy);\r
- return *this;\r
+ opt.reset();\r
}\r
\r
- ~Optional() noexcept\r
+ void swap (Optional& other)\r
+ noexcept (std::is_nothrow_swappable_v<std::optional<Value>>)\r
{\r
- reset();\r
+ opt.swap (other.opt);\r
}\r
\r
- Value* operator->() noexcept { return reinterpret_cast< Value*> (&storage); }\r
- const Value* operator->() const noexcept { return reinterpret_cast<const Value*> (&storage); }\r
-\r
- Value& operator*() noexcept { return *operator->(); }\r
- const Value& operator*() const noexcept { return *operator->(); }\r
+ decltype (auto) operator->() { return opt.operator->(); }\r
+ decltype (auto) operator->() const { return opt.operator->(); }\r
+ decltype (auto) operator* () { return opt.operator* (); }\r
+ decltype (auto) operator* () const { return opt.operator* (); }\r
\r
- explicit operator bool() const noexcept { return valid; }\r
- bool hasValue() const noexcept { return valid; }\r
+ operator bool() const noexcept { return opt.has_value(); }\r
+ bool hasValue() const noexcept { return opt.has_value(); }\r
\r
- void reset()\r
- {\r
- if (std::exchange (valid, false))\r
- operator*().~Value();\r
- }\r
+ template <typename U>\r
+ decltype (auto) orFallback (U&& fallback) const& { return opt.value_or (std::forward<U> (fallback)); }\r
\r
- /** Like std::optional::value_or */\r
template <typename U>\r
- Value orFallback (U&& fallback) const { return *this ? **this : std::forward<U> (fallback); }\r
+ decltype (auto) orFallback (U&& fallback) & { return opt.value_or (std::forward<U> (fallback)); }\r
\r
- template <typename... Args>\r
- Value& emplace (Args&&... args)\r
- {\r
- reset();\r
- new (&storage) Value (std::forward<Args> (args)...);\r
- valid = true;\r
- return **this;\r
- }\r
+ #define X(op) \\r
+ template <typename T, typename U> friend bool operator op (const Optional<T>&, const Optional<U>&); \\r
+ template <typename T> friend bool operator op (const Optional<T>&, Nullopt); \\r
+ template <typename T> friend bool operator op (Nullopt, const Optional<T>&); \\r
+ template <typename T, typename U> friend bool operator op (const Optional<T>&, const U&); \\r
+ template <typename T, typename U> friend bool operator op (const T&, const Optional<U>&);\r
\r
- void swap (Optional& other) noexcept (std::is_nothrow_move_constructible<Value>::value\r
- && detail::adlSwap::isNothrowSwappable<Value>)\r
- {\r
- if (hasValue() && other.hasValue())\r
- {\r
- using std::swap;\r
- swap (**this, *other);\r
- }\r
- else if (hasValue() || other.hasValue())\r
- {\r
- (hasValue() ? other : *this).constructFrom (hasValue() ? *this : other);\r
- }\r
- }\r
-\r
-private:\r
- template <typename Other>\r
- void constructFrom (Optional<Other>& other) noexcept (noexcept (Value (std::move (*other))))\r
- {\r
- if (! other.hasValue())\r
- return;\r
+ JUCE_OPTIONAL_OPERATORS\r
\r
- new (&storage) Value (std::move (*other));\r
- valid = true;\r
- other.reset();\r
- }\r
+ #undef X\r
\r
+private:\r
template <typename Other>\r
- void assign (Optional<Other>& other) noexcept (noexcept (std::declval<Value&>() = std::move (*other)) && noexcept (std::declval<Optional>().constructFrom (other)))\r
- {\r
- if (valid)\r
- {\r
- if (other.hasValue())\r
- {\r
- **this = std::move (*other);\r
- other.reset();\r
- }\r
- else\r
- {\r
- reset();\r
- }\r
- }\r
- else\r
- {\r
- constructFrom (other);\r
- }\r
- }\r
+ friend class Optional;\r
\r
- union\r
- {\r
- char placeholder;\r
- Value storage;\r
- };\r
- bool valid = false;\r
+ std::optional<Value> opt;\r
};\r
\r
JUCE_END_IGNORE_WARNINGS_MSVC\r
return std::forward<Value> (v);\r
}\r
\r
-template <class T, class U>\r
-bool operator== (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
- if (lhs.hasValue() != rhs.hasValue()) return false;\r
- if (! lhs.hasValue()) return true;\r
- return *lhs == *rhs;\r
-}\r
+#define X(op) \\r
+ template <typename T, typename U> bool operator op (const Optional<T>& lhs, const Optional<U>& rhs) { return lhs.opt op rhs.opt; } \\r
+ template <typename T> bool operator op (const Optional<T>& lhs, Nullopt rhs) { return lhs.opt op rhs; } \\r
+ template <typename T> bool operator op (Nullopt lhs, const Optional<T>& rhs) { return lhs op rhs.opt; } \\r
+ template <typename T, typename U> bool operator op (const Optional<T>& lhs, const U& rhs) { return lhs.opt op rhs; } \\r
+ template <typename T, typename U> bool operator op (const T& lhs, const Optional<U>& rhs) { return lhs op rhs.opt; }\r
\r
-template <class T, class U>\r
-bool operator!= (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
- if (lhs.hasValue() != rhs.hasValue()) return true;\r
- if (! lhs.hasValue()) return false;\r
- return *lhs != *rhs;\r
-}\r
-\r
-template <class T, class U>\r
-bool operator< (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
- if (! rhs.hasValue()) return false;\r
- if (! lhs.hasValue()) return true;\r
- return *lhs < *rhs;\r
-}\r
+JUCE_OPTIONAL_OPERATORS\r
\r
-template <class T, class U>\r
-bool operator<= (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
- if (! lhs.hasValue()) return true;\r
- if (! rhs.hasValue()) return false;\r
- return *lhs <= *rhs;\r
-}\r
-\r
-template <class T, class U>\r
-bool operator> (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
- if (! lhs.hasValue()) return false;\r
- if (! rhs.hasValue()) return true;\r
- return *lhs > *rhs;\r
-}\r
-\r
-template <class T, class U>\r
-bool operator>= (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
- if (! rhs.hasValue()) return true;\r
- if (! lhs.hasValue()) return false;\r
- return *lhs >= *rhs;\r
-}\r
+#undef X\r
\r
-template <class T>\r
-bool operator== (const Optional<T>& opt, Nullopt) noexcept { return ! opt.hasValue(); }\r
-template <class T>\r
-bool operator== (Nullopt, const Optional<T>& opt) noexcept { return ! opt.hasValue(); }\r
-template <class T>\r
-bool operator!= (const Optional<T>& opt, Nullopt) noexcept { return opt.hasValue(); }\r
-template <class T>\r
-bool operator!= (Nullopt, const Optional<T>& opt) noexcept { return opt.hasValue(); }\r
-template <class T>\r
-bool operator< (const Optional<T>&, Nullopt) noexcept { return false; }\r
-template <class T>\r
-bool operator< (Nullopt, const Optional<T>& opt) noexcept { return opt.hasValue(); }\r
-template <class T>\r
-bool operator<= (const Optional<T>& opt, Nullopt) noexcept { return ! opt.hasValue(); }\r
-template <class T>\r
-bool operator<= (Nullopt, const Optional<T>&) noexcept { return true; }\r
-template <class T>\r
-bool operator> (const Optional<T>& opt, Nullopt) noexcept { return opt.hasValue(); }\r
-template <class T>\r
-bool operator> (Nullopt, const Optional<T>&) noexcept { return false; }\r
-template <class T>\r
-bool operator>= (const Optional<T>&, Nullopt) noexcept { return true; }\r
-template <class T>\r
-bool operator>= (Nullopt, const Optional<T>& opt) noexcept { return ! opt.hasValue(); }\r
-\r
-template <class T, class U>\r
-bool operator== (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt == value : false; }\r
-template <class T, class U>\r
-bool operator== (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value == *opt : false; }\r
-template <class T, class U>\r
-bool operator!= (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt != value : true; }\r
-template <class T, class U>\r
-bool operator!= (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value != *opt : true; }\r
-template <class T, class U>\r
-bool operator< (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt < value : true; }\r
-template <class T, class U>\r
-bool operator< (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value < *opt : false; }\r
-template <class T, class U>\r
-bool operator<= (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt <= value : true; }\r
-template <class T, class U>\r
-bool operator<= (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value <= *opt : false; }\r
-template <class T, class U>\r
-bool operator> (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt > value : false; }\r
-template <class T, class U>\r
-bool operator> (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value > *opt : true; }\r
-template <class T, class U>\r
-bool operator>= (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt >= value : false; }\r
-template <class T, class U>\r
-bool operator>= (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value >= *opt : true; }\r
+#undef JUCE_OPTIONAL_OPERATORS\r
\r
} // namespace juce\r
Optional<Ptr> original (ptr);\r
expect (ptr.use_count() == 2);\r
auto other = std::move (original);\r
- expect (! original.hasValue());\r
+ // A moved-from optional still contains a value!\r
+ expect (original.hasValue());\r
expect (other.hasValue());\r
expect (ptr.use_count() == 2);\r
}\r
aOpt = std::move (bOpt);\r
\r
expect (aOpt.hasValue());\r
- expect (! bOpt.hasValue());\r
+ expect (bOpt.hasValue());\r
\r
expect (a.use_count() == 1);\r
expect (b.use_count() == 2);\r
empty = std::move (aOpt);\r
\r
expect (empty.hasValue());\r
- expect (! aOpt.hasValue());\r
+ expect (aOpt.hasValue());\r
\r
expect (a.use_count() == 2);\r
}\r
expect (! a.hasValue());\r
}\r
\r
- beginTest ("Strong exception safety is maintained when copying over populated object");\r
+ beginTest ("Exception safety of contained type is maintained when copying over populated object");\r
{\r
bool threw = false;\r
Optional<ThrowOnCopy> a = ThrowOnCopy();\r
\r
expect (threw);\r
expect (a.hasValue());\r
- expect (a->value == 5);\r
+ expect (a->value == -100);\r
}\r
\r
beginTest ("Assigning from nullopt clears the instance");\r
}\r
\r
String FileSearchPath::toString() const\r
+{\r
+ return toStringWithSeparator (";");\r
+}\r
+\r
+String FileSearchPath::toStringWithSeparator (StringRef separator) const\r
{\r
auto dirs = directories;\r
\r
for (auto& d : dirs)\r
- if (d.containsChar (';'))\r
+ if (d.contains (separator))\r
d = d.quoted();\r
\r
- return dirs.joinIntoString (";");\r
+ return dirs.joinIntoString (separator);\r
}\r
\r
void FileSearchPath::add (const File& dir, int insertIndex)\r
/** Returns the search path as a semicolon-separated list of directories. */\r
String toString() const;\r
\r
+ /** Returns the search paths, joined with the provided separator. */\r
+ String toStringWithSeparator (StringRef separator) const;\r
+\r
//==============================================================================\r
/** Adds a new directory to the search path.\r
\r
namespace juce\r
{\r
\r
-struct MimeTypeTableEntry\r
+namespace\r
{\r
- const char* fileExtension, *mimeType;\r
\r
- static MimeTypeTableEntry table[641];\r
+struct Entry\r
+{\r
+ const char* fileExtension;\r
+ const char* mimeType;\r
};\r
\r
-static StringArray getMatches (const String& toMatch,\r
- const char* MimeTypeTableEntry::* matchField,\r
- const char* MimeTypeTableEntry::* returnField)\r
+class Table\r
{\r
- StringArray result;\r
+public:\r
+ void addEntry (const Entry& entry)\r
+ {\r
+ typeForExtension.emplace (entry.fileExtension, entry.mimeType);\r
+ extensionForType.emplace (entry.mimeType, entry.fileExtension);\r
+ }\r
\r
- for (auto type : MimeTypeTableEntry::table)\r
- if (toMatch == type.*matchField)\r
- result.add (type.*returnField);\r
+ StringArray getTypesForExtension (const String& extension) const\r
+ {\r
+ return getValuesForKey (typeForExtension, extension);\r
+ }\r
\r
- return result;\r
-}\r
+ StringArray getExtensionsForType (const String& type) const\r
+ {\r
+ return getValuesForKey (extensionForType, type);\r
+ }\r
\r
-namespace MimeTypeTable\r
-{\r
+ static Table& get()\r
+ {\r
+ static Table table;\r
+ return table;\r
+ }\r
+\r
+private:\r
+ Table() = default;\r
+\r
+ static StringArray getValuesForKey (const std::multimap<String, String>& map, const String& key)\r
+ {\r
+ const auto [begin, end] = map.equal_range (key);\r
+\r
+ StringArray result;\r
+ std::for_each (begin, end, [&] (const auto& pair) { result.add (pair.second); });\r
+\r
+ return result;\r
+ }\r
+\r
+ static inline constexpr Entry initialEntries[]\r
+ {\r
+ { "3dm", "x-world/x-3dmf" },\r
+ { "3dmf", "x-world/x-3dmf" },\r
+ { "a", "application/octet-stream" },\r
+ { "aab", "application/x-authorware-bin" },\r
+ { "aam", "application/x-authorware-map" },\r
+ { "aas", "application/x-authorware-seg" },\r
+ { "abc", "text/vnd.abc" },\r
+ { "acgi", "text/html" },\r
+ { "afl", "video/animaflex" },\r
+ { "ai", "application/postscript" },\r
+ { "aif", "audio/aiff" },\r
+ { "aif", "audio/x-aiff" },\r
+ { "aifc", "audio/aiff" },\r
+ { "aifc", "audio/x-aiff" },\r
+ { "aiff", "audio/aiff" },\r
+ { "aiff", "audio/x-aiff" },\r
+ { "aim", "application/x-aim" },\r
+ { "aip", "text/x-audiosoft-intra" },\r
+ { "ani", "application/x-navi-animation" },\r
+ { "aos", "application/x-nokia-9000-communicator-add-on-software" },\r
+ { "aps", "application/mime" },\r
+ { "arc", "application/octet-stream" },\r
+ { "arj", "application/arj" },\r
+ { "arj", "application/octet-stream" },\r
+ { "art", "image/x-jg" },\r
+ { "asf", "video/x-ms-asf" },\r
+ { "asm", "text/x-asm" },\r
+ { "asp", "text/asp" },\r
+ { "asx", "application/x-mplayer2" },\r
+ { "asx", "video/x-ms-asf" },\r
+ { "asx", "video/x-ms-asf-plugin" },\r
+ { "au", "audio/basic" },\r
+ { "au", "audio/x-au" },\r
+ { "avi", "application/x-troff-msvideo" },\r
+ { "avi", "video/avi" },\r
+ { "avi", "video/msvideo" },\r
+ { "avi", "video/x-msvideo" },\r
+ { "avs", "video/avs-video" },\r
+ { "bcpio", "application/x-bcpio" },\r
+ { "bin", "application/mac-binary" },\r
+ { "bin", "application/macbinary" },\r
+ { "bin", "application/octet-stream" },\r
+ { "bin", "application/x-binary" },\r
+ { "bin", "application/x-macbinary" },\r
+ { "bm", "image/bmp" },\r
+ { "bmp", "image/bmp" },\r
+ { "bmp", "image/x-windows-bmp" },\r
+ { "boo", "application/book" },\r
+ { "book", "application/book" },\r
+ { "boz", "application/x-bzip2" },\r
+ { "bsh", "application/x-bsh" },\r
+ { "bz", "application/x-bzip" },\r
+ { "bz2", "application/x-bzip2" },\r
+ { "c", "text/plain" },\r
+ { "c", "text/x-c" },\r
+ { "c++", "text/plain" },\r
+ { "cat", "application/vnd.ms-pki.seccat" },\r
+ { "cc", "text/plain" },\r
+ { "cc", "text/x-c" },\r
+ { "ccad", "application/clariscad" },\r
+ { "cco", "application/x-cocoa" },\r
+ { "cdf", "application/cdf" },\r
+ { "cdf", "application/x-cdf" },\r
+ { "cdf", "application/x-netcdf" },\r
+ { "cer", "application/pkix-cert" },\r
+ { "cer", "application/x-x509-ca-cert" },\r
+ { "cha", "application/x-chat" },\r
+ { "chat", "application/x-chat" },\r
+ { "class", "application/java" },\r
+ { "class", "application/java-byte-code" },\r
+ { "class", "application/x-java-class" },\r
+ { "com", "application/octet-stream" },\r
+ { "com", "text/plain" },\r
+ { "conf", "text/plain" },\r
+ { "cpio", "application/x-cpio" },\r
+ { "cpp", "text/x-c" },\r
+ { "cpt", "application/mac-compactpro" },\r
+ { "cpt", "application/x-compactpro" },\r
+ { "cpt", "application/x-cpt" },\r
+ { "crl", "application/pkcs-crl" },\r
+ { "crl", "application/pkix-crl" },\r
+ { "crt", "application/pkix-cert" },\r
+ { "crt", "application/x-x509-ca-cert" },\r
+ { "crt", "application/x-x509-user-cert" },\r
+ { "csh", "application/x-csh" },\r
+ { "csh", "text/x-script.csh" },\r
+ { "css", "application/x-pointplus" },\r
+ { "css", "text/css" },\r
+ { "cxx", "text/plain" },\r
+ { "dcr", "application/x-director" },\r
+ { "deepv", "application/x-deepv" },\r
+ { "def", "text/plain" },\r
+ { "der", "application/x-x509-ca-cert" },\r
+ { "dif", "video/x-dv" },\r
+ { "dir", "application/x-director" },\r
+ { "dl", "video/dl" },\r
+ { "dl", "video/x-dl" },\r
+ { "doc", "application/msword" },\r
+ { "dot", "application/msword" },\r
+ { "dp", "application/commonground" },\r
+ { "drw", "application/drafting" },\r
+ { "dump", "application/octet-stream" },\r
+ { "dv", "video/x-dv" },\r
+ { "dvi", "application/x-dvi" },\r
+ { "dwf", "drawing/x-dwf" },\r
+ { "dwf", "model/vnd.dwf" },\r
+ { "dwg", "application/acad" },\r
+ { "dwg", "image/vnd.dwg" },\r
+ { "dwg", "image/x-dwg" },\r
+ { "dxf", "application/dxf" },\r
+ { "dxf", "image/vnd.dwg" },\r
+ { "dxf", "image/x-dwg" },\r
+ { "dxr", "application/x-director" },\r
+ { "el", "text/x-script.elisp" },\r
+ { "elc", "application/x-bytecode.elisp" },\r
+ { "elc", "application/x-elc" },\r
+ { "env", "application/x-envoy" },\r
+ { "eps", "application/postscript" },\r
+ { "es", "application/x-esrehber" },\r
+ { "etx", "text/x-setext" },\r
+ { "evy", "application/envoy" },\r
+ { "evy", "application/x-envoy" },\r
+ { "exe", "application/octet-stream" },\r
+ { "f", "text/plain" },\r
+ { "f", "text/x-fortran" },\r
+ { "f77", "text/x-fortran" },\r
+ { "f90", "text/plain" },\r
+ { "f90", "text/x-fortran" },\r
+ { "fdf", "application/vnd.fdf" },\r
+ { "fif", "application/fractals" },\r
+ { "fif", "image/fif" },\r
+ { "fli", "video/fli" },\r
+ { "fli", "video/x-fli" },\r
+ { "flo", "image/florian" },\r
+ { "flx", "text/vnd.fmi.flexstor" },\r
+ { "fmf", "video/x-atomic3d-feature" },\r
+ { "for", "text/plain" },\r
+ { "for", "text/x-fortran" },\r
+ { "fpx", "image/vnd.fpx" },\r
+ { "fpx", "image/vnd.net-fpx" },\r
+ { "frl", "application/freeloader" },\r
+ { "funk", "audio/make" },\r
+ { "g", "text/plain" },\r
+ { "g3", "image/g3fax" },\r
+ { "gif", "image/gif" },\r
+ { "gl", "video/gl" },\r
+ { "gl", "video/x-gl" },\r
+ { "gsd", "audio/x-gsm" },\r
+ { "gsm", "audio/x-gsm" },\r
+ { "gsp", "application/x-gsp" },\r
+ { "gss", "application/x-gss" },\r
+ { "gtar", "application/x-gtar" },\r
+ { "gz", "application/x-compressed" },\r
+ { "gz", "application/x-gzip" },\r
+ { "gzip", "application/x-gzip" },\r
+ { "gzip", "multipart/x-gzip" },\r
+ { "h", "text/plain" },\r
+ { "h", "text/x-h" },\r
+ { "hdf", "application/x-hdf" },\r
+ { "help", "application/x-helpfile" },\r
+ { "hgl", "application/vnd.hp-hpgl" },\r
+ { "hh", "text/plain" },\r
+ { "hh", "text/x-h" },\r
+ { "hlb", "text/x-script" },\r
+ { "hlp", "application/hlp" },\r
+ { "hlp", "application/x-helpfile" },\r
+ { "hlp", "application/x-winhelp" },\r
+ { "hpg", "application/vnd.hp-hpgl" },\r
+ { "hpgl", "application/vnd.hp-hpgl" },\r
+ { "hqx", "application/binhex" },\r
+ { "hqx", "application/binhex4" },\r
+ { "hqx", "application/mac-binhex" },\r
+ { "hqx", "application/mac-binhex40" },\r
+ { "hqx", "application/x-binhex40" },\r
+ { "hqx", "application/x-mac-binhex40" },\r
+ { "hta", "application/hta" },\r
+ { "htc", "text/x-component" },\r
+ { "htm", "text/html" },\r
+ { "html", "text/html" },\r
+ { "htmls", "text/html" },\r
+ { "htt", "text/webviewhtml" },\r
+ { "htx", "text/html" },\r
+ { "ice", "x-conference/x-cooltalk" },\r
+ { "ico", "image/x-icon" },\r
+ { "idc", "text/plain" },\r
+ { "ief", "image/ief" },\r
+ { "iefs", "image/ief" },\r
+ { "iges", "application/iges" },\r
+ { "iges", "model/iges" },\r
+ { "igs", "application/iges" },\r
+ { "igs", "model/iges" },\r
+ { "ima", "application/x-ima" },\r
+ { "imap", "application/x-httpd-imap" },\r
+ { "inf", "application/inf" },\r
+ { "ins", "application/x-internett-signup" },\r
+ { "ip", "application/x-ip2" },\r
+ { "isu", "video/x-isvideo" },\r
+ { "it", "audio/it" },\r
+ { "iv", "application/x-inventor" },\r
+ { "ivr", "i-world/i-vrml" },\r
+ { "ivy", "application/x-livescreen" },\r
+ { "jam", "audio/x-jam" },\r
+ { "jav", "text/plain" },\r
+ { "jav", "text/x-java-source" },\r
+ { "java", "text/plain" },\r
+ { "java", "text/x-java-source" },\r
+ { "jcm", "application/x-java-commerce" },\r
+ { "jfif", "image/jpeg" },\r
+ { "jfif", "image/pjpeg" },\r
+ { "jpe", "image/jpeg" },\r
+ { "jpe", "image/pjpeg" },\r
+ { "jpeg", "image/jpeg" },\r
+ { "jpeg", "image/pjpeg" },\r
+ { "jpg", "image/jpeg" },\r
+ { "jpg", "image/pjpeg" },\r
+ { "jps", "image/x-jps" },\r
+ { "js", "application/x-javascript" },\r
+ { "json", "application/json" },\r
+ { "jut", "image/jutvision" },\r
+ { "kar", "audio/midi" },\r
+ { "kar", "music/x-karaoke" },\r
+ { "ksh", "application/x-ksh" },\r
+ { "ksh", "text/x-script.ksh" },\r
+ { "la", "audio/nspaudio" },\r
+ { "la", "audio/x-nspaudio" },\r
+ { "lam", "audio/x-liveaudio" },\r
+ { "latex", "application/x-latex" },\r
+ { "lha", "application/lha" },\r
+ { "lha", "application/octet-stream" },\r
+ { "lha", "application/x-lha" },\r
+ { "lhx", "application/octet-stream" },\r
+ { "list", "text/plain" },\r
+ { "lma", "audio/nspaudio" },\r
+ { "lma", "audio/x-nspaudio" },\r
+ { "log", "text/plain" },\r
+ { "lsp", "application/x-lisp" },\r
+ { "lsp", "text/x-script.lisp" },\r
+ { "lst", "text/plain" },\r
+ { "lsx", "text/x-la-asf" },\r
+ { "ltx", "application/x-latex" },\r
+ { "lzh", "application/octet-stream" },\r
+ { "lzh", "application/x-lzh" },\r
+ { "lzx", "application/lzx" },\r
+ { "lzx", "application/octet-stream" },\r
+ { "lzx", "application/x-lzx" },\r
+ { "m", "text/plain" },\r
+ { "m", "text/x-m" },\r
+ { "m1v", "video/mpeg" },\r
+ { "m2a", "audio/mpeg" },\r
+ { "m2v", "video/mpeg" },\r
+ { "m3u", "audio/x-mpequrl" },\r
+ { "man", "application/x-troff-man" },\r
+ { "map", "application/x-navimap" },\r
+ { "mar", "text/plain" },\r
+ { "mbd", "application/mbedlet" },\r
+ { "mc$", "application/x-magic-cap-package-1.0" },\r
+ { "mcd", "application/mcad" },\r
+ { "mcd", "application/x-mathcad" },\r
+ { "mcf", "image/vasa" },\r
+ { "mcf", "text/mcf" },\r
+ { "mcp", "application/netmc" },\r
+ { "me", "application/x-troff-me" },\r
+ { "mht", "message/rfc822" },\r
+ { "mhtml", "message/rfc822" },\r
+ { "mid", "application/x-midi" },\r
+ { "mid", "audio/midi" },\r
+ { "mid", "audio/x-mid" },\r
+ { "mid", "audio/x-midi" },\r
+ { "mid", "music/crescendo" },\r
+ { "mid", "x-music/x-midi" },\r
+ { "midi", "application/x-midi" },\r
+ { "midi", "audio/midi" },\r
+ { "midi", "audio/x-mid" },\r
+ { "midi", "audio/x-midi" },\r
+ { "midi", "music/crescendo" },\r
+ { "midi", "x-music/x-midi" },\r
+ { "mif", "application/x-frame" },\r
+ { "mif", "application/x-mif" },\r
+ { "mime", "message/rfc822" },\r
+ { "mime", "www/mime" },\r
+ { "mjf", "audio/x-vnd.audioexplosion.mjuicemediafile" },\r
+ { "mjpg", "video/x-motion-jpeg" },\r
+ { "mm", "application/base64" },\r
+ { "mm", "application/x-meme" },\r
+ { "mme", "application/base64" },\r
+ { "mod", "audio/mod" },\r
+ { "mod", "audio/x-mod" },\r
+ { "moov", "video/quicktime" },\r
+ { "mov", "video/quicktime" },\r
+ { "movie", "video/x-sgi-movie" },\r
+ { "mp2", "audio/mpeg" },\r
+ { "mp2", "audio/x-mpeg" },\r
+ { "mp2", "video/mpeg" },\r
+ { "mp2", "video/x-mpeg" },\r
+ { "mp2", "video/x-mpeq2a" },\r
+ { "mp3", "audio/mpeg" },\r
+ { "mp3", "audio/mpeg3" },\r
+ { "mp3", "audio/x-mpeg-3" },\r
+ { "mp3", "video/mpeg" },\r
+ { "mp3", "video/x-mpeg" },\r
+ { "mpa", "audio/mpeg" },\r
+ { "mpa", "video/mpeg" },\r
+ { "mpc", "application/x-project" },\r
+ { "mpe", "video/mpeg" },\r
+ { "mpeg", "video/mpeg" },\r
+ { "mpg", "audio/mpeg" },\r
+ { "mpg", "video/mpeg" },\r
+ { "mpga", "audio/mpeg" },\r
+ { "mpp", "application/vnd.ms-project" },\r
+ { "mpt", "application/x-project" },\r
+ { "mpv", "application/x-project" },\r
+ { "mpx", "application/x-project" },\r
+ { "mrc", "application/marc" },\r
+ { "ms", "application/x-troff-ms" },\r
+ { "mv", "video/x-sgi-movie" },\r
+ { "my", "audio/make" },\r
+ { "mzz", "application/x-vnd.audioexplosion.mzz" },\r
+ { "nap", "image/naplps" },\r
+ { "naplps", "image/naplps" },\r
+ { "nc", "application/x-netcdf" },\r
+ { "ncm", "application/vnd.nokia.configuration-message" },\r
+ { "nif", "image/x-niff" },\r
+ { "niff", "image/x-niff" },\r
+ { "nix", "application/x-mix-transfer" },\r
+ { "nsc", "application/x-conference" },\r
+ { "nvd", "application/x-navidoc" },\r
+ { "o", "application/octet-stream" },\r
+ { "oda", "application/oda" },\r
+ { "omc", "application/x-omc" },\r
+ { "omcd", "application/x-omcdatamaker" },\r
+ { "omcr", "application/x-omcregerator" },\r
+ { "p", "text/x-pascal" },\r
+ { "p10", "application/pkcs10" },\r
+ { "p10", "application/x-pkcs10" },\r
+ { "p12", "application/pkcs-12" },\r
+ { "p12", "application/x-pkcs12" },\r
+ { "p7a", "application/x-pkcs7-signature" },\r
+ { "p7c", "application/pkcs7-mime" },\r
+ { "p7c", "application/x-pkcs7-mime" },\r
+ { "p7m", "application/pkcs7-mime" },\r
+ { "p7m", "application/x-pkcs7-mime" },\r
+ { "p7r", "application/x-pkcs7-certreqresp" },\r
+ { "p7s", "application/pkcs7-signature" },\r
+ { "part", "application/pro_eng" },\r
+ { "pas", "text/pascal" },\r
+ { "pbm", "image/x-portable-bitmap" },\r
+ { "pcl", "application/vnd.hp-pcl" },\r
+ { "pcl", "application/x-pcl" },\r
+ { "pct", "image/x-pict" },\r
+ { "pcx", "image/x-pcx" },\r
+ { "pdb", "chemical/x-pdb" },\r
+ { "pdf", "application/pdf" },\r
+ { "pfunk", "audio/make" },\r
+ { "pfunk", "audio/make.my.funk" },\r
+ { "pgm", "image/x-portable-graymap" },\r
+ { "pgm", "image/x-portable-greymap" },\r
+ { "pic", "image/pict" },\r
+ { "pict", "image/pict" },\r
+ { "pkg", "application/x-newton-compatible-pkg" },\r
+ { "pko", "application/vnd.ms-pki.pko" },\r
+ { "pl", "text/plain" },\r
+ { "pl", "text/x-script.perl" },\r
+ { "plx", "application/x-pixclscript" },\r
+ { "pm", "image/x-xpixmap" },\r
+ { "pm", "text/x-script.perl-module" },\r
+ { "pm4", "application/x-pagemaker" },\r
+ { "pm5", "application/x-pagemaker" },\r
+ { "png", "image/png" },\r
+ { "pnm", "application/x-portable-anymap" },\r
+ { "pnm", "image/x-portable-anymap" },\r
+ { "pot", "application/mspowerpoint" },\r
+ { "pot", "application/vnd.ms-powerpoint" },\r
+ { "pov", "model/x-pov" },\r
+ { "ppa", "application/vnd.ms-powerpoint" },\r
+ { "ppm", "image/x-portable-pixmap" },\r
+ { "pps", "application/mspowerpoint" },\r
+ { "pps", "application/vnd.ms-powerpoint" },\r
+ { "ppt", "application/mspowerpoint" },\r
+ { "ppt", "application/powerpoint" },\r
+ { "ppt", "application/vnd.ms-powerpoint" },\r
+ { "ppt", "application/x-mspowerpoint" },\r
+ { "ppz", "application/mspowerpoint" },\r
+ { "pre", "application/x-freelance" },\r
+ { "prt", "application/pro_eng" },\r
+ { "ps", "application/postscript" },\r
+ { "psd", "application/octet-stream" },\r
+ { "pvu", "paleovu/x-pv" },\r
+ { "pwz", "application/vnd.ms-powerpoint" },\r
+ { "py", "text/x-script.python" },\r
+ { "pyc", "application/x-bytecode.python" },\r
+ { "qcp", "audio/vnd.qcelp" },\r
+ { "qd3", "x-world/x-3dmf" },\r
+ { "qd3d", "x-world/x-3dmf" },\r
+ { "qif", "image/x-quicktime" },\r
+ { "qt", "video/quicktime" },\r
+ { "qtc", "video/x-qtc" },\r
+ { "qti", "image/x-quicktime" },\r
+ { "qtif", "image/x-quicktime" },\r
+ { "ra", "audio/x-pn-realaudio" },\r
+ { "ra", "audio/x-pn-realaudio-plugin" },\r
+ { "ra", "audio/x-realaudio" },\r
+ { "ram", "audio/x-pn-realaudio" },\r
+ { "ras", "application/x-cmu-raster" },\r
+ { "ras", "image/cmu-raster" },\r
+ { "ras", "image/x-cmu-raster" },\r
+ { "rast", "image/cmu-raster" },\r
+ { "rexx", "text/x-script.rexx" },\r
+ { "rf", "image/vnd.rn-realflash" },\r
+ { "rgb", "image/x-rgb" },\r
+ { "rm", "application/vnd.rn-realmedia" },\r
+ { "rm", "audio/x-pn-realaudio" },\r
+ { "rmi", "audio/mid" },\r
+ { "rmm", "audio/x-pn-realaudio" },\r
+ { "rmp", "audio/x-pn-realaudio" },\r
+ { "rmp", "audio/x-pn-realaudio-plugin" },\r
+ { "rng", "application/ringing-tones" },\r
+ { "rng", "application/vnd.nokia.ringing-tone" },\r
+ { "rnx", "application/vnd.rn-realplayer" },\r
+ { "roff", "application/x-troff" },\r
+ { "rp", "image/vnd.rn-realpix" },\r
+ { "rpm", "audio/x-pn-realaudio-plugin" },\r
+ { "rt", "text/richtext" },\r
+ { "rt", "text/vnd.rn-realtext" },\r
+ { "rtf", "application/rtf" },\r
+ { "rtf", "application/x-rtf" },\r
+ { "rtf", "text/richtext" },\r
+ { "rtx", "application/rtf" },\r
+ { "rtx", "text/richtext" },\r
+ { "rv", "video/vnd.rn-realvideo" },\r
+ { "s", "text/x-asm" },\r
+ { "s3m", "audio/s3m" },\r
+ { "saveme", "application/octet-stream" },\r
+ { "sbk", "application/x-tbook" },\r
+ { "scm", "application/x-lotusscreencam" },\r
+ { "scm", "text/x-script.guile" },\r
+ { "scm", "text/x-script.scheme" },\r
+ { "scm", "video/x-scm" },\r
+ { "sdml", "text/plain" },\r
+ { "sdp", "application/sdp" },\r
+ { "sdp", "application/x-sdp" },\r
+ { "sdr", "application/sounder" },\r
+ { "sea", "application/sea" },\r
+ { "sea", "application/x-sea" },\r
+ { "set", "application/set" },\r
+ { "sgm", "text/sgml" },\r
+ { "sgm", "text/x-sgml" },\r
+ { "sgml", "text/sgml" },\r
+ { "sgml", "text/x-sgml" },\r
+ { "sh", "application/x-bsh" },\r
+ { "sh", "application/x-sh" },\r
+ { "sh", "application/x-shar" },\r
+ { "sh", "text/x-script.sh" },\r
+ { "shar", "application/x-bsh" },\r
+ { "shar", "application/x-shar" },\r
+ { "shtml", "text/html" },\r
+ { "shtml", "text/x-server-parsed-html" },\r
+ { "sid", "audio/x-psid" },\r
+ { "sit", "application/x-sit" },\r
+ { "sit", "application/x-stuffit" },\r
+ { "skd", "application/x-koan" },\r
+ { "skm", "application/x-koan" },\r
+ { "skp", "application/x-koan" },\r
+ { "skt", "application/x-koan" },\r
+ { "sl", "application/x-seelogo" },\r
+ { "smi", "application/smil" },\r
+ { "smil", "application/smil" },\r
+ { "snd", "audio/basic" },\r
+ { "snd", "audio/x-adpcm" },\r
+ { "sol", "application/solids" },\r
+ { "spc", "application/x-pkcs7-certificates" },\r
+ { "spc", "text/x-speech" },\r
+ { "spl", "application/futuresplash" },\r
+ { "spr", "application/x-sprite" },\r
+ { "sprite", "application/x-sprite" },\r
+ { "src", "application/x-wais-source" },\r
+ { "ssi", "text/x-server-parsed-html" },\r
+ { "ssm", "application/streamingmedia" },\r
+ { "sst", "application/vnd.ms-pki.certstore" },\r
+ { "step", "application/step" },\r
+ { "stl", "application/sla" },\r
+ { "stl", "application/vnd.ms-pki.stl" },\r
+ { "stl", "application/x-navistyle" },\r
+ { "stp", "application/step" },\r
+ { "sv4cpio,", "application/x-sv4cpio" },\r
+ { "sv4crc", "application/x-sv4crc" },\r
+ { "svf", "image/vnd.dwg" },\r
+ { "svf", "image/x-dwg" },\r
+ { "svr", "application/x-world" },\r
+ { "svr", "x-world/x-svr" },\r
+ { "swf", "application/x-shockwave-flash" },\r
+ { "t", "application/x-troff" },\r
+ { "talk", "text/x-speech" },\r
+ { "tar", "application/x-tar" },\r
+ { "tbk", "application/toolbook" },\r
+ { "tbk", "application/x-tbook" },\r
+ { "tcl", "application/x-tcl" },\r
+ { "tcl", "text/x-script.tcl" },\r
+ { "tcsh", "text/x-script.tcsh" },\r
+ { "tex", "application/x-tex" },\r
+ { "texi", "application/x-texinfo" },\r
+ { "texinfo,", "application/x-texinfo" },\r
+ { "text", "application/plain" },\r
+ { "text", "text/plain" },\r
+ { "tgz", "application/gnutar" },\r
+ { "tgz", "application/x-compressed" },\r
+ { "tif", "image/tiff" },\r
+ { "tif", "image/x-tiff" },\r
+ { "tiff", "image/tiff" },\r
+ { "tiff", "image/x-tiff" },\r
+ { "tr", "application/x-troff" },\r
+ { "tsi", "audio/tsp-audio" },\r
+ { "tsp", "application/dsptype" },\r
+ { "tsp", "audio/tsplayer" },\r
+ { "tsv", "text/tab-separated-values" },\r
+ { "turbot", "image/florian" },\r
+ { "txt", "text/plain" },\r
+ { "uil", "text/x-uil" },\r
+ { "uni", "text/uri-list" },\r
+ { "unis", "text/uri-list" },\r
+ { "unv", "application/i-deas" },\r
+ { "uri", "text/uri-list" },\r
+ { "uris", "text/uri-list" },\r
+ { "ustar", "application/x-ustar" },\r
+ { "ustar", "multipart/x-ustar" },\r
+ { "uu", "application/octet-stream" },\r
+ { "uu", "text/x-uuencode" },\r
+ { "uue", "text/x-uuencode" },\r
+ { "vcd", "application/x-cdlink" },\r
+ { "vcs", "text/x-vcalendar" },\r
+ { "vda", "application/vda" },\r
+ { "vdo", "video/vdo" },\r
+ { "vew", "application/groupwise" },\r
+ { "viv", "video/vivo" },\r
+ { "viv", "video/vnd.vivo" },\r
+ { "vivo", "video/vivo" },\r
+ { "vivo", "video/vnd.vivo" },\r
+ { "vmd", "application/vocaltec-media-desc" },\r
+ { "vmf", "application/vocaltec-media-file" },\r
+ { "voc", "audio/voc" },\r
+ { "voc", "audio/x-voc" },\r
+ { "vos", "video/vosaic" },\r
+ { "vox", "audio/voxware" },\r
+ { "vqe", "audio/x-twinvq-plugin" },\r
+ { "vqf", "audio/x-twinvq" },\r
+ { "vql", "audio/x-twinvq-plugin" },\r
+ { "vrml", "application/x-vrml" },\r
+ { "vrml", "model/vrml" },\r
+ { "vrml", "x-world/x-vrml" },\r
+ { "vrt", "x-world/x-vrt" },\r
+ { "vsd", "application/x-visio" },\r
+ { "vst", "application/x-visio" },\r
+ { "vsw", "application/x-visio" },\r
+ { "w60", "application/wordperfect6.0" },\r
+ { "w61", "application/wordperfect6.1" },\r
+ { "w6w", "application/msword" },\r
+ { "wav", "audio/wav" },\r
+ { "wav", "audio/x-wav" },\r
+ { "wb1", "application/x-qpro" },\r
+ { "wbmp", "image/vnd.wap.wbmp" },\r
+ { "web", "application/vnd.xara" },\r
+ { "wiz", "application/msword" },\r
+ { "wk1", "application/x-123" },\r
+ { "wmf", "windows/metafile" },\r
+ { "wml", "text/vnd.wap.wml" },\r
+ { "wmlc", "application/vnd.wap.wmlc" },\r
+ { "wmls", "text/vnd.wap.wmlscript" },\r
+ { "wmlsc", "application/vnd.wap.wmlscriptc" },\r
+ { "word", "application/msword" },\r
+ { "wp", "application/wordperfect" },\r
+ { "wp5", "application/wordperfect" },\r
+ { "wp5", "application/wordperfect6.0" },\r
+ { "wp6", "application/wordperfect" },\r
+ { "wpd", "application/wordperfect" },\r
+ { "wpd", "application/x-wpwin" },\r
+ { "wq1", "application/x-lotus" },\r
+ { "wri", "application/mswrite" },\r
+ { "wri", "application/x-wri" },\r
+ { "wrl", "application/x-world" },\r
+ { "wrl", "model/vrml" },\r
+ { "wrl", "x-world/x-vrml" },\r
+ { "wrz", "model/vrml" },\r
+ { "wrz", "x-world/x-vrml" },\r
+ { "wsc", "text/scriplet" },\r
+ { "wsrc", "application/x-wais-source" },\r
+ { "wtk", "application/x-wintalk" },\r
+ { "xbm", "image/x-xbitmap" },\r
+ { "xbm", "image/x-xbm" },\r
+ { "xbm", "image/xbm" },\r
+ { "xdr", "video/x-amt-demorun" },\r
+ { "xgz", "xgl/drawing" },\r
+ { "xif", "image/vnd.xiff" },\r
+ { "xl", "application/excel" },\r
+ { "xla", "application/excel" },\r
+ { "xla", "application/x-excel" },\r
+ { "xla", "application/x-msexcel" },\r
+ { "xlb", "application/excel" },\r
+ { "xlb", "application/vnd.ms-excel" },\r
+ { "xlb", "application/x-excel" },\r
+ { "xlc", "application/excel" },\r
+ { "xlc", "application/vnd.ms-excel" },\r
+ { "xlc", "application/x-excel" },\r
+ { "xld", "application/excel" },\r
+ { "xld", "application/x-excel" },\r
+ { "xlk", "application/excel" },\r
+ { "xlk", "application/x-excel" },\r
+ { "xll", "application/excel" },\r
+ { "xll", "application/vnd.ms-excel" },\r
+ { "xll", "application/x-excel" },\r
+ { "xlm", "application/excel" },\r
+ { "xlm", "application/vnd.ms-excel" },\r
+ { "xlm", "application/x-excel" },\r
+ { "xls", "application/excel" },\r
+ { "xls", "application/vnd.ms-excel" },\r
+ { "xls", "application/x-excel" },\r
+ { "xls", "application/x-msexcel" },\r
+ { "xlt", "application/excel" },\r
+ { "xlt", "application/x-excel" },\r
+ { "xlv", "application/excel" },\r
+ { "xlv", "application/x-excel" },\r
+ { "xlw", "application/excel" },\r
+ { "xlw", "application/vnd.ms-excel" },\r
+ { "xlw", "application/x-excel" },\r
+ { "xlw", "application/x-msexcel" },\r
+ { "xm", "audio/xm" },\r
+ { "xml", "application/xml" },\r
+ { "xml", "text/xml" },\r
+ { "xmz", "xgl/movie" },\r
+ { "xpix", "application/x-vnd.ls-xpix" },\r
+ { "xpm", "image/x-xpixmap" },\r
+ { "xpm", "image/xpm" },\r
+ { "x-png", "image/png" },\r
+ { "xsr", "video/x-amt-showrun" },\r
+ { "xwd", "image/x-xwd" },\r
+ { "xwd", "image/x-xwindowdump" },\r
+ { "xyz", "chemical/x-pdb" },\r
+ { "z", "application/x-compress" },\r
+ { "z", "application/x-compressed" },\r
+ { "zip", "application/x-compressed" },\r
+ { "zip", "application/x-zip-compressed" },\r
+ { "zip", "application/zip" },\r
+ { "zip", "multipart/x-zip" },\r
+ { "zoo", "application/octet-stream" },\r
+ };\r
+\r
+ template <typename EntryToPair>\r
+ static std::multimap<String, String> createMultiMap (EntryToPair&& entryToPair)\r
+ {\r
+ std::pair<const char*, const char*> transformed[std::size (initialEntries)];\r
+ std::transform (std::begin (initialEntries),\r
+ std::end (initialEntries),\r
+ std::begin (transformed),\r
+ entryToPair);\r
\r
-StringArray getMimeTypesForFileExtension (const String& fileExtension)\r
+ return { std::begin (transformed),\r
+ std::end (transformed) };\r
+ }\r
+\r
+ std::multimap<String, String> typeForExtension = createMultiMap ([] (auto e)\r
+ {\r
+ return std::make_pair (e.fileExtension, e.mimeType);\r
+ });\r
+\r
+ std::multimap<String, String> extensionForType = createMultiMap ([] (auto e)\r
+ {\r
+ return std::make_pair (e.mimeType, e.fileExtension);\r
+ });\r
+};\r
+\r
+} // namespace\r
+\r
+void MimeTypeTable::registerCustomMimeTypeForFileExtension (const String& mimeType, const String& fileExtension)\r
{\r
- return getMatches (fileExtension, &MimeTypeTableEntry::fileExtension, &MimeTypeTableEntry::mimeType);\r
+ Table::get().addEntry ({ fileExtension.toRawUTF8(), mimeType.toRawUTF8() });\r
}\r
\r
-StringArray getFileExtensionsForMimeType (const String& mimeType)\r
+StringArray MimeTypeTable::getMimeTypesForFileExtension (const String& fileExtension)\r
{\r
- return getMatches (mimeType, &MimeTypeTableEntry::mimeType, &MimeTypeTableEntry::fileExtension);\r
+ return Table::get().getTypesForExtension (fileExtension);\r
}\r
\r
-} // namespace MimeTypeTable\r
-\r
-//==============================================================================\r
-MimeTypeTableEntry MimeTypeTableEntry::table[641] =\r
+StringArray MimeTypeTable::getFileExtensionsForMimeType (const String& mimeType)\r
{\r
- {"3dm", "x-world/x-3dmf"},\r
- {"3dmf", "x-world/x-3dmf"},\r
- {"a", "application/octet-stream"},\r
- {"aab", "application/x-authorware-bin"},\r
- {"aam", "application/x-authorware-map"},\r
- {"aas", "application/x-authorware-seg"},\r
- {"abc", "text/vnd.abc"},\r
- {"acgi", "text/html"},\r
- {"afl", "video/animaflex"},\r
- {"ai", "application/postscript"},\r
- {"aif", "audio/aiff"},\r
- {"aif", "audio/x-aiff"},\r
- {"aifc", "audio/aiff"},\r
- {"aifc", "audio/x-aiff"},\r
- {"aiff", "audio/aiff"},\r
- {"aiff", "audio/x-aiff"},\r
- {"aim", "application/x-aim"},\r
- {"aip", "text/x-audiosoft-intra"},\r
- {"ani", "application/x-navi-animation"},\r
- {"aos", "application/x-nokia-9000-communicator-add-on-software"},\r
- {"aps", "application/mime"},\r
- {"arc", "application/octet-stream"},\r
- {"arj", "application/arj"},\r
- {"arj", "application/octet-stream"},\r
- {"art", "image/x-jg"},\r
- {"asf", "video/x-ms-asf"},\r
- {"asm", "text/x-asm"},\r
- {"asp", "text/asp"},\r
- {"asx", "application/x-mplayer2"},\r
- {"asx", "video/x-ms-asf"},\r
- {"asx", "video/x-ms-asf-plugin"},\r
- {"au", "audio/basic"},\r
- {"au", "audio/x-au"},\r
- {"avi", "application/x-troff-msvideo"},\r
- {"avi", "video/avi"},\r
- {"avi", "video/msvideo"},\r
- {"avi", "video/x-msvideo"},\r
- {"avs", "video/avs-video"},\r
- {"bcpio", "application/x-bcpio"},\r
- {"bin", "application/mac-binary"},\r
- {"bin", "application/macbinary"},\r
- {"bin", "application/octet-stream"},\r
- {"bin", "application/x-binary"},\r
- {"bin", "application/x-macbinary"},\r
- {"bm", "image/bmp"},\r
- {"bmp", "image/bmp"},\r
- {"bmp", "image/x-windows-bmp"},\r
- {"boo", "application/book"},\r
- {"book", "application/book"},\r
- {"boz", "application/x-bzip2"},\r
- {"bsh", "application/x-bsh"},\r
- {"bz", "application/x-bzip"},\r
- {"bz2", "application/x-bzip2"},\r
- {"c", "text/plain"},\r
- {"c", "text/x-c"},\r
- {"c++", "text/plain"},\r
- {"cat", "application/vnd.ms-pki.seccat"},\r
- {"cc", "text/plain"},\r
- {"cc", "text/x-c"},\r
- {"ccad", "application/clariscad"},\r
- {"cco", "application/x-cocoa"},\r
- {"cdf", "application/cdf"},\r
- {"cdf", "application/x-cdf"},\r
- {"cdf", "application/x-netcdf"},\r
- {"cer", "application/pkix-cert"},\r
- {"cer", "application/x-x509-ca-cert"},\r
- {"cha", "application/x-chat"},\r
- {"chat", "application/x-chat"},\r
- {"class", "application/java"},\r
- {"class", "application/java-byte-code"},\r
- {"class", "application/x-java-class"},\r
- {"com", "application/octet-stream"},\r
- {"com", "text/plain"},\r
- {"conf", "text/plain"},\r
- {"cpio", "application/x-cpio"},\r
- {"cpp", "text/x-c"},\r
- {"cpt", "application/mac-compactpro"},\r
- {"cpt", "application/x-compactpro"},\r
- {"cpt", "application/x-cpt"},\r
- {"crl", "application/pkcs-crl"},\r
- {"crl", "application/pkix-crl"},\r
- {"crt", "application/pkix-cert"},\r
- {"crt", "application/x-x509-ca-cert"},\r
- {"crt", "application/x-x509-user-cert"},\r
- {"csh", "application/x-csh"},\r
- {"csh", "text/x-script.csh"},\r
- {"css", "application/x-pointplus"},\r
- {"css", "text/css"},\r
- {"cxx", "text/plain"},\r
- {"dcr", "application/x-director"},\r
- {"deepv", "application/x-deepv"},\r
- {"def", "text/plain"},\r
- {"der", "application/x-x509-ca-cert"},\r
- {"dif", "video/x-dv"},\r
- {"dir", "application/x-director"},\r
- {"dl", "video/dl"},\r
- {"dl", "video/x-dl"},\r
- {"doc", "application/msword"},\r
- {"dot", "application/msword"},\r
- {"dp", "application/commonground"},\r
- {"drw", "application/drafting"},\r
- {"dump", "application/octet-stream"},\r
- {"dv", "video/x-dv"},\r
- {"dvi", "application/x-dvi"},\r
- {"dwf", "drawing/x-dwf"},\r
- {"dwf", "model/vnd.dwf"},\r
- {"dwg", "application/acad"},\r
- {"dwg", "image/vnd.dwg"},\r
- {"dwg", "image/x-dwg"},\r
- {"dxf", "application/dxf"},\r
- {"dxf", "image/vnd.dwg"},\r
- {"dxf", "image/x-dwg"},\r
- {"dxr", "application/x-director"},\r
- {"el", "text/x-script.elisp"},\r
- {"elc", "application/x-bytecode.elisp"},\r
- {"elc", "application/x-elc"},\r
- {"env", "application/x-envoy"},\r
- {"eps", "application/postscript"},\r
- {"es", "application/x-esrehber"},\r
- {"etx", "text/x-setext"},\r
- {"evy", "application/envoy"},\r
- {"evy", "application/x-envoy"},\r
- {"exe", "application/octet-stream"},\r
- {"f", "text/plain"},\r
- {"f", "text/x-fortran"},\r
- {"f77", "text/x-fortran"},\r
- {"f90", "text/plain"},\r
- {"f90", "text/x-fortran"},\r
- {"fdf", "application/vnd.fdf"},\r
- {"fif", "application/fractals"},\r
- {"fif", "image/fif"},\r
- {"fli", "video/fli"},\r
- {"fli", "video/x-fli"},\r
- {"flo", "image/florian"},\r
- {"flx", "text/vnd.fmi.flexstor"},\r
- {"fmf", "video/x-atomic3d-feature"},\r
- {"for", "text/plain"},\r
- {"for", "text/x-fortran"},\r
- {"fpx", "image/vnd.fpx"},\r
- {"fpx", "image/vnd.net-fpx"},\r
- {"frl", "application/freeloader"},\r
- {"funk", "audio/make"},\r
- {"g", "text/plain"},\r
- {"g3", "image/g3fax"},\r
- {"gif", "image/gif"},\r
- {"gl", "video/gl"},\r
- {"gl", "video/x-gl"},\r
- {"gsd", "audio/x-gsm"},\r
- {"gsm", "audio/x-gsm"},\r
- {"gsp", "application/x-gsp"},\r
- {"gss", "application/x-gss"},\r
- {"gtar", "application/x-gtar"},\r
- {"gz", "application/x-compressed"},\r
- {"gz", "application/x-gzip"},\r
- {"gzip", "application/x-gzip"},\r
- {"gzip", "multipart/x-gzip"},\r
- {"h", "text/plain"},\r
- {"h", "text/x-h"},\r
- {"hdf", "application/x-hdf"},\r
- {"help", "application/x-helpfile"},\r
- {"hgl", "application/vnd.hp-hpgl"},\r
- {"hh", "text/plain"},\r
- {"hh", "text/x-h"},\r
- {"hlb", "text/x-script"},\r
- {"hlp", "application/hlp"},\r
- {"hlp", "application/x-helpfile"},\r
- {"hlp", "application/x-winhelp"},\r
- {"hpg", "application/vnd.hp-hpgl"},\r
- {"hpgl", "application/vnd.hp-hpgl"},\r
- {"hqx", "application/binhex"},\r
- {"hqx", "application/binhex4"},\r
- {"hqx", "application/mac-binhex"},\r
- {"hqx", "application/mac-binhex40"},\r
- {"hqx", "application/x-binhex40"},\r
- {"hqx", "application/x-mac-binhex40"},\r
- {"hta", "application/hta"},\r
- {"htc", "text/x-component"},\r
- {"htm", "text/html"},\r
- {"html", "text/html"},\r
- {"htmls", "text/html"},\r
- {"htt", "text/webviewhtml"},\r
- {"htx", "text/html"},\r
- {"ice", "x-conference/x-cooltalk"},\r
- {"ico", "image/x-icon"},\r
- {"idc", "text/plain"},\r
- {"ief", "image/ief"},\r
- {"iefs", "image/ief"},\r
- {"iges", "application/iges"},\r
- {"iges", "model/iges"},\r
- {"igs", "application/iges"},\r
- {"igs", "model/iges"},\r
- {"ima", "application/x-ima"},\r
- {"imap", "application/x-httpd-imap"},\r
- {"inf", "application/inf"},\r
- {"ins", "application/x-internett-signup"},\r
- {"ip", "application/x-ip2"},\r
- {"isu", "video/x-isvideo"},\r
- {"it", "audio/it"},\r
- {"iv", "application/x-inventor"},\r
- {"ivr", "i-world/i-vrml"},\r
- {"ivy", "application/x-livescreen"},\r
- {"jam", "audio/x-jam"},\r
- {"jav", "text/plain"},\r
- {"jav", "text/x-java-source"},\r
- {"java", "text/plain"},\r
- {"java", "text/x-java-source"},\r
- {"jcm", "application/x-java-commerce"},\r
- {"jfif", "image/jpeg"},\r
- {"jfif", "image/pjpeg"},\r
- {"jpe", "image/jpeg"},\r
- {"jpe", "image/pjpeg"},\r
- {"jpeg", "image/jpeg"},\r
- {"jpeg", "image/pjpeg"},\r
- {"jpg", "image/jpeg"},\r
- {"jpg", "image/pjpeg"},\r
- {"jps", "image/x-jps"},\r
- {"js", "application/x-javascript"},\r
- {"jut", "image/jutvision"},\r
- {"kar", "audio/midi"},\r
- {"kar", "music/x-karaoke"},\r
- {"ksh", "application/x-ksh"},\r
- {"ksh", "text/x-script.ksh"},\r
- {"la", "audio/nspaudio"},\r
- {"la", "audio/x-nspaudio"},\r
- {"lam", "audio/x-liveaudio"},\r
- {"latex", "application/x-latex"},\r
- {"lha", "application/lha"},\r
- {"lha", "application/octet-stream"},\r
- {"lha", "application/x-lha"},\r
- {"lhx", "application/octet-stream"},\r
- {"list", "text/plain"},\r
- {"lma", "audio/nspaudio"},\r
- {"lma", "audio/x-nspaudio"},\r
- {"log", "text/plain"},\r
- {"lsp", "application/x-lisp"},\r
- {"lsp", "text/x-script.lisp"},\r
- {"lst", "text/plain"},\r
- {"lsx", "text/x-la-asf"},\r
- {"ltx", "application/x-latex"},\r
- {"lzh", "application/octet-stream"},\r
- {"lzh", "application/x-lzh"},\r
- {"lzx", "application/lzx"},\r
- {"lzx", "application/octet-stream"},\r
- {"lzx", "application/x-lzx"},\r
- {"m", "text/plain"},\r
- {"m", "text/x-m"},\r
- {"m1v", "video/mpeg"},\r
- {"m2a", "audio/mpeg"},\r
- {"m2v", "video/mpeg"},\r
- {"m3u", "audio/x-mpequrl"},\r
- {"man", "application/x-troff-man"},\r
- {"map", "application/x-navimap"},\r
- {"mar", "text/plain"},\r
- {"mbd", "application/mbedlet"},\r
- {"mc$", "application/x-magic-cap-package-1.0"},\r
- {"mcd", "application/mcad"},\r
- {"mcd", "application/x-mathcad"},\r
- {"mcf", "image/vasa"},\r
- {"mcf", "text/mcf"},\r
- {"mcp", "application/netmc"},\r
- {"me", "application/x-troff-me"},\r
- {"mht", "message/rfc822"},\r
- {"mhtml", "message/rfc822"},\r
- {"mid", "application/x-midi"},\r
- {"mid", "audio/midi"},\r
- {"mid", "audio/x-mid"},\r
- {"mid", "audio/x-midi"},\r
- {"mid", "music/crescendo"},\r
- {"mid", "x-music/x-midi"},\r
- {"midi", "application/x-midi"},\r
- {"midi", "audio/midi"},\r
- {"midi", "audio/x-mid"},\r
- {"midi", "audio/x-midi"},\r
- {"midi", "music/crescendo"},\r
- {"midi", "x-music/x-midi"},\r
- {"mif", "application/x-frame"},\r
- {"mif", "application/x-mif"},\r
- {"mime", "message/rfc822"},\r
- {"mime", "www/mime"},\r
- {"mjf", "audio/x-vnd.audioexplosion.mjuicemediafile"},\r
- {"mjpg", "video/x-motion-jpeg"},\r
- {"mm", "application/base64"},\r
- {"mm", "application/x-meme"},\r
- {"mme", "application/base64"},\r
- {"mod", "audio/mod"},\r
- {"mod", "audio/x-mod"},\r
- {"moov", "video/quicktime"},\r
- {"mov", "video/quicktime"},\r
- {"movie", "video/x-sgi-movie"},\r
- {"mp2", "audio/mpeg"},\r
- {"mp2", "audio/x-mpeg"},\r
- {"mp2", "video/mpeg"},\r
- {"mp2", "video/x-mpeg"},\r
- {"mp2", "video/x-mpeq2a"},\r
- {"mp3", "audio/mpeg"},\r
- {"mp3", "audio/mpeg3"},\r
- {"mp3", "audio/x-mpeg-3"},\r
- {"mp3", "video/mpeg"},\r
- {"mp3", "video/x-mpeg"},\r
- {"mpa", "audio/mpeg"},\r
- {"mpa", "video/mpeg"},\r
- {"mpc", "application/x-project"},\r
- {"mpe", "video/mpeg"},\r
- {"mpeg", "video/mpeg"},\r
- {"mpg", "audio/mpeg"},\r
- {"mpg", "video/mpeg"},\r
- {"mpga", "audio/mpeg"},\r
- {"mpp", "application/vnd.ms-project"},\r
- {"mpt", "application/x-project"},\r
- {"mpv", "application/x-project"},\r
- {"mpx", "application/x-project"},\r
- {"mrc", "application/marc"},\r
- {"ms", "application/x-troff-ms"},\r
- {"mv", "video/x-sgi-movie"},\r
- {"my", "audio/make"},\r
- {"mzz", "application/x-vnd.audioexplosion.mzz"},\r
- {"nap", "image/naplps"},\r
- {"naplps", "image/naplps"},\r
- {"nc", "application/x-netcdf"},\r
- {"ncm", "application/vnd.nokia.configuration-message"},\r
- {"nif", "image/x-niff"},\r
- {"niff", "image/x-niff"},\r
- {"nix", "application/x-mix-transfer"},\r
- {"nsc", "application/x-conference"},\r
- {"nvd", "application/x-navidoc"},\r
- {"o", "application/octet-stream"},\r
- {"oda", "application/oda"},\r
- {"omc", "application/x-omc"},\r
- {"omcd", "application/x-omcdatamaker"},\r
- {"omcr", "application/x-omcregerator"},\r
- {"p", "text/x-pascal"},\r
- {"p10", "application/pkcs10"},\r
- {"p10", "application/x-pkcs10"},\r
- {"p12", "application/pkcs-12"},\r
- {"p12", "application/x-pkcs12"},\r
- {"p7a", "application/x-pkcs7-signature"},\r
- {"p7c", "application/pkcs7-mime"},\r
- {"p7c", "application/x-pkcs7-mime"},\r
- {"p7m", "application/pkcs7-mime"},\r
- {"p7m", "application/x-pkcs7-mime"},\r
- {"p7r", "application/x-pkcs7-certreqresp"},\r
- {"p7s", "application/pkcs7-signature"},\r
- {"part", "application/pro_eng"},\r
- {"pas", "text/pascal"},\r
- {"pbm", "image/x-portable-bitmap"},\r
- {"pcl", "application/vnd.hp-pcl"},\r
- {"pcl", "application/x-pcl"},\r
- {"pct", "image/x-pict"},\r
- {"pcx", "image/x-pcx"},\r
- {"pdb", "chemical/x-pdb"},\r
- {"pdf", "application/pdf"},\r
- {"pfunk", "audio/make"},\r
- {"pfunk", "audio/make.my.funk"},\r
- {"pgm", "image/x-portable-graymap"},\r
- {"pgm", "image/x-portable-greymap"},\r
- {"pic", "image/pict"},\r
- {"pict", "image/pict"},\r
- {"pkg", "application/x-newton-compatible-pkg"},\r
- {"pko", "application/vnd.ms-pki.pko"},\r
- {"pl", "text/plain"},\r
- {"pl", "text/x-script.perl"},\r
- {"plx", "application/x-pixclscript"},\r
- {"pm", "image/x-xpixmap"},\r
- {"pm", "text/x-script.perl-module"},\r
- {"pm4", "application/x-pagemaker"},\r
- {"pm5", "application/x-pagemaker"},\r
- {"png", "image/png"},\r
- {"pnm", "application/x-portable-anymap"},\r
- {"pnm", "image/x-portable-anymap"},\r
- {"pot", "application/mspowerpoint"},\r
- {"pot", "application/vnd.ms-powerpoint"},\r
- {"pov", "model/x-pov"},\r
- {"ppa", "application/vnd.ms-powerpoint"},\r
- {"ppm", "image/x-portable-pixmap"},\r
- {"pps", "application/mspowerpoint"},\r
- {"pps", "application/vnd.ms-powerpoint"},\r
- {"ppt", "application/mspowerpoint"},\r
- {"ppt", "application/powerpoint"},\r
- {"ppt", "application/vnd.ms-powerpoint"},\r
- {"ppt", "application/x-mspowerpoint"},\r
- {"ppz", "application/mspowerpoint"},\r
- {"pre", "application/x-freelance"},\r
- {"prt", "application/pro_eng"},\r
- {"ps", "application/postscript"},\r
- {"psd", "application/octet-stream"},\r
- {"pvu", "paleovu/x-pv"},\r
- {"pwz", "application/vnd.ms-powerpoint"},\r
- {"py", "text/x-script.python"},\r
- {"pyc", "application/x-bytecode.python"},\r
- {"qcp", "audio/vnd.qcelp"},\r
- {"qd3", "x-world/x-3dmf"},\r
- {"qd3d", "x-world/x-3dmf"},\r
- {"qif", "image/x-quicktime"},\r
- {"qt", "video/quicktime"},\r
- {"qtc", "video/x-qtc"},\r
- {"qti", "image/x-quicktime"},\r
- {"qtif", "image/x-quicktime"},\r
- {"ra", "audio/x-pn-realaudio"},\r
- {"ra", "audio/x-pn-realaudio-plugin"},\r
- {"ra", "audio/x-realaudio"},\r
- {"ram", "audio/x-pn-realaudio"},\r
- {"ras", "application/x-cmu-raster"},\r
- {"ras", "image/cmu-raster"},\r
- {"ras", "image/x-cmu-raster"},\r
- {"rast", "image/cmu-raster"},\r
- {"rexx", "text/x-script.rexx"},\r
- {"rf", "image/vnd.rn-realflash"},\r
- {"rgb", "image/x-rgb"},\r
- {"rm", "application/vnd.rn-realmedia"},\r
- {"rm", "audio/x-pn-realaudio"},\r
- {"rmi", "audio/mid"},\r
- {"rmm", "audio/x-pn-realaudio"},\r
- {"rmp", "audio/x-pn-realaudio"},\r
- {"rmp", "audio/x-pn-realaudio-plugin"},\r
- {"rng", "application/ringing-tones"},\r
- {"rng", "application/vnd.nokia.ringing-tone"},\r
- {"rnx", "application/vnd.rn-realplayer"},\r
- {"roff", "application/x-troff"},\r
- {"rp", "image/vnd.rn-realpix"},\r
- {"rpm", "audio/x-pn-realaudio-plugin"},\r
- {"rt", "text/richtext"},\r
- {"rt", "text/vnd.rn-realtext"},\r
- {"rtf", "application/rtf"},\r
- {"rtf", "application/x-rtf"},\r
- {"rtf", "text/richtext"},\r
- {"rtx", "application/rtf"},\r
- {"rtx", "text/richtext"},\r
- {"rv", "video/vnd.rn-realvideo"},\r
- {"s", "text/x-asm"},\r
- {"s3m", "audio/s3m"},\r
- {"saveme", "application/octet-stream"},\r
- {"sbk", "application/x-tbook"},\r
- {"scm", "application/x-lotusscreencam"},\r
- {"scm", "text/x-script.guile"},\r
- {"scm", "text/x-script.scheme"},\r
- {"scm", "video/x-scm"},\r
- {"sdml", "text/plain"},\r
- {"sdp", "application/sdp"},\r
- {"sdp", "application/x-sdp"},\r
- {"sdr", "application/sounder"},\r
- {"sea", "application/sea"},\r
- {"sea", "application/x-sea"},\r
- {"set", "application/set"},\r
- {"sgm", "text/sgml"},\r
- {"sgm", "text/x-sgml"},\r
- {"sgml", "text/sgml"},\r
- {"sgml", "text/x-sgml"},\r
- {"sh", "application/x-bsh"},\r
- {"sh", "application/x-sh"},\r
- {"sh", "application/x-shar"},\r
- {"sh", "text/x-script.sh"},\r
- {"shar", "application/x-bsh"},\r
- {"shar", "application/x-shar"},\r
- {"shtml", "text/html"},\r
- {"shtml", "text/x-server-parsed-html"},\r
- {"sid", "audio/x-psid"},\r
- {"sit", "application/x-sit"},\r
- {"sit", "application/x-stuffit"},\r
- {"skd", "application/x-koan"},\r
- {"skm", "application/x-koan"},\r
- {"skp", "application/x-koan"},\r
- {"skt", "application/x-koan"},\r
- {"sl", "application/x-seelogo"},\r
- {"smi", "application/smil"},\r
- {"smil", "application/smil"},\r
- {"snd", "audio/basic"},\r
- {"snd", "audio/x-adpcm"},\r
- {"sol", "application/solids"},\r
- {"spc", "application/x-pkcs7-certificates"},\r
- {"spc", "text/x-speech"},\r
- {"spl", "application/futuresplash"},\r
- {"spr", "application/x-sprite"},\r
- {"sprite", "application/x-sprite"},\r
- {"src", "application/x-wais-source"},\r
- {"ssi", "text/x-server-parsed-html"},\r
- {"ssm", "application/streamingmedia"},\r
- {"sst", "application/vnd.ms-pki.certstore"},\r
- {"step", "application/step"},\r
- {"stl", "application/sla"},\r
- {"stl", "application/vnd.ms-pki.stl"},\r
- {"stl", "application/x-navistyle"},\r
- {"stp", "application/step"},\r
- {"sv4cpio,", "application/x-sv4cpio"},\r
- {"sv4crc", "application/x-sv4crc"},\r
- {"svf", "image/vnd.dwg"},\r
- {"svf", "image/x-dwg"},\r
- {"svr", "application/x-world"},\r
- {"svr", "x-world/x-svr"},\r
- {"swf", "application/x-shockwave-flash"},\r
- {"t", "application/x-troff"},\r
- {"talk", "text/x-speech"},\r
- {"tar", "application/x-tar"},\r
- {"tbk", "application/toolbook"},\r
- {"tbk", "application/x-tbook"},\r
- {"tcl", "application/x-tcl"},\r
- {"tcl", "text/x-script.tcl"},\r
- {"tcsh", "text/x-script.tcsh"},\r
- {"tex", "application/x-tex"},\r
- {"texi", "application/x-texinfo"},\r
- {"texinfo,", "application/x-texinfo"},\r
- {"text", "application/plain"},\r
- {"text", "text/plain"},\r
- {"tgz", "application/gnutar"},\r
- {"tgz", "application/x-compressed"},\r
- {"tif", "image/tiff"},\r
- {"tif", "image/x-tiff"},\r
- {"tiff", "image/tiff"},\r
- {"tiff", "image/x-tiff"},\r
- {"tr", "application/x-troff"},\r
- {"tsi", "audio/tsp-audio"},\r
- {"tsp", "application/dsptype"},\r
- {"tsp", "audio/tsplayer"},\r
- {"tsv", "text/tab-separated-values"},\r
- {"turbot", "image/florian"},\r
- {"txt", "text/plain"},\r
- {"uil", "text/x-uil"},\r
- {"uni", "text/uri-list"},\r
- {"unis", "text/uri-list"},\r
- {"unv", "application/i-deas"},\r
- {"uri", "text/uri-list"},\r
- {"uris", "text/uri-list"},\r
- {"ustar", "application/x-ustar"},\r
- {"ustar", "multipart/x-ustar"},\r
- {"uu", "application/octet-stream"},\r
- {"uu", "text/x-uuencode"},\r
- {"uue", "text/x-uuencode"},\r
- {"vcd", "application/x-cdlink"},\r
- {"vcs", "text/x-vcalendar"},\r
- {"vda", "application/vda"},\r
- {"vdo", "video/vdo"},\r
- {"vew", "application/groupwise"},\r
- {"viv", "video/vivo"},\r
- {"viv", "video/vnd.vivo"},\r
- {"vivo", "video/vivo"},\r
- {"vivo", "video/vnd.vivo"},\r
- {"vmd", "application/vocaltec-media-desc"},\r
- {"vmf", "application/vocaltec-media-file"},\r
- {"voc", "audio/voc"},\r
- {"voc", "audio/x-voc"},\r
- {"vos", "video/vosaic"},\r
- {"vox", "audio/voxware"},\r
- {"vqe", "audio/x-twinvq-plugin"},\r
- {"vqf", "audio/x-twinvq"},\r
- {"vql", "audio/x-twinvq-plugin"},\r
- {"vrml", "application/x-vrml"},\r
- {"vrml", "model/vrml"},\r
- {"vrml", "x-world/x-vrml"},\r
- {"vrt", "x-world/x-vrt"},\r
- {"vsd", "application/x-visio"},\r
- {"vst", "application/x-visio"},\r
- {"vsw", "application/x-visio"},\r
- {"w60", "application/wordperfect6.0"},\r
- {"w61", "application/wordperfect6.1"},\r
- {"w6w", "application/msword"},\r
- {"wav", "audio/wav"},\r
- {"wav", "audio/x-wav"},\r
- {"wb1", "application/x-qpro"},\r
- {"wbmp", "image/vnd.wap.wbmp"},\r
- {"web", "application/vnd.xara"},\r
- {"wiz", "application/msword"},\r
- {"wk1", "application/x-123"},\r
- {"wmf", "windows/metafile"},\r
- {"wml", "text/vnd.wap.wml"},\r
- {"wmlc", "application/vnd.wap.wmlc"},\r
- {"wmls", "text/vnd.wap.wmlscript"},\r
- {"wmlsc", "application/vnd.wap.wmlscriptc"},\r
- {"word", "application/msword"},\r
- {"wp", "application/wordperfect"},\r
- {"wp5", "application/wordperfect"},\r
- {"wp5", "application/wordperfect6.0"},\r
- {"wp6", "application/wordperfect"},\r
- {"wpd", "application/wordperfect"},\r
- {"wpd", "application/x-wpwin"},\r
- {"wq1", "application/x-lotus"},\r
- {"wri", "application/mswrite"},\r
- {"wri", "application/x-wri"},\r
- {"wrl", "application/x-world"},\r
- {"wrl", "model/vrml"},\r
- {"wrl", "x-world/x-vrml"},\r
- {"wrz", "model/vrml"},\r
- {"wrz", "x-world/x-vrml"},\r
- {"wsc", "text/scriplet"},\r
- {"wsrc", "application/x-wais-source"},\r
- {"wtk", "application/x-wintalk"},\r
- {"xbm", "image/x-xbitmap"},\r
- {"xbm", "image/x-xbm"},\r
- {"xbm", "image/xbm"},\r
- {"xdr", "video/x-amt-demorun"},\r
- {"xgz", "xgl/drawing"},\r
- {"xif", "image/vnd.xiff"},\r
- {"xl", "application/excel"},\r
- {"xla", "application/excel"},\r
- {"xla", "application/x-excel"},\r
- {"xla", "application/x-msexcel"},\r
- {"xlb", "application/excel"},\r
- {"xlb", "application/vnd.ms-excel"},\r
- {"xlb", "application/x-excel"},\r
- {"xlc", "application/excel"},\r
- {"xlc", "application/vnd.ms-excel"},\r
- {"xlc", "application/x-excel"},\r
- {"xld", "application/excel"},\r
- {"xld", "application/x-excel"},\r
- {"xlk", "application/excel"},\r
- {"xlk", "application/x-excel"},\r
- {"xll", "application/excel"},\r
- {"xll", "application/vnd.ms-excel"},\r
- {"xll", "application/x-excel"},\r
- {"xlm", "application/excel"},\r
- {"xlm", "application/vnd.ms-excel"},\r
- {"xlm", "application/x-excel"},\r
- {"xls", "application/excel"},\r
- {"xls", "application/vnd.ms-excel"},\r
- {"xls", "application/x-excel"},\r
- {"xls", "application/x-msexcel"},\r
- {"xlt", "application/excel"},\r
- {"xlt", "application/x-excel"},\r
- {"xlv", "application/excel"},\r
- {"xlv", "application/x-excel"},\r
- {"xlw", "application/excel"},\r
- {"xlw", "application/vnd.ms-excel"},\r
- {"xlw", "application/x-excel"},\r
- {"xlw", "application/x-msexcel"},\r
- {"xm", "audio/xm"},\r
- {"xml", "application/xml"},\r
- {"xml", "text/xml"},\r
- {"xmz", "xgl/movie"},\r
- {"xpix", "application/x-vnd.ls-xpix"},\r
- {"xpm", "image/x-xpixmap"},\r
- {"xpm", "image/xpm"},\r
- {"x-png", "image/png"},\r
- {"xsr", "video/x-amt-showrun"},\r
- {"xwd", "image/x-xwd"},\r
- {"xwd", "image/x-xwindowdump"},\r
- {"xyz", "chemical/x-pdb"},\r
- {"z", "application/x-compress"},\r
- {"z", "application/x-compressed"},\r
- {"zip", "application/x-compressed"},\r
- {"zip", "application/x-zip-compressed"},\r
- {"zip", "application/zip"},\r
- {"zip", "multipart/x-zip"},\r
- {"zoo", "application/octet-stream"}\r
-};\r
+ return Table::get().getExtensionsForType (mimeType);\r
+}\r
\r
} // namespace juce\r
namespace juce\r
{\r
\r
-namespace MimeTypeTable\r
+struct MimeTypeTable\r
{\r
\r
/* @internal */\r
-StringArray getMimeTypesForFileExtension (const String& fileExtension);\r
+static void registerCustomMimeTypeForFileExtension (const String& mimeType, const String& fileExtension);\r
\r
/* @internal */\r
-StringArray getFileExtensionsForMimeType (const String& mimeType);\r
+static StringArray getMimeTypesForFileExtension (const String& fileExtension);\r
\r
-} // namespace MimeTypeTable\r
+/* @internal */\r
+static StringArray getFileExtensionsForMimeType (const String& mimeType);\r
+\r
+};\r
\r
} // namespace juce\r
#include "zip/juce_ZipFile.cpp"\r
#include "files/juce_FileFilter.cpp"\r
#include "files/juce_WildcardFileFilter.cpp"\r
+#include "native/juce_native_ThreadPriorities.h"\r
\r
//==============================================================================\r
#if ! JUCE_WINDOWS\r
\r
ID: juce_core\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies:\r
OSXFrameworks: Cocoa Foundation IOKit\r
return n & (((uint32) 0xffffffff) >> endSpace);\r
}\r
\r
-void BigInteger::setBitRangeAsInt (const int startBit, int numBits, uint32 valueToSet)\r
+BigInteger& BigInteger::setBitRangeAsInt (const int startBit, int numBits, uint32 valueToSet)\r
{\r
if (numBits > 32)\r
{\r
setBit (startBit + i, (valueToSet & 1) != 0);\r
valueToSet >>= 1;\r
}\r
+\r
+ return *this;\r
}\r
\r
//==============================================================================\r
-void BigInteger::clear() noexcept\r
+BigInteger& BigInteger::clear() noexcept\r
{\r
heapAllocation.free();\r
allocatedSize = numPreallocatedInts;\r
\r
for (int i = 0; i < numPreallocatedInts; ++i)\r
preallocated[i] = 0;\r
+\r
+ return *this;\r
}\r
\r
-void BigInteger::setBit (const int bit)\r
+BigInteger& BigInteger::setBit (const int bit)\r
{\r
if (bit >= 0)\r
{\r
\r
getValues() [bitToIndex (bit)] |= bitToMask (bit);\r
}\r
+\r
+ return *this;\r
}\r
\r
-void BigInteger::setBit (const int bit, const bool shouldBeSet)\r
+BigInteger& BigInteger::setBit (const int bit, const bool shouldBeSet)\r
{\r
if (shouldBeSet)\r
setBit (bit);\r
else\r
clearBit (bit);\r
+\r
+ return *this;\r
}\r
\r
-void BigInteger::clearBit (const int bit) noexcept\r
+BigInteger& BigInteger::clearBit (const int bit) noexcept\r
{\r
if (bit >= 0 && bit <= highestBit)\r
{\r
if (bit == highestBit)\r
highestBit = getHighestBit();\r
}\r
+\r
+ return *this;\r
}\r
\r
-void BigInteger::setRange (int startBit, int numBits, const bool shouldBeSet)\r
+BigInteger& BigInteger::setRange (int startBit, int numBits, const bool shouldBeSet)\r
{\r
while (--numBits >= 0)\r
setBit (startBit++, shouldBeSet);\r
+\r
+ return *this;\r
}\r
\r
-void BigInteger::insertBit (const int bit, const bool shouldBeSet)\r
+BigInteger& BigInteger::insertBit (const int bit, const bool shouldBeSet)\r
{\r
if (bit >= 0)\r
shiftBits (1, bit);\r
\r
setBit (bit, shouldBeSet);\r
+ return *this;\r
}\r
\r
//==============================================================================\r
}\r
}\r
\r
-void BigInteger::shiftBits (int bits, const int startBit)\r
+BigInteger& BigInteger::shiftBits (int bits, const int startBit)\r
{\r
if (highestBit >= 0)\r
{\r
else if (bits > 0)\r
shiftLeft (bits, startBit);\r
}\r
+\r
+ return *this;\r
}\r
\r
//==============================================================================\r
\r
//==============================================================================\r
/** Resets the value to 0. */\r
- void clear() noexcept;\r
+ BigInteger& clear() noexcept;\r
\r
/** Clears a particular bit in the number. */\r
- void clearBit (int bitNumber) noexcept;\r
+ BigInteger& clearBit (int bitNumber) noexcept;\r
\r
/** Sets a specified bit to 1. */\r
- void setBit (int bitNumber);\r
+ BigInteger& setBit (int bitNumber);\r
\r
/** Sets or clears a specified bit. */\r
- void setBit (int bitNumber, bool shouldBeSet);\r
+ BigInteger& setBit (int bitNumber, bool shouldBeSet);\r
\r
/** Sets a range of bits to be either on or off.\r
\r
@param numBits the number of bits to change\r
@param shouldBeSet whether to turn these bits on or off\r
*/\r
- void setRange (int startBit, int numBits, bool shouldBeSet);\r
+ BigInteger& setRange (int startBit, int numBits, bool shouldBeSet);\r
\r
/** Inserts a bit an a given position, shifting up any bits above it. */\r
- void insertBit (int bitNumber, bool shouldBeSet);\r
+ BigInteger& insertBit (int bitNumber, bool shouldBeSet);\r
\r
/** Returns a range of bits as a new BigInteger.\r
\r
Copies the given integer onto a range of bits, starting at startBit,\r
and using up to numBits of the available bits.\r
*/\r
- void setBitRangeAsInt (int startBit, int numBits, uint32 valueToSet);\r
+ BigInteger& setBitRangeAsInt (int startBit, int numBits, uint32 valueToSet);\r
\r
/** Shifts a section of bits left or right.\r
\r
@param howManyBitsLeft how far to move the bits (+ve numbers shift it left, -ve numbers shift it right).\r
@param startBit the first bit to affect - if this is > 0, only bits above that index will be affected.\r
*/\r
- void shiftBits (int howManyBitsLeft, int startBit);\r
+ BigInteger& shiftBits (int howManyBitsLeft, int startBit);\r
\r
/** Returns the total number of set bits in the value. */\r
int countNumberOfSetBits() const noexcept;\r
int findHighestSetBit (uint32 n) noexcept;\r
\r
/** Returns the number of bits in a 32-bit integer. */\r
-inline int countNumberOfBits (uint32 n) noexcept\r
+constexpr int countNumberOfBits (uint32 n) noexcept\r
{\r
n -= ((n >> 1) & 0x55555555);\r
n = (((n >> 2) & 0x33333333) + (n & 0x33333333));\r
}\r
\r
/** Returns the number of bits in a 64-bit integer. */\r
-inline int countNumberOfBits (uint64 n) noexcept\r
+constexpr int countNumberOfBits (uint64 n) noexcept\r
{\r
return countNumberOfBits ((uint32) n) + countNumberOfBits ((uint32) (n >> 32));\r
}\r
\r
@tags{Core}\r
*/\r
- template <typename Type> struct SmallestFloatType { using type = float; };\r
-\r
- #ifndef DOXYGEN\r
- template <> struct SmallestFloatType <double> { using type = double; };\r
- #endif\r
+ template <typename Type>\r
+ using SmallestFloatType = std::conditional_t<std::is_same_v<Type, double>, double, float>;\r
\r
/** These templates are designed to take an integer type, and return an unsigned int\r
version with the same size.\r
}\r
\r
/** Returns a range with a given start and length. */\r
- JUCE_NODISCARD static Range withStartAndLength (const ValueType startValue, const ValueType length) noexcept\r
+ [[nodiscard]] static Range withStartAndLength (const ValueType startValue, const ValueType length) noexcept\r
{\r
jassert (length >= ValueType());\r
return Range (startValue, startValue + length);\r
}\r
\r
/** Returns a range with the specified start position and a length of zero. */\r
- JUCE_NODISCARD constexpr static Range emptyRange (const ValueType start) noexcept\r
+ [[nodiscard]] constexpr static Range emptyRange (const ValueType start) noexcept\r
{\r
return Range (start, start);\r
}\r
If the new start position is higher than the current end of the range, the end point\r
will be pushed along to equal it, returning an empty range at the new position.\r
*/\r
- JUCE_NODISCARD constexpr Range withStart (const ValueType newStart) const noexcept\r
+ [[nodiscard]] constexpr Range withStart (const ValueType newStart) const noexcept\r
{\r
return Range (newStart, jmax (newStart, end));\r
}\r
\r
/** Returns a range with the same length as this one, but moved to have the given start position. */\r
- JUCE_NODISCARD constexpr Range movedToStartAt (const ValueType newStart) const noexcept\r
+ [[nodiscard]] constexpr Range movedToStartAt (const ValueType newStart) const noexcept\r
{\r
return Range (newStart, end + (newStart - start));\r
}\r
If the new end position is below the current start of the range, the start point\r
will be pushed back to equal the new end point.\r
*/\r
- JUCE_NODISCARD constexpr Range withEnd (const ValueType newEnd) const noexcept\r
+ [[nodiscard]] constexpr Range withEnd (const ValueType newEnd) const noexcept\r
{\r
return Range (jmin (start, newEnd), newEnd);\r
}\r
\r
/** Returns a range with the same length as this one, but moved to have the given end position. */\r
- JUCE_NODISCARD constexpr Range movedToEndAt (const ValueType newEnd) const noexcept\r
+ [[nodiscard]] constexpr Range movedToEndAt (const ValueType newEnd) const noexcept\r
{\r
return Range (start + (newEnd - end), newEnd);\r
}\r
/** Returns a range with the same start as this one, but a different length.\r
Lengths less than zero are treated as zero.\r
*/\r
- JUCE_NODISCARD constexpr Range withLength (const ValueType newLength) const noexcept\r
+ [[nodiscard]] constexpr Range withLength (const ValueType newLength) const noexcept\r
{\r
return Range (start, start + newLength);\r
}\r
given amount.\r
@returns The returned range will be (start - amount, end + amount)\r
*/\r
- JUCE_NODISCARD constexpr Range expanded (ValueType amount) const noexcept\r
+ [[nodiscard]] constexpr Range expanded (ValueType amount) const noexcept\r
{\r
return Range (start - amount, end + amount);\r
}\r
\r
/** Returns the range that is the intersection of the two ranges, or an empty range\r
with an undefined start position if they don't overlap. */\r
- JUCE_NODISCARD constexpr Range getIntersectionWith (Range other) const noexcept\r
+ [[nodiscard]] constexpr Range getIntersectionWith (Range other) const noexcept\r
{\r
return Range (jmax (start, other.start),\r
jmin (end, other.end));\r
}\r
\r
/** Returns the smallest range that contains both this one and the other one. */\r
- JUCE_NODISCARD constexpr Range getUnionWith (Range other) const noexcept\r
+ [[nodiscard]] constexpr Range getUnionWith (Range other) const noexcept\r
{\r
return Range (jmin (start, other.start),\r
jmax (end, other.end));\r
}\r
\r
/** Returns the smallest range that contains both this one and the given value. */\r
- JUCE_NODISCARD constexpr Range getUnionWith (const ValueType valueToInclude) const noexcept\r
+ [[nodiscard]] constexpr Range getUnionWith (const ValueType valueToInclude) const noexcept\r
{\r
return Range (jmin (valueToInclude, start),\r
jmax (valueToInclude, end));\r
}\r
\r
/** Scans an array of values for its min and max, and returns these as a Range. */\r
- template <typename Integral, std::enable_if_t<std::is_integral<Integral>::value, int> = 0>\r
+ template <typename Integral, std::enable_if_t<std::is_integral_v<Integral>, int> = 0>\r
static Range findMinAndMax (const ValueType* values, Integral numValues) noexcept\r
{\r
if (numValues <= 0)\r
{\r
private:\r
template <class OtherElementType>\r
- using AllowConversion = typename std::enable_if<std::is_base_of<typename std::remove_pointer<ElementType>::type,\r
- typename std::remove_pointer<OtherElementType>::type>::value>::type;\r
+ using AllowConversion = std::enable_if_t<std::is_base_of_v<std::remove_pointer_t<ElementType>,\r
+ std::remove_pointer_t<OtherElementType>>>;\r
\r
public:\r
//==============================================================================\r
If you want an array of zero values, you can use the calloc() method or the\r
other constructor that takes an InitialisationState parameter.\r
*/\r
- template <typename SizeType, std::enable_if_t<std::is_convertible<SizeType, int>::value, int> = 0>\r
+ template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>\r
explicit HeapBlock (SizeType numElements)\r
: data (static_cast<ElementType*> (std::malloc (static_cast<size_t> (numElements) * sizeof (ElementType))))\r
{\r
The initialiseToZero parameter determines whether the new memory should be cleared,\r
or left uninitialised.\r
*/\r
- template <typename SizeType, std::enable_if_t<std::is_convertible<SizeType, int>::value, int> = 0>\r
+ template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>\r
HeapBlock (SizeType numElements, bool initialiseToZero)\r
: data (static_cast<ElementType*> (initialiseToZero\r
? std::calloc (static_cast<size_t> (numElements), sizeof (ElementType))\r
\r
/** Converting move constructor.\r
Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,\r
- where std::is_base_of<Base, Derived>::value == true.\r
+ where std::is_base_of_v<Base, Derived> == true.\r
*/\r
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>\r
HeapBlock (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept\r
\r
/** Converting move assignment operator.\r
Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,\r
- where std::is_base_of<Base, Derived>::value == true.\r
+ where std::is_base_of_v<Base, Derived> == true.\r
*/\r
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>\r
HeapBlock& operator= (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept\r
to a region that has suitable alignment for `Type`, e.g. regions returned from\r
malloc/calloc that should be suitable for any non-over-aligned type.\r
*/\r
-template <typename Type, typename std::enable_if<std::is_pointer<Type>::value, int>::type = 0>\r
+template <typename Type>\r
inline Type unalignedPointerCast (void* ptr) noexcept\r
{\r
+ static_assert (std::is_pointer_v<Type>);\r
return reinterpret_cast<Type> (ptr);\r
}\r
\r
to a region that has suitable alignment for `Type`, e.g. regions returned from\r
malloc/calloc that should be suitable for any non-over-aligned type.\r
*/\r
-template <typename Type, typename std::enable_if<std::is_pointer<Type>::value, int>::type = 0>\r
+template <typename Type>\r
inline Type unalignedPointerCast (const void* ptr) noexcept\r
{\r
+ static_assert (std::is_pointer_v<Type>);\r
return reinterpret_cast<Type> (ptr);\r
}\r
\r
*/\r
bool wasObjectDeleted() const noexcept { return holder != nullptr && holder->get() == nullptr; }\r
\r
- bool operator== (ObjectType* object) const noexcept { return get() == object; }\r
- bool operator!= (ObjectType* object) const noexcept { return get() != object; }\r
-\r
//==============================================================================\r
/** This class is used internally by the WeakReference class - don't use it directly\r
in your code!\r
using Void = void;\r
\r
template <typename, typename = void>\r
- struct EqualityComparableToNullptr\r
- : std::false_type {};\r
+ constexpr auto equalityComparableToNullptr = false;\r
\r
template <typename T>\r
- struct EqualityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>>\r
- : std::true_type {};\r
-\r
- template <typename T>\r
- constexpr bool shouldCheckAgainstNullptr = EqualityComparableToNullptr<T>::value;\r
+ constexpr auto equalityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>> = true;\r
} // namespace detail\r
#endif\r
\r
*/\r
struct NullCheckedInvocation\r
{\r
- template <typename Callable, typename... Args,\r
- std::enable_if_t<detail::shouldCheckAgainstNullptr<Callable>, int> = 0>\r
+ template <typename Callable, typename... Args>\r
static void invoke (Callable&& fn, Args&&... args)\r
{\r
- JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress")\r
-\r
- if (fn != nullptr)\r
- fn (std::forward<Args> (args)...);\r
+ if constexpr (detail::equalityComparableToNullptr<Callable>)\r
+ {\r
+ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress")\r
\r
- JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
- }\r
+ if (fn != nullptr)\r
+ fn (std::forward<Args> (args)...);\r
\r
- template <typename Callable, typename... Args,\r
- std::enable_if_t<! detail::shouldCheckAgainstNullptr<Callable>, int> = 0>\r
- static void invoke (Callable&& fn, Args&&... args)\r
- {\r
- fn (std::forward<Args> (args)...);\r
+ JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+ }\r
+ else\r
+ {\r
+ fn (std::forward<Args> (args)...);\r
+ }\r
}\r
\r
template <typename... Args>\r
Adapted from https://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/\r
*/\r
template <typename A, typename B>\r
-using DisableIfSameOrDerived = typename std::enable_if_t<! std::is_base_of<A, std::remove_reference_t<B>>::value>;\r
+using DisableIfSameOrDerived = std::enable_if_t<! std::is_base_of_v<A, std::remove_reference_t<B>>>;\r
\r
/** Copies an object, sets one of the copy's members to the specified value, and then returns the copy. */\r
-template <typename Object, typename OtherObject, typename Member>\r
-Object withMember (Object copy, Member OtherObject::* member, Member&& value)\r
+template <typename Object, typename OtherObject, typename Member, typename Other>\r
+Object withMember (Object copy, Member OtherObject::* member, Other&& value)\r
{\r
- copy.*member = std::forward<Member> (value);\r
+ copy.*member = std::forward<Other> (value);\r
return copy;\r
}\r
\r
+/** An easy way to ensure that a function is called at the end of the current\r
+ scope.\r
+\r
+ Usage:\r
+ @code\r
+ {\r
+ if (flag == true)\r
+ return;\r
+\r
+ // While this code executes, flag is true e.g. to prevent reentrancy\r
+ flag = true;\r
+ // When we exit this scope, flag must be false\r
+ const ScopeGuard scope { [&] { flag = false; } };\r
+\r
+ if (checkInitialCondition())\r
+ return; // Scope's lambda will fire here...\r
+\r
+ if (checkCriticalCondition())\r
+ throw std::runtime_error{}; // ...or here...\r
+\r
+ doWorkHavingEstablishedPreconditions();\r
+ } // ...or here!\r
+ @endcode\r
+*/\r
+template <typename Fn> struct ScopeGuard : Fn { ~ScopeGuard() { Fn::operator()(); } };\r
+template <typename Fn> ScopeGuard (Fn) -> ScopeGuard<Fn>;\r
+\r
} // namespace juce\r
#include <iphlpapi.h>\r
#include <accctrl.h>\r
#include <aclapi.h>\r
-\r
- #if ! JUCE_CXX17_IS_AVAILABLE\r
- #pragma push_macro ("WIN_NOEXCEPT")\r
- #define WIN_NOEXCEPT\r
- #endif\r
-\r
#include <mapi.h>\r
-\r
- #if ! JUCE_CXX17_IS_AVAILABLE\r
- #pragma pop_macro ("WIN_NOEXCEPT")\r
- #endif\r
-\r
#include <float.h>\r
#include <process.h>\r
#include <shlobj.h>\r
#include <sys/ptrace.h>\r
#include <sys/socket.h>\r
#include <sys/stat.h>\r
+ #include <sys/syscall.h>\r
#include <sys/sysinfo.h>\r
#include <sys/time.h>\r
#include <sys/types.h>\r
\r
void onStart() override\r
{\r
- getEnv()->CallVoidMethod (getNativeHandle(), AndroidFragment.startActivityForResult,\r
- intent.get(), requestCode);\r
+ if (! std::exchange (activityHasStarted, true))\r
+ getEnv()->CallVoidMethod (getNativeHandle(), AndroidFragment.startActivityForResult,\r
+ intent.get(), requestCode);\r
}\r
\r
void onActivityResult (int activityRequestCode, int resultCode, LocalRef<jobject> data) override\r
GlobalRef intent;\r
int requestCode;\r
std::function<void (int, int, LocalRef<jobject>)> callback;\r
+ bool activityHasStarted = false;\r
};\r
\r
void startAndroidActivityForResult (const LocalRef<jobject>& intent, int requestCode,\r
javaString (name).get())));\r
}\r
\r
+ static String getAndroidID()\r
+ {\r
+ auto* env = getEnv();\r
+\r
+ if (auto settings = (jclass) env->FindClass ("android/provider/Settings$Secure"))\r
+ {\r
+ if (auto fId = env->GetStaticFieldID (settings, "ANDROID_ID", "Ljava/lang/String;"))\r
+ {\r
+ auto androidID = (jstring) env->GetStaticObjectField (settings, fId);\r
+ return juceString (LocalRef<jstring> (androidID));\r
+ }\r
+ }\r
+\r
+ return "";\r
+ }\r
+\r
static String getLocaleValue (bool isRegion)\r
{\r
auto* env = getEnv();\r
String SystemStats::getUserRegion() { return AndroidStatsHelpers::getLocaleValue (true); }\r
String SystemStats::getDisplayLanguage() { return getUserLanguage() + "-" + getUserRegion(); }\r
\r
+String SystemStats::getUniqueDeviceID()\r
+{\r
+ auto id = String ((uint64_t) AndroidStatsHelpers::getAndroidID().hashCode64());\r
+\r
+ // Please tell someone at JUCE if this occurs\r
+ jassert (id.isNotEmpty());\r
+ return id;\r
+}\r
+\r
//==============================================================================\r
void CPUInformation::initialise() noexcept\r
{\r
}\r
\r
//==============================================================================\r
-// sets the process to 0=low priority, 1=normal, 2=high, 3=realtime\r
-JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority prior)\r
+#if JUCE_ANDROID && JUCE_MODULE_AVAILABLE_juce_audio_devices && (JUCE_USE_ANDROID_OPENSLES || JUCE_USE_ANDROID_OBOE)\r
+ #define JUCE_ANDROID_REALTIME_THREAD_AVAILABLE 1\r
+#endif\r
+\r
+#if JUCE_ANDROID_REALTIME_THREAD_AVAILABLE\r
+pthread_t juce_createRealtimeAudioThread (void* (*entry) (void*), void* userPtr);\r
+#endif\r
+\r
+extern JavaVM* androidJNIJavaVM;\r
+\r
+bool Thread::createNativeThread (Priority)\r
{\r
- // TODO\r
+ if (isRealtime())\r
+ {\r
+ #if JUCE_ANDROID_REALTIME_THREAD_AVAILABLE\r
+ threadHandle = (void*) juce_createRealtimeAudioThread (threadEntryProc, this);\r
+ threadId = (ThreadID) threadHandle.get();\r
+ return threadId != nullptr;\r
+ #else\r
+ jassertfalse;\r
+ #endif\r
+ }\r
\r
- struct sched_param param;\r
- int policy, maxp, minp;\r
+ PosixThreadAttribute attr { threadStackSize };\r
+ threadId = threadHandle = makeThreadHandle (attr, this, [] (void* userData) -> void*\r
+ {\r
+ auto* myself = static_cast<Thread*> (userData);\r
\r
- const int p = (int) prior;\r
+ juce_threadEntryPoint (myself);\r
\r
- if (p <= 1)\r
- policy = SCHED_OTHER;\r
- else\r
- policy = SCHED_RR;\r
+ if (androidJNIJavaVM != nullptr)\r
+ {\r
+ void* env = nullptr;\r
+ androidJNIJavaVM->GetEnv (&env, JNI_VERSION_1_2);\r
\r
- minp = sched_get_priority_min (policy);\r
- maxp = sched_get_priority_max (policy);\r
+ // only detach if we have actually been attached\r
+ if (env != nullptr)\r
+ androidJNIJavaVM->DetachCurrentThread();\r
+ }\r
\r
- if (p < 2)\r
- param.sched_priority = 0;\r
- else if (p == 2 )\r
- // Set to middle of lower realtime priority range\r
- param.sched_priority = minp + (maxp - minp) / 4;\r
- else\r
- // Set to middle of higher realtime priority range\r
- param.sched_priority = minp + (3 * (maxp - minp) / 4);\r
+ return nullptr;\r
+ });\r
\r
- pthread_setschedparam (pthread_self(), policy, ¶m);\r
+ return threadId != nullptr;\r
}\r
\r
+void Thread::killThread()\r
+{\r
+ if (threadHandle != nullptr)\r
+ jassertfalse; // pthread_cancel not available!\r
+}\r
+\r
+Thread::Priority Thread::getPriority() const\r
+{\r
+ jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+ const auto native = getpriority (PRIO_PROCESS, (id_t) gettid());\r
+ return ThreadPriorities::getJucePriority (native);\r
+}\r
+\r
+bool Thread::setPriority (Priority)\r
+{\r
+ jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+ if (isRealtime())\r
+ return false;\r
+\r
+ return setpriority (PRIO_PROCESS, (id_t) gettid(), ThreadPriorities::getNativePriority (priority)) == 0;\r
+}\r
+\r
+//==============================================================================\r
+JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority) {}\r
+\r
JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger() noexcept\r
{\r
StringArray lines;\r
#endif\r
}\r
\r
+String SystemStats::getUniqueDeviceID()\r
+{\r
+ static const auto deviceId = []()\r
+ {\r
+ const auto call = [] (auto command) -> String\r
+ {\r
+ ChildProcess proc;\r
+\r
+ if (proc.start (command, ChildProcess::wantStdOut))\r
+ return proc.readAllProcessOutput();\r
+\r
+ return {};\r
+ };\r
+\r
+ auto data = call ("cat /sys/class/dmi/id/board_serial");\r
+\r
+ // 'board_serial' is enough on its own, fallback to bios stuff if we can't find it.\r
+ if (data.isEmpty())\r
+ {\r
+ data = call ("cat /sys/class/dmi/id/bios_date")\r
+ + call ("cat /sys/class/dmi/id/bios_release")\r
+ + call ("cat /sys/class/dmi/id/bios_vendor")\r
+ + call ("cat /sys/class/dmi/id/bios_version");\r
+ }\r
+\r
+ auto cpuData = call ("lscpu");\r
+\r
+ if (cpuData.isNotEmpty())\r
+ {\r
+ auto getCpuInfo = [&cpuData] (auto key) -> String\r
+ {\r
+ auto index = cpuData.indexOf (key);\r
+\r
+ if (index >= 0)\r
+ {\r
+ auto start = cpuData.indexOf (index, ":");\r
+ auto end = cpuData.indexOf (start, "\n");\r
+\r
+ return cpuData.substring (start + 1, end).trim();\r
+ }\r
+\r
+ return {};\r
+ };\r
+\r
+ data += getCpuInfo ("CPU family:");\r
+ data += getCpuInfo ("Model:");\r
+ data += getCpuInfo ("Model name:");\r
+ data += getCpuInfo ("Vendor ID:");\r
+ }\r
+\r
+ return String ((uint64_t) data.hashCode64());\r
+ }();\r
+\r
+ // Please tell someone at JUCE if this occurs\r
+ jassert (deviceId.isNotEmpty());\r
+ return deviceId;\r
+}\r
+\r
//==============================================================================\r
uint32 juce_millisecondsSinceStartup() noexcept\r
{\r
live in juce_posix_SharedCode.h!\r
*/\r
\r
-//==============================================================================\r
-JUCE_API void JUCE_CALLTYPE Process::setPriority (const ProcessPriority prior)\r
+bool Thread::createNativeThread (Priority)\r
{\r
- auto policy = (prior <= NormalPriority) ? SCHED_OTHER : SCHED_RR;\r
- auto minp = sched_get_priority_min (policy);\r
- auto maxp = sched_get_priority_max (policy);\r
-\r
- struct sched_param param;\r
+ PosixThreadAttribute attr { threadStackSize };\r
+ PosixSchedulerPriority::getNativeSchedulerAndPriority (realtimeOptions, {}).apply (attr);\r
\r
- switch (prior)\r
+ threadId = threadHandle = makeThreadHandle (attr, this, [] (void* userData) -> void*\r
{\r
- case LowPriority:\r
- case NormalPriority: param.sched_priority = 0; break;\r
- case HighPriority: param.sched_priority = minp + (maxp - minp) / 4; break;\r
- case RealtimePriority: param.sched_priority = minp + (3 * (maxp - minp) / 4); break;\r
- default: jassertfalse; break;\r
- }\r
-\r
- pthread_setschedparam (pthread_self(), policy, ¶m);\r
+ auto* myself = static_cast<Thread*> (userData);\r
+\r
+ juce_threadEntryPoint (myself);\r
+\r
+ return nullptr;\r
+ });\r
+\r
+ return threadId != nullptr;\r
+}\r
+\r
+void Thread::killThread()\r
+{\r
+ if (threadHandle != nullptr)\r
+ pthread_cancel ((pthread_t) threadHandle.load());\r
+}\r
+\r
+// Until we implement Nice awareness, these don't do anything on Linux.\r
+Thread::Priority Thread::getPriority() const\r
+{\r
+ jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+ return priority;\r
}\r
\r
+bool Thread::setPriority (Priority newPriority)\r
+{\r
+ jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+ // Return true to make it compatible with other platforms.\r
+ priority = newPriority;\r
+ return true;\r
+}\r
+\r
+//==============================================================================\r
+JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority) {}\r
+\r
static bool swapUserAndEffectiveUser()\r
{\r
auto result1 = setreuid (geteuid(), getuid());\r
};\r
\r
template <typename CFType>\r
-using CFUniquePtr = std::unique_ptr<typename std::remove_pointer<CFType>::type, CFObjectDeleter<CFType>>;\r
+using CFUniquePtr = std::unique_ptr<std::remove_pointer_t<CFType>, CFObjectDeleter<CFType>>;\r
\r
template <typename CFType>\r
struct CFObjectHolder\r
return obj != nullptr ? getIvar<Class*> (obj, "cppObject") : nullptr;\r
}\r
\r
-template <typename ReturnT, class Class, typename... Params>\r
-ReturnT (^CreateObjCBlock(Class* object, ReturnT (Class::*fn)(Params...))) (Params...)\r
+namespace detail\r
+{\r
+template <typename> struct Signature;\r
+template <typename R, typename... A> struct Signature<R (A...)> {};\r
+\r
+template <typename Class, typename Result, typename... Args>\r
+constexpr auto getSignature (Result (Class::*) (Args...)) { return Signature<Result (Args...)>{}; }\r
+\r
+template <typename Class, typename Result, typename... Args>\r
+constexpr auto getSignature (Result (Class::*) (Args...) const) { return Signature<Result (Args...)>{}; }\r
+\r
+template <typename Class, typename Fn, typename Result, typename... Params>\r
+auto createObjCBlockImpl (Class* object, Fn func, Signature<Result (Params...)>)\r
{\r
- __block Class* _this = object;\r
- __block ReturnT (Class::*_fn)(Params...) = fn;\r
+ __block auto _this = object;\r
+ __block auto _func = func;\r
\r
- return [[^ReturnT (Params... params) { return (_this->*_fn) (params...); } copy] autorelease];\r
+ return [[^Result (Params... params) { return (_this->*_func) (params...); } copy] autorelease];\r
+}\r
+} // namespace detail\r
+\r
+template <typename Class, typename MemberFunc>\r
+auto CreateObjCBlock (Class* object, MemberFunc fn)\r
+{\r
+ return detail::createObjCBlockImpl (object, fn, detail::getSignature (fn));\r
}\r
\r
template <typename BlockType>\r
\r
case 11: return MacOS_11;\r
case 12: return MacOS_12;\r
+ case 13: return MacOS_13;\r
}\r
\r
- return UnknownOS;\r
+ return MacOSX;\r
#endif\r
}\r
\r
return (int) NSPageSize();\r
}\r
\r
+String SystemStats::getUniqueDeviceID()\r
+{\r
+ static const auto deviceId = []\r
+ {\r
+ ChildProcess proc;\r
+\r
+ if (proc.start ("ioreg -rd1 -c IOPlatformExpertDevice", ChildProcess::wantStdOut))\r
+ {\r
+ constexpr const char key[] = "\"IOPlatformUUID\"";\r
+ constexpr const auto keyLen = (int) sizeof (key);\r
+\r
+ auto output = proc.readAllProcessOutput();\r
+ auto index = output.indexOf (key);\r
+\r
+ if (index >= 0)\r
+ {\r
+ auto start = output.indexOf (index + keyLen, "\"");\r
+ auto end = output.indexOf (start + 1, "\"");\r
+ return output.substring (start + 1, end).replace("-", "");\r
+ }\r
+ }\r
+\r
+ return String();\r
+ }();\r
+\r
+ // Please tell someone at JUCE if this occurs\r
+ jassert (deviceId.isNotEmpty());\r
+ return deviceId;\r
+}\r
+\r
} // namespace juce\r
*/\r
\r
#if JUCE_IOS\r
-bool isIOSAppActive = true;\r
+ bool isIOSAppActive = true;\r
#endif\r
\r
+API_AVAILABLE (macos (10.10))\r
+static auto getNativeQOS (Thread::Priority priority)\r
+{\r
+ switch (priority)\r
+ {\r
+ case Thread::Priority::highest: return QOS_CLASS_USER_INTERACTIVE;\r
+ case Thread::Priority::high: return QOS_CLASS_USER_INITIATED;\r
+ case Thread::Priority::low: return QOS_CLASS_UTILITY;\r
+ case Thread::Priority::background: return QOS_CLASS_BACKGROUND;\r
+ case Thread::Priority::normal: break;\r
+ }\r
+\r
+ return QOS_CLASS_DEFAULT;\r
+}\r
+\r
+API_AVAILABLE (macos (10.10))\r
+static auto getJucePriority (qos_class_t qos)\r
+{\r
+ switch (qos)\r
+ {\r
+ case QOS_CLASS_USER_INTERACTIVE: return Thread::Priority::highest;\r
+ case QOS_CLASS_USER_INITIATED: return Thread::Priority::high;\r
+ case QOS_CLASS_UTILITY: return Thread::Priority::low;\r
+ case QOS_CLASS_BACKGROUND: return Thread::Priority::background;\r
+\r
+ case QOS_CLASS_UNSPECIFIED:\r
+ case QOS_CLASS_DEFAULT: break;\r
+ }\r
+\r
+ return Thread::Priority::normal;\r
+}\r
+\r
+bool Thread::createNativeThread (Priority priority)\r
+{\r
+ PosixThreadAttribute attr { threadStackSize };\r
+\r
+ if (@available (macos 10.10, *))\r
+ pthread_attr_set_qos_class_np (attr.get(), getNativeQOS (priority), 0);\r
+ else\r
+ PosixSchedulerPriority::getNativeSchedulerAndPriority (realtimeOptions, priority).apply (attr);\r
+\r
+ threadId = threadHandle = makeThreadHandle (attr, this, [] (void* userData) -> void*\r
+ {\r
+ auto* myself = static_cast<Thread*> (userData);\r
+\r
+ JUCE_AUTORELEASEPOOL\r
+ {\r
+ juce_threadEntryPoint (myself);\r
+ }\r
+\r
+ return nullptr;\r
+ });\r
+\r
+ return threadId != nullptr;\r
+}\r
+\r
+void Thread::killThread()\r
+{\r
+ if (threadHandle != nullptr)\r
+ pthread_cancel ((pthread_t) threadHandle.load());\r
+}\r
+\r
+Thread::Priority Thread::getPriority() const\r
+{\r
+ jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+ if (! isRealtime())\r
+ {\r
+ if (@available (macOS 10.10, *))\r
+ return getJucePriority (qos_class_self());\r
+\r
+ // fallback for older versions of macOS\r
+ const auto min = jmax (0, sched_get_priority_min (SCHED_OTHER));\r
+ const auto max = jmax (0, sched_get_priority_max (SCHED_OTHER));\r
+\r
+ if (min != 0 && max != 0)\r
+ {\r
+ const auto native = PosixSchedulerPriority::findCurrentSchedulerAndPriority().getPriority();\r
+ const auto mapped = jmap (native, min, max, 0, 4);\r
+ return ThreadPriorities::getJucePriority (mapped);\r
+ }\r
+ }\r
+\r
+ return {};\r
+}\r
+\r
+bool Thread::setPriority (Priority priority)\r
+{\r
+ jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+ if (isRealtime())\r
+ {\r
+ // macOS/iOS needs to know how much time you need!\r
+ jassert (realtimeOptions->workDurationMs > 0);\r
+\r
+ mach_timebase_info_data_t timebase;\r
+ mach_timebase_info (&timebase);\r
+\r
+ const auto periodMs = realtimeOptions->workDurationMs;\r
+ const auto ticksPerMs = ((double) timebase.denom * 1000000.0) / (double) timebase.numer;\r
+ const auto periodTicks = (uint32_t) jmin ((double) std::numeric_limits<uint32_t>::max(), periodMs * ticksPerMs);\r
+\r
+ thread_time_constraint_policy_data_t policy;\r
+ policy.period = periodTicks;\r
+ policy.computation = jmin ((uint32_t) 50000, policy.period);\r
+ policy.constraint = policy.period;\r
+ policy.preemptible = true;\r
+\r
+ return thread_policy_set (pthread_mach_thread_np (pthread_self()),\r
+ THREAD_TIME_CONSTRAINT_POLICY,\r
+ (thread_policy_t) &policy,\r
+ THREAD_TIME_CONSTRAINT_POLICY_COUNT) == KERN_SUCCESS;\r
+ }\r
+\r
+ if (@available (macOS 10.10, *))\r
+ return pthread_set_qos_class_self_np (getNativeQOS (priority), 0) == 0;\r
+\r
+ #if JUCE_ARM\r
+ // M1 platforms should never reach this code!!!!!!\r
+ jassertfalse;\r
+ #endif\r
+\r
+ // Just in case older versions of macOS support SCHED_OTHER priorities.\r
+ const auto psp = PosixSchedulerPriority::getNativeSchedulerAndPriority ({}, priority);\r
+\r
+ struct sched_param param;\r
+ param.sched_priority = psp.getPriority();\r
+ return pthread_setschedparam (pthread_self(), psp.getScheduler(), ¶m) == 0;\r
+}\r
+\r
//==============================================================================\r
JUCE_API bool JUCE_CALLTYPE Process::isForegroundProcess()\r
{\r
--- /dev/null
+/*\r
+ ==============================================================================\r
+\r
+ This file is part of the JUCE library.\r
+ Copyright (c) 2022 - Raw Material Software Limited\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
+struct ThreadPriorities\r
+{\r
+ struct Entry\r
+ {\r
+ Thread::Priority priority;\r
+ int native;\r
+ };\r
+\r
+ #if JUCE_ANDROID\r
+ enum AndroidThreadPriority\r
+ {\r
+ THREAD_PRIORITY_AUDIO = -16,\r
+ THREAD_PRIORITY_FOREGROUND = -2,\r
+ THREAD_PRIORITY_MORE_FAVORABLE = -1,\r
+ THREAD_PRIORITY_DEFAULT = 0,\r
+ THREAD_PRIORITY_LESS_FAVORABLE = 1,\r
+ THREAD_PRIORITY_BACKGROUND = 10,\r
+ THREAD_PRIORITY_LOWEST = 19\r
+ };\r
+ #endif\r
+\r
+ inline static constexpr Entry table[]\r
+ {\r
+ #if JUCE_ANDROID\r
+ { Thread::Priority::highest, AndroidThreadPriority::THREAD_PRIORITY_AUDIO },\r
+ { Thread::Priority::high, AndroidThreadPriority::THREAD_PRIORITY_FOREGROUND },\r
+ { Thread::Priority::normal, AndroidThreadPriority::THREAD_PRIORITY_DEFAULT },\r
+ { Thread::Priority::low, AndroidThreadPriority::THREAD_PRIORITY_BACKGROUND - 5 },\r
+ { Thread::Priority::background, AndroidThreadPriority::THREAD_PRIORITY_BACKGROUND },\r
+ #endif\r
+\r
+ #if JUCE_LINUX || JUCE_BSD\r
+ { Thread::Priority::highest, 0 },\r
+ { Thread::Priority::high, 0 },\r
+ { Thread::Priority::normal, 0 },\r
+ { Thread::Priority::low, 0 },\r
+ { Thread::Priority::background, 0 },\r
+ #endif\r
+\r
+ #if JUCE_MAC || JUCE_IOS\r
+ { Thread::Priority::highest, 4 },\r
+ { Thread::Priority::high, 3 },\r
+ { Thread::Priority::normal, 2 },\r
+ { Thread::Priority::low, 1 },\r
+ { Thread::Priority::background, 0 },\r
+ #endif\r
+\r
+ #if JUCE_WINDOWS\r
+ { Thread::Priority::highest, THREAD_PRIORITY_TIME_CRITICAL },\r
+ { Thread::Priority::high, THREAD_PRIORITY_HIGHEST },\r
+ { Thread::Priority::normal, THREAD_PRIORITY_NORMAL },\r
+ { Thread::Priority::low, THREAD_PRIORITY_LOWEST },\r
+ { Thread::Priority::background, THREAD_PRIORITY_IDLE },\r
+ #endif\r
+ };\r
+\r
+ static_assert (std::size (table) == 5,\r
+ "The platform may be unsupported or there may be a priority entry missing.");\r
+\r
+ static Thread::Priority getJucePriority (const int value)\r
+ {\r
+ const auto iter = std::min_element (std::begin (table),\r
+ std::end (table),\r
+ [value] (const auto& a, const auto& b)\r
+ {\r
+ return std::abs (a.native - value) < std::abs (b.native - value);\r
+ });\r
+\r
+ jassert (iter != std::end (table));\r
+ return iter != std::end (table) ? iter->priority : Thread::Priority{};\r
+ }\r
+\r
+ static int getNativePriority (const Thread::Priority value)\r
+ {\r
+ const auto iter = std::find_if (std::begin (table),\r
+ std::end (table),\r
+ [value] (const auto& entry) { return entry.priority == value; });\r
+\r
+ jassert (iter != std::end (table));\r
+ return iter != std::end (table) ? iter->native : 0;\r
+ }\r
+};\r
+\r
+} // namespace juce\r
pimpl.reset();\r
}\r
\r
-//==============================================================================\r
-#if JUCE_ANDROID\r
-extern JavaVM* androidJNIJavaVM;\r
-#endif\r
-\r
-static void* threadEntryProc (void* userData)\r
+class PosixThreadAttribute\r
{\r
- auto* myself = static_cast<Thread*> (userData);\r
-\r
- JUCE_AUTORELEASEPOOL\r
+public:\r
+ explicit PosixThreadAttribute (size_t stackSize)\r
{\r
- juce_threadEntryPoint (myself);\r
+ if (valid)\r
+ pthread_attr_setstacksize (&attr, stackSize);\r
}\r
\r
- #if JUCE_ANDROID\r
- if (androidJNIJavaVM != nullptr)\r
+ ~PosixThreadAttribute()\r
{\r
- void* env = nullptr;\r
- androidJNIJavaVM->GetEnv(&env, JNI_VERSION_1_2);\r
-\r
- // only detach if we have actually been attached\r
- if (env != nullptr)\r
- androidJNIJavaVM->DetachCurrentThread();\r
+ if (valid)\r
+ pthread_attr_destroy (&attr);\r
}\r
- #endif\r
\r
- return nullptr;\r
-}\r
-\r
-#if JUCE_ANDROID && JUCE_MODULE_AVAILABLE_juce_audio_devices && (JUCE_USE_ANDROID_OPENSLES || JUCE_USE_ANDROID_OBOE)\r
- #define JUCE_ANDROID_REALTIME_THREAD_AVAILABLE 1\r
-#endif\r
+ auto* get() { return valid ? &attr : nullptr; }\r
\r
-#if JUCE_ANDROID_REALTIME_THREAD_AVAILABLE\r
-extern pthread_t juce_createRealtimeAudioThread (void* (*entry) (void*), void* userPtr);\r
-#endif\r
+private:\r
+ pthread_attr_t attr;\r
+ bool valid { pthread_attr_init (&attr) == 0 };\r
+};\r
\r
-void Thread::launchThread()\r
+class PosixSchedulerPriority\r
{\r
- #if JUCE_ANDROID\r
- if (isAndroidRealtimeThread)\r
+public:\r
+ static PosixSchedulerPriority findCurrentSchedulerAndPriority()\r
{\r
- #if JUCE_ANDROID_REALTIME_THREAD_AVAILABLE\r
- threadHandle = (void*) juce_createRealtimeAudioThread (threadEntryProc, this);\r
- threadId = (ThreadID) threadHandle.get();\r
-\r
- return;\r
- #else\r
- jassertfalse;\r
- #endif\r
+ int scheduler{};\r
+ sched_param param{};\r
+ pthread_getschedparam (pthread_self(), &scheduler, ¶m);\r
+ return { scheduler, param.sched_priority };\r
}\r
- #endif\r
\r
- threadHandle = {};\r
- pthread_t handle = {};\r
- pthread_attr_t attr;\r
- pthread_attr_t* attrPtr = nullptr;\r
-\r
- if (pthread_attr_init (&attr) == 0)\r
+ static PosixSchedulerPriority getNativeSchedulerAndPriority (const Optional<Thread::RealtimeOptions>& rt,\r
+ [[maybe_unused]] Thread::Priority prio)\r
{\r
- attrPtr = &attr;\r
- pthread_attr_setstacksize (attrPtr, threadStackSize);\r
- }\r
+ const auto isRealtime = rt.hasValue();\r
+\r
+ const auto priority = [&]\r
+ {\r
+ if (isRealtime)\r
+ {\r
+ const auto min = jmax (0, sched_get_priority_min (SCHED_RR));\r
+ const auto max = jmax (1, sched_get_priority_max (SCHED_RR));\r
+\r
+ return jmap (rt->priority, 0, 10, min, max);\r
+ }\r
+\r
+ // We only use this helper if we're on an old macos/ios platform that might\r
+ // still respect legacy pthread priorities for SCHED_OTHER.\r
+ #if JUCE_MAC || JUCE_IOS\r
+ const auto min = jmax (0, sched_get_priority_min (SCHED_OTHER));\r
+ const auto max = jmax (0, sched_get_priority_max (SCHED_OTHER));\r
+\r
+ const auto p = [prio]\r
+ {\r
+ switch (prio)\r
+ {\r
+ case Thread::Priority::highest: return 4;\r
+ case Thread::Priority::high: return 3;\r
+ case Thread::Priority::normal: return 2;\r
+ case Thread::Priority::low: return 1;\r
+ case Thread::Priority::background: return 0;\r
+ }\r
+\r
+ return 3;\r
+ }();\r
+\r
+ if (min != 0 && max != 0)\r
+ return jmap (p, 0, 4, min, max);\r
+ #endif\r
+\r
+ return 0;\r
+ }();\r
+\r
+ #if JUCE_MAC || JUCE_IOS\r
+ const auto scheduler = SCHED_OTHER;\r
+ #elif JUCE_LINUX || JUCE_BSD\r
+ const auto backgroundSched = prio == Thread::Priority::background ? SCHED_IDLE\r
+ : SCHED_OTHER;\r
+ const auto scheduler = isRealtime ? SCHED_RR : backgroundSched;\r
+ #else\r
+ const auto scheduler = 0;\r
+ #endif\r
\r
+ return { scheduler, priority };\r
+ }\r
\r
- if (pthread_create (&handle, attrPtr, threadEntryProc, this) == 0)\r
+ void apply ([[maybe_unused]] PosixThreadAttribute& attr) const\r
{\r
- pthread_detach (handle);\r
- threadHandle = (void*) handle;\r
- threadId = (ThreadID) threadHandle.get();\r
+ #if JUCE_LINUX || JUCE_BSD\r
+ const struct sched_param param { getPriority() };\r
+\r
+ pthread_attr_setinheritsched (attr.get(), PTHREAD_EXPLICIT_SCHED);\r
+ pthread_attr_setschedpolicy (attr.get(), getScheduler());\r
+ pthread_attr_setschedparam (attr.get(), ¶m);\r
+ #endif\r
}\r
\r
- if (attrPtr != nullptr)\r
- pthread_attr_destroy (attrPtr);\r
-}\r
+ constexpr int getScheduler() const { return scheduler; }\r
+ constexpr int getPriority() const { return priority; }\r
\r
-void Thread::closeThreadHandle()\r
+private:\r
+ constexpr PosixSchedulerPriority (int schedulerIn, int priorityIn)\r
+ : scheduler (schedulerIn), priority (priorityIn) {}\r
+\r
+ int scheduler;\r
+ int priority;\r
+};\r
+\r
+static void* makeThreadHandle (PosixThreadAttribute& attr, Thread* userData, void* (*threadEntryProc) (void*))\r
{\r
- threadId = {};\r
- threadHandle = {};\r
+ pthread_t handle = {};\r
+\r
+ if (pthread_create (&handle, attr.get(), threadEntryProc, userData) != 0)\r
+ return nullptr;\r
+\r
+ pthread_detach (handle);\r
+ return (void*) handle;\r
}\r
\r
-void Thread::killThread()\r
+void Thread::closeThreadHandle()\r
{\r
- if (threadHandle.get() != nullptr)\r
- {\r
- #if JUCE_ANDROID\r
- jassertfalse; // pthread_cancel not available!\r
- #else\r
- pthread_cancel ((pthread_t) threadHandle.get());\r
- #endif\r
- }\r
+ threadId = {};\r
+ threadHandle = nullptr;\r
}\r
\r
void JUCE_CALLTYPE Thread::setCurrentThreadName (const String& name)\r
#endif\r
}\r
\r
-bool Thread::setThreadPriority (void* handle, int priority)\r
-{\r
- constexpr auto maxInputPriority = 10;\r
-\r
- #if JUCE_LINUX || JUCE_BSD\r
- constexpr auto lowestRrPriority = 8;\r
- #else\r
- constexpr auto lowestRrPriority = 0;\r
- #endif\r
-\r
- struct sched_param param;\r
- int policy;\r
-\r
- if (handle == nullptr)\r
- handle = (void*) pthread_self();\r
-\r
- if (pthread_getschedparam ((pthread_t) handle, &policy, ¶m) != 0)\r
- return false;\r
-\r
- policy = priority < lowestRrPriority ? SCHED_OTHER : SCHED_RR;\r
-\r
- const auto minPriority = sched_get_priority_min (policy);\r
- const auto maxPriority = sched_get_priority_max (policy);\r
-\r
- param.sched_priority = [&]\r
- {\r
- if (policy == SCHED_OTHER)\r
- return 0;\r
-\r
- return jmap (priority, lowestRrPriority, maxInputPriority, minPriority, maxPriority);\r
- }();\r
-\r
- return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0;\r
-}\r
-\r
Thread::ThreadID JUCE_CALLTYPE Thread::getCurrentThreadId()\r
{\r
return (ThreadID) pthread_self();\r
\r
#endif\r
\r
-//==============================================================================\r
-struct HighResolutionTimer::Pimpl\r
-{\r
- explicit Pimpl (HighResolutionTimer& t)\r
- : owner (t)\r
- {}\r
-\r
- ~Pimpl()\r
- {\r
- jassert (periodMs == 0);\r
- stop();\r
- }\r
-\r
- void start (int newPeriod)\r
- {\r
- if (periodMs == newPeriod)\r
- return;\r
-\r
- if (thread.get_id() == std::this_thread::get_id())\r
- {\r
- periodMs = newPeriod;\r
- return;\r
- }\r
-\r
- stop();\r
-\r
- periodMs = newPeriod;\r
-\r
- thread = std::thread ([this, newPeriod]\r
- {\r
- setThisThreadToRealtime ((uint64) newPeriod);\r
-\r
- auto lastPeriod = periodMs.load();\r
- Clock clock (lastPeriod);\r
-\r
- std::unique_lock<std::mutex> unique_lock (timerMutex);\r
-\r
- while (periodMs != 0)\r
- {\r
- clock.next();\r
- while (periodMs != 0 && clock.wait (stopCond, unique_lock));\r
-\r
- if (periodMs == 0)\r
- break;\r
-\r
- owner.hiResTimerCallback();\r
-\r
- auto nextPeriod = periodMs.load();\r
-\r
- if (lastPeriod != nextPeriod)\r
- {\r
- lastPeriod = nextPeriod;\r
- clock = Clock (lastPeriod);\r
- }\r
- }\r
-\r
- periodMs = 0;\r
- });\r
- }\r
-\r
- void stop()\r
- {\r
- periodMs = 0;\r
-\r
- const auto thread_id = thread.get_id();\r
-\r
- if (thread_id == std::thread::id() || thread_id == std::this_thread::get_id())\r
- return;\r
-\r
- {\r
- std::unique_lock<std::mutex> unique_lock (timerMutex);\r
- stopCond.notify_one();\r
- }\r
-\r
- thread.join();\r
- }\r
-\r
- HighResolutionTimer& owner;\r
- std::atomic<int> periodMs { 0 };\r
-\r
-private:\r
- std::thread thread;\r
- std::condition_variable stopCond;\r
- std::mutex timerMutex;\r
-\r
- class Clock\r
- {\r
- public:\r
- explicit Clock (std::chrono::steady_clock::rep millis) noexcept\r
- : time (std::chrono::steady_clock::now()),\r
- delta (std::chrono::milliseconds (millis))\r
- {}\r
-\r
- bool wait (std::condition_variable& cond, std::unique_lock<std::mutex>& lock) noexcept\r
- {\r
- return cond.wait_until (lock, time) != std::cv_status::timeout;\r
- }\r
-\r
- void next() noexcept\r
- {\r
- time += delta;\r
- }\r
-\r
- private:\r
- std::chrono::time_point<std::chrono::steady_clock> time;\r
- std::chrono::steady_clock::duration delta;\r
- };\r
-\r
- static bool setThisThreadToRealtime (uint64 periodMs)\r
- {\r
- const auto thread = pthread_self();\r
-\r
- #if JUCE_MAC || JUCE_IOS\r
- mach_timebase_info_data_t timebase;\r
- mach_timebase_info (&timebase);\r
-\r
- const auto ticksPerMs = ((double) timebase.denom * 1000000.0) / (double) timebase.numer;\r
- const auto periodTicks = (uint32_t) jmin ((double) std::numeric_limits<uint32_t>::max(), periodMs * ticksPerMs);\r
-\r
- thread_time_constraint_policy_data_t policy;\r
- policy.period = periodTicks;\r
- policy.computation = jmin ((uint32_t) 50000, policy.period);\r
- policy.constraint = policy.period;\r
- policy.preemptible = true;\r
-\r
- return thread_policy_set (pthread_mach_thread_np (thread),\r
- THREAD_TIME_CONSTRAINT_POLICY,\r
- (thread_policy_t) &policy,\r
- THREAD_TIME_CONSTRAINT_POLICY_COUNT) == KERN_SUCCESS;\r
-\r
- #else\r
- ignoreUnused (periodMs);\r
- struct sched_param param;\r
- param.sched_priority = sched_get_priority_max (SCHED_RR);\r
- return pthread_setschedparam (thread, SCHED_RR, ¶m) == 0;\r
- #endif\r
- }\r
-\r
- JUCE_DECLARE_NON_COPYABLE (Pimpl)\r
-};\r
-\r
} // namespace juce\r
namespace juce\r
{\r
\r
-#if JUCE_MSVC && ! defined (__INTEL_COMPILER)\r
- #pragma intrinsic (__cpuid)\r
- #pragma intrinsic (__rdtsc)\r
-#endif\r
-\r
void Logger::outputDebugString (const String& text)\r
{\r
OutputDebugString ((text + "\n").toWideCharPointer());\r
JUCE_API void juceDLL_free (void* block) { std::free (block); }\r
#endif\r
\r
+static int findNumberOfPhysicalCores() noexcept\r
+{\r
+ #if JUCE_MINGW\r
+ // Not implemented in MinGW\r
+ jassertfalse;\r
+\r
+ return 1;\r
+ #else\r
+\r
+ DWORD bufferSize = 0;\r
+ GetLogicalProcessorInformation (nullptr, &bufferSize);\r
+\r
+ const auto numBuffers = (size_t) (bufferSize / sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION));\r
+\r
+ if (numBuffers == 0)\r
+ {\r
+ jassertfalse;\r
+ return 0;\r
+ };\r
+\r
+ HeapBlock<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer (numBuffers);\r
+\r
+ if (! GetLogicalProcessorInformation (buffer, &bufferSize))\r
+ {\r
+ jassertfalse;\r
+ return 0;\r
+ }\r
+\r
+ return (int) std::count_if (buffer.get(), buffer.get() + numBuffers, [] (const auto& info)\r
+ {\r
+ return info.Relationship == RelationProcessorCore;\r
+ });\r
+\r
+ #endif // JUCE_MINGW\r
+}\r
+\r
//==============================================================================\r
+#if JUCE_INTEL\r
+ #if JUCE_MSVC && ! defined (__INTEL_COMPILER)\r
+ #pragma intrinsic (__cpuid)\r
+ #pragma intrinsic (__rdtsc)\r
+ #endif\r
\r
-#if JUCE_MINGW || JUCE_CLANG\r
+ #if JUCE_MINGW || JUCE_CLANG\r
static void callCPUID (int result[4], uint32 type)\r
{\r
uint32 la = (uint32) result[0], lb = (uint32) result[1],\r
result[0] = (int) la; result[1] = (int) lb;\r
result[2] = (int) lc; result[3] = (int) ld;\r
}\r
-#else\r
+ #else\r
static void callCPUID (int result[4], int infoType)\r
{\r
__cpuid (result, infoType);\r
}\r
-#endif\r
+ #endif\r
\r
String SystemStats::getCpuVendor()\r
{\r
return String (name).trim();\r
}\r
\r
-static int findNumberOfPhysicalCores() noexcept\r
-{\r
- #if JUCE_MINGW\r
- // Not implemented in MinGW\r
- jassertfalse;\r
-\r
- return 1;\r
- #else\r
-\r
- int numPhysicalCores = 0;\r
- DWORD bufferSize = 0;\r
- GetLogicalProcessorInformation (nullptr, &bufferSize);\r
-\r
- if (auto numBuffers = (size_t) (bufferSize / sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)))\r
- {\r
- HeapBlock<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer (numBuffers);\r
-\r
- if (GetLogicalProcessorInformation (buffer, &bufferSize))\r
- for (size_t i = 0; i < numBuffers; ++i)\r
- if (buffer[i].Relationship == RelationProcessorCore)\r
- ++numPhysicalCores;\r
- }\r
-\r
- return numPhysicalCores;\r
- #endif // JUCE_MINGW\r
-}\r
-\r
-//==============================================================================\r
void CPUInformation::initialise() noexcept\r
{\r
int info[4] = { 0 };\r
if (numPhysicalCPUs <= 0)\r
numPhysicalCPUs = numLogicalCPUs;\r
}\r
+#elif JUCE_ARM\r
+String SystemStats::getCpuVendor()\r
+{\r
+ static const auto cpuVendor = []\r
+ {\r
+ static constexpr auto* path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\VendorIdentifier";\r
+ auto vendor = RegistryKeyWrapper::getValue (path, {}, 0).trim();\r
+\r
+ return vendor.isEmpty() ? String ("Unknown Vendor") : vendor;\r
+ }();\r
+\r
+ return cpuVendor;\r
+}\r
+\r
+String SystemStats::getCpuModel()\r
+{\r
+ static const auto cpuModel = []\r
+ {\r
+ static constexpr auto* path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\ProcessorNameString";\r
+ auto model = RegistryKeyWrapper::getValue (path, {}, 0).trim();\r
+\r
+ return model.isEmpty() ? String ("Unknown Model") : model;\r
+ }();\r
+\r
+ return cpuModel;\r
+}\r
+\r
+void CPUInformation::initialise() noexcept\r
+{\r
+ // Windows for arm requires at least armv7 which has neon support\r
+ hasNeon = true;\r
+\r
+ SYSTEM_INFO systemInfo;\r
+ GetNativeSystemInfo (&systemInfo);\r
+ numLogicalCPUs = (int) systemInfo.dwNumberOfProcessors;\r
+ numPhysicalCPUs = findNumberOfPhysicalCores();\r
+\r
+ if (numPhysicalCPUs <= 0)\r
+ numPhysicalCPUs = numLogicalCPUs;\r
+}\r
+#else\r
+ #error Unknown CPU architecture type\r
+#endif\r
\r
#if JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS\r
struct DebugFlagsInitialiser\r
if (major == 5 && minor == 0) return Win2000;\r
\r
jassertfalse;\r
- return UnknownOS;\r
+ return Windows;\r
}\r
\r
String SystemStats::getOperatingSystemName()\r
case MacOSX_10_15: JUCE_FALLTHROUGH\r
case MacOS_11: JUCE_FALLTHROUGH\r
case MacOS_12: JUCE_FALLTHROUGH\r
+ case MacOS_13: JUCE_FALLTHROUGH\r
\r
case UnknownOS: JUCE_FALLTHROUGH\r
case WASM: JUCE_FALLTHROUGH\r
//==============================================================================\r
static int64 juce_getClockCycleCounter() noexcept\r
{\r
- #if JUCE_MSVC\r
+ #if JUCE_MSVC\r
+ #if JUCE_INTEL\r
// MS intrinsics version...\r
return (int64) __rdtsc();\r
-\r
- #elif JUCE_GCC || JUCE_CLANG\r
+ #elif JUCE_ARM\r
+ #if defined (_M_ARM)\r
+ return __rdpmccntr64();\r
+ #elif defined (_M_ARM64)\r
+ return _ReadStatusReg (ARM64_PMCCNTR_EL0);\r
+ #else\r
+ #error Unknown arm architecture\r
+ #endif\r
+ #endif\r
+ #elif JUCE_GCC || JUCE_CLANG\r
+ #if JUCE_INTEL\r
// GNU inline asm version...\r
unsigned int hi = 0, lo = 0;\r
\r
: "cc", "eax", "ebx", "ecx", "edx", "memory");\r
\r
return (int64) ((((uint64) hi) << 32) | lo);\r
- #else\r
- #error "unknown compiler?"\r
- #endif\r
+ #elif JUCE_ARM\r
+ int64 retval;\r
+\r
+ __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r"(retval));\r
+ return retval;\r
+ #endif\r
+ #else\r
+ #error "unknown compiler?"\r
+ #endif\r
}\r
\r
int SystemStats::getCpuSpeedInMegahertz()\r
return languagesBuffer.data();\r
}\r
\r
+String SystemStats::getUniqueDeviceID()\r
+{\r
+ #define PROVIDER(string) (DWORD) (string[0] << 24 | string[1] << 16 | string[2] << 8 | string[3])\r
+\r
+ auto bufLen = GetSystemFirmwareTable (PROVIDER ("RSMB"), PROVIDER ("RSDT"), nullptr, 0);\r
+\r
+ if (bufLen > 0)\r
+ {\r
+ HeapBlock<uint8_t> buffer { bufLen };\r
+ GetSystemFirmwareTable (PROVIDER ("RSMB"), PROVIDER ("RSDT"), (void*) buffer.getData(), bufLen);\r
+\r
+ return [&]\r
+ {\r
+ uint64_t hash = 0;\r
+ const auto start = buffer.getData();\r
+ const auto end = start + jmin (1024, (int) bufLen);\r
+\r
+ for (auto dataPtr = start; dataPtr != end; ++dataPtr)\r
+ hash = hash * (uint64_t) 101 + *dataPtr;\r
+\r
+ return String (hash);\r
+ }();\r
+ }\r
+\r
+ // Please tell someone at JUCE if this occurs\r
+ jassertfalse;\r
+ return {};\r
+}\r
+\r
} // namespace juce\r
bool CriticalSection::tryEnter() const noexcept { return TryEnterCriticalSection ((CRITICAL_SECTION*) &lock) != FALSE; }\r
void CriticalSection::exit() const noexcept { LeaveCriticalSection ((CRITICAL_SECTION*) &lock); }\r
\r
-\r
//==============================================================================\r
static unsigned int STDMETHODCALLTYPE threadEntryProc (void* userData)\r
{\r
return 0;\r
}\r
\r
-void Thread::launchThread()\r
+static bool setPriorityInternal (bool isRealtime, HANDLE handle, Thread::Priority priority)\r
+{\r
+ auto nativeThreadFlag = isRealtime ? THREAD_PRIORITY_TIME_CRITICAL\r
+ : ThreadPriorities::getNativePriority (priority);\r
+\r
+ if (isRealtime) // This should probably be a fail state too?\r
+ Process::setPriority (Process::ProcessPriority::RealtimePriority);\r
+\r
+ return SetThreadPriority (handle, nativeThreadFlag);\r
+}\r
+\r
+bool Thread::createNativeThread (Priority priority)\r
{\r
unsigned int newThreadId;\r
threadHandle = (void*) _beginthreadex (nullptr, (unsigned int) threadStackSize,\r
- &threadEntryProc, this, 0, &newThreadId);\r
- threadId = (ThreadID) (pointer_sized_int) newThreadId;\r
+ &threadEntryProc, this, CREATE_SUSPENDED,\r
+ &newThreadId);\r
+\r
+ if (threadHandle != nullptr)\r
+ {\r
+ threadId = (ThreadID) (pointer_sized_int) newThreadId;\r
+\r
+ if (setPriorityInternal (isRealtime(), threadHandle, priority))\r
+ {\r
+ ResumeThread (threadHandle);\r
+ return true;\r
+ }\r
+\r
+ killThread();\r
+ closeThreadHandle();\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+Thread::Priority Thread::getPriority() const\r
+{\r
+ jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+ const auto native = GetThreadPriority (threadHandle);\r
+ return ThreadPriorities::getJucePriority (native);\r
+}\r
+\r
+bool Thread::setPriority (Priority priority)\r
+{\r
+ jassert (Thread::getCurrentThreadId() == getThreadId());\r
+ return setPriorityInternal (isRealtime(), this, priority);\r
}\r
\r
void Thread::closeThreadHandle()\r
{\r
- CloseHandle ((HANDLE) threadHandle.get());\r
+ CloseHandle (threadHandle);\r
threadId = nullptr;\r
threadHandle = nullptr;\r
}\r
\r
void Thread::killThread()\r
{\r
- if (threadHandle.get() != nullptr)\r
+ if (threadHandle != nullptr)\r
{\r
#if JUCE_DEBUG\r
OutputDebugStringA ("** Warning - Forced thread termination **\n");\r
#endif\r
\r
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6258)\r
- TerminateThread (threadHandle.get(), 0);\r
+ TerminateThread (threadHandle, 0);\r
JUCE_END_IGNORE_WARNINGS_MSVC\r
}\r
}\r
return (ThreadID) (pointer_sized_int) GetCurrentThreadId();\r
}\r
\r
-bool Thread::setThreadPriority (void* handle, int priority)\r
-{\r
- int pri = THREAD_PRIORITY_TIME_CRITICAL;\r
-\r
- if (priority < 1) pri = THREAD_PRIORITY_IDLE;\r
- else if (priority < 2) pri = THREAD_PRIORITY_LOWEST;\r
- else if (priority < 5) pri = THREAD_PRIORITY_BELOW_NORMAL;\r
- else if (priority < 7) pri = THREAD_PRIORITY_NORMAL;\r
- else if (priority < 9) pri = THREAD_PRIORITY_ABOVE_NORMAL;\r
- else if (priority < 10) pri = THREAD_PRIORITY_HIGHEST;\r
-\r
- if (handle == nullptr)\r
- handle = GetCurrentThread();\r
-\r
- return SetThreadPriority (handle, pri) != FALSE;\r
-}\r
-\r
void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)\r
{\r
SetThreadAffinityMask (GetCurrentThread(), affinityMask);\r
}\r
}\r
\r
-void JUCE_CALLTYPE Process::setPriority (ProcessPriority prior)\r
+void JUCE_CALLTYPE Process::setPriority (ProcessPriority newPriority)\r
{\r
- if (lastProcessPriority != (int) prior)\r
+ if (lastProcessPriority != (int) newPriority)\r
{\r
- lastProcessPriority = (int) prior;\r
+ lastProcessPriority = (int) newPriority;\r
juce_repeatLastProcessPriority();\r
}\r
}\r
return start (escaped.trim(), streamFlags);\r
}\r
\r
-//==============================================================================\r
-struct HighResolutionTimer::Pimpl\r
-{\r
- Pimpl (HighResolutionTimer& t) noexcept : owner (t)\r
- {\r
- }\r
-\r
- ~Pimpl()\r
- {\r
- jassert (periodMs == 0);\r
- }\r
-\r
- void start (int newPeriod)\r
- {\r
- if (newPeriod != periodMs)\r
- {\r
- stop();\r
- periodMs = newPeriod;\r
-\r
- TIMECAPS tc;\r
- if (timeGetDevCaps (&tc, sizeof (tc)) == TIMERR_NOERROR)\r
- {\r
- const int actualPeriod = jlimit ((int) tc.wPeriodMin, (int) tc.wPeriodMax, newPeriod);\r
-\r
- timerID = timeSetEvent ((UINT) actualPeriod, tc.wPeriodMin, callbackFunction, (DWORD_PTR) this,\r
- TIME_PERIODIC | TIME_CALLBACK_FUNCTION | 0x100 /*TIME_KILL_SYNCHRONOUS*/);\r
- }\r
- }\r
- }\r
-\r
- void stop()\r
- {\r
- periodMs = 0;\r
- timeKillEvent (timerID);\r
- }\r
-\r
- HighResolutionTimer& owner;\r
- int periodMs = 0;\r
-\r
-private:\r
- unsigned int timerID;\r
-\r
- static void STDMETHODCALLTYPE callbackFunction (UINT, UINT, DWORD_PTR userInfo, DWORD_PTR, DWORD_PTR)\r
- {\r
- if (Pimpl* const timer = reinterpret_cast<Pimpl*> (userInfo))\r
- if (timer->periodMs != 0)\r
- timer->owner.hiResTimerCallback();\r
- }\r
-\r
- JUCE_DECLARE_NON_COPYABLE (Pimpl)\r
-};\r
-\r
} // namespace juce\r
\r
void URL::init()\r
{\r
- auto i = url.indexOfChar ('?');\r
+ auto i = url.indexOfChar ('#');\r
+\r
+ if (i >= 0)\r
+ {\r
+ anchor = removeEscapeChars (url.substring (i + 1));\r
+ url = url.upToFirstOccurrenceOf ("#", false, false);\r
+ }\r
+\r
+ i = url.indexOfChar ('?');\r
\r
if (i >= 0)\r
{\r
\r
String URL::getQueryString() const\r
{\r
+ String result;\r
+\r
if (parameterNames.size() > 0)\r
- return "?" + URLHelpers::getMangledParameters (*this);\r
+ result += "?" + URLHelpers::getMangledParameters (*this);\r
+\r
+ if (anchor.isNotEmpty())\r
+ result += getAnchorString();\r
+\r
+ return result;\r
+}\r
+\r
+String URL::getAnchorString() const\r
+{\r
+ if (anchor.isNotEmpty())\r
+ return "#" + URL::addEscapeChars (anchor, true);\r
\r
return {};\r
}\r
return u;\r
}\r
\r
+URL URL::withAnchor (const String& anchorToAdd) const\r
+{\r
+ auto u = *this;\r
+\r
+ u.anchor = anchorToAdd;\r
+ return u;\r
+}\r
+\r
URL URL::withPOSTData (const String& newPostData) const\r
{\r
return withPOSTData (MemoryBlock (newPostData.toRawUTF8(), newPostData.getNumBytesAsUTF8()));\r
*/\r
String getQueryString() const;\r
\r
+ /** If any anchor is set, returns URL-encoded anchor, including the "#"\r
+ prefix.\r
+ */\r
+ String getAnchorString() const;\r
+\r
/** Returns the scheme of the URL.\r
\r
e.g. for "http://www.xyz.com/foobar", this will return "http" (it won't\r
\r
@see withNewSubPath\r
*/\r
- JUCE_NODISCARD URL withNewDomainAndPath (const String& newFullPath) const;\r
+ [[nodiscard]] URL withNewDomainAndPath (const String& newFullPath) const;\r
\r
/** Returns a new version of this URL with a different sub-path.\r
\r
\r
@see withNewDomainAndPath\r
*/\r
- JUCE_NODISCARD URL withNewSubPath (const String& newPath) const;\r
+ [[nodiscard]] URL withNewSubPath (const String& newPath) const;\r
\r
/** Attempts to return a URL which is the parent folder containing this URL.\r
\r
\r
@see getParameterNames, getParameterValues\r
*/\r
- JUCE_NODISCARD URL withParameter (const String& parameterName,\r
- const String& parameterValue) const;\r
+ [[nodiscard]] URL withParameter (const String& parameterName,\r
+ const String& parameterValue) const;\r
\r
/** Returns a copy of this URL, with a set of GET or POST parameters added.\r
\r
\r
@see withParameter\r
*/\r
- JUCE_NODISCARD URL withParameters (const StringPairArray& parametersToAdd) const;\r
+ [[nodiscard]] URL withParameters (const StringPairArray& parametersToAdd) const;\r
+\r
+ /** Returns a copy of this URL, with an anchor added to the end of the URL.\r
+ */\r
+ [[nodiscard]] URL withAnchor (const String& anchor) const;\r
\r
/** Returns a copy of this URL, with a file-upload type parameter added to it.\r
\r
\r
@see withDataToUpload\r
*/\r
- JUCE_NODISCARD URL withFileToUpload (const String& parameterName,\r
+ [[nodiscard]] URL withFileToUpload (const String& parameterName,\r
const File& fileToUpload,\r
const String& mimeType) const;\r
\r
\r
@see withFileToUpload\r
*/\r
- JUCE_NODISCARD URL withDataToUpload (const String& parameterName,\r
+ [[nodiscard]] URL withDataToUpload (const String& parameterName,\r
const String& filename,\r
const MemoryBlock& fileContentToUpload,\r
const String& mimeType) const;\r
If no HTTP command is set when calling createInputStream() to read from\r
this URL and some data has been set, it will do a POST request.\r
*/\r
- JUCE_NODISCARD URL withPOSTData (const String& postData) const;\r
+ [[nodiscard]] URL withPOSTData (const String& postData) const;\r
\r
/** Returns a copy of this URL, with a block of data to send as the POST data.\r
\r
If no HTTP command is set when calling createInputStream() to read from\r
this URL and some data has been set, it will do a POST request.\r
*/\r
- JUCE_NODISCARD URL withPOSTData (const MemoryBlock& postData) const;\r
+ [[nodiscard]] URL withPOSTData (const MemoryBlock& postData) const;\r
\r
/** Returns the data that was set using withPOSTData(). */\r
String getPostData() const { return postData.toString(); }\r
\r
This can be useful for lengthy POST operations, so that you can provide user feedback.\r
*/\r
- JUCE_NODISCARD InputStreamOptions withProgressCallback (std::function<bool (int bytesSent, int totalBytes)> progressCallback) const;\r
+ [[nodiscard]] InputStreamOptions withProgressCallback (std::function<bool (int bytesSent, int totalBytes)> progressCallback) const;\r
\r
/** A string that will be appended onto the headers that are used for the request.\r
\r
It must be a valid set of HTML header directives, separated by newlines.\r
*/\r
- JUCE_NODISCARD InputStreamOptions withExtraHeaders (const String& extraHeaders) const;\r
+ [[nodiscard]] InputStreamOptions withExtraHeaders (const String& extraHeaders) const;\r
\r
/** Specifies a timeout for the request in milliseconds.\r
\r
If 0, this will use whatever default setting the OS chooses. If a negative\r
number, it will be infinite.\r
*/\r
- JUCE_NODISCARD InputStreamOptions withConnectionTimeoutMs (int connectionTimeoutMs) const;\r
+ [[nodiscard]] InputStreamOptions withConnectionTimeoutMs (int connectionTimeoutMs) const;\r
\r
/** If this is non-null, all the (key, value) pairs received as headers\r
in the response will be stored in this array.\r
*/\r
- JUCE_NODISCARD InputStreamOptions withResponseHeaders (StringPairArray* responseHeaders) const;\r
+ [[nodiscard]] InputStreamOptions withResponseHeaders (StringPairArray* responseHeaders) const;\r
\r
/** If this is non-null, it will get set to the http status code, if one\r
is known, or 0 if a code isn't available.\r
*/\r
- JUCE_NODISCARD InputStreamOptions withStatusCode (int* statusCode) const;\r
+ [[nodiscard]] InputStreamOptions withStatusCode (int* statusCode) const;\r
\r
/** Specifies the number of redirects that will be followed before returning a response.\r
\r
N.B. This will be ignored on Android which follows up to 5 redirects.\r
*/\r
- JUCE_NODISCARD InputStreamOptions withNumRedirectsToFollow (int numRedirectsToFollow) const;\r
+ [[nodiscard]] InputStreamOptions withNumRedirectsToFollow (int numRedirectsToFollow) const;\r
\r
/** Specifies which HTTP request command to use.\r
\r
via withPOSTData(), withFileToUpload(), or withDataToUpload(). Otherwise it\r
will be GET.\r
*/\r
- JUCE_NODISCARD InputStreamOptions withHttpRequestCmd (const String& httpRequestCmd) const;\r
+ [[nodiscard]] InputStreamOptions withHttpRequestCmd (const String& httpRequestCmd) const;\r
\r
//==============================================================================\r
ParameterHandling getParameterHandling() const noexcept { return parameterHandling; }\r
bool usePost = false;\r
\r
/** Specifies headers to add to the request. */\r
- JUCE_NODISCARD auto withExtraHeaders (String value) const { return with (&DownloadTaskOptions::extraHeaders, std::move (value)); }\r
+ [[nodiscard]] auto withExtraHeaders (String value) const { return with (&DownloadTaskOptions::extraHeaders, std::move (value)); }\r
\r
/** On iOS, specifies the container where the downloaded file will be stored.\r
\r
\r
This is currently unused on other platforms.\r
*/\r
- JUCE_NODISCARD auto withSharedContainer (String value) const { return with (&DownloadTaskOptions::sharedContainer, std::move (value)); }\r
+ [[nodiscard]] auto withSharedContainer (String value) const { return with (&DownloadTaskOptions::sharedContainer, std::move (value)); }\r
\r
/** Specifies an observer for the download task. */\r
- JUCE_NODISCARD auto withListener (DownloadTaskListener* value) const { return with (&DownloadTaskOptions::listener, std::move (value)); }\r
+ [[nodiscard]] auto withListener (DownloadTaskListener* value) const { return with (&DownloadTaskOptions::listener, std::move (value)); }\r
\r
/** Specifies whether a post command should be used. */\r
- JUCE_NODISCARD auto withUsePost (bool value) const { return with (&DownloadTaskOptions::usePost, value); }\r
+ [[nodiscard]] auto withUsePost (bool value) const { return with (&DownloadTaskOptions::usePost, value); }\r
\r
private:\r
template <typename Member, typename Value>\r
- JUCE_NODISCARD DownloadTaskOptions with (Member&& member, Value&& value) const\r
+ [[nodiscard]] DownloadTaskOptions with (Member&& member, Value&& value) const\r
{\r
auto copy = *this;\r
copy.*member = std::forward<Value> (value);\r
String url;\r
MemoryBlock postData;\r
StringArray parameterNames, parameterValues;\r
+ String anchor;\r
\r
ReferenceCountedArray<Upload> filesToUpload;\r
\r
int64 MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite)\r
{\r
// before writing from an input, see if we can preallocate to make it more efficient..\r
- int64 availableData = source.getTotalLength() - source.getPosition();\r
+ const auto availableData = source.getTotalLength() - source.getPosition();\r
\r
if (availableData > 0)\r
{\r
maxNumBytesToWrite = availableData;\r
\r
if (blockToUse != nullptr)\r
- preallocate (blockToUse->getSize() + (size_t) maxNumBytesToWrite);\r
+ preallocate (position + (size_t) availableData);\r
}\r
\r
return OutputStream::writeFromInputStream (source, maxNumBytesToWrite);\r
// GCC\r
#if JUCE_GCC\r
\r
- #if (__GNUC__ * 100 + __GNUC_MINOR__) < 500\r
- #error "JUCE requires GCC 5.0 or later"\r
+ #if (__GNUC__ * 100 + __GNUC_MINOR__) < 700\r
+ #error "JUCE requires GCC 7.0 or later"\r
#endif\r
\r
#ifndef JUCE_EXCEPTIONS_DISABLED\r
// Clang\r
#if JUCE_CLANG\r
\r
- #if (__clang_major__ < 3) || (__clang_major__ == 3 && __clang_minor__ < 4)\r
- #error "JUCE requires Clang 3.4 or later"\r
+ #if (__clang_major__ < 6)\r
+ #error "JUCE requires Clang 6 or later"\r
#endif\r
\r
#ifndef JUCE_COMPILER_SUPPORTS_ARC\r
#endif\r
\r
//==============================================================================\r
-#if ! JUCE_CXX14_IS_AVAILABLE\r
- #error "JUCE requires C++14 or later"\r
+#if ! JUCE_CXX17_IS_AVAILABLE\r
+ #error "JUCE requires C++17 or later"\r
#endif\r
\r
//==============================================================================\r
#define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1\r
#define JUCE_DELETED_FUNCTION = delete\r
#define JUCE_CONSTEXPR constexpr\r
-#endif\r
-\r
-#if JUCE_CXX17_IS_AVAILABLE\r
#define JUCE_NODISCARD [[nodiscard]]\r
-#else\r
- #define JUCE_NODISCARD\r
#endif\r
*/\r
#define JUCE_MAJOR_VERSION 7\r
#define JUCE_MINOR_VERSION 0\r
-#define JUCE_BUILDNUMBER 2\r
+#define JUCE_BUILDNUMBER 3\r
\r
/** Current JUCE version number.\r
\r
#include <condition_variable>\r
#include <cstddef>\r
#include <functional>\r
+#include <future>\r
#include <iomanip>\r
#include <iostream>\r
#include <limits>\r
#include <memory>\r
#include <mutex>\r
#include <numeric>\r
+#include <optional>\r
#include <queue>\r
#include <set>\r
#include <sstream>\r
+#include <thread>\r
#include <typeindex>\r
#include <unordered_map>\r
#include <unordered_set>\r
#include <utility>\r
#include <vector>\r
-#include <set>\r
\r
//==============================================================================\r
#include "juce_CompilerSupport.h"\r
#endif\r
}\r
\r
+#if JUCE_UNIT_TESTS\r
+\r
+class UniqueHardwareIDTest : public UnitTest\r
+{\r
+public:\r
+ //==============================================================================\r
+ UniqueHardwareIDTest() : UnitTest ("UniqueHardwareID", UnitTestCategories::analytics) {}\r
+\r
+ void runTest() override\r
+ {\r
+ beginTest ("getUniqueDeviceID returns usable data.");\r
+ {\r
+ expect (SystemStats::getUniqueDeviceID().isNotEmpty());\r
+ }\r
+ }\r
+};\r
+\r
+static UniqueHardwareIDTest uniqueHardwareIDTest;\r
+\r
+#endif\r
+\r
} // namespace juce\r
MacOSX_10_15 = MacOSX | 15,\r
MacOS_11 = MacOSX | 16,\r
MacOS_12 = MacOSX | 17,\r
+ MacOS_13 = MacOSX | 18,\r
\r
Win2000 = Windows | 1,\r
WinXP = Windows | 2,\r
The first choice for an ID is a filesystem ID for the user's home folder or\r
windows directory. If that fails then this function returns the MAC addresses.\r
*/\r
+ [[deprecated ("The identifiers produced by this function are not reliable. Use getUniqueDeviceID() instead.")]]\r
static StringArray getDeviceIdentifiers();\r
\r
+ /** This method returns a machine unique ID unaffected by storage or peripheral\r
+ changes.\r
+\r
+ This ID will be invalidated by changes to the motherboard and CPU on non-mobile\r
+ platforms, or resetting an Android device.\r
+ */\r
+ static String getUniqueDeviceID();\r
+\r
//==============================================================================\r
// CPU and memory information..\r
\r
*/\r
static bool isRunningInAppExtensionSandbox() noexcept;\r
\r
-\r
//==============================================================================\r
#ifndef DOXYGEN\r
[[deprecated ("This method was spelt wrong! Please change your code to use getCpuSpeedInMegahertz instead.")]]\r
/** If defined, this indicates that the processor is little-endian. */\r
#define JUCE_LITTLE_ENDIAN 1\r
\r
- #define JUCE_INTEL 1\r
+ #if defined (_M_ARM) || defined (_M_ARM64) || defined (__arm__) || defined (__aarch64__)\r
+ #define JUCE_ARM 1\r
+ #else\r
+ #define JUCE_INTEL 1\r
+ #endif\r
#endif\r
\r
//==============================================================================\r
\r
#if JUCE_MAC\r
#if ! defined (MAC_OS_X_VERSION_10_14)\r
- #error "The 10.14 SDK (Xcode 10.1+) is required to build JUCE apps. You can create apps that run on macOS 10.7+ by changing the deployment target."\r
- #elif MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7\r
- #error "Building for OSX 10.6 is no longer supported!"\r
+ #error "The 10.14 SDK (Xcode 10.1+) is required to build JUCE apps. You can create apps that run on macOS 10.9+ by changing the deployment target."\r
+ #elif MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9\r
+ #error "Building for OSX 10.8 and earlier is no longer supported!"\r
#endif\r
#endif\r
#endif\r
template <typename ResultType>\r
struct HexParser\r
{\r
- static_assert (std::is_unsigned<ResultType>::value, "ResultType must be unsigned because "\r
- "left-shifting a negative value is UB");\r
+ static_assert (std::is_unsigned_v<ResultType>, "ResultType must be unsigned because "\r
+ "left-shifting a negative value is UB");\r
\r
template <typename CharPointerType>\r
static ResultType parse (CharPointerType t) noexcept\r
// a block of memory here that's big enough to be used internally as a windows\r
// CRITICAL_SECTION structure.\r
#if JUCE_64BIT\r
- std::aligned_storage<44, 8>::type lock;\r
+ std::aligned_storage_t<44, 8> lock;\r
#else\r
- std::aligned_storage<24, 8>::type lock;\r
+ std::aligned_storage_t<24, 8> lock;\r
#endif\r
#else\r
mutable pthread_mutex_t lock;\r
namespace juce\r
{\r
\r
-HighResolutionTimer::HighResolutionTimer() : pimpl (new Pimpl (*this)) {}\r
-HighResolutionTimer::~HighResolutionTimer() { stopTimer(); }\r
+class HighResolutionTimer::Pimpl : private Thread\r
+{\r
+ using steady_clock = std::chrono::steady_clock;\r
+ using milliseconds = std::chrono::milliseconds;\r
+\r
+public:\r
+ explicit Pimpl (HighResolutionTimer& ownerRef)\r
+ : Thread ("HighResolutionTimerThread"),\r
+ owner (ownerRef)\r
+ {\r
+ }\r
+\r
+ using Thread::isThreadRunning;\r
+\r
+ void start (int periodMs)\r
+ {\r
+ {\r
+ const std::scoped_lock lk { mutex };\r
+ periodMillis = periodMs;\r
+ nextTickTime = steady_clock::now() + milliseconds (periodMillis);\r
+ }\r
+\r
+ if (! isThreadRunning())\r
+ startThread (Thread::Priority::high);\r
+ }\r
+\r
+ void stop()\r
+ {\r
+ {\r
+ const std::scoped_lock lk { mutex };\r
+ periodMillis = 0;\r
+ }\r
+\r
+ waitEvent.notify_one();\r
+\r
+ if (Thread::getCurrentThreadId() != getThreadId())\r
+ stopThread (-1);\r
+ }\r
+\r
+ int getPeriod() const\r
+ {\r
+ return periodMillis;\r
+ }\r
+\r
+private:\r
+ void run() override\r
+ {\r
+ for (;;)\r
+ {\r
+ {\r
+ std::unique_lock lk { mutex };\r
+\r
+ if (waitEvent.wait_until (lk, nextTickTime, [this] { return periodMillis == 0; }))\r
+ break;\r
\r
-void HighResolutionTimer::startTimer (int periodMs) { pimpl->start (jmax (1, periodMs)); }\r
-void HighResolutionTimer::stopTimer() { pimpl->stop(); }\r
+ nextTickTime = steady_clock::now() + milliseconds (periodMillis);\r
+ }\r
+\r
+ owner.hiResTimerCallback();\r
+ }\r
+ }\r
+\r
+ HighResolutionTimer& owner;\r
+ std::atomic<int> periodMillis { 0 };\r
+ steady_clock::time_point nextTickTime;\r
+ std::mutex mutex;\r
+ std::condition_variable waitEvent;\r
+};\r
+\r
+HighResolutionTimer::HighResolutionTimer()\r
+ : pimpl (new Pimpl (*this))\r
+{\r
+}\r
+\r
+HighResolutionTimer::~HighResolutionTimer()\r
+{\r
+ stopTimer();\r
+}\r
+\r
+void HighResolutionTimer::startTimer (int periodMs)\r
+{\r
+ pimpl->start (jmax (1, periodMs));\r
+}\r
+\r
+void HighResolutionTimer::stopTimer()\r
+{\r
+ pimpl->stop();\r
+}\r
\r
-bool HighResolutionTimer::isTimerRunning() const noexcept { return pimpl->periodMs != 0; }\r
-int HighResolutionTimer::getTimerInterval() const noexcept { return pimpl->periodMs; }\r
+bool HighResolutionTimer::isTimerRunning() const noexcept { return getTimerInterval() != 0; }\r
+int HighResolutionTimer::getTimerInterval() const noexcept { return pimpl->getPeriod(); }\r
\r
} // namespace juce\r
int getTimerInterval() const noexcept;\r
\r
private:\r
- struct Pimpl;\r
+ class Pimpl;\r
std::unique_ptr<Pimpl> pimpl;\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HighResolutionTimer)\r
@param priority the process priority, where\r
0=low, 1=normal, 2=high, 3=realtime\r
*/\r
- static void JUCE_CALLTYPE setPriority (const ProcessPriority priority);\r
+ static void JUCE_CALLTYPE setPriority (ProcessPriority priority);\r
\r
/** Kills the current process immediately.\r
\r
\r
namespace juce\r
{\r
-\r
-Thread::Thread (const String& name, size_t stackSize)\r
- : threadName (name), threadStackSize (stackSize)\r
+//==============================================================================\r
+Thread::Thread (const String& name, size_t stackSize) : threadName (name),\r
+ threadStackSize (stackSize)\r
{\r
}\r
\r
const CurrentThreadHolder::Ptr currentThreadHolder (getCurrentThreadHolder());\r
currentThreadHolder->value = this;\r
\r
+ #if JUCE_ANDROID\r
+ setPriority (priority);\r
+ #endif\r
+\r
if (threadName.isNotEmpty())\r
setCurrentThreadName (threadName);\r
\r
+ // This 'startSuspensionEvent' protects 'threadId' which is initialised after the platform's native 'CreateThread' method.\r
+ // This ensures it has been initialised correctly before it reaches this point.\r
if (startSuspensionEvent.wait (10000))\r
{\r
- jassert (getCurrentThreadId() == threadId.get());\r
+ jassert (getCurrentThreadId() == threadId);\r
\r
if (affinityMask != 0)\r
setCurrentThreadAffinityMask (affinityMask);\r
}\r
\r
//==============================================================================\r
-void Thread::startThread()\r
+bool Thread::startThreadInternal (Priority threadPriority)\r
{\r
- const ScopedLock sl (startStopLock);\r
+ shouldExit = false;\r
\r
- shouldExit = 0;\r
+ // 'priority' is essentially useless on Linux as only realtime\r
+ // has any options but we need to set this here to satsify\r
+ // later queries, otherwise we get inconsistent results across\r
+ // platforms.\r
+ #if JUCE_LINUX || JUCE_BSD\r
+ priority = threadPriority;\r
+ #endif\r
\r
- if (threadHandle.get() == nullptr)\r
+ if (createNativeThread (threadPriority))\r
{\r
- launchThread();\r
- setThreadPriority (threadHandle.get(), threadPriority);\r
startSuspensionEvent.signal();\r
+ return true;\r
}\r
+\r
+ return false;\r
}\r
\r
-void Thread::startThread (int priority)\r
+bool Thread::startThread()\r
+{\r
+ return startThread (Priority::normal);\r
+}\r
+\r
+bool Thread::startThread (Priority threadPriority)\r
{\r
const ScopedLock sl (startStopLock);\r
\r
- if (threadHandle.get() == nullptr)\r
+ if (threadHandle == nullptr)\r
{\r
- #if JUCE_ANDROID\r
- isAndroidRealtimeThread = (priority == realtimeAudioPriority);\r
- #endif\r
-\r
- threadPriority = getAdjustedPriority (priority);\r
- startThread();\r
+ realtimeOptions.reset();\r
+ return startThreadInternal (threadPriority);\r
}\r
- else\r
+\r
+ return false;\r
+}\r
+\r
+bool Thread::startRealtimeThread (const RealtimeOptions& options)\r
+{\r
+ const ScopedLock sl (startStopLock);\r
+\r
+ if (threadHandle == nullptr)\r
{\r
- setPriority (priority);\r
+ realtimeOptions = makeOptional (options);\r
+\r
+ if (startThreadInternal (Priority::normal))\r
+ return true;\r
+\r
+ realtimeOptions.reset();\r
}\r
+\r
+ return false;\r
}\r
\r
bool Thread::isThreadRunning() const\r
{\r
- return threadHandle.get() != nullptr;\r
+ return threadHandle != nullptr;\r
}\r
\r
Thread* JUCE_CALLTYPE Thread::getCurrentThread()\r
\r
Thread::ThreadID Thread::getThreadId() const noexcept\r
{\r
- return threadId.get();\r
+ return threadId;\r
}\r
\r
//==============================================================================\r
void Thread::signalThreadShouldExit()\r
{\r
- shouldExit = 1;\r
+ shouldExit = true;\r
listeners.call ([] (Listener& l) { l.exitSignalSent(); });\r
}\r
\r
bool Thread::threadShouldExit() const\r
{\r
- return shouldExit.get() != 0;\r
+ return shouldExit;\r
}\r
\r
bool Thread::currentThreadShouldExit()\r
listeners.remove (listener);\r
}\r
\r
-//==============================================================================\r
-bool Thread::setPriority (int newPriority)\r
-{\r
- newPriority = getAdjustedPriority (newPriority);\r
-\r
- // NB: deadlock possible if you try to set the thread prio from the thread itself,\r
- // so using setCurrentThreadPriority instead in that case.\r
- if (getCurrentThreadId() == getThreadId())\r
- return setCurrentThreadPriority (newPriority);\r
-\r
- const ScopedLock sl (startStopLock);\r
-\r
- #if JUCE_ANDROID\r
- bool isRealtime = (newPriority == realtimeAudioPriority);\r
-\r
- // you cannot switch from or to an Android realtime thread once the\r
- // thread is already running!\r
- jassert (isThreadRunning() && (isRealtime == isAndroidRealtimeThread));\r
-\r
- isAndroidRealtimeThread = isRealtime;\r
- #endif\r
-\r
- if ((! isThreadRunning()) || setThreadPriority (threadHandle.get(), newPriority))\r
- {\r
- threadPriority = newPriority;\r
- return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-bool Thread::setCurrentThreadPriority (const int newPriority)\r
+bool Thread::isRealtime() const\r
{\r
- return setThreadPriority ({}, getAdjustedPriority (newPriority));\r
+ return realtimeOptions.hasValue();\r
}\r
\r
void Thread::setAffinityMask (const uint32 newAffinityMask)\r
affinityMask = newAffinityMask;\r
}\r
\r
-int Thread::getAdjustedPriority (int newPriority)\r
-{\r
- return jlimit (0, 10, newPriority == realtimeAudioPriority ? 9 : newPriority);\r
-}\r
-\r
//==============================================================================\r
bool Thread::wait (const int timeOutMilliseconds) const\r
{\r
//==============================================================================\r
struct LambdaThread : public Thread\r
{\r
- LambdaThread (std::function<void()> f) : Thread ("anonymous"), fn (f) {}\r
+ LambdaThread (std::function<void()>&& f) : Thread ("anonymous"), fn (std::move (f)) {}\r
\r
void run() override\r
{\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LambdaThread)\r
};\r
\r
-void Thread::launch (std::function<void()> functionToRun)\r
+bool Thread::launch (std::function<void()> functionToRun)\r
+{\r
+ return launch (Priority::normal, std::move (functionToRun));\r
+}\r
+\r
+bool Thread::launch (Priority priority, std::function<void()> functionToRun)\r
{\r
- auto anon = new LambdaThread (functionToRun);\r
+ auto anon = std::make_unique<LambdaThread> (std::move (functionToRun));\r
anon->deleteOnThreadEnd = true;\r
- anon->startThread();\r
+\r
+ if (anon->startThread (priority))\r
+ {\r
+ anon.release();\r
+ return true;\r
+ }\r
+\r
+ return false;\r
}\r
\r
//==============================================================================\r
return juce_isRunningUnderDebugger();\r
}\r
\r
-\r
//==============================================================================\r
//==============================================================================\r
#if JUCE_UNIT_TESTS\r
Encapsulates a thread.\r
\r
Subclasses derive from Thread and implement the run() method, in which they\r
- do their business. The thread can then be started with the startThread() method\r
- and controlled with various other methods.\r
+ do their business. The thread can then be started with the startThread() or\r
+ startRealtimeThread() methods and controlled with various other methods.\r
\r
This class also contains some thread-related static methods, such\r
as sleep(), yield(), getCurrentThreadId() etc.\r
class JUCE_API Thread\r
{\r
public:\r
+ //==============================================================================\r
+ /** The different runtime priorities of non-realtime threads.\r
+\r
+ @see startThread\r
+ */\r
+ enum class Priority\r
+ {\r
+ /** The highest possible priority that isn't a dedicated realtime thread. */\r
+ highest = 2,\r
+\r
+ /** Makes use of performance cores and higher clocks. */\r
+ high = 1,\r
+\r
+ /** The OS default. It will balance out across all cores. */\r
+ normal = 0,\r
+\r
+ /** Uses efficiency cores when possible. */\r
+ low = -1,\r
+\r
+ /** Restricted to efficiency cores on platforms that have them. */\r
+ background = -2\r
+ };\r
+\r
+ //==============================================================================\r
+ /** A selection of options available when creating realtime threads.\r
+\r
+ @see startRealtimeThread\r
+ */\r
+ struct RealtimeOptions\r
+ {\r
+ /** Linux only: A value with a range of 0-10, where 10 is the highest priority. */\r
+ int priority = 5;\r
+\r
+ /* iOS/macOS only: A millisecond value representing the estimated time between each\r
+ 'Thread::run' call. Your thread may be penalised if you frequently\r
+ overrun this.\r
+ */\r
+ uint32_t workDurationMs = 0;\r
+ };\r
+\r
//==============================================================================\r
/**\r
Creates a thread.\r
virtual void run() = 0;\r
\r
//==============================================================================\r
- /** Starts the thread running.\r
+ /** Attempts to start a new thread with default ('Priority::normal') priority.\r
\r
This will cause the thread's run() method to be called by a new thread.\r
If this thread is already running, startThread() won't do anything.\r
\r
+ If a thread cannot be created with the requested priority, this will return false\r
+ and Thread::run() will not be called. An exception to this is the Android platform,\r
+ which always starts a thread and attempts to upgrade the thread after creation.\r
+\r
+ @returns true if the thread started successfully. false if it was unsuccesful.\r
+\r
@see stopThread\r
*/\r
- void startThread();\r
+ bool startThread();\r
+\r
+ /** Attempts to start a new thread with a given priority.\r
+\r
+ This will cause the thread's run() method to be called by a new thread.\r
+ If this thread is already running, startThread() won't do anything.\r
\r
- /** Starts the thread with a given priority.\r
+ If a thread cannot be created with the requested priority, this will return false\r
+ and Thread::run() will not be called. An exception to this is the Android platform,\r
+ which always starts a thread and attempts to upgrade the thread after creation.\r
\r
- Launches the thread with a given priority, where 0 = lowest, 10 = highest.\r
- If the thread is already running, its priority will be changed.\r
+ @param newPriority Priority the thread should be assigned. This parameter is ignored\r
+ on Linux.\r
\r
- @see startThread, setPriority, realtimeAudioPriority\r
+ @returns true if the thread started successfully, false if it was unsuccesful.\r
+\r
+ @see startThread, setPriority, startRealtimeThread\r
*/\r
- void startThread (int priority);\r
+ bool startThread (Priority newPriority);\r
+\r
+ /** Starts the thread with realtime performance characteristics on platforms\r
+ that support it.\r
+\r
+ You cannot change the options of a running realtime thread, nor switch\r
+ a non-realtime thread to a realtime thread. To make these changes you must\r
+ first stop the thread and then restart with different options.\r
+\r
+ @param options Realtime options the thread should be created with.\r
+\r
+ @see startThread, RealtimeOptions\r
+ */\r
+ bool startRealtimeThread (const RealtimeOptions& options);\r
\r
/** Attempts to stop the thread running.\r
\r
bool stopThread (int timeOutMilliseconds);\r
\r
//==============================================================================\r
- /** Invokes a lambda or function on its own thread.\r
+ /** Invokes a lambda or function on its own thread with the default priority.\r
+\r
+ This will spin up a Thread object which calls the function and then exits.\r
+ Bear in mind that starting and stopping a thread can be a fairly heavyweight\r
+ operation, so you might prefer to use a ThreadPool if you're kicking off a lot\r
+ of short background tasks.\r
+\r
+ Also note that using an anonymous thread makes it very difficult to interrupt\r
+ the function when you need to stop it, e.g. when your app quits. So it's up to\r
+ you to deal with situations where the function may fail to stop in time.\r
+\r
+ @param functionToRun The lambda to be called from the new Thread.\r
+\r
+ @returns true if the thread started successfully, or false if it failed.\r
+\r
+ @see launch.\r
+ */\r
+ static bool launch (std::function<void()> functionToRun);\r
+\r
+ //==============================================================================\r
+ /** Invokes a lambda or function on its own thread with a custom priority.\r
\r
This will spin up a Thread object which calls the function and then exits.\r
Bear in mind that starting and stopping a thread can be a fairly heavyweight\r
Also note that using an anonymous thread makes it very difficult to interrupt\r
the function when you need to stop it, e.g. when your app quits. So it's up to\r
you to deal with situations where the function may fail to stop in time.\r
+\r
+ @param priority The priority the thread is started with.\r
+ @param functionToRun The lambda to be called from the new Thread.\r
+\r
+ @returns true if the thread started successfully, or false if it failed.\r
*/\r
- static void launch (std::function<void()> functionToRun);\r
+ static bool launch (Priority priority, std::function<void()> functionToRun);\r
\r
//==============================================================================\r
/** Returns true if the thread is currently active */\r
/** Removes a listener added with addListener. */\r
void removeListener (Listener*);\r
\r
- //==============================================================================\r
- /** Special realtime audio thread priority\r
-\r
- This priority will create a high-priority thread which is best suited\r
- for realtime audio processing.\r
-\r
- Currently, this priority is identical to priority 9, except when building\r
- for Android with OpenSL/Oboe support.\r
-\r
- In this case, JUCE will ask OpenSL/Oboe to construct a super high priority thread\r
- specifically for realtime audio processing.\r
-\r
- Note that this priority can only be set **before** the thread has\r
- started. Switching to this priority, or from this priority to a different\r
- priority, is not supported under Android and will assert.\r
-\r
- For best performance this thread should yield at regular intervals\r
- and not call any blocking APIs.\r
-\r
- @see startThread, setPriority, sleep, WaitableEvent\r
- */\r
- enum\r
- {\r
- realtimeAudioPriority = -1\r
- };\r
-\r
- /** Changes the thread's priority.\r
-\r
- May return false if for some reason the priority can't be changed.\r
-\r
- @param priority the new priority, in the range 0 (lowest) to 10 (highest). A priority\r
- of 5 is normal.\r
- @see realtimeAudioPriority\r
- */\r
- bool setPriority (int priority);\r
-\r
- /** Changes the priority of the caller thread.\r
-\r
- Similar to setPriority(), but this static method acts on the caller thread.\r
- May return false if for some reason the priority can't be changed.\r
-\r
- @see setPriority\r
- */\r
- static bool setCurrentThreadPriority (int priority);\r
+ /** Returns true if this Thread represents a realtime thread. */\r
+ bool isRealtime() const;\r
\r
//==============================================================================\r
/** Sets the affinity mask for the thread.\r
static void initialiseJUCE (void* jniEnv, void* jContext);\r
#endif\r
\r
+protected:\r
+ //==============================================================================\r
+ /** Returns the current priority of this thread.\r
+\r
+ This can only be called from the target thread. Doing so from another thread\r
+ will cause an assert.\r
+\r
+ @see setPriority\r
+ */\r
+ Priority getPriority() const;\r
+\r
+ /** Attempts to set the priority for this thread. Returns true if the new priority\r
+ was set successfully, false if not.\r
+\r
+ This can only be called from the target thread. Doing so from another thread\r
+ will cause an assert.\r
+\r
+ @param newPriority The new priority to be applied to the thread. Note: This\r
+ has no effect on Linux platforms, subsequent calls to\r
+ 'getPriority' will return this value.\r
+\r
+ @see Priority\r
+ */\r
+ bool setPriority (Priority newPriority);\r
+\r
private:\r
//==============================================================================\r
const String threadName;\r
- Atomic<void*> threadHandle { nullptr };\r
- Atomic<ThreadID> threadId = {};\r
+ std::atomic<void*> threadHandle { nullptr };\r
+ std::atomic<ThreadID> threadId { nullptr };\r
+ Optional<RealtimeOptions> realtimeOptions = {};\r
CriticalSection startStopLock;\r
WaitableEvent startSuspensionEvent, defaultEvent;\r
- int threadPriority = 5;\r
size_t threadStackSize;\r
uint32 affinityMask = 0;\r
bool deleteOnThreadEnd = false;\r
- Atomic<int32> shouldExit { 0 };\r
+ std::atomic<bool> shouldExit { false };\r
ListenerList<Listener, Array<Listener*, CriticalSection>> listeners;\r
\r
- #if JUCE_ANDROID\r
- bool isAndroidRealtimeThread = false;\r
+ #if JUCE_ANDROID || JUCE_LINUX || JUCE_BSD\r
+ std::atomic<Priority> priority;\r
#endif\r
\r
#ifndef DOXYGEN\r
friend void JUCE_API juce_threadEntryPoint (void*);\r
#endif\r
\r
- void launchThread();\r
+ bool startThreadInternal (Priority);\r
+ bool createNativeThread (Priority);\r
void closeThreadHandle();\r
void killThread();\r
void threadEntryPoint();\r
- static bool setThreadPriority (void*, int);\r
- static int getAdjustedPriority (int);\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Thread)\r
};\r
void run() override\r
{\r
while (! threadShouldExit())\r
+ {\r
if (! pool.runNextJob (*this))\r
wait (500);\r
+ }\r
}\r
\r
std::atomic<ThreadPoolJob*> currentJob { nullptr };\r
+\r
ThreadPool& pool;\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadPoolThread)\r
}\r
\r
//==============================================================================\r
-ThreadPool::ThreadPool (int numThreads, size_t threadStackSize)\r
+ThreadPool::ThreadPool (int numThreads, size_t threadStackSize, Thread::Priority priority)\r
{\r
jassert (numThreads > 0); // not much point having a pool without any threads!\r
\r
- createThreads (numThreads, threadStackSize);\r
+ for (int i = jmax (1, numThreads); --i >= 0;)\r
+ threads.add (new ThreadPoolThread (*this, threadStackSize));\r
+\r
+ for (auto* t : threads)\r
+ t->startThread (priority);\r
}\r
\r
-ThreadPool::ThreadPool()\r
+ThreadPool::ThreadPool() : ThreadPool (SystemStats::getNumCpus(), 0, Thread::Priority::normal)\r
{\r
- createThreads (SystemStats::getNumCpus());\r
}\r
\r
ThreadPool::~ThreadPool()\r
stopThreads();\r
}\r
\r
-void ThreadPool::createThreads (int numThreads, size_t threadStackSize)\r
-{\r
- for (int i = jmax (1, numThreads); --i >= 0;)\r
- threads.add (new ThreadPoolThread (*this, threadStackSize));\r
-\r
- for (auto* t : threads)\r
- t->startThread();\r
-}\r
-\r
void ThreadPool::stopThreads()\r
{\r
for (auto* t : threads)\r
return s;\r
}\r
\r
-bool ThreadPool::setThreadPriorities (int newPriority)\r
-{\r
- bool ok = true;\r
-\r
- for (auto* t : threads)\r
- if (! t->setPriority (newPriority))\r
- ok = false;\r
-\r
- return ok;\r
-}\r
-\r
ThreadPoolJob* ThreadPool::pickNextJobToRun()\r
{\r
OwnedArray<ThreadPoolJob> deletionList;\r
@param threadStackSize the size of the stack of each thread. If this value\r
is zero then the default stack size of the OS will\r
be used.\r
+ @param priority the desired priority of each thread in the pool.\r
*/\r
- ThreadPool (int numberOfThreads, size_t threadStackSize = 0);\r
+ ThreadPool (int numberOfThreads, size_t threadStackSize = 0, Thread::Priority priority = Thread::Priority::normal);\r
\r
/** Creates a thread pool with one thread per CPU core.\r
Once you've created a pool, you can give it some jobs by calling addJob().\r
*/\r
StringArray getNamesOfAllJobs (bool onlyReturnActiveJobs) const;\r
\r
- /** Changes the priority of all the threads.\r
- This will call Thread::setPriority() for each thread in the pool.\r
- May return false if for some reason the priority can't be changed.\r
- */\r
- bool setThreadPriorities (int newPriority);\r
-\r
-\r
private:\r
//==============================================================================\r
Array<ThreadPoolJob*> jobs;\r
bool runNextJob (ThreadPoolThread&);\r
ThreadPoolJob* pickNextJobToRun();\r
void addToDeleteList (OwnedArray<ThreadPoolJob>&, ThreadPoolJob*) const;\r
- void createThreads (int numThreads, size_t threadStackSize = 0);\r
void stopThreads();\r
\r
// Note that this method has changed, and no longer has a parameter to indicate\r
\r
int TimeSliceThread::getNumClients() const\r
{\r
+ const ScopedLock sl (listLock);\r
return clients.size();\r
}\r
\r
return clients[i];\r
}\r
\r
+bool TimeSliceThread::contains (const TimeSliceClient* c) const\r
+{\r
+ const ScopedLock sl (listLock);\r
+ return std::any_of (clients.begin(), clients.end(), [=] (auto* registered) { return registered == c; });\r
+}\r
+\r
//==============================================================================\r
TimeSliceClient* TimeSliceThread::getNextClient (int index) const\r
{\r
/** Returns one of the registered clients. */\r
TimeSliceClient* getClient (int index) const;\r
\r
+ /** Returns true if the client is currently registered. */\r
+ bool contains (const TimeSliceClient*) const;\r
+\r
//==============================================================================\r
#ifndef DOXYGEN\r
void run() override;\r
static const String cryptography { "Cryptography" };\r
static const String dsp { "DSP" };\r
static const String files { "Files" };\r
- static const String function { "Function" };\r
static const String graphics { "Graphics" };\r
static const String gui { "GUI" };\r
static const String json { "JSON" };\r
int lineWrapLength = 60; /**< A maximum line length before wrapping is done. (If newLineChars is nullptr, this is ignored) */\r
const char* newLineChars = "\r\n"; /**< Allows the newline characters to be set. If you set this to nullptr, then the whole XML document will be placed on a single line. */\r
\r
- JUCE_NODISCARD TextFormat singleLine() const; /**< returns a copy of this format with newLineChars set to nullptr. */\r
- JUCE_NODISCARD TextFormat withoutHeader() const; /**< returns a copy of this format with the addDefaultHeader flag set to false. */\r
+ [[nodiscard]] TextFormat singleLine() const; /**< returns a copy of this format with newLineChars set to nullptr. */\r
+ [[nodiscard]] TextFormat withoutHeader() const; /**< returns a copy of this format with the addDefaultHeader flag set to false. */\r
};\r
\r
/** Returns a text version of this XML element.\r
\r
ID: juce_cryptography\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_core\r
\r
\r
ID: juce_data_structures\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_events\r
\r
#ifndef DOXYGEN\r
namespace SampleTypeHelpers // Internal classes needed for handling sample type classes\r
{\r
- template <typename T, bool = std::is_floating_point<T>::value>\r
+ template <typename T, bool = std::is_floating_point_v<T>>\r
struct ElementType\r
{\r
using Type = T;\r
private:\r
template <typename OtherSampleType>\r
using MayUseConvertingConstructor =\r
- std::enable_if_t<std::is_same<std::remove_const_t<SampleType>,\r
- std::remove_const_t<OtherSampleType>>::value\r
- && std::is_const<SampleType>::value\r
- && ! std::is_const<OtherSampleType>::value,\r
+ std::enable_if_t<std::is_same_v<std::remove_const_t<SampleType>,\r
+ std::remove_const_t<OtherSampleType>>\r
+ && std::is_const_v<SampleType>\r
+ && ! std::is_const_v<OtherSampleType>,\r
int>;\r
\r
public:\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
- void copyTo (AudioBuffer<typename std::remove_const<NumericType>::type>& dst, size_t srcPos = 0, size_t dstPos = 0,\r
+ void copyTo (AudioBuffer<std::remove_const_t<NumericType>>& dst, size_t srcPos = 0, size_t dstPos = 0,\r
size_t numElements = std::numeric_limits<size_t>::max()) const\r
{\r
auto dstlen = static_cast<size_t> (dst.getNumSamples()) / sizeFactor;\r
\r
//==============================================================================\r
/** Finds the minimum and maximum value of the buffer. */\r
- Range<typename std::remove_const<NumericType>::type> findMinAndMax() const noexcept\r
+ Range<std::remove_const_t<NumericType>> findMinAndMax() const noexcept\r
{\r
if (numChannels == 0)\r
return {};\r
\r
//==============================================================================\r
// This class can only be used with floating point types\r
- static_assert (std::is_same<std::remove_const_t<SampleType>, float>::value\r
- || std::is_same<std::remove_const_t<SampleType>, double>::value\r
+ static_assert (std::is_same_v<std::remove_const_t<SampleType>, float>\r
+ || std::is_same_v<std::remove_const_t<SampleType>, double>\r
#if JUCE_USE_SIMD\r
- || std::is_same<std::remove_const_t<SampleType>, SIMDRegister<float>>::value\r
- || std::is_same<std::remove_const_t<SampleType>, SIMDRegister<double>>::value\r
+ || std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<float>>\r
+ || std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<double>>\r
#endif\r
, "AudioBlock only supports single or double precision floating point types");\r
\r
\r
private:\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
+ void copyingTests()\r
{\r
- auto unchangedElement1 = block.getSample (0, 4);\r
- auto unchangedElement2 = block.getSample (1, 1);\r
+ if constexpr (std::is_scalar_v<SampleType>)\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
+ AudioBuffer<SampleType> otherBuffer (otherData.data(), (int) otherData.size(), numSamples);\r
\r
- block.copyFrom (otherBuffer, 1, 2, 2);\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
+ 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
+ resetBlocks();\r
\r
- block.copyTo (otherBuffer, 2, 1, 2);\r
+ unchangedElement1 = otherBuffer.getSample (0, 4);\r
+ unchangedElement2 = otherBuffer.getSample (1, 3);\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
+ block.copyTo (otherBuffer, 2, 1, 2);\r
\r
- #if JUCE_USE_SIMD\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
+ 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
+ #if JUCE_USE_SIMD\r
+ else\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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ auto unchangedSIMDElement1 = block.getSample (0, 1);\r
+ auto unchangedSIMDElement2 = block.getSample (1, 4);\r
\r
- block.copyFrom (numericData, 1, 2, 2);\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
+ 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
+ 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
+ #endif\r
}\r
- #endif\r
\r
//==============================================================================\r
- template <typename T = SampleType>\r
- ScalarVoid<T> smoothedValueTests()\r
+ void 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
+ if constexpr (std::is_scalar_v<SampleType>)\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
\r
- template <typename T = SampleType>\r
- SIMDVoid<T> smoothedValueTests() {}\r
-\r
//==============================================================================\r
void resetBlocks()\r
{\r
//==============================================================================\r
static SampleType* allocateAlignedMemory (int numSamplesToAllocate)\r
{\r
- auto alignmentLowerBound = std::alignment_of<SampleType>::value;\r
+ auto alignmentLowerBound = std::alignment_of_v<SampleType>;\r
#if ! JUCE_WINDOWS\r
alignmentLowerBound = jmax (sizeof (void*), alignmentLowerBound);\r
#endif\r
}\r
\r
template <typename Fn, typename Ret, typename... Args>\r
- typename std::enable_if<std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args)\r
+ std::enable_if_t<std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)\r
{\r
(*reinterpret_cast<Fn*> (s)) (args...);\r
}\r
\r
template <typename Fn, typename Ret, typename... Args>\r
- typename std::enable_if<! std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args)\r
+ std::enable_if_t<! std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)\r
{\r
return (*reinterpret_cast<Fn*> (s)) (std::forward<Args> (args)...);\r
}\r
class FixedSizeFunction<len, Ret (Args...)>\r
{\r
private:\r
- using Storage = typename std::aligned_storage<len>::type;\r
+ using Storage = std::aligned_storage_t<len>;\r
\r
template <typename Item>\r
- using Decay = typename std::decay<Item>::type;\r
+ using Decay = std::decay_t<Item>;\r
\r
template <typename Item, typename Fn = Decay<Item>>\r
- using IntIfValidConversion = typename std::enable_if<sizeof (Fn) <= len\r
- && alignof (Fn) <= alignof (Storage)\r
- && ! std::is_same<FixedSizeFunction, Fn>::value,\r
- int>::type;\r
+ using IntIfValidConversion = std::enable_if_t<sizeof (Fn) <= len\r
+ && alignof (Fn) <= alignof (Storage)\r
+ && ! std::is_same_v<FixedSizeFunction, Fn>,\r
+ int>;\r
\r
public:\r
/** Create an empty function. */\r
}\r
\r
/** Converting constructor from smaller FixedSizeFunctions. */\r
- template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0>\r
+ template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>\r
FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept\r
: vtable (other.vtable)\r
{\r
}\r
\r
/** Move assignment from smaller FixedSizeFunctions. */\r
- template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0>\r
+ template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>\r
FixedSizeFunction& operator= (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept\r
{\r
return *this = FixedSizeFunction (std::move (other));\r
\r
/** The corresponding primitive integer type, for example, this will be int32_t\r
if type is a float. */\r
- using MaskType = typename SIMDInternal::MaskTypeFor<ElementType>::type;\r
+ using MaskType = SIMDInternal::MaskType<ElementType>;\r
\r
//==============================================================================\r
// Here are some types which are needed internally\r
\r
namespace SIMDRegister_test_internal\r
{\r
- template <typename type, typename = void> struct RandomPrimitive {};\r
-\r
template <typename type>\r
- struct RandomPrimitive<type, typename std::enable_if<std::is_floating_point<type>::value>::type>\r
+ struct RandomPrimitive\r
{\r
static type next (Random& random)\r
{\r
- return static_cast<type> (std::is_signed<type>::value ? (random.nextFloat() * 16.0) - 8.0\r
- : (random.nextFloat() * 8.0));\r
+ if constexpr (std::is_floating_point_v<type>)\r
+ {\r
+ return static_cast<type> (std::is_signed_v<type> ? (random.nextFloat() * 16.0) - 8.0\r
+ : (random.nextFloat() * 8.0));\r
+ }\r
+ else if constexpr (std::is_integral_v<type>)\r
+ {\r
+ return static_cast<type> (random.nextInt64());\r
+ }\r
}\r
};\r
\r
template <typename type>\r
- struct RandomPrimitive<type, typename std::enable_if<std::is_integral<type>::value>::type>\r
+ struct RandomValue\r
{\r
static type next (Random& random)\r
{\r
- return static_cast<type> (random.nextInt64());\r
+ return RandomPrimitive<type>::next (random);\r
}\r
};\r
\r
- template <typename type>\r
- struct RandomValue\r
- {\r
- static type next (Random& random) { return RandomPrimitive<type>::next (random); }\r
- };\r
-\r
template <typename type>\r
struct RandomValue<std::complex<type>>\r
{\r
template <typename type>\r
static void run (UnitTest& u, Random& random, Tag<type>)\r
{\r
- bool is_signed = std::is_signed<type>::value;\r
type array [SIMDRegister<type>::SIMDNumElements];\r
\r
- auto value = is_signed ? static_cast<type> ((random.nextFloat() * 16.0) - 8.0)\r
- : static_cast<type> (random.nextFloat() * 8.0);\r
+ auto value = std::is_signed_v<type> ? static_cast<type> ((random.nextFloat() * 16.0) - 8.0)\r
+ : static_cast<type> (random.nextFloat() * 8.0);\r
\r
std::fill (array, array + SIMDRegister<type>::SIMDNumElements, value);\r
SIMDRegister<type> a, b;\r
stereo processing.\r
*/\r
template <typename ProcessContext,\r
- std::enable_if_t<std::is_same<typename ProcessContext::SampleType, float>::value, int> = 0>\r
+ std::enable_if_t<std::is_same_v<typename ProcessContext::SampleType, float>, int> = 0>\r
void process (const ProcessContext& context) noexcept\r
{\r
processSamples (context.getInputBlock(), context.getOutputBlock(), context.isBypassed);\r
AudioBuffer<float> result (2, length);\r
result.clear();\r
\r
- auto** channels = result.getArrayOfWritePointers();\r
+ auto* const* channels = result.getArrayOfWritePointers();\r
std::for_each (channels, channels + result.getNumChannels(), [length] (auto* channel)\r
{\r
std::fill (channel, channel + length, 1.0f);\r
#include "widgets/juce_Chorus.cpp"\r
\r
#if JUCE_USE_SIMD\r
- #if defined(__i386__) || defined(__amd64__) || defined(_M_X64) || defined(_X86_) || defined(_M_IX86)\r
+ #if JUCE_INTEL\r
#ifdef __AVX2__\r
#include "native/juce_avx_SIMDNativeOps.cpp"\r
#else\r
#include "native/juce_sse_SIMDNativeOps.cpp"\r
#endif\r
- #elif defined(__arm__) || defined(_M_ARM) || defined (__arm64__) || defined (__aarch64__)\r
+ #elif JUCE_ARM\r
#include "native/juce_neon_SIMDNativeOps.cpp"\r
#else\r
#error "SIMD register support not implemented for this platform"\r
\r
ID: juce_dsp\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
license: GPL/Commercial\r
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_audio_formats\r
OSXFrameworks: Accelerate\r
#include <immintrin.h>\r
#endif\r
\r
-#elif defined (__ARM_NEON__) || defined (__ARM_NEON) || defined (__arm64__) || defined (__aarch64__)\r
+// it's ok to check for _M_ARM below as this is only defined on Windows for Arm 32-bit\r
+// which has a minimum requirement of armv7, which supports neon.\r
+#elif defined (__ARM_NEON__) || defined (__ARM_NEON) || defined (__arm64__) || defined (__aarch64__) || defined (_M_ARM) || defined (_M_ARM64)\r
\r
#ifndef JUCE_USE_SIMD\r
#define JUCE_USE_SIMD 1\r
#else\r
#include "native/juce_sse_SIMDNativeOps.h"\r
#endif\r
- #elif defined(__arm__) || defined(_M_ARM) || defined (__arm64__) || defined (__aarch64__)\r
+ #elif JUCE_ARM\r
#include "native/juce_neon_SIMDNativeOps.h"\r
#else\r
#error "SIMD register support not implemented for this platform"\r
template <> struct MaskTypeFor <std::complex<float>> { using type = uint32_t; };\r
template <> struct MaskTypeFor <std::complex<double>> { using type = uint64_t; };\r
\r
- template <typename Primitive> struct PrimitiveType { using type = typename std::remove_cv<Primitive>::type; };\r
- template <typename Primitive> struct PrimitiveType<std::complex<Primitive>> { using type = typename std::remove_cv<Primitive>::type; };\r
+ template <typename Primitive> using MaskType = typename MaskTypeFor<Primitive>::type;\r
+\r
+ template <typename Primitive> struct PrimitiveType { using type = std::remove_cv_t<Primitive>; };\r
+ template <typename Primitive> struct PrimitiveType<std::complex<Primitive>> { using type = std::remove_cv_t<Primitive>; };\r
\r
template <int n> struct Log2Helper { enum { value = Log2Helper<n/2>::value + 1 }; };\r
template <> struct Log2Helper<1> { enum { value = 0 }; };\r
static constexpr size_t bits = SIMDInternal::Log2Helper<(int) n>::value;\r
\r
// helper types\r
- using MaskType = typename SIMDInternal::MaskTypeFor<ScalarType>::type;\r
+ using MaskType = SIMDInternal::MaskType<ScalarType>;\r
union UnionType { vSIMDType v; ScalarType s[n]; };\r
union UnionMaskType { vSIMDType v; MaskType m[n]; };\r
\r
DEFINE_NEON_SIMD_CONST (int32_t, float, kEvenHighBit) = { static_cast<int32_t>(0x80000000), 0, static_cast<int32_t>(0x80000000), 0 };\r
DEFINE_NEON_SIMD_CONST (float, float, kOne) = { 1.0f, 1.0f, 1.0f, 1.0f };\r
\r
+ #if JUCE_64BIT\r
+ DEFINE_NEON_SIMD_CONST (int64_t, double, kAllBitsSet) = { -1, -1 };\r
+ DEFINE_NEON_SIMD_CONST (double, double, kOne) = { 1.0, 1.0 };\r
+ #endif\r
+\r
DEFINE_NEON_SIMD_CONST (int8_t, int8_t, kAllBitsSet) = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };\r
DEFINE_NEON_SIMD_CONST (uint8_t, uint8_t, kAllBitsSet) = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };\r
DEFINE_NEON_SIMD_CONST (int16_t, int16_t, kAllBitsSet) = { -1, -1, -1, -1, -1, -1, -1, -1 };\r
//==============================================================================\r
static forcedinline vSIMDType expand (uint32_t s) noexcept { return vdupq_n_u32 (s); }\r
static forcedinline vSIMDType load (const uint32_t* a) noexcept { return vld1q_u32 (a); }\r
- static forcedinline void store (vSIMDType value, uint32_t* a) noexcept { vst1q_u32 (a, value); }\r
- static forcedinline uint32_t get (vSIMDType v, size_t i) noexcept { return v[i]; }\r
- static forcedinline vSIMDType set (vSIMDType v, size_t i, uint32_t s) noexcept { v[i] = s; return v; }\r
+ static forcedinline void store (vSIMDType value, uint32_t* a) noexcept { vst1q_u32 (a, value); }\r
+ static forcedinline uint32_t get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, uint32_t s) noexcept { return fb::set (v, i, s); }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_u32 (a, b); }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_u32 (a, b); }\r
static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return vmulq_u32 (a, b); }\r
//==============================================================================\r
static forcedinline vSIMDType expand (int32_t s) noexcept { return vdupq_n_s32 (s); }\r
static forcedinline vSIMDType load (const int32_t* a) noexcept { return vld1q_s32 (a); }\r
- static forcedinline void store (vSIMDType value, int32_t* a) noexcept { vst1q_s32 (a, value); }\r
- static forcedinline int32_t get (vSIMDType v, size_t i) noexcept { return v[i]; }\r
- static forcedinline vSIMDType set (vSIMDType v, size_t i, int32_t s) noexcept { v[i] = s; return v; }\r
+ static forcedinline void store (vSIMDType value, int32_t* a) noexcept { vst1q_s32 (a, value); }\r
+ static forcedinline int32_t get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, int32_t s) noexcept { return fb::set (v, i, s); }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_s32 (a, b); }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_s32 (a, b); }\r
static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return vmulq_s32 (a, b); }\r
//==============================================================================\r
static forcedinline vSIMDType expand (int8_t s) noexcept { return vdupq_n_s8 (s); }\r
static forcedinline vSIMDType load (const int8_t* a) noexcept { return vld1q_s8 (a); }\r
- static forcedinline void store (vSIMDType value, int8_t* a) noexcept { vst1q_s8 (a, value); }\r
- static forcedinline int8_t get (vSIMDType v, size_t i) noexcept { return v[i]; }\r
- static forcedinline vSIMDType set (vSIMDType v, size_t i, int8_t s) noexcept { v[i] = s; return v; }\r
+ static forcedinline void store (vSIMDType value, int8_t* a) noexcept { vst1q_s8 (a, value); }\r
+ static forcedinline int8_t get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, int8_t s) noexcept { return fb::set (v, i, s); }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_s8 (a, b); }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_s8 (a, b); }\r
static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return vmulq_s8 (a, b); }\r
static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vcgeq_s8 (a, b); }\r
static forcedinline bool allEqual (vSIMDType a, vSIMDType b) noexcept { return (SIMDNativeOps<int32_t>::sum ((SIMDNativeOps<int32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_s8 (a, b, c); }\r
- static forcedinline int8_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
+ static forcedinline int8_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
static forcedinline vSIMDType truncate (vSIMDType a) noexcept { return a; }\r
};\r
\r
//==============================================================================\r
static forcedinline vSIMDType expand (uint8_t s) noexcept { return vdupq_n_u8 (s); }\r
static forcedinline vSIMDType load (const uint8_t* a) noexcept { return vld1q_u8 (a); }\r
- static forcedinline void store (vSIMDType value, uint8_t* a) noexcept { vst1q_u8 (a, value); }\r
- static forcedinline uint8_t get (vSIMDType v, size_t i) noexcept { return v[i]; }\r
- static forcedinline vSIMDType set (vSIMDType v, size_t i, uint8_t s) noexcept { v[i] = s; return v; }\r
+ static forcedinline void store (vSIMDType value, uint8_t* a) noexcept { vst1q_u8 (a, value); }\r
+ static forcedinline uint8_t get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, uint8_t s) noexcept { return fb::set (v, i, s); }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_u8 (a, b); }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_u8 (a, b); }\r
static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return vmulq_u8 (a, b); }\r
static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vcgeq_u8 (a, b); }\r
static forcedinline bool allEqual (vSIMDType a, vSIMDType b) noexcept { return (SIMDNativeOps<uint32_t>::sum ((SIMDNativeOps<uint32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_u8 (a, b, c); }\r
- static forcedinline uint8_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
+ static forcedinline uint8_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
static forcedinline vSIMDType truncate (vSIMDType a) noexcept { return a; }\r
};\r
\r
//==============================================================================\r
static forcedinline vSIMDType expand (int16_t s) noexcept { return vdupq_n_s16 (s); }\r
static forcedinline vSIMDType load (const int16_t* a) noexcept { return vld1q_s16 (a); }\r
- static forcedinline void store (vSIMDType value, int16_t* a) noexcept { vst1q_s16 (a, value); }\r
- static forcedinline int16_t get (vSIMDType v, size_t i) noexcept { return v[i]; }\r
- static forcedinline vSIMDType set (vSIMDType v, size_t i, int16_t s) noexcept { v[i] = s; return v; }\r
+ static forcedinline void store (vSIMDType value, int16_t* a) noexcept { vst1q_s16 (a, value); }\r
+ static forcedinline int16_t get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, int16_t s) noexcept { return fb::set (v, i, s); }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_s16 (a, b); }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_s16 (a, b); }\r
static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return vmulq_s16 (a, b); }\r
static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vcgeq_s16 (a, b); }\r
static forcedinline bool allEqual (vSIMDType a, vSIMDType b) noexcept { return (SIMDNativeOps<int32_t>::sum ((SIMDNativeOps<int32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_s16 (a, b, c); }\r
- static forcedinline int16_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
+ static forcedinline int16_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
static forcedinline vSIMDType truncate (vSIMDType a) noexcept { return a; }\r
};\r
\r
//==============================================================================\r
static forcedinline vSIMDType expand (uint16_t s) noexcept { return vdupq_n_u16 (s); }\r
static forcedinline vSIMDType load (const uint16_t* a) noexcept { return vld1q_u16 (a); }\r
- static forcedinline void store (vSIMDType value, uint16_t* a) noexcept { vst1q_u16 (a, value); }\r
- static forcedinline uint16_t get (vSIMDType v, size_t i) noexcept { return v[i]; }\r
- static forcedinline vSIMDType set (vSIMDType v, size_t i, uint16_t s) noexcept { v[i] = s; return v; }\r
+ static forcedinline void store (vSIMDType value, uint16_t* a) noexcept { vst1q_u16 (a, value); }\r
+ static forcedinline uint16_t get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, uint16_t s) noexcept { return fb::set (v, i, s); }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_u16 (a, b); }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_u16 (a, b); }\r
static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return vmulq_u16 (a, b); }\r
static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vcgeq_u16 (a, b); }\r
static forcedinline bool allEqual (vSIMDType a, vSIMDType b) noexcept { return (SIMDNativeOps<uint32_t>::sum ((SIMDNativeOps<uint32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_u16 (a, b, c); }\r
- static forcedinline uint16_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
+ static forcedinline uint16_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
static forcedinline vSIMDType truncate (vSIMDType a) noexcept { return a; }\r
};\r
\r
//==============================================================================\r
static forcedinline vSIMDType expand (int64_t s) noexcept { return vdupq_n_s64 (s); }\r
static forcedinline vSIMDType load (const int64_t* a) noexcept { return vld1q_s64 (a); }\r
- static forcedinline void store (vSIMDType value, int64_t* a) noexcept { vst1q_s64 (a, value); }\r
- static forcedinline int64_t get (vSIMDType v, size_t i) noexcept { return v[i]; }\r
- static forcedinline vSIMDType set (vSIMDType v, size_t i, int64_t s) noexcept { v[i] = s; return v; }\r
+ static forcedinline void store (vSIMDType value, int64_t* a) noexcept { vst1q_s64 (a, value); }\r
+ static forcedinline int64_t get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, int64_t s) noexcept { return fb::set (v, i, s); }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_s64 (a, b); }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_s64 (a, b); }\r
static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return fb::mul (a, b); }\r
static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept { return fb::greaterThanOrEqual (a, b); }\r
static forcedinline bool allEqual (vSIMDType a, vSIMDType b) noexcept { return (SIMDNativeOps<int32_t>::sum ((SIMDNativeOps<int32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return fb::multiplyAdd (a, b, c); }\r
- static forcedinline int64_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
+ static forcedinline int64_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
static forcedinline vSIMDType truncate (vSIMDType a) noexcept { return a; }\r
};\r
\r
//==============================================================================\r
static forcedinline vSIMDType expand (uint64_t s) noexcept { return vdupq_n_u64 (s); }\r
static forcedinline vSIMDType load (const uint64_t* a) noexcept { return vld1q_u64 (a); }\r
- static forcedinline void store (vSIMDType value, uint64_t* a) noexcept { vst1q_u64 (a, value); }\r
- static forcedinline uint64_t get (vSIMDType v, size_t i) noexcept { return v[i]; }\r
- static forcedinline vSIMDType set (vSIMDType v, size_t i, uint64_t s) noexcept { v[i] = s; return v; }\r
+ static forcedinline void store (vSIMDType value, uint64_t* a) noexcept { vst1q_u64 (a, value); }\r
+ static forcedinline uint64_t get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, uint64_t s) noexcept { return fb::set (v, i, s); }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_u64 (a, b); }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_u64 (a, b); }\r
static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return fb::mul (a, b); }\r
static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept { return fb::greaterThanOrEqual (a, b); }\r
static forcedinline bool allEqual (vSIMDType a, vSIMDType b) noexcept { return (SIMDNativeOps<uint32_t>::sum ((SIMDNativeOps<uint32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return fb::multiplyAdd (a, b, c); }\r
- static forcedinline uint64_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
+ static forcedinline uint64_t sum (vSIMDType a) noexcept { return fb::sum (a); }\r
static forcedinline vSIMDType truncate (vSIMDType a) noexcept { return a; }\r
};\r
\r
//==============================================================================\r
static forcedinline vSIMDType expand (float s) noexcept { return vdupq_n_f32 (s); }\r
static forcedinline vSIMDType load (const float* a) noexcept { return vld1q_f32 (a); }\r
- static forcedinline float get (vSIMDType v, size_t i) noexcept { return v[i]; }\r
- static forcedinline vSIMDType set (vSIMDType v, size_t i, float s) noexcept { v[i] = s; return v; }\r
- static forcedinline void store (vSIMDType value, float* a) noexcept { vst1q_f32 (a, value); }\r
+ static forcedinline float get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, float s) noexcept { return fb::set (v, i, s); }\r
+ static forcedinline void store (vSIMDType value, float* a) noexcept { vst1q_f32 (a, value); }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_f32 (a, b); }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_f32 (a, b); }\r
static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return vmulq_f32 (a, b); }\r
\r
@tags{DSP}\r
*/\r
+#if JUCE_64BIT\r
+template <>\r
+struct SIMDNativeOps<double>\r
+{\r
+ //==============================================================================\r
+ using vSIMDType = float64x2_t;\r
+ using vMaskType = uint64x2_t;\r
+ using fb = SIMDFallbackOps<double, vSIMDType>;\r
+\r
+ //==============================================================================\r
+ DECLARE_NEON_SIMD_CONST (int64_t, kAllBitsSet);\r
+ DECLARE_NEON_SIMD_CONST (double, kOne);\r
+\r
+ //==============================================================================\r
+ static forcedinline vSIMDType expand (double s) noexcept { return vdupq_n_f64 (s); }\r
+ static forcedinline vSIMDType load (const double* a) noexcept { return vld1q_f64 (a); }\r
+ static forcedinline double get (vSIMDType v, size_t i) noexcept { return fb::get (v, i); }\r
+ static forcedinline vSIMDType set (vSIMDType v, size_t i, double s) noexcept { return fb::set (v, i, s); }\r
+ static forcedinline void store (vSIMDType value, double* a) noexcept { vst1q_f64 (a, value); }\r
+ static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return vaddq_f64 (a, b); }\r
+ static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return vsubq_f64 (a, b); }\r
+ static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept { return vmulq_f64 (a, b); }\r
+ static forcedinline vSIMDType bit_and (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vandq_u64 ((vMaskType) a, (vMaskType) b); }\r
+ static forcedinline vSIMDType bit_or (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vorrq_u64 ((vMaskType) a, (vMaskType) b); }\r
+ static forcedinline vSIMDType bit_xor (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) veorq_u64 ((vMaskType) a, (vMaskType) b); }\r
+ static forcedinline vSIMDType bit_notand (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vbicq_u64 ((vMaskType) b, (vMaskType) a); }\r
+ static forcedinline vSIMDType bit_not (vSIMDType a) noexcept { return bit_notand (a, vld1q_f64 ((double*) kAllBitsSet)); }\r
+ static forcedinline vSIMDType min (vSIMDType a, vSIMDType b) noexcept { return vminq_f64 (a, b); }\r
+ static forcedinline vSIMDType max (vSIMDType a, vSIMDType b) noexcept { return vmaxq_f64 (a, b); }\r
+ static forcedinline vSIMDType equal (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vceqq_f64 (a, b); }\r
+ static forcedinline vSIMDType notEqual (vSIMDType a, vSIMDType b) noexcept { return bit_not (equal (a, b)); }\r
+ static forcedinline vSIMDType greaterThan (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vcgtq_f64 (a, b); }\r
+ static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept { return (vSIMDType) vcgeq_f64 (a, b); }\r
+ static forcedinline bool allEqual (vSIMDType a, vSIMDType b) noexcept { return (SIMDNativeOps<uint32_t>::sum ((SIMDNativeOps<uint32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
+ static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_f64 (a, b, c); }\r
+ static forcedinline vSIMDType cmplxmul (vSIMDType a, vSIMDType b) noexcept { return fb::cmplxmul (a, b); }\r
+ static forcedinline double sum (vSIMDType a) noexcept { return fb::sum (a); }\r
+ static forcedinline vSIMDType oddevensum (vSIMDType a) noexcept { return a; }\r
+ static forcedinline vSIMDType truncate (vSIMDType a) noexcept { return vcvtq_f64_s64 (vcvtq_s64_f64 (a)); }\r
+};\r
+#else\r
template <>\r
struct SIMDNativeOps<double>\r
{\r
\r
static forcedinline vSIMDType expand (double s) noexcept { return {{s, s}}; }\r
static forcedinline vSIMDType load (const double* a) noexcept { return {{a[0], a[1]}}; }\r
- static forcedinline void store (vSIMDType v, double* a) noexcept { a[0] = v.v[0]; a[1] = v.v[1]; }\r
- static forcedinline double get (vSIMDType v, size_t i) noexcept { return v.v[i]; }\r
+ static forcedinline void store (vSIMDType v, double* a) noexcept { a[0] = v.v[0]; a[1] = v.v[1]; }\r
+ static forcedinline double get (vSIMDType v, size_t i) noexcept { return v.v[i]; }\r
static forcedinline vSIMDType set (vSIMDType v, size_t i, double s) noexcept { v.v[i] = s; return v; }\r
static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept { return {{a.v[0] + b.v[0], a.v[1] + b.v[1]}}; }\r
static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept { return {{a.v[0] - b.v[0], a.v[1] - b.v[1]}}; }\r
static forcedinline bool allEqual (vSIMDType a, vSIMDType b) noexcept { return fb::allEqual (a, b); }\r
static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return fb::multiplyAdd (a, b, c); }\r
static forcedinline vSIMDType cmplxmul (vSIMDType a, vSIMDType b) noexcept { return fb::cmplxmul (a, b); }\r
- static forcedinline double sum (vSIMDType a) noexcept { return fb::sum (a); }\r
+ static forcedinline double sum (vSIMDType a) noexcept { return fb::sum (a); }\r
static forcedinline vSIMDType oddevensum (vSIMDType a) noexcept { return a; }\r
static forcedinline vSIMDType truncate (vSIMDType a) noexcept { return fb::truncate (a); }\r
};\r
-\r
-#endif\r
+#endif // JUCE_64BIT\r
+#endif // #ifndef DOXYGEN\r
\r
JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
\r
\r
private:\r
//==============================================================================\r
- template <typename T = InterpolationType>\r
- typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, SampleType>::type\r
- interpolateSample (int channel) const\r
+ SampleType interpolateSample (int channel)\r
{\r
- auto index = (readPos[(size_t) channel] + delayInt) % totalSize;\r
- return bufferData.getSample (channel, index);\r
- }\r
-\r
- template <typename T = InterpolationType>\r
- typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Linear>::value, SampleType>::type\r
- interpolateSample (int channel) const\r
- {\r
- auto index1 = readPos[(size_t) channel] + delayInt;\r
- auto index2 = index1 + 1;\r
-\r
- if (index2 >= totalSize)\r
+ if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::None>)\r
{\r
- index1 %= totalSize;\r
- index2 %= totalSize;\r
+ auto index = (readPos[(size_t) channel] + delayInt) % totalSize;\r
+ return bufferData.getSample (channel, index);\r
}\r
+ else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Linear>)\r
+ {\r
+ auto index1 = readPos[(size_t) channel] + delayInt;\r
+ auto index2 = index1 + 1;\r
\r
- auto value1 = bufferData.getSample (channel, index1);\r
- auto value2 = bufferData.getSample (channel, index2);\r
-\r
- return value1 + delayFrac * (value2 - value1);\r
- }\r
+ if (index2 >= totalSize)\r
+ {\r
+ index1 %= totalSize;\r
+ index2 %= totalSize;\r
+ }\r
\r
- template <typename T = InterpolationType>\r
- typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Lagrange3rd>::value, SampleType>::type\r
- interpolateSample (int channel) const\r
- {\r
- auto index1 = readPos[(size_t) channel] + delayInt;\r
- auto index2 = index1 + 1;\r
- auto index3 = index2 + 1;\r
- auto index4 = index3 + 1;\r
+ auto value1 = bufferData.getSample (channel, index1);\r
+ auto value2 = bufferData.getSample (channel, index2);\r
\r
- if (index4 >= totalSize)\r
- {\r
- index1 %= totalSize;\r
- index2 %= totalSize;\r
- index3 %= totalSize;\r
- index4 %= totalSize;\r
+ return value1 + delayFrac * (value2 - value1);\r
}\r
+ else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)\r
+ {\r
+ auto index1 = readPos[(size_t) channel] + delayInt;\r
+ auto index2 = index1 + 1;\r
+ auto index3 = index2 + 1;\r
+ auto index4 = index3 + 1;\r
\r
- auto* samples = bufferData.getReadPointer (channel);\r
+ if (index4 >= totalSize)\r
+ {\r
+ index1 %= totalSize;\r
+ index2 %= totalSize;\r
+ index3 %= totalSize;\r
+ index4 %= totalSize;\r
+ }\r
\r
- auto value1 = samples[index1];\r
- auto value2 = samples[index2];\r
- auto value3 = samples[index3];\r
- auto value4 = samples[index4];\r
+ auto* samples = bufferData.getReadPointer (channel);\r
\r
- auto d1 = delayFrac - 1.f;\r
- auto d2 = delayFrac - 2.f;\r
- auto d3 = delayFrac - 3.f;\r
+ auto value1 = samples[index1];\r
+ auto value2 = samples[index2];\r
+ auto value3 = samples[index3];\r
+ auto value4 = samples[index4];\r
\r
- auto c1 = -d1 * d2 * d3 / 6.f;\r
- auto c2 = d2 * d3 * 0.5f;\r
- auto c3 = -d1 * d3 * 0.5f;\r
- auto c4 = d1 * d2 / 6.f;\r
+ auto d1 = delayFrac - 1.f;\r
+ auto d2 = delayFrac - 2.f;\r
+ auto d3 = delayFrac - 3.f;\r
\r
- return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4);\r
- }\r
+ auto c1 = -d1 * d2 * d3 / 6.f;\r
+ auto c2 = d2 * d3 * 0.5f;\r
+ auto c3 = -d1 * d3 * 0.5f;\r
+ auto c4 = d1 * d2 / 6.f;\r
\r
- template <typename T = InterpolationType>\r
- typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Thiran>::value, SampleType>::type\r
- interpolateSample (int channel)\r
- {\r
- auto index1 = readPos[(size_t) channel] + delayInt;\r
- auto index2 = index1 + 1;\r
-\r
- if (index2 >= totalSize)\r
- {\r
- index1 %= totalSize;\r
- index2 %= totalSize;\r
+ return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4);\r
}\r
+ else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)\r
+ {\r
+ auto index1 = readPos[(size_t) channel] + delayInt;\r
+ auto index2 = index1 + 1;\r
\r
- auto value1 = bufferData.getSample (channel, index1);\r
- auto value2 = bufferData.getSample (channel, index2);\r
-\r
- auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);\r
- v[(size_t) channel] = output;\r
-\r
- return output;\r
- }\r
+ if (index2 >= totalSize)\r
+ {\r
+ index1 %= totalSize;\r
+ index2 %= totalSize;\r
+ }\r
\r
- //==============================================================================\r
- template <typename T = InterpolationType>\r
- typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, void>::type\r
- updateInternalVariables()\r
- {\r
- }\r
+ auto value1 = bufferData.getSample (channel, index1);\r
+ auto value2 = bufferData.getSample (channel, index2);\r
\r
- template <typename T = InterpolationType>\r
- typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Linear>::value, void>::type\r
- updateInternalVariables()\r
- {\r
- }\r
+ auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);\r
+ v[(size_t) channel] = output;\r
\r
- template <typename T = InterpolationType>\r
- typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Lagrange3rd>::value, void>::type\r
- updateInternalVariables()\r
- {\r
- if (delayInt >= 1)\r
- {\r
- delayFrac++;\r
- delayInt--;\r
+ return output;\r
}\r
}\r
\r
- template <typename T = InterpolationType>\r
- typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Thiran>::value, void>::type\r
- updateInternalVariables()\r
+ //==============================================================================\r
+ void updateInternalVariables()\r
{\r
- if (delayFrac < (SampleType) 0.618 && delayInt >= 1)\r
+ if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)\r
{\r
- delayFrac++;\r
- delayInt--;\r
+ if (delayInt >= 1)\r
+ {\r
+ delayFrac++;\r
+ delayInt--;\r
+ }\r
}\r
+ else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)\r
+ {\r
+ if (delayFrac < (SampleType) 0.618 && delayInt >= 1)\r
+ {\r
+ delayFrac++;\r
+ delayInt--;\r
+ }\r
\r
- alpha = (1 - delayFrac) / (1 + delayFrac);\r
+ alpha = (1 - delayFrac) / (1 + delayFrac);\r
+ }\r
}\r
\r
//==============================================================================\r
template <typename ProcessContext>\r
void process (const ProcessContext& context) noexcept\r
{\r
- static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,\r
+ static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,\r
"The sample-type of the FIR filter must match the sample-type supplied to this process callback");\r
check();\r
\r
template <typename ProcessContext, bool bypassed>\r
void Filter<SampleType>::processInternal (const ProcessContext& context) noexcept\r
{\r
- static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,\r
+ static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,\r
"The sample-type of the IIR filter must match the sample-type supplied to this process callback");\r
check();\r
\r
template <typename Fn, typename Tuple, size_t... Ix>\r
constexpr void forEachInTuple (Fn&& fn, Tuple&& tuple, std::index_sequence<Ix...>)\r
{\r
- (void) std::initializer_list<int> { ((void) fn (std::get<Ix> (tuple), std::integral_constant<size_t, Ix>()), 0)... };\r
+ (fn (std::get<Ix> (tuple), std::integral_constant<size_t, Ix>()), ...);\r
}\r
\r
template <typename T>\r
- using TupleIndexSequence = std::make_index_sequence<std::tuple_size<std::remove_cv_t<std::remove_reference_t<T>>>::value>;\r
+ using TupleIndexSequence = std::make_index_sequence<std::tuple_size_v<std::remove_cv_t<std::remove_reference_t<T>>>>;\r
\r
template <typename Fn, typename Tuple>\r
constexpr void forEachInTuple (Fn&& fn, Tuple&& tuple)\r
forEachInTuple (std::forward<Fn> (fn), std::forward<Tuple> (tuple), TupleIndexSequence<Tuple>{});\r
}\r
\r
- // This could be a template variable, but that code causes an internal compiler error in MSVC 19.00.24215\r
template <typename Context, size_t Ix>\r
- struct UseContextDirectly\r
- {\r
- static constexpr auto value = ! Context::usesSeparateInputAndOutputBlocks() || Ix == 0;\r
- };\r
+ inline constexpr auto useContextDirectly = ! Context::usesSeparateInputAndOutputBlocks() || Ix == 0;\r
}\r
#endif\r
\r
}\r
\r
private:\r
- template <typename Context, typename Proc, size_t Ix, std::enable_if_t<! detail::UseContextDirectly<Context, Ix>::value, int> = 0>\r
+ template <typename Context, typename Proc, size_t Ix>\r
void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept\r
{\r
- jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels());\r
- ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock());\r
- replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed);\r
-\r
- proc.process (replacingContext);\r
- }\r
-\r
- template <typename Context, typename Proc, size_t Ix, std::enable_if_t<detail::UseContextDirectly<Context, Ix>::value, int> = 0>\r
- void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept\r
- {\r
- auto contextCopy = context;\r
- contextCopy.isBypassed = (bypassed[Ix] || context.isBypassed);\r
-\r
- proc.process (contextCopy);\r
+ if constexpr (detail::useContextDirectly<Context, Ix>)\r
+ {\r
+ auto contextCopy = context;\r
+ contextCopy.isBypassed = (bypassed[Ix] || context.isBypassed);\r
+\r
+ proc.process (contextCopy);\r
+ }\r
+ else\r
+ {\r
+ jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels());\r
+ ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock());\r
+ replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed);\r
+\r
+ proc.process (replacingContext);\r
+ }\r
}\r
\r
std::tuple<Processors...> processors;\r
template <typename ProcessContext>\r
void process (const ProcessContext& context) noexcept\r
{\r
- static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,\r
+ static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,\r
"The sample-type of the filter must match the sample-type supplied to this process callback");\r
\r
if (context.isBypassed)\r
};\r
\r
//==============================================================================\r
-#if JUCE_CXX17_IS_AVAILABLE && ! ((JUCE_MAC || JUCE_IOS) && JUCE_CLANG && __clang_major__ < 10)\r
+#if ! ((JUCE_MAC || JUCE_IOS) && JUCE_CLANG && __clang_major__ < 10)\r
template <typename Functor>\r
static WaveShaper<typename std::invoke_result<Functor>, Functor> CreateWaveShaper (Functor functionToUse) { return {functionToUse}; }\r
#else\r
pingReceived();\r
}\r
\r
- void startPinging() { startThread (4); }\r
+ void startPinging() { startThread (Priority::low); }\r
\r
void pingReceived() noexcept { countdown = timeoutMs / 1000 + 1; }\r
void triggerConnectionLostMessage() { triggerAsyncUpdate(); }\r
message.setAttribute ("address", String());\r
message.setAttribute ("port", connectionPort);\r
\r
- startThread (2);\r
+ startThread (Priority::background);\r
}\r
\r
NetworkServiceDiscovery::Advertiser::~Advertiser()\r
#endif\r
\r
socket.bindToPort (broadcastPort);\r
- startThread (2);\r
+ startThread (Priority::background);\r
}\r
\r
NetworkServiceDiscovery::AvailableServiceList::~AvailableServiceList()\r
\r
ID: juce_events\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_core\r
\r
return;\r
\r
HRESULT status = roInitialize (1);\r
- initialised = ! (status != S_OK && status != S_FALSE && status != 0x80010106L);\r
+ initialised = ! (status != S_OK && status != S_FALSE && status != (HRESULT) 0x80010106L);\r
}\r
\r
WinRTWrapper::~WinRTWrapper()\r
\r
void handleAsyncUpdate() override\r
{\r
- startThread (7);\r
+ startThread (Priority::high);\r
}\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimerThread)\r
\r
//==============================================================================\r
/** Returns a copy of this colour with a different hue. */\r
- JUCE_NODISCARD Colour withHue (float newHue) const noexcept;\r
+ [[nodiscard]] Colour withHue (float newHue) const noexcept;\r
\r
/** Returns a copy of this colour with a different saturation. */\r
- JUCE_NODISCARD Colour withSaturation (float newSaturation) const noexcept;\r
+ [[nodiscard]] Colour withSaturation (float newSaturation) const noexcept;\r
\r
/** Returns a copy of this colour with a different saturation in the HSL colour space. */\r
- JUCE_NODISCARD Colour withSaturationHSL (float newSaturation) const noexcept;\r
+ [[nodiscard]] Colour withSaturationHSL (float newSaturation) const noexcept;\r
\r
/** Returns a copy of this colour with a different brightness.\r
@see brighter, darker, withMultipliedBrightness\r
*/\r
- JUCE_NODISCARD Colour withBrightness (float newBrightness) const noexcept;\r
+ [[nodiscard]] Colour withBrightness (float newBrightness) const noexcept;\r
\r
/** Returns a copy of this colour with a different lightness.\r
@see lighter, darker, withMultipliedLightness\r
*/\r
- JUCE_NODISCARD Colour withLightness (float newLightness) const noexcept;\r
+ [[nodiscard]] Colour withLightness (float newLightness) const noexcept;\r
\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
- JUCE_NODISCARD Colour withRotatedHue (float amountToRotate) const noexcept;\r
+ [[nodiscard]] Colour withRotatedHue (float amountToRotate) const noexcept;\r
\r
/** Returns a copy of this colour with its saturation multiplied by the given value.\r
The new colour's saturation is (this->getSaturation() * multiplier)\r
(the result is clipped to legal limits).\r
*/\r
- JUCE_NODISCARD Colour withMultipliedSaturation (float multiplier) const noexcept;\r
+ [[nodiscard]] Colour withMultipliedSaturation (float multiplier) const noexcept;\r
\r
/** Returns a copy of this colour with its saturation multiplied by the given value.\r
The new colour's saturation is (this->getSaturation() * multiplier)\r
\r
This will be in the HSL colour space.\r
*/\r
- JUCE_NODISCARD Colour withMultipliedSaturationHSL (float multiplier) const noexcept;\r
+ [[nodiscard]] Colour withMultipliedSaturationHSL (float multiplier) const noexcept;\r
\r
/** Returns a copy of this colour with its brightness multiplied by the given value.\r
The new colour's brightness is (this->getBrightness() * multiplier)\r
(the result is clipped to legal limits).\r
*/\r
- JUCE_NODISCARD Colour withMultipliedBrightness (float amount) const noexcept;\r
+ [[nodiscard]] Colour withMultipliedBrightness (float amount) const noexcept;\r
\r
/** Returns a copy of this colour with its lightness multiplied by the given value.\r
The new colour's lightness is (this->lightness() * multiplier)\r
(the result is clipped to legal limits).\r
*/\r
- JUCE_NODISCARD Colour withMultipliedLightness (float amount) const noexcept;\r
+ [[nodiscard]] Colour withMultipliedLightness (float amount) const noexcept;\r
\r
//==============================================================================\r
/** Returns a brighter version of this colour.\r
where 0 is unchanged, and higher values make it brighter\r
@see withMultipliedBrightness\r
*/\r
- JUCE_NODISCARD Colour brighter (float amountBrighter = 0.4f) const noexcept;\r
+ [[nodiscard]] Colour brighter (float amountBrighter = 0.4f) const noexcept;\r
\r
/** Returns a darker version of this colour.\r
@param amountDarker how much darker to make it - a value greater than or equal to 0,\r
where 0 is unchanged, and higher values make it darker\r
@see withMultipliedBrightness\r
*/\r
- JUCE_NODISCARD Colour darker (float amountDarker = 0.4f) const noexcept;\r
+ [[nodiscard]] Colour darker (float amountDarker = 0.4f) const noexcept;\r
\r
//==============================================================================\r
/** Returns a colour that will be clearly visible against this colour.\r
that's just a little bit lighter; Colours::black.contrasting (1.0f) will\r
return white; Colours::white.contrasting (1.0f) will return black, etc.\r
*/\r
- JUCE_NODISCARD Colour contrasting (float amount = 1.0f) const noexcept;\r
+ [[nodiscard]] Colour contrasting (float amount = 1.0f) const noexcept;\r
\r
/** Returns a colour that is as close as possible to a target colour whilst\r
still being in contrast to this one.\r
nudged up or down so that it differs from the luminosity of this colour\r
by at least the amount specified by minLuminosityDiff.\r
*/\r
- JUCE_NODISCARD Colour contrasting (Colour targetColour, float minLuminosityDiff) const noexcept;\r
+ [[nodiscard]] Colour contrasting (Colour targetColour, float minLuminosityDiff) const noexcept;\r
\r
/** Returns a colour that contrasts against two colours.\r
Looks for a colour that contrasts with both of the colours passed-in.\r
Handy for things like choosing a highlight colour in text editors, etc.\r
*/\r
- JUCE_NODISCARD static Colour contrasting (Colour colour1,\r
+ [[nodiscard]] static Colour contrasting (Colour colour1,\r
Colour colour2) noexcept;\r
\r
//==============================================================================\r
/** Returns an opaque shade of grey.\r
@param brightness the level of grey to return - 0 is black, 1.0 is white\r
*/\r
- JUCE_NODISCARD static Colour greyLevel (float brightness) noexcept;\r
+ [[nodiscard]] static Colour greyLevel (float brightness) noexcept;\r
\r
//==============================================================================\r
/** Returns a stringified version of this colour.\r
String toString() const;\r
\r
/** Reads the colour from a string that was created with toString(). */\r
- JUCE_NODISCARD static Colour fromString (StringRef encodedColourString);\r
+ [[nodiscard]] static Colour fromString (StringRef encodedColourString);\r
\r
/** Returns the colour as a hex string in the form RRGGBB or AARRGGBB. */\r
String toDisplayString (bool includeAlphaValue) const;\r
\r
void Graphics::fillAll() const\r
{\r
- fillRect (context.getClipBounds());\r
+ context.fillAll();\r
}\r
\r
void Graphics::fillAll (Colour colourToUse) const\r
{\r
if (! colourToUse.isTransparent())\r
{\r
- auto clip = context.getClipBounds();\r
-\r
context.saveState();\r
context.setFill (colourToUse);\r
- context.fillRect (clip, false);\r
+ context.fillAll();\r
context.restoreState();\r
}\r
}\r
virtual void setInterpolationQuality (Graphics::ResamplingQuality) = 0;\r
\r
//==============================================================================\r
+ virtual void fillAll() { fillRect (getClipBounds(), false); }\r
virtual void fillRect (const Rectangle<int>&, bool replaceExistingContents) = 0;\r
virtual void fillRect (const Rectangle<float>&) = 0;\r
virtual void fillRectList (const RectangleList<float>&) = 0;\r
/** Returns a copy of this font with a new typeface style.\r
@see getAvailableStyles()\r
*/\r
- JUCE_NODISCARD Font withTypefaceStyle (const String& newStyle) const;\r
+ [[nodiscard]] Font withTypefaceStyle (const String& newStyle) const;\r
\r
/** Returns a list of the styles that this font can use. */\r
StringArray getAvailableStyles() const;\r
\r
//==============================================================================\r
/** Returns a copy of this font with a new height. */\r
- JUCE_NODISCARD Font withHeight (float height) const;\r
+ [[nodiscard]] Font withHeight (float height) const;\r
\r
/** Returns a copy of this font with a new height, specified in points. */\r
- JUCE_NODISCARD Font withPointHeight (float heightInPoints) const;\r
+ [[nodiscard]] Font withPointHeight (float heightInPoints) const;\r
\r
/** Changes the font's height.\r
@see getHeight, withHeight, setHeightWithoutChangingWidth\r
@param styleFlags a bitwise-or'ed combination of values from the FontStyleFlags enum.\r
@see FontStyleFlags, getStyleFlags\r
*/\r
- JUCE_NODISCARD Font withStyle (int styleFlags) const;\r
+ [[nodiscard]] Font withStyle (int styleFlags) const;\r
\r
/** Changes the font's style.\r
@param newFlags a bitwise-or'ed combination of values from the FontStyleFlags enum.\r
/** Returns a copy of this font with the bold attribute set.\r
If the font does not have a bold version, this will return the default font.\r
*/\r
- JUCE_NODISCARD Font boldened() const;\r
+ [[nodiscard]] Font boldened() const;\r
\r
/** Returns true if the font is bold. */\r
bool isBold() const noexcept;\r
/** Makes the font italic or non-italic. */\r
void setItalic (bool shouldBeItalic);\r
/** Returns a copy of this font with the italic attribute set. */\r
- JUCE_NODISCARD Font italicised() const;\r
+ [[nodiscard]] Font italicised() const;\r
/** Returns true if the font is italic. */\r
bool isItalic() const noexcept;\r
\r
narrower, greater than 1.0 will be stretched out.\r
@see getHorizontalScale\r
*/\r
- JUCE_NODISCARD Font withHorizontalScale (float scaleFactor) const;\r
+ [[nodiscard]] Font withHorizontalScale (float scaleFactor) const;\r
\r
/** Changes the font's horizontal scale factor.\r
@param scaleFactor a value of 1.0 is the normal scale, less than this will be\r
normal spacing, positive values spread the letters out,\r
negative values make them closer together.\r
*/\r
- JUCE_NODISCARD Font withExtraKerningFactor (float extraKerning) const;\r
+ [[nodiscard]] Font withExtraKerningFactor (float extraKerning) const;\r
\r
/** Changes the font's kerning.\r
@param extraKerning a multiple of the font's height that will be added\r
class DereferencingIterator\r
{\r
public:\r
- using value_type = typename std::remove_reference<decltype(**std::declval<Iterator>())>::type;\r
+ using value_type = std::remove_reference_t<decltype(**std::declval<Iterator>())>;\r
using difference_type = typename std::iterator_traits<Iterator>::difference_type;\r
using pointer = value_type*;\r
using reference = value_type&;\r
template <typename OtherType>\r
constexpr Point operator* (OtherType multiplier) const noexcept\r
{\r
- using CommonType = typename std::common_type<ValueType, OtherType>::type;\r
+ using CommonType = std::common_type_t<ValueType, OtherType>;\r
return Point ((ValueType) ((CommonType) x * (CommonType) multiplier),\r
(ValueType) ((CommonType) y * (CommonType) multiplier));\r
}\r
template <typename OtherType>\r
constexpr Point operator/ (OtherType divisor) const noexcept\r
{\r
- using CommonType = typename std::common_type<ValueType, OtherType>::type;\r
+ using CommonType = std::common_type_t<ValueType, OtherType>;\r
return Point ((ValueType) ((CommonType) x / (CommonType) divisor),\r
(ValueType) ((CommonType) y / (CommonType) divisor));\r
}\r
\r
//==============================================================================\r
/** This type will be double if the Point's type is double, otherwise it will be float. */\r
- using FloatType = typename TypeHelpers::SmallestFloatType<ValueType>::type;\r
+ using FloatType = TypeHelpers::SmallestFloatType<ValueType>;\r
\r
//==============================================================================\r
/** Returns the straight-line distance between this point and the origin. */\r
void setVerticalRange (Range<ValueType> range) noexcept { pos.y = range.getStart(); h = range.getLength(); }\r
\r
/** Returns a rectangle which has the same size and y-position as this one, but with a different x-position. */\r
- JUCE_NODISCARD Rectangle withX (ValueType newX) const noexcept { return { newX, pos.y, w, h }; }\r
+ [[nodiscard]] Rectangle withX (ValueType newX) const noexcept { return { newX, pos.y, w, h }; }\r
\r
/** Returns a rectangle which has the same size and x-position as this one, but with a different y-position. */\r
- JUCE_NODISCARD Rectangle withY (ValueType newY) const noexcept { return { pos.x, newY, w, h }; }\r
+ [[nodiscard]] Rectangle withY (ValueType newY) const noexcept { return { pos.x, newY, w, h }; }\r
\r
/** Returns a rectangle which has the same size and y-position as this one, but whose right-hand edge has the given position. */\r
- JUCE_NODISCARD Rectangle withRightX (ValueType newRightX) const noexcept { return { newRightX - w, pos.y, w, h }; }\r
+ [[nodiscard]] Rectangle withRightX (ValueType newRightX) const noexcept { return { newRightX - w, pos.y, w, h }; }\r
\r
/** Returns a rectangle which has the same size and x-position as this one, but whose bottom edge has the given position. */\r
- JUCE_NODISCARD Rectangle withBottomY (ValueType newBottomY) const noexcept { return { pos.x, newBottomY - h, w, h }; }\r
+ [[nodiscard]] Rectangle withBottomY (ValueType newBottomY) const noexcept { return { pos.x, newBottomY - h, w, h }; }\r
\r
/** Returns a rectangle with the same size as this one, but a new position. */\r
- JUCE_NODISCARD Rectangle withPosition (ValueType newX, ValueType newY) const noexcept { return { newX, newY, w, h }; }\r
+ [[nodiscard]] Rectangle withPosition (ValueType newX, ValueType newY) const noexcept { return { newX, newY, w, h }; }\r
\r
/** Returns a rectangle with the same size as this one, but a new position. */\r
- JUCE_NODISCARD Rectangle withPosition (Point<ValueType> newPos) const noexcept { return { newPos.x, newPos.y, w, h }; }\r
+ [[nodiscard]] Rectangle withPosition (Point<ValueType> newPos) const noexcept { return { newPos.x, newPos.y, w, h }; }\r
\r
/** Returns a rectangle whose size is the same as this one, but whose top-left position is (0, 0). */\r
- JUCE_NODISCARD Rectangle withZeroOrigin() const noexcept { return { w, h }; }\r
+ [[nodiscard]] Rectangle withZeroOrigin() const noexcept { return { w, h }; }\r
\r
/** Returns a rectangle with the same size as this one, but a new centre position. */\r
- JUCE_NODISCARD Rectangle withCentre (Point<ValueType> newCentre) const noexcept { return { newCentre.x - w / (ValueType) 2,\r
+ [[nodiscard]] Rectangle withCentre (Point<ValueType> newCentre) const noexcept { return { newCentre.x - w / (ValueType) 2,\r
newCentre.y - h / (ValueType) 2, w, h }; }\r
\r
/** Returns a rectangle which has the same position and height as this one, but with a different width. */\r
- JUCE_NODISCARD Rectangle withWidth (ValueType newWidth) const noexcept { return { pos.x, pos.y, jmax (ValueType(), newWidth), h }; }\r
+ [[nodiscard]] Rectangle withWidth (ValueType newWidth) const noexcept { return { pos.x, pos.y, jmax (ValueType(), newWidth), h }; }\r
\r
/** Returns a rectangle which has the same position and width as this one, but with a different height. */\r
- JUCE_NODISCARD Rectangle withHeight (ValueType newHeight) const noexcept { return { pos.x, pos.y, w, jmax (ValueType(), newHeight) }; }\r
+ [[nodiscard]] Rectangle withHeight (ValueType newHeight) const noexcept { return { pos.x, pos.y, w, jmax (ValueType(), newHeight) }; }\r
\r
/** Returns a rectangle with the same top-left position as this one, but a new size. */\r
- JUCE_NODISCARD Rectangle withSize (ValueType newWidth, ValueType newHeight) const noexcept { return { pos.x, pos.y, jmax (ValueType(), newWidth), jmax (ValueType(), newHeight) }; }\r
+ [[nodiscard]] Rectangle withSize (ValueType newWidth, ValueType newHeight) const noexcept { return { pos.x, pos.y, jmax (ValueType(), newWidth), jmax (ValueType(), newHeight) }; }\r
\r
/** Returns a rectangle with the same centre position as this one, but a new size. */\r
- JUCE_NODISCARD Rectangle withSizeKeepingCentre (ValueType newWidth, ValueType newHeight) const noexcept { return { pos.x + (w - newWidth) / (ValueType) 2,\r
+ [[nodiscard]] Rectangle withSizeKeepingCentre (ValueType newWidth, ValueType newHeight) const noexcept { return { pos.x + (w - newWidth) / (ValueType) 2,\r
pos.y + (h - newHeight) / (ValueType) 2, newWidth, newHeight }; }\r
\r
/** Moves the x position, adjusting the width so that the right-hand edge remains in the same place.\r
If the new x is beyond the right of the current right-hand edge, the width will be set to zero.\r
@see setLeft\r
*/\r
- JUCE_NODISCARD Rectangle withLeft (ValueType newLeft) const noexcept { return { newLeft, pos.y, jmax (ValueType(), pos.x + w - newLeft), h }; }\r
+ [[nodiscard]] Rectangle withLeft (ValueType newLeft) const noexcept { return { newLeft, pos.y, jmax (ValueType(), pos.x + w - newLeft), h }; }\r
\r
/** Moves the y position, adjusting the height so that the bottom edge remains in the same place.\r
If the y is moved to be below the current bottom edge, the height will be set to zero.\r
If the new y is beyond the bottom of the current rectangle, the height will be set to zero.\r
@see setTop\r
*/\r
- JUCE_NODISCARD Rectangle withTop (ValueType newTop) const noexcept { return { pos.x, newTop, w, jmax (ValueType(), pos.y + h - newTop) }; }\r
+ [[nodiscard]] Rectangle withTop (ValueType newTop) const noexcept { return { pos.x, newTop, w, jmax (ValueType(), pos.y + h - newTop) }; }\r
\r
/** Adjusts the width so that the right-hand edge of the rectangle has this new value.\r
If the new right is below the current X value, the X will be pushed down to match it.\r
If the new right edge is below the current left-hand edge, the width will be set to zero.\r
@see setRight\r
*/\r
- JUCE_NODISCARD Rectangle withRight (ValueType newRight) const noexcept { return { jmin (pos.x, newRight), pos.y, jmax (ValueType(), newRight - pos.x), h }; }\r
+ [[nodiscard]] Rectangle withRight (ValueType newRight) const noexcept { return { jmin (pos.x, newRight), pos.y, jmax (ValueType(), newRight - pos.x), h }; }\r
\r
/** Adjusts the height so that the bottom edge of the rectangle has this new value.\r
If the new bottom is lower than the current Y value, the Y will be pushed down to match it.\r
If the new y is beyond the bottom of the current rectangle, the height will be set to zero.\r
@see setBottom\r
*/\r
- JUCE_NODISCARD Rectangle withBottom (ValueType newBottom) const noexcept { return { pos.x, jmin (pos.y, newBottom), w, jmax (ValueType(), newBottom - pos.y) }; }\r
+ [[nodiscard]] Rectangle withBottom (ValueType newBottom) const noexcept { return { pos.x, jmin (pos.y, newBottom), w, jmax (ValueType(), newBottom - pos.y) }; }\r
\r
/** Returns a version of this rectangle with the given amount removed from its left-hand edge. */\r
- JUCE_NODISCARD Rectangle withTrimmedLeft (ValueType amountToRemove) const noexcept { return withLeft (pos.x + amountToRemove); }\r
+ [[nodiscard]] Rectangle withTrimmedLeft (ValueType amountToRemove) const noexcept { return withLeft (pos.x + amountToRemove); }\r
\r
/** Returns a version of this rectangle with the given amount removed from its right-hand edge. */\r
- JUCE_NODISCARD Rectangle withTrimmedRight (ValueType amountToRemove) const noexcept { return withWidth (w - amountToRemove); }\r
+ [[nodiscard]] Rectangle withTrimmedRight (ValueType amountToRemove) const noexcept { return withWidth (w - amountToRemove); }\r
\r
/** Returns a version of this rectangle with the given amount removed from its top edge. */\r
- JUCE_NODISCARD Rectangle withTrimmedTop (ValueType amountToRemove) const noexcept { return withTop (pos.y + amountToRemove); }\r
+ [[nodiscard]] Rectangle withTrimmedTop (ValueType amountToRemove) const noexcept { return withTop (pos.y + amountToRemove); }\r
\r
/** Returns a version of this rectangle with the given amount removed from its bottom edge. */\r
- JUCE_NODISCARD Rectangle withTrimmedBottom (ValueType amountToRemove) const noexcept { return withHeight (h - amountToRemove); }\r
+ [[nodiscard]] Rectangle withTrimmedBottom (ValueType amountToRemove) const noexcept { return withHeight (h - amountToRemove); }\r
\r
//==============================================================================\r
/** Moves the rectangle's position by adding amount to its x and y coordinates. */\r
*/\r
Rectangle transformedBy (const AffineTransform& transform) const noexcept\r
{\r
- using FloatType = typename TypeHelpers::SmallestFloatType<ValueType>::type;\r
+ using FloatType = TypeHelpers::SmallestFloatType<ValueType>;\r
\r
auto x1 = static_cast<FloatType> (pos.x), y1 = static_cast<FloatType> (pos.y);\r
auto x2 = static_cast<FloatType> (pos.x + w), y2 = static_cast<FloatType> (pos.y);\r
\r
ID: juce_graphics\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_events\r
OSXFrameworks: Cocoa QuartzCore\r
//==============================================================================\r
StringArray findAllFamilyNames() const\r
{\r
- StringArray s;\r
+ std::set<String> set;\r
\r
for (auto* face : faces)\r
- s.addIfNotAlreadyThere (face->family);\r
-\r
- return s;\r
- }\r
-\r
- static int indexOfRegularStyle (const StringArray& styles)\r
- {\r
- int i = styles.indexOf ("Regular", true);\r
+ set.insert (face->family);\r
\r
- if (i >= 0)\r
- return i;\r
+ StringArray s;\r
\r
- for (i = 0; i < styles.size(); ++i)\r
- if (! (styles[i].containsIgnoreCase ("Bold") || styles[i].containsIgnoreCase ("Italic")))\r
- return i;\r
+ for (const auto& family : set)\r
+ s.add (family);\r
\r
- return -1;\r
+ return s;\r
}\r
\r
StringArray findAllTypefaceStyles (const String& family) const\r
if (face->family == family)\r
s.addIfNotAlreadyThere (face->style);\r
\r
- // try to get a regular style to be first in the list\r
- auto regular = indexOfRegularStyle (s);\r
-\r
- if (regular > 0)\r
- s.strings.swap (0, regular);\r
-\r
+ // scanFontPaths ensures that regular styles are ordered before other styles\r
return s;\r
}\r
\r
for (auto& path : paths)\r
{\r
for (const auto& iter : RangedDirectoryIterator (File::getCurrentWorkingDirectory().getChildFile (path), true))\r
+ {\r
if (iter.getFile().hasFileExtension ("ttf;pfb;pcf;otf"))\r
scanFont (iter.getFile());\r
+ }\r
}\r
+\r
+ std::sort (faces.begin(), faces.end(), [] (const auto* a, const auto* b)\r
+ {\r
+ const auto tie = [] (const KnownTypeface& t)\r
+ {\r
+ // Used to order styles like "Regular", "Roman" etc. before "Bold", "Italic", etc.\r
+ const auto computeStyleNormalcy = [] (const String& style)\r
+ {\r
+ if (style == "Regular")\r
+ return 0;\r
+\r
+ if (style == "Roman")\r
+ return 1;\r
+\r
+ if (style == "Book")\r
+ return 2;\r
+\r
+ if (style.containsIgnoreCase ("Bold"))\r
+ return 3;\r
+\r
+ if (style.containsIgnoreCase ("Italic"))\r
+ return 4;\r
+\r
+ return 5;\r
+ };\r
+\r
+ return std::make_tuple (t.family,\r
+ computeStyleNormalcy (t.style),\r
+ t.style,\r
+ t.isSansSerif,\r
+ t.isMonospaced,\r
+ t.faceIndex,\r
+ t.file);\r
+ };\r
+\r
+ return tie (*a) < tie (*b);\r
+ });\r
}\r
\r
void getMonospacedNames (StringArray& monoSpaced) const\r
//==============================================================================\r
struct DefaultFontInfo\r
{\r
- struct Characteristics\r
- {\r
- explicit Characteristics (String nameIn) : name (nameIn) {}\r
-\r
- Characteristics withStyle (String styleIn) const\r
- {\r
- auto copy = *this;\r
- copy.style = std::move (styleIn);\r
- return copy;\r
- }\r
-\r
- String name, style;\r
- };\r
-\r
DefaultFontInfo()\r
- : defaultSans (getDefaultSansSerifFontCharacteristics()),\r
- defaultSerif (getDefaultSerifFontCharacteristics()),\r
- defaultFixed (getDefaultMonospacedFontCharacteristics())\r
+ : defaultSans (getDefaultSansSerifFontName()),\r
+ defaultSerif (getDefaultSerifFontName()),\r
+ defaultFixed (getDefaultMonospacedFontName())\r
{\r
}\r
\r
- Characteristics getRealFontCharacteristics (const String& faceName) const\r
+ String getRealFontName (const String& faceName) const\r
{\r
if (faceName == Font::getDefaultSansSerifFontName()) return defaultSans;\r
if (faceName == Font::getDefaultSerifFontName()) return defaultSerif;\r
if (faceName == Font::getDefaultMonospacedFontName()) return defaultFixed;\r
\r
- return Characteristics { faceName };\r
+ return faceName;\r
}\r
\r
- Characteristics defaultSans, defaultSerif, defaultFixed;\r
+ String defaultSans, defaultSerif, defaultFixed;\r
\r
private:\r
template <typename Range>\r
- static Characteristics pickBestFont (const StringArray& names, Range&& choicesArray)\r
+ static String pickBestFont (const StringArray& names, Range&& choicesArray)\r
{\r
for (auto& choice : choicesArray)\r
- if (names.contains (choice.name, true))\r
+ if (names.contains (choice, true))\r
return choice;\r
\r
for (auto& choice : choicesArray)\r
for (auto& name : names)\r
- if (name.startsWithIgnoreCase (choice.name))\r
- return Characteristics { name }.withStyle (choice.style);\r
+ if (name.startsWithIgnoreCase (choice))\r
+ return name;\r
\r
for (auto& choice : choicesArray)\r
for (auto& name : names)\r
- if (name.containsIgnoreCase (choice.name))\r
- return Characteristics { name }.withStyle (choice.style);\r
+ if (name.containsIgnoreCase (choice))\r
+ return name;\r
\r
- return Characteristics { names[0] };\r
+ return names[0];\r
}\r
\r
- static Characteristics getDefaultSansSerifFontCharacteristics()\r
+ static String getDefaultSansSerifFontName()\r
{\r
StringArray allFonts;\r
FTTypefaceList::getInstance()->getSansSerifNames (allFonts);\r
\r
- static const Characteristics targets[] { Characteristics { "Verdana" },\r
- Characteristics { "Bitstream Vera Sans" }.withStyle ("Roman"),\r
- Characteristics { "Luxi Sans" },\r
- Characteristics { "Liberation Sans" },\r
- Characteristics { "DejaVu Sans" },\r
- Characteristics { "Sans" } };\r
+ static constexpr const char* targets[] { "Verdana",\r
+ "Bitstream Vera Sans",\r
+ "Luxi Sans",\r
+ "Liberation Sans",\r
+ "DejaVu Sans",\r
+ "Sans" };\r
return pickBestFont (allFonts, targets);\r
}\r
\r
- static Characteristics getDefaultSerifFontCharacteristics()\r
+ static String getDefaultSerifFontName()\r
{\r
StringArray allFonts;\r
FTTypefaceList::getInstance()->getSerifNames (allFonts);\r
\r
- static const Characteristics targets[] { Characteristics { "Bitstream Vera Serif" }.withStyle ("Roman"),\r
- Characteristics { "Times" },\r
- Characteristics { "Nimbus Roman" },\r
- Characteristics { "Liberation Serif" },\r
- Characteristics { "DejaVu Serif" },\r
- Characteristics { "Serif" } };\r
+ static constexpr const char* targets[] { "Bitstream Vera Serif",\r
+ "Times",\r
+ "Nimbus Roman",\r
+ "Liberation Serif",\r
+ "DejaVu Serif",\r
+ "Serif" };\r
return pickBestFont (allFonts, targets);\r
}\r
\r
- static Characteristics getDefaultMonospacedFontCharacteristics()\r
+ static String getDefaultMonospacedFontName()\r
{\r
StringArray allFonts;\r
FTTypefaceList::getInstance()->getMonospacedNames (allFonts);\r
\r
- static const Characteristics targets[] { Characteristics { "DejaVu Sans Mono" },\r
- Characteristics { "Bitstream Vera Sans Mono" }.withStyle ("Roman"),\r
- Characteristics { "Sans Mono" },\r
- Characteristics { "Liberation Mono" },\r
- Characteristics { "Courier" },\r
- Characteristics { "DejaVu Mono" },\r
- Characteristics { "Mono" } };\r
+ static constexpr const char* targets[] { "DejaVu Sans Mono",\r
+ "Bitstream Vera Sans Mono",\r
+ "Sans Mono",\r
+ "Liberation Mono",\r
+ "Courier",\r
+ "DejaVu Mono",\r
+ "Mono" };\r
return pickBestFont (allFonts, targets);\r
}\r
\r
Font f (font);\r
\r
const auto name = font.getTypefaceName();\r
- const auto characteristics = defaultInfo.getRealFontCharacteristics (name);\r
- f.setTypefaceName (characteristics.name);\r
+ const auto realName = defaultInfo.getRealFontName (name);\r
+ f.setTypefaceName (realName);\r
\r
- const auto styles = findAllTypefaceStyles (name);\r
+ const auto styles = findAllTypefaceStyles (realName);\r
\r
if (! styles.contains (font.getTypefaceStyle()))\r
- f.setTypefaceStyle (characteristics.style);\r
+ f.setTypefaceStyle (styles[0]);\r
\r
return Typeface::createSystemTypefaceFor (f);\r
}\r
void operator() (CGGradientRef ptr) const noexcept { CGGradientRelease (ptr); }\r
};\r
\r
+ struct ColorDelete\r
+ {\r
+ void operator() (CGColorRef ptr) const noexcept { CGColorRelease (ptr); }\r
+ };\r
+\r
//==============================================================================\r
using ColorSpacePtr = std::unique_ptr<CGColorSpace, ColorSpaceDelete>;\r
using ContextPtr = std::unique_ptr<CGContext, ContextDelete>;\r
using DataProviderPtr = std::unique_ptr<CGDataProvider, DataProviderDelete>;\r
using ImagePtr = std::unique_ptr<CGImage, ImageDelete>;\r
using GradientPtr = std::unique_ptr<CGGradient, GradientDelete>;\r
+ using ColorPtr = std::unique_ptr<CGColor, ColorDelete>;\r
}\r
\r
//==============================================================================\r
void setInterpolationQuality (Graphics::ResamplingQuality) override;\r
\r
//==============================================================================\r
+ void fillAll() override;\r
void fillRect (const Rectangle<int>&, bool replaceExistingContents) override;\r
void fillRect (const Rectangle<float>&) override;\r
void fillRectList (const RectangleList<float>&) override;\r
\r
if (fillType.isColour())\r
{\r
- CGContextSetRGBFillColor (context.get(), fillType.colour.getFloatRed(), fillType.colour.getFloatGreen(),\r
- fillType.colour.getFloatBlue(), fillType.colour.getFloatAlpha());\r
+ const CGFloat components[] { fillType.colour.getFloatRed(),\r
+ fillType.colour.getFloatGreen(),\r
+ fillType.colour.getFloatBlue(),\r
+ fillType.colour.getFloatAlpha() };\r
+\r
+ const detail::ColorPtr color { CGColorCreate (rgbColourSpace.get(), components) };\r
+ CGContextSetFillColorWithColor (context.get(), color.get());\r
CGContextSetAlpha (context.get(), 1.0f);\r
}\r
}\r
}\r
\r
//==============================================================================\r
+void CoreGraphicsContext::fillAll()\r
+{\r
+ // The clip rectangle is expanded in order to avoid having alpha blended pixels at the edges.\r
+ // The clipping mechanism will take care of cutting off pixels beyond the clip bounds. This is\r
+ // a hard cutoff and will ensure that no semi-transparent pixels will remain inside the filled\r
+ // area.\r
+ const auto clipBounds = getClipBounds();\r
+\r
+ const auto clipBoundsOnDevice = CGContextConvertSizeToDeviceSpace (context.get(),\r
+ CGSize { (CGFloat) clipBounds.getWidth(),\r
+ (CGFloat) clipBounds.getHeight() });\r
+\r
+ const auto inverseScale = clipBoundsOnDevice.width > (CGFloat) 0.0\r
+ ? (int) (clipBounds.getWidth() / clipBoundsOnDevice.width)\r
+ : 0;\r
+ const auto expansion = jmax (1, inverseScale);\r
+\r
+ fillRect (clipBounds.expanded (expansion), false);\r
+}\r
+\r
void CoreGraphicsContext::fillRect (const Rectangle<int>& r, bool replaceExistingContents)\r
{\r
fillCGRect (CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()), replaceExistingContents);\r
\r
@see isCheckable\r
*/\r
- JUCE_NODISCARD AccessibleState withCheckable() const noexcept { return withFlag (Flags::checkable); }\r
+ [[nodiscard]] AccessibleState withCheckable() const noexcept { return withFlag (Flags::checkable); }\r
\r
/** Sets the checked flag and returns the new state.\r
\r
@see isChecked\r
*/\r
- JUCE_NODISCARD AccessibleState withChecked() const noexcept { return withFlag (Flags::checked); }\r
+ [[nodiscard]] AccessibleState withChecked() const noexcept { return withFlag (Flags::checked); }\r
\r
/** Sets the collapsed flag and returns the new state.\r
\r
@see isCollapsed\r
*/\r
- JUCE_NODISCARD AccessibleState withCollapsed() const noexcept { return withFlag (Flags::collapsed); }\r
+ [[nodiscard]] AccessibleState withCollapsed() const noexcept { return withFlag (Flags::collapsed); }\r
\r
/** Sets the expandable flag and returns the new state.\r
\r
@see isExpandable\r
*/\r
- JUCE_NODISCARD AccessibleState withExpandable() const noexcept { return withFlag (Flags::expandable); }\r
+ [[nodiscard]] AccessibleState withExpandable() const noexcept { return withFlag (Flags::expandable); }\r
\r
/** Sets the expanded flag and returns the new state.\r
\r
@see isExpanded\r
*/\r
- JUCE_NODISCARD AccessibleState withExpanded() const noexcept { return withFlag (Flags::expanded); }\r
+ [[nodiscard]] AccessibleState withExpanded() const noexcept { return withFlag (Flags::expanded); }\r
\r
/** Sets the focusable flag and returns the new state.\r
\r
@see isFocusable\r
*/\r
- JUCE_NODISCARD AccessibleState withFocusable() const noexcept { return withFlag (Flags::focusable); }\r
+ [[nodiscard]] AccessibleState withFocusable() const noexcept { return withFlag (Flags::focusable); }\r
\r
/** Sets the focused flag and returns the new state.\r
\r
@see isFocused\r
*/\r
- JUCE_NODISCARD AccessibleState withFocused() const noexcept { return withFlag (Flags::focused); }\r
+ [[nodiscard]] AccessibleState withFocused() const noexcept { return withFlag (Flags::focused); }\r
\r
/** Sets the ignored flag and returns the new state.\r
\r
@see isIgnored\r
*/\r
- JUCE_NODISCARD AccessibleState withIgnored() const noexcept { return withFlag (Flags::ignored); }\r
+ [[nodiscard]] AccessibleState withIgnored() const noexcept { return withFlag (Flags::ignored); }\r
\r
/** Sets the selectable flag and returns the new state.\r
\r
@see isSelectable\r
*/\r
- JUCE_NODISCARD AccessibleState withSelectable() const noexcept { return withFlag (Flags::selectable); }\r
+ [[nodiscard]] AccessibleState withSelectable() const noexcept { return withFlag (Flags::selectable); }\r
\r
/** Sets the multiSelectable flag and returns the new state.\r
\r
@see isMultiSelectable\r
*/\r
- JUCE_NODISCARD AccessibleState withMultiSelectable() const noexcept { return withFlag (Flags::multiSelectable); }\r
+ [[nodiscard]] AccessibleState withMultiSelectable() const noexcept { return withFlag (Flags::multiSelectable); }\r
\r
/** Sets the selected flag and returns the new state.\r
\r
@see isSelected\r
*/\r
- JUCE_NODISCARD AccessibleState withSelected() const noexcept { return withFlag (Flags::selected); }\r
+ [[nodiscard]] AccessibleState withSelected() const noexcept { return withFlag (Flags::selected); }\r
\r
/** Sets the accessible offscreen flag and returns the new state.\r
\r
@see isSelected\r
*/\r
- JUCE_NODISCARD AccessibleState withAccessibleOffscreen() const noexcept { return withFlag (Flags::accessibleOffscreen); }\r
+ [[nodiscard]] AccessibleState withAccessibleOffscreen() const noexcept { return withFlag (Flags::accessibleOffscreen); }\r
\r
//==============================================================================\r
/** Returns true if the UI element is checkable.\r
accessibleOffscreen = (1 << 11)\r
};\r
\r
- JUCE_NODISCARD AccessibleState withFlag (int flag) const noexcept\r
+ [[nodiscard]] AccessibleState withFlag (int flag) const noexcept\r
{\r
auto copy = *this;\r
copy.flags |= flag;\r
\r
Component* Component::currentlyFocusedComponent = nullptr;\r
\r
+//==============================================================================\r
+class HierarchyChecker\r
+{\r
+public:\r
+ HierarchyChecker (Component* comp, const MouseEvent& originalEvent)\r
+ : me (originalEvent)\r
+ {\r
+ for (; comp != nullptr; comp = comp->getParentComponent())\r
+ hierarchy.emplace_back (comp);\r
+ }\r
+\r
+ Component* nearestNonNullParent() const\r
+ {\r
+ for (auto& comp : hierarchy)\r
+ if (comp != nullptr)\r
+ return comp;\r
+\r
+ return nullptr;\r
+ }\r
+\r
+ bool shouldBailOut() const\r
+ {\r
+ return nearestNonNullParent() == nullptr;\r
+ }\r
+\r
+ MouseEvent eventWithNearestParent() const\r
+ {\r
+ auto* comp = nearestNonNullParent();\r
+ return { me.source,\r
+ me.position.toFloat(),\r
+ me.mods,\r
+ me.pressure, me.orientation, me.rotation,\r
+ me.tiltX, me.tiltY,\r
+ comp, comp,\r
+ me.eventTime,\r
+ me.mouseDownPosition.toFloat(),\r
+ me.mouseDownTime,\r
+ me.getNumberOfClicks(),\r
+ me.mouseWasDraggedSinceMouseDown() };\r
+ }\r
+\r
+private:\r
+ std::vector<Component::SafePointer<Component>> hierarchy;\r
+ const MouseEvent me;\r
+};\r
\r
//==============================================================================\r
class Component::MouseListenerList\r
}\r
}\r
\r
- // g++ 4.8 cannot deduce the parameter pack inside the function pointer when it has more than one element\r
- #if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)\r
- template <typename... Params>\r
- static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
- void (MouseListener::*eventMethod) (const MouseEvent&),\r
- Params... params)\r
- {\r
- sendMouseEvent <decltype (eventMethod), Params...> (comp, checker, eventMethod, params...);\r
- }\r
-\r
- template <typename... Params>\r
- static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
- void (MouseListener::*eventMethod) (const MouseEvent&, const MouseWheelDetails&),\r
- Params... params)\r
- {\r
- sendMouseEvent <decltype (eventMethod), Params...> (comp, checker, eventMethod, params...);\r
- }\r
-\r
- template <typename... Params>\r
- static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
- void (MouseListener::*eventMethod) (const MouseEvent&, float),\r
- Params... params)\r
- {\r
- sendMouseEvent <decltype (eventMethod), Params...> (comp, checker, eventMethod, params...);\r
- }\r
-\r
template <typename EventMethod, typename... Params>\r
- static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
- EventMethod eventMethod,\r
- Params... params)\r
- #else\r
- template <typename... Params>\r
- static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
- void (MouseListener::*eventMethod) (Params...),\r
- Params... params)\r
- #endif\r
+ static void sendMouseEvent (HierarchyChecker& checker, EventMethod&& eventMethod, Params&&... params)\r
{\r
- if (checker.shouldBailOut())\r
+ auto* parent = checker.nearestNonNullParent();\r
+\r
+ if (parent == nullptr)\r
return;\r
\r
- if (auto* list = comp.mouseListeners.get())\r
+ if (auto* list = parent->mouseListeners.get())\r
{\r
for (int i = list->listeners.size(); --i >= 0;)\r
{\r
- (list->listeners.getUnchecked(i)->*eventMethod) (params...);\r
+ (list->listeners.getUnchecked (i)->*eventMethod) (checker.eventWithNearestParent(), params...);\r
\r
if (checker.shouldBailOut())\r
return;\r
}\r
}\r
\r
- for (Component* p = comp.parentComponent; p != nullptr; p = p->parentComponent)\r
+ for (Component* p = checker.nearestNonNullParent()->parentComponent; p != nullptr; p = p->parentComponent)\r
{\r
if (auto* list = p->mouseListeners.get())\r
{\r
if (list->numDeepMouseListeners > 0)\r
{\r
- BailOutChecker2 checker2 (checker, p);\r
+ const auto shouldBailOut = [&checker, safePointer = WeakReference { p }]\r
+ {\r
+ return checker.shouldBailOut() || safePointer == nullptr;\r
+ };\r
\r
for (int i = list->numDeepMouseListeners; --i >= 0;)\r
{\r
- (list->listeners.getUnchecked(i)->*eventMethod) (params...);\r
+ (list->listeners.getUnchecked(i)->*eventMethod) (checker.eventWithNearestParent(), params...);\r
\r
- if (checker2.shouldBailOut())\r
+ if (shouldBailOut())\r
return;\r
\r
i = jmin (i, list->numDeepMouseListeners);\r
Array<MouseListener*> listeners;\r
int numDeepMouseListeners = 0;\r
\r
- struct BailOutChecker2\r
- {\r
- BailOutChecker2 (Component::BailOutChecker& boc, Component* comp)\r
- : checker (boc), safePointer (comp)\r
- {\r
- }\r
-\r
- bool shouldBailOut() const noexcept\r
- {\r
- return checker.shouldBailOut() || safePointer == nullptr;\r
- }\r
-\r
- private:\r
- Component::BailOutChecker& checker;\r
- const WeakReference<Component> safePointer;\r
-\r
- JUCE_DECLARE_NON_COPYABLE (BailOutChecker2)\r
- };\r
-\r
JUCE_DECLARE_NON_COPYABLE (MouseListenerList)\r
};\r
\r
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.\r
JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED\r
\r
+ SafePointer safeReference { this };\r
+\r
if (! isCurrentlyModal (false))\r
{\r
// While this component is in modal state it may block other components from receiving\r
// we must manually force the mouse to "leave" blocked components.\r
ComponentHelpers::sendMouseEventToComponentsThatAreBlockedByModal (*this, &Component::internalMouseExit);\r
\r
+ if (safeReference == nullptr)\r
+ {\r
+ // If you hit this assertion, the mouse-exit event above has caused the modal component to be deleted.\r
+ jassertfalse;\r
+ return;\r
+ }\r
+\r
auto& mcm = *ModalComponentManager::getInstance();\r
mcm.startModal (this, deleteWhenDismissed);\r
mcm.attachCallback (this, callback);\r
if (flags.repaintOnMouseActivityFlag)\r
repaint();\r
\r
- BailOutChecker checker (this);\r
-\r
const auto me = makeMouseEvent (source,\r
PointerState().withPosition (relativePos),\r
source.getCurrentModifiers(),\r
time,\r
0,\r
false);\r
+\r
+ HierarchyChecker checker (this, me);\r
mouseEnter (me);\r
\r
flags.cachedMouseInsideComponent = true;\r
return;\r
\r
Desktop::getInstance().getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseEnter (me); });\r
-\r
- MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseEnter, me);\r
+ MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseEnter);\r
}\r
\r
void Component::internalMouseExit (MouseInputSource source, Point<float> relativePos, Time time)\r
\r
flags.cachedMouseInsideComponent = false;\r
\r
- BailOutChecker checker (this);\r
-\r
const auto me = makeMouseEvent (source,\r
PointerState().withPosition (relativePos),\r
source.getCurrentModifiers(),\r
0,\r
false);\r
\r
+ HierarchyChecker checker (this, me);\r
mouseExit (me);\r
\r
if (checker.shouldBailOut())\r
return;\r
\r
Desktop::getInstance().getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseExit (me); });\r
-\r
- MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseExit, me);\r
+ MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseExit);\r
}\r
\r
void Component::internalMouseDown (MouseInputSource source, const PointerState& relativePointerState, Time time)\r
{\r
auto& desktop = Desktop::getInstance();\r
- BailOutChecker checker (this);\r
+\r
+ const auto me = makeMouseEvent (source,\r
+ relativePointerState,\r
+ source.getCurrentModifiers(),\r
+ this,\r
+ this,\r
+ time,\r
+ relativePointerState.position,\r
+ time,\r
+ source.getNumberOfMultipleClicks(),\r
+ false);\r
+\r
+ HierarchyChecker checker (this, me);\r
\r
if (isCurrentlyBlockedByAnotherModalComponent())\r
{\r
if (isCurrentlyBlockedByAnotherModalComponent())\r
{\r
// allow blocked mouse-events to go to global listeners..\r
- const auto me = makeMouseEvent (source,\r
- relativePointerState,\r
- source.getCurrentModifiers(),\r
- this,\r
- this,\r
- time,\r
- relativePointerState.position,\r
- time,\r
- source.getNumberOfMultipleClicks(),\r
- false);\r
-\r
- desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDown (me); });\r
+ desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDown (checker.eventWithNearestParent()); });\r
return;\r
}\r
}\r
if (flags.repaintOnMouseActivityFlag)\r
repaint();\r
\r
- const auto me = makeMouseEvent (source,\r
- relativePointerState,\r
- source.getCurrentModifiers(),\r
- this,\r
- this,\r
- time,\r
- relativePointerState.position,\r
- time,\r
- source.getNumberOfMultipleClicks(),\r
- false);\r
mouseDown (me);\r
\r
if (checker.shouldBailOut())\r
return;\r
\r
- desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDown (me); });\r
+ desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDown (checker.eventWithNearestParent()); });\r
\r
- MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseDown, me);\r
+ MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseDown);\r
}\r
\r
void Component::internalMouseUp (MouseInputSource source, const PointerState& relativePointerState, Time time, const ModifierKeys oldModifiers)\r
if (flags.mouseDownWasBlocked && isCurrentlyBlockedByAnotherModalComponent())\r
return;\r
\r
- BailOutChecker checker (this);\r
-\r
- if (flags.repaintOnMouseActivityFlag)\r
- repaint();\r
-\r
const auto me = makeMouseEvent (source,\r
relativePointerState,\r
oldModifiers,\r
source.getLastMouseDownTime(),\r
source.getNumberOfMultipleClicks(),\r
source.isLongPressOrDrag());\r
+\r
+ HierarchyChecker checker (this, me);\r
+\r
+ if (flags.repaintOnMouseActivityFlag)\r
+ repaint();\r
+\r
mouseUp (me);\r
\r
if (checker.shouldBailOut())\r
return;\r
\r
auto& desktop = Desktop::getInstance();\r
- desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseUp (me); });\r
+ desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseUp (checker.eventWithNearestParent()); });\r
\r
- MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseUp, me);\r
+ MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseUp);\r
\r
if (checker.shouldBailOut())\r
return;\r
// check for double-click\r
if (me.getNumberOfClicks() >= 2)\r
{\r
- mouseDoubleClick (me);\r
+ mouseDoubleClick (checker.eventWithNearestParent());\r
\r
if (checker.shouldBailOut())\r
return;\r
\r
- desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseDoubleClick (me); });\r
- MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseDoubleClick, me);\r
+ desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseDoubleClick (checker.eventWithNearestParent()); });\r
+ MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseDoubleClick);\r
}\r
}\r
\r
{\r
if (! isCurrentlyBlockedByAnotherModalComponent())\r
{\r
- BailOutChecker checker (this);\r
-\r
const auto me = makeMouseEvent (source,\r
relativePointerState,\r
source.getCurrentModifiers(),\r
source.getLastMouseDownTime(),\r
source.getNumberOfMultipleClicks(),\r
source.isLongPressOrDrag());\r
+\r
+ HierarchyChecker checker (this, me);\r
+\r
mouseDrag (me);\r
\r
if (checker.shouldBailOut())\r
return;\r
\r
- Desktop::getInstance().getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDrag (me); });\r
-\r
- MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseDrag, me);\r
+ Desktop::getInstance().getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDrag (checker.eventWithNearestParent()); });\r
+ MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseDrag);\r
}\r
}\r
\r
}\r
else\r
{\r
- BailOutChecker checker (this);\r
-\r
const auto me = makeMouseEvent (source,\r
PointerState().withPosition (relativePos),\r
source.getCurrentModifiers(),\r
time,\r
0,\r
false);\r
+\r
+ HierarchyChecker checker (this, me);\r
+\r
mouseMove (me);\r
\r
if (checker.shouldBailOut())\r
return;\r
\r
- desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseMove (me); });\r
-\r
- MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseMove, me);\r
+ desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseMove (checker.eventWithNearestParent()); });\r
+ MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseMove);\r
}\r
}\r
\r
Time time, const MouseWheelDetails& wheel)\r
{\r
auto& desktop = Desktop::getInstance();\r
- BailOutChecker checker (this);\r
\r
const auto me = makeMouseEvent (source,\r
PointerState().withPosition (relativePos),\r
0,\r
false);\r
\r
+ HierarchyChecker checker (this, me);\r
+\r
if (isCurrentlyBlockedByAnotherModalComponent())\r
{\r
// allow blocked mouse-events to go to global listeners..\r
if (checker.shouldBailOut())\r
return;\r
\r
- desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseWheelMove (me, wheel); });\r
+ desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseWheelMove (checker.eventWithNearestParent(), wheel); });\r
\r
if (! checker.shouldBailOut())\r
- MouseListenerList::template sendMouseEvent<const MouseEvent&, const MouseWheelDetails&> (*this, checker, &MouseListener::mouseWheelMove, me, wheel);\r
+ MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseWheelMove, wheel);\r
}\r
}\r
\r
Time time, float amount)\r
{\r
auto& desktop = Desktop::getInstance();\r
- BailOutChecker checker (this);\r
\r
const auto me = makeMouseEvent (source,\r
PointerState().withPosition (relativePos),\r
0,\r
false);\r
\r
+ HierarchyChecker checker (this, me);\r
+\r
if (isCurrentlyBlockedByAnotherModalComponent())\r
{\r
// allow blocked mouse-events to go to global listeners..\r
if (checker.shouldBailOut())\r
return;\r
\r
- desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseMagnify (me, amount); });\r
+ desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseMagnify (checker.eventWithNearestParent(), amount); });\r
\r
if (! checker.shouldBailOut())\r
- MouseListenerList::template sendMouseEvent<const MouseEvent&, float> (*this, checker, &MouseListener::mouseMagnify, me, amount);\r
+ MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseMagnify, amount);\r
}\r
}\r
\r
pixels per inch, divide this by the Display::scale value.\r
*/\r
double dpi;\r
+\r
+ /** The vertical refresh rate of the display if applicable.\r
+\r
+ Currently this is only used on Linux for display rate repainting.\r
+ */\r
+ std::optional<double> verticalFrequencyHz;\r
};\r
\r
//==============================================================================\r
{\r
\r
DirectoryContentsList::DirectoryContentsList (const FileFilter* f, TimeSliceThread& t)\r
- : fileFilter (f), thread (t)\r
+ : fileFilter (f), thread (t)\r
{\r
}\r
\r
\r
bool DirectoryContentsList::checkNextFile (bool& hasChanged)\r
{\r
- if (fileFindHandle != nullptr)\r
- {\r
- if (*fileFindHandle != RangedDirectoryIterator())\r
- {\r
- const auto entry = *(*fileFindHandle)++;\r
-\r
- if (addFile (entry.getFile(),\r
- entry.isDirectory(),\r
- entry.getFileSize(),\r
- entry.getModificationTime(),\r
- entry.getCreationTime(),\r
- entry.isReadOnly()))\r
- {\r
- hasChanged = true;\r
- }\r
-\r
- return true;\r
- }\r
+ if (fileFindHandle == nullptr)\r
+ return false;\r
\r
+ if (*fileFindHandle == RangedDirectoryIterator())\r
+ {\r
fileFindHandle = nullptr;\r
isSearching = false;\r
-\r
- if (! wasEmpty && files.isEmpty())\r
- hasChanged = true;\r
+ hasChanged = true;\r
+ return false;\r
}\r
\r
- return false;\r
+ const auto entry = *(*fileFindHandle)++;\r
+\r
+ hasChanged |= addFile (entry.getFile(),\r
+ entry.isDirectory(),\r
+ entry.getFileSize(),\r
+ entry.getModificationTime(),\r
+ entry.getCreationTime(),\r
+ entry.isReadOnly());\r
+\r
+ return true;\r
}\r
\r
bool DirectoryContentsList::addFile (const File& file, const bool isDir,\r
filename = initialFileOrDirectory.getFileName();\r
}\r
\r
+ // The thread must be started before the DirectoryContentsList attempts to scan any file\r
+ thread.startThread (Thread::Priority::low);\r
+\r
fileList.reset (new DirectoryContentsList (this, thread));\r
fileList->setDirectory (currentRoot, true, true);\r
\r
if (filename.isNotEmpty())\r
setFileName (filename);\r
\r
- thread.startThread (4);\r
-\r
startTimer (2000);\r
}\r
\r
callback (*this);\r
}\r
\r
+#if ! JUCE_ANDROID\r
+void FileChooser::registerCustomMimeTypeForFileExtension ([[maybe_unused]] const String& mimeType,\r
+ [[maybe_unused]] const String& fileExtension)\r
+{\r
+}\r
+#endif\r
+\r
//==============================================================================\r
FilePreviewComponent::FilePreviewComponent() {}\r
FilePreviewComponent::~FilePreviewComponent() {}\r
*/\r
static bool isPlatformDialogAvailable();\r
\r
+ /** Associate a particular file-extension to a mime-type\r
+\r
+ On Android, JUCE needs to convert common file extensions to mime-types when using\r
+ wildcard filters in native file chooser dialog boxes. JUCE has an extensive conversion\r
+ table to convert between the most common file-types and mime-types transparently, but\r
+ some more obscure file-types may be missing. Use this method to register your own\r
+ mime-type to file extension conversions. Please contact the JUCE team if you think\r
+ that a common mime-type/file-extension entry is missing in JUCE's internal tables.\r
+ Does nothing on other platforms.\r
+ */\r
+ static void registerCustomMimeTypeForFileExtension (const String& mimeType,\r
+ const String& fileExtension);\r
+\r
//==============================================================================\r
#ifndef DOXYGEN\r
class Native;\r
dialogBox->centreWithDefaultSize (nullptr);\r
dialogBox->enterModalState (true,\r
ModalCallbackFunction::create (onFileSelected),\r
- true);\r
+ false);\r
}\r
@endcode\r
\r
\r
//==============================================================================\r
FileListComponent::FileListComponent (DirectoryContentsList& listToShow)\r
- : ListBox ({}, nullptr),\r
+ : ListBox ({}, this),\r
DirectoryContentsDisplayComponent (listToShow),\r
lastDirectory (listToShow.getDirectory())\r
{\r
setTitle ("Files");\r
- setModel (this);\r
directoryContentsList.addChangeListener (this);\r
}\r
\r
\r
void FileListComponent::setSelectedFile (const File& f)\r
{\r
- for (int i = directoryContentsList.getNumFiles(); --i >= 0;)\r
+ if (! directoryContentsList.isStillLoading())\r
{\r
- if (directoryContentsList.getFile (i) == f)\r
+ for (int i = directoryContentsList.getNumFiles(); --i >= 0;)\r
{\r
- fileWaitingToBeSelected = File();\r
+ if (directoryContentsList.getFile (i) == f)\r
+ {\r
+ fileWaitingToBeSelected = File();\r
\r
- selectRow (i);\r
- return;\r
+ updateContent();\r
+ selectRow (i);\r
+ return;\r
+ }\r
}\r
}\r
\r
\r
@tags{GUI}\r
*/\r
-class JUCE_API FileListComponent : public ListBox,\r
+class JUCE_API FileListComponent : private ListBoxModel,\r
+ public ListBox,\r
public DirectoryContentsDisplayComponent,\r
- private ListBoxModel,\r
private ChangeListener\r
{\r
public:\r
newList->addChangeListener (this);\r
}\r
\r
- bool selectFile (const File& target)\r
+ void selectFile (const File& target)\r
{\r
if (file == target)\r
{\r
setSelected (true, true);\r
- return true;\r
+ return;\r
}\r
\r
- if (target.isAChildOf (file))\r
+ if (subContentsList != nullptr && subContentsList->isStillLoading())\r
{\r
- setOpen (true);\r
+ pendingFileSelection.emplace (*this, target);\r
+ return;\r
+ }\r
\r
- for (int maxRetries = 500; --maxRetries > 0;)\r
- {\r
- for (int i = 0; i < getNumSubItems(); ++i)\r
- if (auto* f = dynamic_cast<FileListTreeItem*> (getSubItem (i)))\r
- if (f->selectFile (target))\r
- return true;\r
+ pendingFileSelection.reset();\r
\r
- // if we've just opened and the contents are still loading, wait for it..\r
- if (subContentsList != nullptr && subContentsList->isStillLoading())\r
- {\r
- Thread::sleep (10);\r
- rebuildItemsFromContentList();\r
- }\r
- else\r
- {\r
- break;\r
- }\r
- }\r
- }\r
+ if (! target.isAChildOf (file))\r
+ return;\r
\r
- return false;\r
+ setOpen (true);\r
+\r
+ for (int i = 0; i < getNumSubItems(); ++i)\r
+ if (auto* f = dynamic_cast<FileListTreeItem*> (getSubItem (i)))\r
+ f->selectFile (target);\r
}\r
\r
void changeListenerCallback (ChangeBroadcaster*) override\r
const File file;\r
\r
private:\r
+ class PendingFileSelection : private Timer\r
+ {\r
+ public:\r
+ PendingFileSelection (FileListTreeItem& item, const File& f)\r
+ : owner (item), fileToSelect (f)\r
+ {\r
+ startTimer (10);\r
+ }\r
+\r
+ ~PendingFileSelection() override\r
+ {\r
+ stopTimer();\r
+ }\r
+\r
+ private:\r
+ void timerCallback() override\r
+ {\r
+ // Take a copy of the file here, in case this PendingFileSelection\r
+ // object is destroyed during the call to selectFile.\r
+ owner.selectFile (File { fileToSelect });\r
+ }\r
+\r
+ FileListTreeItem& owner;\r
+ File fileToSelect;\r
+ };\r
+\r
+ Optional<PendingFileSelection> pendingFileSelection;\r
FileTreeComponent& owner;\r
DirectoryContentsList* parentContentsList;\r
int indexInContentsList;\r
void FileTreeComponent::setSelectedFile (const File& target)\r
{\r
if (auto* t = dynamic_cast<FileListTreeItem*> (getRootItem()))\r
- if (! t->selectFile (target))\r
- clearSelectedItems();\r
+ t->selectFile (target);\r
}\r
\r
void FileTreeComponent::setItemHeight (int newHeight)\r
#include <vfw.h>\r
#include <commdlg.h>\r
#include <commctrl.h>\r
- #include <UIAutomation.h>\r
#include <sapi.h>\r
- #include <Dxgi.h>\r
+ #include <dxgi.h>\r
+\r
+ #if JUCE_MINGW\r
+ // Some MinGW headers use 'new' as a parameter name\r
+ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wkeyword-macro")\r
+ #define new new_\r
+ JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+ #endif\r
+\r
+ #include <uiautomation.h>\r
+\r
+ #undef new\r
\r
#if JUCE_WEB_BROWSER\r
#include <exdisp.h>\r
#include "windows/juce_ThreadWithProgressWindow.cpp"\r
#include "windows/juce_TooltipWindow.cpp"\r
#include "windows/juce_TopLevelWindow.cpp"\r
+#include "windows/juce_VBlankAttachement.cpp"\r
#include "commands/juce_ApplicationCommandInfo.cpp"\r
#include "commands/juce_ApplicationCommandManager.cpp"\r
#include "commands/juce_ApplicationCommandTarget.cpp"\r
\r
#else\r
#include "native/accessibility/juce_mac_Accessibility.mm"\r
+ #include "native/juce_mac_PerScreenDisplayLinks.h"\r
#include "native/juce_mac_NSViewComponentPeer.mm"\r
#include "native/juce_mac_Windowing.mm"\r
#include "native/juce_mac_MainMenu.mm"\r
\r
ID: juce_gui_basics\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_graphics juce_data_structures\r
OSXFrameworks: Cocoa QuartzCore\r
#include "windows/juce_NativeMessageBox.h"\r
#include "windows/juce_ThreadWithProgressWindow.h"\r
#include "windows/juce_TooltipWindow.h"\r
+#include "windows/juce_VBlankAttachement.h"\r
#include "layout/juce_MultiDocumentPanel.h"\r
#include "layout/juce_SidePanel.h"\r
#include "filebrowser/juce_FileBrowserListener.h"\r
Receives callbacks when keys are pressed.\r
\r
You can add a key listener to a component to be informed when that component\r
- gets key events. See the Component::addListener method for more details.\r
+ gets key events. See the Component::addKeyListener method for more details.\r
\r
@see KeyPress, Component::addKeyListener, KeyPressMappingSet\r
\r
\r
//==============================================================================\r
/** Returns a copy of only the mouse-button flags */\r
- JUCE_NODISCARD ModifierKeys withOnlyMouseButtons() const noexcept { return ModifierKeys (flags & allMouseButtonModifiers); }\r
+ [[nodiscard]] ModifierKeys withOnlyMouseButtons() const noexcept { return ModifierKeys (flags & allMouseButtonModifiers); }\r
\r
/** Returns a copy of only the non-mouse flags */\r
- JUCE_NODISCARD ModifierKeys withoutMouseButtons() const noexcept { return ModifierKeys (flags & ~allMouseButtonModifiers); }\r
+ [[nodiscard]] ModifierKeys withoutMouseButtons() const noexcept { return ModifierKeys (flags & ~allMouseButtonModifiers); }\r
\r
bool operator== (const ModifierKeys other) const noexcept { return flags == other.flags; }\r
bool operator!= (const ModifierKeys other) const noexcept { return flags != other.flags; }\r
/** Returns the raw flags for direct testing. */\r
inline int getRawFlags() const noexcept { return flags; }\r
\r
- JUCE_NODISCARD ModifierKeys withoutFlags (int rawFlagsToClear) const noexcept { return ModifierKeys (flags & ~rawFlagsToClear); }\r
- JUCE_NODISCARD ModifierKeys withFlags (int rawFlagsToSet) const noexcept { return ModifierKeys (flags | rawFlagsToSet); }\r
+ [[nodiscard]] ModifierKeys withoutFlags (int rawFlagsToClear) const noexcept { return ModifierKeys (flags & ~rawFlagsToClear); }\r
+ [[nodiscard]] ModifierKeys withFlags (int rawFlagsToSet) const noexcept { return ModifierKeys (flags | rawFlagsToSet); }\r
\r
/** Tests a combination of flags and returns true if any of them are set. */\r
bool testFlags (int flagsToTest) const noexcept { return (flags & flagsToTest) != 0; }\r
+ targetArea.toFloat().getPosition();\r
\r
if (auto* c = item->associatedComponent)\r
- c->setBounds (item->currentBounds.toNearestIntEdges());\r
+ c->setBounds (item->currentBounds.getSmallestIntegerContainer());\r
}\r
}\r
\r
\r
@see withTargetComponent, withTargetScreenArea\r
*/\r
- JUCE_NODISCARD Options withTargetComponent (Component* targetComponent) const;\r
- JUCE_NODISCARD Options withTargetComponent (Component& targetComponent) const;\r
+ [[nodiscard]] Options withTargetComponent (Component* targetComponent) const;\r
+ [[nodiscard]] Options withTargetComponent (Component& targetComponent) const;\r
\r
/** Sets the region of the screen next to which the menu should be displayed.\r
\r
\r
@see withMousePosition\r
*/\r
- JUCE_NODISCARD Options withTargetScreenArea (Rectangle<int> targetArea) const;\r
+ [[nodiscard]] Options withTargetScreenArea (Rectangle<int> targetArea) const;\r
\r
/** Sets the target screen area to match the current mouse position.\r
\r
\r
@see withTargetScreenArea\r
*/\r
- JUCE_NODISCARD Options withMousePosition() const;\r
+ [[nodiscard]] Options withMousePosition() const;\r
\r
/** If the passed component has been deleted when the popup menu exits,\r
the selected item's action will not be called.\r
callback, in the case that the callback needs to access a component that\r
may be deleted.\r
*/\r
- JUCE_NODISCARD Options withDeletionCheck (Component& componentToWatchForDeletion) const;\r
+ [[nodiscard]] Options withDeletionCheck (Component& componentToWatchForDeletion) const;\r
\r
/** Sets the minimum width of the popup window. */\r
- JUCE_NODISCARD Options withMinimumWidth (int minWidth) const;\r
+ [[nodiscard]] Options withMinimumWidth (int minWidth) const;\r
\r
/** Sets the minimum number of columns in the popup window. */\r
- JUCE_NODISCARD Options withMinimumNumColumns (int minNumColumns) const;\r
+ [[nodiscard]] Options withMinimumNumColumns (int minNumColumns) const;\r
\r
/** Sets the maximum number of columns in the popup window. */\r
- JUCE_NODISCARD Options withMaximumNumColumns (int maxNumColumns) const;\r
+ [[nodiscard]] Options withMaximumNumColumns (int maxNumColumns) const;\r
\r
/** Sets the default height of each item in the popup menu. */\r
- JUCE_NODISCARD Options withStandardItemHeight (int standardHeight) const;\r
+ [[nodiscard]] Options withStandardItemHeight (int standardHeight) const;\r
\r
/** Sets an item which must be visible when the menu is initially drawn.\r
\r
This is useful to ensure that a particular item is shown when the menu\r
contains too many items to display on a single screen.\r
*/\r
- JUCE_NODISCARD Options withItemThatMustBeVisible (int idOfItemToBeVisible) const;\r
+ [[nodiscard]] Options withItemThatMustBeVisible (int idOfItemToBeVisible) const;\r
\r
/** Sets a component that the popup menu will be drawn into.\r
\r
avoid this unwanted behaviour, but with the downside that the menu size\r
will be constrained by the size of the parent component.\r
*/\r
- JUCE_NODISCARD Options withParentComponent (Component* parentComponent) const;\r
+ [[nodiscard]] Options withParentComponent (Component* parentComponent) const;\r
\r
/** Sets the direction of the popup menu relative to the target screen area. */\r
- JUCE_NODISCARD Options withPreferredPopupDirection (PopupDirection direction) const;\r
+ [[nodiscard]] Options withPreferredPopupDirection (PopupDirection direction) const;\r
\r
/** Sets an item to select in the menu.\r
\r
than needing to move the highlighted row down from the top of the menu each time\r
it is opened.\r
*/\r
- JUCE_NODISCARD Options withInitiallySelectedItem (int idOfItemToBeSelected) const;\r
+ [[nodiscard]] Options withInitiallySelectedItem (int idOfItemToBeSelected) const;\r
\r
//==============================================================================\r
/** Gets the parent component. This may be nullptr if the Component has been deleted.\r
bool operator== (const PointerState& other) const noexcept { return tie() == other.tie(); }\r
bool operator!= (const PointerState& other) const noexcept { return tie() != other.tie(); }\r
\r
- JUCE_NODISCARD PointerState withPositionOffset (Point<float> x) const noexcept { return with (&PointerState::position, position + x); }\r
- JUCE_NODISCARD PointerState withPosition (Point<float> x) const noexcept { return with (&PointerState::position, x); }\r
- JUCE_NODISCARD PointerState withPressure (float x) const noexcept { return with (&PointerState::pressure, x); }\r
- JUCE_NODISCARD PointerState withOrientation (float x) const noexcept { return with (&PointerState::orientation, x); }\r
- JUCE_NODISCARD PointerState withRotation (float x) const noexcept { return with (&PointerState::rotation, x); }\r
- JUCE_NODISCARD PointerState withTiltX (float x) const noexcept { return with (&PointerState::tiltX, x); }\r
- JUCE_NODISCARD PointerState withTiltY (float x) const noexcept { return with (&PointerState::tiltY, x); }\r
+ [[nodiscard]] PointerState withPositionOffset (Point<float> x) const noexcept { return with (&PointerState::position, position + x); }\r
+ [[nodiscard]] PointerState withPosition (Point<float> x) const noexcept { return with (&PointerState::position, x); }\r
+ [[nodiscard]] PointerState withPressure (float x) const noexcept { return with (&PointerState::pressure, x); }\r
+ [[nodiscard]] PointerState withOrientation (float x) const noexcept { return with (&PointerState::orientation, x); }\r
+ [[nodiscard]] PointerState withRotation (float x) const noexcept { return with (&PointerState::rotation, x); }\r
+ [[nodiscard]] PointerState withTiltX (float x) const noexcept { return with (&PointerState::tiltX, x); }\r
+ [[nodiscard]] PointerState withTiltY (float x) const noexcept { return with (&PointerState::tiltY, x); }\r
\r
Point<float> position;\r
float pressure = MouseInputSource::defaultPressure;\r
template <typename Func, typename... Items>\r
static constexpr void forEach (Func&& func, Items&&... items)\r
{\r
- (void) std::initializer_list<int> { ((void) func (std::forward<Items> (items)), 0)... };\r
+ (func (std::forward<Items> (items)), ...);\r
}\r
\r
public:\r
\r
void notifyAccessibilityEventInternal (const AccessibilityHandler& handler, InternalAccessibilityEvent eventType)\r
{\r
+ using namespace ComTypes::Constants;\r
+\r
if (eventType == InternalAccessibilityEvent::elementCreated\r
|| eventType == InternalAccessibilityEvent::elementDestroyed)\r
{\r
if (auto* parent = handler.getParent())\r
- sendAccessibilityAutomationEvent (*parent, ComTypes::UIA_LayoutInvalidatedEventId);\r
+ sendAccessibilityAutomationEvent (*parent, UIA_LayoutInvalidatedEventId);\r
\r
return;\r
}\r
{\r
switch (eventType)\r
{\r
- case InternalAccessibilityEvent::focusChanged: return ComTypes::UIA_AutomationFocusChangedEventId;\r
- case InternalAccessibilityEvent::windowOpened: return ComTypes::UIA_Window_WindowOpenedEventId;\r
- case InternalAccessibilityEvent::windowClosed: return ComTypes::UIA_Window_WindowClosedEventId;\r
+ case InternalAccessibilityEvent::focusChanged: return UIA_AutomationFocusChangedEventId;\r
+ case InternalAccessibilityEvent::windowOpened: return UIA_Window_WindowOpenedEventId;\r
+ case InternalAccessibilityEvent::windowClosed: return UIA_Window_WindowClosedEventId;\r
case InternalAccessibilityEvent::elementCreated:\r
case InternalAccessibilityEvent::elementDestroyed:\r
case InternalAccessibilityEvent::elementMovedOrResized: break;\r
\r
auto event = [eventType]() -> EVENTID\r
{\r
+ using namespace ComTypes::Constants;\r
+\r
switch (eventType)\r
{\r
- case AccessibilityEvent::textSelectionChanged: return ComTypes::UIA_Text_TextSelectionChangedEventId;\r
- case AccessibilityEvent::textChanged: return ComTypes::UIA_Text_TextChangedEventId;\r
- case AccessibilityEvent::structureChanged: return ComTypes::UIA_StructureChangedEventId;\r
- case AccessibilityEvent::rowSelectionChanged: return ComTypes::UIA_SelectionItem_ElementSelectedEventId;\r
+ case AccessibilityEvent::textSelectionChanged: return UIA_Text_TextSelectionChangedEventId;\r
+ case AccessibilityEvent::textChanged: return UIA_Text_TextChangedEventId;\r
+ case AccessibilityEvent::structureChanged: return UIA_StructureChangedEventId;\r
+ case AccessibilityEvent::rowSelectionChanged: return UIA_SelectionItem_ElementSelectedEventId;\r
case AccessibilityEvent::titleChanged:\r
case AccessibilityEvent::valueChanged: break;\r
}\r
\r
static auto roleToControlTypeId (AccessibilityRole roleType)\r
{\r
+ using namespace ComTypes::Constants;\r
+\r
switch (roleType)\r
{\r
case AccessibilityRole::popupMenu:\r
case AccessibilityRole::dialogWindow:\r
case AccessibilityRole::splashScreen:\r
- case AccessibilityRole::window: return ComTypes::UIA_WindowControlTypeId;\r
+ case AccessibilityRole::window: return UIA_WindowControlTypeId;\r
\r
case AccessibilityRole::label:\r
- case AccessibilityRole::staticText: return ComTypes::UIA_TextControlTypeId;\r
+ case AccessibilityRole::staticText: return UIA_TextControlTypeId;\r
\r
case AccessibilityRole::column:\r
- case AccessibilityRole::row: return ComTypes::UIA_ListItemControlTypeId;\r
-\r
- case AccessibilityRole::button: return ComTypes::UIA_ButtonControlTypeId;\r
- case AccessibilityRole::toggleButton: return ComTypes::UIA_CheckBoxControlTypeId;\r
- case AccessibilityRole::radioButton: return ComTypes::UIA_RadioButtonControlTypeId;\r
- case AccessibilityRole::comboBox: return ComTypes::UIA_ComboBoxControlTypeId;\r
- case AccessibilityRole::image: return ComTypes::UIA_ImageControlTypeId;\r
- case AccessibilityRole::slider: return ComTypes::UIA_SliderControlTypeId;\r
- case AccessibilityRole::editableText: return ComTypes::UIA_EditControlTypeId;\r
- case AccessibilityRole::menuItem: return ComTypes::UIA_MenuItemControlTypeId;\r
- case AccessibilityRole::menuBar: return ComTypes::UIA_MenuBarControlTypeId;\r
- case AccessibilityRole::table: return ComTypes::UIA_TableControlTypeId;\r
- case AccessibilityRole::tableHeader: return ComTypes::UIA_HeaderControlTypeId;\r
- case AccessibilityRole::cell: return ComTypes::UIA_DataItemControlTypeId;\r
- case AccessibilityRole::hyperlink: return ComTypes::UIA_HyperlinkControlTypeId;\r
- case AccessibilityRole::list: return ComTypes::UIA_ListControlTypeId;\r
- case AccessibilityRole::listItem: return ComTypes::UIA_ListItemControlTypeId;\r
- case AccessibilityRole::tree: return ComTypes::UIA_TreeControlTypeId;\r
- case AccessibilityRole::treeItem: return ComTypes::UIA_TreeItemControlTypeId;\r
- case AccessibilityRole::progressBar: return ComTypes::UIA_ProgressBarControlTypeId;\r
- case AccessibilityRole::group: return ComTypes::UIA_GroupControlTypeId;\r
- case AccessibilityRole::scrollBar: return ComTypes::UIA_ScrollBarControlTypeId;\r
- case AccessibilityRole::tooltip: return ComTypes::UIA_ToolTipControlTypeId;\r
+ case AccessibilityRole::row: return UIA_ListItemControlTypeId;\r
+\r
+ case AccessibilityRole::button: return UIA_ButtonControlTypeId;\r
+ case AccessibilityRole::toggleButton: return UIA_CheckBoxControlTypeId;\r
+ case AccessibilityRole::radioButton: return UIA_RadioButtonControlTypeId;\r
+ case AccessibilityRole::comboBox: return UIA_ComboBoxControlTypeId;\r
+ case AccessibilityRole::image: return UIA_ImageControlTypeId;\r
+ case AccessibilityRole::slider: return UIA_SliderControlTypeId;\r
+ case AccessibilityRole::editableText: return UIA_EditControlTypeId;\r
+ case AccessibilityRole::menuItem: return UIA_MenuItemControlTypeId;\r
+ case AccessibilityRole::menuBar: return UIA_MenuBarControlTypeId;\r
+ case AccessibilityRole::table: return UIA_TableControlTypeId;\r
+ case AccessibilityRole::tableHeader: return UIA_HeaderControlTypeId;\r
+ case AccessibilityRole::cell: return UIA_DataItemControlTypeId;\r
+ case AccessibilityRole::hyperlink: return UIA_HyperlinkControlTypeId;\r
+ case AccessibilityRole::list: return UIA_ListControlTypeId;\r
+ case AccessibilityRole::listItem: return UIA_ListItemControlTypeId;\r
+ case AccessibilityRole::tree: return UIA_TreeControlTypeId;\r
+ case AccessibilityRole::treeItem: return UIA_TreeItemControlTypeId;\r
+ case AccessibilityRole::progressBar: return UIA_ProgressBarControlTypeId;\r
+ case AccessibilityRole::group: return UIA_GroupControlTypeId;\r
+ case AccessibilityRole::scrollBar: return UIA_ScrollBarControlTypeId;\r
+ case AccessibilityRole::tooltip: return UIA_ToolTipControlTypeId;\r
\r
case AccessibilityRole::ignored:\r
case AccessibilityRole::unspecified: break;\r
};\r
\r
- return ComTypes::UIA_CustomControlTypeId;\r
+ return UIA_CustomControlTypeId;\r
}\r
\r
//==============================================================================\r
return false;\r
};\r
\r
+ using namespace ComTypes::Constants;\r
+\r
switch (pId)\r
{\r
- case ComTypes::UIA_WindowPatternId:\r
+ case UIA_WindowPatternId:\r
{\r
if (fragmentRoot)\r
return new UIAWindowProvider (this);\r
\r
break;\r
}\r
- case ComTypes::UIA_TransformPatternId:\r
+ case UIA_TransformPatternId:\r
{\r
if (fragmentRoot)\r
return new UIATransformProvider (this);\r
\r
break;\r
}\r
- case ComTypes::UIA_TextPatternId:\r
- case ComTypes::UIA_TextPattern2Id:\r
+ case UIA_TextPatternId:\r
+ case UIA_TextPattern2Id:\r
{\r
if (accessibilityHandler.getTextInterface() != nullptr)\r
return new UIATextProvider (this);\r
\r
break;\r
}\r
- case ComTypes::UIA_ValuePatternId:\r
+ case UIA_ValuePatternId:\r
{\r
if (accessibilityHandler.getValueInterface() != nullptr)\r
return new UIAValueProvider (this);\r
\r
break;\r
}\r
- case ComTypes::UIA_RangeValuePatternId:\r
+ case UIA_RangeValuePatternId:\r
{\r
if (accessibilityHandler.getValueInterface() != nullptr\r
&& accessibilityHandler.getValueInterface()->getRange().isValid())\r
\r
break;\r
}\r
- case ComTypes::UIA_TogglePatternId:\r
+ case UIA_TogglePatternId:\r
{\r
if (accessibilityHandler.getCurrentState().isCheckable()\r
&& (accessibilityHandler.getActions().contains (AccessibilityActionType::toggle)\r
\r
break;\r
}\r
- case ComTypes::UIA_SelectionPatternId:\r
+ case UIA_SelectionPatternId:\r
{\r
if (role == AccessibilityRole::list\r
|| role == AccessibilityRole::popupMenu\r
\r
break;\r
}\r
- case ComTypes::UIA_SelectionItemPatternId:\r
+ case UIA_SelectionItemPatternId:\r
{\r
auto state = accessibilityHandler.getCurrentState();\r
\r
\r
break;\r
}\r
- case ComTypes::UIA_TablePatternId:\r
- case ComTypes::UIA_GridPatternId:\r
+ case UIA_TablePatternId:\r
+ case UIA_GridPatternId:\r
{\r
if (accessibilityHandler.getTableInterface() != nullptr\r
- && (pId == ComTypes::UIA_GridPatternId || accessibilityHandler.getRole() == AccessibilityRole::table))\r
+ && (pId == UIA_GridPatternId || accessibilityHandler.getRole() == AccessibilityRole::table))\r
return static_cast<ComTypes::IGridProvider*> (new UIAGridProvider (this));\r
\r
break;\r
}\r
- case ComTypes::UIA_TableItemPatternId:\r
- case ComTypes::UIA_GridItemPatternId:\r
+ case UIA_TableItemPatternId:\r
+ case UIA_GridItemPatternId:\r
{\r
if (isListOrTableCell (accessibilityHandler))\r
return static_cast<ComTypes::IGridItemProvider*> (new UIAGridItemProvider (this));\r
\r
break;\r
}\r
- case ComTypes::UIA_InvokePatternId:\r
+ case UIA_InvokePatternId:\r
{\r
if (accessibilityHandler.getActions().contains (AccessibilityActionType::press))\r
return new UIAInvokeProvider (this);\r
\r
break;\r
}\r
- case ComTypes::UIA_ExpandCollapsePatternId:\r
+ case UIA_ExpandCollapsePatternId:\r
{\r
if (accessibilityHandler.getActions().contains (AccessibilityActionType::showMenu)\r
&& accessibilityHandler.getCurrentState().isExpandable())\r
\r
break;\r
}\r
- case ComTypes::UIA_ScrollPatternId:\r
+ case UIA_ScrollPatternId:\r
{\r
if (accessibilityHandler.getTableInterface() != nullptr)\r
return new UIAScrollProvider (this);\r
\r
break;\r
}\r
- case ComTypes::UIA_ScrollItemPatternId:\r
+ case UIA_ScrollItemPatternId:\r
{\r
if (isListOrTableCell (accessibilityHandler))\r
return new UIAScrollItemProvider (this);\r
const auto state = accessibilityHandler.getCurrentState();\r
const auto ignored = accessibilityHandler.isIgnored();\r
\r
+ using namespace ComTypes::Constants;\r
+\r
switch (propertyId)\r
{\r
case UIA_AutomationIdPropertyId:\r
VariantHelpers::setBool (textInterface->isDisplayingProtectedText(), pRetVal);\r
\r
break;\r
- case ComTypes::UIA_IsPeripheralPropertyId:\r
+ case UIA_IsPeripheralPropertyId:\r
VariantHelpers::setBool (role == AccessibilityRole::tooltip\r
|| role == AccessibilityRole::popupMenu\r
|| role == AccessibilityRole::splashScreen,\r
namespace juce\r
{\r
\r
-#define UIA_FullDescriptionPropertyId 30159\r
-#define UIA_IsDialogPropertyId 30174\r
-\r
class AccessibilityNativeHandle : public ComBaseClassHelper<IRawElementProviderSimple,\r
ComTypes::IRawElementProviderFragment,\r
ComTypes::IRawElementProviderFragmentRoot>\r
ScrollAmount_SmallIncrement = 4\r
};\r
\r
+namespace Constants\r
+{\r
+\r
+#undef UIA_InvokePatternId\r
+#undef UIA_SelectionPatternId\r
+#undef UIA_ValuePatternId\r
+#undef UIA_RangeValuePatternId\r
+#undef UIA_ScrollPatternId\r
+#undef UIA_ExpandCollapsePatternId\r
+#undef UIA_GridPatternId\r
+#undef UIA_GridItemPatternId\r
+#undef UIA_WindowPatternId\r
+#undef UIA_SelectionItemPatternId\r
+#undef UIA_TablePatternId\r
+#undef UIA_TableItemPatternId\r
+#undef UIA_TextPatternId\r
+#undef UIA_TogglePatternId\r
+#undef UIA_TransformPatternId\r
+#undef UIA_ScrollItemPatternId\r
+#undef UIA_TextPattern2Id\r
+#undef UIA_StructureChangedEventId\r
+#undef UIA_MenuOpenedEventId\r
+#undef UIA_AutomationFocusChangedEventId\r
+#undef UIA_MenuClosedEventId\r
+#undef UIA_LayoutInvalidatedEventId\r
+#undef UIA_Invoke_InvokedEventId\r
+#undef UIA_SelectionItem_ElementSelectedEventId\r
+#undef UIA_Text_TextSelectionChangedEventId\r
+#undef UIA_Text_TextChangedEventId\r
+#undef UIA_Window_WindowOpenedEventId\r
+#undef UIA_Window_WindowClosedEventId\r
+#undef UIA_IsPeripheralPropertyId\r
+#undef UIA_FullDescriptionPropertyId\r
+#undef UIA_IsDialogPropertyId\r
+#undef UIA_IsReadOnlyAttributeId\r
+#undef UIA_CaretPositionAttributeId\r
+#undef UIA_ButtonControlTypeId\r
+#undef UIA_CheckBoxControlTypeId\r
+#undef UIA_ComboBoxControlTypeId\r
+#undef UIA_EditControlTypeId\r
+#undef UIA_HyperlinkControlTypeId\r
+#undef UIA_ImageControlTypeId\r
+#undef UIA_ListItemControlTypeId\r
+#undef UIA_ListControlTypeId\r
+#undef UIA_MenuBarControlTypeId\r
+#undef UIA_MenuItemControlTypeId\r
+#undef UIA_ProgressBarControlTypeId\r
+#undef UIA_RadioButtonControlTypeId\r
+#undef UIA_ScrollBarControlTypeId\r
+#undef UIA_SliderControlTypeId\r
+#undef UIA_TextControlTypeId\r
+#undef UIA_ToolTipControlTypeId\r
+#undef UIA_TreeControlTypeId\r
+#undef UIA_TreeItemControlTypeId\r
+#undef UIA_CustomControlTypeId\r
+#undef UIA_GroupControlTypeId\r
+#undef UIA_DataItemControlTypeId\r
+#undef UIA_WindowControlTypeId\r
+#undef UIA_HeaderControlTypeId\r
+#undef UIA_HeaderItemControlTypeId\r
+#undef UIA_TableControlTypeId\r
+\r
const long UIA_InvokePatternId = 10000;\r
const long UIA_SelectionPatternId = 10001;\r
const long UIA_ValuePatternId = 10002;\r
const long UIA_Window_WindowOpenedEventId = 20016;\r
const long UIA_Window_WindowClosedEventId = 20017;\r
const long UIA_IsPeripheralPropertyId = 30150;\r
+const long UIA_FullDescriptionPropertyId = 30159;\r
+const long UIA_IsDialogPropertyId = 30174;\r
const long UIA_IsReadOnlyAttributeId = 40015;\r
const long UIA_CaretPositionAttributeId = 40038;\r
const long UIA_ButtonControlTypeId = 50000;\r
const long UIA_HeaderItemControlTypeId = 50035;\r
const long UIA_TableControlTypeId = 50036;\r
\r
+} // namespace Constants\r
+\r
interface IRawElementProviderFragmentRoot;\r
interface IRawElementProviderFragment;\r
\r
\r
if (handler.getActions().invoke (AccessibilityActionType::showMenu))\r
{\r
+ using namespace ComTypes::Constants;\r
+\r
sendAccessibilityAutomationEvent (handler, handler.getCurrentState().isExpanded()\r
- ? ComTypes::UIA_MenuOpenedEventId\r
- : ComTypes::UIA_MenuClosedEventId);\r
+ ? UIA_MenuOpenedEventId\r
+ : UIA_MenuClosedEventId);\r
\r
return S_OK;\r
}\r
\r
if (handler.getActions().invoke (AccessibilityActionType::press))\r
{\r
+ using namespace ComTypes::Constants;\r
+\r
if (isElementValid())\r
- sendAccessibilityAutomationEvent (handler, ComTypes::UIA_Invoke_InvokedEventId);\r
+ sendAccessibilityAutomationEvent (handler, UIA_Invoke_InvokedEventId);\r
\r
return S_OK;\r
}\r
\r
if (isRadioButton)\r
{\r
+ using namespace ComTypes::Constants;\r
+\r
handler.getActions().invoke (AccessibilityActionType::press);\r
- sendAccessibilityAutomationEvent (handler, ComTypes::UIA_SelectionItem_ElementSelectedEventId);\r
+ sendAccessibilityAutomationEvent (handler, UIA_SelectionItem_ElementSelectedEventId);\r
\r
return S_OK;\r
}\r
{\r
VariantHelpers::clear (pRetVal);\r
\r
+ using namespace ComTypes::Constants;\r
+\r
switch (attributeId)\r
{\r
- case ComTypes::UIA_IsReadOnlyAttributeId:\r
+ case UIA_IsReadOnlyAttributeId:\r
{\r
VariantHelpers::setBool (textInterface.isReadOnly(), pRetVal);\r
break;\r
}\r
\r
- case ComTypes::UIA_CaretPositionAttributeId:\r
+ case UIA_CaretPositionAttributeId:\r
{\r
auto cursorPos = textInterface.getTextInsertionOffset();\r
\r
import android.graphics.Rect;\r
import android.os.Bundle;\r
import android.text.InputType;\r
+import android.view.Choreographer;\r
import android.view.KeyEvent;\r
import android.view.MotionEvent;\r
import android.view.View;\r
import java.util.List;\r
\r
public final class ComponentPeerView extends ViewGroup\r
- implements View.OnFocusChangeListener, Application.ActivityLifecycleCallbacks\r
+ implements View.OnFocusChangeListener, Application.ActivityLifecycleCallbacks, Choreographer.FrameCallback\r
{\r
public ComponentPeerView (Context context, boolean opaque_, long host)\r
{\r
{\r
}\r
}\r
+\r
+ Choreographer.getInstance().postFrameCallback (this);\r
}\r
\r
public void clear ()\r
handlePaint (host, canvas, paint);\r
}\r
\r
+ private native void handleDoFrame (long host, long frameTimeNanos);\r
+\r
+ @Override\r
+ public void doFrame (long frameTimeNanos)\r
+ {\r
+ if (host == 0)\r
+ return;\r
+\r
+ handleDoFrame (host, frameTimeNanos);\r
+\r
+ Choreographer.getInstance().postFrameCallback (this);\r
+ }\r
+\r
@Override\r
public boolean isOpaque ()\r
{\r
#endif\r
}\r
\r
+void FileChooser::registerCustomMimeTypeForFileExtension (const String& mimeType,\r
+ const String& fileExtension)\r
+{\r
+ MimeTypeTable::registerCustomMimeTypeForFileExtension (mimeType, fileExtension);\r
+}\r
+\r
} // namespace juce\r
// This byte-code is generated from native/java/com/rmsl/juce/ComponentPeerView.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 javaComponentPeerView[] =\r
-{ 31,139,8,8,217,126,216,97,0,3,74,97,118,97,68,101,120,66,121,116,101,67,111,100,101,46,100,101,120,0,165,155,11,124,212,213,149,199,207,189,255,255,204,36,147,215,100,18,146,64,18,50,9,175,16,72,102,8,111,19,148,183,6,18,64,18,16,18,171,76,146,127,146,\r
- 129,201,127,134,153,73,72,124,21,149,143,96,173,21,45,82,21,109,177,165,182,110,109,215,90,219,181,22,181,93,93,215,173,186,85,107,87,180,90,31,69,197,150,90,180,86,105,117,117,127,247,49,147,9,143,210,118,195,231,59,231,252,207,125,223,123,238,185,247,\r
- 63,33,221,214,144,59,48,115,54,125,253,172,186,247,86,249,42,166,141,253,112,218,236,231,195,83,47,91,120,183,99,205,99,123,255,208,184,125,22,81,148,136,134,214,207,242,146,254,57,56,147,168,146,41,251,60,240,129,73,180,4,242,121,7,81,9,228,241,12,162,\r
- 203,33,31,200,36,66,18,237,207,33,218,52,153,200,151,75,212,94,78,116,33,184,24,116,130,205,192,6,215,128,107,193,245,96,55,216,3,110,1,251,192,215,192,195,224,5,240,18,248,13,120,3,188,5,126,15,142,129,63,131,156,241,232,7,184,8,12,131,61,224,126,240,\r
- 60,248,12,140,173,32,170,7,231,130,207,129,65,112,19,120,8,60,7,142,130,137,62,162,101,96,8,220,3,14,131,194,74,162,6,208,11,246,130,23,64,69,21,198,2,46,7,119,130,159,129,195,192,152,64,84,14,2,160,13,92,2,110,0,247,129,199,193,155,224,47,160,122,34,\r
- 209,82,208,1,194,224,10,176,3,220,4,110,6,183,130,253,224,0,184,7,220,7,126,12,30,1,143,129,39,192,211,224,57,240,2,120,5,188,14,222,1,71,193,123,224,35,240,9,48,38,17,101,130,28,224,5,227,64,37,152,4,166,130,5,96,45,184,8,108,6,131,224,42,240,37,112,\r
- 27,184,11,220,7,30,6,79,130,151,192,49,112,28,56,176,174,121,160,6,204,6,243,192,74,208,10,58,64,23,8,131,56,216,14,174,7,119,128,123,192,15,193,65,240,34,120,21,188,1,222,1,89,83,136,138,64,57,152,6,230,129,117,32,14,174,0,55,128,187,192,15,193,35,224,\r
- 73,240,34,56,12,254,2,114,171,137,202,192,20,48,15,44,7,171,193,6,96,129,109,96,39,184,29,124,7,252,4,188,8,94,5,111,130,35,128,79,37,42,0,147,192,92,176,28,180,130,16,184,4,92,7,110,3,223,2,7,193,227,224,85,240,14,248,35,120,31,124,10,140,26,248,15,\r
- 152,0,102,129,115,64,11,184,0,92,12,182,128,1,176,27,236,3,7,192,67,224,41,240,75,240,6,56,2,142,129,227,224,99,192,166,17,185,65,33,168,2,53,32,0,230,128,38,112,17,136,130,171,193,126,240,3,240,56,120,21,188,13,62,4,206,233,40,15,42,64,29,152,11,22,\r
- 129,53,224,34,208,3,34,96,24,108,7,95,4,251,192,215,193,207,192,99,224,105,240,30,200,171,197,122,129,82,48,13,204,7,107,65,39,136,130,47,128,59,193,195,224,73,240,18,120,11,124,8,204,58,204,51,152,0,234,65,51,88,11,54,128,77,160,15,216,32,14,134,193,\r
- 213,224,26,112,61,216,11,110,7,223,5,15,128,159,131,23,193,155,224,8,248,61,248,35,248,19,248,8,124,12,62,3,78,196,36,132,40,202,2,69,160,152,84,220,26,11,198,129,82,80,6,16,82,8,97,131,16,22,8,97,128,176,237,9,91,156,176,125,9,219,138,224,254,4,119,\r
- 37,184,28,193,101,8,203,77,88,30,194,244,18,166,133,48,60,66,115,228,7,1,48,3,212,3,132,79,66,88,165,217,96,14,152,171,227,232,124,112,22,104,0,141,96,1,56,27,156,3,22,130,69,96,49,169,88,187,12,156,7,54,128,78,208,5,186,129,69,106,124,201,31,151,150,\r
- 247,151,170,49,51,253,236,214,186,176,139,121,224,218,158,173,245,131,176,231,165,213,229,213,115,246,152,182,231,106,123,158,78,75,234,99,180,238,209,243,42,234,47,208,250,83,186,108,73,90,157,98,174,159,47,85,186,152,227,151,117,158,201,105,245,76,\r
- 213,245,228,107,253,48,244,66,173,31,45,85,109,138,57,255,64,215,35,244,79,116,61,181,186,158,49,122,29,204,50,213,31,177,22,217,101,106,14,235,117,158,38,173,139,182,86,104,189,16,121,86,106,93,180,219,172,117,31,236,45,90,15,64,95,165,245,70,232,171,\r
- 181,126,30,244,53,90,111,131,126,190,214,47,132,222,170,245,238,52,123,56,77,79,64,95,167,245,203,210,236,187,210,244,221,105,250,45,105,117,238,79,179,127,27,122,155,214,239,77,179,31,40,29,209,197,156,175,213,186,152,207,100,61,15,164,229,23,243,185,\r
- 94,235,63,133,253,2,173,63,145,150,231,80,154,254,90,153,242,205,153,122,110,55,106,253,8,236,237,90,63,150,166,127,2,189,67,235,25,226,142,160,117,15,244,207,105,189,76,220,27,180,94,13,253,34,173,7,210,236,194,199,54,105,125,30,236,65,173,159,151,150,\r
- 191,173,92,248,57,163,97,82,50,135,137,125,63,137,226,164,228,191,73,201,232,65,45,15,106,249,144,150,15,107,249,136,206,255,115,18,177,194,71,110,166,100,1,19,113,99,38,253,23,9,89,65,89,76,196,16,149,94,161,211,43,144,82,196,132,207,23,209,86,225,79,\r
- 216,117,15,72,89,65,79,72,89,78,191,148,114,38,189,35,101,22,29,149,62,63,153,150,67,58,16,129,254,68,98,127,58,233,70,41,199,208,126,200,76,68,49,67,202,89,244,33,137,125,94,45,159,179,180,61,11,17,225,35,57,110,245,156,135,118,111,144,178,136,110,210,\r
- 207,183,106,121,167,152,127,157,46,228,110,41,77,186,89,63,239,147,210,160,219,73,237,211,59,180,252,170,148,140,238,210,242,91,36,246,37,167,189,82,78,165,111,146,216,131,147,100,251,5,136,120,191,149,114,62,29,150,178,148,222,38,177,95,107,105,64,203,\r
- 15,72,196,233,57,244,31,36,226,72,54,61,47,229,88,122,159,68,44,81,227,24,139,136,43,100,25,162,230,143,164,172,161,191,74,121,14,153,114,93,2,50,189,28,51,176,67,202,18,218,165,159,175,149,114,30,189,43,215,171,78,230,27,143,26,95,39,177,78,170,92,5,\r
- 236,61,90,246,74,153,71,125,82,142,37,7,83,210,41,215,115,178,204,239,195,10,133,164,244,211,102,41,23,209,22,41,11,40,172,101,191,148,11,201,150,114,44,13,105,121,185,148,115,233,74,41,43,233,58,41,189,116,189,148,57,244,37,41,157,180,71,251,205,94,\r
- 157,254,21,41,103,211,45,82,102,210,215,164,116,211,215,117,190,111,72,153,65,7,164,84,235,32,252,236,110,41,203,232,95,180,252,142,150,247,104,127,252,174,148,227,233,123,218,254,175,186,220,189,90,126,95,203,251,164,244,209,15,164,108,160,251,165,156,\r
- 67,143,105,249,184,148,19,232,5,41,171,232,144,150,47,106,249,146,78,255,181,126,126,89,203,87,164,204,165,223,72,57,133,94,149,114,58,189,38,229,217,244,134,148,202,143,124,218,143,196,243,155,122,255,188,37,165,242,43,145,255,136,148,141,116,76,202,\r
- 122,58,174,229,95,164,156,70,159,72,57,142,62,149,114,6,125,166,159,137,169,124,76,75,206,84,186,193,212,188,20,50,113,110,21,211,109,36,228,98,122,84,238,87,78,63,147,50,159,188,76,156,77,202,95,167,97,103,124,153,196,249,100,208,21,82,114,122,154,196,\r
- 25,85,72,255,78,226,190,48,86,251,171,218,83,201,51,19,175,88,116,33,98,220,21,250,208,26,175,237,226,204,19,49,93,164,39,32,239,208,233,21,186,252,180,180,242,59,144,126,175,78,247,145,58,87,197,153,120,143,46,191,7,242,144,78,23,119,129,169,208,3,245,\r
- 234,190,112,86,189,178,173,134,92,15,12,157,190,9,108,214,121,226,210,110,72,157,251,213,189,161,131,185,41,234,17,55,168,14,158,133,181,204,64,45,162,173,28,191,186,59,121,89,91,167,155,182,122,102,193,158,197,139,240,218,56,131,115,115,62,55,201,229,\r
- 201,167,182,206,44,218,234,171,160,24,118,191,200,215,214,165,242,26,148,101,110,93,51,135,22,15,184,249,124,254,135,207,108,143,24,143,203,83,253,182,169,219,159,224,87,119,152,42,204,104,212,115,153,28,173,104,91,244,187,214,175,238,96,167,107,219,\r
- 160,124,230,245,206,156,50,246,228,54,3,115,105,177,35,27,49,227,24,218,20,113,202,205,108,223,20,68,169,108,86,253,214,201,185,231,201,220,213,239,136,248,107,202,254,44,241,171,181,107,139,170,124,34,165,136,203,123,9,159,143,60,94,196,151,182,173,\r
- 238,244,116,206,118,176,155,93,119,109,115,206,199,200,16,215,143,25,232,175,24,227,106,191,136,247,152,89,111,14,198,184,13,54,47,93,232,201,150,119,180,12,60,137,177,110,240,171,179,182,192,89,72,85,60,27,249,196,44,180,197,115,168,109,102,46,217,158,\r
- 165,200,149,205,230,179,198,17,155,239,60,236,197,145,28,139,144,195,109,172,157,40,222,21,25,125,191,237,70,50,204,217,155,198,209,186,56,230,193,40,34,175,113,33,180,100,254,182,68,14,250,29,192,72,178,77,209,127,83,206,195,108,90,226,16,249,231,27,\r
- 46,154,187,201,65,222,2,81,70,180,85,140,56,103,123,138,196,200,78,104,163,250,191,197,90,10,159,187,218,175,238,116,29,222,92,61,206,42,204,97,212,39,246,82,135,7,20,228,201,49,51,249,143,232,203,126,245,253,67,212,35,110,123,185,41,251,190,148,189,\r
- 94,218,185,190,21,127,195,175,252,185,205,147,39,247,132,240,32,209,238,119,252,234,94,220,230,203,67,31,197,205,27,227,172,244,160,215,101,104,57,55,149,239,190,211,230,43,151,249,114,225,241,98,36,63,70,190,167,132,223,185,188,69,81,95,9,226,111,149,\r
- 153,133,222,56,209,171,142,61,69,120,170,160,104,160,150,246,100,118,236,41,192,83,57,158,38,203,167,66,212,187,16,107,157,109,142,115,68,81,47,86,16,122,133,89,132,114,249,84,102,58,96,75,32,190,187,205,121,230,231,168,194,45,158,241,158,74,237,183,\r
- 123,161,69,113,227,185,112,223,24,104,33,156,77,182,111,179,252,220,130,243,190,10,117,70,61,242,60,54,11,105,194,162,89,52,153,137,27,161,237,51,209,243,54,209,39,7,246,175,207,65,162,70,23,90,245,26,182,103,72,247,228,99,242,78,158,208,51,7,227,233,\r
- 204,40,166,150,12,167,203,91,92,150,145,37,53,59,16,167,54,103,182,49,207,40,36,47,247,78,156,176,116,46,121,29,91,61,131,152,135,108,103,139,211,116,120,199,120,165,180,3,151,210,151,77,225,105,194,187,197,168,84,239,247,80,245,157,57,102,245,7,224,\r
- 125,112,12,188,4,196,225,97,152,242,61,96,228,103,251,57,244,15,61,159,248,163,210,197,93,178,8,251,241,18,82,247,23,110,84,223,202,166,124,133,213,221,204,248,244,59,88,205,62,70,58,186,224,221,47,160,124,166,213,231,149,113,214,148,145,15,239,125,1,\r
- 237,99,129,213,84,105,228,98,207,59,100,188,155,27,80,49,54,186,174,143,42,151,184,165,63,39,203,44,77,166,5,22,163,76,182,244,193,100,90,75,42,237,236,84,154,75,222,254,16,135,117,218,160,179,77,70,6,81,167,67,239,123,43,160,246,76,235,66,111,90,124,\r
- 49,224,139,194,18,13,52,227,118,84,253,215,145,241,244,235,186,196,123,113,59,198,148,171,251,32,126,226,1,21,251,189,158,188,212,158,185,60,144,220,51,133,178,79,73,251,213,218,190,206,51,70,182,207,245,222,187,54,160,222,61,109,207,114,217,87,25,235,\r
- 80,159,151,170,63,53,116,59,55,4,212,57,146,43,203,169,55,211,175,164,217,156,58,126,127,245,12,99,91,161,199,150,204,255,173,51,228,95,153,154,11,213,143,123,79,209,143,7,78,97,123,36,205,102,234,182,30,15,168,239,11,188,76,124,163,208,17,224,164,164,\r
- 65,27,103,32,238,29,219,24,112,209,198,128,83,91,51,225,199,88,73,207,198,128,137,244,12,236,199,177,232,79,21,249,88,190,30,175,88,147,95,5,212,89,125,234,254,183,45,46,162,232,218,86,50,207,175,62,46,124,195,144,254,247,202,105,203,204,92,246,217,103,\r
- 114,220,11,23,144,25,20,101,220,104,71,156,213,191,11,168,239,57,218,182,231,99,157,196,41,229,198,73,55,142,90,175,68,20,241,228,98,215,187,177,251,189,66,154,182,167,64,72,135,141,53,204,164,44,167,107,251,96,70,147,246,17,177,166,110,180,37,124,244,\r
- 163,128,250,174,195,235,105,141,161,39,226,140,101,56,99,153,58,233,166,139,87,62,18,41,54,206,45,85,95,150,144,78,215,86,182,99,208,217,130,249,173,254,67,36,48,150,118,102,226,228,59,98,123,206,194,8,171,197,69,143,171,113,38,191,191,17,178,64,147,\r
- 173,207,218,49,51,212,123,159,151,90,175,66,219,78,217,182,115,62,51,208,242,252,204,76,180,137,158,227,4,247,86,213,87,186,40,178,112,28,221,242,32,90,121,223,246,184,97,207,102,243,152,184,89,40,221,246,13,11,191,117,136,154,68,31,179,68,31,175,100,\r
- 123,84,31,189,158,234,23,212,220,139,245,154,57,67,125,239,48,122,238,213,136,133,77,140,213,73,110,30,93,187,10,171,134,178,127,38,189,163,137,22,205,24,241,169,76,29,59,86,207,80,107,25,217,80,74,109,131,233,181,206,67,155,202,135,99,240,97,81,38,79,\r
- 175,229,38,36,151,161,162,214,103,145,219,16,35,103,134,156,117,150,199,108,79,14,234,119,103,138,181,203,165,44,215,175,110,252,140,166,177,15,165,215,86,191,215,250,156,23,210,246,229,227,140,21,235,44,98,129,88,151,2,33,157,174,103,7,51,214,136,17,\r
- 231,87,191,124,230,156,107,85,206,255,60,115,206,243,145,211,246,136,211,210,157,229,205,159,91,90,67,222,202,9,101,179,113,18,44,193,253,216,59,110,246,131,149,36,106,17,117,124,79,212,225,43,20,146,121,29,75,29,217,142,171,214,61,62,198,246,141,81,\r
- 150,162,165,206,108,231,85,61,143,23,37,235,61,228,118,179,234,215,208,143,171,113,83,199,165,254,135,55,190,238,102,25,243,221,37,244,247,142,96,42,245,124,150,222,159,127,166,39,162,166,234,95,255,227,61,88,163,123,48,233,255,221,131,53,178,7,88,102,\r
- 166,190,29,20,190,37,226,144,95,75,17,191,196,187,91,92,250,30,151,119,150,23,102,168,239,50,209,71,156,251,46,202,230,227,140,255,37,111,225,132,165,56,247,29,157,78,156,251,242,12,143,83,189,41,238,145,46,244,59,7,251,31,124,226,245,78,168,194,169,\r
- 111,136,83,63,3,39,123,139,201,13,113,218,111,229,213,239,230,240,234,163,224,119,224,136,240,247,124,244,173,84,238,93,68,61,62,189,168,166,196,168,174,158,50,189,174,38,45,222,26,245,35,123,195,208,214,172,122,117,7,158,199,93,36,102,196,70,142,92,\r
- 242,46,172,254,88,140,79,197,228,194,122,21,7,196,29,74,220,118,199,241,159,202,59,84,37,90,171,192,251,219,60,68,15,219,115,9,118,168,155,45,96,5,152,109,59,48,137,2,24,241,185,50,191,29,152,72,30,179,109,70,1,110,182,117,178,254,100,138,151,219,129,\r
- 9,228,225,42,205,47,230,247,125,146,191,239,18,63,201,239,92,197,123,206,116,216,102,37,191,60,213,63,11,79,120,94,115,194,179,40,95,72,234,236,205,71,239,152,182,9,124,90,102,232,116,175,62,103,199,105,123,133,150,92,227,211,243,53,141,230,74,123,173,\r
- 182,215,34,58,43,201,100,60,101,250,159,131,70,206,116,174,125,35,121,150,155,41,157,105,187,43,245,93,50,199,76,179,84,126,33,115,82,101,132,116,234,52,39,242,113,109,115,105,153,169,101,242,187,232,92,217,43,210,247,11,49,198,153,122,44,62,105,159,\r
- 169,125,120,102,170,215,170,252,44,45,103,235,114,201,126,10,153,163,219,23,122,94,42,61,47,109,76,57,169,177,22,167,250,161,234,246,232,246,124,169,156,106,92,62,157,155,145,122,223,102,213,132,247,41,103,99,200,14,37,206,38,126,118,3,21,45,137,244,\r
- 71,35,182,101,39,214,88,86,108,125,200,218,86,183,57,56,24,36,182,156,248,242,38,98,77,196,155,166,2,168,43,136,175,104,166,242,21,3,93,214,162,174,46,43,30,15,117,134,194,161,196,240,170,72,183,181,38,22,25,12,117,91,49,42,94,105,13,119,70,130,177,238,\r
- 165,161,120,127,40,30,111,14,197,19,150,141,4,214,76,188,25,181,53,163,154,230,102,50,154,241,128,143,21,226,163,153,138,154,131,118,119,44,18,234,246,7,163,81,255,162,174,68,104,16,53,55,208,172,209,246,104,52,28,234,10,38,66,17,123,98,50,79,115,168,\r
- 199,234,26,238,10,91,75,130,225,112,103,176,107,75,188,129,198,158,174,84,122,82,87,196,70,207,18,254,37,66,14,37,210,147,122,99,193,104,95,168,43,238,95,18,180,7,131,168,112,252,41,146,34,225,72,108,121,40,156,176,98,167,79,111,9,38,98,161,161,6,154,\r
- 250,55,211,71,85,85,114,114,214,53,193,144,141,254,21,159,156,178,214,234,66,66,65,42,33,18,247,47,30,176,187,195,86,3,21,166,27,155,22,135,236,110,81,251,72,29,131,88,106,63,22,107,217,160,37,42,31,55,58,161,37,34,166,75,167,77,29,157,38,156,100,226,\r
- 106,123,121,164,107,32,190,164,47,104,247,90,201,69,78,239,74,42,107,250,144,82,198,115,99,145,129,104,3,205,57,57,165,45,102,89,171,59,227,86,108,208,138,161,149,115,195,145,206,96,184,57,56,28,25,72,140,52,83,241,183,203,53,208,140,209,25,130,233,254,\r
- 234,31,229,189,45,65,59,216,43,138,212,255,221,69,132,195,55,217,61,145,147,250,127,134,50,201,77,210,64,117,163,203,133,236,232,64,162,223,74,244,69,186,253,139,131,113,84,142,103,248,165,141,229,149,94,59,233,244,249,151,117,135,18,145,152,234,78,205,\r
- 233,179,157,84,101,237,25,242,182,72,61,53,59,231,52,119,69,250,253,177,254,120,216,191,25,1,192,127,82,216,152,248,55,227,66,3,45,63,99,5,167,137,28,19,71,175,236,252,127,182,158,6,170,60,83,209,6,170,106,238,14,134,7,67,91,252,65,219,142,36,100,204,\r
- 240,47,179,187,194,145,120,200,238,93,18,14,198,101,48,56,57,79,19,38,54,166,211,43,79,145,222,98,245,119,234,12,22,178,148,159,34,75,107,168,215,14,38,6,98,150,216,48,34,6,251,195,216,91,126,236,176,88,171,181,117,192,178,187,144,146,159,158,162,154,\r
- 171,74,51,53,133,195,86,111,48,172,150,97,217,80,151,21,85,139,61,241,20,121,98,189,3,253,24,123,90,174,130,244,92,8,138,189,106,210,70,140,171,34,173,3,93,125,202,51,210,202,121,211,178,172,238,220,44,99,82,121,154,173,213,234,26,136,193,33,78,83,164,\r
- 21,49,208,238,21,30,57,98,139,89,61,97,212,131,110,12,70,84,232,110,11,198,122,173,244,222,142,59,69,118,213,181,6,26,163,210,6,18,161,176,127,81,44,22,28,22,78,208,64,121,105,102,97,33,207,9,134,6,50,219,54,174,89,70,217,233,62,71,108,61,241,245,77,\r
- 228,88,223,132,31,168,43,200,185,126,69,211,242,229,120,155,135,20,9,43,68,2,30,196,193,182,126,69,59,242,8,69,28,110,235,165,169,185,29,169,205,237,56,250,214,183,163,112,187,172,136,181,147,209,46,202,225,163,89,168,205,228,104,95,33,116,19,2,199,101,\r
- 187,176,226,152,116,182,55,75,179,67,72,216,59,112,54,119,52,145,183,227,100,103,40,232,56,197,90,184,85,92,154,24,8,4,82,250,140,52,189,62,77,159,153,166,207,74,211,103,167,233,115,210,244,185,105,250,60,232,89,74,95,30,14,246,198,41,103,84,64,164,194,\r
- 224,41,2,47,57,131,50,34,137,146,66,54,7,59,173,48,101,4,245,241,78,99,131,221,221,167,62,6,40,51,168,125,56,78,172,147,242,197,225,191,120,32,145,136,216,107,98,104,198,234,38,103,103,4,143,253,144,242,80,36,103,151,60,207,201,213,37,143,173,110,114,\r
- 224,222,16,140,81,86,151,8,85,17,156,178,139,18,226,33,117,50,83,174,124,104,139,5,237,120,79,36,214,79,57,226,214,128,227,56,46,115,163,34,117,121,64,69,145,1,60,151,118,197,172,96,226,228,48,40,194,51,153,221,161,158,30,98,22,57,44,113,174,146,175,\r
- 7,135,242,41,179,198,23,15,183,137,90,51,69,14,121,206,146,163,71,138,236,158,145,83,183,155,178,228,147,136,92,77,221,84,138,237,49,170,182,229,105,137,101,39,38,142,186,180,101,202,84,185,10,121,41,181,37,24,223,130,54,198,8,195,200,13,74,223,150,40,\r
- 7,102,17,154,176,78,86,44,78,25,226,81,184,32,185,133,166,51,101,139,29,43,198,218,22,234,183,100,43,231,89,161,222,190,4,21,64,149,167,76,122,31,133,177,89,239,246,213,118,43,166,210,178,101,21,216,213,193,86,68,73,85,133,218,227,178,163,114,17,16,86,\r
- 229,220,103,143,24,80,153,11,79,107,131,219,54,36,149,141,148,37,148,72,36,33,90,35,15,30,90,135,225,71,253,173,216,227,161,46,139,114,97,89,103,135,132,39,136,113,201,222,156,120,175,144,163,94,31,74,57,180,40,115,1,150,40,178,173,45,178,5,157,45,75,\r
- 61,203,76,97,11,71,80,52,28,28,94,30,11,98,252,38,82,55,200,207,141,196,250,168,4,139,8,167,28,181,42,231,69,68,43,121,58,37,26,93,19,28,16,126,236,73,25,214,90,113,120,124,202,178,56,229,242,148,163,44,56,252,150,70,182,97,55,165,30,215,69,169,48,245,\r
- 32,15,198,243,66,221,221,232,173,110,166,37,130,54,100,153,81,134,88,176,55,89,167,52,160,26,93,167,188,142,82,129,126,176,98,98,99,104,239,201,232,11,198,149,191,22,247,193,179,90,35,61,122,153,99,145,126,53,49,200,130,210,210,187,205,190,8,66,48,11,\r
- 145,27,222,177,90,70,245,56,25,161,254,126,202,19,239,39,161,96,120,73,48,26,111,193,130,80,142,54,180,90,225,101,118,119,42,29,143,240,139,24,54,138,188,190,180,13,71,45,202,150,234,197,234,42,67,25,104,108,125,48,60,128,189,31,194,81,178,197,66,99,\r
- 241,38,59,158,8,226,56,69,106,124,117,52,136,179,149,198,134,226,109,17,156,109,203,134,162,216,239,210,5,151,217,65,172,96,55,234,142,235,213,36,215,22,107,120,137,232,79,241,150,211,188,229,228,36,19,90,251,196,140,58,194,50,154,229,192,7,172,152,232,\r
- 222,42,220,55,200,12,91,61,9,114,134,45,187,55,209,71,78,221,85,102,147,105,11,63,113,217,214,182,85,66,201,176,147,161,35,219,78,223,174,206,72,167,136,65,100,70,194,221,125,242,115,27,229,71,236,228,27,209,18,25,131,176,159,70,76,75,173,120,34,22,25,\r
- 22,142,51,98,212,206,149,86,50,233,93,165,35,166,214,224,160,149,156,47,181,7,211,242,203,201,31,93,69,107,34,18,141,194,84,140,80,33,251,113,194,197,19,157,183,225,91,219,40,39,146,254,6,65,185,145,81,49,158,178,35,182,220,12,50,124,80,102,196,78,58,\r
- 118,142,84,91,6,194,137,80,84,44,137,124,132,115,102,136,163,67,22,69,142,214,208,37,86,50,72,162,38,181,180,178,38,103,68,45,184,75,201,139,81,110,0,81,63,129,24,230,136,74,199,118,71,131,49,228,148,97,34,39,58,202,189,29,81,25,245,203,163,145,232,64,\r
- 248,180,113,158,197,200,21,83,239,164,84,21,179,122,133,111,196,78,255,186,74,101,49,171,31,67,85,195,95,109,159,112,200,57,98,50,98,26,113,43,65,185,113,17,91,83,47,139,148,141,103,57,137,194,83,169,56,253,169,73,13,90,238,30,81,44,237,78,47,139,53,\r
- 39,61,146,74,240,116,202,183,57,26,19,79,6,201,117,161,180,168,87,122,74,179,184,76,7,113,122,198,85,216,148,14,156,19,31,21,46,221,201,199,176,234,211,5,161,112,120,85,36,33,221,33,59,142,13,147,12,80,40,136,167,84,244,64,102,225,104,170,95,184,42,34,\r
- 25,94,54,242,88,18,87,189,105,26,105,75,143,212,148,199,144,153,232,11,197,201,41,62,39,6,180,156,1,171,56,148,12,212,4,85,76,68,198,64,162,103,158,140,253,108,144,28,131,50,106,184,164,88,221,67,166,120,75,162,60,241,153,238,92,153,194,208,22,89,23,\r
- 183,200,51,120,210,105,49,24,138,37,6,130,97,125,190,185,7,71,166,130,109,35,54,68,124,40,0,102,128,122,48,19,204,34,54,76,223,52,57,237,229,174,220,246,90,186,199,100,183,112,87,57,207,122,150,15,149,111,54,232,151,172,228,141,149,244,144,201,175,229,\r
- 176,231,210,163,38,187,142,185,202,159,228,151,148,191,111,208,245,172,166,246,38,7,209,115,166,113,11,143,111,115,229,62,90,65,191,229,140,80,85,35,253,142,147,107,122,135,193,223,103,57,215,26,236,93,86,80,55,244,145,65,215,48,190,185,145,229,231,135,\r
- 26,121,188,220,65,141,44,203,137,242,92,117,128,207,217,200,87,110,171,165,95,112,118,187,104,237,68,121,8,85,230,222,79,175,40,209,104,92,205,126,207,126,204,92,211,249,179,212,192,63,101,219,248,51,108,219,16,127,227,210,215,118,49,238,112,47,170,109,\r
- 172,107,108,60,187,195,160,237,204,125,153,193,174,100,179,27,239,170,52,140,95,176,0,43,30,19,24,111,240,167,24,103,249,197,14,206,207,71,87,28,204,97,56,221,124,218,1,135,219,73,78,230,228,78,163,166,134,15,78,119,240,26,30,159,78,115,85,23,230,242,\r
- 219,249,29,82,49,133,242,85,254,181,209,214,148,226,72,38,239,23,143,215,137,46,127,161,140,6,33,86,210,97,131,239,227,119,10,251,235,38,12,180,75,76,25,189,100,136,207,47,152,124,224,82,200,29,38,27,128,120,215,16,2,37,111,150,207,215,149,209,167,134,\r
- 202,176,91,101,56,46,51,208,141,6,59,138,133,89,185,178,182,125,101,123,29,125,158,93,38,75,221,107,240,27,249,143,24,10,150,214,210,219,140,237,130,186,139,21,229,249,104,15,231,79,136,199,242,157,124,76,57,239,47,231,121,13,117,43,45,62,176,226,66,\r
- 62,188,130,30,228,198,19,108,135,76,231,249,215,240,88,249,222,142,205,187,12,199,110,206,253,214,57,116,175,46,155,187,211,87,182,151,238,54,28,151,63,205,190,196,63,100,151,160,35,251,13,243,54,126,55,123,129,253,15,210,23,236,108,167,91,84,171,59,\r
- 249,19,84,206,31,252,124,249,74,35,51,206,155,13,215,245,220,224,143,210,70,190,112,58,43,200,11,40,60,205,70,214,51,140,47,104,52,178,143,177,57,11,24,51,220,15,50,94,203,202,114,206,113,184,29,217,51,28,89,155,157,238,58,86,80,196,47,109,104,116,102,\r
- 47,96,229,99,132,125,180,145,47,103,229,185,244,136,193,110,197,12,251,12,182,139,7,152,183,136,103,79,199,40,43,12,218,201,106,199,59,72,42,211,38,56,232,245,64,13,253,196,96,207,161,139,244,170,193,134,92,185,161,50,58,206,216,13,40,252,152,65,7,89,\r
- 121,221,230,149,67,155,198,238,36,94,201,110,228,37,62,94,197,35,166,247,25,86,156,195,39,194,80,230,42,102,197,11,139,51,139,151,22,243,226,154,98,83,229,170,144,185,224,143,197,231,166,242,231,242,9,34,63,43,25,175,20,94,82,94,82,65,156,153,238,221,\r
- 62,230,157,124,229,118,243,80,217,20,118,188,140,177,67,229,140,125,0,142,141,71,50,203,230,108,183,111,218,246,237,230,193,138,233,236,181,10,50,156,148,43,74,48,111,45,202,28,168,100,187,124,207,139,143,163,226,99,71,21,227,183,131,199,170,200,89,82,\r
- 154,239,133,135,123,213,191,153,200,124,180,10,89,30,152,140,143,103,196,199,17,241,177,99,10,62,246,139,143,131,83,204,171,56,49,32,164,75,235,127,47,133,192,13,206,98,135,166,96,201,171,25,59,80,109,176,7,170,139,216,51,208,143,128,47,78,101,108,63,\r
- 184,31,28,6,123,106,24,251,54,56,8,158,1,7,166,97,232,224,139,211,25,123,13,188,92,203,216,243,117,204,220,237,103,230,1,63,210,252,14,182,127,22,99,247,204,230,236,167,224,240,108,79,218,239,7,146,50,249,119,57,226,251,234,228,223,230,136,239,177,147,\r
- 127,159,147,252,93,169,248,27,29,241,29,118,242,239,116,156,52,242,183,58,134,71,127,191,157,139,58,125,234,247,66,27,160,59,125,42,143,248,255,103,204,163,236,226,255,156,113,159,106,87,252,109,143,161,243,139,255,247,101,250,212,239,37,166,214,171,\r
- 95,84,136,178,242,255,173,121,84,95,197,223,17,253,31,67,245,215,66,128,52,0,0,0,0 };\r
+{ 31,139,8,8,136,16,72,99,0,3,74,97,118,97,68,101,120,66,121,116,101,67,111,100,101,46,100,101,120,0,165,155,11,124,220,85,149,199,207,253,255,255,51,147,76,38,201,100,242,108,155,180,147,52,208,36,52,201,36,233,35,33,45,180,77,90,154,52,109,98,51,13,52,\r
+ 97,23,38,201,36,153,118,242,159,233,204,36,77,4,165,101,89,169,110,113,1,43,139,80,21,177,160,235,11,84,240,193,178,187,40,42,174,136,128,143,69,87,101,169,139,90,21,92,20,20,151,5,187,191,115,239,157,201,164,15,89,119,147,207,119,206,185,231,62,254,\r
+ 247,113,238,185,247,159,199,120,120,206,29,104,91,75,23,61,245,207,167,202,99,239,248,192,190,187,191,252,216,84,255,10,199,175,90,191,95,180,235,111,191,112,251,209,245,68,113,34,154,27,90,227,35,253,245,240,58,162,181,66,217,59,65,183,131,104,27,100,\r
+ 192,73,180,156,203,230,18,93,15,57,229,38,114,112,186,128,40,85,71,84,81,72,244,53,20,248,58,120,28,124,27,124,15,252,24,156,4,191,1,111,128,194,21,68,171,64,19,104,1,107,193,70,176,9,116,131,237,96,7,232,7,54,184,17,188,11,188,27,220,10,110,3,119,130,\r
+ 187,192,61,224,31,193,203,160,192,79,84,15,186,193,56,184,1,220,7,254,5,252,4,188,10,242,171,137,58,192,229,32,14,142,130,207,131,111,130,159,129,229,53,68,151,130,4,184,23,60,11,10,86,162,143,32,4,110,6,79,131,37,181,68,65,112,16,188,31,124,9,156,4,\r
+ 214,5,68,43,193,70,48,0,82,224,14,112,31,248,54,248,25,112,92,136,250,96,59,24,7,215,128,163,224,3,224,4,248,12,120,16,60,10,158,6,223,3,63,2,207,129,83,224,215,224,119,224,53,64,171,208,30,200,5,5,160,24,84,128,229,160,6,52,128,70,208,10,218,193,70,\r
+ 208,13,122,193,46,48,8,70,192,40,152,0,251,192,219,193,123,192,7,193,199,193,231,193,163,224,73,240,67,240,115,240,50,56,13,60,88,247,101,160,5,116,128,109,96,0,236,7,179,96,30,28,5,199,192,113,112,2,124,18,60,0,190,4,190,5,158,5,191,7,142,122,140,1,\r
+ 148,130,86,208,14,54,131,110,176,3,76,131,57,112,29,184,9,220,1,62,6,30,3,63,5,47,1,209,128,241,131,85,160,5,108,4,59,192,16,216,15,230,192,77,224,78,112,47,248,60,248,42,248,22,120,6,60,15,126,15,156,23,97,92,160,1,92,12,174,0,127,9,198,193,36,56,12,\r
+ 110,5,39,192,231,192,87,193,119,193,73,240,42,200,89,141,53,6,117,96,45,232,5,65,48,13,14,130,183,129,67,224,40,184,5,220,13,62,13,190,12,158,0,63,4,63,5,47,130,255,2,102,35,214,20,212,131,86,176,3,12,131,16,136,131,89,240,118,240,14,240,78,240,183,224,\r
+ 118,112,55,184,31,124,1,252,19,248,10,120,6,188,0,254,8,138,154,176,15,193,102,16,4,211,96,6,220,0,142,129,187,193,39,193,195,224,171,224,73,240,44,120,1,188,2,222,0,174,102,172,27,88,10,234,65,0,244,131,81,16,6,54,184,21,220,9,238,1,143,130,111,128,\r
+ 39,193,191,131,23,129,51,64,84,6,106,193,37,96,15,72,128,235,192,187,193,29,224,99,224,11,224,49,240,12,248,25,160,22,212,5,30,80,2,42,65,13,88,5,26,193,122,112,49,216,12,122,193,0,8,129,40,120,59,184,9,188,15,28,7,31,4,31,6,31,1,31,7,247,129,207,130,\r
+ 60,60,6,33,142,138,64,37,168,34,21,7,17,114,8,33,133,16,54,8,97,130,16,22,8,33,128,176,197,73,111,77,130,91,19,220,146,224,82,4,183,32,44,37,97,218,9,211,70,205,28,83,213,16,168,21,180,129,53,96,45,64,8,38,132,102,106,7,29,224,98,29,139,55,128,141,224,\r
+ 18,112,41,216,4,54,131,45,160,139,99,53,216,74,42,94,95,6,182,131,30,208,11,118,128,62,176,11,188,5,140,3,27,196,72,197,250,3,164,198,154,254,242,104,233,173,82,227,23,233,180,214,217,206,115,98,104,187,79,235,21,176,151,66,58,181,189,2,228,240,92,105,\r
+ 123,129,182,151,234,182,210,122,73,150,94,174,245,50,176,68,63,107,137,214,235,116,59,75,179,218,231,53,9,84,41,157,215,162,93,151,169,207,106,103,181,110,167,92,235,155,170,84,27,172,111,135,190,76,175,203,128,110,135,245,43,116,59,1,221,14,151,225,\r
+ 181,186,90,247,135,215,107,170,74,205,231,90,93,38,168,117,126,214,30,173,199,161,15,105,157,159,123,185,214,175,133,126,133,214,143,66,223,171,245,219,161,15,107,253,4,244,17,173,127,2,250,149,90,255,2,244,191,208,250,35,208,175,210,250,215,179,236,\r
+ 79,101,233,223,135,30,210,250,115,89,246,23,178,244,87,178,244,215,179,218,180,150,47,216,61,89,122,9,244,171,181,94,153,101,127,189,114,65,231,181,248,75,173,111,207,106,179,54,171,60,207,243,168,214,87,195,62,166,245,53,89,101,186,179,244,190,229,202,\r
+ 127,215,233,57,15,107,61,8,251,132,214,175,204,210,167,160,79,106,61,5,125,74,235,215,66,143,104,253,8,244,253,90,63,6,125,159,214,143,103,217,217,247,162,90,63,1,251,180,214,31,200,42,255,200,114,222,59,130,254,154,148,172,22,28,55,234,232,58,82,242,\r
+ 235,82,10,122,92,203,39,180,252,150,150,79,106,249,148,46,255,67,226,88,83,67,203,133,146,171,4,199,157,117,244,111,196,178,154,86,8,142,65,42,191,90,231,87,35,167,65,240,94,168,160,183,17,75,131,254,69,202,106,250,129,148,43,232,121,41,215,209,107,82,\r
+ 230,209,27,196,49,44,32,247,45,75,151,148,235,200,173,211,249,82,10,218,173,211,131,188,86,216,97,253,196,247,192,11,201,33,120,207,59,233,46,98,89,70,247,67,230,98,135,89,82,174,39,55,242,221,136,132,156,206,211,246,60,60,37,79,240,60,169,180,23,37,\r
+ 63,34,101,35,25,130,227,139,65,31,32,150,229,244,33,82,233,191,215,242,211,196,49,71,229,179,252,160,148,22,157,208,233,143,75,105,210,39,72,197,166,79,106,249,41,41,5,125,78,203,207,179,31,163,252,61,82,94,68,15,18,239,249,85,178,63,165,136,182,175,\r
+ 72,185,129,126,39,101,37,253,129,56,134,4,232,176,150,57,130,227,69,7,253,43,113,76,200,167,159,74,137,241,8,142,47,106,92,203,16,237,89,46,71,196,126,76,202,213,84,32,88,110,161,10,185,174,109,50,127,5,102,226,22,41,151,208,109,58,253,119,82,118,210,\r
+ 105,185,222,45,178,156,31,237,254,150,120,157,85,189,106,216,19,90,38,165,244,82,74,202,165,180,68,40,185,84,250,67,157,44,95,131,21,155,145,178,149,102,165,236,166,131,82,150,208,156,150,243,82,118,209,91,165,92,74,55,104,249,78,41,47,166,119,75,89,\r
+ 69,239,145,114,37,189,79,202,98,58,46,101,1,189,95,74,39,125,88,251,223,61,58,255,94,41,219,233,163,82,186,233,62,237,127,159,209,229,62,43,101,14,61,32,165,90,15,120,55,125,81,63,239,33,45,255,65,203,135,181,95,255,163,148,126,250,39,237,223,255,172,\r
+ 243,31,209,245,191,164,229,151,181,124,84,202,26,250,138,148,151,208,87,165,236,160,239,105,249,140,148,23,208,41,41,107,233,23,90,254,82,203,95,233,252,23,116,250,69,45,127,45,101,33,253,167,148,245,244,146,148,205,244,27,41,55,211,203,82,42,191,170,\r
+ 209,126,197,233,223,235,253,248,170,148,202,207,184,252,127,73,121,41,9,185,126,107,201,163,101,190,148,77,228,149,114,25,249,164,92,67,197,58,93,162,203,149,106,89,166,243,203,133,154,151,58,193,251,88,249,103,61,60,248,99,82,110,165,239,202,125,109,\r
+ 208,183,165,244,209,133,130,207,66,85,174,9,59,239,110,226,243,208,164,119,73,105,208,179,196,103,98,41,125,135,248,14,179,84,251,177,58,219,211,103,52,94,25,233,1,156,9,87,235,67,210,175,237,124,198,242,89,193,249,223,132,188,78,231,87,235,250,77,89,\r
+ 245,127,132,252,91,117,62,159,241,69,164,206,102,171,74,229,191,128,252,135,116,254,74,157,159,174,159,163,229,189,8,208,187,215,170,123,202,27,56,188,173,181,234,46,83,160,109,43,33,27,128,169,243,215,64,191,68,151,185,76,218,77,169,127,174,69,181,57,\r
+ 34,220,20,247,242,211,70,140,60,248,124,14,90,225,119,226,47,181,168,187,159,79,4,71,221,116,192,187,14,246,60,163,12,83,211,98,24,86,135,97,145,203,91,68,193,209,60,58,224,175,198,206,245,16,151,11,142,169,178,38,229,89,7,6,218,105,203,140,219,232,48,\r
+ 94,60,109,123,121,188,46,111,221,207,45,253,252,103,90,212,253,170,6,51,30,247,30,150,163,229,103,115,191,79,182,168,51,242,124,207,54,169,72,248,124,109,171,150,156,253,204,64,7,109,113,120,176,55,95,194,51,121,223,187,133,237,175,71,44,247,136,186,\r
+ 159,157,93,250,98,89,186,238,23,28,199,45,217,159,87,91,212,221,56,24,87,229,56,167,204,144,119,92,163,3,101,124,216,23,193,3,238,236,124,67,220,32,222,235,186,247,160,179,19,35,115,83,221,75,38,250,203,99,180,90,213,186,142,248,242,49,198,107,97,243,\r
+ 209,149,94,143,188,63,230,32,197,99,205,111,85,247,164,98,103,9,213,24,30,148,227,89,8,38,243,41,216,86,64,182,247,50,148,242,136,14,177,97,193,230,223,1,239,88,40,209,141,18,110,115,55,46,238,187,47,16,244,233,224,45,100,90,107,175,94,74,123,146,152,\r
+ 7,179,140,124,230,149,208,210,229,131,169,124,244,187,21,35,241,88,220,127,75,206,195,122,234,114,112,249,14,211,69,235,175,118,144,175,152,235,240,179,150,192,147,109,111,5,143,236,140,103,212,125,139,215,146,125,174,29,99,40,148,227,44,208,227,228,\r
+ 40,22,247,55,98,7,140,120,65,113,161,190,127,11,57,47,219,81,158,247,88,220,203,111,12,5,25,251,64,198,190,70,218,13,125,99,191,162,85,249,115,208,91,40,247,4,123,16,63,247,234,86,117,199,15,250,11,209,71,126,83,192,56,171,189,232,245,114,60,185,32,83,\r
+ 110,242,188,229,86,200,114,5,240,120,30,137,141,114,28,51,124,46,95,89,220,191,20,231,116,141,149,135,222,56,209,171,145,99,101,72,85,83,28,47,135,199,114,71,142,21,35,181,2,169,58,153,42,65,187,93,88,107,143,181,212,113,45,218,197,10,66,95,97,85,160,\r
+ 94,17,85,90,14,216,230,113,174,187,173,118,107,156,86,184,57,141,119,66,26,62,238,131,150,194,73,117,229,157,165,208,166,113,151,179,253,182,252,140,225,60,170,65,155,113,47,143,189,216,42,161,149,155,215,35,150,241,109,219,246,91,232,121,144,251,228,\r
+ 192,254,245,59,136,91,116,225,169,62,211,246,190,77,247,164,80,248,46,92,57,209,129,241,140,230,84,209,206,28,167,203,87,94,153,147,39,53,59,48,71,65,167,199,108,55,75,200,103,248,106,87,118,95,76,62,199,1,239,53,152,7,143,115,167,211,114,248,74,125,\r
+ 82,218,129,67,244,30,235,128,244,100,143,101,251,221,116,140,61,195,203,190,206,99,84,99,57,70,117,119,228,91,117,47,130,95,129,95,128,239,128,167,225,40,153,247,34,245,117,232,82,250,179,210,103,126,169,124,190,131,151,97,111,242,30,247,242,58,155,23,\r
+ 221,37,26,62,32,90,142,11,163,249,132,104,188,91,144,142,52,68,63,214,254,51,232,247,201,152,108,201,40,72,244,124,218,223,2,131,84,109,22,96,255,59,100,236,123,177,85,253,92,48,190,39,74,213,93,110,233,219,233,58,175,165,243,2,91,81,199,35,253,49,157,\r
+ 103,182,165,243,54,103,242,92,242,70,137,153,211,121,179,206,43,100,148,224,54,29,58,6,44,107,83,251,103,112,147,47,43,214,152,152,101,182,196,3,253,184,137,213,189,182,48,158,149,186,45,126,39,28,198,152,10,116,31,248,171,190,77,157,3,62,236,149,28,\r
+ 216,184,92,91,155,42,59,56,112,86,251,176,196,47,31,32,71,72,175,47,241,250,14,80,221,203,233,189,119,73,91,122,239,149,232,119,101,101,239,214,246,61,222,82,217,119,67,239,225,222,54,146,247,109,219,219,35,199,41,99,38,250,226,163,186,63,154,186,143,\r
+ 3,109,250,204,146,245,212,219,247,112,150,205,169,207,129,209,55,153,151,157,122,94,210,229,163,111,82,126,87,102,30,85,63,102,207,209,143,67,231,176,29,201,178,89,250,89,55,183,169,51,222,39,248,134,48,18,48,72,73,147,246,182,32,126,190,180,55,224,162,\r
+ 189,1,167,182,230,98,15,192,11,188,123,3,22,242,115,228,237,38,30,168,37,191,40,210,227,229,117,250,96,155,58,243,207,221,255,224,150,50,138,239,190,156,172,183,212,253,129,253,202,148,190,251,247,231,173,211,182,245,244,105,57,238,77,155,200,10,113,\r
+ 29,55,158,195,103,254,231,218,212,253,35,120,168,8,235,228,39,206,105,71,79,7,15,35,26,121,249,13,198,141,40,82,194,210,178,177,190,144,14,27,167,125,46,229,57,93,135,102,115,250,180,127,241,154,186,241,44,246,239,71,219,212,187,163,207,59,152,64,79,\r
+ 248,172,22,56,171,133,58,49,87,231,240,207,55,56,199,246,22,232,246,242,89,58,93,7,196,13,179,206,183,96,126,235,94,140,5,150,209,141,185,56,65,79,217,222,13,24,97,29,191,224,25,106,156,252,243,140,37,90,22,107,60,250,204,62,217,166,126,246,228,163,193,\r
+ 235,241,108,167,124,182,179,67,152,120,114,71,110,46,158,153,135,72,225,22,190,154,214,106,23,197,54,85,210,237,15,225,41,191,181,113,22,231,225,116,109,23,124,67,81,186,237,127,59,251,173,131,91,226,62,230,113,31,15,139,99,170,143,62,111,221,51,106,\r
+ 238,121,189,78,183,169,251,219,226,185,87,35,102,27,143,213,73,110,35,190,123,55,86,13,117,127,71,58,26,224,220,95,179,224,83,185,58,238,84,173,81,107,25,187,162,138,130,179,217,173,182,227,153,202,135,103,225,195,92,167,80,175,101,19,234,84,162,161,\r
+ 193,167,81,218,228,145,11,83,206,186,40,20,182,151,207,93,119,46,175,93,1,229,185,190,119,203,105,186,72,252,94,122,109,221,111,6,191,237,131,180,253,197,184,239,240,58,151,112,89,7,175,119,1,143,249,233,217,156,32,143,184,168,238,71,111,94,114,72,149,\r
+ 124,236,205,75,238,65,73,219,203,49,203,157,231,43,90,191,172,129,124,213,43,43,219,17,119,182,209,19,228,91,186,246,161,106,226,86,184,141,79,113,27,254,50,150,194,231,232,118,120,28,215,239,249,90,169,237,47,87,150,178,110,167,199,121,253,196,215,202,\r
+ 210,237,126,223,237,22,117,207,161,31,127,133,55,7,188,108,62,120,203,73,183,200,233,112,87,208,255,118,4,245,52,113,58,187,63,255,151,158,112,75,117,63,252,243,123,16,212,61,184,224,255,221,131,160,236,1,150,89,184,164,175,177,111,113,28,106,214,146,\r
+ 227,23,191,155,38,165,239,25,242,238,115,207,26,245,174,129,62,226,254,224,34,143,177,212,196,45,187,100,101,55,238,15,142,81,39,238,15,242,46,48,71,173,22,223,71,93,232,119,62,246,63,120,221,231,91,89,131,219,131,201,183,135,28,220,9,118,90,134,201,\r
+ 183,134,3,70,221,175,243,141,186,23,192,47,193,41,246,247,34,244,109,153,220,187,136,122,70,115,89,99,133,121,81,93,195,106,254,85,71,38,222,62,157,181,55,76,109,253,193,26,117,151,110,55,92,196,51,146,64,137,2,242,109,170,251,111,30,159,138,201,255,\r
+ 177,70,197,1,190,139,241,173,121,169,241,180,188,139,85,227,105,43,48,239,237,136,30,182,247,58,236,80,183,216,40,138,49,219,118,96,21,5,48,226,94,89,222,14,92,72,94,43,216,82,140,27,114,64,182,159,206,241,25,118,224,2,242,26,42,175,133,231,247,183,11,\r
+ 247,217,63,172,73,223,91,175,149,189,230,223,35,242,87,250,231,205,60,182,90,216,86,107,123,250,171,253,140,244,246,51,210,92,191,76,175,87,49,158,80,168,109,105,106,180,204,33,117,230,151,232,254,84,106,123,181,150,134,166,70,207,101,19,93,44,237,1,\r
+ 109,15,224,148,86,82,200,113,8,253,237,160,133,243,222,208,253,72,159,243,86,70,23,186,125,67,231,187,228,207,224,149,109,157,44,107,102,234,231,103,234,178,116,234,60,39,173,147,249,108,115,105,153,171,165,71,215,45,144,189,163,204,28,20,103,198,188,\r
+ 78,143,173,70,218,249,12,114,72,153,30,133,42,191,94,203,118,93,79,232,187,23,203,124,221,15,214,139,50,249,69,89,99,204,207,140,125,73,166,63,170,109,159,126,94,77,166,36,233,159,79,169,210,130,212,190,18,117,228,104,105,10,52,97,20,27,200,185,33,98,\r
+ 71,82,151,144,113,73,39,21,108,30,24,232,235,233,218,28,236,233,223,117,85,79,55,185,183,236,233,233,235,190,42,184,119,96,43,121,183,204,68,162,227,93,49,123,34,50,217,180,47,52,27,162,178,174,216,116,60,102,135,237,212,64,56,156,24,138,132,15,42,187,\r
+ 163,123,235,150,61,151,145,216,70,198,182,30,114,110,235,219,60,212,191,155,68,15,25,61,245,0,119,177,94,50,122,251,168,170,119,102,44,188,121,108,44,156,76,70,70,35,209,72,106,126,87,108,60,60,144,136,205,70,198,195,9,42,223,17,158,31,141,133,18,227,\r
+ 221,145,228,116,36,153,236,139,36,83,97,27,25,162,143,140,62,180,214,135,102,250,250,200,236,67,2,31,189,252,209,71,101,125,33,123,60,17,139,140,55,135,226,241,230,205,99,169,200,44,90,238,164,53,139,237,241,120,52,50,22,74,69,98,118,109,186,76,95,100,\r
+ 34,60,54,63,22,13,119,133,162,209,209,208,216,254,100,39,45,57,95,173,236,172,177,152,141,158,165,154,187,88,206,165,178,179,38,19,161,248,84,100,44,217,220,21,178,103,67,104,112,249,57,178,98,209,88,98,91,36,154,10,39,206,159,191,51,148,74,68,230,58,\r
+ 169,254,79,230,47,106,170,226,236,162,3,161,136,141,254,149,159,157,179,59,60,134,140,226,76,70,44,217,188,101,198,30,143,134,59,169,36,219,216,179,37,98,143,115,235,13,25,235,44,86,190,185,107,42,150,8,199,100,115,225,68,237,182,68,104,58,51,141,157,\r
+ 84,249,39,202,102,247,70,230,98,217,183,206,134,185,155,75,23,103,236,140,241,196,235,188,250,197,121,236,125,181,253,246,182,216,216,76,178,107,42,100,79,134,211,238,146,61,168,76,209,236,201,201,24,47,75,196,102,226,157,180,238,236,156,96,34,28,238,\r
+ 31,77,134,19,179,24,91,191,125,89,52,54,26,138,246,133,230,99,51,169,133,199,172,248,211,245,58,169,101,113,129,80,182,231,55,47,218,7,59,67,118,104,146,171,180,254,175,171,240,214,233,177,39,98,103,245,255,77,234,164,183,91,39,53,45,174,23,177,227,51,\r
+ 169,233,112,106,42,54,222,188,37,148,68,227,72,195,195,109,56,138,244,255,11,206,95,126,235,120,36,21,75,168,238,52,156,191,216,89,77,54,190,73,217,157,82,207,204,206,165,125,99,177,233,230,196,116,50,218,188,15,161,164,249,172,120,84,251,39,35,76,39,\r
+ 109,123,211,6,206,19,131,106,23,175,108,199,255,181,157,78,170,126,179,170,157,84,43,139,192,217,18,144,241,144,61,223,60,59,26,13,217,251,155,179,34,114,39,213,244,141,135,162,179,145,253,205,33,219,142,165,100,140,106,222,106,143,69,99,201,136,61,217,\r
+ 21,13,37,101,240,57,187,76,15,166,63,161,243,171,207,145,191,51,60,61,170,11,132,81,164,234,28,69,6,35,147,118,40,53,147,8,243,182,226,35,160,25,221,155,196,54,15,37,6,195,7,102,194,246,24,114,138,178,115,212,227,106,178,76,61,209,104,120,50,20,85,139,\r
+ 181,117,110,44,28,87,46,81,123,142,50,137,201,153,105,204,80,86,169,226,236,82,8,194,147,106,106,23,140,187,98,131,51,99,83,202,127,178,234,249,178,138,244,143,238,147,49,176,42,203,54,24,30,155,73,192,109,206,83,101,16,49,215,158,100,191,93,176,37,194,\r
+ 19,81,180,131,110,204,198,212,81,17,12,37,38,195,217,189,93,122,142,226,170,107,157,84,170,242,102,82,145,104,243,230,68,34,52,207,174,210,73,133,89,102,182,144,247,12,67,39,89,242,152,246,100,123,38,137,33,242,12,109,221,61,200,231,121,87,127,247,214,\r
+ 133,212,174,205,59,183,146,49,212,67,142,161,30,124,65,237,37,231,80,111,207,182,109,189,100,65,114,70,47,103,152,67,189,210,194,39,237,80,239,48,10,178,194,167,237,144,52,245,13,35,183,111,24,103,241,208,48,90,24,150,173,137,97,50,161,145,133,143,62,\r
+ 86,251,200,49,220,203,186,5,129,243,123,152,173,56,183,157,195,125,210,236,96,9,251,8,46,13,35,61,228,27,57,219,91,138,71,206,177,88,110,21,222,106,3,129,64,70,111,201,210,91,179,244,182,44,125,77,150,190,54,75,95,151,165,175,207,210,219,161,231,41,125,\r
+ 91,52,52,153,164,252,69,113,149,74,66,231,136,223,228,12,201,192,198,53,89,246,133,70,195,81,202,9,233,251,6,45,9,141,143,159,251,52,161,220,144,118,242,36,137,81,42,226,99,116,203,76,42,21,179,7,18,120,76,120,156,156,163,49,36,167,33,229,41,77,206,49,\r
+ 121,193,32,215,152,60,253,198,201,129,139,76,40,65,121,99,28,241,98,56,246,55,167,56,145,185,42,80,129,76,4,19,33,59,57,17,75,76,83,25,162,75,83,86,148,105,82,81,134,242,249,122,131,123,67,82,182,130,7,168,91,14,30,16,155,65,122,217,88,34,28,74,157,29,\r
+ 101,57,250,147,53,30,153,152,32,215,120,76,94,8,72,132,201,17,230,243,155,252,19,184,70,156,179,78,114,203,124,144,155,207,229,18,242,60,39,199,132,20,158,137,133,211,125,156,242,100,138,35,100,207,56,21,76,112,251,193,200,116,120,87,200,142,37,105,25,\r
+ 54,220,162,214,183,101,21,174,60,51,115,209,181,51,87,230,202,101,43,204,168,59,67,201,253,120,102,41,27,22,238,128,250,190,71,249,48,115,176,195,194,134,19,73,202,225,36,251,44,185,89,211,133,60,28,3,120,236,220,75,249,148,237,225,200,228,84,138,138,\r
+ 161,202,211,45,187,143,121,210,152,76,133,16,59,101,137,62,29,76,250,237,65,76,120,216,150,237,33,104,132,6,17,132,85,123,42,132,200,94,203,165,66,212,150,43,228,89,48,160,101,23,82,187,67,7,175,72,43,123,229,179,118,199,98,41,126,52,121,145,24,156,135,\r
+ 23,78,15,34,132,68,240,244,2,88,246,216,17,246,35,30,164,236,205,153,151,27,57,5,67,145,204,118,224,58,151,99,253,98,7,131,177,253,232,108,101,38,45,11,69,195,56,7,227,209,208,188,114,11,11,185,87,200,207,189,36,166,168,2,43,12,151,94,180,68,219,99,252,\r
+ 148,66,157,19,143,15,132,102,120,23,120,51,134,221,225,36,246,75,198,178,37,179,97,40,95,89,186,181,15,234,36,14,228,238,216,65,108,205,76,114,79,156,74,50,9,121,88,111,143,140,143,163,243,250,169,59,99,120,164,172,179,200,144,8,77,166,219,148,6,52,163,\r
+ 219,148,151,109,42,214,137,112,130,119,153,246,172,156,169,80,82,249,118,249,20,188,110,48,54,161,93,32,17,155,86,243,132,34,168,45,119,130,53,21,67,192,23,17,114,195,115,250,229,25,146,36,51,50,61,77,133,252,234,22,9,69,187,66,241,228,78,172,15,229,\r
+ 107,195,96,56,186,213,30,207,228,35,9,55,73,96,83,201,43,85,112,62,30,38,143,84,175,82,215,43,202,193,195,134,66,209,25,4,146,8,14,174,253,97,60,44,153,113,192,156,72,178,63,30,194,73,78,75,34,201,96,12,39,233,214,185,56,130,135,244,200,173,118,8,11,\r
+ 58,142,182,147,122,113,201,181,63,60,223,197,253,41,223,127,158,119,184,252,116,198,224,20,207,168,35,42,67,99,62,92,34,156,224,238,237,194,29,136,172,104,120,34,69,206,104,216,158,76,77,145,83,119,85,216,100,217,188,146,46,59,124,112,23,43,57,118,58,\r
+ 222,120,236,236,173,236,140,141,114,224,34,43,22,29,159,146,159,7,169,40,102,167,223,247,186,100,224,26,167,226,5,83,119,56,153,74,196,230,217,143,22,140,218,215,178,106,166,157,109,217,130,105,48,52,27,78,207,151,218,146,89,229,229,228,47,110,98,48,\r
+ 21,139,199,97,42,71,24,145,253,56,227,50,140,206,219,240,173,131,148,31,203,126,171,161,130,216,162,3,131,60,49,91,238,13,25,90,40,55,102,167,29,59,95,170,59,103,162,169,72,156,151,68,38,225,156,57,124,14,201,170,40,49,24,121,107,56,29,80,209,146,90,\r
+ 90,217,146,51,166,22,220,165,228,85,168,55,131,35,36,133,248,230,136,75,199,118,199,67,9,148,148,81,35,63,190,200,189,29,113,121,84,84,197,99,241,153,232,121,15,135,162,56,252,122,209,155,34,137,4,185,18,234,37,156,106,18,225,73,118,151,196,249,223,207,\r
+ 185,48,78,185,36,92,64,43,87,81,101,34,60,141,9,81,147,212,111,159,113,174,58,18,50,230,154,201,112,138,10,146,28,157,51,47,204,228,65,90,78,53,251,51,149,103,167,122,212,212,200,61,198,213,178,222,70,100,181,190,180,223,82,5,82,231,124,15,165,210,100,\r
+ 58,178,238,137,100,133,202,101,231,52,243,107,64,8,7,118,82,197,90,233,230,249,201,69,49,214,157,78,70,85,159,46,143,68,163,187,98,41,233,52,158,36,182,85,58,140,161,34,82,153,24,131,194,236,142,170,95,184,190,34,27,190,184,144,172,72,170,222,244,44,\r
+ 60,75,143,212,146,7,153,149,154,138,36,201,201,159,181,1,45,91,96,229,99,205,68,75,80,121,34,114,102,82,19,237,242,192,16,179,228,152,149,177,197,37,69,255,4,89,252,126,71,133,252,153,237,130,185,108,8,198,246,96,65,189,179,103,29,49,179,145,68,106,38,\r
+ 20,213,39,164,123,118,97,42,196,65,18,115,100,204,5,64,11,104,5,109,96,13,137,121,122,208,50,232,99,134,171,96,184,145,30,182,196,39,12,87,149,145,247,180,49,87,181,207,164,231,197,210,159,236,160,39,44,227,253,6,236,5,244,29,75,188,79,184,170,30,55,\r
+ 222,90,245,91,147,238,20,141,141,183,58,136,126,98,153,159,48,174,251,43,225,42,120,116,5,189,108,8,66,91,27,232,53,131,92,171,71,76,227,6,35,255,157,166,56,45,74,155,230,94,53,233,61,194,216,183,65,20,21,69,54,24,201,42,7,109,16,121,78,52,96,168,30,\r
+ 24,235,246,26,59,14,54,210,191,27,226,126,126,220,153,242,20,154,44,120,128,94,84,98,163,121,179,120,93,124,67,184,86,27,207,81,167,241,71,113,208,120,74,28,156,51,190,115,205,115,71,132,225,112,111,110,220,208,180,97,195,37,35,38,29,21,238,107,77,113,\r
+ 147,104,223,112,111,181,105,62,39,218,68,121,105,96,185,105,252,88,24,162,168,194,97,204,25,253,232,139,67,56,76,167,219,184,232,132,195,237,36,167,112,26,78,179,161,193,152,93,237,48,26,140,228,106,106,87,125,104,55,238,55,62,45,21,139,149,207,24,159,\r
+ 93,108,205,40,142,116,246,3,156,188,147,251,252,174,74,154,135,216,65,175,152,198,125,198,131,108,191,73,136,227,152,184,163,75,71,232,55,22,242,232,118,158,62,250,165,201,159,119,88,198,97,113,35,178,233,152,37,14,179,252,163,41,37,26,186,71,89,254,\r
+ 166,146,222,157,41,117,151,46,117,68,203,15,153,226,13,44,215,142,29,141,195,59,134,155,232,122,33,142,168,202,143,152,198,61,198,99,92,125,89,35,189,42,196,109,80,143,136,178,66,63,157,48,140,31,112,178,234,70,163,180,202,152,174,50,10,59,155,118,132,\r
+ 141,153,222,43,141,249,94,250,134,97,254,64,220,34,243,141,162,119,24,137,170,219,70,246,29,49,29,168,212,28,190,148,30,209,117,11,110,244,87,222,70,95,52,29,239,20,207,138,187,141,119,25,239,224,206,220,111,90,159,50,190,40,78,137,159,35,181,241,198,\r
+ 97,250,168,122,238,141,198,215,169,202,120,232,186,170,29,102,238,117,70,159,233,250,144,97,26,143,210,94,99,211,106,81,92,24,80,120,251,204,188,147,194,216,184,193,244,28,54,58,54,10,97,186,31,23,70,163,168,204,191,212,225,118,120,90,28,121,251,156,\r
+ 238,38,81,92,102,92,211,185,193,233,217,40,170,74,217,190,216,104,108,19,85,5,244,164,41,62,137,153,247,155,226,184,209,38,124,101,134,103,53,198,185,194,164,247,138,192,114,7,73,165,105,165,131,78,6,26,232,113,83,252,7,247,253,63,77,113,3,100,164,146,\r
+ 142,24,226,195,168,253,21,147,158,16,43,154,246,237,152,187,122,201,141,228,228,197,50,106,197,61,70,69,141,113,129,113,141,229,59,41,202,139,141,85,48,84,186,202,69,121,79,121,97,249,206,114,179,188,181,220,161,74,85,203,82,6,74,13,100,202,151,24,23,\r
+ 114,121,81,225,87,138,81,177,162,162,218,89,126,211,122,167,88,177,222,37,44,81,110,144,33,44,247,205,126,225,171,59,124,200,122,106,121,189,120,105,185,16,79,173,16,226,5,112,202,143,108,225,49,196,205,254,198,67,135,172,7,170,155,196,247,171,201,116,\r
+ 82,1,215,16,190,102,212,57,190,82,28,241,127,147,63,158,231,143,215,87,10,227,88,173,48,30,174,37,231,146,202,34,31,182,131,79,125,175,69,225,231,107,81,228,225,58,124,124,151,63,94,224,143,35,245,248,56,193,31,143,212,59,174,55,72,0,11,184,180,254,231,\r
+ 80,2,220,96,131,248,81,189,16,71,27,132,248,40,120,184,193,20,127,104,40,23,55,95,132,52,248,38,120,14,188,2,78,172,22,226,187,224,20,120,29,220,220,40,196,243,224,246,38,148,3,119,53,99,55,5,132,56,214,34,172,167,192,243,45,200,107,117,136,231,214,97,\r
+ 138,214,27,226,80,187,33,78,180,59,73,80,249,18,145,249,62,200,19,211,81,148,245,123,156,180,76,255,95,26,255,14,33,253,191,105,252,187,133,244,255,167,169,191,177,85,255,163,198,191,87,72,255,159,154,147,22,254,87,205,244,42,157,127,207,36,252,234,255,\r
+ 47,6,160,59,253,170,62,255,157,162,240,42,59,255,109,162,225,87,207,229,255,109,51,117,121,254,251,63,203,175,126,119,196,127,39,232,240,171,254,241,223,22,242,31,55,114,251,242,111,29,189,202,206,255,83,247,63,73,81,207,80,140,55,0,0,0,0 };\r
\r
//==============================================================================\r
#if JUCE_PUSH_NOTIFICATIONS && JUCE_MODULE_AVAILABLE_juce_gui_extra\r
}\r
\r
//==============================================================================\r
+ void handleDoFrameCallback ([[maybe_unused]] int64 frameTimeNanos)\r
+ {\r
+ vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
+ }\r
+\r
void handlePaintCallback (jobject canvas, jobject paint)\r
{\r
auto* env = getEnv();\r
METHOD (isVisible, "isVisible", "()Z") \\r
METHOD (containsPoint, "containsPoint", "(II)Z") \\r
METHOD (showKeyboard, "showKeyboard", "(Ljava/lang/String;)V") \\r
- METHOD (setSystemUiVisibilityCompat, "setSystemUiVisibilityCompat", "(I)V") \\r
+ METHOD (setSystemUiVisibilityCompat, "setSystemUiVisibilityCompat", "(I)V") \\r
+ CALLBACK (handleDoFrameJni, "handleDoFrame", "(JJ)V") \\r
CALLBACK (handlePaintJni, "handlePaint", "(JLandroid/graphics/Canvas;Landroid/graphics/Paint;)V") \\r
CALLBACK (handleMouseDownJni, "handleMouseDown", "(JIFFJ)V") \\r
CALLBACK (handleMouseDragJni, "handleMouseDrag", "(JIFFJ)V") \\r
DECLARE_JNI_CLASS_WITH_BYTECODE (ComponentPeerView, "com/rmsl/juce/ComponentPeerView", 16, javaComponentPeerView, sizeof (javaComponentPeerView))\r
#undef JNI_CLASS_MEMBERS\r
\r
+ static void JNICALL handleDoFrameJni (JNIEnv*, jobject /*view*/, jlong host, jlong frameTimeNanos) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleDoFrameCallback (frameTimeNanos); }\r
static void JNICALL handlePaintJni (JNIEnv*, jobject /*view*/, jlong host, jobject canvas, jobject paint) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handlePaintCallback (canvas, paint); }\r
static void JNICALL handleMouseDownJni (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMouseDownCallback (i, Point<float> ((float) x, (float) y), (int64) time); }\r
static void JNICALL handleMouseDragJni (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMouseDragCallback (i, Point<float> ((float) x, (float) y), (int64) time); }\r
==============================================================================\r
*/\r
\r
+@interface FileChooserControllerClass : UIDocumentPickerViewController\r
+- (void) setParent: (FileChooser::Native*) ptr;\r
+@end\r
+\r
+@interface FileChooserDelegateClass : NSObject<UIDocumentPickerDelegate>\r
+- (id) initWithOwner: (FileChooser::Native*) owner;\r
+@end\r
+\r
namespace juce\r
{\r
\r
\r
class FileChooser::Native : public FileChooser::Pimpl,\r
public Component,\r
- private AsyncUpdater\r
+ public AsyncUpdater,\r
+ public std::enable_shared_from_this<Native>\r
{\r
public:\r
+ static std::shared_ptr<Native> make (FileChooser& fileChooser, int flags)\r
+ {\r
+ std::shared_ptr<Native> result { new Native (fileChooser, flags) };\r
+ /* Must be called after forming a shared_ptr to an instance of this class.\r
+ Note that we can't call this directly inside the class constructor, because\r
+ the owning shared_ptr might not yet exist.\r
+ */\r
+ [result->controller.get() setParent: result.get()];\r
+ return result;\r
+ }\r
+\r
+ ~Native() override\r
+ {\r
+ exitModalState (0);\r
+ }\r
+\r
+ void launch() override\r
+ {\r
+ jassert (shared_from_this() != nullptr);\r
+\r
+ /* Normally, when deleteWhenDismissed is true, the modal component manger will keep a copy of a raw pointer\r
+ to our component and delete it when the modal state has ended. However, this is incompatible with\r
+ our class being tracked by shared_ptr as it will force delete our class regardless of the current\r
+ reference count. On the other hand, it's important that the modal manager keeps a reference as it can\r
+ sometimes be the only reference to our class.\r
+\r
+ To do this, we set deleteWhenDismissed to false so that the modal component manager does not delete\r
+ our class. Instead, we pass in a lambda which captures a shared_ptr to ourselves to increase the\r
+ reference count while the component is modal.\r
+ */\r
+ enterModalState (true,\r
+ ModalCallbackFunction::create ([_self = shared_from_this()] (int) {}),\r
+ false);\r
+ }\r
+\r
+ void runModally() override\r
+ {\r
+ #if JUCE_MODAL_LOOPS_PERMITTED\r
+ launch();\r
+ runModalLoop();\r
+ #else\r
+ jassertfalse;\r
+ #endif\r
+ }\r
+\r
+ void parentHierarchyChanged() override\r
+ {\r
+ auto* newPeer = dynamic_cast<UIViewComponentPeer*> (getPeer());\r
+\r
+ if (peer != newPeer)\r
+ {\r
+ peer = newPeer;\r
+\r
+ if (peer != nullptr)\r
+ {\r
+ if (auto* parentController = peer->controller)\r
+ [parentController showViewController: controller.get() sender: parentController];\r
+\r
+ peer->toFront (false);\r
+ }\r
+ }\r
+ }\r
+\r
+ void handleAsyncUpdate() override\r
+ {\r
+ pickerWasCancelled();\r
+ }\r
+\r
+ //==============================================================================\r
+ void didPickDocumentsAtURLs (NSArray<NSURL*>* urls)\r
+ {\r
+ cancelPendingUpdate();\r
+\r
+ const auto isWriting = controller.get().documentPickerMode == UIDocumentPickerModeExportToService\r
+ || controller.get().documentPickerMode == UIDocumentPickerModeMoveToService;\r
+ const auto accessOptions = isWriting ? 0 : NSFileCoordinatorReadingWithoutChanges;\r
+\r
+ auto* fileCoordinator = [[[NSFileCoordinator alloc] initWithFilePresenter: nil] autorelease];\r
+ auto* intents = [[[NSMutableArray alloc] init] autorelease];\r
+\r
+ for (NSURL* url in urls)\r
+ {\r
+ auto* fileAccessIntent = isWriting\r
+ ? [NSFileAccessIntent writingIntentWithURL: url options: accessOptions]\r
+ : [NSFileAccessIntent readingIntentWithURL: url options: accessOptions];\r
+ [intents addObject: fileAccessIntent];\r
+ }\r
+\r
+ [fileCoordinator coordinateAccessWithIntents: intents queue: [NSOperationQueue mainQueue] byAccessor: ^(NSError* err)\r
+ {\r
+ if (err != nil)\r
+ {\r
+ auto desc = [err localizedDescription];\r
+ ignoreUnused (desc);\r
+ jassertfalse;\r
+ return;\r
+ }\r
+\r
+ Array<URL> result;\r
+\r
+ for (NSURL* url in urls)\r
+ {\r
+ [url startAccessingSecurityScopedResource];\r
+\r
+ NSError* error = nil;\r
+\r
+ auto* bookmark = [url bookmarkDataWithOptions: 0\r
+ includingResourceValuesForKeys: nil\r
+ relativeToURL: nil\r
+ error: &error];\r
+\r
+ [bookmark retain];\r
+\r
+ [url stopAccessingSecurityScopedResource];\r
+\r
+ URL juceUrl (nsStringToJuce ([url absoluteString]));\r
+\r
+ if (error == nil)\r
+ {\r
+ setURLBookmark (juceUrl, (void*) bookmark);\r
+ }\r
+ else\r
+ {\r
+ auto desc = [error localizedDescription];\r
+ ignoreUnused (desc);\r
+ jassertfalse;\r
+ }\r
+\r
+ result.add (std::move (juceUrl));\r
+ }\r
+\r
+ passResultsToInitiator (std::move (result));\r
+ }];\r
+ }\r
+\r
+ void didPickDocumentAtURL (NSURL* url)\r
+ {\r
+ didPickDocumentsAtURLs (@[url]);\r
+ }\r
+\r
+ void pickerWasCancelled()\r
+ {\r
+ passResultsToInitiator ({});\r
+ }\r
+\r
+private:\r
Native (FileChooser& fileChooser, int flags)\r
: owner (fileChooser)\r
{\r
- static FileChooserDelegateClass delegateClass;\r
- delegate.reset ([delegateClass.createInstance() init]);\r
- FileChooserDelegateClass::setOwner (delegate.get(), this);\r
-\r
- static FileChooserControllerClass controllerClass;\r
- auto* controllerClassInstance = controllerClass.createInstance();\r
+ delegate.reset ([[FileChooserDelegateClass alloc] initWithOwner: this]);\r
\r
String firstFileExtension;\r
auto utTypeArray = createNSArrayFromStringArray (getUTTypesForWildcards (owner.filters, firstFileExtension));\r
\r
auto url = [[NSURL alloc] initFileURLWithPath: juceStringToNS (currentFileOrDirectory.getFullPathName())];\r
\r
- controller.reset ([controllerClassInstance initWithURL: url\r
- inMode: pickerMode]);\r
-\r
+ controller.reset ([[FileChooserControllerClass alloc] initWithURL: url inMode: pickerMode]);\r
[url release];\r
}\r
else\r
{\r
- controller.reset ([controllerClassInstance initWithDocumentTypes: utTypeArray\r
- inMode: UIDocumentPickerModeOpen]);\r
+ controller.reset ([[FileChooserControllerClass alloc] initWithDocumentTypes: utTypeArray inMode: UIDocumentPickerModeOpen]);\r
+\r
if (@available (iOS 11.0, *))\r
[controller.get() setAllowsMultipleSelection: (flags & FileBrowserComponent::canSelectMultipleItems) != 0];\r
}\r
\r
- FileChooserControllerClass::setOwner (controller.get(), this);\r
\r
[controller.get() setDelegate: delegate.get()];\r
[controller.get() setModalTransitionStyle: UIModalTransitionStyleCrossDissolve];\r
}\r
}\r
\r
- ~Native() override\r
+ void passResultsToInitiator (Array<URL> urls)\r
{\r
+ cancelPendingUpdate();\r
exitModalState (0);\r
\r
- // Our old peer may not have received a becomeFirstResponder call at this point,\r
- // so the static currentlyFocusedPeer may be null.\r
- // We'll try to find an appropriate peer to focus.\r
-\r
+ // If the caller attempts to show a platform-native dialog box inside the results callback (e.g. in the DialogsDemo)\r
+ // then the original peer must already have focus. Otherwise, there's a danger that either the invisible FileChooser\r
+ // components will display the popup, locking the application, or maybe no component will have focus, and the\r
+ // dialog won't show at all.\r
for (auto i = 0; i < ComponentPeer::getNumPeers(); ++i)\r
if (auto* p = ComponentPeer::getPeer (i))\r
if (p != getPeer())\r
if (auto* view = (UIView*) p->getNativeHandle())\r
- [view becomeFirstResponder];\r
- }\r
-\r
- void launch() override\r
- {\r
- enterModalState (true, nullptr, true);\r
- }\r
-\r
- void runModally() override\r
- {\r
- #if JUCE_MODAL_LOOPS_PERMITTED\r
- runModalLoop();\r
- #else\r
- jassertfalse;\r
- #endif\r
- }\r
-\r
- void parentHierarchyChanged() override\r
- {\r
- auto* newPeer = dynamic_cast<UIViewComponentPeer*> (getPeer());\r
-\r
- if (peer != newPeer)\r
- {\r
- peer = newPeer;\r
-\r
- if (peer != nullptr)\r
- {\r
- if (auto* parentController = peer->controller)\r
- [parentController showViewController: controller.get() sender: parentController];\r
+ if ([view becomeFirstResponder] && [view isFirstResponder])\r
+ break;\r
\r
- peer->toFront (false);\r
- }\r
- }\r
- }\r
-\r
-private:\r
- //==============================================================================\r
- void handleAsyncUpdate() override\r
- {\r
- pickerWasCancelled();\r
+ // Calling owner.finished will delete this Pimpl instance, so don't call any more member functions here!\r
+ owner.finished (std::move (urls));\r
}\r
\r
//==============================================================================\r
return filename;\r
}\r
\r
- //==============================================================================\r
- void didPickDocumentsAtURLs (NSArray<NSURL*>* urls)\r
- {\r
- cancelPendingUpdate();\r
-\r
- const auto isWriting = controller.get().documentPickerMode == UIDocumentPickerModeExportToService\r
- || controller.get().documentPickerMode == UIDocumentPickerModeMoveToService;\r
- const auto accessOptions = isWriting ? 0 : NSFileCoordinatorReadingWithoutChanges;\r
-\r
- auto* fileCoordinator = [[[NSFileCoordinator alloc] initWithFilePresenter: nil] autorelease];\r
- auto* intents = [[[NSMutableArray alloc] init] autorelease];\r
-\r
- for (NSURL* url in urls)\r
- {\r
- auto* fileAccessIntent = isWriting\r
- ? [NSFileAccessIntent writingIntentWithURL: url options: accessOptions]\r
- : [NSFileAccessIntent readingIntentWithURL: url options: accessOptions];\r
- [intents addObject: fileAccessIntent];\r
- }\r
-\r
- [fileCoordinator coordinateAccessWithIntents: intents queue: [NSOperationQueue mainQueue] byAccessor: ^(NSError* err)\r
- {\r
- if (err != nil)\r
- {\r
- auto desc = [err localizedDescription];\r
- ignoreUnused (desc);\r
- jassertfalse;\r
- return;\r
- }\r
-\r
- Array<URL> result;\r
-\r
- for (NSURL* url in urls)\r
- {\r
- [url startAccessingSecurityScopedResource];\r
-\r
- NSError* error = nil;\r
-\r
- auto* bookmark = [url bookmarkDataWithOptions: 0\r
- includingResourceValuesForKeys: nil\r
- relativeToURL: nil\r
- error: &error];\r
-\r
- [bookmark retain];\r
-\r
- [url stopAccessingSecurityScopedResource];\r
-\r
- URL juceUrl (nsStringToJuce ([url absoluteString]));\r
-\r
- if (error == nil)\r
- {\r
- setURLBookmark (juceUrl, (void*) bookmark);\r
- }\r
- else\r
- {\r
- auto desc = [error localizedDescription];\r
- ignoreUnused (desc);\r
- jassertfalse;\r
- }\r
-\r
- result.add (std::move (juceUrl));\r
- }\r
-\r
- owner.finished (std::move (result));\r
- }];\r
- }\r
-\r
- void didPickDocumentAtURL (NSURL* url)\r
- {\r
- didPickDocumentsAtURLs (@[url]);\r
- }\r
-\r
- void pickerWasCancelled()\r
- {\r
- cancelPendingUpdate();\r
- owner.finished ({});\r
- // Calling owner.finished will delete this Pimpl instance, so don't call any more member functions here!\r
- }\r
-\r
- //==============================================================================\r
- struct FileChooserDelegateClass : public ObjCClass<NSObject<UIDocumentPickerDelegate>>\r
- {\r
- FileChooserDelegateClass() : ObjCClass<NSObject<UIDocumentPickerDelegate>> ("FileChooserDelegate_")\r
- {\r
- addIvar<Native*> ("owner");\r
-\r
- addMethod (@selector (documentPicker:didPickDocumentAtURL:), didPickDocumentAtURL);\r
- addMethod (@selector (documentPicker:didPickDocumentsAtURLs:), didPickDocumentsAtURLs);\r
- addMethod (@selector (documentPickerWasCancelled:), documentPickerWasCancelled);\r
-\r
- addProtocol (@protocol (UIDocumentPickerDelegate));\r
-\r
- registerClass();\r
- }\r
-\r
- static void setOwner (id self, Native* owner) { object_setInstanceVariable (self, "owner", owner); }\r
- static Native* getOwner (id self) { return getIvar<Native*> (self, "owner"); }\r
-\r
- //==============================================================================\r
- static void didPickDocumentAtURL (id self, SEL, UIDocumentPickerViewController*, NSURL* url)\r
- {\r
- if (auto* picker = getOwner (self))\r
- picker->didPickDocumentAtURL (url);\r
- }\r
-\r
- static void didPickDocumentsAtURLs (id self, SEL, UIDocumentPickerViewController*, NSArray<NSURL*>* urls)\r
- {\r
- if (auto* picker = getOwner (self))\r
- picker->didPickDocumentsAtURLs (urls);\r
- }\r
-\r
- static void documentPickerWasCancelled (id self, SEL, UIDocumentPickerViewController*)\r
- {\r
- if (auto* picker = getOwner (self))\r
- picker->pickerWasCancelled();\r
- }\r
- };\r
-\r
- struct FileChooserControllerClass : public ObjCClass<UIDocumentPickerViewController>\r
- {\r
- FileChooserControllerClass() : ObjCClass<UIDocumentPickerViewController> ("FileChooserController_")\r
- {\r
- addIvar<Native*> ("owner");\r
- addMethod (@selector (viewDidDisappear:), viewDidDisappear);\r
-\r
- registerClass();\r
- }\r
-\r
- static void setOwner (id self, Native* owner) { object_setInstanceVariable (self, "owner", owner); }\r
- static Native* getOwner (id self) { return getIvar<Native*> (self, "owner"); }\r
-\r
- //==============================================================================\r
- static void viewDidDisappear (id self, SEL, BOOL animated)\r
- {\r
- sendSuperclassMessage<void> (self, @selector (viewDidDisappear:), animated);\r
-\r
- if (auto* picker = getOwner (self))\r
- picker->triggerAsyncUpdate();\r
- }\r
- };\r
-\r
//==============================================================================\r
FileChooser& owner;\r
NSUniquePtr<NSObject<UIDocumentPickerDelegate>> delegate;\r
- NSUniquePtr<UIDocumentPickerViewController> controller;\r
+ NSUniquePtr<FileChooserControllerClass> controller;\r
UIViewComponentPeer* peer = nullptr;\r
\r
- static FileChooserDelegateClass fileChooserDelegateClass;\r
- static FileChooserControllerClass fileChooserControllerClass;\r
-\r
//==============================================================================\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Native)\r
};\r
std::shared_ptr<FileChooser::Pimpl> FileChooser::showPlatformDialog (FileChooser& owner, int flags,\r
FilePreviewComponent*)\r
{\r
- return std::make_shared<FileChooser::Native> (owner, flags);\r
+ return Native::make (owner, flags);\r
}\r
\r
#if JUCE_DEPRECATION_IGNORED\r
#endif\r
\r
} // namespace juce\r
+\r
+@implementation FileChooserControllerClass\r
+{\r
+ std::weak_ptr<FileChooser::Native> ptr;\r
+}\r
+\r
+- (void) setParent: (FileChooser::Native*) parent\r
+{\r
+ jassert (parent != nullptr);\r
+ jassert (parent->shared_from_this() != nullptr);\r
+ ptr = parent->weak_from_this();\r
+}\r
+\r
+- (void) viewDidDisappear: (BOOL) animated\r
+{\r
+ [super viewDidDisappear: animated];\r
+\r
+ if (auto nativeParent = ptr.lock())\r
+ nativeParent->triggerAsyncUpdate();\r
+}\r
+\r
+@end\r
+\r
+@implementation FileChooserDelegateClass\r
+{\r
+ FileChooser::Native* owner;\r
+}\r
+\r
+- (id) initWithOwner: (FileChooser::Native*) o\r
+{\r
+ self = [super init];\r
+ owner = o;\r
+ return self;\r
+}\r
+\r
+JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-implementations")\r
+- (void) documentPicker: (UIDocumentPickerViewController*) controller didPickDocumentAtURL: (NSURL*) url\r
+{\r
+ if (owner != nullptr)\r
+ owner->didPickDocumentAtURL (url);\r
+}\r
+JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+\r
+- (void) documentPicker: (UIDocumentPickerViewController*) controller didPickDocumentsAtURLs: (NSArray<NSURL*>*) urls\r
+{\r
+ if (owner != nullptr)\r
+ owner->didPickDocumentsAtURLs (urls);\r
+}\r
+\r
+- (void) documentPickerWasCancelled: (UIDocumentPickerViewController*) controller\r
+{\r
+ if (owner != nullptr)\r
+ owner->pickerWasCancelled();\r
+}\r
+\r
+@end\r
JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
}\r
\r
-namespace Orientations\r
+struct Orientations\r
{\r
static Desktop::DisplayOrientation convertToJuce (UIInterfaceOrientation orientation)\r
{\r
return UIInterfaceOrientationPortrait;\r
}\r
\r
-\r
- static NSUInteger getSupportedOrientations()\r
+ static UIInterfaceOrientationMask getSupportedOrientations()\r
{\r
NSUInteger allowed = 0;\r
auto& d = Desktop::getInstance();\r
\r
return allowed;\r
}\r
-}\r
+};\r
\r
enum class MouseEventFlags\r
{\r
\r
//==============================================================================\r
class UIViewComponentPeer : public ComponentPeer,\r
- private UIViewPeerControllerReceiver\r
+ public UIViewPeerControllerReceiver\r
{\r
public:\r
UIViewComponentPeer (Component&, int windowStyleFlags, UIView* viewToAttachTo);\r
const auto rangeToDelete = range.isEmpty() ? range.withStartAndLength (jmax (range.getStart() - 1, 0),\r
range.getStart() != 0 ? 1 : 0)\r
: range;\r
+ const auto start = rangeToDelete.getStart();\r
\r
+ // This ensures that the cursor is at the beginning, rather than the end, of the selection\r
+ target->setHighlightedRegion ({ start, start });\r
target->setHighlightedRegion (rangeToDelete);\r
target->insertTextAtCaret ("");\r
}\r
return UITextAutocorrectionTypeNo;\r
}\r
\r
+- (UITextSpellCheckingType) spellCheckingType\r
+{\r
+ return UITextSpellCheckingTypeNo;\r
+}\r
+\r
- (BOOL) canBecomeFirstResponder\r
{\r
return YES;\r
details.isSmooth = true;\r
details.isInertial = false;\r
\r
+ const auto reconstructedMousePosition = convertToPointFloat ([gesture locationInView: view]) - convertToPointFloat (offset);\r
+\r
handleMouseWheel (MouseInputSource::InputSourceType::touch,\r
- convertToPointFloat ([gesture locationInView: view]),\r
+ reconstructedMousePosition,\r
UIViewComponentPeer::getMouseTime ([[NSProcessInfo processInfo] systemUptime]),\r
details);\r
}\r
//==============================================================================\r
void UIViewComponentPeer::displayLinkCallback()\r
{\r
+ vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
+\r
if (deferredRepaints.isEmpty())\r
return;\r
\r
\r
void Desktop::allowedOrientationsChanged()\r
{\r
+ #if defined (__IPHONE_16_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_16_0\r
+ if (@available (iOS 16.0, *))\r
+ {\r
+ UIApplication* sharedApplication = [UIApplication sharedApplication];\r
+\r
+ const NSUniquePtr<UIWindowSceneGeometryPreferencesIOS> preferences { [UIWindowSceneGeometryPreferencesIOS alloc] };\r
+ [preferences.get() initWithInterfaceOrientations: Orientations::getSupportedOrientations()];\r
+\r
+ for (UIScene* scene in [sharedApplication connectedScenes])\r
+ {\r
+ if ([scene isKindOfClass: [UIWindowScene class]])\r
+ {\r
+ [static_cast<UIWindowScene*> (scene) requestGeometryUpdateWithPreferences: preferences.get()\r
+ errorHandler: ^([[maybe_unused]] NSError* error)\r
+ {\r
+ // Failed to set the new set of supported orientations.\r
+ // You may have hit this assertion because you're trying to restrict the supported orientations\r
+ // of an app that allows multitasking (i.e. the app does not require fullscreen, and supports\r
+ // all orientations).\r
+ // iPadOS apps that allow multitasking must support all interface orientations,\r
+ // so attempting to change the set of supported orientations will fail.\r
+ // If you hit this assertion in an application that requires fullscreen, it may be because the\r
+ // set of supported orientations declared in the app's plist doesn't have any entries in common\r
+ // with the orientations passed to Desktop::setOrientationsEnabled.\r
+ DBG (nsStringToJuce ([error localizedDescription]));\r
+ jassertfalse;\r
+ }];\r
+ }\r
+ }\r
+\r
+ return;\r
+ }\r
+ #endif\r
+\r
// if the current orientation isn't allowed anymore then switch orientations\r
if (! isOrientationEnabled (getCurrentOrientation()))\r
{\r
\r
bounds = parentWindow == 0 ? Desktop::getInstance().getDisplays().physicalToLogical (physicalBounds)\r
: physicalBounds / currentScaleFactor;\r
+\r
+ updateVBlankTimer();\r
}\r
\r
void updateBorderSize()\r
\r
private:\r
//==============================================================================\r
- class LinuxRepaintManager : public Timer\r
+ class LinuxRepaintManager\r
{\r
public:\r
LinuxRepaintManager (LinuxComponentPeer& p)\r
{\r
}\r
\r
- void timerCallback() override\r
+ void dispatchDeferredRepaints()\r
{\r
XWindowSystem::getInstance()->processPendingPaintsForWindow (peer.windowH);\r
\r
return;\r
\r
if (! regionsNeedingRepaint.isEmpty())\r
- {\r
- stopTimer();\r
performAnyPendingRepaintsNow();\r
- }\r
else if (Time::getApproximateMillisecondCounter() > lastTimeImageUsed + 3000)\r
- {\r
- stopTimer();\r
image = Image();\r
- }\r
}\r
\r
void repaint (Rectangle<int> area)\r
{\r
- if (! isTimerRunning())\r
- startTimer (repaintTimerPeriod);\r
-\r
regionsNeedingRepaint.add (area * peer.currentScaleFactor);\r
}\r
\r
void performAnyPendingRepaintsNow()\r
{\r
if (XWindowSystem::getInstance()->getNumPaintsPendingForWindow (peer.windowH) > 0)\r
- {\r
- startTimer (repaintTimerPeriod);\r
return;\r
- }\r
\r
auto originalRepaintRegion = regionsNeedingRepaint;\r
regionsNeedingRepaint.clear();\r
}\r
}\r
\r
- startTimer (repaintTimerPeriod);\r
-\r
RectangleList<int> adjustedList (originalRepaintRegion);\r
adjustedList.offsetAll (-totalArea.getX(), -totalArea.getY());\r
\r
}\r
\r
lastTimeImageUsed = Time::getApproximateMillisecondCounter();\r
- startTimer (repaintTimerPeriod);\r
}\r
\r
private:\r
- enum { repaintTimerPeriod = 1000 / 100 };\r
-\r
LinuxComponentPeer& peer;\r
const bool isSemiTransparentWindow;\r
Image image;\r
JUCE_DECLARE_NON_COPYABLE (LinuxRepaintManager)\r
};\r
\r
+ class LinuxVBlankManager : public Timer\r
+ {\r
+ public:\r
+ explicit LinuxVBlankManager (std::function<void()> cb) : callback (std::move (cb))\r
+ {\r
+ jassert (callback);\r
+ }\r
+\r
+ ~LinuxVBlankManager() override { stopTimer(); }\r
+\r
+ //==============================================================================\r
+ void timerCallback() override { callback(); }\r
+\r
+ private:\r
+ std::function<void()> callback;\r
+\r
+ JUCE_DECLARE_NON_COPYABLE (LinuxVBlankManager)\r
+ JUCE_DECLARE_NON_MOVEABLE (LinuxVBlankManager)\r
+ };\r
+\r
//==============================================================================\r
template <typename This>\r
static Point<float> localToGlobal (This& t, Point<float> relativePosition)\r
}\r
}\r
\r
+ void onVBlank()\r
+ {\r
+ vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
+\r
+ if (repainter != nullptr)\r
+ repainter->dispatchDeferredRepaints();\r
+ }\r
+\r
+ void updateVBlankTimer()\r
+ {\r
+ if (auto* display = Desktop::getInstance().getDisplays().getDisplayForRect (bounds))\r
+ {\r
+ if (display->verticalFrequencyHz)\r
+ {\r
+ const auto newIntFrequencyHz = roundToInt (*display->verticalFrequencyHz);\r
+\r
+ if (vBlankManager.getTimerInterval() != newIntFrequencyHz)\r
+ vBlankManager.startTimerHz (newIntFrequencyHz);\r
+ }\r
+ }\r
+ }\r
+\r
//==============================================================================\r
std::unique_ptr<LinuxRepaintManager> repainter;\r
+ LinuxVBlankManager vBlankManager { [this]() { onVBlank(); } };\r
\r
::Window windowH = {}, parentWindow = {};\r
Rectangle<int> bounds;\r
}\r
#endif\r
\r
- createCVDisplayLink();\r
-\r
if (isSharedWindow)\r
{\r
window = [viewToAttachTo window];\r
styleMask: getNSWindowStyleMask (windowStyleFlags)\r
backing: NSBackingStoreBuffered\r
defer: YES];\r
+ [window setColorSpace: [NSColorSpace sRGBColorSpace]];\r
setOwner (window, this);\r
\r
if (@available (macOS 10.10, *))\r
scopedObservers.emplace_back (view, frameChangedSelector, NSWindowDidMoveNotification, window);\r
scopedObservers.emplace_back (view, frameChangedSelector, NSWindowDidMiniaturizeNotification, window);\r
scopedObservers.emplace_back (view, @selector (windowWillMiniaturize:), NSWindowWillMiniaturizeNotification, window);\r
- scopedObservers.emplace_back (view, @selector (windowDidMiniaturize:), NSWindowDidMiniaturizeNotification, window);\r
+ scopedObservers.emplace_back (view, @selector (windowDidDeminiaturize:), NSWindowDidDeminiaturizeNotification, window);\r
}\r
\r
auto alpha = component.getAlpha();\r
\r
~NSViewComponentPeer() override\r
{\r
- CVDisplayLinkStop (displayLink);\r
- dispatch_source_cancel (displaySource);\r
-\r
scopedObservers.clear();\r
\r
setOwner (view, nullptr);\r
return areAnyWindowsInLiveResize();\r
}\r
\r
+ void onVBlank()\r
+ {\r
+ vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
+ setNeedsDisplayRectangles();\r
+ }\r
+\r
void setNeedsDisplayRectangles()\r
{\r
if (deferredRepaints.isEmpty())\r
setNeedsDisplayRectangles();\r
}\r
\r
- void windowDidChangeScreen()\r
- {\r
- updateCVDisplayLinkScreen();\r
- }\r
-\r
void viewMovedToWindow()\r
{\r
if (isSharedWindow)\r
windowObservers.emplace_back (view, dismissModalsSelector, NSWindowWillMiniaturizeNotification, currentWindow);\r
windowObservers.emplace_back (view, becomeKeySelector, NSWindowDidBecomeKeyNotification, currentWindow);\r
windowObservers.emplace_back (view, resignKeySelector, NSWindowDidResignKeyNotification, currentWindow);\r
- windowObservers.emplace_back (view, @selector (windowDidChangeScreen:), NSWindowDidChangeScreenNotification, currentWindow);\r
-\r
- updateCVDisplayLinkScreen();\r
}\r
}\r
\r
if (auto keyCode = getKeyCodeFromEvent (ev))\r
{\r
if (isKeyDown)\r
- keysCurrentlyDown.addIfNotAlreadyThere (keyCode);\r
+ keysCurrentlyDown.insert (keyCode);\r
else\r
- keysCurrentlyDown.removeFirstMatchingValue (keyCode);\r
+ keysCurrentlyDown.erase (keyCode);\r
}\r
}\r
\r
#else\r
bool usingCoreGraphics = false;\r
#endif\r
- bool isZooming = false, isFirstLiveResize = false, textWasInserted = false;\r
+ bool textWasInserted = false, isFirstLiveResize = false;\r
bool isStretchingTop = false, isStretchingLeft = false, isStretchingBottom = false, isStretchingRight = false;\r
bool windowRepresentsFile = false;\r
bool isAlwaysOnTop = false, wasAlwaysOnTop = false;\r
uint32 lastRepaintTime;\r
\r
static ComponentPeer* currentlyFocusedPeer;\r
- static Array<int> keysCurrentlyDown;\r
+ static std::set<int> keysCurrentlyDown;\r
static int insideToFrontCall;\r
\r
static const SEL dismissModalsSelector;\r
static const SEL resignKeySelector;\r
\r
private:\r
+ JUCE_DECLARE_WEAK_REFERENCEABLE (NSViewComponentPeer)\r
+\r
+ // Note: the OpenGLContext also has a SharedResourcePointer<PerScreenDisplayLinks> to\r
+ // avoid unnecessarily duplicating display-link threads.\r
+ SharedResourcePointer<PerScreenDisplayLinks> sharedDisplayLinks;\r
+\r
+ class AsyncRepainter : private AsyncUpdater\r
+ {\r
+ public:\r
+ explicit AsyncRepainter (NSViewComponentPeer& o) : owner (o) {}\r
+ ~AsyncRepainter() override { cancelPendingUpdate(); }\r
+\r
+ void markUpdated (const CGDirectDisplayID x)\r
+ {\r
+ {\r
+ const std::scoped_lock lock { mutex };\r
+\r
+ if (std::find (backgroundDisplays.cbegin(), backgroundDisplays.cend(), x) == backgroundDisplays.cend())\r
+ backgroundDisplays.push_back (x);\r
+ }\r
+\r
+ triggerAsyncUpdate();\r
+ }\r
+\r
+ private:\r
+ void handleAsyncUpdate() override\r
+ {\r
+ {\r
+ const std::scoped_lock lock { mutex };\r
+ mainThreadDisplays = backgroundDisplays;\r
+ backgroundDisplays.clear();\r
+ }\r
+\r
+ for (const auto& display : mainThreadDisplays)\r
+ if (auto* peerView = owner.view)\r
+ if (auto* peerWindow = [peerView window])\r
+ if (display == ScopedDisplayLink::getDisplayIdForScreen ([peerWindow screen]))\r
+ owner.onVBlank();\r
+ }\r
+\r
+ NSViewComponentPeer& owner;\r
+ std::mutex mutex;\r
+ std::vector<CGDirectDisplayID> backgroundDisplays, mainThreadDisplays;\r
+ };\r
+\r
+ AsyncRepainter asyncRepainter { *this };\r
+\r
+ /* Creates a function object that can be called from an arbitrary thread (probably a CVLink\r
+ thread). When called, this function object will trigger a call to setNeedsDisplayRectangles\r
+ as soon as possible on the main thread, for any peers currently on the provided NSScreen.\r
+ */\r
+ PerScreenDisplayLinks::Connection connection\r
+ {\r
+ sharedDisplayLinks->registerFactory ([this] (CGDirectDisplayID display)\r
+ {\r
+ return [this, display] { asyncRepainter.markUpdated (display); };\r
+ })\r
+ };\r
+\r
static NSView* createViewInstance();\r
static NSWindow* createWindowInstance();\r
\r
}\r
\r
//==============================================================================\r
- void onDisplaySourceCallback()\r
- {\r
- setNeedsDisplayRectangles();\r
- }\r
-\r
- void onDisplayLinkCallback()\r
- {\r
- dispatch_source_merge_data (displaySource, 1);\r
- }\r
-\r
- static CVReturn displayLinkCallback (CVDisplayLinkRef, const CVTimeStamp*, const CVTimeStamp*,\r
- CVOptionFlags, CVOptionFlags*, void* context)\r
- {\r
- static_cast<NSViewComponentPeer*> (context)->onDisplayLinkCallback();\r
- return kCVReturnSuccess;\r
- }\r
-\r
- void updateCVDisplayLinkScreen()\r
- {\r
- auto viewDisplayID = (CGDirectDisplayID) [[window.screen.deviceDescription objectForKey: @"NSScreenNumber"] unsignedIntegerValue];\r
- auto result = CVDisplayLinkSetCurrentCGDisplay (displayLink, viewDisplayID);\r
- jassertquiet (result == kCVReturnSuccess);\r
- }\r
-\r
- void createCVDisplayLink()\r
- {\r
- displaySource = dispatch_source_create (DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());\r
- dispatch_source_set_event_handler (displaySource, ^(){ onDisplaySourceCallback(); });\r
- dispatch_resume (displaySource);\r
-\r
- auto cvReturn = CVDisplayLinkCreateWithActiveCGDisplays (&displayLink);\r
- jassertquiet (cvReturn == kCVReturnSuccess);\r
-\r
- cvReturn = CVDisplayLinkSetOutputCallback (displayLink, &displayLinkCallback, this);\r
- jassertquiet (cvReturn == kCVReturnSuccess);\r
-\r
- CVDisplayLinkStart (displayLink);\r
- }\r
-\r
- CVDisplayLinkRef displayLink = nullptr;\r
- dispatch_source_t displaySource = nullptr;\r
-\r
int numFramesToSkipMetalRenderer = 0;\r
std::unique_ptr<CoreGraphicsMetalLayerRenderer<NSView>> metalRenderer;\r
\r
}\r
});\r
\r
- addMethod (@selector (windowDidChangeScreen:), [] (id self, SEL, NSNotification*)\r
- {\r
- if (auto* p = getOwner (self))\r
- p->windowDidChangeScreen();\r
- });\r
-\r
addMethod (@selector (wantsDefaultClipping), [] (id, SEL) { return YES; }); // (this is the default, but may want to customise it in future)\r
\r
addMethod (@selector (worksWhenModal), [] (id self, SEL)\r
{\r
if (auto* owner = getOwner (self))\r
{\r
- auto* target = owner->findCurrentTextInputTarget();\r
owner->textWasInserted = false;\r
\r
- if (target != nullptr)\r
+ if (auto* target = owner->findCurrentTextInputTarget())\r
[(NSView*) self interpretKeyEvents: [NSArray arrayWithObject: ev]];\r
else\r
owner->stringBeingComposed.clear();\r
\r
- if (! (owner->textWasInserted || owner->redirectKeyDown (ev)))\r
+ if (! (owner->textWasInserted || owner->stringBeingComposed.isNotEmpty() || owner->redirectKeyDown (ev)))\r
sendSuperclassMessage<void> (self, @selector (keyDown:), ev);\r
}\r
});\r
{\r
auto* owner = getOwner (self);\r
\r
- if (owner == nullptr || owner->isZooming)\r
+ if (owner == nullptr)\r
return proposedFrameSize;\r
\r
NSRect frameRect = flippedScreenRect ([(NSWindow*) self frame]);\r
\r
//==============================================================================\r
ComponentPeer* NSViewComponentPeer::currentlyFocusedPeer = nullptr;\r
-Array<int> NSViewComponentPeer::keysCurrentlyDown;\r
+std::set<int> NSViewComponentPeer::keysCurrentlyDown;\r
\r
//==============================================================================\r
bool KeyPress::isKeyCurrentlyDown (int keyCode)\r
{\r
- if (NSViewComponentPeer::keysCurrentlyDown.contains (keyCode))\r
+ const auto isDown = [] (int k)\r
+ {\r
+ return NSViewComponentPeer::keysCurrentlyDown.find (k) != NSViewComponentPeer::keysCurrentlyDown.cend();\r
+ };\r
+\r
+ if (isDown (keyCode))\r
return true;\r
\r
if (keyCode >= 'A' && keyCode <= 'Z'\r
- && NSViewComponentPeer::keysCurrentlyDown.contains ((int) CharacterFunctions::toLowerCase ((juce_wchar) keyCode)))\r
+ && isDown ((int) CharacterFunctions::toLowerCase ((juce_wchar) keyCode)))\r
return true;\r
\r
if (keyCode >= 'a' && keyCode <= 'z'\r
- && NSViewComponentPeer::keysCurrentlyDown.contains ((int) CharacterFunctions::toUpperCase ((juce_wchar) keyCode)))\r
+ && isDown ((int) CharacterFunctions::toUpperCase ((juce_wchar) keyCode)))\r
return true;\r
\r
return false;\r
--- /dev/null
+/*\r
+ ==============================================================================\r
+\r
+ This file is part of the JUCE library.\r
+ Copyright (c) 2022 - Raw Material Software Limited\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 7 End-User License\r
+ Agreement and JUCE Privacy Policy.\r
+\r
+ End User License Agreement: www.juce.com/juce-7-licence\r
+ Privacy Policy: www.juce.com/juce-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
+namespace juce\r
+{\r
+\r
+//==============================================================================\r
+/*\r
+ Forwards NSNotificationCenter callbacks to a std::function<void()>.\r
+*/\r
+class FunctionNotificationCenterObserver\r
+{\r
+public:\r
+ FunctionNotificationCenterObserver (NSNotificationName notificationName,\r
+ id objectToObserve,\r
+ std::function<void()> callback)\r
+ : onNotification (std::move (callback)),\r
+ observer (observerObject.get(), getSelector(), notificationName, objectToObserve)\r
+ {}\r
+\r
+private:\r
+ struct ObserverClass\r
+ {\r
+ ObserverClass()\r
+ {\r
+ klass.addIvar<FunctionNotificationCenterObserver*> ("owner");\r
+\r
+ klass.addMethod (getSelector(), [] (id self, SEL, NSNotification*)\r
+ {\r
+ getIvar<FunctionNotificationCenterObserver*> (self, "owner")->onNotification();\r
+ });\r
+\r
+ klass.registerClass();\r
+ }\r
+\r
+ NSObject* createInstance() const { return klass.createInstance(); }\r
+\r
+ private:\r
+ ObjCClass<NSObject> klass { "JUCEObserverClass_" };\r
+ };\r
+\r
+ static SEL getSelector()\r
+ {\r
+ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")\r
+ return @selector (notificationFired:);\r
+ JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+ }\r
+\r
+ std::function<void()> onNotification;\r
+\r
+ NSUniquePtr<NSObject> observerObject\r
+ {\r
+ [this]\r
+ {\r
+ static ObserverClass observerClass;\r
+ auto* result = observerClass.createInstance();\r
+ object_setInstanceVariable (result, "owner", this);\r
+ return result;\r
+ }()\r
+ };\r
+\r
+ ScopedNotificationCenterObserver observer;\r
+\r
+ // Instances can't be copied or moved, because 'this' is stored as a member of the ObserverClass\r
+ // object.\r
+ JUCE_DECLARE_NON_COPYABLE (FunctionNotificationCenterObserver)\r
+ JUCE_DECLARE_NON_MOVEABLE (FunctionNotificationCenterObserver)\r
+};\r
+\r
+//==============================================================================\r
+/*\r
+ Manages the lifetime of a CVDisplayLinkRef for a single display, and automatically starts and\r
+ stops it.\r
+*/\r
+class ScopedDisplayLink\r
+{\r
+public:\r
+ static CGDirectDisplayID getDisplayIdForScreen (NSScreen* screen)\r
+ {\r
+ return (CGDirectDisplayID) [[screen.deviceDescription objectForKey: @"NSScreenNumber"] unsignedIntegerValue];\r
+ }\r
+\r
+ ScopedDisplayLink (NSScreen* screenIn, std::function<void()> onCallbackIn)\r
+ : displayId (getDisplayIdForScreen (screenIn)),\r
+ link ([display = displayId]\r
+ {\r
+ CVDisplayLinkRef ptr = nullptr;\r
+ const auto result = CVDisplayLinkCreateWithCGDisplay (display, &ptr);\r
+ jassertquiet (result == kCVReturnSuccess);\r
+ jassertquiet (ptr != nullptr);\r
+ return ptr;\r
+ }()),\r
+ onCallback (std::move (onCallbackIn))\r
+ {\r
+ const auto callback = [] (CVDisplayLinkRef,\r
+ const CVTimeStamp*,\r
+ const CVTimeStamp*,\r
+ CVOptionFlags,\r
+ CVOptionFlags*,\r
+ void* context) -> int\r
+ {\r
+ static_cast<const ScopedDisplayLink*> (context)->onCallback();\r
+ return kCVReturnSuccess;\r
+ };\r
+\r
+ const auto callbackResult = CVDisplayLinkSetOutputCallback (link.get(), callback, this);\r
+ jassertquiet (callbackResult == kCVReturnSuccess);\r
+\r
+ const auto startResult = CVDisplayLinkStart (link.get());\r
+ jassertquiet (startResult == kCVReturnSuccess);\r
+ }\r
+\r
+ ~ScopedDisplayLink() noexcept\r
+ {\r
+ if (link != nullptr)\r
+ CVDisplayLinkStop (link.get());\r
+ }\r
+\r
+ CGDirectDisplayID getDisplayId() const { return displayId; }\r
+\r
+ double getNominalVideoRefreshPeriodS() const\r
+ {\r
+ const auto nominalVideoRefreshPeriod = CVDisplayLinkGetNominalOutputVideoRefreshPeriod (link.get());\r
+\r
+ if ((nominalVideoRefreshPeriod.flags & kCVTimeIsIndefinite) == 0)\r
+ return (double) nominalVideoRefreshPeriod.timeValue / (double) nominalVideoRefreshPeriod.timeScale;\r
+\r
+ return 0.0;\r
+ }\r
+\r
+private:\r
+ struct DisplayLinkDestructor\r
+ {\r
+ void operator() (CVDisplayLinkRef ptr) const\r
+ {\r
+ if (ptr != nullptr)\r
+ CVDisplayLinkRelease (ptr);\r
+ }\r
+ };\r
+\r
+ CGDirectDisplayID displayId;\r
+ std::unique_ptr<std::remove_pointer_t<CVDisplayLinkRef>, DisplayLinkDestructor> link;\r
+ std::function<void()> onCallback;\r
+\r
+ // Instances can't be copied or moved, because 'this' is passed as context to\r
+ // CVDisplayLinkSetOutputCallback\r
+ JUCE_DECLARE_NON_COPYABLE (ScopedDisplayLink)\r
+ JUCE_DECLARE_NON_MOVEABLE (ScopedDisplayLink)\r
+};\r
+\r
+//==============================================================================\r
+/*\r
+ Holds a ScopedDisplayLink for each screen. When the screen configuration changes, the\r
+ ScopedDisplayLinks will be recreated automatically to match the new configuration.\r
+*/\r
+class PerScreenDisplayLinks\r
+{\r
+public:\r
+ PerScreenDisplayLinks()\r
+ {\r
+ refreshScreens();\r
+ }\r
+\r
+ using RefreshCallback = std::function<void()>;\r
+ using Factory = std::function<RefreshCallback (CGDirectDisplayID)>;\r
+\r
+ /*\r
+ Automatically unregisters a CVDisplayLink callback factory when ~Connection() is called.\r
+ */\r
+ class Connection\r
+ {\r
+ public:\r
+ Connection() = default;\r
+\r
+ Connection (PerScreenDisplayLinks& linksIn, std::list<Factory>::const_iterator it)\r
+ : links (&linksIn), iter (it) {}\r
+\r
+ ~Connection() noexcept\r
+ {\r
+ if (links != nullptr)\r
+ links->unregisterFactory (iter);\r
+ }\r
+\r
+ Connection (const Connection&) = delete;\r
+ Connection& operator= (const Connection&) = delete;\r
+\r
+ Connection (Connection&& other) noexcept\r
+ : links (std::exchange (other.links, nullptr)), iter (other.iter) {}\r
+\r
+ Connection& operator= (Connection&& other) noexcept\r
+ {\r
+ Connection { std::move (other) }.swap (*this);\r
+ return *this;\r
+ }\r
+\r
+ private:\r
+ void swap (Connection& other) noexcept\r
+ {\r
+ std::swap (other.links, links);\r
+ std::swap (other.iter, iter);\r
+ }\r
+\r
+ PerScreenDisplayLinks* links = nullptr;\r
+ std::list<Factory>::const_iterator iter;\r
+ };\r
+\r
+ /* Stores the provided factory for as long as the returned Connection remains alive.\r
+\r
+ Whenever the screen configuration changes, the factory function will be called for each\r
+ screen. The RefreshCallback returned by the factory will be called every time that screen's\r
+ display link callback fires.\r
+ */\r
+ [[nodiscard]] Connection registerFactory (Factory factory)\r
+ {\r
+ const ScopedLock lock (mutex);\r
+ factories.push_front (std::move (factory));\r
+ refreshScreens();\r
+ return { *this, factories.begin() };\r
+ }\r
+\r
+ double getNominalVideoRefreshPeriodSForScreen (CGDirectDisplayID display) const\r
+ {\r
+ const ScopedLock lock (mutex);\r
+\r
+ for (const auto& link : links)\r
+ if (link.getDisplayId() == display)\r
+ return link.getNominalVideoRefreshPeriodS();\r
+\r
+ return 0.0;\r
+ }\r
+\r
+private:\r
+ void unregisterFactory (std::list<Factory>::const_iterator iter)\r
+ {\r
+ const ScopedLock lock (mutex);\r
+ factories.erase (iter);\r
+ refreshScreens();\r
+ }\r
+\r
+ void refreshScreens()\r
+ {\r
+ auto newLinks = [&]\r
+ {\r
+ std::list<ScopedDisplayLink> result;\r
+\r
+ for (NSScreen* screen in [NSScreen screens])\r
+ {\r
+ std::vector<RefreshCallback> callbacks;\r
+\r
+ for (auto& factory : factories)\r
+ callbacks.push_back (factory (ScopedDisplayLink::getDisplayIdForScreen (screen)));\r
+\r
+ // This is the callback that will actually fire in response to this screen's display\r
+ // link callback.\r
+ result.emplace_back (screen, [callbacks = std::move (callbacks)]\r
+ {\r
+ for (const auto& callback : callbacks)\r
+ callback();\r
+ });\r
+ }\r
+\r
+ return result;\r
+ }();\r
+\r
+ const ScopedLock lock (mutex);\r
+ links = std::move (newLinks);\r
+ }\r
+\r
+ CriticalSection mutex;\r
+ // This is a list rather than a vector so that the iterators are stable, even when items are\r
+ // added/removed from the list. This is important because Connection objects store an iterator\r
+ // internally, and may be created/destroyed arbitrarily.\r
+ std::list<Factory> factories;\r
+ // This is a list rather than a vector because ScopedDisplayLink is non-moveable.\r
+ std::list<ScopedDisplayLink> links;\r
+\r
+ FunctionNotificationCenterObserver screenParamsObserver { NSApplicationDidChangeScreenParametersNotification,\r
+ nullptr,\r
+ [this] { refreshScreens(); } };\r
+};\r
+\r
+} // namespace juce\r
//==============================================================================\r
namespace IconConverters\r
{\r
+ struct IconDestructor\r
+ {\r
+ void operator() (HICON ptr) const { if (ptr != nullptr) DestroyIcon (ptr); }\r
+ };\r
+\r
+ using IconPtr = std::unique_ptr<std::remove_pointer_t<HICON>, IconDestructor>;\r
+\r
static Image createImageFromHICON (HICON icon)\r
{\r
if (icon == nullptr)\r
: desc.Monitor;\r
}\r
\r
-struct VBlankListener\r
-{\r
- virtual void onVBlank() = 0;\r
-};\r
+using VBlankListener = ComponentPeer::VBlankListener;\r
\r
//==============================================================================\r
class VSyncThread : private Thread,\r
monitor (mon)\r
{\r
listeners.push_back (listener);\r
- startThread (10);\r
+ startThread (Priority::highest);\r
}\r
\r
~VSyncThread() override\r
\r
callFunctionIfNotLocked (&destroyWindowCallback, (void*) hwnd);\r
\r
- if (currentWindowIcon != nullptr)\r
- DestroyIcon (currentWindowIcon);\r
-\r
if (dropTarget != nullptr)\r
{\r
dropTarget->peerIsDeleted = true;\r
//==============================================================================\r
void onVBlank() override\r
{\r
+ vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
dispatchDeferredRepaints();\r
}\r
\r
bool fullScreen = false, isDragging = false, isMouseOver = false,\r
hasCreatedCaret = false, constrainerIsResizing = false;\r
BorderSize<int> windowBorder;\r
- HICON currentWindowIcon = nullptr;\r
+ IconConverters::IconPtr currentWindowIcon;\r
FileDropTarget* dropTarget = nullptr;\r
uint8 updateLayeredWindowAlpha = 255;\r
UWPUIViewSettings uwpViewSettings;\r
\r
TCHAR moduleFile[1024] = {};\r
GetModuleFileName (moduleHandle, moduleFile, 1024);\r
- WORD iconNum = 0;\r
\r
WNDCLASSEX wcex = {};\r
wcex.cbSize = sizeof (wcex);\r
wcex.lpszClassName = windowClassName.toWideCharPointer();\r
wcex.cbWndExtra = 32;\r
wcex.hInstance = moduleHandle;\r
- wcex.hIcon = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum);\r
- iconNum = 1;\r
- wcex.hIconSm = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum);\r
+\r
+ for (const auto& [index, field, ptr] : { std::tuple { 0, &wcex.hIcon, &iconBig },\r
+ std::tuple { 1, &wcex.hIconSm, &iconSmall } })\r
+ {\r
+ auto iconNum = static_cast<WORD> (index);\r
+ ptr->reset (*field = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum));\r
+ }\r
\r
atom = RegisterClassEx (&wcex);\r
jassert (atom != 0);\r
return false;\r
}\r
\r
+ IconConverters::IconPtr iconBig, iconSmall;\r
+\r
JUCE_DECLARE_NON_COPYABLE (WindowClassHolder)\r
};\r
\r
\r
void setIcon (const Image& newIcon) override\r
{\r
- if (auto hicon = IconConverters::createHICONFromImage (newIcon, TRUE, 0, 0))\r
+ if (IconConverters::IconPtr hicon { IconConverters::createHICONFromImage (newIcon, TRUE, 0, 0) })\r
{\r
- SendMessage (hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);\r
- SendMessage (hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);\r
-\r
- if (currentWindowIcon != nullptr)\r
- DestroyIcon (currentWindowIcon);\r
-\r
- currentWindowIcon = hicon;\r
+ SendMessage (hwnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM> (hicon.get()));\r
+ SendMessage (hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM> (hicon.get()));\r
+ currentWindowIcon = std::move (hicon);\r
}\r
}\r
\r
CombineRgn (rgn, rgn, clipRgn, RGN_AND);\r
DeleteObject (clipRgn);\r
\r
- std::aligned_storage<8192, alignof (RGNDATA)>::type rgnData;\r
+ std::aligned_storage_t<8192, alignof (RGNDATA)> rgnData;\r
const DWORD res = GetRegionData (rgn, sizeof (rgnData), (RGNDATA*) &rgnData);\r
\r
if (res > 0 && res <= sizeof (rgnData))\r
}\r
\r
//==============================================================================\r
-static HICON extractFileHICON (const File& file)\r
+static auto extractFileHICON (const File& file)\r
{\r
WORD iconNum = 0;\r
WCHAR name[MAX_PATH * 2];\r
file.getFullPathName().copyToUTF16 (name, sizeof (name));\r
\r
- return ExtractAssociatedIcon ((HINSTANCE) Process::getCurrentModuleInstanceHandle(),\r
- name, &iconNum);\r
+ return IconConverters::IconPtr { ExtractAssociatedIcon ((HINSTANCE) Process::getCurrentModuleInstanceHandle(),\r
+ name,\r
+ &iconNum) };\r
}\r
\r
Image juce_createIconForFile (const File& file)\r
{\r
- Image image;\r
-\r
- if (auto icon = extractFileHICON (file))\r
- {\r
- image = IconConverters::createImageFromHICON (icon);\r
- DestroyIcon (icon);\r
- }\r
+ if (const auto icon = extractFileHICON (file))\r
+ return IconConverters::createImageFromHICON (icon.get());\r
\r
- return image;\r
+ return {};\r
}\r
\r
//==============================================================================\r
public:\r
explicit ImageImpl (const CustomMouseCursorInfo& infoIn) : info (infoIn) {}\r
\r
- ~ImageImpl() override\r
- {\r
- for (auto& pair : cursorsBySize)\r
- DestroyCursor (pair.second);\r
- }\r
-\r
HCURSOR getCursor (ComponentPeer& peer) override\r
{\r
JUCE_ASSERT_MESSAGE_THREAD;\r
const auto iter = cursorsBySize.find (size);\r
\r
if (iter != cursorsBySize.end())\r
- return iter->second;\r
+ return iter->second.get();\r
\r
const auto logicalSize = info.image.getScaledBounds();\r
const auto scale = (float) size / (float) unityCursorSize;\r
const auto hx = jlimit (0, rescaled.getWidth(), roundToInt ((float) info.hotspot.x * effectiveScale));\r
const auto hy = jlimit (0, rescaled.getHeight(), roundToInt ((float) info.hotspot.y * effectiveScale));\r
\r
- return cursorsBySize.emplace (size, IconConverters::createHICONFromImage (rescaled, false, hx, hy)).first->second;\r
+ return cursorsBySize.emplace (size, CursorPtr { IconConverters::createHICONFromImage (rescaled, false, hx, hy) }).first->second.get();\r
}\r
\r
private:\r
+ struct CursorDestructor\r
+ {\r
+ void operator() (HCURSOR ptr) const { if (ptr != nullptr) DestroyCursor (ptr); }\r
+ };\r
+\r
+ using CursorPtr = std::unique_ptr<std::remove_pointer_t<HCURSOR>, CursorDestructor>;\r
+\r
const CustomMouseCursorInfo info;\r
- std::map<int, HCURSOR> cursorsBySize;\r
+ std::map<int, CursorPtr> cursorsBySize;\r
};\r
\r
static auto getCursorSizeForPeerFunction() -> int (*) (ComponentPeer&)\r
d.isMain = (mainDisplay == screens->outputs[j]) && (i == 0);\r
d.dpi = DisplayHelpers::getDisplayDPI (display, 0);\r
\r
+ d.verticalFrequencyHz = [&]() -> std::optional<double>\r
+ {\r
+ if (crtc->mode != None)\r
+ {\r
+ if (auto it = std::find_if (screens->modes,\r
+ screens->modes + screens->nmode,\r
+ [&crtc] (const auto& m) { return m.id == crtc->mode; });\r
+ it != screens->modes + screens->nmode)\r
+ {\r
+ return (double) it->dotClock / ((double) it->hTotal * (double) it->vTotal);\r
+ }\r
+ }\r
+\r
+ return {};\r
+ }();\r
+\r
// The raspberry pi returns a zero sized display, so we need to guard for divide-by-zero\r
if (output->mm_width > 0 && output->mm_height > 0)\r
d.dpi = ((static_cast<double> (crtc->width) * 25.4 * 0.5) / static_cast<double> (output->mm_width))\r
if (visual24Bit != nullptr)\r
return { visual24Bit, 24 };\r
\r
+ if (visual32Bit != nullptr)\r
+ return { visual32Bit, 32 };\r
+\r
+ // No visual available!\r
+ jassert (visual16Bit != nullptr);\r
+\r
return { visual16Bit, 16 };\r
}\r
\r
if (onChange != nullptr)\r
onChange();\r
\r
+ if (checker.shouldBailOut())\r
+ return;\r
+\r
if (auto* handler = getAccessibilityHandler())\r
handler->notifyAccessibilityEvent (AccessibilityEvent::valueChanged);\r
}\r
setFocusContainerType (FocusContainerType::focusContainer);\r
colourChanged();\r
\r
- setModel (m);\r
+ assignModelPtr (m);\r
}\r
\r
ListBox::~ListBox()\r
\r
updateText();\r
owner.repaint();\r
- updatePopupDisplay (newValue);\r
\r
triggerChangeMessage (notification);\r
}\r
lastValueMin = newValue;\r
valueMin = newValue;\r
owner.repaint();\r
- updatePopupDisplay (newValue);\r
+ updatePopupDisplay();\r
\r
triggerChangeMessage (notification);\r
}\r
lastValueMax = newValue;\r
valueMax = newValue;\r
owner.repaint();\r
- updatePopupDisplay (valueMax.getValue());\r
+ updatePopupDisplay();\r
\r
triggerChangeMessage (notification);\r
}\r
if (owner.onValueChange != nullptr)\r
owner.onValueChange();\r
\r
+ if (checker.shouldBailOut())\r
+ return;\r
+\r
if (auto* handler = owner.getAccessibilityHandler())\r
handler->notifyAccessibilityEvent (AccessibilityEvent::valueChanged);\r
}\r
if (newValue != valueBox->getText())\r
valueBox->setText (newValue, dontSendNotification);\r
}\r
+\r
+ updatePopupDisplay();\r
}\r
\r
double constrainedValue (double value) const\r
| ComponentPeer::windowIgnoresKeyPresses\r
| ComponentPeer::windowIgnoresMouseClicks);\r
\r
- if (style == SliderStyle::TwoValueHorizontal\r
- || style == SliderStyle::TwoValueVertical)\r
- {\r
- updatePopupDisplay (sliderBeingDragged == 2 ? getMaxValue()\r
- : getMinValue());\r
- }\r
- else\r
- {\r
- updatePopupDisplay (getValue());\r
- }\r
-\r
+ updatePopupDisplay();\r
popupDisplay->setVisible (true);\r
}\r
}\r
\r
- void updatePopupDisplay (double valueToShow)\r
+ void updatePopupDisplay()\r
{\r
- if (popupDisplay != nullptr)\r
- popupDisplay->updatePosition (owner.getTextFromValue (valueToShow));\r
+ if (popupDisplay == nullptr)\r
+ return;\r
+\r
+ const auto valueToShow = [this]\r
+ {\r
+ constexpr SliderStyle multiSliderStyles[] { SliderStyle::TwoValueHorizontal,\r
+ SliderStyle::TwoValueVertical,\r
+ SliderStyle::ThreeValueHorizontal,\r
+ SliderStyle::ThreeValueVertical };\r
+\r
+ if (std::find (std::begin (multiSliderStyles), std::end (multiSliderStyles), style) == std::end (multiSliderStyles))\r
+ return getValue();\r
+\r
+ if (sliderBeingDragged == 2)\r
+ return getMaxValue();\r
+\r
+ if (sliderBeingDragged == 1)\r
+ return getMinValue();\r
+\r
+ return getValue();\r
+ }();\r
+\r
+ popupDisplay->updatePosition (owner.getTextFromValue (valueToShow));\r
}\r
\r
bool canDoubleClickToValue() const\r
\r
setWantsKeyboardFocus (true);\r
recreateCaret();\r
-\r
- juce::Desktop::getInstance().addGlobalMouseListener (this);\r
}\r
\r
TextEditor::~TextEditor()\r
{\r
- juce::Desktop::getInstance().removeGlobalMouseListener (this);\r
-\r
textValue.removeListener (textHolder);\r
textValue.referTo (Value());\r
\r
\r
bool TextEditor::isTextInputActive() const\r
{\r
- return ! isReadOnly() && (! clicksOutsideDismissVirtualKeyboard || mouseDownInEditor);\r
+ return ! isReadOnly() && (! clicksOutsideDismissVirtualKeyboard || globalMouseListener.lastMouseDownInEditor());\r
}\r
\r
void TextEditor::setReturnKeyStartsNewLine (bool shouldStartNewLine)\r
\r
void TextEditor::insertTextAtCaret (const String& t)\r
{\r
- String newText (inputFilter != nullptr ? inputFilter->filterNewText (*this, t) : t);\r
-\r
- if (isMultiLine())\r
- newText = newText.replace ("\r\n", "\n");\r
- else\r
- newText = newText.replaceCharacters ("\r\n", " ");\r
-\r
- const int insertIndex = selection.getStart();\r
- const int newCaretPos = insertIndex + newText.length();\r
+ const auto filtered = inputFilter != nullptr ? inputFilter->filterNewText (*this, t) : t;\r
+ const auto newText = isMultiLine() ? filtered.replace ("\r\n", "\n")\r
+ : filtered.replaceCharacters ("\r\n", " ");\r
+ const auto insertIndex = selection.getStart();\r
+ const auto newCaretPos = insertIndex + newText.length();\r
\r
remove (selection, getUndoManager(),\r
newText.isNotEmpty() ? newCaretPos - 1 : newCaretPos);\r
//==============================================================================\r
void TextEditor::mouseDown (const MouseEvent& e)\r
{\r
- mouseDownInEditor = e.originalComponent == this;\r
-\r
- if (! mouseDownInEditor)\r
- return;\r
-\r
beginDragAutoRepeat (100);\r
newTransaction();\r
\r
\r
void TextEditor::mouseDrag (const MouseEvent& e)\r
{\r
- if (! mouseDownInEditor)\r
- return;\r
-\r
if (wasFocused || ! selectAllTextWhenFocused)\r
if (! (popupMenuEnabled && e.mods.isPopupMenu()))\r
moveCaretTo (getTextIndexAt (e.getPosition()), true);\r
\r
void TextEditor::mouseUp (const MouseEvent& e)\r
{\r
- if (! mouseDownInEditor)\r
- return;\r
-\r
newTransaction();\r
textHolder->restartTimer();\r
\r
\r
void TextEditor::mouseDoubleClick (const MouseEvent& e)\r
{\r
- if (! mouseDownInEditor)\r
- return;\r
-\r
int tokenEnd = getTextIndexAt (e.getPosition());\r
int tokenStart = 0;\r
\r
\r
void TextEditor::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel)\r
{\r
- if (! mouseDownInEditor)\r
- return;\r
-\r
if (! viewport->useMouseWheelMoveIfNeeded (e, wheel))\r
Component::mouseWheelMove (e, wheel);\r
}\r
return moveCaretToStartOfLine (selecting);\r
\r
const auto caretPos = (getCaretRectangle() - getTextOffset()).toFloat();\r
- return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getY() - 1.0f), selecting);\r
+\r
+ const auto newY = caretPos.getY() - 1.0f;\r
+\r
+ if (newY < 0.0f)\r
+ return moveCaretToStartOfLine (selecting);\r
+\r
+ return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), newY), selecting);\r
}\r
\r
bool TextEditor::moveCaretDown (bool selecting)\r
case TextEditorDefs::textChangeMessageId:\r
listeners.callChecked (checker, [this] (Listener& l) { l.textEditorTextChanged (*this); });\r
\r
- if (! checker.shouldBailOut() && onTextChange != nullptr)\r
- onTextChange();\r
+ if (! checker.shouldBailOut())\r
+ NullCheckedInvocation::invoke (onTextChange);\r
\r
break;\r
\r
case TextEditorDefs::returnKeyMessageId:\r
listeners.callChecked (checker, [this] (Listener& l) { l.textEditorReturnKeyPressed (*this); });\r
\r
- if (! checker.shouldBailOut() && onReturnKey != nullptr)\r
- onReturnKey();\r
+ if (! checker.shouldBailOut())\r
+ NullCheckedInvocation::invoke (onReturnKey);\r
\r
break;\r
\r
case TextEditorDefs::escapeKeyMessageId:\r
listeners.callChecked (checker, [this] (Listener& l) { l.textEditorEscapeKeyPressed (*this); });\r
\r
- if (! checker.shouldBailOut() && onEscapeKey != nullptr)\r
- onEscapeKey();\r
+ if (! checker.shouldBailOut())\r
+ NullCheckedInvocation::invoke (onEscapeKey);\r
\r
break;\r
\r
updateValueFromText();\r
listeners.callChecked (checker, [this] (Listener& l) { l.textEditorFocusLost (*this); });\r
\r
- if (! checker.shouldBailOut() && onFocusLost != nullptr)\r
- onFocusLost();\r
+ if (! checker.shouldBailOut())\r
+ NullCheckedInvocation::invoke (onFocusLost);\r
\r
break;\r
\r
{\r
for (Iterator i (*this); i.next();)\r
{\r
- if (y < i.lineY + i.lineHeight)\r
+ if (y < i.lineY + (i.lineHeight * lineSpacing))\r
{\r
- if (y < i.lineY)\r
+ if (jmax (0.0f, y) < i.lineY)\r
return jmax (0, i.indexInText - 1);\r
\r
if (x <= i.atomX || i.atom->isNewLine())\r
struct RemoveAction;\r
class EditorAccessibilityHandler;\r
\r
+ class GlobalMouseListener : private MouseListener\r
+ {\r
+ public:\r
+ explicit GlobalMouseListener (Component& e) : editor (e) { Desktop::getInstance().addGlobalMouseListener (this); }\r
+ ~GlobalMouseListener() override { Desktop::getInstance().removeGlobalMouseListener (this); }\r
+\r
+ bool lastMouseDownInEditor() const { return mouseDownInEditor; }\r
+\r
+ private:\r
+ void mouseDown (const MouseEvent& event) override { mouseDownInEditor = event.originalComponent == &editor; }\r
+\r
+ Component& editor;\r
+ bool mouseDownInEditor = false;\r
+ };\r
+\r
std::unique_ptr<Viewport> viewport;\r
TextHolderComponent* textHolder;\r
BorderSize<int> borderSize { 1, 1, 1, 3 };\r
Justification justification { Justification::topLeft };\r
+ const GlobalMouseListener globalMouseListener { *this };\r
\r
bool readOnly = false;\r
bool caretVisible = true;\r
bool valueTextNeedsUpdating = false;\r
bool consumeEscAndReturnKeys = true;\r
bool underlineWhitespace = true;\r
- bool mouseDownInEditor = false;\r
bool clicksOutsideDismissVirtualKeyboard = false;\r
\r
UndoManager undoManager;\r
\r
enum class Async { yes, no };\r
\r
- void recalculatePositions (Async useAsyncUpdate)\r
+ void recalculatePositions (Async useAsyncUpdate, std::optional<Point<int>> viewportPosition)\r
{\r
needsRecalculating = true;\r
+ viewportAfterRecalculation = std::move (viewportPosition);\r
\r
if (useAsyncUpdate == Async::yes)\r
triggerAsyncUpdate();\r
\r
void handleAsyncUpdate() override\r
{\r
- if (structureChanged)\r
+ if (std::exchange (structureChanged, false))\r
{\r
if (auto* handler = owner.getAccessibilityHandler())\r
handler->notifyAccessibilityEvent (AccessibilityEvent::structureChanged);\r
-\r
- structureChanged = false;\r
}\r
\r
- if (needsRecalculating)\r
+ if (std::exchange (needsRecalculating, false))\r
{\r
if (auto* root = owner.rootItem)\r
{\r
\r
updateComponents (false);\r
\r
- needsRecalculating = false;\r
+ if (const auto viewportPosition = std::exchange (viewportAfterRecalculation, {}))\r
+ setViewPosition (viewportPosition->getX(), viewportPosition->getY());\r
}\r
}\r
\r
TreeView& owner;\r
int lastX = -1;\r
bool structureChanged = false, needsRecalculating = false;\r
+ std::optional<Point<int>> viewportAfterRecalculation;\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeViewport)\r
};\r
rootItem->setOpen (true);\r
}\r
\r
- viewport->recalculatePositions (TreeViewport::Async::no);\r
+ viewport->recalculatePositions (TreeViewport::Async::no, {});\r
}\r
}\r
\r
{\r
rootItem->restoreOpennessState (newState);\r
\r
- if (newState.hasAttribute ("scrollPos"))\r
- viewport->setViewPosition (viewport->getViewPositionX(),\r
- newState.getIntAttribute ("scrollPos"));\r
-\r
if (restoreStoredSelection)\r
{\r
clearSelectedItems();\r
item->setSelected (true, false);\r
}\r
\r
- updateVisibleItems();\r
+ const auto scrollPos = newState.hasAttribute ("scrollPos")\r
+ ? std::make_optional<Point<int>> (viewport->getViewPositionX(), newState.getIntAttribute ("scrollPos"))\r
+ : std::nullopt;\r
+\r
+ updateVisibleItems (std::move (scrollPos));\r
}\r
}\r
\r
return false;\r
}\r
\r
-void TreeView::updateVisibleItems()\r
+void TreeView::updateVisibleItems (std::optional<Point<int>> viewportPosition)\r
{\r
- viewport->recalculatePositions (TreeViewport::Async::yes);\r
+ viewport->recalculatePositions (TreeViewport::Async::yes, std::move (viewportPosition));\r
}\r
\r
//==============================================================================\r
\r
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;\r
void itemsChanged() noexcept;\r
- void updateVisibleItems();\r
+ void updateVisibleItems (std::optional<Point<int>> viewportPosition = {});\r
void updateButtonUnderMouse (const MouseEvent&);\r
void showDragHighlight (const InsertPoint&) noexcept;\r
void hideDragHighlight() noexcept;\r
/** Removes a scale factor listener. */\r
void removeScaleFactorListener (ScaleFactorListener* listenerToRemove) { scaleFactorListeners.remove (listenerToRemove); }\r
\r
+ //==============================================================================\r
+ /** Used to receive callbacks on every vertical blank event of the display that the peer\r
+ currently belongs to.\r
+\r
+ On Linux this is currently limited to receiving callbacks from a timer approximately at\r
+ display refresh rate.\r
+\r
+ This is a low-level facility used by the peer implementations. If you wish to synchronise\r
+ Component events with the display refresh, you should probably use the VBlankAttachment,\r
+ which automatically takes care of listening to the vblank events of the right peer.\r
+\r
+ @see VBlankAttachment\r
+ */\r
+ struct JUCE_API VBlankListener\r
+ {\r
+ /** Destructor. */\r
+ virtual ~VBlankListener() = default;\r
+\r
+ /** Called on every vertical blank of the display to which the peer is associated. */\r
+ virtual void onVBlank() = 0;\r
+ };\r
+\r
+ /** Adds a VBlankListener. */\r
+ void addVBlankListener (VBlankListener* listenerToAdd) { vBlankListeners.add (listenerToAdd); }\r
+\r
+ /** Removes a VBlankListener. */\r
+ void removeVBlankListener (VBlankListener* listenerToRemove) { vBlankListeners.remove (listenerToRemove); }\r
+\r
//==============================================================================\r
/** On Windows and Linux this will return the OS scaling factor currently being applied\r
to the native window. This is used to convert between physical and logical pixels\r
ComponentBoundsConstrainer* constrainer = nullptr;\r
static std::function<ModifierKeys()> getNativeRealtimeModifiers;\r
ListenerList<ScaleFactorListener> scaleFactorListeners;\r
+ ListenerList<VBlankListener> vBlankListeners;\r
Style style = Style::automatic;\r
\r
private:\r
\r
//==============================================================================\r
/** Sets the type of icon that should be used for the dialog box. */\r
- JUCE_NODISCARD MessageBoxOptions withIconType (MessageBoxIconType type) const { return with (*this, &MessageBoxOptions::iconType, type); }\r
+ [[nodiscard]] MessageBoxOptions withIconType (MessageBoxIconType type) const { return with (*this, &MessageBoxOptions::iconType, type); }\r
\r
/** Sets the title of the dialog box. */\r
- JUCE_NODISCARD MessageBoxOptions withTitle (const String& boxTitle) const { return with (*this, &MessageBoxOptions::title, boxTitle); }\r
+ [[nodiscard]] MessageBoxOptions withTitle (const String& boxTitle) const { return with (*this, &MessageBoxOptions::title, boxTitle); }\r
\r
/** Sets the message that should be displayed in the dialog box. */\r
- JUCE_NODISCARD MessageBoxOptions withMessage (const String& boxMessage) const { return with (*this, &MessageBoxOptions::message, boxMessage); }\r
+ [[nodiscard]] MessageBoxOptions withMessage (const String& boxMessage) const { return with (*this, &MessageBoxOptions::message, boxMessage); }\r
\r
/** If the string passed in is not empty, this will add a button to the\r
dialog box with the specified text.\r
Generally up to 3 buttons are supported for dialog boxes, so adding any more\r
than this may have no effect.\r
*/\r
- JUCE_NODISCARD MessageBoxOptions withButton (const String& text) const { auto copy = *this; copy.buttons.add (text); return copy; }\r
+ [[nodiscard]] MessageBoxOptions withButton (const String& text) const { auto copy = *this; copy.buttons.add (text); return copy; }\r
\r
/** The component that the dialog box should be associated with. */\r
- JUCE_NODISCARD MessageBoxOptions withAssociatedComponent (Component* component) const { return with (*this, &MessageBoxOptions::associatedComponent, component); }\r
+ [[nodiscard]] MessageBoxOptions withAssociatedComponent (Component* component) const { return with (*this, &MessageBoxOptions::associatedComponent, component); }\r
\r
//==============================================================================\r
/** Returns the icon type of the dialog box.\r
stopThread (timeOutMsWhenCancelling);\r
}\r
\r
-void ThreadWithProgressWindow::launchThread (int priority)\r
+void ThreadWithProgressWindow::launchThread (Priority threadPriority)\r
{\r
JUCE_ASSERT_MESSAGE_THREAD\r
\r
- startThread (priority);\r
+ startThread (threadPriority);\r
startTimer (100);\r
\r
{\r
void ThreadWithProgressWindow::threadComplete (bool) {}\r
\r
#if JUCE_MODAL_LOOPS_PERMITTED\r
-bool ThreadWithProgressWindow::runThread (const int priority)\r
+bool ThreadWithProgressWindow::runThread (Priority threadPriority)\r
{\r
- launchThread (priority);\r
+ launchThread (threadPriority);\r
\r
while (isTimerRunning())\r
MessageManager::getInstance()->runDispatchLoopUntil (5);\r
Before returning, the dialog box will be hidden.\r
\r
@param priority the priority to use when starting the thread - see\r
- Thread::startThread() for values\r
+ Thread::Priority for values\r
@returns true if the thread finished normally; false if the user pressed cancel\r
*/\r
- bool runThread (int priority = 5);\r
+ bool runThread (Priority Priority = Priority::normal);\r
#endif\r
\r
/** Starts the thread and returns.\r
hidden and the threadComplete() method will be called.\r
\r
@param priority the priority to use when starting the thread - see\r
- Thread::startThread() for values\r
+ Thread::Priority for values\r
*/\r
- void launchThread (int priority = 5);\r
+ void launchThread (Priority priority = Priority::normal);\r
\r
/** The thread should call this periodically to update the position of the progress bar.\r
\r
{\r
const auto scale = getDesktopScaleFactor() / Desktop::getInstance().getGlobalScaleFactor();\r
\r
- auto targetCentre = c->localPointToGlobal (c->getLocalBounds().getCentre()) / scale;\r
- auto parentArea = getLocalArea (nullptr, c->getParentMonitorArea());\r
-\r
- if (auto* parent = getParentComponent())\r
+ const auto [targetCentre, parentArea] = [&]\r
{\r
- targetCentre = parent->getLocalPoint (nullptr, targetCentre);\r
- parentArea = parent->getLocalBounds();\r
- }\r
+ const auto globalTargetCentre = c->localPointToGlobal (c->getLocalBounds().getCentre()) / scale;\r
+\r
+ if (auto* parent = getParentComponent())\r
+ return std::make_pair (parent->getLocalPoint (nullptr, globalTargetCentre), parent->getLocalBounds());\r
+\r
+ return std::make_pair (globalTargetCentre, c->getParentMonitorArea() / scale);\r
+ }();\r
\r
setBounds (Rectangle<int> (targetCentre.x - width / 2,\r
targetCentre.y - height / 2,\r
--- /dev/null
+/*\r
+ ==============================================================================\r
+\r
+ This file is part of the JUCE library.\r
+ Copyright (c) 2022 - Raw Material Software Limited\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 7 End-User License\r
+ Agreement and JUCE Privacy Policy.\r
+\r
+ End User License Agreement: www.juce.com/juce-7-licence\r
+ Privacy Policy: www.juce.com/juce-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
+namespace juce\r
+{\r
+\r
+VBlankAttachment::VBlankAttachment (Component* c, std::function<void()> callbackIn)\r
+ : owner (c),\r
+ callback (std::move (callbackIn))\r
+{\r
+ jassert (owner != nullptr && callback);\r
+\r
+ updateOwner();\r
+ updatePeer();\r
+}\r
+\r
+VBlankAttachment::VBlankAttachment (VBlankAttachment&& other)\r
+ : VBlankAttachment (other.owner, std::move (other.callback))\r
+{\r
+ other.cleanup();\r
+}\r
+\r
+VBlankAttachment& VBlankAttachment::operator= (VBlankAttachment&& other)\r
+{\r
+ cleanup();\r
+\r
+ owner = other.owner;\r
+ callback = std::move (other.callback);\r
+ updateOwner();\r
+ updatePeer();\r
+\r
+ other.cleanup();\r
+\r
+ return *this;\r
+}\r
+\r
+VBlankAttachment::~VBlankAttachment()\r
+{\r
+ cleanup();\r
+}\r
+\r
+void VBlankAttachment::onVBlank()\r
+{\r
+ callback();\r
+}\r
+\r
+void VBlankAttachment::componentParentHierarchyChanged (Component&)\r
+{\r
+ updatePeer();\r
+}\r
+\r
+void VBlankAttachment::updateOwner()\r
+{\r
+ if (auto previousLastOwner = std::exchange (lastOwner, owner); previousLastOwner != owner)\r
+ {\r
+ if (previousLastOwner != nullptr)\r
+ previousLastOwner->removeComponentListener (this);\r
+\r
+ if (owner != nullptr)\r
+ owner->addComponentListener (this);\r
+ }\r
+}\r
+\r
+void VBlankAttachment::updatePeer()\r
+{\r
+ if (owner != nullptr)\r
+ {\r
+ if (auto* peer = owner->getPeer())\r
+ {\r
+ peer->addVBlankListener (this);\r
+\r
+ if (lastPeer != peer && ComponentPeer::isValidPeer (lastPeer))\r
+ lastPeer->removeVBlankListener (this);\r
+\r
+ lastPeer = peer;\r
+ }\r
+ }\r
+ else if (auto peer = std::exchange (lastPeer, nullptr); ComponentPeer::isValidPeer (peer))\r
+ {\r
+ peer->removeVBlankListener (this);\r
+ }\r
+}\r
+\r
+void VBlankAttachment::cleanup()\r
+{\r
+ owner = nullptr;\r
+ updateOwner();\r
+ updatePeer();\r
+}\r
+\r
+} // namespace juce\r
--- /dev/null
+/*\r
+ ==============================================================================\r
+\r
+ This file is part of the JUCE library.\r
+ Copyright (c) 2022 - Raw Material Software Limited\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 7 End-User License\r
+ Agreement and JUCE Privacy Policy.\r
+\r
+ End User License Agreement: www.juce.com/juce-7-licence\r
+ Privacy Policy: www.juce.com/juce-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
+namespace juce\r
+{\r
+\r
+/** Helper class to synchronise Component updates to the vertical blank event of the display that\r
+ the Component is presented on. This is useful when animating the Component's contents.\r
+*/\r
+class JUCE_API VBlankAttachment final : public ComponentPeer::VBlankListener,\r
+ public ComponentListener\r
+{\r
+public:\r
+ /** Default constructor for creating an empty object. */\r
+ VBlankAttachment() {}\r
+\r
+ /** Constructor. Creates an attachment that will call the passed in function at every vertical\r
+ blank event of the display that the passed in Component is currently visible on.\r
+\r
+ The Component must be valid for the entire lifetime of the VBlankAttachment.\r
+ */\r
+ VBlankAttachment (Component* c, std::function<void()> callbackIn);\r
+ VBlankAttachment (VBlankAttachment&& other);\r
+ VBlankAttachment& operator= (VBlankAttachment&& other);\r
+\r
+ /** Destructor. */\r
+ ~VBlankAttachment() override;\r
+\r
+ /** Returns true for a default constructed object. */\r
+ bool isEmpty() { return owner == nullptr; }\r
+\r
+ //==============================================================================\r
+ void onVBlank() override;\r
+\r
+ //==============================================================================\r
+ void componentParentHierarchyChanged (Component&) override;\r
+\r
+private:\r
+ void updateOwner();\r
+ void updatePeer();\r
+ void cleanup();\r
+\r
+ Component* owner = nullptr;\r
+ Component* lastOwner = nullptr;\r
+ std::function<void()> callback;\r
+ ComponentPeer* lastPeer = nullptr;\r
+\r
+ JUCE_DECLARE_NON_COPYABLE (VBlankAttachment)\r
+};\r
+\r
+} // namespace juce\r
*/\r
bool areMouseEventsAllowed() const noexcept { return mouseEventsAllowed; }\r
\r
+ //==============================================================================\r
+ /** Set an instance of IDispatch where dispatch events should be delivered to\r
+ */\r
+ void setEventHandler (void* eventHandler);\r
+\r
//==============================================================================\r
/** @internal */\r
void paint (Graphics&) override;\r
/** Resizes this component to fit the view that it contains. */\r
void resizeToFitView();\r
\r
+ /** Resizes the NSView to match the bounds of this component.\r
+\r
+ Most of the time, this will be done for you automatically.\r
+ */\r
+ void resizeViewToFit();\r
+\r
//==============================================================================\r
/** @internal */\r
void paint (Graphics&) override;\r
#include "native/juce_android_WebBrowserComponent.cpp"\r
#endif\r
#endif\r
-\r
-//==============================================================================\r
-#if ! JUCE_WINDOWS && JUCE_WEB_BROWSER\r
- juce::WebBrowserComponent::WebBrowserComponent (ConstructWithoutPimpl) {}\r
- juce::WindowsWebView2WebBrowserComponent::WindowsWebView2WebBrowserComponent (bool unloadWhenHidden,\r
- const WebView2Preferences&)\r
- : WebBrowserComponent (unloadWhenHidden) {}\r
-#endif\r
\r
ID: juce_gui_extra\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_gui_basics\r
OSXFrameworks: WebKit\r
{\r
\r
AnimatedAppComponent::AnimatedAppComponent()\r
- : lastUpdateTime (Time::getCurrentTime()), totalUpdates (0)\r
{\r
setOpaque (true);\r
}\r
\r
-void AnimatedAppComponent::setFramesPerSecond (int framesPerSecond)\r
+void AnimatedAppComponent::setFramesPerSecond (int framesPerSecondIn)\r
{\r
- jassert (framesPerSecond > 0 && framesPerSecond < 1000);\r
- startTimerHz (framesPerSecond);\r
+ jassert (0 < framesPerSecond && framesPerSecond < 1000);\r
+ framesPerSecond = framesPerSecondIn;\r
+ updateSync();\r
+}\r
+\r
+void AnimatedAppComponent::updateSync()\r
+{\r
+ if (useVBlank)\r
+ {\r
+ stopTimer();\r
+\r
+ if (vBlankAttachment.isEmpty())\r
+ vBlankAttachment = { this, [this] { timerCallback(); } };\r
+ }\r
+ else\r
+ {\r
+ vBlankAttachment = {};\r
+\r
+ const auto interval = 1000 / framesPerSecond;\r
+\r
+ if (getTimerInterval() != interval)\r
+ startTimer (interval);\r
+ }\r
+}\r
+\r
+void AnimatedAppComponent::setSynchroniseToVBlank (bool syncToVBlank)\r
+{\r
+ useVBlank = syncToVBlank;\r
+ updateSync();\r
}\r
\r
int AnimatedAppComponent::getMillisecondsSinceLastUpdate() const noexcept\r
*/\r
void setFramesPerSecond (int framesPerSecond);\r
\r
+ /** You can use this function to synchronise animation updates with the current display's vblank\r
+ events. When this mode is enabled the value passed to setFramesPerSecond() is ignored.\r
+ */\r
+ void setSynchroniseToVBlank (bool syncToVBlank);\r
+\r
/** Called periodically, at the frequency specified by setFramesPerSecond().\r
This is a the best place to do things like advancing animation parameters,\r
checking the mouse position, etc.\r
\r
private:\r
//==============================================================================\r
- Time lastUpdateTime;\r
- int totalUpdates;\r
+ void updateSync();\r
+\r
+ Time lastUpdateTime = Time::getCurrentTime();\r
+ int totalUpdates = 0;\r
+ int framesPerSecond = 60;\r
+ bool useVBlank = false;\r
+ VBlankAttachment vBlankAttachment;\r
\r
void timerCallback() override;\r
\r
{\r
public:\r
//==============================================================================\r
+ class JUCE_API Options\r
+ {\r
+ public:\r
+ //==============================================================================\r
+ enum class Backend\r
+ {\r
+ /**\r
+ Default web browser backend. WebKit will be used on macOS, gtk-webkit2 on Linux and internet\r
+ explorer on Windows. On Windows, the default may change to webview2 in the fututre.\r
+ */\r
+ defaultBackend,\r
+\r
+ /**\r
+ Use Internet Explorer as the backend on Windows. By default, IE will use an ancient version\r
+ of IE. To change this behaviour, you either need to add the following html element into your page's\r
+ head section:\r
+\r
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />\r
+\r
+ or you need to change windows registry values for your application. More infromation on the latter\r
+ can be found here:\r
+\r
+ https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/general-info/ee330730(v=vs.85)?redirectedfrom=MSDN#browser-emulation\r
+ */\r
+ ie,\r
+\r
+ /**\r
+ Use the chromium based WebView2 engine on Windows\r
+ */\r
+ webview2\r
+ };\r
+\r
+ /**\r
+ Use a particular backend to create the WebViewBrowserComponent. JUCE will silently\r
+ fallback to the default backend if the selected backend is not supported. To check\r
+ if a specific backend is supported on your platform or not, use\r
+ WebBrowserComponent::areOptionsSupported.\r
+ */\r
+ [[nodiscard]] Options withBackend (Backend backend) const { return withMember (*this, &Options::browserBackend, backend); }\r
+\r
+ //==============================================================================\r
+ /**\r
+ Tell JUCE to keep the web page alive when the WebBrowserComponent is not visible.\r
+ By default, JUCE will replace the current page with a blank page - this can be\r
+ handy to stop the browser using resources in the background when it's not\r
+ actually being used.\r
+ */\r
+ [[nodiscard]] Options withKeepPageLoadedWhenBrowserIsHidden () const { return withMember (*this, &Options::keepPageLoadedWhenBrowserIsHidden, true); }\r
+\r
+ /**\r
+ Use a specific user agent string when requesting web pages.\r
+ */\r
+ [[nodiscard]] Options withUserAgent (String ua) const { return withMember (*this, &Options::userAgent, std::move (ua)); }\r
+\r
+ //==============================================================================\r
+ /** Options specific to the WebView2 backend. These options will be ignored\r
+ if another backend is used.\r
+ */\r
+ class WinWebView2\r
+ {\r
+ public:\r
+ //==============================================================================\r
+ /** Sets a custom location for the WebView2Loader.dll that is not a part of the\r
+ standard system DLL search paths.\r
+ */\r
+ [[nodiscard]] WinWebView2 withDLLLocation (const File& location) const { return withMember (*this, &WinWebView2::dllLocation, location); }\r
+\r
+ /** Sets a non-default location for storing user data for the browser instance. */\r
+ [[nodiscard]] WinWebView2 withUserDataFolder (const File& folder) const { return withMember (*this, &WinWebView2::userDataFolder, folder); }\r
+\r
+ /** If this is set, the status bar usually displayed in the lower-left of the webview\r
+ will be disabled.\r
+ */\r
+ [[nodiscard]] WinWebView2 withStatusBarDisabled() const { return withMember (*this, &WinWebView2::disableStatusBar, true); }\r
+\r
+ /** If this is set, a blank page will be displayed on error instead of the default\r
+ built-in error page.\r
+ */\r
+ [[nodiscard]] WinWebView2 withBuiltInErrorPageDisabled() const { return withMember (*this, &WinWebView2::disableBuiltInErrorPage, true); }\r
+\r
+ /** Sets the background colour that WebView2 renders underneath all web content.\r
+\r
+ This colour must either be fully opaque or transparent. On Windows 7 this\r
+ colour must be opaque.\r
+ */\r
+ [[nodiscard]] WinWebView2 withBackgroundColour (const Colour& colour) const\r
+ {\r
+ // the background colour must be either fully opaque or transparent!\r
+ jassert (colour.isOpaque() || colour.isTransparent());\r
+\r
+ return withMember (*this, &WinWebView2::backgroundColour, colour);\r
+ }\r
+\r
+ //==============================================================================\r
+ File getDLLLocation() const { return dllLocation; }\r
+ File getUserDataFolder() const { return userDataFolder; }\r
+ bool getIsStatusBarDisabled() const noexcept { return disableStatusBar; }\r
+ bool getIsBuiltInErrorPageDisabled() const noexcept { return disableBuiltInErrorPage; }\r
+ Colour getBackgroundColour() const { return backgroundColour; }\r
+\r
+ private:\r
+ //==============================================================================\r
+ File dllLocation, userDataFolder;\r
+ bool disableStatusBar = false, disableBuiltInErrorPage = false;\r
+ Colour backgroundColour;\r
+ };\r
+\r
+ [[nodiscard]] Options withWinWebView2Options (const WinWebView2& winWebView2Options) const\r
+ {\r
+ return withMember (*this, &Options::winWebView2, winWebView2Options);\r
+ }\r
+\r
+ //==============================================================================\r
+ Backend getBackend() const noexcept { return browserBackend; }\r
+ bool keepsPageLoadedWhenBrowserIsHidden() const noexcept { return keepPageLoadedWhenBrowserIsHidden; }\r
+ String getUserAgent() const { return userAgent; }\r
+ WinWebView2 getWinWebView2BackendOptions() const { return winWebView2; }\r
+\r
+ private:\r
+ //==============================================================================\r
+ Backend browserBackend = Backend::defaultBackend;\r
+ bool keepPageLoadedWhenBrowserIsHidden = false;\r
+ String userAgent;\r
+ WinWebView2 winWebView2;\r
+ };\r
+\r
+ //==============================================================================\r
+ /** Creates a WebBrowserComponent with default options*/\r
+ WebBrowserComponent() : WebBrowserComponent (Options {}) {}\r
+\r
/** Creates a WebBrowserComponent.\r
\r
Once it's created and visible, send the browser to a URL using goToURL().\r
the browser using resources in the background when it's not\r
actually being used.\r
*/\r
- explicit WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true);\r
+ explicit WebBrowserComponent (const Options& options);\r
\r
/** Destructor. */\r
~WebBrowserComponent() override;\r
\r
+ //==============================================================================\r
+ /** Check if the specified options are supported on this platform. */\r
+ static bool areOptionsSupported (const Options& options);\r
+\r
//==============================================================================\r
/** Sends the browser to a particular URL.\r
\r
/** @internal */\r
class Pimpl;\r
\r
-protected:\r
- friend class WindowsWebView2WebBrowserComponent;\r
-\r
- /** @internal */\r
- struct ConstructWithoutPimpl\r
- {\r
- explicit ConstructWithoutPimpl (bool unloadOnHide) : unloadWhenHidden (unloadOnHide) {}\r
- const bool unloadWhenHidden;\r
- };\r
- explicit WebBrowserComponent (ConstructWithoutPimpl);\r
-\r
private:\r
//==============================================================================\r
std::unique_ptr<Pimpl> browser;\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebBrowserComponent)\r
};\r
-\r
-//==============================================================================\r
-/** Class used to create a set of preferences to pass to the WindowsWebView2WebBrowserComponent\r
- wrapper constructor to modify aspects of its behaviour and settings.\r
-\r
- You can chain together a series of calls to this class's methods to create a set of whatever\r
- preferences you want to specify.\r
-\r
- @tags{GUI}\r
-*/\r
-class JUCE_API WebView2Preferences\r
-{\r
-public:\r
- //==============================================================================\r
- /** Sets a custom location for the WebView2Loader.dll that is not a part of the\r
- standard system DLL search paths.\r
- */\r
- JUCE_NODISCARD WebView2Preferences withDLLLocation (const File& location) const { return with (&WebView2Preferences::dllLocation, location); }\r
-\r
- /** Sets a non-default location for storing user data for the browser instance. */\r
- WebView2Preferences withUserDataFolder (const File& folder) const { return with (&WebView2Preferences::userDataFolder, folder); }\r
-\r
- /** If this is set, the status bar usually displayed in the lower-left of the webview\r
- will be disabled.\r
- */\r
- JUCE_NODISCARD WebView2Preferences withStatusBarDisabled() const { return with (&WebView2Preferences::disableStatusBar, true); }\r
-\r
- /** If this is set, a blank page will be displayed on error instead of the default\r
- built-in error page.\r
- */\r
- JUCE_NODISCARD WebView2Preferences withBuiltInErrorPageDisabled() const { return with (&WebView2Preferences::disableBuiltInErrorPage, true); }\r
-\r
- /** Sets the background colour that WebView2 renders underneath all web content.\r
-\r
- This colour must either be fully opaque or transparent. On Windows 7 this\r
- colour must be opaque.\r
- */\r
- JUCE_NODISCARD WebView2Preferences withBackgroundColour (const Colour& colour) const\r
- {\r
- // the background colour must be either fully opaque or transparent!\r
- jassert (colour.isOpaque() || colour.isTransparent());\r
-\r
- return with (&WebView2Preferences::backgroundColour, colour);\r
- }\r
-\r
- //==============================================================================\r
- File getDLLLocation() const { return dllLocation; }\r
- File getUserDataFolder() const { return userDataFolder; }\r
- bool getIsStatusBarDisabled() const noexcept { return disableStatusBar; }\r
- bool getIsBuiltInErrorPageDisabled() const noexcept { return disableBuiltInErrorPage; }\r
- Colour getBackgroundColour() const { return backgroundColour; }\r
-\r
-private:\r
- //==============================================================================\r
- template <typename Member, typename Item>\r
- WebView2Preferences with (Member&& member, Item&& item) const\r
- {\r
- auto options = *this;\r
- options.*member = std::forward<Item> (item);\r
-\r
- return options;\r
- }\r
-\r
- File dllLocation, userDataFolder;\r
- bool disableStatusBar = false, disableBuiltInErrorPage = false;\r
- Colour backgroundColour = Colours::white;\r
-};\r
-\r
-/**\r
- If you have enabled the JUCE_USE_WIN_WEBVIEW2 flag then this wrapper will attempt to\r
- use the Microsoft Edge (Chromium) WebView2 control instead of IE on Windows. It will\r
- behave the same as WebBrowserComponent on all other platforms and will fall back to\r
- IE on Windows if the WebView2 requirements are not met.\r
-\r
- This requires Microsoft Edge (minimum version 82.0.488.0) to be installed at runtime.\r
-\r
- Currently this also requires that WebView2Loader.dll, which can be found in the\r
- Microsoft.Web.WebView package, is installed at runtime. As this is not a standard\r
- system DLL, we can't rely on it being found via the normal system DLL search paths.\r
- Therefore in order to use WebView2 you need to ensure that WebView2Loader.dll is\r
- installed either to a location covered by the Windows DLL system search paths or\r
- to the folder specified in the WebView2Preferences.\r
-\r
- @tags{GUI}\r
-*/\r
-class WindowsWebView2WebBrowserComponent : public WebBrowserComponent\r
-{\r
-public:\r
- //==============================================================================\r
- /** Creates a WebBrowserComponent that is compatible with the WebView2 control\r
- on Windows.\r
-\r
- @param unloadPageWhenBrowserIsHidden if this is true, then when the browser\r
- component is taken offscreen, it'll clear the current page\r
- and replace it with a blank page - this can be handy to stop\r
- the browser using resources in the background when it's not\r
- actually being used.\r
- @param preferences a set of preferences used to control aspects of the webview's\r
- behaviour.\r
-\r
- @see WebView2Preferences\r
- */\r
- WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,\r
- const WebView2Preferences& preferences = {});\r
-\r
- // This constructor has been deprecated. Use the new constructor that takes a\r
- // WebView2Preferences instead.\r
- explicit WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,\r
- const File& dllLocation = {},\r
- const File& userDataFolder = {})\r
- : WindowsWebView2WebBrowserComponent (unloadPageWhenBrowserIsHidden,\r
- WebView2Preferences().withDLLLocation (dllLocation)\r
- .withUserDataFolder (userDataFolder))\r
- {\r
- }\r
-};\r
-\r
#endif\r
\r
} // namespace juce\r
METHOD (setBuiltInZoomControls, "setBuiltInZoomControls", "(Z)V") \\r
METHOD (setDisplayZoomControls, "setDisplayZoomControls", "(Z)V") \\r
METHOD (setJavaScriptEnabled, "setJavaScriptEnabled", "(Z)V") \\r
- METHOD (setSupportMultipleWindows, "setSupportMultipleWindows", "(Z)V")\r
+ METHOD (setSupportMultipleWindows, "setSupportMultipleWindows", "(Z)V") \\r
+ METHOD (setUserAgentString, "setUserAgentString", "(Ljava/lang/String;)V")\r
\r
DECLARE_JNI_CLASS (WebSettings, "android/webkit/WebSettings")\r
#undef JNI_CLASS_MEMBERS\r
public AsyncUpdater\r
{\r
public:\r
- Pimpl (WebBrowserComponent& o)\r
+ Pimpl (WebBrowserComponent& o, const String& userAgent)\r
: owner (o)\r
{\r
auto* env = getEnv();\r
env->CallVoidMethod (settings, WebSettings.setDisplayZoomControls, false);\r
env->CallVoidMethod (settings, WebSettings.setSupportMultipleWindows, true);\r
\r
+ if (userAgent.isNotEmpty())\r
+ env->CallVoidMethod (settings, WebSettings.setUserAgentString, javaString (userAgent).get());\r
+\r
juceWebChromeClient = GlobalRef (LocalRef<jobject> (env->NewObject (JuceWebChromeClient, JuceWebChromeClient.constructor,\r
reinterpret_cast<jlong> (this))));\r
env->CallVoidMethod ((jobject) getView(), AndroidWebView.setWebChromeClient, juceWebChromeClient.get());\r
};\r
\r
//==============================================================================\r
-WebBrowserComponent::WebBrowserComponent (const bool unloadWhenHidden)\r
+WebBrowserComponent::WebBrowserComponent (const Options& options)\r
: blankPageShown (false),\r
- unloadPageWhenHidden (unloadWhenHidden)\r
+ unloadPageWhenHidden (! options.keepsPageLoadedWhenBrowserIsHidden())\r
{\r
setOpaque (true);\r
\r
- browser.reset (new Pimpl (*this));\r
+ browser.reset (new Pimpl (*this, options.getUserAgent()));\r
addAndMakeVisible (browser.get());\r
}\r
\r
}\r
}\r
\r
+bool WebBrowserComponent::areOptionsSupported (const Options& options)\r
+{\r
+ return (options.getBackend() == Options::Backend::defaultBackend);\r
+}\r
+\r
WebBrowserComponent::Pimpl::JuceWebViewClient16_Class WebBrowserComponent::Pimpl::JuceWebViewClient16;\r
WebBrowserComponent::Pimpl::JuceWebViewClient21_Class WebBrowserComponent::Pimpl::JuceWebViewClient21;\r
WebBrowserComponent::Pimpl::JuceWebChromeClient_Class WebBrowserComponent::Pimpl::JuceWebChromeClient;\r
JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_settings_set_hardware_acceleration_policy, juce_webkit_settings_set_hardware_acceleration_policy,\r
(WebKitSettings*, int), void)\r
\r
+ JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_settings_set_user_agent, juce_webkit_settings_set_user_agent,\r
+ (WebKitSettings*, const gchar*), void)\r
+\r
JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_web_view_new_with_settings, juce_webkit_web_view_new_with_settings,\r
(WebKitSettings*), GtkWidget*)\r
\r
JUCE_GENERATE_FUNCTION_WITH_DEFAULT (g_signal_connect_data, juce_g_signal_connect_data,\r
(gpointer, const gchar*, GCallback, gpointer, GClosureNotify, GConnectFlags), gulong)\r
\r
+ //==============================================================================\r
+ JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gdk_set_allowed_backends, juce_gdk_set_allowed_backends,\r
+ (const char*), void)\r
+\r
//==============================================================================\r
JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL (WebKitSymbols)\r
\r
return loadSymbols (webkitLib,\r
makeSymbolBinding (juce_webkit_settings_new, "webkit_settings_new"),\r
makeSymbolBinding (juce_webkit_settings_set_hardware_acceleration_policy, "webkit_settings_set_hardware_acceleration_policy"),\r
+ makeSymbolBinding (juce_webkit_settings_set_user_agent, "webkit_settings_set_user_agent"),\r
makeSymbolBinding (juce_webkit_web_view_new_with_settings, "webkit_web_view_new_with_settings"),\r
makeSymbolBinding (juce_webkit_policy_decision_use, "webkit_policy_decision_use"),\r
makeSymbolBinding (juce_webkit_policy_decision_ignore, "webkit_policy_decision_ignore"),\r
bool loadGtkSymbols()\r
{\r
return loadSymbols (gtkLib,\r
- makeSymbolBinding (juce_gtk_init, "gtk_init"),\r
- makeSymbolBinding (juce_gtk_plug_new, "gtk_plug_new"),\r
- makeSymbolBinding (juce_gtk_scrolled_window_new, "gtk_scrolled_window_new"),\r
- makeSymbolBinding (juce_gtk_container_add, "gtk_container_add"),\r
- makeSymbolBinding (juce_gtk_widget_show_all, "gtk_widget_show_all"),\r
- makeSymbolBinding (juce_gtk_plug_get_id, "gtk_plug_get_id"),\r
- makeSymbolBinding (juce_gtk_main, "gtk_main"),\r
- makeSymbolBinding (juce_gtk_main_quit, "gtk_main_quit"),\r
- makeSymbolBinding (juce_g_unix_fd_add, "g_unix_fd_add"),\r
- makeSymbolBinding (juce_g_object_ref, "g_object_ref"),\r
- makeSymbolBinding (juce_g_object_unref, "g_object_unref"),\r
- makeSymbolBinding (juce_g_signal_connect_data, "g_signal_connect_data"));\r
+ makeSymbolBinding (juce_gtk_init, "gtk_init"),\r
+ makeSymbolBinding (juce_gtk_plug_new, "gtk_plug_new"),\r
+ makeSymbolBinding (juce_gtk_scrolled_window_new, "gtk_scrolled_window_new"),\r
+ makeSymbolBinding (juce_gtk_container_add, "gtk_container_add"),\r
+ makeSymbolBinding (juce_gtk_widget_show_all, "gtk_widget_show_all"),\r
+ makeSymbolBinding (juce_gtk_plug_get_id, "gtk_plug_get_id"),\r
+ makeSymbolBinding (juce_gtk_main, "gtk_main"),\r
+ makeSymbolBinding (juce_gtk_main_quit, "gtk_main_quit"),\r
+ makeSymbolBinding (juce_g_unix_fd_add, "g_unix_fd_add"),\r
+ makeSymbolBinding (juce_g_object_ref, "g_object_ref"),\r
+ makeSymbolBinding (juce_g_object_unref, "g_object_unref"),\r
+ makeSymbolBinding (juce_g_signal_connect_data, "g_signal_connect_data"),\r
+ makeSymbolBinding (juce_gdk_set_allowed_backends, "gdk_set_allowed_backends"));\r
}\r
\r
//==============================================================================\r
{\r
public:\r
//==============================================================================\r
- GtkChildProcess (int inChannel, int outChannelToUse)\r
+ GtkChildProcess (int inChannel, int outChannelToUse, const String& userAgentToUse)\r
: outChannel (outChannelToUse),\r
- receiver (this, inChannel)\r
+ receiver (this, inChannel),\r
+ userAgent (userAgentToUse)\r
{}\r
\r
int entry()\r
{\r
CommandReceiver::setBlocking (outChannel, true);\r
\r
+ // webkit2gtk crashes when using the wayland backend embedded into an x11 window\r
+ WebKitSymbols::getInstance()->juce_gdk_set_allowed_backends ("x11");\r
+\r
WebKitSymbols::getInstance()->juce_gtk_init (nullptr, nullptr);\r
\r
auto* settings = WebKitSymbols::getInstance()->juce_webkit_settings_new();\r
WebKitSymbols::getInstance()->juce_webkit_settings_set_hardware_acceleration_policy (settings,\r
/* WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER */ 2);\r
+ if (userAgent.isNotEmpty())\r
+ WebKitSymbols::getInstance()->juce_webkit_settings_set_user_agent (settings, userAgent.toRawUTF8());\r
\r
auto* plug = WebKitSymbols::getInstance()->juce_gtk_plug_new (0);\r
auto* container = WebKitSymbols::getInstance()->juce_gtk_scrolled_window_new (nullptr, nullptr);\r
\r
int outChannel = 0;\r
CommandReceiver receiver;\r
+ String userAgent;\r
WebKitWebView* webview = nullptr;\r
Array<WebKitPolicyDecision*> decisions;\r
};\r
private CommandReceiver::Responder\r
{\r
public:\r
- Pimpl (WebBrowserComponent& parent)\r
- : Thread ("Webview"), owner (parent)\r
+ Pimpl (WebBrowserComponent& parent, const String& userAgentToUse)\r
+ : Thread ("Webview"), owner (parent), userAgent (userAgentToUse)\r
{\r
webKitIsAvailable = WebKitSymbols::getInstance()->isWebKitAvailable();\r
}\r
close (inPipe[0]);\r
close (outPipe[1]);\r
\r
- HeapBlock<const char*> argv (5);\r
StringArray arguments;\r
\r
arguments.add (File::getSpecialLocation (File::currentExecutableFile).getFullPathName());\r
arguments.add (String (outPipe[0]));\r
arguments.add (String (inPipe [1]));\r
\r
- for (int i = 0; i < arguments.size(); ++i)\r
- argv[i] = arguments[i].toRawUTF8();\r
+ if (userAgent.isNotEmpty())\r
+ arguments.add (userAgent);\r
+\r
+ std::vector<const char*> argv;\r
+ argv.reserve (static_cast<std::size_t> (arguments.size() + 1));\r
\r
- argv[4] = nullptr;\r
+ for (const auto& arg : arguments)\r
+ argv.push_back (arg.toRawUTF8());\r
+\r
+ argv.push_back (nullptr);\r
\r
if (JUCEApplicationBase::isStandaloneApp())\r
- execv (arguments[0].toRawUTF8(), (char**) argv.getData());\r
+ execv (arguments[0].toRawUTF8(), (char**) argv.data());\r
else\r
- juce_gtkWebkitMain (4, (const char**) argv.getData());\r
+ juce_gtkWebkitMain (arguments.size(), (const char**) argv.data());\r
\r
exit (0);\r
}\r
bool webKitIsAvailable = false;\r
\r
WebBrowserComponent& owner;\r
+ String userAgent;\r
std::unique_ptr<CommandReceiver> receiver;\r
int childProcess = 0, inChannel = 0, outChannel = 0;\r
int threadControl[2];\r
};\r
\r
//==============================================================================\r
-WebBrowserComponent::WebBrowserComponent (const bool unloadWhenHidden)\r
- : browser (new Pimpl (*this)),\r
- unloadPageWhenHidden (unloadWhenHidden)\r
+WebBrowserComponent::WebBrowserComponent (const Options& options)\r
+ : browser (new Pimpl (*this, options.getUserAgent()))\r
{\r
ignoreUnused (blankPageShown);\r
ignoreUnused (unloadPageWhenHidden);\r
jassertfalse;\r
}\r
\r
+bool WebBrowserComponent::areOptionsSupported (const Options& options)\r
+{\r
+ return (options.getBackend() == Options::Backend::defaultBackend);\r
+}\r
+\r
int juce_gtkWebkitMain (int argc, const char* argv[])\r
{\r
- if (argc != 4)\r
+ if (argc < 4)\r
return -1;\r
\r
GtkChildProcess child (String (argv[2]).getIntValue(),\r
- String (argv[3]).getIntValue());\r
+ String (argv[3]).getIntValue(),\r
+ argc >= 5 ? String (argv[4]) : String());\r
\r
return child.entry();\r
}\r
}\r
}\r
\r
+void NSViewComponent::resizeViewToFit()\r
+{\r
+ if (attachment != nullptr)\r
+ static_cast<NSViewAttachment*> (attachment.get())->componentMovedOrResized (true, true);\r
+}\r
+\r
void NSViewComponent::paint (Graphics&) {}\r
\r
void NSViewComponent::alphaChanged()\r
using Action = PushNotifications::Notification::Action;\r
\r
//==============================================================================\r
- NSUserNotification* juceNotificationToNSUserNotification (const PushNotifications::Notification& n,\r
- bool isEarlierThanMavericks,\r
- bool isEarlierThanYosemite)\r
+ static NSUserNotification* juceNotificationToNSUserNotification (const PushNotifications::Notification& n)\r
{\r
auto notification = [[NSUserNotification alloc] init];\r
\r
if (n.actions.size() > 0)\r
notification.actionButtonTitle = juceStringToNS (n.actions.getReference (0).title);\r
\r
- if (! isEarlierThanMavericks)\r
+ if (@available (macOS 10.9, *))\r
{\r
notification.identifier = juceStringToNS (n.identifier);\r
\r
\r
notification.contentImage = [[NSImage alloc] initWithContentsOfFile: imagePath];\r
\r
- if (! isEarlierThanYosemite)\r
+ if (@available (macOS 10.10, *))\r
{\r
if (n.actions.size() > 1)\r
{\r
}\r
\r
//==============================================================================\r
- PushNotifications::Notification nsUserNotificationToJuceNotification (NSUserNotification* n,\r
- bool isEarlierThanMavericks,\r
- bool isEarlierThanYosemite)\r
+ static PushNotifications::Notification nsUserNotificationToJuceNotification (NSUserNotification* n)\r
{\r
PushNotifications::Notification notif;\r
\r
notif.soundToPlay = URL (nsStringToJuce (n.soundName));\r
notif.properties = nsDictionaryToVar (n.userInfo);\r
\r
- if (! isEarlierThanMavericks)\r
+ if (@available (macOS 10.9, *))\r
{\r
notif.identifier = nsStringToJuce (n.identifier);\r
\r
Action action;\r
action.title = nsStringToJuce (n.actionButtonTitle);\r
\r
- if (! isEarlierThanMavericks)\r
+ if (@available (macOS 10.9, *))\r
{\r
if (n.hasReplyButton)\r
action.style = Action::text;\r
actions.add (action);\r
}\r
\r
- if (! isEarlierThanYosemite)\r
+ if (@available (macOS 10.10, *))\r
{\r
if (n.additionalActions != nil)\r
{\r
}\r
\r
//==============================================================================\r
- var getNotificationPropertiesFromDictionaryVar (const var& dictionaryVar)\r
+ static var getNotificationPropertiesFromDictionaryVar (const var& dictionaryVar)\r
{\r
auto* dictionaryVarObject = dictionaryVar.getDynamicObject();\r
\r
return var (propsVarObject.get());\r
}\r
\r
- PushNotifications::Notification nsDictionaryToJuceNotification (NSDictionary* dictionary)\r
+ static PushNotifications::Notification nsDictionaryToJuceNotification (NSDictionary* dictionary)\r
{\r
const var dictionaryVar = nsDictionaryToVar (dictionary);\r
\r
\r
void requestPermissionsWithSettings (const PushNotifications::Settings& settingsToUse)\r
{\r
- if (isEarlierThanLion)\r
- return;\r
-\r
- settings = settingsToUse;\r
+ if (@available (macOS 10.7, *))\r
+ {\r
+ settings = settingsToUse;\r
\r
- NSRemoteNotificationType types = NSUInteger ((bool) settings.allowBadge);\r
+ NSRemoteNotificationType types = NSUInteger ((bool) settings.allowBadge);\r
\r
- if (isAtLeastMountainLion)\r
- types |= (NSUInteger) ((bool) settings.allowSound << 1 | (bool) settings.allowAlert << 2);\r
+ if (@available (macOS 10.8, *))\r
+ {\r
+ types |= (NSUInteger) ((settings.allowSound ? NSRemoteNotificationTypeSound : 0)\r
+ | (settings.allowAlert ? NSRemoteNotificationTypeAlert : 0));\r
+ }\r
\r
- [[NSApplication sharedApplication] registerForRemoteNotificationTypes: types];\r
+ [[NSApplication sharedApplication] registerForRemoteNotificationTypes: types];\r
+ }\r
}\r
\r
void requestSettingsUsed()\r
{\r
- if (isEarlierThanLion)\r
+ if (@available (macOS 10.7, *))\r
{\r
- // no settings available\r
- owner.listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); });\r
- return;\r
- }\r
+ settings.allowBadge = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeBadge;\r
\r
- settings.allowBadge = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeBadge;\r
+ if (@available (macOS 10.8, *))\r
+ {\r
+ settings.allowSound = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeSound;\r
+ settings.allowAlert = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeAlert;\r
+ }\r
\r
- if (isAtLeastMountainLion)\r
+ owner.listeners.call ([&] (Listener& l) { l.notificationSettingsReceived (settings); });\r
+ }\r
+ else\r
{\r
- settings.allowSound = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeSound;\r
- settings.allowAlert = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeAlert;\r
+ // no settings available\r
+ owner.listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); });\r
}\r
-\r
- owner.listeners.call ([&] (Listener& l) { l.notificationSettingsReceived (settings); });\r
}\r
\r
bool areNotificationsEnabled() const { return true; }\r
\r
void sendLocalNotification (const Notification& n)\r
{\r
- auto* notification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n, isEarlierThanMavericks, isEarlierThanYosemite);\r
+ auto* notification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n);\r
\r
[[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification: notification];\r
}\r
Array<PushNotifications::Notification> notifs;\r
\r
for (NSUserNotification* n in [NSUserNotificationCenter defaultUserNotificationCenter].deliveredNotifications)\r
- notifs.add (PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (n, isEarlierThanMavericks, isEarlierThanYosemite));\r
+ notifs.add (PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (n));\r
\r
owner.listeners.call ([&] (Listener& l) { l.deliveredNotificationsListReceived (notifs); });\r
}\r
PushNotifications::Notification n;\r
n.identifier = identifier;\r
\r
- auto nsNotification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n, isEarlierThanMavericks, isEarlierThanYosemite);\r
+ auto nsNotification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n);\r
\r
[[NSUserNotificationCenter defaultUserNotificationCenter] removeDeliveredNotification: nsNotification];\r
}\r
Array<PushNotifications::Notification> notifs;\r
\r
for (NSUserNotification* n in [NSUserNotificationCenter defaultUserNotificationCenter].scheduledNotifications)\r
- notifs.add (PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (n, isEarlierThanMavericks, isEarlierThanYosemite));\r
+ notifs.add (PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (n));\r
\r
owner.listeners.call ([&] (Listener& l) { l.pendingLocalNotificationsListReceived (notifs); });\r
}\r
PushNotifications::Notification n;\r
n.identifier = identifier;\r
\r
- auto nsNotification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n, isEarlierThanMavericks, isEarlierThanYosemite);\r
+ auto nsNotification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n);\r
\r
[[NSUserNotificationCenter defaultUserNotificationCenter] removeScheduledNotification: nsNotification];\r
}\r
\r
void didActivateNotification (NSUserNotification* notification) override\r
{\r
- auto n = PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (notification, isEarlierThanMavericks, isEarlierThanYosemite);\r
+ auto n = PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (notification);\r
\r
if (notification.activationType == NSUserNotificationActivationTypeContentsClicked)\r
{\r
}\r
else\r
{\r
- auto actionIdentifier = (! isEarlierThanYosemite && notification.additionalActivationAction != nil)\r
- ? nsStringToJuce (notification.additionalActivationAction.identifier)\r
- : nsStringToJuce (notification.actionButtonTitle);\r
+ const auto actionIdentifier = nsStringToJuce ([&]\r
+ {\r
+ if (@available (macOS 10.10, *))\r
+ if (notification.additionalActivationAction != nil)\r
+ return notification.additionalActivationAction.identifier;\r
+\r
+ return notification.actionButtonTitle;\r
+ }());\r
\r
auto reply = notification.activationType == NSUserNotificationActivationTypeReplied\r
? nsStringToJuce ([notification.response string])\r
private:\r
PushNotifications& owner;\r
\r
- const bool isEarlierThanLion = std::floor (NSFoundationVersionNumber) < std::floor (NSFoundationVersionNumber10_7);\r
- const bool isAtLeastMountainLion = std::floor (NSFoundationVersionNumber) >= NSFoundationVersionNumber10_7;\r
- const bool isEarlierThanMavericks = std::floor (NSFoundationVersionNumber) < NSFoundationVersionNumber10_9;\r
- const bool isEarlierThanYosemite = std::floor (NSFoundationVersionNumber) <= NSFoundationVersionNumber10_9;\r
-\r
bool initialised = false;\r
String deviceToken;\r
\r
class WebViewImpl : public WebViewBase\r
{\r
public:\r
- WebViewImpl (WebBrowserComponent* owner)\r
+ WebViewImpl (WebBrowserComponent* owner, const String& userAgent)\r
{\r
static WebViewKeyEquivalentResponder<WebView> webviewClass;\r
\r
frameName: nsEmptyString()\r
groupName: nsEmptyString()]);\r
\r
+ webView.get().customUserAgent = juceStringToNS (userAgent);\r
+\r
static DownloadClickDetectorClass cls;\r
clickListener.reset ([cls.createInstance() init]);\r
DownloadClickDetectorClass::setOwner (clickListener.get(), owner);\r
class API_AVAILABLE (macos (10.11)) WKWebViewImpl : public WebViewBase\r
{\r
public:\r
- WKWebViewImpl (WebBrowserComponent* owner)\r
+ WKWebViewImpl (WebBrowserComponent* owner, const String& userAgent)\r
{\r
- #if JUCE_MAC\r
- static WebViewKeyEquivalentResponder<WKWebView> webviewClass;\r
+ #if JUCE_MAC\r
+ static WebViewKeyEquivalentResponder<WKWebView> webviewClass;\r
+\r
+ webView.reset ([webviewClass.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)]);\r
+ #else\r
+ webView.reset ([[WKWebView alloc] initWithFrame: CGRectMake (0, 0, 100.0f, 100.0f)]);\r
+ #endif\r
+\r
+ if (userAgent.isNotEmpty())\r
+ webView.get().customUserAgent = juceStringToNS (userAgent);\r
\r
- webView.reset ([webviewClass.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)]);\r
- #else\r
- webView.reset ([[WKWebView alloc] initWithFrame: CGRectMake (0, 0, 100.0f, 100.0f)]);\r
- #endif\r
+ static WebViewDelegateClass cls;\r
+ webViewDelegate.reset ([cls.createInstance() init]);\r
+ WebViewDelegateClass::setOwner (webViewDelegate.get(), owner);\r
\r
- static WebViewDelegateClass cls;\r
- webViewDelegate.reset ([cls.createInstance() init]);\r
- WebViewDelegateClass::setOwner (webViewDelegate.get(), owner);\r
+ [webView.get() setNavigationDelegate: webViewDelegate.get()];\r
+ [webView.get() setUIDelegate: webViewDelegate.get()];\r
\r
- [webView.get() setNavigationDelegate: webViewDelegate.get()];\r
- [webView.get() setUIDelegate: webViewDelegate.get()];\r
+ #if JUCE_DEBUG\r
+ [[[webView.get() configuration] preferences] setValue: @(true) forKey: @"developerExtrasEnabled"];\r
+ #endif\r
}\r
\r
~WKWebViewImpl() override\r
#endif\r
{\r
public:\r
- Pimpl (WebBrowserComponent* owner)\r
+ Pimpl (WebBrowserComponent* owner, const String& userAgent)\r
{\r
if (@available (macOS 10.11, *))\r
- webView = std::make_unique<WKWebViewImpl> (owner);\r
+ webView = std::make_unique<WKWebViewImpl> (owner, userAgent);\r
#if JUCE_MAC\r
else\r
- webView = std::make_unique<WebViewImpl> (owner);\r
+ webView = std::make_unique<WebViewImpl> (owner, userAgent);\r
#endif\r
\r
setView (webView->getWebView());\r
}\r
\r
- ~Pimpl()\r
+ ~Pimpl() override\r
{\r
webView = nullptr;\r
setView (nil);\r
};\r
\r
//==============================================================================\r
-WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)\r
- : unloadPageWhenHidden (unloadWhenHidden)\r
+WebBrowserComponent::WebBrowserComponent (const Options& options)\r
+ : unloadPageWhenHidden (! options.keepsPageLoadedWhenBrowserIsHidden())\r
{\r
setOpaque (true);\r
- browser.reset (new Pimpl (this));\r
+ browser.reset (new Pimpl (this, options.getUserAgent()));\r
addAndMakeVisible (browser.get());\r
}\r
\r
[[NSUserDefaults standardUserDefaults] synchronize];\r
}\r
\r
+//==============================================================================\r
+bool WebBrowserComponent::areOptionsSupported (const Options& options)\r
+{\r
+ return (options.getBackend() == Options::Backend::defaultBackend);\r
+}\r
+\r
} // namespace juce\r
~JuceIOleClientSite()\r
{\r
inplaceSite->Release();\r
+\r
+ if (dispatchEventHandler != nullptr)\r
+ {\r
+ dispatchEventHandler->Release();\r
+ dispatchEventHandler = nullptr;\r
+ }\r
}\r
\r
JUCE_COMRESULT QueryInterface (REFIID type, void** result)\r
*result = static_cast<IOleInPlaceSite*> (inplaceSite);\r
return S_OK;\r
}\r
+ else if (type == __uuidof(IDispatch) && dispatchEventHandler != nullptr)\r
+ {\r
+ dispatchEventHandler->AddRef();\r
+ *result = dispatchEventHandler;\r
+ return S_OK;\r
+ }\r
\r
return ComBaseClassHelper <IOleClientSite>::QueryInterface (type, result);\r
\r
return S_FALSE;\r
}\r
\r
+ void setEventHandler (void* eventHandler)\r
+ {\r
+ IDispatch* newEventHandler = nullptr;\r
+\r
+ if (eventHandler != nullptr)\r
+ {\r
+ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token")\r
+\r
+ auto iidIDispatch = __uuidof (IDispatch);\r
+\r
+ if (static_cast<IUnknown*>(eventHandler)->QueryInterface (iidIDispatch, (void**) &newEventHandler) != S_OK\r
+ || newEventHandler == nullptr)\r
+ return;\r
+\r
+ JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+ }\r
+\r
+ if (dispatchEventHandler != nullptr)\r
+ dispatchEventHandler->Release();\r
+\r
+ dispatchEventHandler = newEventHandler;\r
+ }\r
+\r
JuceIOleInPlaceSite* inplaceSite;\r
+ IDispatch* dispatchEventHandler = nullptr;\r
};\r
\r
//==============================================================================\r
\r
~Pimpl() override\r
{\r
+ // If the wndproc of the ActiveX HWND isn't set back to it's original\r
+ // wndproc, then clientSite will leak when control is released\r
+ if (controlHWND != nullptr)\r
+ SetWindowLongPtr ((HWND) controlHWND, GWLP_WNDPROC, (LONG_PTR) originalWndProc);\r
+\r
if (control != nullptr)\r
{\r
control->Close (OLECLOSE_NOSAVE);\r
return S_FALSE;\r
}\r
\r
+void ActiveXControlComponent::setEventHandler (void* eventHandler)\r
+{\r
+ if (control->clientSite != nullptr)\r
+ control->clientSite->setEventHandler (eventHandler);\r
+}\r
+\r
LRESULT juce_offerEventToActiveXControl (::MSG& msg);\r
LRESULT juce_offerEventToActiveXControl (::MSG& msg)\r
{\r
public ActiveXControlComponent\r
{\r
public:\r
- Win32WebView (WebBrowserComponent& owner)\r
+ Win32WebView (WebBrowserComponent& parent, const String& userAgentToUse)\r
+ : owner (parent),\r
+ userAgent (userAgentToUse)\r
{\r
owner.addAndMakeVisible (this);\r
}\r
~Win32WebView() override\r
{\r
if (connectionPoint != nullptr)\r
+ {\r
connectionPoint->Unadvise (adviseCookie);\r
+ connectionPoint->Release();\r
+ }\r
\r
if (browser != nullptr)\r
browser->Release();\r
\r
auto iidWebBrowser2 = __uuidof (IWebBrowser2);\r
auto iidConnectionPointContainer = __uuidof (IConnectionPointContainer);\r
+ auto iidOleControl = __uuidof (IOleControl);\r
\r
browser = (IWebBrowser2*) queryInterface (&iidWebBrowser2);\r
\r
\r
if (connectionPoint != nullptr)\r
{\r
- if (auto* owner = dynamic_cast<WebBrowserComponent*> (Component::getParentComponent()))\r
- {\r
- auto handler = new EventHandler (*owner);\r
- connectionPoint->Advise (handler, &adviseCookie);\r
- handler->Release();\r
- }\r
+ auto handler = new EventHandler (*this);\r
+ connectionPoint->Advise (handler, &adviseCookie);\r
+ setEventHandler (handler);\r
+ handler->Release();\r
}\r
+\r
+ connectionPointContainer->Release();\r
+ }\r
+\r
+ if (auto oleControl = (IOleControl*) queryInterface (&iidOleControl))\r
+ {\r
+ oleControl->OnAmbientPropertyChange (/*DISPID_AMBIENT_USERAGENT*/-5513);\r
+ oleControl->Release();\r
}\r
\r
JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
return browser != nullptr;\r
}\r
\r
- void goToURL (const String& url, const StringArray* headers, const MemoryBlock* postData) override\r
+ void goToURL (const String& url, const StringArray* requestedHeaders, const MemoryBlock* postData) override\r
{\r
if (browser != nullptr)\r
{\r
VariantInit (&postDataVar);\r
VariantInit (&headersVar);\r
\r
- if (headers != nullptr)\r
+ StringArray headers;\r
+\r
+ if (userAgent.isNotEmpty())\r
+ headers.add("User-Agent: " + userAgent);\r
+\r
+ if (requestedHeaders != nullptr)\r
+ headers.addArray (*requestedHeaders);\r
+\r
+ if (headers.size() > 0)\r
{\r
V_VT (&headersVar) = VT_BSTR;\r
- V_BSTR (&headersVar) = SysAllocString ((const OLECHAR*) headers->joinIntoString ("\r\n").toWideCharPointer());\r
+ V_BSTR (&headersVar) = SysAllocString ((const OLECHAR*) headers.joinIntoString ("\r\n").toWideCharPointer());\r
}\r
\r
if (postData != nullptr && postData->getSize() > 0)\r
}\r
\r
private:\r
+ WebBrowserComponent& owner;\r
IWebBrowser2* browser = nullptr;\r
IConnectionPoint* connectionPoint = nullptr;\r
DWORD adviseCookie = 0;\r
+ String userAgent;\r
\r
//==============================================================================\r
struct EventHandler : public ComBaseClassHelper<IDispatch>,\r
public ComponentMovementWatcher\r
{\r
- EventHandler (WebBrowserComponent& w) : ComponentMovementWatcher (&w), owner (w) {}\r
+ EventHandler (Win32WebView& w) : ComponentMovementWatcher (&w.owner), owner (w) {}\r
\r
JUCE_COMRESULT GetTypeInfoCount (UINT*) override { return E_NOTIMPL; }\r
JUCE_COMRESULT GetTypeInfo (UINT, LCID, ITypeInfo**) override { return E_NOTIMPL; }\r
JUCE_COMRESULT GetIDsOfNames (REFIID, LPOLESTR*, UINT, LCID, DISPID*) override { return E_NOTIMPL; }\r
\r
JUCE_COMRESULT Invoke (DISPID dispIdMember, REFIID /*riid*/, LCID /*lcid*/, WORD /*wFlags*/, DISPPARAMS* pDispParams,\r
- VARIANT* /*pVarResult*/, EXCEPINFO* /*pExcepInfo*/, UINT* /*puArgErr*/) override\r
+ VARIANT* pVarResult, EXCEPINFO* /*pExcepInfo*/, UINT* /*puArgErr*/) override\r
{\r
+\r
+ if (dispIdMember == /*DISPID_AMBIENT_USERAGENT*/-5513)\r
+ {\r
+ V_VT( pVarResult ) = VT_BSTR;\r
+ V_BSTR( pVarResult ) = SysAllocString ((const OLECHAR*) String(owner.userAgent).toWideCharPointer());;\r
+ return S_OK;\r
+ }\r
+\r
if (dispIdMember == DISPID_BEFORENAVIGATE2)\r
{\r
*pDispParams->rgvarg->pboolVal\r
- = owner.pageAboutToLoad (getStringFromVariant (pDispParams->rgvarg[5].pvarVal)) ? VARIANT_FALSE\r
+ = owner.owner.pageAboutToLoad (getStringFromVariant (pDispParams->rgvarg[5].pvarVal)) ? VARIANT_FALSE\r
: VARIANT_TRUE;\r
return S_OK;\r
}\r
\r
if (dispIdMember == 273 /*DISPID_NEWWINDOW3*/)\r
{\r
- owner.newWindowAttemptingToLoad (pDispParams->rgvarg[0].bstrVal);\r
+ owner.owner.newWindowAttemptingToLoad (pDispParams->rgvarg[0].bstrVal);\r
*pDispParams->rgvarg[3].pboolVal = VARIANT_TRUE;\r
return S_OK;\r
}\r
\r
if (dispIdMember == DISPID_DOCUMENTCOMPLETE)\r
{\r
- owner.pageFinishedLoading (getStringFromVariant (pDispParams->rgvarg[0].pvarVal));\r
+ owner.owner.pageFinishedLoading (getStringFromVariant (pDispParams->rgvarg[0].pvarVal));\r
return S_OK;\r
}\r
\r
String message (messageBuffer, size);\r
LocalFree (messageBuffer);\r
\r
- if (! owner.pageLoadHadNetworkError (message))\r
+ if (! owner.owner.pageLoadHadNetworkError (message))\r
*pDispParams->rgvarg[0].pboolVal = VARIANT_TRUE;\r
}\r
\r
\r
if (dispIdMember == 263 /*DISPID_WINDOWCLOSING*/)\r
{\r
- owner.windowCloseRequest();\r
+ owner.owner.windowCloseRequest();\r
\r
// setting this bool tells the browser to ignore the event - we'll handle it.\r
if (pDispParams->cArgs > 0 && pDispParams->rgvarg[0].vt == (VT_BYREF | VT_BOOL))\r
using ComponentMovementWatcher::componentMovedOrResized;\r
\r
private:\r
- WebBrowserComponent& owner;\r
+ Win32WebView& owner;\r
\r
static String getStringFromVariant (VARIANT* v)\r
{\r
public ComponentMovementWatcher\r
{\r
public:\r
- WebView2 (WebBrowserComponent& o, const WebView2Preferences& prefs)\r
+ WebView2 (WebBrowserComponent& o, const WebBrowserComponent::Options& prefs)\r
: ComponentMovementWatcher (&o),\r
owner (o),\r
- preferences (prefs)\r
+ preferences (prefs.getWinWebView2BackendOptions()),\r
+ userAgent (prefs.getUserAgent())\r
{\r
- if (! createWebViewEnvironment())\r
+ if (auto handle = createWebViewHandle (preferences))\r
+ webViewHandle = std::move (*handle);\r
+ else\r
throw std::runtime_error ("Failed to create the CoreWebView2Environemnt");\r
\r
owner.addAndMakeVisible (this);\r
{\r
removeEventHandlers();\r
closeWebView();\r
-\r
- if (webView2LoaderHandle != nullptr)\r
- ::FreeLibrary (webView2LoaderHandle);\r
}\r
\r
void createBrowser() override\r
{\r
if (webView == nullptr)\r
{\r
- jassert (webViewEnvironment != nullptr);\r
+ jassert (webViewHandle.environment != nullptr);\r
createWebView();\r
}\r
}\r
owner.visibilityChanged();\r
}\r
\r
+ //==============================================================================\r
+ struct WebViewHandle\r
+ {\r
+ using LibraryRef = std::unique_ptr<typename std::pointer_traits<HMODULE>::element_type, decltype(&::FreeLibrary)>;\r
+ LibraryRef loaderHandle {nullptr, &::FreeLibrary};\r
+ ComSmartPtr<ICoreWebView2Environment> environment;\r
+ };\r
+\r
+ static std::optional<WebViewHandle> createWebViewHandle(const WebBrowserComponent::Options::WinWebView2& options)\r
+ {\r
+ using CreateWebViewEnvironmentWithOptionsFunc = HRESULT (*) (PCWSTR, PCWSTR,\r
+ ICoreWebView2EnvironmentOptions*,\r
+ ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);\r
+\r
+ auto dllPath = options.getDLLLocation().getFullPathName();\r
+\r
+ if (dllPath.isEmpty())\r
+ dllPath = "WebView2Loader.dll";\r
+\r
+ WebViewHandle result;\r
+\r
+ result.loaderHandle = WebViewHandle::LibraryRef (LoadLibraryA (dllPath.toUTF8()), &::FreeLibrary);\r
+\r
+ if (result.loaderHandle == nullptr)\r
+ return {};\r
+\r
+ auto* createWebViewEnvironmentWithOptions = (CreateWebViewEnvironmentWithOptionsFunc) GetProcAddress (result.loaderHandle.get(),\r
+ "CreateCoreWebView2EnvironmentWithOptions");\r
+ if (createWebViewEnvironmentWithOptions == nullptr)\r
+ return {};\r
+\r
+ auto webViewOptions = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();\r
+ const auto userDataFolder = options.getUserDataFolder().getFullPathName();\r
+\r
+ auto hr = createWebViewEnvironmentWithOptions (nullptr,\r
+ userDataFolder.isNotEmpty() ? userDataFolder.toWideCharPointer() : nullptr,\r
+ webViewOptions.Get(),\r
+ Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(\r
+ [&result] (HRESULT, ICoreWebView2Environment* env) -> HRESULT\r
+ {\r
+ result.environment = env;\r
+ return S_OK;\r
+ }).Get());\r
+\r
+ if (! SUCCEEDED (hr))\r
+ return {};\r
+\r
+ return result;\r
+ }\r
+\r
private:\r
//==============================================================================\r
template <class ArgType>\r
{\r
settings->put_IsStatusBarEnabled (! preferences.getIsStatusBarDisabled());\r
settings->put_IsBuiltInErrorPageEnabled (! preferences.getIsBuiltInErrorPageDisabled());\r
- }\r
- }\r
-\r
- bool createWebViewEnvironment()\r
- {\r
- using CreateWebViewEnvironmentWithOptionsFunc = HRESULT (*) (PCWSTR, PCWSTR,\r
- ICoreWebView2EnvironmentOptions*,\r
- ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);\r
-\r
- auto dllPath = preferences.getDLLLocation().getFullPathName();\r
\r
- if (dllPath.isEmpty())\r
- dllPath = "WebView2Loader.dll";\r
-\r
- webView2LoaderHandle = LoadLibraryA (dllPath.toUTF8());\r
+ if (userAgent.isNotEmpty())\r
+ {\r
+ ComSmartPtr<ICoreWebView2Settings2> settings2;\r
\r
- if (webView2LoaderHandle == nullptr)\r
- return false;\r
+ settings.QueryInterface (settings2);\r
\r
- auto* createWebViewEnvironmentWithOptions = (CreateWebViewEnvironmentWithOptionsFunc) GetProcAddress (webView2LoaderHandle,\r
- "CreateCoreWebView2EnvironmentWithOptions");\r
- if (createWebViewEnvironmentWithOptions == nullptr)\r
- {\r
- // failed to load WebView2Loader.dll\r
- jassertfalse;\r
- return false;\r
+ if (settings2 != nullptr)\r
+ settings2->put_UserAgent (userAgent.toWideCharPointer());\r
+ }\r
}\r
-\r
- auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();\r
- const auto userDataFolder = preferences.getUserDataFolder().getFullPathName();\r
-\r
- auto hr = createWebViewEnvironmentWithOptions (nullptr,\r
- userDataFolder.isNotEmpty() ? userDataFolder.toWideCharPointer() : nullptr,\r
- options.Get(),\r
- Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(\r
- [weakThis = WeakReference<WebView2> { this }] (HRESULT, ICoreWebView2Environment* env) -> HRESULT\r
- {\r
- if (weakThis != nullptr)\r
- weakThis->webViewEnvironment = env;\r
-\r
- return S_OK;\r
- }).Get());\r
-\r
- return SUCCEEDED (hr);\r
}\r
\r
void createWebView()\r
\r
WeakReference<WebView2> weakThis (this);\r
\r
- webViewEnvironment->CreateCoreWebView2Controller ((HWND) peer->getNativeHandle(),\r
+ webViewHandle.environment->CreateCoreWebView2Controller ((HWND) peer->getNativeHandle(),\r
Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler> (\r
[weakThis = WeakReference<WebView2> { this }] (HRESULT, ICoreWebView2Controller* controller) -> HRESULT\r
{\r
webView = nullptr;\r
}\r
\r
- webViewEnvironment = nullptr;\r
+ webViewHandle.environment = nullptr;\r
}\r
\r
//==============================================================================\r
\r
//==============================================================================\r
WebBrowserComponent& owner;\r
- WebView2Preferences preferences;\r
-\r
- HMODULE webView2LoaderHandle = nullptr;\r
+ WebBrowserComponent::Options::WinWebView2 preferences;\r
+ String userAgent;\r
\r
- ComSmartPtr<ICoreWebView2Environment> webViewEnvironment;\r
+ WebViewHandle webViewHandle;\r
ComSmartPtr<ICoreWebView2Controller> webViewController;\r
ComSmartPtr<ICoreWebView2> webView;\r
\r
{\r
public:\r
Pimpl (WebBrowserComponent& owner,\r
- const WebView2Preferences& preferences,\r
- bool useWebView2)\r
+ const Options& preferences,\r
+ bool useWebView2, const String& userAgent)\r
{\r
if (useWebView2)\r
{\r
ignoreUnused (preferences);\r
\r
if (internal == nullptr)\r
- internal.reset (new Win32WebView (owner));\r
+ internal.reset (new Win32WebView (owner, userAgent));\r
}\r
\r
InternalWebViewType& getInternalWebView()\r
};\r
\r
//==============================================================================\r
-WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)\r
- : browser (new Pimpl (*this, {}, false)),\r
- unloadPageWhenHidden (unloadWhenHidden)\r
-{\r
- setOpaque (true);\r
-}\r
-\r
-WebBrowserComponent::WebBrowserComponent (ConstructWithoutPimpl args)\r
- : unloadPageWhenHidden (args.unloadWhenHidden)\r
+WebBrowserComponent::WebBrowserComponent (const Options& options)\r
+ : browser (new Pimpl (*this, options,\r
+ options.getBackend() == Options::Backend::webview2, options.getUserAgent())),\r
+ unloadPageWhenHidden (! options.keepsPageLoadedWhenBrowserIsHidden())\r
{\r
setOpaque (true);\r
}\r
{\r
}\r
\r
-WindowsWebView2WebBrowserComponent::WindowsWebView2WebBrowserComponent (bool unloadWhenHidden,\r
- const WebView2Preferences& preferences)\r
- : WebBrowserComponent (ConstructWithoutPimpl { unloadWhenHidden })\r
-{\r
- browser = std::make_unique<Pimpl> (*this, preferences, true);\r
-}\r
-\r
//==============================================================================\r
void WebBrowserComponent::goToURL (const String& url,\r
const StringArray* headers,\r
}\r
}\r
\r
+//==============================================================================\r
+bool WebBrowserComponent::areOptionsSupported (const Options& options)\r
+{\r
+ if (options.getBackend() == Options::Backend::defaultBackend || options.getBackend() == Options::Backend::ie)\r
+ return true;\r
+\r
+ #if JUCE_USE_WIN_WEBVIEW2\r
+ if (options.getBackend() != Options::Backend::webview2)\r
+ return false;\r
+\r
+ if (auto webView = WebView2::createWebViewHandle (options.getWinWebView2BackendOptions()))\r
+ return true;\r
+ #endif\r
+\r
+ return false;\r
+}\r
+\r
} // namespace juce\r
\r
static void clearGLError() noexcept\r
{\r
+ #if JUCE_DEBUG\r
while (glGetError() != GL_NO_ERROR) {}\r
+ #endif\r
}\r
\r
struct OpenGLTargetSaver\r
OpenGLTargetSaver& operator= (const OpenGLTargetSaver&);\r
};\r
\r
+static bool contextRequiresTexture2DEnableDisable()\r
+{\r
+ #if JUCE_OPENGL_ES\r
+ return false;\r
+ #else\r
+ clearGLError();\r
+ GLint mask = 0;\r
+ glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &mask);\r
+\r
+ if (glGetError() == GL_INVALID_ENUM)\r
+ return true;\r
+\r
+ return (mask & (GLint) GL_CONTEXT_CORE_PROFILE_BIT) == 0;\r
+ #endif\r
+}\r
+\r
} // namespace juce\r
\r
//==============================================================================\r
\r
ID: juce_opengl\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_gui_extra\r
OSXFrameworks: OpenGL\r
#undef JNI_CLASS_MEMBERS\r
\r
//==============================================================================\r
-class OpenGLContext::NativeContext : private SurfaceHolderCallback\r
+class OpenGLContext::NativeContext : private SurfaceHolderCallback\r
{\r
public:\r
NativeContext (Component& comp,\r
void* /*contextToShareWith*/,\r
bool useMultisamplingIn,\r
OpenGLVersion)\r
- : component (comp),\r
- surface (EGL_NO_SURFACE), context (EGL_NO_CONTEXT)\r
+ : component (comp)\r
{\r
auto env = getEnv();\r
\r
}\r
\r
//==============================================================================\r
- bool initialiseOnRenderThread (OpenGLContext& aContext)\r
+ InitResult initialiseOnRenderThread (OpenGLContext& ctx)\r
{\r
- jassert (hasInitialised);\r
+ // The "real" initialisation happens when the surface is created. Here, we'll\r
+ // just return true if the initialisation happened successfully, or false if\r
+ // it hasn't happened yet, or was unsuccessful.\r
+ const std::lock_guard lock { nativeHandleMutex };\r
\r
- // has the context already attached?\r
- jassert (surface == EGL_NO_SURFACE && context == EGL_NO_CONTEXT);\r
-\r
- auto env = getEnv();\r
-\r
- ANativeWindow* window = nullptr;\r
-\r
- LocalRef<jobject> holder (env->CallObjectMethod (surfaceView.get(), JuceOpenGLViewSurface.getHolder));\r
-\r
- if (holder != nullptr)\r
- {\r
- LocalRef<jobject> jSurface (env->CallObjectMethod (holder.get(), AndroidSurfaceHolder.getSurface));\r
-\r
- if (jSurface != nullptr)\r
- {\r
- window = ANativeWindow_fromSurface(env, jSurface.get());\r
-\r
- // if we didn't succeed the first time, wait 25ms and try again\r
- if (window == nullptr)\r
- {\r
- Thread::sleep (200);\r
- window = ANativeWindow_fromSurface (env, jSurface.get());\r
- }\r
- }\r
- }\r
-\r
- if (window == nullptr)\r
- {\r
- // failed to get a pointer to the native window after second try so bail out\r
- jassertfalse;\r
- return false;\r
- }\r
-\r
- // create the surface\r
- surface = eglCreateWindowSurface (display, config, window, nullptr);\r
- jassert (surface != EGL_NO_SURFACE);\r
-\r
- ANativeWindow_release (window);\r
+ if (! hasInitialised)\r
+ return InitResult::fatal;\r
\r
- // create the OpenGL context\r
- EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };\r
- context = eglCreateContext (display, config, EGL_NO_CONTEXT, contextAttribs);\r
- jassert (context != EGL_NO_CONTEXT);\r
+ if (context.get() == EGL_NO_CONTEXT && surface.get() == EGL_NO_SURFACE)\r
+ return InitResult::retry;\r
\r
- juceContext = &aContext;\r
- return true;\r
+ juceContext = &ctx;\r
+ return InitResult::success;\r
}\r
\r
void shutdownOnRenderThread()\r
{\r
- jassert (hasInitialised);\r
-\r
- // is there a context available to detach?\r
- jassert (surface != EGL_NO_SURFACE && context != EGL_NO_CONTEXT);\r
-\r
- eglDestroyContext (display, context);\r
- context = EGL_NO_CONTEXT;\r
-\r
- eglDestroySurface (display, surface);\r
- surface = EGL_NO_SURFACE;\r
+ const std::lock_guard lock { nativeHandleMutex };\r
+ juceContext = nullptr;\r
}\r
\r
//==============================================================================\r
bool makeActive() const noexcept\r
{\r
- if (! hasInitialised)\r
- return false;\r
+ const std::lock_guard lock { nativeHandleMutex };\r
\r
- if (surface == EGL_NO_SURFACE || context == EGL_NO_CONTEXT)\r
- return false;\r
-\r
- if (! eglMakeCurrent (display, surface, surface, context))\r
- return false;\r
-\r
- return true;\r
+ return hasInitialised\r
+ && surface.get() != EGL_NO_SURFACE\r
+ && context.get() != EGL_NO_CONTEXT\r
+ && eglMakeCurrent (display, surface.get(), surface.get(), context.get());\r
}\r
\r
- bool isActive() const noexcept { return eglGetCurrentContext() == context; }\r
+ bool isActive() const noexcept\r
+ {\r
+ const std::lock_guard lock { nativeHandleMutex };\r
+ return eglGetCurrentContext() == context.get();\r
+ }\r
\r
static void deactivateCurrentContext()\r
{\r
}\r
\r
//==============================================================================\r
- void swapBuffers() const noexcept { eglSwapBuffers (display, surface); }\r
+ void swapBuffers() const noexcept { eglSwapBuffers (display, surface.get()); }\r
bool setSwapInterval (const int) { return false; }\r
int getSwapInterval() const { return 0; }\r
\r
ignoreUnused (holder, format, width, height);\r
}\r
\r
- void surfaceCreated (LocalRef<jobject> holder) override;\r
- void surfaceDestroyed (LocalRef<jobject> holder) override;\r
+ void surfaceCreated (LocalRef<jobject>) override;\r
+ void surfaceDestroyed (LocalRef<jobject>) override;\r
\r
//==============================================================================\r
- struct Locker { Locker (NativeContext&) {} };\r
+ struct Locker\r
+ {\r
+ explicit Locker (NativeContext& ctx) : lock (ctx.mutex) {}\r
+ const ScopedLock lock;\r
+ };\r
\r
Component& component;\r
\r
\r
void dispatchDraw (jobject /*canvas*/)\r
{\r
+ const std::lock_guard lock { nativeHandleMutex };\r
+\r
if (juceContext != nullptr)\r
juceContext->triggerRepaint();\r
}\r
return false;\r
}\r
\r
+ struct NativeWindowReleaser\r
+ {\r
+ void operator() (ANativeWindow* ptr) const { if (ptr != nullptr) ANativeWindow_release (ptr); }\r
+ };\r
+\r
+ std::unique_ptr<ANativeWindow, NativeWindowReleaser> getNativeWindow() const\r
+ {\r
+ auto* env = getEnv();\r
+\r
+ const LocalRef<jobject> holder (env->CallObjectMethod (surfaceView.get(), JuceOpenGLViewSurface.getHolder));\r
+\r
+ if (holder == nullptr)\r
+ return nullptr;\r
+\r
+ const LocalRef<jobject> jSurface (env->CallObjectMethod (holder.get(), AndroidSurfaceHolder.getSurface));\r
+\r
+ if (jSurface == nullptr)\r
+ return nullptr;\r
+\r
+ constexpr auto numAttempts = 2;\r
+\r
+ for (auto i = 0; i < numAttempts; Thread::sleep (200), ++i)\r
+ if (auto* ptr = ANativeWindow_fromSurface (env, jSurface.get()))\r
+ return std::unique_ptr<ANativeWindow, NativeWindowReleaser> { ptr };\r
+\r
+ return nullptr;\r
+ }\r
+\r
//==============================================================================\r
+ CriticalSection mutex;\r
bool hasInitialised = false;\r
\r
GlobalRef surfaceView;\r
Rectangle<int> lastBounds;\r
\r
+ struct SurfaceDestructor\r
+ {\r
+ void operator() (EGLSurface x) const { if (x != EGL_NO_SURFACE) eglDestroySurface (display, x); }\r
+ };\r
+\r
+ struct ContextDestructor\r
+ {\r
+ void operator() (EGLContext x) const { if (x != EGL_NO_CONTEXT) eglDestroyContext (display, x); }\r
+ };\r
+\r
+ mutable std::mutex nativeHandleMutex;\r
OpenGLContext* juceContext = nullptr;\r
- EGLSurface surface;\r
- EGLContext context;\r
+ std::unique_ptr<std::remove_pointer_t<EGLSurface>, SurfaceDestructor> surface { EGL_NO_SURFACE };\r
+ std::unique_ptr<std::remove_pointer_t<EGLContext>, ContextDestructor> context { EGL_NO_CONTEXT };\r
\r
GlobalRef surfaceHolderCallback;\r
\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)\r
};\r
\r
+EGLDisplay OpenGLContext::NativeContext::display = EGL_NO_DISPLAY;\r
+EGLDisplay OpenGLContext::NativeContext::config;\r
+\r
//==============================================================================\r
void AndroidGLCallbacks::attachedToWindow (JNIEnv*, jobject /*this*/, jlong host)\r
{\r
\r
[((UIView*) peer->getNativeHandle()) addSubview: view];\r
\r
- if (version == openGL3_2 && [[UIDevice currentDevice].systemVersion floatValue] >= 7.0)\r
- {\r
- if (! createContext (kEAGLRenderingAPIOpenGLES3, contextToShare))\r
- {\r
- releaseContext();\r
- createContext (kEAGLRenderingAPIOpenGLES2, contextToShare);\r
- }\r
- }\r
- else\r
- {\r
- createContext (kEAGLRenderingAPIOpenGLES2, contextToShare);\r
- }\r
+ const auto shouldUseES3 = version != defaultGLVersion\r
+ && [[UIDevice currentDevice].systemVersion floatValue] >= 7.0;\r
+\r
+ const auto gotContext = (shouldUseES3 && createContext (kEAGLRenderingAPIOpenGLES3, contextToShare))\r
+ || createContext (kEAGLRenderingAPIOpenGLES2, contextToShare);\r
+\r
+ jassertquiet (gotContext);\r
\r
if (context != nil)\r
{\r
// I'd prefer to put this stuff in the initialiseOnRenderThread() call, but doing\r
// so causes mysterious timing-related failures.\r
- [EAGLContext setCurrentContext: context];\r
+ [EAGLContext setCurrentContext: context.get()];\r
gl::loadFunctions();\r
createGLBuffers();\r
deactivateCurrentContext();\r
\r
~NativeContext()\r
{\r
- releaseContext();\r
+ context.reset();\r
[view removeFromSuperview];\r
[view release];\r
}\r
\r
- bool initialiseOnRenderThread (OpenGLContext&) { return true; }\r
+ InitResult initialiseOnRenderThread (OpenGLContext&) { return InitResult::success; }\r
\r
void shutdownOnRenderThread()\r
{\r
}\r
\r
bool createdOk() const noexcept { return getRawContext() != nullptr; }\r
- void* getRawContext() const noexcept { return context; }\r
+ void* getRawContext() const noexcept { return context.get(); }\r
GLuint getFrameBufferID() const noexcept { return useMSAA ? msaaBufferHandle : frameBufferHandle; }\r
\r
bool makeActive() const noexcept\r
{\r
- if (! [EAGLContext setCurrentContext: context])\r
+ if (! [EAGLContext setCurrentContext: context.get()])\r
return false;\r
\r
glBindFramebuffer (GL_FRAMEBUFFER, useMSAA ? msaaBufferHandle\r
\r
bool isActive() const noexcept\r
{\r
- return [EAGLContext currentContext] == context;\r
+ return [EAGLContext currentContext] == context.get();\r
}\r
\r
static void deactivateCurrentContext()\r
}\r
\r
glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);\r
- [context presentRenderbuffer: GL_RENDERBUFFER];\r
+ [context.get() presentRenderbuffer: GL_RENDERBUFFER];\r
\r
if (needToRebuildBuffers)\r
{\r
\r
int getSwapInterval() const noexcept { return swapFrames; }\r
\r
- struct Locker { Locker (NativeContext&) {} };\r
+ struct Locker\r
+ {\r
+ explicit Locker (NativeContext& ctx) : lock (ctx.mutex) {}\r
+ const ScopedLock lock;\r
+ };\r
\r
private:\r
+ CriticalSection mutex;\r
Component& component;\r
JuceGLView* view = nil;\r
CAEAGLLayer* glLayer = nil;\r
- EAGLContext* context = nil;\r
+ NSUniquePtr<EAGLContext> context;\r
const OpenGLVersion openGLversion;\r
const bool useDepthBuffer, useMSAA;\r
\r
bool createContext (EAGLRenderingAPI type, void* contextToShare)\r
{\r
jassert (context == nil);\r
- context = [EAGLContext alloc];\r
+ context.reset ([EAGLContext alloc]);\r
\r
- context = contextToShare != nullptr\r
- ? [context initWithAPI: type sharegroup: [(EAGLContext*) contextToShare sharegroup]]\r
- : [context initWithAPI: type];\r
+ if (contextToShare != nullptr)\r
+ [context.get() initWithAPI: type sharegroup: [(EAGLContext*) contextToShare sharegroup]];\r
+ else\r
+ [context.get() initWithAPI: type];\r
\r
return context != nil;\r
}\r
\r
- void releaseContext()\r
- {\r
- [context release];\r
- context = nil;\r
- }\r
-\r
//==============================================================================\r
void createGLBuffers()\r
{\r
\r
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferHandle);\r
\r
- bool ok = [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: glLayer];\r
+ bool ok = [context.get() renderbufferStorage: GL_RENDERBUFFER fromDrawable: glLayer];\r
jassert (ok); ignoreUnused (ok);\r
\r
GLint width, height;\r
void freeGLBuffers()\r
{\r
JUCE_CHECK_OPENGL_ERROR\r
- [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil];\r
+ [context.get() renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil];\r
\r
deleteFrameBuffer (frameBufferHandle);\r
deleteFrameBuffer (msaaBufferHandle);\r
\r
extern XContext windowHandleXContext;\r
\r
+struct XFreeDeleter\r
+{\r
+ void operator() (void* ptr) const\r
+ {\r
+ if (ptr != nullptr)\r
+ X11Symbols::getInstance()->xFree (ptr);\r
+ }\r
+};\r
+\r
+template <typename Data>\r
+std::unique_ptr<Data, XFreeDeleter> makeXFreePtr (Data* raw) { return std::unique_ptr<Data, XFreeDeleter> (raw); }\r
+\r
//==============================================================================\r
// Defined juce_linux_Windowing.cpp\r
void juce_LinuxAddRepaintListener (ComponentPeer*, Component* dummy);\r
jassert (peer != nullptr);\r
\r
auto windowH = (Window) peer->getNativeHandle();\r
- auto colourMap = X11Symbols::getInstance()->xCreateColormap (display, windowH, bestVisual->visual, AllocNone);\r
+ auto visual = glXGetVisualFromFBConfig (display, *bestConfig);\r
+ auto colourMap = X11Symbols::getInstance()->xCreateColormap (display, windowH, visual->visual, AllocNone);\r
\r
XSetWindowAttributes swa;\r
swa.colormap = colourMap;\r
swa.border_pixel = 0;\r
swa.event_mask = embeddedWindowEventMask;\r
\r
- auto glBounds = component.getTopLevelComponent()\r
- ->getLocalArea (&component, component.getLocalBounds());\r
+ auto glBounds = component.getTopLevelComponent()->getLocalArea (&component, component.getLocalBounds());\r
\r
glBounds = Desktop::getInstance().getDisplays().logicalToPhysical (glBounds);\r
\r
glBounds.getX(), glBounds.getY(),\r
(unsigned int) jmax (1, glBounds.getWidth()),\r
(unsigned int) jmax (1, glBounds.getHeight()),\r
- 0, bestVisual->depth,\r
+ 0, visual->depth,\r
InputOutput,\r
- bestVisual->visual,\r
+ visual->visual,\r
CWBorderPixel | CWColormap | CWEventMask,\r
&swa);\r
\r
}\r
}\r
}\r
-\r
- if (bestVisual != nullptr)\r
- X11Symbols::getInstance()->xFree (bestVisual);\r
}\r
\r
- bool initialiseOnRenderThread (OpenGLContext& c)\r
+ InitResult initialiseOnRenderThread (OpenGLContext& c)\r
{\r
XWindowSystemUtilities::ScopedXLock xLock;\r
- renderContext = glXCreateContext (display, bestVisual, (GLXContext) contextToShareWith, GL_TRUE);\r
+\r
+ const auto components = [&]() -> Optional<Version>\r
+ {\r
+ switch (c.versionRequired)\r
+ {\r
+ case OpenGLVersion::openGL3_2: return Version { 3, 2 };\r
+ case OpenGLVersion::openGL4_1: return Version { 4, 1 };\r
+ case OpenGLVersion::openGL4_3: return Version { 4, 3 };\r
+\r
+ case OpenGLVersion::defaultGLVersion: break;\r
+ }\r
+\r
+ return {};\r
+ }();\r
+\r
+ if (components.hasValue())\r
+ {\r
+ using GLXCreateContextAttribsARB = GLXContext (*) (Display*, GLXFBConfig, GLXContext, Bool, const int*);\r
+\r
+ if (const auto glXCreateContextAttribsARB = (GLXCreateContextAttribsARB) OpenGLHelpers::getExtensionFunction ("glXCreateContextAttribsARB"))\r
+ {\r
+ #if JUCE_DEBUG\r
+ constexpr auto contextFlags = GLX_CONTEXT_DEBUG_BIT_ARB;\r
+ #else\r
+ constexpr auto contextFlags = 0;\r
+ #endif\r
+\r
+ const int attribs[]\r
+ {\r
+ GLX_CONTEXT_MAJOR_VERSION_ARB, components->major,\r
+ GLX_CONTEXT_MINOR_VERSION_ARB, components->minor,\r
+ GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,\r
+ GLX_CONTEXT_FLAGS_ARB, contextFlags,\r
+ None\r
+ };\r
+\r
+ renderContext = glXCreateContextAttribsARB (display, *bestConfig, (GLXContext) contextToShareWith, GL_TRUE, attribs);\r
+ }\r
+ }\r
+\r
+ if (renderContext == nullptr)\r
+ renderContext = glXCreateNewContext (display, *bestConfig, GLX_RGBA_TYPE, (GLXContext) contextToShareWith, GL_TRUE);\r
+\r
+ if (renderContext == nullptr)\r
+ return InitResult::fatal;\r
+\r
c.makeActive();\r
context = &c;\r
-\r
- return true;\r
+ return InitResult::success;\r
}\r
\r
void shutdownOnRenderThread()\r
context->triggerRepaint();\r
}\r
\r
- struct Locker { Locker (NativeContext&) {} };\r
+ struct Locker\r
+ {\r
+ explicit Locker (NativeContext& ctx) : lock (ctx.mutex) {}\r
+ const ScopedLock lock;\r
+ };\r
\r
private:\r
bool tryChooseVisual (const OpenGLPixelFormat& format, const std::vector<GLint>& optionalAttribs)\r
{\r
std::vector<GLint> allAttribs\r
{\r
- GLX_RGBA,\r
- GLX_DOUBLEBUFFER,\r
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,\r
+ GLX_DOUBLEBUFFER, True,\r
GLX_RED_SIZE, format.redBits,\r
GLX_GREEN_SIZE, format.greenBits,\r
GLX_BLUE_SIZE, format.blueBits,\r
\r
allAttribs.push_back (None);\r
\r
- bestVisual = glXChooseVisual (display, X11Symbols::getInstance()->xDefaultScreen (display), allAttribs.data());\r
+ int nElements = 0;\r
+ bestConfig = makeXFreePtr (glXChooseFBConfig (display, X11Symbols::getInstance()->xDefaultScreen (display), allAttribs.data(), &nElements));\r
\r
- return bestVisual != nullptr;\r
+ return nElements != 0 && bestConfig != nullptr;\r
}\r
\r
static constexpr int embeddedWindowEventMask = ExposureMask | StructureNotifyMask;\r
\r
+ CriticalSection mutex;\r
Component& component;\r
GLXContext renderContext = {};\r
Window embeddedWindow = {};\r
\r
int swapFrames = 1;\r
Rectangle<int> bounds;\r
- XVisualInfo* bestVisual = nullptr;\r
+ std::unique_ptr<GLXFBConfig, XFreeDeleter> bestConfig;\r
void* contextToShareWith;\r
\r
OpenGLContext* context = nullptr;\r
OpenGLVersion version)\r
: owner (component)\r
{\r
- NSOpenGLPixelFormatAttribute attribs[64] = { 0 };\r
- createAttribs (attribs, version, pixFormat, shouldUseMultisampling);\r
+ const auto attribs = createAttribs (version, pixFormat, shouldUseMultisampling);\r
\r
- NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];\r
+ NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs.data()];\r
\r
static MouseForwardingNSOpenGLViewClass cls;\r
view = [cls.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)\r
[view release];\r
}\r
\r
- static void createAttribs (NSOpenGLPixelFormatAttribute* attribs, OpenGLVersion version,\r
- const OpenGLPixelFormat& pixFormat, bool shouldUseMultisampling)\r
+ static std::vector<NSOpenGLPixelFormatAttribute> createAttribs (OpenGLVersion version,\r
+ const OpenGLPixelFormat& pixFormat,\r
+ bool shouldUseMultisampling)\r
{\r
- ignoreUnused (version);\r
- int numAttribs = 0;\r
-\r
- attribs[numAttribs++] = NSOpenGLPFAOpenGLProfile;\r
- attribs[numAttribs++] = version >= openGL3_2 ? NSOpenGLProfileVersion3_2Core\r
- : NSOpenGLProfileVersionLegacy;\r
-\r
- attribs[numAttribs++] = NSOpenGLPFADoubleBuffer;\r
- attribs[numAttribs++] = NSOpenGLPFAClosestPolicy;\r
- attribs[numAttribs++] = NSOpenGLPFANoRecovery;\r
- attribs[numAttribs++] = NSOpenGLPFAColorSize;\r
- attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) (pixFormat.redBits + pixFormat.greenBits + pixFormat.blueBits);\r
- attribs[numAttribs++] = NSOpenGLPFAAlphaSize;\r
- attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) pixFormat.alphaBits;\r
- attribs[numAttribs++] = NSOpenGLPFADepthSize;\r
- attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) pixFormat.depthBufferBits;\r
- attribs[numAttribs++] = NSOpenGLPFAStencilSize;\r
- attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) pixFormat.stencilBufferBits;\r
- attribs[numAttribs++] = NSOpenGLPFAAccumSize;\r
- attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) (pixFormat.accumulationBufferRedBits + pixFormat.accumulationBufferGreenBits\r
- + pixFormat.accumulationBufferBlueBits + pixFormat.accumulationBufferAlphaBits);\r
+ std::vector<NSOpenGLPixelFormatAttribute> attribs\r
+ {\r
+ NSOpenGLPFAOpenGLProfile, [version]\r
+ {\r
+ if (version == openGL3_2)\r
+ return NSOpenGLProfileVersion3_2Core;\r
+\r
+ if (version != defaultGLVersion)\r
+ if (@available (macOS 10.10, *))\r
+ return NSOpenGLProfileVersion4_1Core;\r
+\r
+ return NSOpenGLProfileVersionLegacy;\r
+ }(),\r
+ NSOpenGLPFADoubleBuffer,\r
+ NSOpenGLPFAClosestPolicy,\r
+ NSOpenGLPFANoRecovery,\r
+ NSOpenGLPFAColorSize, static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.redBits + pixFormat.greenBits + pixFormat.blueBits),\r
+ NSOpenGLPFAAlphaSize, static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.alphaBits),\r
+ NSOpenGLPFADepthSize, static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.depthBufferBits),\r
+ NSOpenGLPFAStencilSize, static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.stencilBufferBits),\r
+ NSOpenGLPFAAccumSize, static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.accumulationBufferRedBits + pixFormat.accumulationBufferGreenBits\r
+ + pixFormat.accumulationBufferBlueBits + pixFormat.accumulationBufferAlphaBits)\r
+ };\r
\r
if (shouldUseMultisampling)\r
{\r
- attribs[numAttribs++] = NSOpenGLPFAMultisample;\r
- attribs[numAttribs++] = NSOpenGLPFASampleBuffers;\r
- attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) 1;\r
- attribs[numAttribs++] = NSOpenGLPFASamples;\r
- attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) pixFormat.multisamplingLevel;\r
+ attribs.insert (attribs.cend(),\r
+ {\r
+ NSOpenGLPFAMultisample,\r
+ NSOpenGLPFASampleBuffers, static_cast<NSOpenGLPixelFormatAttribute> (1),\r
+ NSOpenGLPFASamples, static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.multisamplingLevel)\r
+ });\r
}\r
+\r
+ attribs.push_back (0);\r
+\r
+ return attribs;\r
}\r
\r
- bool initialiseOnRenderThread (OpenGLContext&) { return true; }\r
- void shutdownOnRenderThread() { deactivateCurrentContext(); }\r
+ InitResult initialiseOnRenderThread (OpenGLContext&) { return InitResult::success; }\r
+ void shutdownOnRenderThread() { deactivateCurrentContext(); }\r
\r
bool createdOk() const noexcept { return getRawContext() != nullptr; }\r
- void* getRawContext() const noexcept { return static_cast<void*> (renderContext); }\r
+ NSOpenGLView* getNSView() const noexcept { return view; }\r
+ NSOpenGLContext* getRawContext() const noexcept { return renderContext; }\r
GLuint getFrameBufferID() const noexcept { return 0; }\r
\r
bool makeActive() const noexcept\r
//==============================================================================\r
struct MouseForwardingNSOpenGLViewClass : public ObjCClass<NSOpenGLView>\r
{\r
- MouseForwardingNSOpenGLViewClass() : ObjCClass<NSOpenGLView> ("JUCEGLView_")\r
+ MouseForwardingNSOpenGLViewClass() : ObjCClass ("JUCEGLView_")\r
{\r
- addMethod (@selector (rightMouseDown:), rightMouseDown);\r
- addMethod (@selector (rightMouseUp:), rightMouseUp);\r
- addMethod (@selector (acceptsFirstMouse:), acceptsFirstMouse);\r
- addMethod (@selector (accessibilityHitTest:), accessibilityHitTest);\r
+ addMethod (@selector (rightMouseDown:), [] (id self, SEL, NSEvent* ev) { [[(NSOpenGLView*) self superview] rightMouseDown: ev]; });\r
+ addMethod (@selector (rightMouseUp:), [] (id self, SEL, NSEvent* ev) { [[(NSOpenGLView*) self superview] rightMouseUp: ev]; });\r
+ addMethod (@selector (acceptsFirstMouse:), [] (id, SEL, NSEvent*) -> BOOL { return YES; });\r
+ addMethod (@selector (accessibilityHitTest:), [] (id self, SEL, NSPoint p) -> id { return [[(NSOpenGLView*) self superview] accessibilityHitTest: p]; });\r
\r
registerClass();\r
}\r
-\r
- private:\r
- static void rightMouseDown (id self, SEL, NSEvent* ev) { [[(NSOpenGLView*) self superview] rightMouseDown: ev]; }\r
- static void rightMouseUp (id self, SEL, NSEvent* ev) { [[(NSOpenGLView*) self superview] rightMouseUp: ev]; }\r
- static BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; }\r
- static id accessibilityHitTest (id self, SEL, NSPoint p) { return [[(NSOpenGLView*) self superview] accessibilityHitTest: p]; }\r
};\r
\r
-\r
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)\r
};\r
\r
PIXELFORMATDESCRIPTOR pfd;\r
initialisePixelFormatDescriptor (pfd, pixelFormat);\r
\r
- auto pixFormat = ChoosePixelFormat (dc, &pfd);\r
+ auto pixFormat = ChoosePixelFormat (dc.get(), &pfd);\r
\r
if (pixFormat != 0)\r
- SetPixelFormat (dc, pixFormat, &pfd);\r
+ SetPixelFormat (dc.get(), pixFormat, &pfd);\r
\r
- initialiseWGLExtensions (dc);\r
- renderContext = createRenderContext (version, dc);\r
+ initialiseWGLExtensions (dc.get());\r
+ renderContext.reset (createRenderContext (version, dc.get()));\r
\r
if (renderContext != nullptr)\r
{\r
if (wglFormat != pixFormat && wglFormat != 0)\r
{\r
// can't change the pixel format of a window, so need to delete the\r
- // old one and create a new one..\r
- releaseDC();\r
+ // old one and create a new one.\r
+ dc.reset();\r
nativeWindow = nullptr;\r
createNativeWindow (component);\r
\r
- if (SetPixelFormat (dc, wglFormat, &pfd))\r
+ if (SetPixelFormat (dc.get(), wglFormat, &pfd))\r
{\r
- deleteRenderContext();\r
- renderContext = createRenderContext (version, dc);\r
+ renderContext.reset();\r
+ renderContext.reset (createRenderContext (version, dc.get()));\r
}\r
}\r
\r
if (contextToShareWithIn != nullptr)\r
- wglShareLists ((HGLRC) contextToShareWithIn, renderContext);\r
+ wglShareLists ((HGLRC) contextToShareWithIn, renderContext.get());\r
\r
component.getTopLevelComponent()->repaint();\r
component.repaint();\r
\r
~NativeContext() override\r
{\r
- deleteRenderContext();\r
- releaseDC();\r
+ renderContext.reset();\r
+ dc.reset();\r
\r
if (safeComponent != nullptr)\r
if (auto* peer = safeComponent->getTopLevelComponent()->getPeer())\r
peer->removeScaleFactorListener (this);\r
}\r
\r
- bool initialiseOnRenderThread (OpenGLContext& c)\r
+ InitResult initialiseOnRenderThread (OpenGLContext& c)\r
{\r
threadAwarenessSetter = std::make_unique<ScopedThreadDPIAwarenessSetter> (nativeWindow->getNativeHandle());\r
context = &c;\r
- return true;\r
+ return InitResult::success;\r
}\r
\r
void shutdownOnRenderThread()\r
}\r
\r
static void deactivateCurrentContext() { wglMakeCurrent (nullptr, nullptr); }\r
- bool makeActive() const noexcept { return isActive() || wglMakeCurrent (dc, renderContext) != FALSE; }\r
- bool isActive() const noexcept { return wglGetCurrentContext() == renderContext; }\r
- void swapBuffers() const noexcept { SwapBuffers (dc); }\r
+ bool makeActive() const noexcept { return isActive() || wglMakeCurrent (dc.get(), renderContext.get()) != FALSE; }\r
+ bool isActive() const noexcept { return wglGetCurrentContext() == renderContext.get(); }\r
+ void swapBuffers() const noexcept { SwapBuffers (dc.get()); }\r
\r
bool setSwapInterval (int numFramesPerSwap)\r
{\r
}\r
\r
bool createdOk() const noexcept { return getRawContext() != nullptr; }\r
- void* getRawContext() const noexcept { return renderContext; }\r
+ void* getRawContext() const noexcept { return renderContext.get(); }\r
unsigned int getFrameBufferID() const noexcept { return 0; }\r
\r
void triggerRepaint()\r
context->triggerRepaint();\r
}\r
\r
- struct Locker { Locker (NativeContext&) {} };\r
+ struct Locker\r
+ {\r
+ explicit Locker (NativeContext& ctx) : lock (ctx.mutex) {}\r
+ const ScopedLock lock;\r
+ };\r
\r
HWND getNativeHandle()\r
{\r
\r
static HGLRC createRenderContext (OpenGLVersion version, HDC dcIn)\r
{\r
- if (version >= openGL3_2 && wglCreateContextAttribsARB != nullptr)\r
+ const auto components = [&]() -> Optional<Version>\r
+ {\r
+ switch (version)\r
+ {\r
+ case OpenGLVersion::openGL3_2: return Version { 3, 2 };\r
+ case OpenGLVersion::openGL4_1: return Version { 4, 1 };\r
+ case OpenGLVersion::openGL4_3: return Version { 4, 3 };\r
+\r
+ case OpenGLVersion::defaultGLVersion: break;\r
+ }\r
+\r
+ return {};\r
+ }();\r
+\r
+ if (components.hasValue() && wglCreateContextAttribsARB != nullptr)\r
{\r
+ #if JUCE_DEBUG\r
+ constexpr auto contextFlags = WGL_CONTEXT_DEBUG_BIT_ARB;\r
+ constexpr auto noErrorChecking = GL_FALSE;\r
+ #else\r
+ constexpr auto contextFlags = 0;\r
+ constexpr auto noErrorChecking = GL_TRUE;\r
+ #endif\r
+\r
const int attribs[] =\r
{\r
- WGL_CONTEXT_MAJOR_VERSION_ARB, 3,\r
- WGL_CONTEXT_MINOR_VERSION_ARB, 2,\r
- WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,\r
+ WGL_CONTEXT_MAJOR_VERSION_ARB, components->major,\r
+ WGL_CONTEXT_MINOR_VERSION_ARB, components->minor,\r
+ WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,\r
+ WGL_CONTEXT_FLAGS_ARB, contextFlags,\r
+ WGL_CONTEXT_OPENGL_NO_ERROR_ARB, noErrorChecking,\r
0\r
};\r
\r
}\r
\r
nativeWindow->setVisible (true);\r
- dc = GetDC ((HWND) nativeWindow->getNativeHandle());\r
- }\r
-\r
- void deleteRenderContext()\r
- {\r
- if (renderContext != nullptr)\r
- {\r
- wglDeleteContext (renderContext);\r
- renderContext = nullptr;\r
- }\r
- }\r
-\r
- void releaseDC()\r
- {\r
- ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc);\r
+ dc = std::unique_ptr<std::remove_pointer_t<HDC>, DeviceContextDeleter> { GetDC ((HWND) nativeWindow->getNativeHandle()),\r
+ DeviceContextDeleter { (HWND) nativeWindow->getNativeHandle() } };\r
}\r
\r
int wglChoosePixelFormatExtension (const OpenGLPixelFormat& pixelFormat) const\r
jassert (n <= numElementsInArray (atts));\r
\r
UINT formatsCount = 0;\r
- wglChoosePixelFormatARB (dc, atts, nullptr, 1, &format, &formatsCount);\r
+ wglChoosePixelFormatARB (dc.get(), atts, nullptr, 1, &format, &formatsCount);\r
}\r
\r
return format;\r
#undef JUCE_DECLARE_WGL_EXTENSION_FUNCTION\r
\r
//==============================================================================\r
+ struct RenderContextDeleter\r
+ {\r
+ void operator() (HGLRC ptr) const { wglDeleteContext (ptr); }\r
+ };\r
+\r
+ struct DeviceContextDeleter\r
+ {\r
+ void operator() (HDC ptr) const { ReleaseDC (hwnd, ptr); }\r
+ HWND hwnd;\r
+ };\r
+\r
+ CriticalSection mutex;\r
std::unique_ptr<DummyComponent> dummyComponent;\r
std::unique_ptr<ComponentPeer> nativeWindow;\r
std::unique_ptr<ScopedThreadDPIAwarenessSetter> threadAwarenessSetter;\r
Component::SafePointer<Component> safeComponent;\r
- HGLRC renderContext;\r
- HDC dc;\r
+ std::unique_ptr<std::remove_pointer_t<HGLRC>, RenderContextDeleter> renderContext;\r
+ std::unique_ptr<std::remove_pointer_t<HDC>, DeviceContextDeleter> dc;\r
OpenGLContext* context = nullptr;\r
double nativeScaleFactor = 1.0;\r
\r
==============================================================================\r
*/\r
\r
+#if JUCE_MAC\r
+ #include <juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h>\r
+#endif\r
+\r
namespace juce\r
{\r
\r
}\r
\r
//==============================================================================\r
-class OpenGLContext::CachedImage : public CachedComponentImage,\r
- private ThreadPoolJob\r
+class OpenGLContext::CachedImage : public CachedComponentImage\r
{\r
+ template <typename T, typename U>\r
+ static constexpr bool isFlagSet (const T& t, const U& u) { return (t & u) != 0; }\r
+\r
struct AreaAndScale\r
{\r
Rectangle<int> area;\r
public:\r
CachedImage (OpenGLContext& c, Component& comp,\r
const OpenGLPixelFormat& pixFormat, void* contextToShare)\r
- : ThreadPoolJob ("OpenGL Rendering"),\r
- context (c),\r
+ : context (c),\r
component (comp)\r
{\r
nativeContext.reset (new NativeContext (component, pixFormat, contextToShare,\r
void start()\r
{\r
if (nativeContext != nullptr)\r
- {\r
- #if JUCE_MAC\r
- cvDisplayLinkWrapper = std::make_unique<CVDisplayLinkWrapper> (*this);\r
- cvDisplayLinkWrapper->updateActiveDisplay();\r
- #endif\r
-\r
- renderThread = std::make_unique<ThreadPool> (1);\r
resume();\r
- }\r
}\r
\r
void stop()\r
{\r
- if (renderThread != nullptr)\r
- {\r
- // make sure everything has finished executing\r
- destroying = true;\r
-\r
- if (workQueue.size() > 0)\r
- {\r
- if (! renderThread->contains (this))\r
- resume();\r
+ // make sure everything has finished executing\r
+ state |= StateFlags::pendingDestruction;\r
\r
- while (workQueue.size() != 0)\r
- Thread::sleep (20);\r
- }\r
+ if (workQueue.size() > 0)\r
+ {\r
+ if (! renderThread->contains (this))\r
+ resume();\r
\r
- pause();\r
- renderThread.reset();\r
+ while (workQueue.size() != 0)\r
+ Thread::sleep (20);\r
}\r
\r
- #if JUCE_MAC\r
- cvDisplayLinkWrapper = nullptr;\r
- #endif\r
-\r
- hasInitialised = false;\r
+ pause();\r
}\r
\r
//==============================================================================\r
void pause()\r
{\r
- signalJobShouldExit();\r
- messageManagerLock.abort();\r
+ renderThread->remove (this);\r
\r
- if (renderThread != nullptr)\r
+ if ((state.fetch_and (~StateFlags::initialised) & StateFlags::initialised) != 0)\r
{\r
- repaintEvent.signal();\r
- renderThread->removeJob (this, true, -1);\r
+ context.makeActive();\r
+ shutdownOnThread();\r
+ OpenGLContext::deactivateCurrentContext();\r
}\r
}\r
\r
void resume()\r
{\r
- if (renderThread != nullptr)\r
- renderThread->addJob (this, false);\r
+ renderThread->add (this);\r
}\r
\r
//==============================================================================\r
void paint (Graphics&) override\r
{\r
- updateViewportSize (false);\r
+ if (MessageManager::getInstance()->isThisTheMessageThread())\r
+ {\r
+ updateViewportSize();\r
+ }\r
+ else\r
+ {\r
+ // If you hit this assertion, it's because paint has been called from a thread other\r
+ // than the message thread. This commonly happens when nesting OpenGL contexts, because\r
+ // the 'outer' OpenGL renderer will attempt to call paint on the 'inner' context's\r
+ // component from the OpenGL thread.\r
+ // Nesting OpenGL contexts is not directly supported, however there is a workaround:\r
+ // https://forum.juce.com/t/opengl-how-do-3d-with-custom-shaders-and-2d-with-juce-paint-methods-work-together/28026/7\r
+ jassertfalse;\r
+ }\r
}\r
\r
bool invalidateAll() override\r
\r
void triggerRepaint()\r
{\r
- needsUpdate = 1;\r
- repaintEvent.signal();\r
+ state |= (StateFlags::pendingRender | StateFlags::paintComponents);\r
+ renderThread->triggerRepaint();\r
}\r
\r
//==============================================================================\r
JUCE_CHECK_OPENGL_ERROR\r
}\r
\r
- bool renderFrame()\r
+ struct ScopedContextActivator\r
{\r
- MessageManager::Lock::ScopedTryLockType mmLock (messageManagerLock, false);\r
+ bool activate (OpenGLContext& ctx)\r
+ {\r
+ if (! active)\r
+ active = ctx.makeActive();\r
\r
- auto isUpdatingTestValue = true;\r
- auto isUpdating = needsUpdate.compare_exchange_strong (isUpdatingTestValue, false);\r
+ return active;\r
+ }\r
\r
- if (context.renderComponents && isUpdating)\r
+ ~ScopedContextActivator()\r
{\r
- // This avoids hogging the message thread when doing intensive rendering.\r
- if (lastMMLockReleaseTime + 1 >= Time::getMillisecondCounter())\r
- Thread::sleep (2);\r
+ if (active)\r
+ OpenGLContext::deactivateCurrentContext();\r
+ }\r
\r
- while (! shouldExit())\r
- {\r
- doWorkWhileWaitingForLock (false);\r
+ private:\r
+ bool active = false;\r
+ };\r
\r
- if (mmLock.retryLock())\r
- break;\r
- }\r
+ enum class RenderStatus\r
+ {\r
+ nominal,\r
+ messageThreadAborted,\r
+ noWork,\r
+ };\r
\r
- if (shouldExit())\r
- return false;\r
+ RenderStatus renderFrame (MessageManager::Lock& mmLock)\r
+ {\r
+ if (! isFlagSet (state, StateFlags::initialised))\r
+ {\r
+ switch (initialiseOnThread())\r
+ {\r
+ case InitResult::fatal:\r
+ case InitResult::retry: return RenderStatus::noWork;\r
+ case InitResult::success: break;\r
+ }\r
}\r
\r
- if (! context.makeActive())\r
- return false;\r
+ state |= StateFlags::initialised;\r
+\r
+ #if JUCE_IOS\r
+ if (backgroundProcessCheck.isBackgroundProcess())\r
+ return RenderStatus::noWork;\r
+ #endif\r
\r
- NativeContext::Locker locker (*nativeContext);\r
+ std::optional<MessageManager::Lock::ScopedTryLockType> scopedLock;\r
+ ScopedContextActivator contextActivator;\r
\r
- JUCE_CHECK_OPENGL_ERROR\r
+ const auto stateToUse = state.fetch_and (StateFlags::persistent);\r
\r
- doWorkWhileWaitingForLock (true);\r
+ if (! isFlagSet (stateToUse, StateFlags::pendingRender) && ! context.continuousRepaint)\r
+ return RenderStatus::noWork;\r
\r
- const auto currentAreaAndScale = areaAndScale.get();\r
- const auto viewportArea = currentAreaAndScale.area;\r
+ const auto isUpdating = isFlagSet (stateToUse, StateFlags::paintComponents);\r
\r
- if (context.renderer != nullptr)\r
+ if (context.renderComponents && isUpdating)\r
{\r
- glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());\r
- context.currentRenderScale = currentAreaAndScale.scale;\r
- context.renderer->renderOpenGL();\r
- clearGLError();\r
+ bool abortScope = false;\r
+ // If we early-exit here, we need to restore these flags so that the render is\r
+ // attempted again in the next time slice.\r
+ const ScopeGuard scope { [&] { if (! abortScope) state |= stateToUse; } };\r
\r
- bindVertexArray();\r
+ // This avoids hogging the message thread when doing intensive rendering.\r
+ std::this_thread::sleep_until (lastMMLockReleaseTime + std::chrono::milliseconds { 2 });\r
+\r
+ if (renderThread->isListChanging())\r
+ return RenderStatus::messageThreadAborted;\r
+\r
+ doWorkWhileWaitingForLock (contextActivator);\r
+\r
+ scopedLock.emplace (mmLock);\r
+\r
+ // If we can't get the lock here, it's probably because a context has been removed\r
+ // on the main thread.\r
+ // We return, just in case this renderer needs to be removed from the rendering thread.\r
+ // If another renderer is being removed instead, then we should be able to get the lock\r
+ // next time round.\r
+ if (! scopedLock->isLocked())\r
+ return RenderStatus::messageThreadAborted;\r
+\r
+ abortScope = true;\r
}\r
\r
- if (context.renderComponents)\r
+ if (! contextActivator.activate (context))\r
+ return RenderStatus::noWork;\r
+\r
{\r
- if (isUpdating)\r
- {\r
- paintComponent (currentAreaAndScale);\r
+ NativeContext::Locker locker (*nativeContext);\r
\r
- if (! hasInitialised)\r
- return false;\r
+ JUCE_CHECK_OPENGL_ERROR\r
\r
- messageManagerLock.exit();\r
- lastMMLockReleaseTime = Time::getMillisecondCounter();\r
+ doWorkWhileWaitingForLock (contextActivator);\r
+\r
+ const auto currentAreaAndScale = areaAndScale.get();\r
+ const auto viewportArea = currentAreaAndScale.area;\r
+\r
+ if (context.renderer != nullptr)\r
+ {\r
+ glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());\r
+ context.currentRenderScale = currentAreaAndScale.scale;\r
+ context.renderer->renderOpenGL();\r
+ clearGLError();\r
+\r
+ bindVertexArray();\r
}\r
\r
- glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());\r
- drawComponentBuffer();\r
- }\r
+ if (context.renderComponents)\r
+ {\r
+ if (isUpdating)\r
+ {\r
+ paintComponent (currentAreaAndScale);\r
\r
- context.swapBuffers();\r
+ if (! isFlagSet (state, StateFlags::initialised))\r
+ return RenderStatus::noWork;\r
\r
- OpenGLContext::deactivateCurrentContext();\r
- return true;\r
+ scopedLock.reset();\r
+ lastMMLockReleaseTime = std::chrono::steady_clock::now();\r
+ }\r
+\r
+ glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());\r
+ drawComponentBuffer();\r
+ }\r
+ }\r
+\r
+ nativeContext->swapBuffers();\r
+ return RenderStatus::nominal;\r
}\r
\r
- void updateViewportSize (bool canTriggerUpdate)\r
+ void updateViewportSize()\r
{\r
JUCE_ASSERT_MESSAGE_THREAD\r
\r
if (auto* peer = component.getPeer())\r
{\r
#if JUCE_MAC\r
+ updateScreen();\r
+\r
const auto displayScale = Desktop::getInstance().getGlobalScaleFactor() * [this]\r
{\r
- if (auto* wrapper = cvDisplayLinkWrapper.get())\r
- if (wrapper->updateActiveDisplay())\r
- nativeContext->setNominalVideoRefreshPeriodS (wrapper->getNominalVideoRefreshPeriodS());\r
-\r
if (auto* view = getCurrentView())\r
{\r
if ([view respondsToSelector: @selector (backingScaleFactor)])\r
return areaAndScale.get().scale;\r
}();\r
#else\r
- const auto displayScale = Desktop::getInstance().getDisplays().getDisplayForRect (component.getTopLevelComponent()->getScreenBounds())->scale;\r
+ const auto displayScale = Desktop::getInstance().getDisplays()\r
+ .getDisplayForRect (component.getTopLevelComponent()\r
+ ->getScreenBounds())\r
+ ->scale;\r
#endif\r
\r
- auto localBounds = component.getLocalBounds();\r
- auto newArea = peer->getComponent().getLocalArea (&component, localBounds).withZeroOrigin() * displayScale;\r
+ const auto localBounds = component.getLocalBounds();\r
+ const auto newArea = peer->getComponent().getLocalArea (&component, localBounds).withZeroOrigin() * displayScale;\r
\r
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
- auto newScale = getScaleFactorForWindow (nativeContext->getNativeHandle());\r
- auto desktopScale = Desktop::getInstance().getGlobalScaleFactor();\r
-\r
- if (! approximatelyEqual (1.0f, desktopScale))\r
- newScale *= desktopScale;\r
+ // Some hosts (Pro Tools 2022.7) do not take the current DPI into account when sizing\r
+ // plugin editor windows. Instead of querying the OS for the DPI of the editor window,\r
+ // we approximate based on the physical size of the window that was actually provided\r
+ // for the context to draw into. This may break if the OpenGL context's component is\r
+ // scaled differently in its width and height - but in this case, a single scale factor\r
+ // isn't that helpful anyway.\r
+ const auto newScale = (float) newArea.getWidth() / (float) localBounds.getWidth();\r
#else\r
- auto newScale = displayScale;\r
+ const auto newScale = (float) displayScale;\r
#endif\r
\r
areaAndScale.set ({ newArea, newScale }, [&]\r
(float) newArea.getHeight() / (float) localBounds.getHeight());\r
\r
nativeContext->updateWindowPosition (peer->getAreaCoveredBy (component));\r
-\r
- if (canTriggerUpdate)\r
- invalidateAll();\r
+ invalidateAll();\r
});\r
}\r
}\r
\r
if (lastScreenBounds != screenBounds)\r
{\r
- updateViewportSize (true);\r
+ updateViewportSize();\r
lastScreenBounds = screenBounds;\r
}\r
}\r
\r
void drawComponentBuffer()\r
{\r
- #if ! JUCE_ANDROID\r
- glEnable (GL_TEXTURE_2D);\r
- clearGLError();\r
- #endif\r
+ if (contextRequiresTexture2DEnableDisable())\r
+ glEnable (GL_TEXTURE_2D);\r
\r
#if JUCE_WINDOWS\r
// some stupidly old drivers are missing this function, so try to at least avoid a crash here,\r
jassert (context.extensions.glActiveTexture != nullptr);\r
if (context.extensions.glActiveTexture != nullptr)\r
#endif\r
+ {\r
context.extensions.glActiveTexture (GL_TEXTURE0);\r
+ }\r
\r
glBindTexture (GL_TEXTURE_2D, cachedImageFrameBuffer.getTextureID());\r
bindVertexArray();\r
\r
void handleResize()\r
{\r
- updateViewportSize (true);\r
+ updateViewportSize();\r
\r
#if JUCE_MAC\r
- if (hasInitialised)\r
+ if (isFlagSet (state, StateFlags::initialised))\r
{\r
[nativeContext->view update];\r
- renderFrame();\r
+\r
+ // We're already on the message thread, no need to lock it again.\r
+ MessageManager::Lock mml;\r
+ renderFrame (mml);\r
}\r
#endif\r
}\r
\r
//==============================================================================\r
- JobStatus runJob() override\r
- {\r
- {\r
- // Allow the message thread to finish setting-up the context before using it.\r
- MessageManager::Lock::ScopedTryLockType mmLock (messageManagerLock, false);\r
-\r
- do\r
- {\r
- if (shouldExit())\r
- return ThreadPoolJob::jobHasFinished;\r
-\r
- } while (! mmLock.retryLock());\r
- }\r
-\r
- if (! initialiseOnThread())\r
- {\r
- hasInitialised = false;\r
-\r
- return ThreadPoolJob::jobHasFinished;\r
- }\r
-\r
- hasInitialised = true;\r
-\r
- while (! shouldExit())\r
- {\r
- #if JUCE_IOS\r
- if (backgroundProcessCheck.isBackgroundProcess())\r
- {\r
- repaintEvent.wait (300);\r
- repaintEvent.reset();\r
- continue;\r
- }\r
- #endif\r
-\r
- if (shouldExit())\r
- break;\r
-\r
- #if JUCE_MAC\r
- if (context.continuousRepaint)\r
- {\r
- repaintEvent.wait (-1);\r
- renderFrame();\r
- }\r
- else\r
- #endif\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
-\r
- repaintEvent.reset();\r
- }\r
-\r
- hasInitialised = false;\r
- context.makeActive();\r
- shutdownOnThread();\r
- OpenGLContext::deactivateCurrentContext();\r
-\r
- return ThreadPoolJob::jobHasFinished;\r
- }\r
-\r
- bool initialiseOnThread()\r
+ InitResult initialiseOnThread()\r
{\r
// On android, this can get called twice, so drop any previous state.\r
associatedObjectNames.clear();\r
\r
context.makeActive();\r
\r
- if (! nativeContext->initialiseOnRenderThread (context))\r
- return false;\r
+ if (const auto nativeResult = nativeContext->initialiseOnRenderThread (context); nativeResult != InitResult::success)\r
+ return nativeResult;\r
\r
#if JUCE_ANDROID\r
// On android the context may be created in initialiseOnRenderThread\r
bindVertexArray();\r
}\r
\r
+ #if JUCE_DEBUG\r
+ if (getOpenGLVersion() >= Version { 4, 3 } && glDebugMessageCallback != nullptr)\r
+ {\r
+ glEnable (GL_DEBUG_OUTPUT);\r
+ glDebugMessageCallback ([] (GLenum type, GLenum, GLuint, GLenum severity, GLsizei, const GLchar* message, const void*)\r
+ {\r
+ // This may reiterate issues that are also flagged by JUCE_CHECK_OPENGL_ERROR.\r
+ // The advantage of this callback is that it will catch *all* errors, even if we\r
+ // forget to check manually.\r
+ DBG ("OpenGL DBG message: " << message);\r
+ jassertquiet (type != GL_DEBUG_TYPE_ERROR && severity != GL_DEBUG_SEVERITY_HIGH);\r
+ }, nullptr);\r
+ }\r
+ #endif\r
+\r
const auto currentViewportArea = areaAndScale.get().area;\r
glViewport (0, 0, currentViewportArea.getWidth(), currentViewportArea.getHeight());\r
\r
if (context.renderer != nullptr)\r
context.renderer->newOpenGLContextCreated();\r
\r
- #if JUCE_MAC\r
- jassert (cvDisplayLinkWrapper != nullptr);\r
- nativeContext->setNominalVideoRefreshPeriodS (cvDisplayLinkWrapper->getNominalVideoRefreshPeriodS());\r
- #endif\r
-\r
- return true;\r
+ return InitResult::success;\r
}\r
\r
void shutdownOnThread()\r
WaitableEvent finishedSignal;\r
};\r
\r
- bool doWorkWhileWaitingForLock (bool contextIsAlreadyActive)\r
+ void doWorkWhileWaitingForLock (ScopedContextActivator& contextActivator)\r
{\r
- bool contextActivated = false;\r
-\r
- for (OpenGLContext::AsyncWorker::Ptr work = workQueue.removeAndReturn (0);\r
- work != nullptr && (! shouldExit()); work = workQueue.removeAndReturn (0))\r
+ while (const auto work = workQueue.removeAndReturn (0))\r
{\r
- if ((! contextActivated) && (! contextIsAlreadyActive))\r
- {\r
- if (! context.makeActive())\r
- break;\r
-\r
- contextActivated = true;\r
- }\r
+ if (renderThread->isListChanging() || ! contextActivator.activate (context))\r
+ break;\r
\r
NativeContext::Locker locker (*nativeContext);\r
\r
(*work) (context);\r
clearGLError();\r
}\r
-\r
- if (contextActivated)\r
- OpenGLContext::deactivateCurrentContext();\r
-\r
- return shouldExit();\r
}\r
\r
- void execute (OpenGLContext::AsyncWorker::Ptr workerToUse, bool shouldBlock, bool calledFromDestructor = false)\r
+ void execute (OpenGLContext::AsyncWorker::Ptr workerToUse, bool shouldBlock)\r
{\r
- if (calledFromDestructor || ! destroying)\r
+ if (! isFlagSet (state, StateFlags::pendingDestruction))\r
{\r
if (shouldBlock)\r
{\r
OpenGLContext::AsyncWorker::Ptr worker (*blocker);\r
workQueue.add (worker);\r
\r
- messageManagerLock.abort();\r
+ renderThread->abortLock();\r
context.triggerRepaint();\r
\r
blocker->block();\r
{\r
workQueue.add (std::move (workerToUse));\r
\r
- messageManagerLock.abort();\r
+ renderThread->abortLock();\r
context.triggerRepaint();\r
}\r
}\r
return dynamic_cast<CachedImage*> (c.getCachedComponentImage());\r
}\r
\r
+ class RenderThread\r
+ {\r
+ public:\r
+ RenderThread() = default;\r
+\r
+ ~RenderThread()\r
+ {\r
+ flags.setDestructing();\r
+ thread.join();\r
+ }\r
+\r
+ void add (CachedImage* x)\r
+ {\r
+ const std::scoped_lock lock { listMutex };\r
+ images.push_back (x);\r
+ }\r
+\r
+ void remove (CachedImage* x)\r
+ {\r
+ JUCE_ASSERT_MESSAGE_THREAD;\r
+\r
+ flags.setSafe (false);\r
+ abortLock();\r
+\r
+ {\r
+ const std::scoped_lock lock { callbackMutex, listMutex };\r
+ images.remove (x);\r
+ }\r
+\r
+ flags.setSafe (true);\r
+ }\r
+\r
+ bool contains (CachedImage* x)\r
+ {\r
+ const std::scoped_lock lock { listMutex };\r
+ return std::find (images.cbegin(), images.cend(), x) != images.cend();\r
+ }\r
+\r
+ void triggerRepaint() { flags.setRenderRequested(); }\r
+\r
+ void abortLock() { messageManagerLock.abort(); }\r
+\r
+ bool isListChanging() { return ! flags.isSafe(); }\r
+\r
+ private:\r
+ RenderStatus renderAll()\r
+ {\r
+ auto result = RenderStatus::noWork;\r
+\r
+ const std::scoped_lock lock { callbackMutex, listMutex };\r
+\r
+ for (auto* x : images)\r
+ {\r
+ listMutex.unlock();\r
+ const ScopeGuard scope { [&] { listMutex.lock(); } };\r
+\r
+ const auto status = x->renderFrame (messageManagerLock);\r
+\r
+ switch (status)\r
+ {\r
+ case RenderStatus::noWork: break;\r
+ case RenderStatus::nominal: result = RenderStatus::nominal; break;\r
+ case RenderStatus::messageThreadAborted: return RenderStatus::messageThreadAborted;\r
+ }\r
+\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ /* Allows the main thread to communicate changes to the render thread.\r
+\r
+ When the render thread needs to change in some way (asked to resume rendering,\r
+ a renderer is added/removed, or the thread needs to stop prior to destruction),\r
+ the main thread can set the appropriate flag on this structure. The render thread\r
+ will call waitForWork() repeatedly, pausing when the render thread has no work to do,\r
+ and resuming when requested by the main thread.\r
+ */\r
+ class Flags\r
+ {\r
+ public:\r
+ void setDestructing() { update ([] (auto& f) { f |= destructorCalled; }); }\r
+ void setRenderRequested() { update ([] (auto& f) { f |= renderRequested; }); }\r
+\r
+ void setSafe (const bool safe)\r
+ {\r
+ update ([safe] (auto& f)\r
+ {\r
+ if (safe)\r
+ f |= listSafe;\r
+ else\r
+ f &= ~listSafe;\r
+ });\r
+ }\r
+\r
+ bool isSafe()\r
+ {\r
+ const std::scoped_lock lock { mutex };\r
+ return (flags & listSafe) != 0;\r
+ }\r
+\r
+ /* Blocks until the 'safe' flag is set, and at least one other flag is set.\r
+ After returning, the renderRequested flag will be unset.\r
+ Returns true if rendering should continue.\r
+ */\r
+ bool waitForWork (bool requestRender)\r
+ {\r
+ std::unique_lock lock { mutex };\r
+ flags |= (requestRender ? renderRequested : 0);\r
+ condvar.wait (lock, [this] { return flags > listSafe; });\r
+ flags &= ~renderRequested;\r
+ return ((flags & destructorCalled) == 0);\r
+ }\r
+\r
+ private:\r
+ template <typename Fn>\r
+ void update (Fn fn)\r
+ {\r
+ {\r
+ const std::scoped_lock lock { mutex };\r
+ fn (flags);\r
+ }\r
+\r
+ condvar.notify_one();\r
+ }\r
+\r
+ enum\r
+ {\r
+ renderRequested = 1 << 0,\r
+ destructorCalled = 1 << 1,\r
+ listSafe = 1 << 2\r
+ };\r
+\r
+ std::mutex mutex;\r
+ std::condition_variable condvar;\r
+ int flags = listSafe;\r
+ };\r
+\r
+ MessageManager::Lock messageManagerLock;\r
+ std::mutex listMutex, callbackMutex;\r
+ std::list<CachedImage*> images;\r
+ Flags flags;\r
+\r
+ std::thread thread { [this]\r
+ {\r
+ Thread::setCurrentThreadName ("OpenGL Renderer");\r
+ while (flags.waitForWork (renderAll() != RenderStatus::noWork)) {}\r
+ } };\r
+ };\r
+\r
//==============================================================================\r
friend class NativeContext;\r
std::unique_ptr<NativeContext> nativeContext;\r
OpenGLContext& context;\r
Component& component;\r
\r
+ SharedResourcePointer<RenderThread> renderThread;\r
+\r
OpenGLFrameBuffer cachedImageFrameBuffer;\r
RectangleList<int> validArea;\r
Rectangle<int> lastScreenBounds;\r
StringArray associatedObjectNames;\r
ReferenceCountedArray<ReferenceCountedObject> associatedObjects;\r
\r
- WaitableEvent canPaintNowFlag, finishedPaintingFlag, repaintEvent { true };\r
+ WaitableEvent canPaintNowFlag, finishedPaintingFlag;\r
#if JUCE_OPENGL_ES\r
bool shadersAvailable = true;\r
#else\r
bool shadersAvailable = false;\r
#endif\r
bool textureNpotSupported = false;\r
- std::atomic<bool> hasInitialised { false }, needsUpdate { true }, destroying { false };\r
- uint32 lastMMLockReleaseTime = 0;\r
+ std::chrono::steady_clock::time_point lastMMLockReleaseTime{};\r
\r
#if JUCE_MAC\r
NSView* getCurrentView() const\r
{\r
+ JUCE_ASSERT_MESSAGE_THREAD;\r
+\r
if (auto* peer = component.getPeer())\r
return static_cast<NSView*> (peer->getNativeHandle());\r
\r
return nullptr;\r
}\r
\r
- NSScreen* getCurrentScreen() const\r
+ NSWindow* getCurrentWindow() const\r
{\r
JUCE_ASSERT_MESSAGE_THREAD;\r
\r
if (auto* view = getCurrentView())\r
- if (auto* window = [view window])\r
- return [window screen];\r
+ return [view window];\r
\r
return nullptr;\r
}\r
\r
- struct CVDisplayLinkWrapper\r
+ NSScreen* getCurrentScreen() const\r
{\r
- explicit CVDisplayLinkWrapper (CachedImage& cachedImageIn)\r
- : cachedImage (cachedImageIn),\r
- continuousRepaint (cachedImageIn.context.continuousRepaint.load())\r
- {\r
- CVDisplayLinkCreateWithActiveCGDisplays (&displayLink);\r
- CVDisplayLinkSetOutputCallback (displayLink, &displayLinkCallback, this);\r
- CVDisplayLinkStart (displayLink);\r
- }\r
+ JUCE_ASSERT_MESSAGE_THREAD;\r
\r
- double getNominalVideoRefreshPeriodS() const\r
- {\r
- const auto nominalVideoRefreshPeriod = CVDisplayLinkGetNominalOutputVideoRefreshPeriod (displayLink);\r
+ if (auto* window = getCurrentWindow())\r
+ return [window screen];\r
\r
- if ((nominalVideoRefreshPeriod.flags & kCVTimeIsIndefinite) == 0)\r
- return (double) nominalVideoRefreshPeriod.timeValue / (double) nominalVideoRefreshPeriod.timeScale;\r
+ return nullptr;\r
+ }\r
\r
- return 0.0;\r
- }\r
+ void updateScreen()\r
+ {\r
+ const auto screen = getCurrentScreen();\r
+ const auto display = ScopedDisplayLink::getDisplayIdForScreen (screen);\r
\r
- /* Returns true if updated, or false otherwise. */\r
- bool updateActiveDisplay()\r
- {\r
- auto* oldScreen = std::exchange (currentScreen, cachedImage.getCurrentScreen());\r
+ if (lastDisplay.exchange (display) == display)\r
+ return;\r
\r
- if (oldScreen == currentScreen)\r
- return false;\r
+ const auto newRefreshPeriod = sharedDisplayLinks->getNominalVideoRefreshPeriodSForScreen (display);\r
\r
- for (NSScreen* screen in [NSScreen screens])\r
- if (screen == currentScreen)\r
- if (NSNumber* number = [[screen deviceDescription] objectForKey: @"NSScreenNumber"])\r
- CVDisplayLinkSetCurrentCGDisplay (displayLink, [number unsignedIntValue]);\r
+ if (newRefreshPeriod != 0.0 && std::exchange (refreshPeriod, newRefreshPeriod) != newRefreshPeriod)\r
+ nativeContext->setNominalVideoRefreshPeriodS (newRefreshPeriod);\r
\r
- return true;\r
- }\r
+ updateColourSpace();\r
+ }\r
\r
- ~CVDisplayLinkWrapper()\r
- {\r
- CVDisplayLinkStop (displayLink);\r
- CVDisplayLinkRelease (displayLink);\r
- }\r
+ void updateColourSpace()\r
+ {\r
+ if (auto* view = nativeContext->getNSView())\r
+ if (auto* window = [view window])\r
+ [window setColorSpace: [NSColorSpace sRGBColorSpace]];\r
+ }\r
\r
- static CVReturn displayLinkCallback (CVDisplayLinkRef, const CVTimeStamp*, const CVTimeStamp*,\r
- CVOptionFlags, CVOptionFlags*, void* displayLinkContext)\r
- {\r
- auto* self = reinterpret_cast<CVDisplayLinkWrapper*> (displayLinkContext);\r
+ std::atomic<CGDirectDisplayID> lastDisplay { 0 };\r
+ double refreshPeriod = 0.0;\r
\r
- if (self->continuousRepaint)\r
- self->cachedImage.repaintEvent.signal();\r
+ FunctionNotificationCenterObserver observer { NSWindowDidChangeScreenNotification,\r
+ getCurrentWindow(),\r
+ [this] { updateScreen(); } };\r
\r
- return kCVReturnSuccess;\r
- }\r
+ // Note: the NSViewComponentPeer also has a SharedResourcePointer<PerScreenDisplayLinks> to\r
+ // avoid unnecessarily duplicating display-link threads.\r
+ SharedResourcePointer<PerScreenDisplayLinks> sharedDisplayLinks;\r
+ #endif\r
\r
- CachedImage& cachedImage;\r
- const bool continuousRepaint;\r
- CVDisplayLinkRef displayLink;\r
- NSScreen* currentScreen = nullptr;\r
- };\r
+ enum StateFlags\r
+ {\r
+ pendingRender = 1 << 0,\r
+ paintComponents = 1 << 1,\r
+ pendingDestruction = 1 << 2,\r
+ initialised = 1 << 3,\r
\r
- std::unique_ptr<CVDisplayLinkWrapper> cvDisplayLinkWrapper;\r
- #endif\r
+ // Flags that may change state after each frame\r
+ transient = pendingRender | paintComponents,\r
\r
- std::unique_ptr<ThreadPool> renderThread;\r
+ // Flags that should retain their state after each frame\r
+ persistent = initialised | pendingDestruction\r
+ };\r
+\r
+ std::atomic<int> state { 0 };\r
ReferenceCountedArray<OpenGLContext::AsyncWorker, CriticalSection> workQueue;\r
- MessageManager::Lock messageManagerLock;\r
\r
#if JUCE_IOS\r
iOSBackgroundProcessCheck backgroundProcessCheck;\r
}\r
#endif\r
\r
- void update()\r
- {\r
- auto& comp = *getComponent();\r
-\r
- if (canBeAttached (comp))\r
- start();\r
- else\r
- stop();\r
- }\r
-\r
private:\r
OpenGLContext& context;\r
\r
if (auto* cachedImage = CachedImage::get (comp))\r
{\r
cachedImage->start(); // (must wait until this is attached before starting its thread)\r
- cachedImage->updateViewportSize (true);\r
+ cachedImage->updateViewportSize();\r
\r
startTimer (400);\r
}\r
struct OverlayShaderProgram : public ReferenceCountedObject\r
{\r
OverlayShaderProgram (OpenGLContext& context)\r
- : program (context), builder (program), params (program)\r
+ : program (context), params (program)\r
{}\r
\r
static const OverlayShaderProgram& select (OpenGLContext& context)\r
return *program;\r
}\r
\r
- struct ProgramBuilder\r
+ struct BuiltProgram : public OpenGLShaderProgram\r
{\r
- ProgramBuilder (OpenGLShaderProgram& prog)\r
+ explicit BuiltProgram (OpenGLContext& ctx)\r
+ : OpenGLShaderProgram (ctx)\r
{\r
- prog.addVertexShader (OpenGLHelpers::translateVertexShaderToV3 (\r
+ addVertexShader (OpenGLHelpers::translateVertexShaderToV3 (\r
"attribute " JUCE_HIGHP " vec2 position;"\r
"uniform " JUCE_HIGHP " vec2 screenSize;"\r
"uniform " JUCE_HIGHP " float textureBounds[4];"\r
"texturePos = vec2 (texturePos.x, vOffsetAndScale.x + vOffsetAndScale.y * texturePos.y);"\r
"}"));\r
\r
- prog.addFragmentShader (OpenGLHelpers::translateFragmentShaderToV3 (\r
+ addFragmentShader (OpenGLHelpers::translateFragmentShaderToV3 (\r
"uniform sampler2D imageTexture;"\r
"varying " JUCE_HIGHP " vec2 texturePos;"\r
"void main()"\r
"gl_FragColor = texture2D (imageTexture, texturePos);"\r
"}"));\r
\r
- prog.link();\r
+ link();\r
}\r
};\r
\r
OpenGLShaderProgram::Uniform screenSize, imageTexture, textureBounds, vOffsetAndScale;\r
};\r
\r
- OpenGLShaderProgram program;\r
- ProgramBuilder builder;\r
+ BuiltProgram program;\r
Params params;\r
};\r
\r
}\r
\r
#if JUCE_ANDROID\r
-EGLDisplay OpenGLContext::NativeContext::display = EGL_NO_DISPLAY;\r
-EGLDisplay OpenGLContext::NativeContext::config;\r
\r
-void OpenGLContext::NativeContext::surfaceCreated (LocalRef<jobject> holder)\r
+void OpenGLContext::NativeContext::surfaceCreated (LocalRef<jobject>)\r
{\r
- ignoreUnused (holder);\r
-\r
- if (auto* cachedImage = CachedImage::get (component))\r
{\r
- if (auto* pool = cachedImage->renderThread.get())\r
+ const std::lock_guard lock { nativeHandleMutex };\r
+\r
+ jassert (hasInitialised);\r
+\r
+ // has the context already attached?\r
+ jassert (surface.get() == EGL_NO_SURFACE && context.get() == EGL_NO_CONTEXT);\r
+\r
+ const auto window = getNativeWindow();\r
+\r
+ if (window == nullptr)\r
{\r
- if (! pool->contains (cachedImage))\r
- {\r
- cachedImage->resume();\r
- cachedImage->context.triggerRepaint();\r
- }\r
+ // failed to get a pointer to the native window so bail out\r
+ jassertfalse;\r
+ return;\r
}\r
+\r
+ // create the surface\r
+ surface.reset (eglCreateWindowSurface (display, config, window.get(), nullptr));\r
+ jassert (surface.get() != EGL_NO_SURFACE);\r
+\r
+ // create the OpenGL context\r
+ EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };\r
+ context.reset (eglCreateContext (display, config, EGL_NO_CONTEXT, contextAttribs));\r
+ jassert (context.get() != EGL_NO_CONTEXT);\r
+ }\r
+\r
+ if (auto* cached = CachedImage::get (component))\r
+ {\r
+ cached->resume();\r
+ cached->triggerRepaint();\r
}\r
}\r
\r
-void OpenGLContext::NativeContext::surfaceDestroyed (LocalRef<jobject> holder)\r
+void OpenGLContext::NativeContext::surfaceDestroyed (LocalRef<jobject>)\r
{\r
- ignoreUnused (holder);\r
+ if (auto* cached = CachedImage::get (component))\r
+ cached->pause();\r
\r
- // unlike the name suggests this will be called just before the\r
- // surface is destroyed. We need to pause the render thread.\r
- if (auto* cachedImage = CachedImage::get (component))\r
{\r
- cachedImage->pause();\r
+ const std::lock_guard lock { nativeHandleMutex };\r
\r
- if (auto* threadPool = cachedImage->renderThread.get())\r
- threadPool->waitForJobToFinish (cachedImage, -1);\r
+ context.reset (EGL_NO_CONTEXT);\r
+ surface.reset (EGL_NO_SURFACE);\r
}\r
}\r
+\r
#endif\r
\r
} // namespace juce\r
/** OpenGL versions, used by setOpenGLVersionRequired(). */\r
enum OpenGLVersion\r
{\r
- defaultGLVersion = 0,\r
- openGL3_2\r
+ defaultGLVersion = 0, ///< Whatever the device decides to give us, normally a compatibility profile\r
+ openGL3_2, ///< 3.2 Core profile\r
+ openGL4_1, ///< 4.1 Core profile, the latest supported by macOS at time of writing\r
+ openGL4_3 ///< 4.3 Core profile, will enable improved debugging support when building in Debug\r
};\r
\r
/** Sets a preference for the version of GL that this context should use, if possible.\r
#endif\r
\r
private:\r
+ enum class InitResult\r
+ {\r
+ fatal,\r
+ retry,\r
+ success\r
+ };\r
+\r
friend class OpenGLTexture;\r
\r
class CachedImage;\r
//==============================================================================\r
struct ActiveTextures\r
{\r
- ActiveTextures (const OpenGLContext& c) noexcept : context (c)\r
- {}\r
+ explicit ActiveTextures (const OpenGLContext& c) noexcept\r
+ : context (c)\r
+ {\r
+ }\r
\r
void clear() noexcept\r
{\r
{\r
quadQueue.flush();\r
\r
- for (int i = 3; --i >= 0;)\r
+ for (int i = numTextures; --i >= 0;)\r
{\r
if ((texturesEnabled & (1 << i)) != (textureIndexMask & (1 << i)))\r
{\r
setActiveTexture (i);\r
JUCE_CHECK_OPENGL_ERROR\r
\r
+ const auto thisTextureEnabled = (textureIndexMask & (1 << i)) != 0;\r
+\r
+ if (! thisTextureEnabled)\r
+ currentTextureID[i] = 0;\r
+\r
#if ! JUCE_ANDROID\r
- if ((textureIndexMask & (1 << i)) != 0)\r
- glEnable (GL_TEXTURE_2D);\r
- else\r
+ if (needsToEnableTexture)\r
{\r
- glDisable (GL_TEXTURE_2D);\r
- currentTextureID[i] = 0;\r
- }\r
+ if (thisTextureEnabled)\r
+ glEnable (GL_TEXTURE_2D);\r
+ else\r
+ glDisable (GL_TEXTURE_2D);\r
\r
- clearGLError();\r
+ JUCE_CHECK_OPENGL_ERROR\r
+ }\r
#endif\r
}\r
}\r
GLuint currentTextureID[numTextures];\r
int texturesEnabled = 0, currentActiveTexture = -1;\r
const OpenGLContext& context;\r
+ const bool needsToEnableTexture = contextRequiresTexture2DEnableDisable();\r
\r
ActiveTextures& operator= (const ActiveTextures&);\r
};\r
\r
ID: juce_osc\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\r
name: JUCE OSC classes\r
description: Open Sound Control implementation.\r
website: http://www.juce.com/juce\r
license: GPL/Commercial\r
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_events\r
\r
\r
ID: juce_product_unlocking\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_cryptography\r
\r
cancelButton->addListener (this);\r
}\r
\r
- startThread (4);\r
+ startThread (Priority::normal);\r
}\r
\r
~OverlayComp() override\r
ids.add (getEncodedIDString (address.toString()));\r
}\r
\r
+String OnlineUnlockStatus::MachineIDUtilities::getUniqueMachineID()\r
+{\r
+ return getEncodedIDString (SystemStats::getUniqueDeviceID());\r
+}\r
+\r
+JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")\r
+JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)\r
+\r
StringArray OnlineUnlockStatus::MachineIDUtilities::getLocalMachineIDs()\r
{\r
auto identifiers = SystemStats::getDeviceIdentifiers();\r
return MachineIDUtilities::getLocalMachineIDs();\r
}\r
\r
+JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+JUCE_END_IGNORE_WARNINGS_MSVC\r
+\r
void OnlineUnlockStatus::userCancelled()\r
{\r
}\r
return false;\r
}\r
\r
-static bool canConnectToWebsite (const URL& url)\r
-{\r
- return url.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)\r
- .withConnectionTimeoutMs (2000)) != nullptr;\r
-}\r
-\r
static bool areMajorWebsitesAvailable()\r
{\r
- const char* urlsToTry[] = { "http://google.com", "http://bing.com", "http://amazon.com",\r
- "https://google.com", "https://bing.com", "https://amazon.com", nullptr};\r
-\r
- for (const char** url = urlsToTry; *url != nullptr; ++url)\r
- if (canConnectToWebsite (URL (*url)))\r
- return true;\r
+ static constexpr const char* const urlsToTry[] = { "http://google.com", "http://bing.com", "http://amazon.com",\r
+ "https://google.com", "https://bing.com", "https://amazon.com" };\r
+ const auto canConnectToWebsite = [] (auto url)\r
+ {\r
+ return URL (url).createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)\r
+ .withConnectionTimeoutMs (2000)) != nullptr;\r
+ };\r
\r
- return false;\r
+ return std::any_of (std::begin (urlsToTry),\r
+ std::end (urlsToTry),\r
+ canConnectToWebsite);\r
}\r
\r
OnlineUnlockStatus::UnlockResult OnlineUnlockStatus::handleXmlReply (XmlElement xml)\r
/** Utility function that you may want to use in your machine-ID generation code.\r
This adds some ID strings to the given array which represent each MAC address of the machine.\r
*/\r
+ [[deprecated ("MAC addresses are no longer reliable methods of ID generation. You should use getUniqueMachineID() instead, You can still get a list of this device's MAC addresses with MACAddress::findAllAddresses().")]]\r
static void addMACAddressesToList (StringArray& result);\r
\r
/** This method calculates some machine IDs based on things like network\r
registration on machines which have had hardware added/removed\r
since the product was first registered.\r
*/\r
+ [[deprecated ("The identifiers generated by this function are no longer reliable. Use getUniqueMachineID() instead.")]]\r
static StringArray getLocalMachineIDs();\r
+\r
+ /** Returns an encoded unique machine ID.\r
+\r
+ @see SystemStats::getUniqueDeviceID\r
+ */\r
+ static String getUniqueMachineID();\r
};\r
\r
private:\r
\r
ID: juce_video\r
vendor: juce\r
- version: 7.0.2\r
+ version: 7.0.3\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
- minimumCppStandard: 14\r
+ minimumCppStandard: 17\r
\r
dependencies: juce_gui_extra\r
OSXFrameworks: AVKit AVFoundation CoreMedia\r