1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-09 23:34:20 +00:00

juce_audio_processors_headless: Remove juce_graphics dependency

This commit is contained in:
reuk 2025-08-21 22:10:19 +01:00
parent 86123aeddf
commit 50b51f512a
No known key found for this signature in database
12 changed files with 170 additions and 136 deletions

View file

@ -2,6 +2,28 @@
# Version 8.0.9 # 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 ## Change
The function AudioPluginFormatManager::addDefaultFormats() has been removed. The function AudioPluginFormatManager::addDefaultFormats() has been removed.

View file

@ -1440,7 +1440,7 @@ public:
void paint (Graphics& g) override void paint (Graphics& g) override
{ {
g.fillAll (convertOptionalARAColour (playbackRegion.getEffectiveColor(), Colours::black)); g.fillAll (Colour { convertOptionalARAColour (playbackRegion.getEffectiveColor()) });
const auto* audioModification = playbackRegion.getAudioModification<ARADemoPluginAudioModification>(); const auto* audioModification = playbackRegion.getAudioModification<ARADemoPluginAudioModification>();
g.setColour (audioModification->isDimmed() ? Colours::darkgrey.darker() : Colours::darkgrey.brighter()); g.setColour (audioModification->isDimmed() ? Colours::darkgrey.darker() : Colours::darkgrey.brighter());
@ -1827,7 +1827,7 @@ public:
if (auto colour = regionSequence.getColor()) if (auto colour = regionSequence.getColor())
{ {
g.setColour (convertARAColour (colour)); g.setColour (Colour { convertARAColourARGB (colour) });
g.fillRect (getLocalBounds().removeFromTop (16).reduced (6)); g.fillRect (getLocalBounds().removeFromTop (16).reduced (6));
g.fillRect (getLocalBounds().removeFromBottom (16).reduced (6)); g.fillRect (getLocalBounds().removeFromBottom (16).reduced (6));
} }

View file

@ -468,10 +468,10 @@ private:
void updateTrackProperties() void updateTrackProperties()
{ {
auto trackColour = getProcessor().getTrackProperties().colour; auto trackColour = getProcessor().getTrackProperties().colourARGB;
auto& lf = getLookAndFeel(); 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)); : lf.findColour (ResizableWindow::backgroundColourId));
repaint(); repaint();
} }

View file

@ -1158,8 +1158,7 @@ public:
{ {
Steinberg::int64 colour; Steinberg::int64 colour;
if (list->getInt (Vst::ChannelContext::kChannelColorKey, colour) == kResultTrue) if (list->getInt (Vst::ChannelContext::kChannelColorKey, colour) == kResultTrue)
trackProperties.colour = std::make_optional (Colour (Vst::ChannelContext::GetRed ((uint32) colour), Vst::ChannelContext::GetGreen ((uint32) colour), trackProperties.colourARGB.emplace ((uint32) colour);
Vst::ChannelContext::GetBlue ((uint32) colour), Vst::ChannelContext::GetAlpha ((uint32) colour)));
} }

View file

@ -43,6 +43,125 @@ namespace juce
namespace lv2_host 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<int> 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<UiFeaturesData*> (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<const UiFeaturesData*> (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<const UiFeaturesData*> (handle)->touchCallback (index, b);
}
static std::map<String, uint32_t> makePortIndices (const Ports& ports)
{
std::map<String, uint32_t> 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<LV2_Options_Option> 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<String, uint32_t> 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. Creates and holds a UI instance for a plugin with a specific URI, using the provided descriptor.
*/ */

View file

@ -2613,38 +2613,14 @@ private:
} }
}; };
class UiFeaturesData class UiFeatureUris
{ {
public: 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<String> getFeatureUris() static std::vector<String> getFeatureUris()
{ {
return Features::getUris (makeFeatures ({}, {}, {}, {}, {}, {}, {}, {}, {}, {})); return Features::getUris (makeFeatures ({}, {}, {}, {}, {}, {}, {}, {}, {}, {}));
} }
Rectangle<int> getLastRequestedBounds() const { return { lastRequestedWidth, lastRequestedHeight }; }
private:
static std::vector<LV2_Feature> makeFeatures (LV2UI_Resize* resize, static std::vector<LV2_Feature> makeFeatures (LV2UI_Resize* resize,
LV2UI_Widget parent, LV2UI_Widget parent,
LV2_Handle handle, LV2_Handle handle,
@ -2668,97 +2644,6 @@ private:
LV2_Feature { LV2_OPTIONS__options, options }, LV2_Feature { LV2_OPTIONS__options, options },
LV2_Feature { LV2_LOG__log, log } }; 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<UiFeaturesData*> (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<const UiFeaturesData*> (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<const UiFeaturesData*> (handle)->touchCallback (index, b);
}
static std::map<String, uint32_t> makePortIndices (const Ports& ports)
{
std::map<String, uint32_t> 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<LV2_Options_Option> 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<String, uint32_t> portIndices;
Features features { makeFeatures (&resize,
parent,
instance,
&dataAccess,
&map,
&unmap,
&portMap,
&touch,
options.data(),
log.getLogFeature()) };
JUCE_LEAK_DETECTOR (UiFeaturesData)
}; };
struct RequiredFeatures struct RequiredFeatures
@ -4602,7 +4487,7 @@ public:
}; };
const auto missingUiFeatures = findMissingFeatures (queryUi (LV2_CORE__requiredFeature), const auto missingUiFeatures = findMissingFeatures (queryUi (LV2_CORE__requiredFeature),
lv2_host::UiFeaturesData::getFeatureUris()); lv2_host::UiFeatureUris::getFeatureUris());
return missingUiFeatures.empty() ? bestMatch : nullptr; return missingUiFeatures.empty() ? bestMatch : nullptr;
}(); }();

