diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index 7a414e6d2f..aa7994b191 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -2,6 +2,28 @@ # Version 8.0.9 +## Change + +AudioProcessor::TrackProperties::colour has been removed. It is replaced by a +new data member, colourARGB. + +**Possible Issues** + +Code that references this data member will fail to compile. + +**Workaround** + +Use the new colourARGB field, which holds the raw ARGB values packed in a +uint32, instead. In order to convert to a Colour instance, pass the value held +by colourARGB to the constructor of Colour. + +**Rationale** + +This change removes the dependency between the juce_audio_processors_headless +and juce_graphics. It is now possible to build programs that work with headless +AudioProcessors without needing to include juce_graphics. + + ## Change The function AudioPluginFormatManager::addDefaultFormats() has been removed. diff --git a/examples/Plugins/ARAPluginDemo.h b/examples/Plugins/ARAPluginDemo.h index c9a9777082..83f11ee5aa 100644 --- a/examples/Plugins/ARAPluginDemo.h +++ b/examples/Plugins/ARAPluginDemo.h @@ -1440,7 +1440,7 @@ public: void paint (Graphics& g) override { - g.fillAll (convertOptionalARAColour (playbackRegion.getEffectiveColor(), Colours::black)); + g.fillAll (Colour { convertOptionalARAColour (playbackRegion.getEffectiveColor()) }); const auto* audioModification = playbackRegion.getAudioModification(); g.setColour (audioModification->isDimmed() ? Colours::darkgrey.darker() : Colours::darkgrey.brighter()); @@ -1827,7 +1827,7 @@ public: if (auto colour = regionSequence.getColor()) { - g.setColour (convertARAColour (colour)); + g.setColour (Colour { convertARAColourARGB (colour) }); g.fillRect (getLocalBounds().removeFromTop (16).reduced (6)); g.fillRect (getLocalBounds().removeFromBottom (16).reduced (6)); } diff --git a/examples/Plugins/AudioPluginDemo.h b/examples/Plugins/AudioPluginDemo.h index 5aeb4c803b..f24a68e56a 100644 --- a/examples/Plugins/AudioPluginDemo.h +++ b/examples/Plugins/AudioPluginDemo.h @@ -468,10 +468,10 @@ private: void updateTrackProperties() { - auto trackColour = getProcessor().getTrackProperties().colour; + auto trackColour = getProcessor().getTrackProperties().colourARGB; auto& lf = getLookAndFeel(); - backgroundColour = (trackColour.has_value() ? trackColour->withAlpha (1.0f).withBrightness (0.266f) + backgroundColour = (trackColour.has_value() ? Colour { *trackColour }.withAlpha (1.0f).withBrightness (0.266f) : lf.findColour (ResizableWindow::backgroundColourId)); repaint(); } diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp index cadec2315d..173a2c7e6b 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp @@ -1158,8 +1158,7 @@ public: { Steinberg::int64 colour; if (list->getInt (Vst::ChannelContext::kChannelColorKey, colour) == kResultTrue) - trackProperties.colour = std::make_optional (Colour (Vst::ChannelContext::GetRed ((uint32) colour), Vst::ChannelContext::GetGreen ((uint32) colour), - Vst::ChannelContext::GetBlue ((uint32) colour), Vst::ChannelContext::GetAlpha ((uint32) colour))); + trackProperties.colourARGB.emplace ((uint32) colour); } diff --git a/modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp index 80563cc5a8..ab4c4f220e 100644 --- a/modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp @@ -43,6 +43,125 @@ namespace juce namespace lv2_host { +class UiFeaturesData +{ +public: + UiFeaturesData (PhysicalResizeListener& rl, + TouchListener& tl, + LV2_Handle instanceIn, + LV2UI_Widget parentIn, + Instance::GetExtensionData getExtensionData, + const Ports& ports, + SymbolMap& symapIn, + const UiFeaturesDataOptions& optIn) + : opts (optIn), + resizeListener (rl), + touchListener (tl), + instance (instanceIn), + parent (parentIn), + symap (symapIn), + dataAccess { getExtensionData }, + portIndices (makePortIndices (ports)) + { + } + + const LV2_Feature* const* getFeatureArray() const noexcept { return features.pointers.data(); } + + Rectangle getLastRequestedBounds() const { return { lastRequestedWidth, lastRequestedHeight }; } + +private: + int resizeCallback (int width, int height) + { + lastRequestedWidth = width; + lastRequestedHeight = height; + resizeListener.viewRequestedResizeInPhysicalPixels (width, height); + return 0; + } + + static int resizeCallback (LV2UI_Feature_Handle handle, int width, int height) + { + return static_cast (handle)->resizeCallback (width, height); + } + + uint32_t portIndexCallback (const char* symbol) const + { + const auto it = portIndices.find (symbol); + return it != portIndices.cend() ? it->second : LV2UI_INVALID_PORT_INDEX; + } + + static uint32_t portIndexCallback (LV2UI_Feature_Handle handle, const char* symbol) + { + return static_cast (handle)->portIndexCallback (symbol); + } + + void touchCallback (uint32_t portIndex, bool grabbed) const + { + touchListener.controlGrabbed (portIndex, grabbed); + } + + static void touchCallback (LV2UI_Feature_Handle handle, uint32_t index, bool b) + { + return static_cast (handle)->touchCallback (index, b); + } + + static std::map makePortIndices (const Ports& ports) + { + std::map result; + + ports.forEachPort ([&] (const PortHeader& header) + { + [[maybe_unused]] const auto emplaced = result.emplace (header.symbol, header.index); + + // This will complain if there are duplicate port symbols. + jassert (emplaced.second); + }); + + return result; + } + + const UiFeaturesDataOptions opts; + PhysicalResizeListener& resizeListener; + TouchListener& touchListener; + LV2_Handle instance{}; + LV2UI_Widget parent{}; + SymbolMap& symap; + const UsefulUrids urids { symap }; + Log log { &urids }; + int lastRequestedWidth = 0, lastRequestedHeight = 0; + std::vector options { { LV2_OPTIONS_INSTANCE, + 0, + symap.map (LV2_UI__scaleFactor), + sizeof (float), + symap.map (LV2_ATOM__Float), + &opts.initialScaleFactor }, + { LV2_OPTIONS_INSTANCE, + 0, + symap.map (LV2_PARAMETERS__sampleRate), + sizeof (float), + symap.map (LV2_ATOM__Float), + &opts.sampleRate }, + { LV2_OPTIONS_INSTANCE, 0, 0, 0, 0, nullptr } }; // The final entry must be nulled out + LV2UI_Resize resize { this, resizeCallback }; + LV2_URID_Map map = symap.getMapFeature(); + LV2_URID_Unmap unmap = symap.getUnmapFeature(); + LV2UI_Port_Map portMap { this, portIndexCallback }; + LV2UI_Touch touch { this, touchCallback }; + LV2_Extension_Data_Feature dataAccess; + std::map portIndices; + Features features { UiFeatureUris::makeFeatures (&resize, + parent, + instance, + &dataAccess, + &map, + &unmap, + &portMap, + &touch, + options.data(), + log.getLogFeature()) }; + + JUCE_LEAK_DETECTOR (UiFeaturesData) +}; + /* Creates and holds a UI instance for a plugin with a specific URI, using the provided descriptor. */ diff --git a/modules/juce_audio_processors_headless/format_types/juce_LV2PluginFormatImpl.h b/modules/juce_audio_processors_headless/format_types/juce_LV2PluginFormatImpl.h index 5eeb307453..f21381e047 100644 --- a/modules/juce_audio_processors_headless/format_types/juce_LV2PluginFormatImpl.h +++ b/modules/juce_audio_processors_headless/format_types/juce_LV2PluginFormatImpl.h @@ -2613,38 +2613,14 @@ private: } }; -class UiFeaturesData +class UiFeatureUris { public: - UiFeaturesData (PhysicalResizeListener& rl, - TouchListener& tl, - LV2_Handle instanceIn, - LV2UI_Widget parentIn, - Instance::GetExtensionData getExtensionData, - const Ports& ports, - SymbolMap& symapIn, - const UiFeaturesDataOptions& optIn) - : opts (optIn), - resizeListener (rl), - touchListener (tl), - instance (instanceIn), - parent (parentIn), - symap (symapIn), - dataAccess { getExtensionData }, - portIndices (makePortIndices (ports)) - { - } - - const LV2_Feature* const* getFeatureArray() const noexcept { return features.pointers.data(); } - static std::vector getFeatureUris() { return Features::getUris (makeFeatures ({}, {}, {}, {}, {}, {}, {}, {}, {}, {})); } - Rectangle getLastRequestedBounds() const { return { lastRequestedWidth, lastRequestedHeight }; } - -private: static std::vector makeFeatures (LV2UI_Resize* resize, LV2UI_Widget parent, LV2_Handle handle, @@ -2668,97 +2644,6 @@ private: LV2_Feature { LV2_OPTIONS__options, options }, LV2_Feature { LV2_LOG__log, log } }; } - - int resizeCallback (int width, int height) - { - lastRequestedWidth = width; - lastRequestedHeight = height; - resizeListener.viewRequestedResizeInPhysicalPixels (width, height); - return 0; - } - - static int resizeCallback (LV2UI_Feature_Handle handle, int width, int height) - { - return static_cast (handle)->resizeCallback (width, height); - } - - uint32_t portIndexCallback (const char* symbol) const - { - const auto it = portIndices.find (symbol); - return it != portIndices.cend() ? it->second : LV2UI_INVALID_PORT_INDEX; - } - - static uint32_t portIndexCallback (LV2UI_Feature_Handle handle, const char* symbol) - { - return static_cast (handle)->portIndexCallback (symbol); - } - - void touchCallback (uint32_t portIndex, bool grabbed) const - { - touchListener.controlGrabbed (portIndex, grabbed); - } - - static void touchCallback (LV2UI_Feature_Handle handle, uint32_t index, bool b) - { - return static_cast (handle)->touchCallback (index, b); - } - - static std::map makePortIndices (const Ports& ports) - { - std::map result; - - ports.forEachPort ([&] (const PortHeader& header) - { - [[maybe_unused]] const auto emplaced = result.emplace (header.symbol, header.index); - - // This will complain if there are duplicate port symbols. - jassert (emplaced.second); - }); - - return result; - } - - const UiFeaturesDataOptions opts; - PhysicalResizeListener& resizeListener; - TouchListener& touchListener; - LV2_Handle instance{}; - LV2UI_Widget parent{}; - SymbolMap& symap; - const UsefulUrids urids { symap }; - Log log { &urids }; - int lastRequestedWidth = 0, lastRequestedHeight = 0; - std::vector options { { LV2_OPTIONS_INSTANCE, - 0, - symap.map (LV2_UI__scaleFactor), - sizeof (float), - symap.map (LV2_ATOM__Float), - &opts.initialScaleFactor }, - { LV2_OPTIONS_INSTANCE, - 0, - symap.map (LV2_PARAMETERS__sampleRate), - sizeof (float), - symap.map (LV2_ATOM__Float), - &opts.sampleRate }, - { LV2_OPTIONS_INSTANCE, 0, 0, 0, 0, nullptr } }; // The final entry must be nulled out - LV2UI_Resize resize { this, resizeCallback }; - LV2_URID_Map map = symap.getMapFeature(); - LV2_URID_Unmap unmap = symap.getUnmapFeature(); - LV2UI_Port_Map portMap { this, portIndexCallback }; - LV2UI_Touch touch { this, touchCallback }; - LV2_Extension_Data_Feature dataAccess; - std::map portIndices; - Features features { makeFeatures (&resize, - parent, - instance, - &dataAccess, - &map, - &unmap, - &portMap, - &touch, - options.data(), - log.getLogFeature()) }; - - JUCE_LEAK_DETECTOR (UiFeaturesData) }; struct RequiredFeatures @@ -4602,7 +4487,7 @@ public: }; const auto missingUiFeatures = findMissingFeatures (queryUi (LV2_CORE__requiredFeature), - lv2_host::UiFeaturesData::getFeatureUris()); + lv2_host::UiFeatureUris::getFeatureUris()); return missingUiFeatures.empty() ? bestMatch : nullptr; }(); diff --git a/modules/juce_audio_processors_headless/format_types/juce_VST3PluginFormatImpl.h b/modules/juce_audio_processors_headless/format_types/juce_VST3PluginFormatImpl.h index b818fd4e2a..dbd1831238 100644 --- a/modules/juce_audio_processors_headless/format_types/juce_VST3PluginFormatImpl.h +++ b/modules/juce_audio_processors_headless/format_types/juce_VST3PluginFormatImpl.h @@ -2680,7 +2680,7 @@ public: if (! std::strcmp (Vst::ChannelContext::kChannelNameLengthKey, id)) value = props.name.value_or (String{}).length(); else if (! std::strcmp (Vst::ChannelContext::kChannelColorKey, id)) - value = static_cast (props.colour.value_or (Colours::transparentBlack).getARGB()); + value = static_cast (props.colourARGB.value_or (0)); else return kResultFalse; diff --git a/modules/juce_audio_processors_headless/juce_audio_processors_headless.h b/modules/juce_audio_processors_headless/juce_audio_processors_headless.h index c62020a47c..eec282893a 100644 --- a/modules/juce_audio_processors_headless/juce_audio_processors_headless.h +++ b/modules/juce_audio_processors_headless/juce_audio_processors_headless.h @@ -51,7 +51,7 @@ license: AGPLv3/Commercial minimumCppStandard: 17 - dependencies: juce_audio_basics, juce_graphics + dependencies: juce_audio_basics juce_events OSXFrameworks: CoreAudio CoreMIDI AudioToolbox iOSFrameworks: AudioToolbox @@ -64,7 +64,7 @@ #define JUCE_AUDIO_PROCESSORS_HEADLESS_H_INCLUDED #include -#include +#include #include #include diff --git a/modules/juce_audio_processors_headless/processors/juce_AudioProcessor.h b/modules/juce_audio_processors_headless/processors/juce_AudioProcessor.h index b3cf4cd9d6..8fec4270b4 100644 --- a/modules/juce_audio_processors_headless/processors/juce_AudioProcessor.h +++ b/modules/juce_audio_processors_headless/processors/juce_AudioProcessor.h @@ -1313,13 +1313,14 @@ public: /** Returns a textual description of a WrapperType value */ static const char* getWrapperTypeDescription (AudioProcessor::WrapperType) noexcept; - /** A struct containing information about the DAW track inside which your - AudioProcessor is loaded. */ + AudioProcessor is loaded. + */ struct TrackProperties { - std::optional name; // The name of the track - this will be empty if the track name is not known - std::optional colour; // The colour of the track - this will be empty if the colour is not known + std::optional name; ///< The name of the track - this will be empty if the track name is not known + std::optional colourARGB; ///< The colour of the track - The format of this number is: ((alpha << 24) | (red << 16) | (green << 8) | blue). + ///< You can pass this to the constructor of Colour to create a matching colour instance. // other properties may be added in the future }; diff --git a/modules/juce_audio_processors_headless/utilities/ARA/juce_ARA_utils.h b/modules/juce_audio_processors_headless/utilities/ARA/juce_ARA_utils.h index 558d170be7..d4a5f10e88 100644 --- a/modules/juce_audio_processors_headless/utilities/ARA/juce_ARA_utils.h +++ b/modules/juce_audio_processors_headless/utilities/ARA/juce_ARA_utils.h @@ -70,9 +70,17 @@ inline String convertOptionalARAString (ARA::ARAUtf8String str, const String& fa } /** Converts an ARA::ARAColor* to a JUCE Colour. */ -inline Colour convertARAColour (const ARA::ARAColor* colour) +inline uint32 convertARAColourARGB (const ARA::ARAColor* colour) { - return Colour::fromFloatRGBA (colour->r, colour->g, colour->b, 1.0f); + static constexpr auto floatToByte = [] (float x) + { + return (uint32) jlimit (0, 255, roundToInt (x * 255.0f)); + }; + + return 0xff000000 + | (floatToByte (colour->r) << 0x10) + | (floatToByte (colour->g) << 0x08) + | (floatToByte (colour->b) << 0x00); } /** Converts a potentially NULL ARA::ARAColor* to a JUCE Colour. @@ -80,9 +88,9 @@ inline Colour convertARAColour (const ARA::ARAColor* colour) Returns the JUCE equivalent of the provided colour if it's not nullptr, and the fallback colour otherwise. */ -inline Colour convertOptionalARAColour (const ARA::ARAColor* colour, const Colour& fallbackColour = Colour()) +inline uint32 convertOptionalARAColour (const ARA::ARAColor* colour, uint32 fallbackColour = {}) { - return (colour != nullptr) ? convertARAColour (colour) : fallbackColour; + return (colour != nullptr) ? convertARAColourARGB (colour) : fallbackColour; } } // namespace juce diff --git a/modules/juce_core/misc/juce_Functional.h b/modules/juce_core/misc/juce_Functional.h index b33a61e4b4..e85d129300 100644 --- a/modules/juce_core/misc/juce_Functional.h +++ b/modules/juce_core/misc/juce_Functional.h @@ -46,6 +46,8 @@ namespace detail template constexpr auto equalityComparableToNullptr() != nullptr)>> = true; + + template struct Tag {}; } // namespace detail /** @endcond */ diff --git a/modules/juce_graphics/geometry/juce_Rectangle.h b/modules/juce_graphics/geometry/juce_Rectangle.h index 42b8248d9f..eb71819be3 100644 --- a/modules/juce_graphics/geometry/juce_Rectangle.h +++ b/modules/juce_graphics/geometry/juce_Rectangle.h @@ -39,8 +39,6 @@ namespace juce namespace detail { -template struct Tag {}; - inline auto getNumericValue (StringRef s, Tag) { return s.text.getIntValue32(); } inline auto getNumericValue (StringRef s, Tag) { return s.text.getDoubleValue(); } inline auto getNumericValue (StringRef s, Tag) { return static_cast (s.text.getDoubleValue()); }