From 4805b86ca47ee5f2fc43304c3bc0f9572eb80d11 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 4 May 2022 18:58:05 +0100 Subject: [PATCH] LV2 Client: Update Atom parsing to use Optional --- .../LV2/juce_LV2_Client.cpp | 32 ++++---- .../format_types/juce_LV2Common.h | 77 ++++++++++--------- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/modules/juce_audio_plugin_client/LV2/juce_LV2_Client.cpp b/modules/juce_audio_plugin_client/LV2/juce_LV2_Client.cpp index 8ad8b9580f..cfa8f36337 100644 --- a/modules/juce_audio_plugin_client/LV2/juce_LV2_Client.cpp +++ b/modules/juce_audio_plugin_client/LV2/juce_LV2_Client.cpp @@ -297,12 +297,12 @@ public: // Carla always seems to give us an integral 'beat' even though I'd expect // it to be a floating-point value - if ( parser.parseNumericAtom (atomBeatsPerMinute).andThen ([&] (float value) { info.bpm = value; }) - && parser.parseNumericAtom (atomBeatsPerBar) .andThen ([&] (float value) { info.timeSigNumerator = (int) value; }) - && parser.parseNumericAtom (atomBeatUnit) .andThen ([&] (int32_t value) { info.timeSigDenominator = value; }) - && parser.parseNumericAtom (atomBeat) .andThen ([&] (double value) { info.ppqPosition = value; }) - && parser.parseNumericAtom (atomSpeed) .andThen ([&] (float value) { info.isPlaying = value != 0.0f; }) - && parser.parseNumericAtom (atomFrame) .andThen (setTimeInFrames)) + if ( lv2_shared::withValue (parser.parseNumericAtom (atomBeatsPerMinute), [&] (float value) { info.bpm = value; }) + && lv2_shared::withValue (parser.parseNumericAtom (atomBeatsPerBar), [&] (float value) { info.timeSigNumerator = (int) value; }) + && lv2_shared::withValue (parser.parseNumericAtom (atomBeatUnit), [&] (int32_t value) { info.timeSigDenominator = value; }) + && lv2_shared::withValue (parser.parseNumericAtom (atomBeat), [&] (double value) { info.ppqPosition = value; }) + && lv2_shared::withValue (parser.parseNumericAtom (atomSpeed), [&] (float value) { info.isPlaying = value != 0.0f; }) + && lv2_shared::withValue (parser.parseNumericAtom (atomFrame), setTimeInFrames)) { valid = true; } @@ -1371,14 +1371,14 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor (uint32_t index) const auto blockLengthUrid = mapFeature->map (mapFeature->handle, LV2_BUF_SIZE__maxBlockLength); const auto blockSize = parser.parseNumericOption (findMatchingOption (options, blockLengthUrid)); - if (! blockSize.successful) + if (! blockSize.hasValue()) { // The host doesn't specify a maximum block size jassertfalse; return nullptr; } - return new LV2PluginInstance { sampleRate, blockSize.value, pathToBundle, *mapFeature }; + return new LV2PluginInstance { sampleRate, *blockSize, pathToBundle, *mapFeature }; }, [] (LV2_Handle instance, uint32_t port, void* data) { @@ -1434,8 +1434,7 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor (uint32_t index) return &descriptor; } -static lv2_shared::NumericAtomParser::ParseResult findScaleFactor (const LV2_URID_Map* symap, - const LV2_Options_Option* options) +static Optional findScaleFactor (const LV2_URID_Map* symap, const LV2_Options_Option* options) { if (options == nullptr || symap == nullptr) return {}; @@ -1459,7 +1458,7 @@ public: LV2UI_Widget parentIn, const LV2_URID_Map* symapIn, const LV2UI_Resize* resizeFeatureIn, - lv2_shared::NumericAtomParser::ParseResult scaleFactorIn) + Optional scaleFactorIn) : writeFunction (writeFunctionIn), controller (controllerIn), plugin (pluginIn), @@ -1544,11 +1543,11 @@ public: if (opt->context != LV2_OPTIONS_INSTANCE || opt->subject != 0 || opt->key != scaleFactorUrid) continue; - if (scaleFactor.successful) + if (scaleFactor.hasValue()) { opt->type = floatUrid; opt->size = sizeof (float); - opt->value = &scaleFactor.value; + opt->value = &(*scaleFactor); } } @@ -1571,8 +1570,7 @@ public: continue; } - scaleFactor.successful = true; - scaleFactor.value = *static_cast (opt->value); + scaleFactor = *static_cast (opt->value); updateScale(); } @@ -1596,7 +1594,7 @@ private: float getScaleFactor() const noexcept { - return scaleFactor.successful ? scaleFactor.value : 1.0f; + return scaleFactor.hasValue() ? *scaleFactor : 1.0f; } void componentMovedOrResized (Component&, bool, bool wasResized) override @@ -1637,7 +1635,7 @@ private: LV2UI_Widget parent; const LV2_URID_Map* symap = nullptr; const LV2UI_Resize* resizeFeature = nullptr; - lv2_shared::NumericAtomParser::ParseResult scaleFactor; + Optional scaleFactor; std::unique_ptr editor; bool hostRequestedResize = false; diff --git a/modules/juce_audio_processors/format_types/juce_LV2Common.h b/modules/juce_audio_processors/format_types/juce_LV2Common.h index dfedac93ee..a133a171d8 100644 --- a/modules/juce_audio_processors/format_types/juce_LV2Common.h +++ b/modules/juce_audio_processors/format_types/juce_LV2Common.h @@ -19,6 +19,7 @@ #pragma once #include "juce_lv2_config.h" +#include "juce_core/containers/juce_Optional.h" #ifdef Bool #undef Bool // previously defined in X11/Xlib.h @@ -127,61 +128,61 @@ struct ObjectTraits { static constexpr auto construct = lv2_atom_forge_object; using SequenceFrame = ScopedFrame; using ObjectFrame = ScopedFrame; +template +bool withValue (const Optional& opt, Callback&& callback) +{ + if (! opt.hasValue()) + return false; + + callback (*opt); + return true; +} + struct NumericAtomParser { explicit NumericAtomParser (LV2_URID_Map mapFeatureIn) : mapFeature (mapFeatureIn) {} - template - struct ParseResult - { - ParseResult (Type type) : value (type), successful (true) {} - ParseResult() : value(), successful (false) {} + template struct Tag { LV2_URID urid; }; - template - ParseResult andThen (Fn&& fn) const - { - if (successful) - fn (value); - - return *this; - } + template + static Optional tryParse (const LV2_Atom&, const void*) + { + return {}; + } - operator bool() const noexcept { return successful; } + template + static Optional tryParse (const LV2_Atom& atom, const void* data, Tag head, Tag... tail) + { + if (atom.type == head.urid && atom.size == sizeof (Head)) + return static_cast (*reinterpret_cast (data)); - Type value; - bool successful; - }; + return tryParse (atom, data, tail...); + } template - ParseResult parseNumericAtom (const LV2_Atom* atom, const void* data) const + Optional parseNumericAtom (const LV2_Atom* atom, const void* data) const { if (atom == nullptr) return {}; - if (atom->type == mLV2_ATOM__Int && atom->size == sizeof (int32_t)) - return { static_cast (*static_cast (data)) }; - - if (atom->type == mLV2_ATOM__Long && atom->size == sizeof (int64_t)) - return { static_cast (*static_cast (data)) }; - - if (atom->type == mLV2_ATOM__Float && atom->size == sizeof (float)) - return { static_cast (*static_cast (data)) }; - - if (atom->type == mLV2_ATOM__Double && atom->size == sizeof (double)) - return { static_cast (*static_cast (data)) }; - - return {}; + return tryParse (*atom, + data, + Tag { mLV2_ATOM__Bool }, + Tag { mLV2_ATOM__Int }, + Tag { mLV2_ATOM__Long }, + Tag { mLV2_ATOM__Float }, + Tag { mLV2_ATOM__Double }); } template - ParseResult parseNumericAtom (const LV2_Atom* atom) const + Optional parseNumericAtom (const LV2_Atom* atom) const { return parseNumericAtom (atom, atom + 1); } template - ParseResult parseNumericOption (const LV2_Options_Option* option) const + Optional parseNumericOption (const LV2_Options_Option* option) const { if (option != nullptr) { @@ -240,8 +241,10 @@ struct PatchSetHelper lv2_atom_object_query (object, query); - if (isPlugin (subject)) - setPluginProperty (property, value, std::forward (callback)); + if (! isPlugin (subject)) + return; + + setPluginProperty (property, value, std::forward (callback)); } template @@ -270,14 +273,14 @@ struct PatchSetHelper const auto parseResult = parser.parseNumericAtom (value); - if (! parseResult.successful) + if (! parseResult.hasValue()) { // Didn't understand the type of this atom. jassertfalse; return; } - callback.setParameter (reinterpret_cast (property)->body, parseResult.value); + callback.setParameter (reinterpret_cast (property)->body, *parseResult); } NumericAtomParser parser;