View file

@ -2680,7 +2680,7 @@ public:
if (! std::strcmp (Vst::ChannelContext::kChannelNameLengthKey, id)) if (! std::strcmp (Vst::ChannelContext::kChannelNameLengthKey, id))
value = props.name.value_or (String{}).length(); value = props.name.value_or (String{}).length();
else if (! std::strcmp (Vst::ChannelContext::kChannelColorKey, id)) else if (! std::strcmp (Vst::ChannelContext::kChannelColorKey, id))
value = static_cast<Steinberg::int64> (props.colour.value_or (Colours::transparentBlack).getARGB()); value = static_cast<Steinberg::int64> (props.colourARGB.value_or (0));
else else
return kResultFalse; return kResultFalse;

View file

@ -51,7 +51,7 @@
license: AGPLv3/Commercial license: AGPLv3/Commercial
minimumCppStandard: 17 minimumCppStandard: 17
dependencies: juce_audio_basics, juce_graphics dependencies: juce_audio_basics juce_events
OSXFrameworks: CoreAudio CoreMIDI AudioToolbox OSXFrameworks: CoreAudio CoreMIDI AudioToolbox
iOSFrameworks: AudioToolbox iOSFrameworks: AudioToolbox
@ -64,7 +64,7 @@
#define JUCE_AUDIO_PROCESSORS_HEADLESS_H_INCLUDED #define JUCE_AUDIO_PROCESSORS_HEADLESS_H_INCLUDED
#include <juce_audio_basics/juce_audio_basics.h> #include <juce_audio_basics/juce_audio_basics.h>
#include <juce_graphics/juce_graphics.h> #include <juce_events/juce_events.h>
#include <juce_audio_processors_headless/processors/juce_AudioProcessorListener.h> #include <juce_audio_processors_headless/processors/juce_AudioProcessorListener.h>
#include <juce_audio_processors_headless/utilities/juce_AAXClientExtensions.h> #include <juce_audio_processors_headless/utilities/juce_AAXClientExtensions.h>

View file

@ -1313,13 +1313,14 @@ public:
/** Returns a textual description of a WrapperType value */ /** Returns a textual description of a WrapperType value */
static const char* getWrapperTypeDescription (AudioProcessor::WrapperType) noexcept; static const char* getWrapperTypeDescription (AudioProcessor::WrapperType) noexcept;
/** A struct containing information about the DAW track inside which your /** A struct containing information about the DAW track inside which your
AudioProcessor is loaded. */ AudioProcessor is loaded.
*/
struct TrackProperties struct TrackProperties
{ {
std::optional<String> name; // The name of the track - this will be empty if the track name is not known std::optional<String> name; ///< The name of the track - this will be empty if the track name is not known
std::optional<Colour> colour; // The colour of the track - this will be empty if the colour is not known std::optional<uint32> 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 // other properties may be added in the future
}; };

View file

@ -70,9 +70,17 @@ inline String convertOptionalARAString (ARA::ARAUtf8String str, const String& fa
} }
/** Converts an ARA::ARAColor* to a JUCE Colour. */ /** 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. /** 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 Returns the JUCE equivalent of the provided colour if it's not nullptr, and the fallback colour
otherwise. 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 } // namespace juce

View file

@ -46,6 +46,8 @@ namespace detail
template <typename T> template <typename T>
constexpr auto equalityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>> = true; constexpr auto equalityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>> = true;
template <typename> struct Tag {};
} // namespace detail } // namespace detail
/** @endcond */ /** @endcond */

View file

@ -39,8 +39,6 @@ namespace juce
namespace detail namespace detail
{ {
template <typename> struct Tag {};
inline auto getNumericValue (StringRef s, Tag<int>) { return s.text.getIntValue32(); } inline auto getNumericValue (StringRef s, Tag<int>) { return s.text.getIntValue32(); }
inline auto getNumericValue (StringRef s, Tag<double>) { return s.text.getDoubleValue(); } inline auto getNumericValue (StringRef s, Tag<double>) { return s.text.getDoubleValue(); }
inline auto getNumericValue (StringRef s, Tag<float>) { return static_cast<float> (s.text.getDoubleValue()); } inline auto getNumericValue (StringRef s, Tag<float>) { return static_cast<float> (s.text.getDoubleValue()); }