diff --git a/modules/common/chowdsp_serialization/Serialization/chowdsp_BaseSerializer.h b/modules/common/chowdsp_serialization/Serialization/chowdsp_BaseSerializer.h index cf5ec98e6..7e77629e9 100644 --- a/modules/common/chowdsp_serialization/Serialization/chowdsp_BaseSerializer.h +++ b/modules/common/chowdsp_serialization/Serialization/chowdsp_BaseSerializer.h @@ -15,12 +15,25 @@ namespace serialization_detail using DeserializedType = const json&; static auto createBaseElement() { return SerializedType {}; } + static auto createBaseElement(juce::String id) { return SerializedType {}; } static void addChildElement (SerializedType&, SerializedType&&) {} //NOSONAR static auto getChildElement (DeserializedType, int) { return false; } + static auto getChildElement (DeserializedType, juce::String) { return false; } + static int getNumChildElements (DeserializedType) { return 0; } + static int getNumAttributes (DeserializedType) { return 0; } + static juce::String getAttributeName (DeserializedType, int i) { return ""; } - template - static SerializedType serialize (const C&) + static auto getAttribute (DeserializedType, juce::String id) { return false; } + + template + static SerializedType serialize (const C&, SerializedType t, juce::String id) + { + return {}; + } + + template + static SerializedType serialize (const C&, SerializedType t) { return {}; } @@ -35,6 +48,11 @@ namespace serialization_detail static void deserialize (DeserializedType, C&) { } + + template + static void deserialize (juce::String, C&) + { + } }; // The reason we need this "detail" namespace is so that we can define these static method @@ -85,97 +103,157 @@ class BaseSerializer return serial; } - /** Serializer for serial type */ - template - static std::enable_if_t>, SerialType> - serialize (T x) - { - return x; - } - /** Deserializer for serial types */ - template - static std::enable_if_t>, void> - deserialize (DeserialType serial, T& x) - { - x = serial; - } +// /** Serializer for arithmetic types */ +// template +// static std::enable_if_t, SerialType> +// serialize (T x) +// { +// return Serializer::serializeArithmeticType (x); +// } +// /** Deserializer for arithmetic types */ +// template +// static std::enable_if_t, void> +// deserialize (DeserialType serial, T& x) +// { +// x = Serializer::template deserializeArithmeticType (serial); +// } + + /** Serializes an arithmetic type. */ - /** Serializer for arithmetic types */ template static std::enable_if_t, SerialType> - serialize (T x) + serialize(SerialType& parent, juce::String id, T x) { - return Serializer::serializeArithmeticType (x); + return Serializer::serializeArithmeticType(parent, id, x); } - /** Deserializer for arithmetic types */ + /** Deserializes an arithmetic type. */ template - static std::enable_if_t, void> - deserialize (DeserialType serial, T& x) + static std::enable_if_t, T> + deserialize(DeserialType serial, juce::String id,T& x) { - x = Serializer::template deserializeArithmeticType (serial); + x = Serializer::template deserializeArithmeticType(serial, id); } - /** Serializer for enum types */ - template - static std::enable_if_t, SerialType> - serialize (T x) - { - return Serializer::serializeEnumType (x); - } - /** Deserializer for enum types */ + + + + + /** Serializes an enum type. */ template - static std::enable_if_t, void> - deserialize (DeserialType serial, T& x) + static SerialType serializeEnumType(SerialType& parent, juce::String id, T x) { - x = Serializer::template deserializeEnumType (serial); + return Serializer::serializeEnumType(parent, id, x); } - /** Serializer for string types */ + /** Deserializes an enum type. */ template - static std::enable_if_t, SerialType> - serialize (const T& x) + static T deserializeEnumType(DeserialType serial, juce::String id, T& x) { - return Serializer::serializeString (x); + x = Serializer::template deserializeEnumType(serial, id); } - /** Deserializer for string types */ +// /** Serializer for enum types */ +// template +// static std::enable_if_t, SerialType> +// serialize (T x) +// { +// return Serializer::serializeEnumType (x); +// } +// +// /** Deserializer for enum types */ +// template +// static std::enable_if_t, void> +// deserialize (DeserialType serial, T& x) { +// x = Serializer::template deserializeEnumType (serial); +// } + +// /** Serializer for string types */ +// template +// static std::enable_if_t, SerialType> +// serialize (const T& x) +// { +// return Serializer::serializeString (x); +// } +// +// /** Deserializer for string types */ +// template +// static std::enable_if_t, void> +// deserialize (DeserialType serial, T& x) +// { +// x = Serializer::template deserializeString (serial); +// } + /** Serializes a string. */ template - static std::enable_if_t, void> - deserialize (DeserialType serial, T& x) + static std::enable_if_t || std::is_same_v, SerialType> + serializeString(SerialType& parent, juce::String id, const T& x) { - x = Serializer::template deserializeString (serial); + return Serializer::serializeString(parent, id, x); } -#if JUCE_MODULE_AVAILABLE_juce_graphics - /** Serializer for juce::Point types */ + /** Deserializes a string. */ template - static std::enable_if_t, SerialType> - serialize (const T& point) + static std::enable_if_t || std::is_same_v, T> + deserializeString(DeserialType serial, juce::String id, T& x) { - auto serial = Serializer::createBaseElement(); - Serializer::addChildElement (serial, serialize (point.x)); - Serializer::addChildElement (serial, serialize (point.y)); - return serial; + x = Serializer::template deserializeString(serial, id); } - /** Deserializer for juce::Point types */ - template - static std::enable_if_t, void> - deserialize (DeserialType serial, T& point) - { - if (Serializer::getNumChildElements (serial) != 2) +#if JUCE_MODULE_AVAILABLE_juce_graphics +// /** Serializer for juce::Point types */ +// template +// static std::enable_if_t, SerialType> +// serialize (const T& point) +// { +// auto serial = Serializer::createBaseElement(); +// Serializer::addChildElement (serial, serialize (point.x)); +// Serializer::addChildElement (serial, serialize (point.y)); +// return serial; +// } + +// /** Deserializer for juce::Point types */ +// template +// static std::enable_if_t, void> +// deserialize (DeserialType serial, T& point) +// { +// if (Serializer::getNumChildElements (serial) != 2) +// { +// jassertfalse; // the serialized data does not contain the correct number of elements to fill this array! +// point = {}; +// return; +// } +// +// deserialize (Serializer::getChildElement (serial, 0), point.x); +// deserialize (Serializer::getChildElement (serial, 1), point.y); +// } + + /** Serializer for juce::Point types */ + template + static std::enable_if_t, SerialType> + serialize (const T& point, SerialType &parent) { - jassertfalse; // the serialized data does not contain the correct number of elements to fill this array! - point = {}; - return; + + Serializer::addChildElement (parent, "x", (point.x) ); + Serializer::addChildElement (parent, "y" (point.y)); + return parent; + } + + /** Deserializer for juce::Point types */ + template + static std::enable_if_t, void> + deserialize (DeserialType serial, T& point) { + if (Serializer::getNumChildElements(serial) != 2) { + jassertfalse; // the serialized data does not contain the correct number of elements to fill this array! + point = {}; + return; + } + point.x = Serializer::template deserializeArithmeticType(serial, "point_x"); + point.y = Serializer::template deserializeArithmeticType(serial, "point_y"); + } - deserialize (Serializer::getChildElement (serial, 0), point.x); - deserialize (Serializer::getChildElement (serial, 1), point.y); - } #endif /** Serializer for container types */ @@ -285,6 +363,13 @@ class BaseSerializer return T::template serialize (object); } + +/** Serializer for types with custom serialization behaviour */ + template + static std::enable_if_t, SerialType> serialize (const T& object, SerialType& parent) + { + return T::template serialize (object, parent); + } /** Deserializer for types with custom deserialization behaviour */ template static std::enable_if_t, void> deserialize (DeserialType serial, T& object) diff --git a/modules/common/chowdsp_serialization/Serialization/chowdsp_Serialization.h b/modules/common/chowdsp_serialization/Serialization/chowdsp_Serialization.h index d3490a8df..d0e2764d8 100644 --- a/modules/common/chowdsp_serialization/Serialization/chowdsp_Serialization.h +++ b/modules/common/chowdsp_serialization/Serialization/chowdsp_Serialization.h @@ -15,6 +15,15 @@ namespace Serialization return Serializer::template serialize (objectToSerialize); } + template + typename Serializer::SerializedType serialize (const TypeToSerialize& objectToSerialize,typename Serializer::SerializedType& serial) + { + static_assert (std::is_base_of_v || std::is_same_v, + "Serializer type must be derived from BaseSerializer"); + + return Serializer::template serialize (objectToSerialize, serial); + } + /** Serialize an object to a file with a given serializer */ template void serialize (const TypeToSerialize& objectToSerialize, const juce::File& targetFile) @@ -40,6 +49,26 @@ namespace Serialization Serializer::template deserialize (deserial, objectToDeserialize); } + /** Deserialize an object with a given serializer */ + template + void deserialize (const typename Serializer::SerializedType& serial, juce::String id, TypeToDeserialize& objectToDeserialize) + { + static_assert (std::is_base_of_v || std::is_same_v, + "Serializer type must be derived from BaseSerializer"); + + const auto deserial = Serializer::template getDeserial (serial); + Serializer::template deserialize (deserial, id, objectToDeserialize); + } + + template + void deserialize (const typename Serializer::DeserializedType& serial, juce::String id, TypeToDeserialize& objectToDeserialize) + { + static_assert (std::is_base_of_v || std::is_same_v, + "Serializer type must be derived from BaseSerializer"); + + //const auto deserial = Serializer::template getDeserial (serial); + Serializer::template deserialize (serial, id, objectToDeserialize); + } /** Deserialize an object from a file with a given serializer */ template void deserialize (const juce::File& file, TypeToDeserialize& objectToDeserialize) @@ -60,5 +89,11 @@ namespace Serialization { deserialize (Serializer::fromBinaryData (data, dataSize), objectToDeserialize); } + /** Deserialize an object from a file with a given serializer */ + template + void deserialize (const juce::XmlElement* xml, TypeToDeserialize& objectToDeserialize) + { + deserialize (Serializer::fromXML (xml), objectToDeserialize); + } } // namespace Serialization } // namespace chowdsp diff --git a/modules/common/chowdsp_serialization/Serialization/chowdsp_XMLSerializer.h b/modules/common/chowdsp_serialization/Serialization/chowdsp_XMLSerializer.h index f5d6a3254..a603d1fd1 100644 --- a/modules/common/chowdsp_serialization/Serialization/chowdsp_XMLSerializer.h +++ b/modules/common/chowdsp_serialization/Serialization/chowdsp_XMLSerializer.h @@ -28,6 +28,8 @@ class XMLSerializer : public BaseSerializer static void toMemoryBlock (const SerializedType& serial, juce::MemoryBlock& block) // NOSONAR { auto&& outStream = juce::MemoryOutputStream (block, false); + // magic number to identify memory blocks that we've stored as XML + const juce::uint32 magicXmlNumber = 0x21324356; serial->writeTo (outStream); } @@ -38,6 +40,11 @@ class XMLSerializer : public BaseSerializer return serial; } + static SerializedType fromXML(const juce::XmlElement* xmlElement) + { + return std::unique_ptr(const_cast(xmlElement)); + } + static SerializedType fromMemoryBlock (const juce::MemoryBlock& block) { auto serial = juce::parseXML (block.toString()); @@ -52,16 +59,34 @@ class XMLSerializer : public BaseSerializer return serial; } - static auto createBaseElement() + static auto createBaseElement(juce::String id) { - return std::make_unique (defaultID); + return std::make_unique (id); } static void addChildElement (SerializedType& parent, SerializedType&& newChild) // NOSONAR { parent->addChildElement (newChild.release()); } + static void addChildElement (SerializedType& parent, juce::String newChild) // NOSONAR + { + parent->addChildElement (new juce::XmlElement(newChild)); + } + static void addChildElement (SerializedType& parent, juce::String element, float f) // NOSONAR + { + parent->setAttribute (element, juce::String(f,3)); + } + static void addChildElement (SerializedType& parent, juce::String element,juce::Point point) // NOSONAR + { + parent->setAttribute ("point_x",juce::String(point.getX())); + parent->setAttribute ("point_y",juce::String(point.getY())); + + } + static void addChildElement (SerializedType& parent, juce::String element, juce::String f) // NOSONAR + { + parent->setAttribute (element, f); + } static juce::XmlElement* getChildElement (DeserializedType parent, int index) { if (parent == nullptr || ! juce::isPositiveAndBelow (index, parent->getNumChildElements())) @@ -72,6 +97,16 @@ class XMLSerializer : public BaseSerializer return parent->getChildElement (index); } + static juce::XmlElement* getChildElement (DeserializedType parent, juce::String attr ) + { +// if (parent == nullptr || ! juce::isPositiveAndBelow (index, parent->getNumChildElements())) +// { +// jassertfalse; +// return {}; +// } + + return parent->getChildByName(attr); + } static int getNumChildElements (DeserializedType serial) { @@ -84,80 +119,112 @@ class XMLSerializer : public BaseSerializer return serial->getNumChildElements(); } + static int getNumAttributes (DeserializedType serial) + { + if (serial == nullptr) + { + jassertfalse; + return 0; + } + + return serial->getNumAttributes(); + } + static juce::String getAttributeName (DeserializedType serial, int i) + { + if (serial == nullptr) + { + jassertfalse; + return ""; + } + + return serial->getAttributeName(i); + } + + static juce::String getAttribute (DeserializedType serial, int i) + { + if (serial == nullptr) + { + jassertfalse; + return ""; + } + + return serial->getAttributeName(i); + } + + + template - static std::enable_if_t, SerializedType> serializeArithmeticType (T x) + static std::enable_if_t, SerializedType> serializeArithmeticType (SerializedType& parent, juce::String id, T x) { - auto element = createBaseElement(); - element->setAttribute (defaultID, (int) x); - return element; + + parent->setAttribute (id, (int) x); + return parent; } template - static std::enable_if_t, SerializedType> serializeArithmeticType (T x) + static std::enable_if_t, SerializedType> serializeArithmeticType (SerializedType& parent, juce::String id, T x) { - auto element = createBaseElement(); - element->setAttribute (defaultID, (double) x); - return element; + parent->setAttribute (id, (double) x); + return parent; } template static std::enable_if_t, T> - deserializeArithmeticType (DeserializedType serial) + deserializeArithmeticType (DeserializedType serial, juce::String id) { if (serial == nullptr) return T {}; - return (T) serial->getIntAttribute (defaultID); + return (T) serial->getIntAttribute (id); } template static std::enable_if_t, T> - deserializeArithmeticType (DeserializedType serial) + deserializeArithmeticType (DeserializedType serial, juce::String id) { if (serial == nullptr) return T {}; - return (T) serial->getDoubleAttribute (defaultID); + return (T) serial->getDoubleAttribute (id); } template - static SerializedType serializeEnumType (T x) + static SerializedType serializeEnumType (SerializedType& parent, juce::String id, T x) { - return serializeArithmeticType (static_cast (x)); + return serializeArithmeticType (parent, id,static_cast ( x)); } template - static T deserializeEnumType (DeserializedType serial) + static T deserializeEnumType (DeserializedType serial, juce::String id) { - return static_cast (deserializeArithmeticType (serial)); + return static_cast (deserializeArithmeticType (serial, id)); } template - static SerializedType serializeString (const T& x) + static SerializedType serializeString (SerializedType& parent, juce::String id, const T& x) { - auto element = createBaseElement(); - element->setAttribute (defaultID, x); - return element; + parent->setAttribute (id, x); + return std::move(parent); } template static std::enable_if_t, T> - deserializeString (DeserializedType serial) + deserializeString (DeserializedType serial, juce::String id) { if (serial == nullptr) return T {}; - return deserializeString (serial).toStdString(); + return deserializeString (serial,id).toStdString(); } template static std::enable_if_t, T> - deserializeString (DeserializedType serial) + deserializeString (DeserializedType serial, juce::String id) { if (serial == nullptr) return T {}; - return serial->getStringAttribute (defaultID); + return serial->getStringAttribute (id); } private: diff --git a/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterConversions.cpp b/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterConversions.cpp index 69d5d5703..57607a1aa 100644 --- a/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterConversions.cpp +++ b/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterConversions.cpp @@ -81,5 +81,5 @@ juce::String floatValToString (float floatVal) return floatValToStringDecimal<2> (floatVal); } -float stringToFloatVal (const juce::String& s) { return s.getFloatValue(); } + float stringToFloatVal (const juce::String& s) { return s.getFloatValue(); } } // namespace chowdsp::ParamUtils diff --git a/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterConversions.h b/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterConversions.h index 86a422288..3bd3bbf30 100644 --- a/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterConversions.h +++ b/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterConversions.h @@ -27,4 +27,5 @@ juce::String floatValToStringDecimal (float floatVal) return { floatVal, NumDecimalPlaces, false }; } float stringToFloatVal (const juce::String& s); + } // namespace chowdsp::ParamUtils diff --git a/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterTypes.h b/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterTypes.h index 96afdcfc7..d6b79e92e 100644 --- a/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterTypes.h +++ b/modules/plugin/chowdsp_parameters/ParamUtils/chowdsp_ParameterTypes.h @@ -78,6 +78,11 @@ class FloatParameter : public juce::AudioParameterFloat, /** Returns the current parameter value accounting for any modulation that is currently applied. */ operator float() const noexcept { return getCurrentValue(); } // NOSONAR, NOLINT(google-explicit-constructor): we want to be able to do implicit conversion here + /** Print debug info. */ + void printDebug() const + { + DBG(paramID + " : " + juce::String(get())); + } private: const float unsnappedDefault; const juce::NormalisableRange normalisableRange; @@ -97,6 +102,10 @@ class ChoiceParameter : public juce::AudioParameterChoice, defaultChoiceIndex (defaultItemIndex) { } + void printDebug() const + { + DBG(paramID + " : " + juce::String(getIndex())); // Using getIndex() for ChoiceParameter + } using Ptr = OptionalPointer; @@ -147,6 +156,10 @@ class EnumChoiceParameter : public ChoiceParameter { return magic_enum::enum_value ((size_t) getIndex()); } + void printDebug() const + { + DBG(paramID + " : " + juce::String(static_cast(get()))); + } /** * Sets the parameter value. @@ -170,7 +183,10 @@ class BoolParameter : public juce::AudioParameterBool, : juce::AudioParameterBool (parameterID, parameterName, defaultBoolValue) { } - + void printDebug() const + { + DBG(paramID + " : " + juce::String(static_cast(get()))); + } using Ptr = OptionalPointer; /** @@ -300,6 +316,7 @@ class RatioParameter : public FloatParameter }; /** A float parameter which specifically stores a semitones value. */ + class SemitonesParameter : public FloatParameter { public: @@ -326,4 +343,5 @@ class SemitonesParameter : public FloatParameter private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SemitonesParameter) }; + } // namespace chowdsp diff --git a/modules/plugin/chowdsp_plugin_base/PluginBase/chowdsp_PluginBase.h b/modules/plugin/chowdsp_plugin_base/PluginBase/chowdsp_PluginBase.h index 62032e49a..def229e91 100644 --- a/modules/plugin/chowdsp_plugin_base/PluginBase/chowdsp_PluginBase.h +++ b/modules/plugin/chowdsp_plugin_base/PluginBase/chowdsp_PluginBase.h @@ -259,11 +259,19 @@ void PluginBase

