Browse Source

Save support implemented (loading projects not yet, only presets)

tags/1.9.4
falkTX 11 years ago
parent
commit
d7ec8f7122
10 changed files with 405 additions and 71 deletions
  1. +10
    -0
      source/backend/CarlaPlugin.hpp
  2. +2
    -2
      source/backend/CarlaStandalone.hpp
  3. +60
    -13
      source/backend/engine/CarlaEngine.cpp
  4. +62
    -12
      source/backend/plugin/CarlaPlugin.cpp
  5. +30
    -0
      source/backend/standalone/CarlaStandalone.cpp
  6. +1
    -1
      source/backend/standalone/Makefile
  7. +12
    -0
      source/carla_backend.py
  8. +3
    -3
      source/carla_shared.py
  9. +37
    -3
      source/utils/CarlaBackendUtils.hpp
  10. +188
    -37
      source/utils/CarlaStateUtils.hpp

+ 10
- 0
source/backend/CarlaPlugin.hpp View File

@@ -427,6 +427,16 @@ public:
*/
void loadSaveState(const SaveState& saveState);

/*!
* TODO
*/
bool saveStateToFile(const char* const filename);

/*!
* TODO
*/
bool loadStateFromFile(const char* const filename);

// -------------------------------------------------------------------
// Set data (internal stuff)



+ 2
- 2
source/backend/CarlaStandalone.hpp View File

@@ -178,8 +178,8 @@ CARLA_EXPORT bool carla_add_plugin(CarlaBinaryType btype, CarlaPluginType ptype,
CARLA_EXPORT bool carla_remove_plugin(unsigned int pluginId);
CARLA_EXPORT void carla_remove_all_plugins();

//CARLA_EXPORT bool carla_load_plugin_state(unsigned int pluginId, const char* filename);
//CARLA_EXPORT bool carla_save_plugin_state(unsigned int pluginId, const char* filename);
CARLA_EXPORT bool carla_load_plugin_state(unsigned int pluginId, const char* filename);
CARLA_EXPORT bool carla_save_plugin_state(unsigned int pluginId, const char* filename);

CARLA_EXPORT const CarlaPluginInfo* carla_get_plugin_info(unsigned int pluginId);
CARLA_EXPORT const CarlaPortCountInfo* carla_get_audio_port_count_info(unsigned int pluginId);


+ 60
- 13
source/backend/engine/CarlaEngine.cpp View File

@@ -17,6 +17,7 @@

#include "CarlaEngineInternal.hpp"
#include "CarlaBackendUtils.hpp"
#include "CarlaStateUtils.hpp"
#include "CarlaMIDI.h"

#include <QtCore/QFile>
@@ -966,29 +967,66 @@ void CarlaEngine::__bridgePluginRegister(const unsigned short id, CarlaPlugin* c

bool CarlaEngine::loadProject(const char* const filename)
{
carla_debug("CarlaEngine::loadProject(\"%s\")", filename);
CARLA_ASSERT(filename != nullptr);

//QFile file(filename);
QFile file(filename);

if (! file.open(QIODevice::ReadOnly | QIODevice::Text))
return false;

QDomDocument xml;
xml.setContent(file.readAll());
file.close();

QDomNode xmlNode(xml.documentElement());

if (xmlNode.toElement().tagName() != "CARLA-PROJECT")
{
carla_stderr2("Not a valid Carla project file");
return false;
}

std::vector<SaveState> saveStates;

{
QDomNode node(xmlNode.firstChild());

while (! node.isNull())
{
if (node.toElement().tagName() == "Plugin")
{
const SaveState& saveState = getSaveStateDictFromXML(node);
saveStates.push_back(saveState);
}

node = node.nextSibling();
}
}

//if (! file.open(QIODevice::WriteOnly | QIODevice::Text))
// return;
// TODO - add plugins as set in XML
// TODO - clear+free states

//getSaveStateDictFromXML
return true;
}

bool CarlaEngine::saveProject(const char* const filename)
{
carla_debug("CarlaEngine::saveProject(\"%s\")", filename);
CARLA_ASSERT(filename != nullptr);

#if 0
QFile file(filename);
file.open(QIODevice::WriteOnly | QIODevice::Text);

if (! file.open(QIODevice::WriteOnly | QIODevice::Text))
return false;

QTextStream out(&file);
out << "<?xml version='1.0' encoding='UTF-8'?>\n";
out << "<!DOCTYPE CARLA-PRESET>\n";
out << "<CARLA-PRESET VERSION='0.5.0'>\n";
out << "<!DOCTYPE CARLA-PROJECT>\n";
out << "<CARLA-PROJECT VERSION='1.0'>\n";

bool firstPlugin = true;
char strBuf[STR_MAX];

for (unsigned int i=0; i < kData->curPluginCount; i++)
{
@@ -996,16 +1034,25 @@ bool CarlaEngine::saveProject(const char* const filename)

if (plugin != nullptr && plugin->enabled())
{
const SaveState& saveState = plugin->getSaveState();
// TODO
if (! firstPlugin)
out << "\n";

plugin->getRealName(strBuf);

if (*strBuf != 0)
out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true));

out << " <Plugin>\n";
out << getXMLFromSaveState(plugin->getSaveState());
out << " </Plugin>\n";

firstPlugin = false;
}
}

out << "</CARLA-PRESET>\n";
out << "</CARLA-PROJECT>\n";

file.close();
#endif

return true;
}



