| @@ -6,15 +6,15 @@ | |||||
| include ../../Makefile.mk | include ../../Makefile.mk | ||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| BUILD_CXX_FLAGS += -I. -I.. -I../../includes -I../../utils -isystem ../../modules | BUILD_CXX_FLAGS += -I. -I.. -I../../includes -I../../utils -isystem ../../modules | ||||
| BUILD_CXX_FLAGS += $(LIBLO_FLAGS) | BUILD_CXX_FLAGS += $(LIBLO_FLAGS) | ||||
| BUILD_CXX_FLAGS += $(QTCORE_FLAGS) | |||||
| BUILD_CXX_FLAGS += $(QTXML_FLAGS) | |||||
| # BUILD_CXX_FLAGS += $(QTCORE_FLAGS) | |||||
| # BUILD_CXX_FLAGS += $(QTXML_FLAGS) | |||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| BUILD_CXX_FLAGS += -DWANT_NATIVE | BUILD_CXX_FLAGS += -DWANT_NATIVE | ||||
| @@ -26,7 +26,7 @@ BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 | |||||
| # endif | # endif | ||||
| endif | endif | ||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| # ifeq ($(HAVE_CSOUND),true) | # ifeq ($(HAVE_CSOUND),true) | ||||
| # BUILD_CXX_FLAGS += -DWANT_CSOUND | # BUILD_CXX_FLAGS += -DWANT_CSOUND | ||||
| @@ -40,7 +40,7 @@ ifeq ($(HAVE_LINUXSAMPLER),true) | |||||
| BUILD_CXX_FLAGS += -DWANT_LINUXSAMPLER | BUILD_CXX_FLAGS += -DWANT_LINUXSAMPLER | ||||
| endif | endif | ||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| ifeq ($(HAVE_AF_DEPS),true) | ifeq ($(HAVE_AF_DEPS),true) | ||||
| BUILD_CXX_FLAGS += -DWANT_AUDIOFILE | BUILD_CXX_FLAGS += -DWANT_AUDIOFILE | ||||
| @@ -57,7 +57,7 @@ BUILD_CXX_FLAGS += -DWANT_ZYNADDSUBFX_UI | |||||
| endif | endif | ||||
| endif | endif | ||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| CARLA_DEFINES_H = ../../includes/CarlaDefines.h | CARLA_DEFINES_H = ../../includes/CarlaDefines.h | ||||
| CARLA_MIDI_H = ../../includes/CarlaMIDI.h | CARLA_MIDI_H = ../../includes/CarlaMIDI.h | ||||
| @@ -69,6 +69,7 @@ CARLA_PLUGIN_HPP = ../CarlaPlugin.hpp $(CARLA_BACKEND_H) | |||||
| CARLA_UTILS_HPP = ../../utils/CarlaUtils.hpp $(CARLA_DEFINES_H) | CARLA_UTILS_HPP = ../../utils/CarlaUtils.hpp $(CARLA_DEFINES_H) | ||||
| CARLA_JUCE_UTILS_HPP = ../../utils/CarlaJuceUtils.hpp $(CARLA_UTILS_HPP) | CARLA_JUCE_UTILS_HPP = ../../utils/CarlaJuceUtils.hpp $(CARLA_UTILS_HPP) | ||||
| CARLA_LIB_UTILS_HPP = ../../utils/CarlaLibUtils.hpp $(CARLA_UTILS_HPP) | |||||
| CARLA_OSC_UTILS_HPP = ../../utils/CarlaOscUtils.hpp $(CARLA_UTILS_HPP) | CARLA_OSC_UTILS_HPP = ../../utils/CarlaOscUtils.hpp $(CARLA_UTILS_HPP) | ||||
| CARLA_MUTEX_HPP = ../../utils/CarlaMutex.hpp $(CARLA_UTILS_HPP) | CARLA_MUTEX_HPP = ../../utils/CarlaMutex.hpp $(CARLA_UTILS_HPP) | ||||
| @@ -76,19 +77,27 @@ CARLA_RING_BUFFER_HPP = ../../utils/CarlaRingBuffer.hpp $(CARLA_UTILS_HPP) | |||||
| CARLA_STRING_HPP = ../../utils/CarlaString.hpp $(CARLA_JUCE_UTILS_HPP) | CARLA_STRING_HPP = ../../utils/CarlaString.hpp $(CARLA_JUCE_UTILS_HPP) | ||||
| CARLA_THREAD_HPP = ../../utils/CarlaThread.hpp $(CARLA_MUTEX_HPP) $(CARLA_STRING_HPP) | CARLA_THREAD_HPP = ../../utils/CarlaThread.hpp $(CARLA_MUTEX_HPP) $(CARLA_STRING_HPP) | ||||
| LV2_ATOM_QUEUE_HPP = ../../utils/Lv2AtomQueue.hpp $(CARLA_MUTEX_HPP) $(CARLA_RING_BUFFER_HPP) | |||||
| LINKED_LIST_HPP = ../../utils/LinkedList.hpp $(CARLA_UTILS_HPP) | LINKED_LIST_HPP = ../../utils/LinkedList.hpp $(CARLA_UTILS_HPP) | ||||
| RT_LINKED_LIST_HPP = ../../utils/RtLinkedList.hpp $(LINKED_LIST_HPP) | RT_LINKED_LIST_HPP = ../../utils/RtLinkedList.hpp $(LINKED_LIST_HPP) | ||||
| CARLA_BACKEND_UTILS_HPP = ../../utils/CarlaBackendUtils.hpp $(CARLA_BACKEND_H) $(CARLA_HOST_H) $(CARLA_STRING_HPP) | CARLA_BACKEND_UTILS_HPP = ../../utils/CarlaBackendUtils.hpp $(CARLA_BACKEND_H) $(CARLA_HOST_H) $(CARLA_STRING_HPP) | ||||
| CARLA_BRIDGE_UTILS_HPP = ../../utils/CarlaBridgeUtils.hpp $(CARLA_RING_BUFFER_HPP) | CARLA_BRIDGE_UTILS_HPP = ../../utils/CarlaBridgeUtils.hpp $(CARLA_RING_BUFFER_HPP) | ||||
| CARLA_ENGINE_UTILS_HPP = ../../utils/CarlaEngineUtils.hpp $(CARLA_ENGINE_HPP) $(CARLA_UTILS_HPP) | CARLA_ENGINE_UTILS_HPP = ../../utils/CarlaEngineUtils.hpp $(CARLA_ENGINE_HPP) $(CARLA_UTILS_HPP) | ||||
| CARLA_LIB_COUNTER_HPP = ../../utils/CarlaLibCounter.hpp $(CARLA_LIB_UTILS_HPP) $(CARLA_MUTEX_HPP) $(LINKED_LIST_HPP) | |||||
| CARLA_PIPE_UTILS_HPP = ../../utils/CarlaPipeUtils.hpp $(CARLA_STRING_HPP) | CARLA_PIPE_UTILS_HPP = ../../utils/CarlaPipeUtils.hpp $(CARLA_STRING_HPP) | ||||
| CARLA_SHM_UTILS_HPP = ../../utils/CarlaShmUtils.hpp $(CARLA_UTILS_HPP) | |||||
| CARLA_STATE_UTILS_HPP = ../../utils/CarlaStateUtils.hpp $(CARLA_BACKEND_UTILS_HPP) $(CARLA_MIDI_H) $(LINKED_LIST_HPP) | CARLA_STATE_UTILS_HPP = ../../utils/CarlaStateUtils.hpp $(CARLA_BACKEND_UTILS_HPP) $(CARLA_MIDI_H) $(LINKED_LIST_HPP) | ||||
| CARLA_LADSPA_UTILS_HPP = ../../utils/CarlaLadspaUtils.hpp $(CARLA_UTILS_HPP) | |||||
| CARLA_DSSI_UTILS_HPP = ../../utils/CarlaDssiUtils.hpp $(CARLA_LADSPA_UTILS_HPP) | |||||
| CARLA_LV2_UTILS_HPP = ../../utils/CarlaLv2Utils.hpp $(CARLA_UTILS_HPP) | |||||
| CARLA_VST_UTILS_HPP = ../../utils/CarlaVstUtils.hpp $(CARLA_UTILS_HPP) | |||||
| CARLA_NATIVE_H = ../../modules/CarlaNative.h | CARLA_NATIVE_H = ../../modules/CarlaNative.h | ||||
| CARLA_NATIVE_HPP = ../../modules/CarlaNative.hpp $(CARLA_NATIVE_H) $(CARLA_MIDI_H) $(CARLA_JUCE_UTILS_HPP) | CARLA_NATIVE_HPP = ../../modules/CarlaNative.hpp $(CARLA_NATIVE_H) $(CARLA_MIDI_H) $(CARLA_JUCE_UTILS_HPP) | ||||
| JACK_BRIDGE_HPP = ../../modules/jackbridge/JackBridge.hpp $(CARLA_DEFINES_H) | JACK_BRIDGE_HPP = ../../modules/jackbridge/JackBridge.hpp $(CARLA_DEFINES_H) | ||||
| RTAUDIO_HPP = ../../modules/rtaudio/RtAudio.h | RTAUDIO_HPP = ../../modules/rtaudio/RtAudio.h | ||||
| RTMIDI_HPP = ../../modules/rtmidi/RtMidi.h $(CARLA_DEFINES_H) | RTMIDI_HPP = ../../modules/rtmidi/RtMidi.h $(CARLA_DEFINES_H) | ||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| @@ -32,6 +32,8 @@ | |||||
| #include "CarlaEngineUtils.hpp" | #include "CarlaEngineUtils.hpp" | ||||
| #include "CarlaStateUtils.hpp" | #include "CarlaStateUtils.hpp" | ||||
| #include "CarlaMIDI.h" | |||||
| #ifndef HAVE_JUCE | #ifndef HAVE_JUCE | ||||
| # include <cmath> | # include <cmath> | ||||
| #else | #else | ||||
| @@ -42,6 +44,7 @@ using juce::FloatVectorOperations; | |||||
| #include <QtCore/QFile> | #include <QtCore/QFile> | ||||
| #include <QtCore/QFileInfo> | #include <QtCore/QFileInfo> | ||||
| #include <QtCore/QTextStream> | #include <QtCore/QTextStream> | ||||
| #include <QtXml/QDomNode> | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -1414,8 +1417,8 @@ bool CarlaEngine::saveProject(const char* const filename) | |||||
| plugin->getRealName(strBuf); | plugin->getRealName(strBuf); | ||||
| if (strBuf[0] != '\0') | |||||
| out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true)); | |||||
| //if (strBuf[0] != '\0') | |||||
| // out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true)); | |||||
| QString content; | QString content; | ||||
| fillXmlStringFromSaveState(content, plugin->getSaveState()); | fillXmlStringFromSaveState(content, plugin->getSaveState()); | ||||
| @@ -27,16 +27,19 @@ | |||||
| #include "CarlaEngineInternal.hpp" | #include "CarlaEngineInternal.hpp" | ||||
| #include "CarlaPlugin.hpp" | #include "CarlaPlugin.hpp" | ||||
| #include "CarlaNative.hpp" | |||||
| #include "CarlaBackendUtils.hpp" | |||||
| #include "CarlaPipeUtils.hpp" | #include "CarlaPipeUtils.hpp" | ||||
| #include "CarlaStateUtils.hpp" | #include "CarlaStateUtils.hpp" | ||||
| #include "CarlaNative.hpp" | |||||
| #ifdef HAVE_JUCE | #ifdef HAVE_JUCE | ||||
| # include "juce_audio_basics.h" | # include "juce_audio_basics.h" | ||||
| using juce::FloatVectorOperations; | using juce::FloatVectorOperations; | ||||
| #endif | #endif | ||||
| #include <QtCore/QTextStream> | #include <QtCore/QTextStream> | ||||
| #include <QtXml/QDomNode> | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| @@ -1255,8 +1258,8 @@ protected: | |||||
| plugin->getRealName(strBuf); | plugin->getRealName(strBuf); | ||||
| if (strBuf[0] != '\0') | |||||
| out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true)); | |||||
| //if (strBuf[0] != '\0') | |||||
| // out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true)); | |||||
| QString content; | QString content; | ||||
| fillXmlStringFromSaveState(content, plugin->getSaveState()); | fillXmlStringFromSaveState(content, plugin->getSaveState()); | ||||
| @@ -49,7 +49,7 @@ endif | |||||
| all: $(TARGETa) $(TARGETp) | all: $(TARGETa) $(TARGETp) | ||||
| clean: | clean: | ||||
| $(RM) *.o $(OBJSp) $(TARGET) $(TARGETp) | |||||
| $(RM) *.o $(TARGET) $(TARGETp) | |||||
| debug: | debug: | ||||
| $(MAKE) DEBUG=true | $(MAKE) DEBUG=true | ||||
| @@ -66,8 +66,8 @@ $(TARGETp): $(OBJSp) | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------------------------------- | ||||
| CarlaEngine.cpp.o: CarlaEngine.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_BACKEND_UTILS_HPP) $(CARLA_ENGINE_UTILS_HPP) $(CARLA_STATE_UTILS_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| CarlaEngine.cpp.o: CarlaEngine.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_BACKEND_UTILS_HPP) $(CARLA_ENGINE_UTILS_HPP) $(CARLA_STATE_UTILS_HPP) $(CARLA_MIDI_H) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) $(QTXML_FLAGS) -c -o $@ | |||||
| CarlaEngineInternal.cpp.o: CarlaEngineInternal.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_MIDI_H) | CarlaEngineInternal.cpp.o: CarlaEngineInternal.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_MIDI_H) | ||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | ||||
| @@ -79,7 +79,7 @@ CarlaEngineThread.cpp.o: CarlaEngineThread.cpp $(CARLA_ENGINE_HPP) $(CARLA_ENGIN | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | ||||
| CarlaEngineJack.cpp.o: CarlaEngineJack.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_BACKEND_UTILS_HPP) $(CARLA_ENGINE_UTILS_HPP) $(CARLA_MIDI_H) $(JACK_BRIDGE_HPP) | CarlaEngineJack.cpp.o: CarlaEngineJack.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_BACKEND_UTILS_HPP) $(CARLA_ENGINE_UTILS_HPP) $(CARLA_MIDI_H) $(JACK_BRIDGE_HPP) | ||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ | |||||
| CarlaEngineRtAudio.cpp.o: CarlaEngineRtAudio.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_BACKEND_UTILS_HPP) $(RT_LINKED_LIST_HPP) $(RTAUDIO_HPP) $(RTMIDI_HPP) | CarlaEngineRtAudio.cpp.o: CarlaEngineRtAudio.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_BACKEND_UTILS_HPP) $(RT_LINKED_LIST_HPP) $(RTAUDIO_HPP) $(RTMIDI_HPP) | ||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(RTAUDIO_FLAGS) $(RTMIDI_FLAGS) -c -o $@ | $(CXX) $< $(BUILD_CXX_FLAGS) $(RTAUDIO_FLAGS) $(RTMIDI_FLAGS) -c -o $@ | ||||
| @@ -87,10 +87,10 @@ CarlaEngineRtAudio.cpp.o: CarlaEngineRtAudio.cpp $(CARLA_ENGINE_INTERNAL_HPP) $( | |||||
| CarlaEngineJuce.cpp.o: CarlaEngineJuce.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_BACKEND_UTILS_HPP) | CarlaEngineJuce.cpp.o: CarlaEngineJuce.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_BACKEND_UTILS_HPP) | ||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | ||||
| CarlaEngineNative.cpp.o: CarlaEngineNative.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_NATIVE_HPP) $(CARLA_PIPE_UTILS_HPP) $(CARLA_STATE_UTILS_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| CarlaEngineNative.cpp.o: CarlaEngineNative.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_BACKEND_UTILS_HPP) $(CARLA_PIPE_UTILS_HPP) $(CARLA_STATE_UTILS_HPP) $(CARLA_NATIVE_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) $(QTXML_FLAGS) -c -o $@ | |||||
| CarlaEngineNative.cpp.exp.o: CarlaEngineNative.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_NATIVE_HPP) $(CARLA_PIPE_UTILS_HPP) $(CARLA_STATE_UTILS_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -DCARLA_PLUGIN_EXPORT -c -o $@ | |||||
| CarlaEngineNative.cpp.exp.o: CarlaEngineNative.cpp $(CARLA_ENGINE_INTERNAL_HPP) $(CARLA_PLUGIN_HPP) $(CARLA_BACKEND_UTILS_HPP) $(CARLA_PIPE_UTILS_HPP) $(CARLA_STATE_UTILS_HPP) $(CARLA_NATIVE_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) $(QTXML_FLAGS) -DCARLA_PLUGIN_EXPORT -c -o $@ | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -20,6 +20,7 @@ | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| #include "CarlaBackendUtils.hpp" | |||||
| #include "CarlaBridgeUtils.hpp" | #include "CarlaBridgeUtils.hpp" | ||||
| #include "CarlaShmUtils.hpp" | #include "CarlaShmUtils.hpp" | ||||
| @@ -18,8 +18,12 @@ | |||||
| #include "CarlaPluginInternal.hpp" | #include "CarlaPluginInternal.hpp" | ||||
| #include "CarlaEngine.hpp" | #include "CarlaEngine.hpp" | ||||
| #include "CarlaBackendUtils.hpp" | |||||
| #include "CarlaMIDI.h" | |||||
| #include <QtCore/QFile> | #include <QtCore/QFile> | ||||
| #include <QtCore/QTextStream> | #include <QtCore/QTextStream> | ||||
| #include <QtXml/QDomNode> | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| @@ -27,6 +27,8 @@ | |||||
| #include "CarlaMutex.hpp" | #include "CarlaMutex.hpp" | ||||
| #include "RtLinkedList.hpp" | #include "RtLinkedList.hpp" | ||||
| #include "CarlaMIDI.h" | |||||
| #include <cmath> | #include <cmath> | ||||
| #ifdef HAVE_JUCE | #ifdef HAVE_JUCE | ||||
| @@ -15,9 +15,8 @@ | |||||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
| */ | */ | ||||
| #include "CarlaPluginThread.hpp" | |||||
| #include "CarlaPlugin.hpp" | #include "CarlaPlugin.hpp" | ||||
| #include "CarlaPluginThread.hpp" | |||||
| #include "CarlaEngine.hpp" | #include "CarlaEngine.hpp" | ||||
| #include <QtCore/QProcess> | #include <QtCore/QProcess> | ||||
| @@ -21,7 +21,6 @@ | |||||
| #ifdef WANT_DSSI | #ifdef WANT_DSSI | ||||
| #include "CarlaDssiUtils.hpp" | #include "CarlaDssiUtils.hpp" | ||||
| #include "CarlaLibUtils.hpp" | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| @@ -1806,7 +1805,7 @@ public: | |||||
| if (! pData->libOpen(filename)) | if (! pData->libOpen(filename)) | ||||
| { | { | ||||
| pData->engine->setLastError(lib_error(filename)); | |||||
| pData->engine->setLastError(pData->libError(filename)); | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -26,6 +26,8 @@ | |||||
| #ifdef WANT_LINUXSAMPLER | #ifdef WANT_LINUXSAMPLER | ||||
| #include "CarlaBackendUtils.hpp" | |||||
| #include "linuxsampler/EngineFactory.h" | #include "linuxsampler/EngineFactory.h" | ||||
| #include <linuxsampler/Sampler.h> | #include <linuxsampler/Sampler.h> | ||||
| @@ -21,7 +21,6 @@ | |||||
| #ifdef WANT_LV2 | #ifdef WANT_LV2 | ||||
| #include "CarlaLv2Utils.hpp" | #include "CarlaLv2Utils.hpp" | ||||
| #include "CarlaLibUtils.hpp" | |||||
| #include "Lv2AtomQueue.hpp" | #include "Lv2AtomQueue.hpp" | ||||
| #include "../engine/CarlaEngineOsc.hpp" | #include "../engine/CarlaEngineOsc.hpp" | ||||
| @@ -1408,7 +1407,7 @@ public: | |||||
| if (! pData->libOpen(fRdfDescriptor->Binary)) | if (! pData->libOpen(fRdfDescriptor->Binary)) | ||||
| { | { | ||||
| pData->engine->setLastError(lib_error(fRdfDescriptor->Binary)); | |||||
| pData->engine->setLastError(pData->libError(fRdfDescriptor->Binary)); | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -6,55 +6,92 @@ | |||||
| include ../Makefile.mk | include ../Makefile.mk | ||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| CARLA_ENGINE_OSC_HPP = ../engine/CarlaEngineOsc.hpp $(CARLA_BACKEND_H) $(CARLA_OSC_UTILS_HPP) $(CARLA_STRING_HPP) | |||||
| CARLA_PLUGIN_THREAD_HPP = CarlaPluginThread.hpp $(CARLA_BACKEND_H) $(CARLA_THREAD_HPP) | |||||
| CARLA_PLUGIN_INTERNAL_HPP = CarlaPluginInternal.hpp $(CARLA_PLUGIN_HPP) $(CARLA_PLUGIN_THREAD_HPP) $(CARLA_OSC_UTILS_HPP) $(CARLA_STATE_UTILS_HPP) $(CARLA_MUTEX_HPP) $(RT_LINKED_LIST_HPP) $(CARLA_MIDI_H) | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| OBJS = \ | OBJS = \ | ||||
| CarlaPlugin.cpp.o \ | CarlaPlugin.cpp.o \ | ||||
| CarlaPluginInternal.cpp.o \ | CarlaPluginInternal.cpp.o \ | ||||
| CarlaPluginThread.cpp.o \ | CarlaPluginThread.cpp.o \ | ||||
| BridgePlugin.cpp.o \ | |||||
| NativePlugin.cpp.o \ | NativePlugin.cpp.o \ | ||||
| BridgePlugin.cpp.o \ | |||||
| LadspaPlugin.cpp.o \ | LadspaPlugin.cpp.o \ | ||||
| DssiPlugin.cpp.o \ | DssiPlugin.cpp.o \ | ||||
| Lv2Plugin.cpp.o \ | Lv2Plugin.cpp.o \ | ||||
| VstPlugin.cpp.o \ | VstPlugin.cpp.o \ | ||||
| AuPlugin.cpp.o \ | AuPlugin.cpp.o \ | ||||
| CsoundPlugin.cpp.o \ | CsoundPlugin.cpp.o \ | ||||
| JucePlugin.cpp.o \ | |||||
| FluidSynthPlugin.cpp.o \ | FluidSynthPlugin.cpp.o \ | ||||
| LinuxSamplerPlugin.cpp.o \ | |||||
| JucePlugin.cpp.o | |||||
| LinuxSamplerPlugin.cpp.o | |||||
| HEADERS = \ | |||||
| ../CarlaBackend.h ../CarlaEngine.hpp ../CarlaPlugin.hpp \ | |||||
| CarlaPluginInternal.hpp CarlaPluginThread.hpp | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| TARGET = ../carla_plugin.a | TARGET = ../carla_plugin.a | ||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| all: $(TARGET) | all: $(TARGET) | ||||
| # -------------------------------------------------------------- | |||||
| %.cpp.o: %.cpp $(HEADERS) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| clean: | |||||
| $(RM) *.o $(TARGET) | |||||
| FluidSynthPlugin.cpp.o: FluidSynthPlugin.cpp $(HEADERS) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(FLUIDSYNTH_FLAGS) -c -o $@ | |||||
| debug: | |||||
| $(MAKE) DEBUG=true | |||||
| LinuxSamplerPlugin.cpp.o: LinuxSamplerPlugin.cpp $(HEADERS) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(LINUXSAMPLER_FLAGS) -c -o $@ | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| $(TARGET): $(OBJS) | $(TARGET): $(OBJS) | ||||
| $(RM) $@ | $(RM) $@ | ||||
| $(AR) crs $@ $^ | $(AR) crs $@ $^ | ||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| clean: | |||||
| $(RM) *.o $(TARGET) | |||||
| CarlaPlugin.cpp.o: CarlaPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_BACKEND_UTILS_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) $(QTXML_FLAGS) -c -o $@ | |||||
| debug: | |||||
| $(MAKE) DEBUG=true | |||||
| CarlaPluginInternal.cpp.o: CarlaPluginInternal.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_LIB_COUNTER_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ | |||||
| CarlaPluginThread.cpp.o: CarlaPluginThread.cpp $(CARLA_PLUGIN_HPP) $(CARLA_PLUGIN_THREAD_HPP) $(CARLA_ENGINE_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ | |||||
| NativePlugin.cpp.o: NativePlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_NATIVE_H) $(CARLA_HOST_H) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ | |||||
| BridgePlugin.cpp.o: BridgePlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_BACKEND_UTILS_HPP) $(CARLA_BRIDGE_UTILS_HPP) $(CARLA_SHM_UTILS_HPP) $(JACK_BRIDGE_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| LadspaPlugin.cpp.o: LadspaPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_LADSPA_UTILS_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| DssiPlugin.cpp.o: DssiPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_DSSI_UTILS_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ # FIXME | |||||
| Lv2Plugin.cpp.o: Lv2Plugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_LV2_UTILS_HPP) $(LV2_ATOM_QUEUE_HPP) $(CARLA_ENGINE_OSC_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ # FIXME | |||||
| VstPlugin.cpp.o: VstPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_VST_UTILS_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| AuPlugin.cpp.o: AuPlugin.cpp $(CARLA_PLUGIN_HPP) $(CARLA_ENGINE_HPP) $(CARLA_UTILS_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| CsoundPlugin.cpp.o: CsoundPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| JucePlugin.cpp.o: JucePlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||||
| FluidSynthPlugin.cpp.o: FluidSynthPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(FLUIDSYNTH_FLAGS) $(QTCORE_FLAGS) -c -o $@ | |||||
| LinuxSamplerPlugin.cpp.o: LinuxSamplerPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_BACKEND_UTILS_HPP) | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(LINUXSAMPLER_FLAGS) $(QTCORE_FLAGS) -c -o $@ | |||||
| # -------------------------------------------------------------- | |||||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||||
| @@ -23,6 +23,8 @@ | |||||
| #include "CarlaNative.h" | #include "CarlaNative.h" | ||||
| #include "CarlaHost.h" | #include "CarlaHost.h" | ||||
| #include "CarlaMIDI.h" | |||||
| #include <QtCore/QStringList> | #include <QtCore/QStringList> | ||||
| extern const char* carla_file_callback(FileCallbackOpcode action, bool isDir, const char* title, const char* filter); | extern const char* carla_file_callback(FileCallbackOpcode action, bool isDir, const char* title, const char* filter); | ||||
| @@ -21,7 +21,6 @@ | |||||
| #ifdef WANT_VST | #ifdef WANT_VST | ||||
| #include "CarlaVstUtils.hpp" | #include "CarlaVstUtils.hpp" | ||||
| #include "CarlaLibUtils.hpp" | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| @@ -2157,7 +2156,7 @@ public: | |||||
| if (! pData->libOpen(filename)) | if (! pData->libOpen(filename)) | ||||
| { | { | ||||
| pData->engine->setLastError(lib_error(filename)); | |||||
| pData->engine->setLastError(pData->libError(filename)); | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -31,7 +31,7 @@ public: | |||||
| void* open(const char* const filename) | void* open(const char* const filename) | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(filename != nullptr, nullptr); | |||||
| CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); | |||||
| const CarlaMutex::ScopedLocker sl(fMutex); | const CarlaMutex::ScopedLocker sl(fMutex); | ||||
| @@ -0,0 +1,567 @@ | |||||
| /* | |||||
| * Carla State utils | |||||
| * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||||
| * | |||||
| * 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 doc/GPL.txt file. | |||||
| */ | |||||
| #include "CarlaStateUtils.hpp" | |||||
| #include "CarlaBackendUtils.hpp" | |||||
| #include "CarlaMIDI.h" | |||||
| #include <QtCore/QString> | |||||
| #include <QtXml/QDomNode> | |||||
| CARLA_BACKEND_START_NAMESPACE | |||||
| // ----------------------------------------------------------------------- | |||||
| // StateParameter | |||||
| StateParameter::StateParameter() noexcept | |||||
| : index(0), | |||||
| name(nullptr), | |||||
| symbol(nullptr), | |||||
| value(0.0f), | |||||
| midiChannel(0), | |||||
| midiCC(-1) {} | |||||
| StateParameter::~StateParameter() | |||||
| { | |||||
| if (name != nullptr) | |||||
| { | |||||
| delete[] name; | |||||
| name = nullptr; | |||||
| } | |||||
| if (symbol != nullptr) | |||||
| { | |||||
| delete[] symbol; | |||||
| symbol = nullptr; | |||||
| } | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| // StateCustomData | |||||
| StateCustomData::StateCustomData() noexcept | |||||
| : type(nullptr), | |||||
| key(nullptr), | |||||
| value(nullptr) {} | |||||
| StateCustomData::~StateCustomData() | |||||
| { | |||||
| if (type != nullptr) | |||||
| { | |||||
| delete[] type; | |||||
| type = nullptr; | |||||
| } | |||||
| if (key != nullptr) | |||||
| { | |||||
| delete[] key; | |||||
| key = nullptr; | |||||
| } | |||||
| if (value != nullptr) | |||||
| { | |||||
| delete[] value; | |||||
| value = nullptr; | |||||
| } | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| // SaveState | |||||
| SaveState::SaveState() noexcept | |||||
| : type(nullptr), | |||||
| name(nullptr), | |||||
| label(nullptr), | |||||
| binary(nullptr), | |||||
| uniqueID(0), | |||||
| active(false), | |||||
| dryWet(1.0f), | |||||
| volume(1.0f), | |||||
| balanceLeft(-1.0f), | |||||
| balanceRight(1.0f), | |||||
| panning(0.0f), | |||||
| ctrlChannel(-1), | |||||
| currentProgramIndex(-1), | |||||
| currentProgramName(nullptr), | |||||
| currentMidiBank(-1), | |||||
| currentMidiProgram(-1), | |||||
| chunk(nullptr) {} | |||||
| SaveState::~SaveState() | |||||
| { | |||||
| reset(); | |||||
| } | |||||
| void SaveState::reset() | |||||
| { | |||||
| if (type != nullptr) | |||||
| { | |||||
| delete[] type; | |||||
| type = nullptr; | |||||
| } | |||||
| if (name != nullptr) | |||||
| { | |||||
| delete[] name; | |||||
| name = nullptr; | |||||
| } | |||||
| if (label != nullptr) | |||||
| { | |||||
| delete[] label; | |||||
| label = nullptr; | |||||
| } | |||||
| if (binary != nullptr) | |||||
| { | |||||
| delete[] binary; | |||||
| binary = nullptr; | |||||
| } | |||||
| if (currentProgramName != nullptr) | |||||
| { | |||||
| delete[] currentProgramName; | |||||
| currentProgramName = nullptr; | |||||
| } | |||||
| if (chunk != nullptr) | |||||
| { | |||||
| delete[] chunk; | |||||
| chunk = nullptr; | |||||
| } | |||||
| uniqueID = 0; | |||||
| active = false; | |||||
| dryWet = 1.0f; | |||||
| volume = 1.0f; | |||||
| balanceLeft = -1.0f; | |||||
| balanceRight = 1.0f; | |||||
| panning = 0.0f; | |||||
| ctrlChannel = -1; | |||||
| currentProgramIndex = -1; | |||||
| currentMidiBank = -1; | |||||
| currentMidiProgram = -1; | |||||
| for (StateParameterItenerator it = parameters.begin(); it.valid(); it.next()) | |||||
| { | |||||
| StateParameter* const stateParameter(it.getValue()); | |||||
| delete stateParameter; | |||||
| } | |||||
| for (StateCustomDataItenerator it = customData.begin(); it.valid(); it.next()) | |||||
| { | |||||
| StateCustomData* const stateCustomData(it.getValue()); | |||||
| delete stateCustomData; | |||||
| } | |||||
| parameters.clear(); | |||||
| customData.clear(); | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| // xmlSafeString | |||||
| 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(""","\""); | |||||
| } | |||||
| const char* xmlSafeStringCharDup(const QString& string, const bool toXml) | |||||
| { | |||||
| return carla_strdup(xmlSafeString(string, toXml).toUtf8().constData()); | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| // fillSaveStateFromXmlNode | |||||
| void fillSaveStateFromXmlNode(SaveState& saveState, const QDomNode& xmlNode) | |||||
| { | |||||
| if (xmlNode.isNull()) | |||||
| return; | |||||
| for (QDomNode node = xmlNode.firstChild(); ! node.isNull(); node = node.nextSibling()) | |||||
| { | |||||
| QString tagName(node.toElement().tagName()); | |||||
| // --------------------------------------------------------------- | |||||
| // Info | |||||
| if (tagName.compare("info", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| for (QDomNode xmlInfo = node.toElement().firstChild(); ! xmlInfo.isNull(); xmlInfo = xmlInfo.nextSibling()) | |||||
| { | |||||
| const QString tag(xmlInfo.toElement().tagName()); | |||||
| const QString text(xmlInfo.toElement().text().trimmed()); | |||||
| if (tag.compare("type", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.type = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| else if (tag.compare("name", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.name = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| else if (tag.compare("label", Qt::CaseInsensitive) == 0 || tag.compare("uri", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.label = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| else if (tag.compare("binary", Qt::CaseInsensitive) == 0 || tag.compare("filename", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.binary = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| else if (tag.compare("uniqueid", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const long uniqueID(text.toLong(&ok)); | |||||
| if (ok) saveState.uniqueID = uniqueID; | |||||
| } | |||||
| } | |||||
| } | |||||
| // --------------------------------------------------------------- | |||||
| // Data | |||||
| else if (tagName.compare("data", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| for (QDomNode xmlData = node.toElement().firstChild(); ! xmlData.isNull(); xmlData = xmlData.nextSibling()) | |||||
| { | |||||
| const QString tag(xmlData.toElement().tagName()); | |||||
| const QString text(xmlData.toElement().text().trimmed()); | |||||
| // ------------------------------------------------------- | |||||
| // Internal Data | |||||
| if (tag.compare("active", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.active = (text.compare("yes", Qt::CaseInsensitive) == 0 || text.compare("true", Qt::CaseInsensitive) == 0); | |||||
| } | |||||
| else if (tag.compare("drywet", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.dryWet = carla_fixValue(0.0f, 1.0f, value); | |||||
| } | |||||
| else if (tag.compare("volume", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.volume = carla_fixValue(0.0f, 1.27f, value); | |||||
| } | |||||
| else if (tag.compare("balanceleft", Qt::CaseInsensitive) == 0 || tag.compare("balance-left", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.balanceLeft = carla_fixValue(-1.0f, 1.0f, value); | |||||
| } | |||||
| else if (tag.compare("balanceright", Qt::CaseInsensitive) == 0 || tag.compare("balance-right", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.balanceRight = carla_fixValue(-1.0f, 1.0f, value); | |||||
| } | |||||
| else if (tag.compare("panning", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.panning = carla_fixValue(-1.0f, 1.0f, value); | |||||
| } | |||||
| else if (tag.compare("controlchannel", Qt::CaseInsensitive) == 0 || tag.compare("control-channel", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const short value(text.toShort(&ok)); | |||||
| if (ok && value >= 1 && value < MAX_MIDI_CHANNELS) | |||||
| saveState.ctrlChannel = static_cast<int8_t>(value-1); | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Program (current) | |||||
| else if (tag.compare("currentprogramindex", Qt::CaseInsensitive) == 0 || tag.compare("current-program-index", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const int value(text.toInt(&ok)); | |||||
| if (ok && value >= 1) | |||||
| saveState.currentProgramIndex = value-1; | |||||
| } | |||||
| else if (tag.compare("currentprogramname", Qt::CaseInsensitive) == 0 || tag.compare("current-program-name", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.currentProgramName = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Midi Program (current) | |||||
| else if (tag.compare("currentmidibank", Qt::CaseInsensitive) == 0 || tag.compare("current-midi-bank", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const int value(text.toInt(&ok)); | |||||
| if (ok && value >= 1) | |||||
| saveState.currentMidiBank = value-1; | |||||
| } | |||||
| else if (tag.compare("currentmidiprogram", Qt::CaseInsensitive) == 0 || tag.compare("current-midi-program", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const int value(text.toInt(&ok)); | |||||
| if (ok && value >= 1) | |||||
| saveState.currentMidiProgram = value-1; | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Parameters | |||||
| else if (tag.compare("parameter", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| StateParameter* const stateParameter(new StateParameter()); | |||||
| for (QDomNode xmlSubData = xmlData.toElement().firstChild(); ! xmlSubData.isNull(); xmlSubData = xmlSubData.nextSibling()) | |||||
| { | |||||
| const QString pTag(xmlSubData.toElement().tagName()); | |||||
| const QString pText(xmlSubData.toElement().text().trimmed()); | |||||
| if (pTag.compare("index", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const uint index(pText.toUInt(&ok)); | |||||
| if (ok) stateParameter->index = index; | |||||
| } | |||||
| else if (pTag.compare("name", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| stateParameter->name = xmlSafeStringCharDup(pText, false); | |||||
| } | |||||
| else if (pTag.compare("symbol", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| stateParameter->symbol = xmlSafeStringCharDup(pText, false); | |||||
| } | |||||
| else if (pTag.compare("value", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(pText.toFloat(&ok)); | |||||
| if (ok) stateParameter->value = value; | |||||
| } | |||||
| else if (pTag.compare("midichannel", Qt::CaseInsensitive) == 0 || pTag.compare("midi-channel", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const ushort channel(pText.toUShort(&ok)); | |||||
| if (ok && channel >= 1 && channel < MAX_MIDI_CHANNELS) | |||||
| stateParameter->midiChannel = static_cast<uint8_t>(channel-1); | |||||
| } | |||||
| else if (pTag.compare("midicc", Qt::CaseInsensitive) == 0 || pTag.compare("midi-cc", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const int cc(pText.toInt(&ok)); | |||||
| if (ok && cc >= 1 && cc < 0x5F) | |||||
| stateParameter->midiCC = static_cast<int16_t>(cc); | |||||
| } | |||||
| } | |||||
| saveState.parameters.append(stateParameter); | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Custom Data | |||||
| else if (tag.compare("customdata", Qt::CaseInsensitive) == 0 || tag.compare("custom-data", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| StateCustomData* const stateCustomData(new StateCustomData()); | |||||
| for (QDomNode xmlSubData = xmlData.toElement().firstChild(); ! xmlSubData.isNull(); xmlSubData = xmlSubData.nextSibling()) | |||||
| { | |||||
| const QString cTag(xmlSubData.toElement().tagName()); | |||||
| const QString cText(xmlSubData.toElement().text().trimmed()); | |||||
| if (cTag.compare("type", Qt::CaseInsensitive) == 0) | |||||
| stateCustomData->type = xmlSafeStringCharDup(cText, false); | |||||
| else if (cTag.compare("key", Qt::CaseInsensitive) == 0) | |||||
| stateCustomData->key = xmlSafeStringCharDup(cText, false); | |||||
| else if (cTag.compare("value", Qt::CaseInsensitive) == 0) | |||||
| stateCustomData->value = xmlSafeStringCharDup(cText, false); | |||||
| } | |||||
| saveState.customData.append(stateCustomData); | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Chunk | |||||
| else if (tag.compare("chunk", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.chunk = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| // fillXmlStringFromSaveState | |||||
| void fillXmlStringFromSaveState(QString& content, const SaveState& saveState) | |||||
| { | |||||
| { | |||||
| QString info(" <Info>\n"); | |||||
| 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_AU: | |||||
| // TODO? | |||||
| info += QString(" <Binary>%1</Binary>\n").arg(xmlSafeString(saveState.binary, true)); | |||||
| info += QString(" <UniqueID>%1</UniqueID>\n").arg(saveState.uniqueID); | |||||
| break; | |||||
| case PLUGIN_FILE_CSD: | |||||
| case PLUGIN_FILE_GIG: | |||||
| case PLUGIN_FILE_SF2: | |||||
| case PLUGIN_FILE_SFZ: | |||||
| info += QString(" <Filename>%1</Filename>\n").arg(xmlSafeString(saveState.binary, true)); | |||||
| info += QString(" <Label>%1</Label>\n").arg(xmlSafeString(saveState.label, 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); | |||||
| if (saveState.ctrlChannel < 0) | |||||
| data += QString(" <ControlChannel>N</ControlChannel>\n"); | |||||
| else | |||||
| data += QString(" <ControlChannel>%1</ControlChannel>\n").arg(saveState.ctrlChannel+1); | |||||
| content += data; | |||||
| } | |||||
| for (StateParameterItenerator it = saveState.parameters.begin(); it.valid(); it.next()) | |||||
| { | |||||
| StateParameter* const stateParameter(it.getValue()); | |||||
| 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] != '\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+1); | |||||
| } | |||||
| parameter += " </Parameter>\n"; | |||||
| content += parameter; | |||||
| } | |||||
| if (saveState.currentProgramIndex >= 0 && saveState.currentProgramName != nullptr && saveState.currentProgramName[0] != '\0') | |||||
| { | |||||
| // ignore 'default' program | |||||
| if (saveState.currentProgramIndex > 0 || QString(saveState.currentProgramName).compare("default", Qt::CaseInsensitive) != 0) | |||||
| { | |||||
| QString program("\n"); | |||||
| program += QString(" <CurrentProgramIndex>%1</CurrentProgramIndex>\n").arg(saveState.currentProgramIndex+1); | |||||
| 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+1); | |||||
| midiProgram += QString(" <CurrentMidiProgram>%1</CurrentMidiProgram>\n").arg(saveState.currentMidiProgram+1); | |||||
| content += midiProgram; | |||||
| } | |||||
| for (StateCustomDataItenerator it = saveState.customData.begin(); it.valid(); it.next()) | |||||
| { | |||||
| StateCustomData* const stateCustomData(it.getValue()); | |||||
| 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_TYPE_CHUNK) == 0 || std::strlen(stateCustomData->value) >= 128) | |||||
| { | |||||
| 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] != '\0') | |||||
| { | |||||
| QString chunk("\n"" <Chunk>\n"); | |||||
| chunk += QString("%1\n").arg(saveState.chunk); | |||||
| chunk += " </Chunk>\n"; | |||||
| content += chunk; | |||||
| } | |||||
| content += " </Data>\n"; | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| CARLA_BACKEND_END_NAMESPACE | |||||
| @@ -18,14 +18,19 @@ | |||||
| #ifndef CARLA_STATE_UTILS_HPP_INCLUDED | #ifndef CARLA_STATE_UTILS_HPP_INCLUDED | ||||
| #define CARLA_STATE_UTILS_HPP_INCLUDED | #define CARLA_STATE_UTILS_HPP_INCLUDED | ||||
| #include "CarlaBackendUtils.hpp" | |||||
| #include "CarlaMIDI.h" | |||||
| #include "LinkedList.hpp" | #include "LinkedList.hpp" | ||||
| #include <QtXml/QDomNode> | |||||
| class QDomNode; | |||||
| class QString; | |||||
| // ----------------------------------------------------------------------- | |||||
| CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
| #if 0 | |||||
| } // Fix editor indentation | |||||
| #endif | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| struct StateParameter { | struct StateParameter { | ||||
| @@ -36,27 +41,8 @@ struct StateParameter { | |||||
| uint8_t midiChannel; | uint8_t midiChannel; | ||||
| int16_t midiCC; | int16_t midiCC; | ||||
| StateParameter() noexcept | |||||
| : index(0), | |||||
| name(nullptr), | |||||
| symbol(nullptr), | |||||
| value(0.0f), | |||||
| midiChannel(0), | |||||
| midiCC(-1) {} | |||||
| ~StateParameter() | |||||
| { | |||||
| if (name != nullptr) | |||||
| { | |||||
| delete[] name; | |||||
| name = nullptr; | |||||
| } | |||||
| if (symbol != nullptr) | |||||
| { | |||||
| delete[] symbol; | |||||
| symbol = nullptr; | |||||
| } | |||||
| } | |||||
| StateParameter() noexcept; | |||||
| ~StateParameter(); | |||||
| CARLA_DECLARE_NON_COPY_STRUCT(StateParameter) | CARLA_DECLARE_NON_COPY_STRUCT(StateParameter) | ||||
| }; | }; | ||||
| @@ -66,29 +52,8 @@ struct StateCustomData { | |||||
| const char* key; | const char* key; | ||||
| const char* value; | const char* value; | ||||
| StateCustomData() noexcept | |||||
| : type(nullptr), | |||||
| key(nullptr), | |||||
| value(nullptr) {} | |||||
| ~StateCustomData() | |||||
| { | |||||
| if (type != nullptr) | |||||
| { | |||||
| delete[] type; | |||||
| type = nullptr; | |||||
| } | |||||
| if (key != nullptr) | |||||
| { | |||||
| delete[] key; | |||||
| key = nullptr; | |||||
| } | |||||
| if (value != nullptr) | |||||
| { | |||||
| delete[] value; | |||||
| value = nullptr; | |||||
| } | |||||
| } | |||||
| StateCustomData() noexcept; | |||||
| ~StateCustomData(); | |||||
| CARLA_DECLARE_NON_COPY_STRUCT(StateCustomData) | CARLA_DECLARE_NON_COPY_STRUCT(StateCustomData) | ||||
| }; | }; | ||||
| @@ -123,491 +88,17 @@ struct SaveState { | |||||
| StateParameterList parameters; | StateParameterList parameters; | ||||
| StateCustomDataList customData; | StateCustomDataList customData; | ||||
| SaveState() noexcept | |||||
| : type(nullptr), | |||||
| name(nullptr), | |||||
| label(nullptr), | |||||
| binary(nullptr), | |||||
| uniqueID(0), | |||||
| active(false), | |||||
| dryWet(1.0f), | |||||
| volume(1.0f), | |||||
| balanceLeft(-1.0f), | |||||
| balanceRight(1.0f), | |||||
| panning(0.0f), | |||||
| ctrlChannel(-1), | |||||
| currentProgramIndex(-1), | |||||
| currentProgramName(nullptr), | |||||
| currentMidiBank(-1), | |||||
| currentMidiProgram(-1), | |||||
| chunk(nullptr) {} | |||||
| ~SaveState() | |||||
| { | |||||
| reset(); | |||||
| } | |||||
| void reset() | |||||
| { | |||||
| if (type != nullptr) | |||||
| { | |||||
| delete[] type; | |||||
| type = nullptr; | |||||
| } | |||||
| if (name != nullptr) | |||||
| { | |||||
| delete[] name; | |||||
| name = nullptr; | |||||
| } | |||||
| if (label != nullptr) | |||||
| { | |||||
| delete[] label; | |||||
| label = nullptr; | |||||
| } | |||||
| if (binary != nullptr) | |||||
| { | |||||
| delete[] binary; | |||||
| binary = nullptr; | |||||
| } | |||||
| if (currentProgramName != nullptr) | |||||
| { | |||||
| delete[] currentProgramName; | |||||
| currentProgramName = nullptr; | |||||
| } | |||||
| if (chunk != nullptr) | |||||
| { | |||||
| delete[] chunk; | |||||
| chunk = nullptr; | |||||
| } | |||||
| uniqueID = 0; | |||||
| active = false; | |||||
| dryWet = 1.0f; | |||||
| volume = 1.0f; | |||||
| balanceLeft = -1.0f; | |||||
| balanceRight = 1.0f; | |||||
| panning = 0.0f; | |||||
| ctrlChannel = -1; | |||||
| currentProgramIndex = -1; | |||||
| currentMidiBank = -1; | |||||
| currentMidiProgram = -1; | |||||
| for (StateParameterItenerator it = parameters.begin(); it.valid(); it.next()) | |||||
| { | |||||
| StateParameter* const stateParameter(it.getValue()); | |||||
| delete stateParameter; | |||||
| } | |||||
| for (StateCustomDataItenerator it = customData.begin(); it.valid(); it.next()) | |||||
| { | |||||
| StateCustomData* const stateCustomData(it.getValue()); | |||||
| delete stateCustomData; | |||||
| } | |||||
| parameters.clear(); | |||||
| customData.clear(); | |||||
| } | |||||
| SaveState() noexcept; | |||||
| ~SaveState(); | |||||
| void reset(); | |||||
| CARLA_DECLARE_NON_COPY_STRUCT(SaveState) | CARLA_DECLARE_NON_COPY_STRUCT(SaveState) | ||||
| }; | }; | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| 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* xmlSafeStringCharDup(const QString& string, const bool toXml) | |||||
| { | |||||
| return carla_strdup(xmlSafeString(string, toXml).toUtf8().constData()); | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| static inline | |||||
| void fillSaveStateFromXmlNode(SaveState& saveState, const QDomNode& xmlNode) | |||||
| { | |||||
| if (xmlNode.isNull()) | |||||
| return; | |||||
| for (QDomNode node = xmlNode.firstChild(); ! node.isNull(); node = node.nextSibling()) | |||||
| { | |||||
| QString tagName(node.toElement().tagName()); | |||||
| // --------------------------------------------------------------- | |||||
| // Info | |||||
| if (tagName.compare("info", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| for (QDomNode xmlInfo = node.toElement().firstChild(); ! xmlInfo.isNull(); xmlInfo = xmlInfo.nextSibling()) | |||||
| { | |||||
| const QString tag(xmlInfo.toElement().tagName()); | |||||
| const QString text(xmlInfo.toElement().text().trimmed()); | |||||
| if (tag.compare("type", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.type = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| else if (tag.compare("name", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.name = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| else if (tag.compare("label", Qt::CaseInsensitive) == 0 || tag.compare("uri", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.label = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| else if (tag.compare("binary", Qt::CaseInsensitive) == 0 || tag.compare("filename", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.binary = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| else if (tag.compare("uniqueid", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const long uniqueID(text.toLong(&ok)); | |||||
| if (ok) saveState.uniqueID = uniqueID; | |||||
| } | |||||
| } | |||||
| } | |||||
| // --------------------------------------------------------------- | |||||
| // Data | |||||
| else if (tagName.compare("data", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| for (QDomNode xmlData = node.toElement().firstChild(); ! xmlData.isNull(); xmlData = xmlData.nextSibling()) | |||||
| { | |||||
| const QString tag(xmlData.toElement().tagName()); | |||||
| const QString text(xmlData.toElement().text().trimmed()); | |||||
| // ------------------------------------------------------- | |||||
| // Internal Data | |||||
| if (tag.compare("active", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.active = (text.compare("yes", Qt::CaseInsensitive) == 0 || text.compare("true", Qt::CaseInsensitive) == 0); | |||||
| } | |||||
| else if (tag.compare("drywet", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.dryWet = carla_fixValue(0.0f, 1.0f, value); | |||||
| } | |||||
| else if (tag.compare("volume", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.volume = carla_fixValue(0.0f, 1.27f, value); | |||||
| } | |||||
| else if (tag.compare("balanceleft", Qt::CaseInsensitive) == 0 || tag.compare("balance-left", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.balanceLeft = carla_fixValue(-1.0f, 1.0f, value); | |||||
| } | |||||
| else if (tag.compare("balanceright", Qt::CaseInsensitive) == 0 || tag.compare("balance-right", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.balanceRight = carla_fixValue(-1.0f, 1.0f, value); | |||||
| } | |||||
| else if (tag.compare("panning", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(text.toFloat(&ok)); | |||||
| if (ok) saveState.panning = carla_fixValue(-1.0f, 1.0f, value); | |||||
| } | |||||
| else if (tag.compare("controlchannel", Qt::CaseInsensitive) == 0 || tag.compare("control-channel", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const short value(text.toShort(&ok)); | |||||
| if (ok && value >= 1 && value < MAX_MIDI_CHANNELS) | |||||
| saveState.ctrlChannel = static_cast<int8_t>(value-1); | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Program (current) | |||||
| else if (tag.compare("currentprogramindex", Qt::CaseInsensitive) == 0 || tag.compare("current-program-index", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const int value(text.toInt(&ok)); | |||||
| if (ok && value >= 1) | |||||
| saveState.currentProgramIndex = value-1; | |||||
| } | |||||
| else if (tag.compare("currentprogramname", Qt::CaseInsensitive) == 0 || tag.compare("current-program-name", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.currentProgramName = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Midi Program (current) | |||||
| else if (tag.compare("currentmidibank", Qt::CaseInsensitive) == 0 || tag.compare("current-midi-bank", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const int value(text.toInt(&ok)); | |||||
| if (ok && value >= 1) | |||||
| saveState.currentMidiBank = value-1; | |||||
| } | |||||
| else if (tag.compare("currentmidiprogram", Qt::CaseInsensitive) == 0 || tag.compare("current-midi-program", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const int value(text.toInt(&ok)); | |||||
| if (ok && value >= 1) | |||||
| saveState.currentMidiProgram = value-1; | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Parameters | |||||
| else if (tag.compare("parameter", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| StateParameter* const stateParameter(new StateParameter()); | |||||
| for (QDomNode xmlSubData = xmlData.toElement().firstChild(); ! xmlSubData.isNull(); xmlSubData = xmlSubData.nextSibling()) | |||||
| { | |||||
| const QString pTag(xmlSubData.toElement().tagName()); | |||||
| const QString pText(xmlSubData.toElement().text().trimmed()); | |||||
| if (pTag.compare("index", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const uint index(pText.toUInt(&ok)); | |||||
| if (ok) stateParameter->index = index; | |||||
| } | |||||
| else if (pTag.compare("name", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| stateParameter->name = xmlSafeStringCharDup(pText, false); | |||||
| } | |||||
| else if (pTag.compare("symbol", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| stateParameter->symbol = xmlSafeStringCharDup(pText, false); | |||||
| } | |||||
| else if (pTag.compare("value", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const float value(pText.toFloat(&ok)); | |||||
| if (ok) stateParameter->value = value; | |||||
| } | |||||
| else if (pTag.compare("midichannel", Qt::CaseInsensitive) == 0 || pTag.compare("midi-channel", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const ushort channel(pText.toUShort(&ok)); | |||||
| if (ok && channel >= 1 && channel < MAX_MIDI_CHANNELS) | |||||
| stateParameter->midiChannel = static_cast<uint8_t>(channel-1); | |||||
| } | |||||
| else if (pTag.compare("midicc", Qt::CaseInsensitive) == 0 || pTag.compare("midi-cc", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| bool ok; | |||||
| const int cc(pText.toInt(&ok)); | |||||
| if (ok && cc >= 1 && cc < 0x5F) | |||||
| stateParameter->midiCC = static_cast<int16_t>(cc); | |||||
| } | |||||
| } | |||||
| saveState.parameters.append(stateParameter); | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Custom Data | |||||
| else if (tag.compare("customdata", Qt::CaseInsensitive) == 0 || tag.compare("custom-data", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| StateCustomData* const stateCustomData(new StateCustomData()); | |||||
| for (QDomNode xmlSubData = xmlData.toElement().firstChild(); ! xmlSubData.isNull(); xmlSubData = xmlSubData.nextSibling()) | |||||
| { | |||||
| const QString cTag(xmlSubData.toElement().tagName()); | |||||
| const QString cText(xmlSubData.toElement().text().trimmed()); | |||||
| if (cTag.compare("type", Qt::CaseInsensitive) == 0) | |||||
| stateCustomData->type = xmlSafeStringCharDup(cText, false); | |||||
| else if (cTag.compare("key", Qt::CaseInsensitive) == 0) | |||||
| stateCustomData->key = xmlSafeStringCharDup(cText, false); | |||||
| else if (cTag.compare("value", Qt::CaseInsensitive) == 0) | |||||
| stateCustomData->value = xmlSafeStringCharDup(cText, false); | |||||
| } | |||||
| saveState.customData.append(stateCustomData); | |||||
| } | |||||
| // ------------------------------------------------------- | |||||
| // Chunk | |||||
| else if (tag.compare("chunk", Qt::CaseInsensitive) == 0) | |||||
| { | |||||
| saveState.chunk = xmlSafeStringCharDup(text, false); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| static inline | |||||
| void fillXmlStringFromSaveState(QString& content, const SaveState& saveState) | |||||
| { | |||||
| { | |||||
| QString info(" <Info>\n"); | |||||
| 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_AU: | |||||
| // TODO? | |||||
| info += QString(" <Binary>%1</Binary>\n").arg(xmlSafeString(saveState.binary, true)); | |||||
| info += QString(" <UniqueID>%1</UniqueID>\n").arg(saveState.uniqueID); | |||||
| break; | |||||
| case PLUGIN_FILE_CSD: | |||||
| case PLUGIN_FILE_GIG: | |||||
| case PLUGIN_FILE_SF2: | |||||
| case PLUGIN_FILE_SFZ: | |||||
| info += QString(" <Filename>%1</Filename>\n").arg(xmlSafeString(saveState.binary, true)); | |||||
| info += QString(" <Label>%1</Label>\n").arg(xmlSafeString(saveState.label, 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); | |||||
| if (saveState.ctrlChannel < 0) | |||||
| data += QString(" <ControlChannel>N</ControlChannel>\n"); | |||||
| else | |||||
| data += QString(" <ControlChannel>%1</ControlChannel>\n").arg(saveState.ctrlChannel+1); | |||||
| content += data; | |||||
| } | |||||
| for (StateParameterItenerator it = saveState.parameters.begin(); it.valid(); it.next()) | |||||
| { | |||||
| StateParameter* const stateParameter(it.getValue()); | |||||
| 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] != '\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+1); | |||||
| } | |||||
| parameter += " </Parameter>\n"; | |||||
| content += parameter; | |||||
| } | |||||
| if (saveState.currentProgramIndex >= 0 && saveState.currentProgramName != nullptr && saveState.currentProgramName[0] != '\0') | |||||
| { | |||||
| // ignore 'default' program | |||||
| if (saveState.currentProgramIndex > 0 || QString(saveState.currentProgramName).compare("default", Qt::CaseInsensitive) != 0) | |||||
| { | |||||
| QString program("\n"); | |||||
| program += QString(" <CurrentProgramIndex>%1</CurrentProgramIndex>\n").arg(saveState.currentProgramIndex+1); | |||||
| 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+1); | |||||
| midiProgram += QString(" <CurrentMidiProgram>%1</CurrentMidiProgram>\n").arg(saveState.currentMidiProgram+1); | |||||
| content += midiProgram; | |||||
| } | |||||
| for (StateCustomDataItenerator it = saveState.customData.begin(); it.valid(); it.next()) | |||||
| { | |||||
| StateCustomData* const stateCustomData(it.getValue()); | |||||
| 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_TYPE_CHUNK) == 0 || std::strlen(stateCustomData->value) >= 128) | |||||
| { | |||||
| 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] != '\0') | |||||
| { | |||||
| QString chunk("\n"" <Chunk>\n"); | |||||
| chunk += QString("%1\n").arg(saveState.chunk); | |||||
| chunk += " </Chunk>\n"; | |||||
| content += chunk; | |||||
| } | |||||
| content += " </Data>\n"; | |||||
| } | |||||
| void fillSaveStateFromXmlNode(SaveState& saveState, const QDomNode& xmlNode); | |||||
| void fillXmlStringFromSaveState(QString& content, const SaveState& saveState); | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||