::processBlock (juce::AudioBuffer& buffer, juce::MidiBu processAudioBlock (buffer); } - +// magic number to identify memory blocks that we've stored as XML + const juce::uint32 magicXmlNumber = 0x21324356; #if JUCE_MODULE_AVAILABLE_chowdsp_plugin_state template void PluginBase::getStateInformation (juce::MemoryBlock& data) { +// { +// juce::MemoryOutputStream out (data, false); +// out.writeInt (magicXmlNumber); +// out.writeInt (0); +// xml.writeTo (out, XmlElement::TextFormat().singleLine()); +// out.writeByte (0); +// } state.serialize (data); } diff --git a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_NonParamState.cpp b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_NonParamState.cpp index 1062ae2b0..c79902acc 100644 --- a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_NonParamState.cpp +++ b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_NonParamState.cpp @@ -34,7 +34,7 @@ inline void NonParamState::validateStateValues() const template typename Serializer::SerializedType NonParamState::serialize (const NonParamState& state) { - auto serial = Serializer::createBaseElement(); + auto serial = Serializer::createBaseElement("nonparam"); for (const auto& value : state.values) value->serialize (serial); return serial; @@ -43,20 +43,24 @@ typename Serializer::SerializedType NonParamState::serialize (const NonParamStat template void NonParamState::deserialize (typename Serializer::DeserializedType deserial, const NonParamState& state) { - std::vector namesThatHaveBeenDeserialized {}; - if (const auto numNamesAndVals = Serializer::getNumChildElements (deserial); numNamesAndVals % 2 == 0) + + juce::StringArray namesThatHaveBeenDeserialized {}; + if (const auto numNamesAndVals = Serializer::getNumAttributes (deserial)) { - namesThatHaveBeenDeserialized.reserve (static_cast (numNamesAndVals) / 2); - for (int i = 0; i < numNamesAndVals; i += 2) + for (int i = 0; i < numNamesAndVals; i++) { - const auto name = Serializer::getChildElement (deserial, i).template get(); - const auto& valueDeserial = Serializer::getChildElement (deserial, i + 1); + juce::String name {}; + name = Serializer::getAttributeName (deserial, i); +//Serialization::deserialize (Serializer::getChildElement (deserial, i), name); + for (auto& value : state.values) { - if (name == value->name) + if (name == toString(value->name)) { - value->deserialize (valueDeserial); - namesThatHaveBeenDeserialized.push_back (name); + + value->deserialize (deserial); + namesThatHaveBeenDeserialized.add (name); + } } } @@ -65,15 +69,15 @@ void NonParamState::deserialize (typename Serializer::DeserializedType deserial, { jassertfalse; // state loading error } - + for(auto id: namesThatHaveBeenDeserialized) { + DBG("nonparam " + id); + } // set all un-matched objects to their default values - if (! namesThatHaveBeenDeserialized.empty()) + for (auto& value : state.values) { - for (auto& value : state.values) - { - if (std::find (namesThatHaveBeenDeserialized.begin(), namesThatHaveBeenDeserialized.end(), value->name) == namesThatHaveBeenDeserialized.end()) - value->reset(); - } + if (! namesThatHaveBeenDeserialized.contains (toString (value->name))) + value->reset(); } } + } // namespace chowdsp diff --git a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParamHolder.cpp b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParamHolder.cpp index d06448c72..bec6b880d 100644 --- a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParamHolder.cpp +++ b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParamHolder.cpp @@ -178,7 +178,7 @@ size_t ParamHolder::doForAllParameters (Callable&& callable, size_t index) const template typename Serializer::SerializedType ParamHolder::serialize (const ParamHolder& paramHolder) { - auto serial = Serializer::createBaseElement(); + auto serial = Serializer::createBaseElement(paramHolder.name); paramHolder.doForAllParameters ( [&serial] (auto& param, size_t) { @@ -190,56 +190,52 @@ typename Serializer::SerializedType ParamHolder::serialize (const ParamHolder& p template void ParamHolder::deserialize (typename Serializer::DeserializedType deserial, ParamHolder& paramHolder) { - std::vector paramIDsThatHaveBeenDeserialized {}; - if (const auto numParamIDsAndVals = Serializer::getNumChildElements (deserial); numParamIDsAndVals % 2 == 0) + + juce::StringArray paramIDsThatHaveBeenDeserialized {}; + if (const auto numParamIDsAndVals = Serializer::getNumAttributes (deserial)) { - paramIDsThatHaveBeenDeserialized.reserve (static_cast (numParamIDsAndVals) / 2); - for (int i = 0; i < numParamIDsAndVals; i += 2) + for (int i = 0; i < numParamIDsAndVals; i += 1) { - const auto paramID = Serializer::getChildElement (deserial, i).template get(); - const auto& paramDeserial = Serializer::getChildElement (deserial, i + 1); + juce::String paramID {}; + paramID = Serializer::getAttributeName (deserial, i); +//DBG("PArAMID" + paramID); + //Serialization::deserialize (, paramID); +//const auto paramDeserial = Serializer::getAttribute (deserial,paramID); - auto paramPtrIter = paramHolder.allParamsMap.find (std::string { paramID }); - if (paramPtrIter == paramHolder.allParamsMap.end()) - continue; - paramIDsThatHaveBeenDeserialized.push_back (paramID); - [¶mDeserial] (const ParamPtrVariant& paramPtr) - { - const auto deserializeParam = [] (auto* param, auto& pd) + paramHolder.doForAllParameters ( + [&deserial, + ¶mID = std::as_const (paramID), + ¶mIDsThatHaveBeenDeserialized] (auto& param, size_t) { - ParameterTypeHelpers::deserializeParameter (pd, *param); - }; + if (param.paramID == paramID) + { + ParameterTypeHelpers::deserializeParameter (deserial, param); + paramIDsThatHaveBeenDeserialized.add (paramID); + } + }); - if (auto* floatParamPtr = std::get_if (¶mPtr)) - deserializeParam (*floatParamPtr, paramDeserial); - else if (auto* choiceParamPtr = std::get_if (¶mPtr)) - deserializeParam (*choiceParamPtr, paramDeserial); - else if (auto* boolParamPtr = std::get_if (¶mPtr)) - deserializeParam (*boolParamPtr, paramDeserial); - else - jassertfalse; // bad variant access? - }(paramPtrIter->second); } } else { - jassertfalse; // state loading error + // jassertfalse; // state loading error } - // set all un-matched objects to their default values - if (! paramIDsThatHaveBeenDeserialized.empty()) + for(auto id: paramIDsThatHaveBeenDeserialized) { + DBG("deserialzied " + id); + } + // set all un-matched objects to their default values +// if (! paramIDsThatHaveBeenDeserialized.empty()) +// { paramHolder.doForAllParameters ( [¶mIDsThatHaveBeenDeserialized] (auto& param, size_t) { - if (std::find (paramIDsThatHaveBeenDeserialized.begin(), - paramIDsThatHaveBeenDeserialized.end(), - std::string_view { param.paramID.toRawUTF8(), param.paramID.getNumBytesAsUTF8() }) - == paramIDsThatHaveBeenDeserialized.end()) + if (! paramIDsThatHaveBeenDeserialized.contains (param.paramID)) ParameterTypeHelpers::resetParameter (param); }); - } +// } } inline void ParamHolder::applyVersionStreaming (const Version& version) diff --git a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParamHolder.h b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParamHolder.h index 19839d8f2..8c19cabb2 100644 --- a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParamHolder.h +++ b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParamHolder.h @@ -18,7 +18,7 @@ class ParamHolder ParamHolder (ParamHolder&&) noexcept = default; ParamHolder& operator= (ParamHolder&&) noexcept = default; - + virtual ~ParamHolder() = default; /** Adds parameters to the ParamHolder. */ template std::enable_if_t, void> @@ -105,7 +105,10 @@ class ParamHolder /** Assign this function to apply version streaming to your non-parameter state. */ std::function versionStreamingCallback = nullptr; - + std::vector>* getFloatParams() + { + return &floatParams; + } private: void add() const { diff --git a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParameterTypeHelpers.h b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParameterTypeHelpers.h index 9c887485f..f936e845f 100644 --- a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParameterTypeHelpers.h +++ b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_ParameterTypeHelpers.h @@ -59,8 +59,8 @@ namespace ParameterTypeHelpers template void serializeParameter (typename Serializer::SerializedType& serial, const ParamType& param) { - Serializer::addChildElement (serial, param.paramID); - Serializer::addChildElement (serial, getValue (param)); + + Serializer::addChildElement (serial, param.paramID,getValue (param)); } template @@ -70,10 +70,35 @@ namespace ParameterTypeHelpers } template - void deserializeParameter (const typename Serializer::SerializedType& serial, ParamType& param) + std::enable_if_t, void> + deserializeParameter (const typename Serializer::SerializedType& serial, ParamType& param) + { + ParameterElementType val; + Serialization::deserialize (serial,param.paramID, val); + if constexpr (std::is_same_v,bool>) + { + DBG("paramid" + param.paramID + "val " + juce::String(static_cast(val))); + } else + { + DBG("paramid" + param.paramID + "val " + juce::String(val)); + } + + setValue (val, param); + } + template + std::enable_if_t, void> + deserializeParameter (const typename Serializer::DeserializedType& serial, ParamType& param) { ParameterElementType val; - Serialization::deserialize (serial, val); + Serialization::deserialize (serial,param.paramID, val); +// if constexpr (std::is_same_v,bool>) +// { +// DBG("paramid" + param.paramID + "val " + juce::String(static_cast(val))); +// } else +// { +// DBG("paramid" + param.paramID + "val " + juce::String(val)); +// } + setValue (val, param); } } // namespace ParameterTypeHelpers diff --git a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_PluginStateImpl.cpp b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_PluginStateImpl.cpp index acb2d4b09..71285db83 100644 --- a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_PluginStateImpl.cpp +++ b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_PluginStateImpl.cpp @@ -42,14 +42,14 @@ template typename Serializer::SerializedType PluginStateImpl::serialize (const PluginStateImpl& object) { - auto serial = Serializer::createBaseElement(); + auto serial = Serializer::createBaseElement("testing"); #if defined JucePlugin_VersionString - Serializer::addChildElement (serial, Serializer::template serialize (currentPluginVersion)); +// Serializer::template serialize (currentPluginVersion, serial); #endif Serializer::addChildElement (serial, Serializer::template serialize (object.nonParams)); - Serializer::addChildElement (serial, Serializer::template serialize (object.params)); + Serializer::addChildElement(serial, Serializer::template serialize (object.params)); return serial; } @@ -60,9 +60,9 @@ void PluginStateImpl::deserialize { enum { -#if defined JucePlugin_VersionString - versionChildIndex, -#endif +//#if defined JucePlugin_VersionString +// versionChildIndex, +//#endif nonParamStateChildIndex, paramStateChildIndex, expectedNumChildElements, @@ -74,15 +74,15 @@ void PluginStateImpl::deserialize return; } -#if defined JucePlugin_VersionString - Serializer::template deserialize (Serializer::getChildElement (serial, versionChildIndex), object.pluginStateVersion); -#else - using namespace version_literals; - object.pluginStateVersion = "0.0.0"_v; -#endif - - Serializer::template deserialize (Serializer::getChildElement (serial, nonParamStateChildIndex), object.nonParams); - Serializer::template deserialize (Serializer::getChildElement (serial, paramStateChildIndex), object.params); +//#if defined JucePlugin_VersionString +// Serializer::template deserialize (Serializer::getChildElement (serial, versionChildIndex), object.pluginStateVersion); +//#else +// using namespace version_literals; +// object.pluginStateVersion = "0.0.0"_v; +//#endif +// + Serializer::template deserialize (Serializer::getChildElement (serial, "nonparam"), object.nonParams); + Serializer::template deserialize (Serializer::getChildElement (serial, object.params.getName()), object.params); } template diff --git a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_PluginStateImpl.h b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_PluginStateImpl.h index 76b5ee5fc..5990f1b2c 100644 --- a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_PluginStateImpl.h +++ b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_PluginStateImpl.h @@ -9,7 +9,7 @@ namespace chowdsp * @tparam NonParameterState Struct containing all of the plugin's non-parameter state as StateValue objects. * @tparam Serializer A type that implements chowdsp::BaseSerializer (JSONSerializer by default) */ -template +template class PluginStateImpl : public PluginState { static_assert (std::is_base_of_v, "ParameterState must be a chowdsp::ParamHolder!"); diff --git a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_StateValue.h b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_StateValue.h index 3001625b2..995e5df99 100644 --- a/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_StateValue.h +++ b/modules/plugin/chowdsp_plugin_state/Backend/chowdsp_StateValue.h @@ -14,8 +14,12 @@ struct StateValueBase virtual void serialize (JSONSerializer::SerializedType&) const {} virtual void deserialize (JSONSerializer::DeserializedType) {} - const std::string_view name {}; - Broadcaster changeBroadcaster {}; + + virtual void serialize (XMLSerializer::SerializedType&) const {} + virtual void deserialize (XMLSerializer::DeserializedType) {} + const std::string_view name; + Broadcaster changeBroadcaster; + }; #endif @@ -69,36 +73,68 @@ struct StateValue : StateValueBase /** Resets the value to its default state */ void reset() override { set (defaultValue); } - /** JSON Serializer */ - void serialize (JSONSerializer::SerializedType& serial) const override + + + /** XML Serializer */ + void serialize (XMLSerializer::SerializedType& serial) const override { - serialize (serial, *this); + serialize (serial, *this); } - /** JSON Deserializer */ - void deserialize (JSONSerializer::DeserializedType deserial) override + /** XML Deserializer */ + void deserialize (XMLSerializer::DeserializedType deserial) override { - deserialize (deserial, *this); + + deserialize (deserial, *this); } +// /** JSON Serializer */ +// void serialize (JSONSerializer::SerializedType& serial) const override +// { +// serialize (serial, *this); +// } +// +// /** JSON Deserializer */ +// void deserialize (JSONSerializer::DeserializedType deserial) override +// { +// deserialize (deserial, *this); +// } const element_type defaultValue; private: + + template + static std::enable_if_t, void> + serialize (typename Serializer::SerializedType& serial,const StateValue& value) { + Serializer::addChildElement (serial, toString(value.name), value.get()); + + } + template + static std::enable_if_t, void> + serialize (typename Serializer::SerializedType& serial, const StateValue& value) + { + Serializer::addChildElement (serial, toString(value.name)); + Serializer::addChildElement (serial, Serialization::serialize (value.get())); + } + template - static void serialize (typename Serializer::SerializedType& serial, const StateValue& value) + static std::enable_if_t, void> + deserialize (typename Serializer::DeserializedType deserial, StateValue& value) { - Serializer::addChildElement (serial, value.name); - Serializer::addChildElement (serial, Serialization::serialize (value.get())); + T val {}; + Serialization::deserialize (deserial, val); + value.set (val); } template - static void deserialize (typename Serializer::DeserializedType deserial, StateValue& value) + static std::enable_if_t, void> + deserialize (typename Serializer::DeserializedType deserial, StateValue& value) { + element_type val {}; Serialization::deserialize (deserial, val); value.set (val); } - T currentValue; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StateValue) diff --git a/modules/plugin/chowdsp_version/Version/chowdsp_Version.cpp b/modules/plugin/chowdsp_version/Version/chowdsp_Version.cpp index bec3d8f07..362b461b4 100644 --- a/modules/plugin/chowdsp_version/Version/chowdsp_Version.cpp +++ b/modules/plugin/chowdsp_version/Version/chowdsp_Version.cpp @@ -24,7 +24,7 @@ Version::Version (const juce::String& versionStr) patch = tokens[2].getIntValue(); } -juce::String Version::getVersionString() const +const juce::String Version::getVersionString() const { return juce::String (major) + "." + juce::String (minor) + "." + juce::String (patch); } diff --git a/modules/plugin/chowdsp_version/Version/chowdsp_Version.h b/modules/plugin/chowdsp_version/Version/chowdsp_Version.h index f189e32e8..326be5e03 100644 --- a/modules/plugin/chowdsp_version/Version/chowdsp_Version.h +++ b/modules/plugin/chowdsp_version/Version/chowdsp_Version.h @@ -54,7 +54,7 @@ class Version constexpr Version& operator= (Version&&) noexcept = default; /** Returns the version as a string of the form MAJOR.MINOR.PATCH. */ - [[nodiscard]] juce::String getVersionString() const; + [[nodiscard]] const juce::String getVersionString() const; /** Returns an integer hint for this version value. */ [[nodiscard]] constexpr int getVersionHint() const { return major * 10000 + minor * 100 + patch; } @@ -70,9 +70,9 @@ class Version template static void deserialize (typename Serializer::DeserializedType serial, Version& object) { - juce::String versionString; - Serializer::template deserialize (serial, versionString); - object = Version { versionString }; +// juce::String versionString; +// Serializer::template deserialize (serial, versionString); +// object = Version { versionString }; } friend constexpr bool operator== (const Version& v1, const Version& v2) noexcept;