+ 62
- 12
source/backend/plugin/CarlaPlugin.cpp View File

@@ -19,6 +19,9 @@
#include "CarlaLibUtils.hpp"
#include "CarlaMIDI.h"

#include <QtCore/QFile>
#include <QtCore/QTextStream>

//#include <QtGui/QtEvents>

// TODO - save&load options
@@ -477,22 +480,22 @@ const SaveState& CarlaPlugin::getSaveState()
if (paramData.type != PARAMETER_INPUT)
continue;

StateParameter stateParameter;
StateParameter* stateParameter(new StateParameter);

stateParameter.index = paramData.index;
stateParameter.midiCC = paramData.midiCC;
stateParameter.midiChannel = paramData.midiChannel + 1;
stateParameter->index = paramData.index;
stateParameter->midiCC = paramData.midiCC;
stateParameter->midiChannel = paramData.midiChannel + 1;

getParameterName(i, strBuf);
stateParameter.name = carla_strdup(strBuf);
stateParameter->name = carla_strdup(strBuf);

getParameterSymbol(i, strBuf);
stateParameter.symbol = carla_strdup(strBuf);;
stateParameter->symbol = carla_strdup(strBuf);;

stateParameter.value = getParameterValue(i);
stateParameter->value = getParameterValue(i);

if (paramData.hints & PARAMETER_USES_SAMPLERATE)
stateParameter.value /= sampleRate;
stateParameter->value /= sampleRate;

saveState.parameters.push_back(stateParameter);
}
@@ -507,11 +510,11 @@ const SaveState& CarlaPlugin::getSaveState()
if (cData.type == nullptr)
continue;

StateCustomData stateCustomData;
StateCustomData* stateCustomData(new StateCustomData);

stateCustomData.type = carla_strdup(cData.type);
stateCustomData.key = carla_strdup(cData.key);
stateCustomData.value = carla_strdup(cData.value);
stateCustomData->type = carla_strdup(cData.type);
stateCustomData->key = carla_strdup(cData.key);
stateCustomData->value = carla_strdup(cData.value);

saveState.customData.push_back(stateCustomData);
}
@@ -542,6 +545,53 @@ void CarlaPlugin::loadSaveState(const SaveState& saveState)
Q_UNUSED(saveState);
}

bool CarlaPlugin::saveStateToFile(const char* const filename)
{
carla_debug("CarlaPlugin::saveStateToFile(\"%s\")", filename);
CARLA_ASSERT(filename != nullptr);

QFile file(filename);

if (! file.open(QIODevice::WriteOnly | QIODevice::Text))
return false;

QTextStream out(&file);
out << "<?xml version='1.0' encoding='UTF-8'?>\n";
out << "<!DOCTYPE CARLA-PRESET>\n";
out << "<CARLA-PRESET VERSION='1.0'>\n";
out << getXMLFromSaveState(getSaveState());
out << "</CARLA-PRESET>\n";

file.close();
return true;
}

bool CarlaPlugin::loadStateFromFile(const char* const filename)
{
carla_debug("CarlaPlugin::loadStateFromFile(\"%s\")", filename);
CARLA_ASSERT(filename != nullptr);

QFile file(filename);

if (! file.open(QIODevice::ReadOnly | QIODevice::Text))
return false;

QDomDocument xml;
xml.setContent(file.readAll());
file.close();

QDomNode xmlNode(xml.documentElement());

if (xmlNode.toElement().tagName() != "CARLA-PRESET")
{
carla_stderr2("Not a valid Carla preset file");
return false;
}

loadSaveState(getSaveStateDictFromXML(xmlNode));
return true;
}

