From b591854fd4f23279898579136f64703195df1927 Mon Sep 17 00:00:00 2001 From: falkTX Date: Tue, 12 Feb 2013 22:48:23 +0000 Subject: [PATCH] Add missing file --- source/utils/carla_state_utils.hpp | 430 +++++++++++++++++++++++++++++ 1 file changed, 430 insertions(+) create mode 100644 source/utils/carla_state_utils.hpp diff --git a/source/utils/carla_state_utils.hpp b/source/utils/carla_state_utils.hpp new file mode 100644 index 000000000..67389bc46 --- /dev/null +++ b/source/utils/carla_state_utils.hpp @@ -0,0 +1,430 @@ +/* + * Carla Backend utils + * Copyright (C) 2011-2013 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the GPL.txt file + */ + +#ifndef __CARLA_STATE_UTILS_HPP__ +#define __CARLA_STATE_UTILS_HPP__ + +#include "carla_backend.hpp" +#include "carla_utils.hpp" + +#include + +CARLA_BACKEND_START_NAMESPACE + +// ------------------------------------------------- +// Carla GUI stuff + +struct StateParameter { + uint32_t index; + const char* name; + const char* symbol; + double value; + uint8_t midiChannel; + int16_t midiCC; + + StateParameter() + : index(0), + name(nullptr), + symbol(nullptr), + value(0.0), + midiChannel(1), + midiCC(-1) {} + + ~StateParameter() + { + std::free((void*)name); + std::free((void*)symbol); + } +}; + +struct StateCustomData { + const char* type; + const char* key; + const char* value; + + StateCustomData() + : type(nullptr), + key(nullptr), + value(nullptr) {} + + ~StateCustomData() + { + std::free((void*)type); + std::free((void*)key); + std::free((void*)value); + } +}; + +typedef std::vector StateParameterVector; +typedef std::vector StateCustomDataVector; + +struct SaveState { + const char* type; + const char* name; + const char* label; + const char* binary; + long uniqueID; + + bool active; + double dryWet; + double volume; + double balanceLeft; + double balanceRight; + double panning; + + int32_t currentProgramIndex; + const char* currentProgramName; + int32_t currentMidiBank; + int32_t currentMidiProgram; + const char* chunk; + + StateParameterVector parameters; + StateCustomDataVector customData; + + SaveState() + : type(nullptr), + name(nullptr), + label(nullptr), + binary(nullptr), + uniqueID(0), + active(false), + dryWet(1.0), + volume(1.0), + balanceLeft(-1.0), + balanceRight(1.0), + panning(0.0), + currentProgramIndex(-1), + currentProgramName(nullptr), + currentMidiBank(-1), + currentMidiProgram(-1), + chunk(nullptr) {} + + ~SaveState() + { + reset(); + } + + void reset() + { + if (type != nullptr) + { + std::free((void*)type); + type = nullptr; + } + + if (name != nullptr) + { + std::free((void*)name); + name = nullptr; + } + + if (label != nullptr) + { + std::free((void*)label); + label = nullptr; + } + + if (binary != nullptr) + { + std::free((void*)binary); + binary = nullptr; + } + + if (currentProgramName != nullptr) + { + std::free((void*)currentProgramName); + currentProgramName = nullptr; + } + + if (chunk != nullptr) + { + std::free((void*)chunk); + chunk = nullptr; + } + + uniqueID = 0; + active = false; + dryWet = 1.0; + volume = 1.0; + balanceLeft = -1.0; + balanceRight = 1.0; + panning = 0.0; + currentProgramIndex = -1; + currentMidiBank = -1; + currentMidiProgram = -1; + + parameters.clear(); + customData.clear(); + } +}; + +// ------------------------------------------------- +// Carla XML helpers (xml to state) + +static inline +QString xmlSafeString(const QString& string, const bool toXml) +{ + QString newString(string); + + if (toXml) + return newString.replace("&", "&").replace("<","<").replace(">",">").replace("'","'").replace("\"","""); + else + return newString.replace("&", "&").replace("<","<").replace(">",">").replace("'","'").replace(""","\""); +} + +static inline +const char* xmlSafeStringChar(const QString& string, const bool toXml) +{ + return strdup(xmlSafeString(string, toXml).toUtf8().constData()); +} + +static inline +const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode) +{ + static SaveState saveState; + saveState.reset(); + + QDomNode node(xmlNode.firstChild()); + + while (! node.isNull()) + { + // ------------------------------------------------------ + // Info + + if (node.toElement().tagName() == "Info") + { + QDomNode xmlInfo(node.toElement().firstChild()); + + while (! xmlInfo.isNull()) + { + const QString tag = xmlInfo.toElement().tagName(); + const QString text = xmlInfo.toElement().text(); //.strip(); + + if (tag == "Type") + saveState.type = xmlSafeStringChar(text, false); + else if (tag == "Name") + saveState.name = xmlSafeStringChar(text, false); + else if (tag == "Label" || tag == "URI") + saveState.label = xmlSafeStringChar(text, false); + else if (tag == "Binary") + saveState.binary = xmlSafeStringChar(text, false); + else if (tag == "UniqueID") + { + bool ok; + long uniqueID = text.toLong(&ok); + if (ok) saveState.uniqueID = uniqueID; + } + + xmlInfo = xmlInfo.nextSibling(); + } + } + + // ------------------------------------------------------ + // Data + + else if (node.toElement().tagName() == "Data") + { + QDomNode xmlData(node.toElement().firstChild()); + + while (! xmlData.isNull()) + { + const QString tag = xmlData.toElement().tagName(); + const QString text = xmlData.toElement().text(); //.strip(); + + // ---------------------------------------------- + // Internal Data + + if (tag == "Active") + { + saveState.active = bool(text == "Yes"); + } + else if (tag == "DryWet") + { + bool ok; + double value = text.toDouble(&ok); + if (ok) saveState.dryWet = value; + } + else if (tag == "Volume") + { + bool ok; + double value = text.toDouble(&ok); + if (ok) saveState.volume = value; + } + else if (tag == "Balance-Left") + { + bool ok; + double value = text.toDouble(&ok); + if (ok) saveState.balanceLeft = value; + } + else if (tag == "Balance-Right") + { + bool ok; + double value = text.toDouble(&ok); + if (ok) saveState.balanceRight = value; + } + + // ---------------------------------------------- + // Program (current) + + else if (tag == "CurrentProgramIndex") + { + bool ok; + int value = text.toInt(&ok); + if (ok) saveState.currentProgramIndex = value; + } + else if (tag == "CurrentProgramName") + { + saveState.currentProgramName = xmlSafeStringChar(text, false); + } + + // ---------------------------------------------- + // Midi Program (current) + + else if (tag == "CurrentMidiBank") + { + bool ok; + int value = text.toInt(&ok); + if (ok) saveState.currentMidiBank = value; + } + else if (tag == "CurrentMidiProgram") + { + bool ok; + int value = text.toInt(&ok); + if (ok) saveState.currentMidiProgram = value; + } + + // ---------------------------------------------- + // Parameters + + else if (tag == "Parameter") + { + StateParameter stateParameter; + + QDomNode xmlSubData(xmlData.toElement().firstChild()); + + while (! xmlSubData.isNull()) + { + const QString pTag = xmlSubData.toElement().tagName(); + const QString pText = xmlSubData.toElement().text(); //.strip(); + + if (pTag == "index") + { + bool ok; + uint index = pText.toUInt(&ok); + if (ok) stateParameter.index = index; + } + else if (pTag == "name") + { + stateParameter.name = xmlSafeStringChar(pText, false); + } + else if (pTag == "symbol") + { + stateParameter.symbol = xmlSafeStringChar(pText, false); + } + else if (pTag == "value") + { + bool ok; + double value = pText.toDouble(&ok); + if (ok) stateParameter.value = value; + } + else if (pTag == "midiChannel") + { + bool ok; + uint channel = pText.toUInt(&ok); + if (ok && channel < 16) + stateParameter.midiChannel = static_cast(channel); + } + else if (pTag == "midiCC") + { + bool ok; + int cc = pText.toInt(&ok); + if (ok && cc < INT16_MAX) + stateParameter.midiCC = static_cast(cc); + } + + xmlSubData = xmlSubData.nextSibling(); + } + + saveState.parameters.push_back(stateParameter); + } + + // ---------------------------------------------- + // Custom Data + + else if (tag == "CustomData") + { + StateCustomData stateCustomData; + + QDomNode xmlSubData(xmlData.toElement().firstChild()); + + while (! xmlSubData.isNull()) + { + const QString cTag = xmlSubData.toElement().tagName(); + const QString cText = xmlSubData.toElement().text(); //.strip(); + + if (cTag == "type") + stateCustomData.type = xmlSafeStringChar(cText, false); + else if (cTag == "key") + stateCustomData.key = xmlSafeStringChar(cText, false); + else if (cTag == "value") + stateCustomData.value = xmlSafeStringChar(cText, false); + + xmlSubData = xmlSubData.nextSibling(); + } + + saveState.customData.push_back(stateCustomData); + } + + // ---------------------------------------------- + // Chunk + + else if (tag == "Chunk") + { + saveState.chunk = xmlSafeStringChar(text, false); + } + + // ---------------------------------------------- + + xmlData = xmlData.nextSibling(); + } + } + + // ------------------------------------------------------ + + node = node.nextSibling(); + } + + return saveState; +} + +static inline +QString getXMLFromSaveState(const SaveState& saveState) +{ + return ""; + + // TODO + Q_UNUSED(saveState); +} + +// ------------------------------------------------- +// Carla XML helpers (state to xml) + +// ------------------------------------------------- + +CARLA_BACKEND_END_NAMESPACE + +#endif // __CARLA_STATE_UTILS_HPP__