// -------------------------------------------------------------------
// Set data (internal stuff)



+ 30
- 0
source/backend/standalone/CarlaStandalone.cpp View File

@@ -541,6 +541,36 @@ void carla_remove_all_plugins()
standalone.engine->removeAllPlugins();
}

bool carla_load_plugin_state(unsigned int pluginId, const char* filename)
{
carla_debug("carla_load_plugin_state(%i, \"%s\")", pluginId, filename);
CARLA_ASSERT(standalone.engine != nullptr);

if (standalone.engine == nullptr)
return false;

if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
return plugin->loadStateFromFile(filename);

carla_stderr2("carla_load_plugin_state(%i, \"%s\") - could not find plugin", pluginId, filename);
return false;
}

bool carla_save_plugin_state(unsigned int pluginId, const char* filename)
{
carla_debug("carla_save_plugin_state(%i, \"%s\")", pluginId, filename);
CARLA_ASSERT(standalone.engine != nullptr);

if (standalone.engine == nullptr)
return false;

if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
return plugin->saveStateToFile(filename);

carla_stderr2("carla_save_plugin_state(%i, \"%s\") - could not find plugin", pluginId, filename);
return false;
}

// -------------------------------------------------------------------------------------------------------------------

const CarlaPluginInfo* carla_get_plugin_info(unsigned int pluginId)


+ 1
- 1
source/backend/standalone/Makefile View File

@@ -9,7 +9,7 @@ include ../Makefile.mk
# --------------------------------------------------------------
# Common

LINK_FLAGS += $(shell pkg-config --libs liblo QtCore QtGui)
LINK_FLAGS += $(shell pkg-config --libs liblo QtCore QtGui QtXml)

# --------------------------------------------------------------
# Engine


+ 12
- 0
source/carla_backend.py View File

@@ -209,6 +209,12 @@ class Host(object):
self.lib.carla_remove_all_plugins.argtypes = None
self.lib.carla_remove_all_plugins.restype = None

self.lib.carla_load_plugin_state.argtypes = [c_uint, c_char_p]
self.lib.carla_load_plugin_state.restype = c_bool

self.lib.carla_save_plugin_state.argtypes = [c_uint, c_char_p]
self.lib.carla_save_plugin_state.restype = c_bool

self.lib.carla_get_plugin_info.argtypes = [c_uint]
self.lib.carla_get_plugin_info.restype = POINTER(CarlaPluginInfo)

@@ -423,6 +429,12 @@ class Host(object):
def remove_all_plugins(self):
self.lib.carla_remove_all_plugins()

def load_plugin_state(self, pluginId, filename):
return self.lib.carla_load_plugin_state(pluginId, filename.encode("utf-8"))

def save_plugin_state(self, pluginId, filename):
return self.lib.carla_save_plugin_state(pluginId, filename.encode("utf-8"))

def get_plugin_info(self, pluginId):
return structToDict(self.lib.carla_get_plugin_info(pluginId).contents)



+ 3
- 3
source/carla_shared.py View File

@@ -1930,7 +1930,7 @@ class PluginEdit(QDialog):
askTry = QMessageBox.question(self, self.tr("Overwrite?"), self.tr("Overwrite previously created file?"), QMessageBox.Ok|QMessageBox.Cancel)

if askTry == QMessageBox.Ok:
return #self.saveState()
Carla.host.save_plugin_state(self.fPluginId, self.fCurrentStateFilename)

self.fCurrentStateFilename = None

@@ -1942,7 +1942,7 @@ class PluginEdit(QDialog):
filenameTry += ".carxs"

self.fCurrentStateFilename = filenameTry
#self.saveState()
Carla.host.save_plugin_state(self.fPluginId, self.fCurrentStateFilename)

@pyqtSlot()
def slot_loadState(self):
@@ -1951,7 +1951,7 @@ class PluginEdit(QDialog):

if filenameTry:
self.fCurrentStateFilename = filenameTry
#self.loadState()
Carla.host.load_plugin_state(self.fPluginId, self.fCurrentStateFilename)

@pyqtSlot(bool)
def slot_optionChanged(self, clicked):


+ 37
- 3
source/utils/CarlaBackendUtils.hpp View File

@@ -366,9 +366,9 @@ void* getPointerFromAddress(uintptr_t& addr)
// -------------------------------------------------

static inline
const char* getPluginTypeString(const PluginType& type)
const char* getPluginTypeAsString(const PluginType& type)
{
carla_debug("CarlaBackend::getPluginTypeString(%s)", PluginType2Str(type));
carla_debug("CarlaBackend::getPluginTypeAsString(%s)", PluginType2Str(type));

switch (type)
{
@@ -392,10 +392,44 @@ const char* getPluginTypeString(const PluginType& type)
return "SFZ";
}

carla_stderr("CarlaBackend::getPluginTypeString(%i) - invalid type", type);
carla_stderr("CarlaBackend::getPluginTypeAsString(%i) - invalid type", type);
return "NONE";
}

static inline
PluginType getPluginTypeFromString(const char* const stype)
{
carla_debug("CarlaBackend::getPluginTypeFromString(%s)", stype);

if (stype == nullptr)
{
carla_stderr("CarlaBackend::getPluginTypeFromString() - null string type");
return PLUGIN_NONE;
}

if (std::strcmp(stype, "NONE") == 0)
return PLUGIN_NONE;
if (std::strcmp(stype, "INTERNAL") == 0 || std::strcmp(stype, "Internal") == 0)
return PLUGIN_INTERNAL;
if (std::strcmp(stype, "LADSPA") == 0)
return PLUGIN_LADSPA;
if (std::strcmp(stype, "DSSI") == 0)
return PLUGIN_DSSI;
if (std::strcmp(stype, "LV2") == 0)
return PLUGIN_LV2;
if (std::strcmp(stype, "VST") == 0)
return PLUGIN_VST;
if (std::strcmp(stype, "GIG") == 0)
return PLUGIN_GIG;
if (std::strcmp(stype, "SF2") == 0)
return PLUGIN_SF2;
if (std::strcmp(stype, "SFZ") == 0)
return PLUGIN_SFZ;

carla_stderr("CarlaBackend::getPluginTypeFromString(%s) - invalid string type", stype);
return PLUGIN_NONE;
}

// -------------------------------------------------

static inline


+ 188
- 37
source/utils/CarlaStateUtils.hpp View File

@@ -18,8 +18,7 @@
#ifndef __CARLA_STATE_UTILS_HPP__
#define __CARLA_STATE_UTILS_HPP__

#include "CarlaBackend.hpp"
#include "CarlaUtils.hpp"
#include "CarlaBackendUtils.hpp"

#include <QtXml/QDomNode>
#include <vector>
@@ -27,7 +26,6 @@
CARLA_BACKEND_START_NAMESPACE

// -------------------------------------------------
// Carla GUI stuff

struct StateParameter {
uint32_t index;
@@ -75,8 +73,8 @@ struct StateCustomData {
}
};

typedef std::vector<StateParameter> StateParameterVector;
typedef std::vector<StateCustomData> StateCustomDataVector;
typedef std::vector<StateParameter*> StateParameterVector;
typedef std::vector<StateCustomData*> StateCustomDataVector;

struct SaveState {
const char* type;
@@ -173,13 +171,24 @@ struct SaveState {
currentMidiBank = -1;
currentMidiProgram = -1;

for (auto it = parameters.begin(); it != parameters.end(); ++it)
{
StateParameter* stateParameter = *it;
delete stateParameter;
}

for (auto it = customData.begin(); it != customData.end(); ++it)
{
StateCustomData* stateCustomData = *it;
delete stateCustomData;
}

parameters.clear();
customData.clear();
}
};

// -------------------------------------------------
// Carla XML helpers (xml to state)

static inline
QString xmlSafeString(const QString& string, const bool toXml)
@@ -198,6 +207,8 @@ const char* xmlSafeStringChar(const QString& string, const bool toXml)
return carla_strdup(xmlSafeString(string, toXml).toUtf8().constData());
}

// -------------------------------------------------

static inline
const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode)
{
@@ -261,27 +272,33 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode)
else if (tag == "DryWet")
{
bool ok;
double value = text.toDouble(&ok);
float value = text.toFloat(&ok);
if (ok) saveState.dryWet = value;
}
else if (tag == "Volume")
{
bool ok;
double value = text.toDouble(&ok);
float value = text.toFloat(&ok);
if (ok) saveState.volume = value;
}
else if (tag == "Balance-Left")
{
bool ok;
double value = text.toDouble(&ok);
float value = text.toFloat(&ok);
if (ok) saveState.balanceLeft = value;
}
else if (tag == "Balance-Right")
{
bool ok;
double value = text.toDouble(&ok);
float value = text.toFloat(&ok);
if (ok) saveState.balanceRight = value;
}
else if (tag == "Panning")
{
bool ok;
float value = text.toFloat(&ok);
if (ok) saveState.panning = value;
}

// ----------------------------------------------
// Program (current)
@@ -318,7 +335,7 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode)

else if (tag == "Parameter")
{
StateParameter stateParameter;
StateParameter* stateParameter(new StateParameter);

QDomNode xmlSubData(xmlData.toElement().firstChild());

@@ -327,39 +344,39 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode)
const QString pTag = xmlSubData.toElement().tagName();
const QString pText = xmlSubData.toElement().text(); //.strip();

if (pTag == "index")
if (pTag == "Index")
{
bool ok;
uint index = pText.toUInt(&ok);
if (ok) stateParameter.index = index;
if (ok) stateParameter->index = index;
}
else if (pTag == "name")
else if (pTag == "Name")
{
stateParameter.name = xmlSafeStringChar(pText, false);
stateParameter->name = xmlSafeStringChar(pText, false);
}
else if (pTag == "symbol")
else if (pTag == "Symbol")
{
stateParameter.symbol = xmlSafeStringChar(pText, false);
stateParameter->symbol = xmlSafeStringChar(pText, false);
}
else if (pTag == "value")
else if (pTag == "Value")
{
bool ok;
double value = pText.toDouble(&ok);
if (ok) stateParameter.value = value;
float value = text.toFloat(&ok);
if (ok) stateParameter->value = value;
}
else if (pTag == "midiChannel")
else if (pTag == "MidiChannel")
{
bool ok;
uint channel = pText.toUInt(&ok);
if (ok && channel < 16)
stateParameter.midiChannel = static_cast<uint8_t>(channel);
stateParameter->midiChannel = static_cast<uint8_t>(channel);
}
else if (pTag == "midiCC")
else if (pTag == "MidiCC")
{
bool ok;
int cc = pText.toInt(&ok);
if (ok && cc < INT16_MAX)
stateParameter.midiCC = static_cast<int16_t>(cc);
stateParameter->midiCC = static_cast<int16_t>(cc);
}

xmlSubData = xmlSubData.nextSibling();
@@ -373,7 +390,7 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode)

else if (tag == "CustomData")
{
StateCustomData stateCustomData;
StateCustomData* stateCustomData(new StateCustomData);

QDomNode xmlSubData(xmlData.toElement().firstChild());

@@ -382,12 +399,12 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode)
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);
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();
}
@@ -417,17 +434,151 @@ const SaveState& getSaveStateDictFromXML(const QDomNode& xmlNode)
return saveState;
}

// -------------------------------------------------

static inline
QString getXMLFromSaveState(const SaveState& saveState)
{
return "";
QString content;

// TODO
(void)saveState;
}
{
QString info(" <Info>\n");

// -------------------------------------------------
// Carla XML helpers (state to xml)
info += QString(" <Type>%1</Type>\n").arg(saveState.type);
info += QString(" <Name>%1</Name>\n").arg(xmlSafeString(saveState.name, true));

switch (getPluginTypeFromString(saveState.type))
{
case PLUGIN_NONE:
break;
case PLUGIN_INTERNAL:
info += QString(" <Label>%1</Label>\n").arg(xmlSafeString(saveState.label, true));
break;
case PLUGIN_LADSPA:
info += QString(" <Binary>%1</Binary>\n").arg(xmlSafeString(saveState.binary, true));
info += QString(" <Label>%1</Label>\n").arg(xmlSafeString(saveState.label, true));
info += QString(" <UniqueID>%1</UniqueID>\n").arg(saveState.uniqueID);
break;
case PLUGIN_DSSI:
info += QString(" <Binary>%1</Binary>\n").arg(xmlSafeString(saveState.binary, true));
info += QString(" <Label>%1</Label>\n").arg(xmlSafeString(saveState.label, true));
break;
case PLUGIN_LV2:
info += QString(" <URI>%1</URI>\n").arg(xmlSafeString(saveState.label, true));
break;
case PLUGIN_VST:
info += QString(" <Binary>%1</Binary>\n").arg(xmlSafeString(saveState.binary, true));
info += QString(" <UniqueID>%1</UniqueID>\n").arg(saveState.uniqueID);
break;
case PLUGIN_GIG:
case PLUGIN_SF2:
case PLUGIN_SFZ:
info += QString(" <Binary>%1</Binary>\n").arg(xmlSafeString(saveState.binary, true));
break;
}

info += " </Info>\n\n";

content += info;
}

{
QString data(" <Data>\n");

data += QString(" <Active>%1</Active>\n").arg(saveState.active ? "Yes" : "No");

if (saveState.dryWet != 1.0f)
data += QString(" <DryWet>%1</DryWet>\n").arg(saveState.dryWet);
if (saveState.volume != 1.0f)
data += QString(" <Volume>%1</Volume>\n").arg(saveState.volume);
if (saveState.balanceLeft != -1.0f)
data += QString(" <Balance-Left>%1</Balance-Left>\n").arg(saveState.balanceLeft);
if (saveState.balanceRight != 1.0f)
data += QString(" <Balance-Right>%1</Balance-Right>\n").arg(saveState.balanceRight);
if (saveState.panning != 0.0f)
data += QString(" <Panning>%1</Panning>\n").arg(saveState.panning);

content += data;
}

for (auto it = saveState.parameters.begin(); it != saveState.parameters.end(); ++it)
{
StateParameter* stateParameter = *it;

QString parameter("\n"" <Parameter>\n");

parameter += QString(" <Index>%1</Index>\n").arg(stateParameter->index);
parameter += QString(" <Name>%1</Name>\n").arg(xmlSafeString(stateParameter->name, true));

if (stateParameter->symbol != nullptr && *stateParameter->symbol != 0)
parameter += QString(" <Symbol>%1</Symbol>\n").arg(xmlSafeString(stateParameter->symbol, true));

parameter += QString(" <Value>%1</Value>\n").arg(stateParameter->value);

if (stateParameter->midiCC > 0)
{
parameter += QString(" <MidiCC>%1</MidiCC>\n").arg(stateParameter->midiCC);
parameter += QString(" <MidiChannel>%1</MidiChannel>\n").arg(stateParameter->midiChannel);
}

parameter += " </Parameter>\n";

content += parameter;
}

if (saveState.currentProgramIndex >= 0)
{
QString program("\n");
program += QString(" <CurrentProgramIndex>%1</CurrentProgramIndex>\n").arg(saveState.currentProgramIndex);
program += QString(" <CurrentProgramName>%1</CurrentProgramName>\n").arg(xmlSafeString(saveState.currentProgramName, true));

content += program;
}

if (saveState.currentMidiBank >= 0 && saveState.currentMidiProgram >= 0)
{
QString midiProgram("\n");
midiProgram += QString(" <CurrentMidiBank>%1</CurrentMidiBank>\n").arg(saveState.currentMidiBank);
midiProgram += QString(" <CurrentMidiProgram>%1</CurrentMidiProgram>\n").arg(saveState.currentMidiProgram);

content += midiProgram;
}

for (auto it = saveState.customData.begin(); it != saveState.customData.end(); ++it)
{
StateCustomData* stateCustomData = *it;

QString customData("\n"" <CustomData>\n");
customData += QString(" <Type>%1</Type>\n").arg(xmlSafeString(stateCustomData->type, true));
customData += QString(" <Key>%1</Key>\n").arg(xmlSafeString(stateCustomData->key, true));

if (std::strcmp(stateCustomData->type, CUSTOM_DATA_CHUNK) == 0)
{
customData += " <Value>\n";
customData += QString("%1\n").arg(xmlSafeString(stateCustomData->value, true));
customData += " </Value>\n";
}
else
customData += QString(" <Value>%1</Value>\n").arg(xmlSafeString(stateCustomData->value, true));

customData += " </CustomData>\n";

content += customData;
}

if (saveState.chunk != nullptr && *saveState.chunk != 0)
{
QString chunk("\n"" <Chunk>\n");
chunk += QString("%1\n").arg(saveState.chunk);
chunk += " </Chunk>\n";

content += chunk;
}

content += " </Data>\n";

return content;
}

// -------------------------------------------------



Loading…
Cancel
Save