| 
							- /*
 -  * Carla Plugin Engine (Native)
 -  * Copyright (C) 2013 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.
 -  */
 - 
 - #ifndef BUILD_BRIDGE
 - 
 - #include "CarlaEngineInternal.hpp"
 - #include "CarlaStateUtils.hpp"
 - 
 - #include "carla_native/CarlaNative.hpp"
 - 
 - #include <QtCore/QProcess>
 - #include <QtCore/QTextStream>
 - #include <QtCore/QThread>
 - 
 - CARLA_BACKEND_START_NAMESPACE
 - 
 - // -----------------------------------------------------------------------
 - 
 - class CarlaEngineNativeThread : public QThread
 - {
 - public:
 -     enum UiState {
 -         UiNone = 0,
 -         UiHide,
 -         UiShow,
 -         UiCrashed
 -     };
 - 
 -     CarlaEngineNativeThread(CarlaEngine* const engine)
 -         : kEngine(engine),
 -           fBinary("carla-control"),
 -           fProcess(nullptr),
 -           fUiState(UiNone)
 -     {
 -         carla_debug("CarlaEngineNativeThread::CarlaEngineNativeThread(engine:\"%s\")", engine->getName());
 -     }
 - 
 -     ~CarlaEngineNativeThread()
 -     {
 -         CARLA_ASSERT_INT(fUiState == UiNone, fUiState);
 -         carla_debug("CarlaEngineNativeThread::~CarlaEngineNativeThread()");
 - 
 -         if (fProcess != nullptr)
 -         {
 -             delete fProcess;
 -             fProcess = nullptr;
 -         }
 -     }
 - 
 -     void setOscData(const char* const binary)
 -     {
 -         fBinary = binary;
 -     }
 - 
 -     UiState getUiState()
 -     {
 -         const UiState state(fUiState);
 -         fUiState = UiNone;
 - 
 -         return state;
 -     }
 - 
 -     void stop()
 -     {
 -         if (fProcess == nullptr)
 -             return;
 - 
 -         fUiState = UiNone;
 -         fProcess->kill();
 -         //fProcess->close();
 -     }
 - 
 - protected:
 -     void run()
 -     {
 -         carla_debug("CarlaEngineNativeThread::run() - binary:\"%s\"", (const char*)fBinary);
 - 
 -         if (fProcess == nullptr)
 -         {
 -             fProcess = new QProcess(nullptr);
 -             fProcess->setProcessChannelMode(QProcess::ForwardedChannels);
 -         }
 -         else if (fProcess->state() == QProcess::Running)
 -         {
 -             carla_stderr("CarlaEngineNativeThread::run() - already running, giving up...");
 - 
 -             fUiState = UiCrashed;
 -             fProcess->terminate();
 -             //kEngine->callback(CarlaBackend::CALLBACK_SHOW_GUI, kPlugin->id(), -1, 0, 0.0f, nullptr);
 -             // TODO: tell master to hide UI
 -             return;
 -         }
 - 
 -         QStringList arguments;
 -         arguments << kEngine->getOscServerPathTCP();
 - 
 -         fProcess->start((const char*)fBinary, arguments);
 -         fProcess->waitForStarted();
 - 
 -         fUiState = UiShow;
 - 
 -         fProcess->waitForFinished(-1);
 - 
 -         if (fProcess->exitCode() == 0)
 -         {
 -             // Hide
 -             fUiState = UiHide;
 -             carla_stdout("CarlaEngineNativeThread::run() - GUI closed");
 -         }
 -         else
 -         {
 -             // Kill
 -             fUiState = UiCrashed;
 -             carla_stderr("CarlaEngineNativeThread::run() - GUI crashed while running");
 -         }
 -     }
 - 
 - private:
 -     CarlaEngine* const kEngine;
 - 
 -     CarlaString fBinary;
 -     QProcess*   fProcess;
 - 
 -     UiState fUiState;
 - 
 -     CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNativeThread)
 - };
 - 
 - // -----------------------------------------------------------------------
 - 
 - class CarlaEngineNative : public PluginClass,
 -                           public CarlaEngine
 - {
 - public:
 -     CarlaEngineNative(const HostDescriptor* const host)
 -         : PluginClass(host),
 -           CarlaEngine(),
 -           fIsRunning(true),
 -           fThread(this)
 -     {
 -         carla_debug("CarlaEngineNative::CarlaEngineNative()");
 - 
 -         // set-up engine
 -         fOptions.processMode   = PROCESS_MODE_CONTINUOUS_RACK;
 -         fOptions.transportMode = TRANSPORT_MODE_PLUGIN;
 -         fOptions.forceStereo   = true;
 -         fOptions.preferPluginBridges = false;
 -         fOptions.preferUiBridges = false;
 -         init("Carla-Plugin");
 - 
 -         // set control thread binary
 -         CarlaString threadBinary(getResourceDir());
 -         threadBinary += "/../";
 -         threadBinary += "carla_control.py";
 - 
 -         fThread.setOscData(threadBinary);
 - 
 -         // TESTING
 - //         if (! addPlugin(PLUGIN_INTERNAL, nullptr, "MIDI Transpose", "midiTranspose"))
 - //             carla_stdout("TESTING PLUG1 ERROR:\n%s", getLastError());
 - //         if (! addPlugin(PLUGIN_INTERNAL, nullptr, "ZynAddSubFX", "zynaddsubfx"))
 - //             carla_stdout("TESTING PLUG2 ERROR:\n%s", getLastError());
 - //         if (! addPlugin(PLUGIN_INTERNAL, nullptr, "Ping Pong Pan", "PingPongPan"))
 - //             carla_stdout("TESTING PLUG3 ERROR:\n%s", getLastError());
 -     }
 - 
 -     ~CarlaEngineNative() override
 -     {
 -         carla_debug("CarlaEngineNative::~CarlaEngineNative()");
 - 
 -         fIsRunning = false;
 - 
 -         setAboutToClose();
 -         removeAllPlugins();
 -         close();
 -     }
 - 
 - protected:
 -     // -------------------------------------
 -     // CarlaEngine virtual calls
 - 
 -     bool init(const char* const clientName) override
 -     {
 -         carla_debug("CarlaEngineNative::init(\"%s\")", clientName);
 - 
 -         fBufferSize = PluginClass::getBufferSize();
 -         fSampleRate = PluginClass::getSampleRate();
 - 
 -         CarlaEngine::init(clientName);
 -         return true;
 -     }
 - 
 -     bool close() override
 -     {
 -         carla_debug("CarlaEngineNative::close()");
 - 
 -         runPendingRtEvents();
 -         return CarlaEngine::close();
 -     }
 - 
 -     bool isRunning() const noexcept override
 -     {
 -         return fIsRunning;
 -     }
 - 
 -     bool isOffline() const noexcept override
 -     {
 -         return false;
 -     }
 - 
 -     EngineType getType() const noexcept override
 -     {
 -         return kEngineTypePlugin;
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin parameter calls
 - 
 -     uint32_t getParameterCount() const override
 -     {
 -         if (pData->curPluginCount == 0 || pData->plugins == nullptr)
 -             return 0;
 - 
 -         CarlaPlugin* const plugin(pData->plugins[0].plugin);
 - 
 -         if (plugin == nullptr || ! plugin->isEnabled())
 -             return 0;
 - 
 -         return pData->plugins[0].plugin->getParameterCount();
 -     }
 - 
 -     const Parameter* getParameterInfo(const uint32_t index) const override
 -     {
 -         if (index >= getParameterCount())
 -             return nullptr;
 - 
 -         CarlaPlugin* const plugin(pData->plugins[0].plugin);
 - 
 -         if (plugin == nullptr || ! plugin->isEnabled())
 -             return nullptr;
 - 
 -         static ::Parameter param;
 -         static char strBufName[STR_MAX+1];
 -         static char strBufUnit[STR_MAX+1];
 - 
 -         const ParameterData& paramData(plugin->getParameterData(index));
 -         const ParameterRanges& paramRanges(plugin->getParameterRanges(index));
 - 
 -         plugin->getParameterName(index, strBufName);
 -         plugin->getParameterUnit(index, strBufUnit);
 - 
 -         unsigned int hints = 0x0;
 - 
 -         if (paramData.hints & PARAMETER_IS_BOOLEAN)
 -             hints |= ::PARAMETER_IS_BOOLEAN;
 -         if (paramData.hints & PARAMETER_IS_INTEGER)
 -             hints |= ::PARAMETER_IS_INTEGER;
 -         if (paramData.hints & PARAMETER_IS_LOGARITHMIC)
 -             hints |= ::PARAMETER_IS_LOGARITHMIC;
 -         if (paramData.hints & PARAMETER_IS_AUTOMABLE)
 -             hints |= ::PARAMETER_IS_AUTOMABLE;
 -         if (paramData.hints & PARAMETER_USES_SAMPLERATE)
 -             hints |= ::PARAMETER_USES_SAMPLE_RATE;
 -         if (paramData.hints & PARAMETER_USES_SCALEPOINTS)
 -             hints |= ::PARAMETER_USES_SCALEPOINTS;
 -         if (paramData.hints & PARAMETER_USES_CUSTOM_TEXT)
 -             hints |= ::PARAMETER_USES_CUSTOM_TEXT;
 - 
 -         if (paramData.type == PARAMETER_INPUT || paramData.type == PARAMETER_OUTPUT)
 -         {
 -             if (paramData.hints & PARAMETER_IS_ENABLED)
 -                 hints |= ::PARAMETER_IS_ENABLED;
 -             if (paramData.type == PARAMETER_OUTPUT)
 -                 hints |= ::PARAMETER_IS_OUTPUT;
 -         }
 - 
 -         param.hints = static_cast< ::ParameterHints>(hints);
 -         param.name  = strBufName;
 -         param.unit  = strBufUnit;
 -         param.ranges.def = paramRanges.def;
 -         param.ranges.min = paramRanges.min;
 -         param.ranges.max = paramRanges.max;
 -         param.ranges.step = paramRanges.step;
 -         param.ranges.stepSmall = paramRanges.stepSmall;
 -         param.ranges.stepLarge = paramRanges.stepLarge;
 -         param.scalePointCount = 0; // TODO
 -         param.scalePoints = nullptr;
 - 
 -         return ¶m;
 -     }
 - 
 -     float getParameterValue(const uint32_t index) const override
 -     {
 -         if (index >= getParameterCount())
 -             return 0.0f;
 - 
 -         CarlaPlugin* const plugin(pData->plugins[0].plugin);
 - 
 -         if (plugin == nullptr || ! plugin->isEnabled())
 -             return 0.0f;
 - 
 -         return plugin->getParameterValue(index);
 -     }
 - 
 -     const char* getParameterText(const uint32_t index, const float value) const override // FIXME - use value
 -     {
 -         if (index >= getParameterCount())
 -             return nullptr;
 - 
 -         CarlaPlugin* const plugin(pData->plugins[0].plugin);
 - 
 -         if (plugin == nullptr || ! plugin->isEnabled())
 -             return nullptr;
 - 
 -         static char strBuf[STR_MAX+1];
 - 
 -         plugin->getParameterText(index, strBuf);
 - 
 -         return strBuf;
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin midi-program calls
 - 
 -     uint32_t getMidiProgramCount() const override
 -     {
 -         if (pData->curPluginCount == 0 || pData->plugins == nullptr)
 -             return 0;
 - 
 -         CarlaPlugin* const plugin(pData->plugins[0].plugin);
 - 
 -         if (plugin == nullptr || ! plugin->isEnabled())
 -             return 0.0f;
 - 
 -         return plugin->getMidiProgramCount();
 -     }
 - 
 -     const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
 -     {
 -         if (index >= getMidiProgramCount())
 -             return nullptr;
 - 
 -         CarlaPlugin* const plugin(pData->plugins[0].plugin);
 - 
 -         if (plugin == nullptr || ! plugin->isEnabled())
 -             return nullptr;
 - 
 -         static ::MidiProgram midiProg;
 - 
 -         {
 -             const MidiProgramData& midiProgData(plugin->getMidiProgramData(index));
 - 
 -             midiProg.bank    = midiProgData.bank;
 -             midiProg.program = midiProgData.program;
 -             midiProg.name    = midiProgData.name;
 -         }
 - 
 -         return &midiProg;
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin state calls
 - 
 -     void setParameterValue(const uint32_t index, const float value) override
 -     {
 -         if (index >= getParameterCount())
 -             return;
 - 
 -         CarlaPlugin* const plugin(pData->plugins[0].plugin);
 - 
 -         if (plugin == nullptr || ! plugin->isEnabled())
 -             return;
 - 
 -         plugin->setParameterValue(index, value, false, false, false);
 -     }
 - 
 -     void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
 -     {
 -         if (pData->curPluginCount == 0 || pData->plugins == nullptr)
 -             return;
 - 
 -         CarlaPlugin* const plugin(pData->plugins[0].plugin);
 - 
 -         if (plugin == nullptr || ! plugin->isEnabled())
 -             return;
 - 
 -         plugin->setMidiProgramById(bank, program, false, false, false);
 -     }
 - 
 -     void setCustomData(const char* const key, const char* const value) override
 -     {
 -         CARLA_ASSERT(key != nullptr);
 -         CARLA_ASSERT(value != nullptr);
 -         return;
 - 
 -         // TODO
 - 
 -         // unused
 -         (void)key;
 -         (void)value;
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin process calls
 - 
 -     void activate() override
 -     {
 -         for (uint32_t i=0; i < pData->curPluginCount; ++i)
 -         {
 -             CarlaPlugin* const plugin(pData->plugins[i].plugin);
 - 
 -             if (plugin == nullptr || ! plugin->isEnabled())
 -                 continue;
 - 
 -             plugin->setActive(true, true, false);
 -         }
 -     }
 - 
 -     void deactivate() override
 -     {
 -         for (uint32_t i=0; i < pData->curPluginCount; ++i)
 -         {
 -             CarlaPlugin* const plugin(pData->plugins[i].plugin);
 - 
 -             if (plugin == nullptr || ! plugin->isEnabled())
 -                 continue;
 - 
 -             plugin->setActive(false, true, false);
 -         }
 - 
 -         // just in case
 -         runPendingRtEvents();
 -     }
 - 
 -     void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const ::MidiEvent* const midiEvents, const uint32_t midiEventCount) override
 -     {
 -         if (pData->curPluginCount == 0)
 -         {
 -             carla_zeroFloat(outBuffer[0], frames);
 -             carla_zeroFloat(outBuffer[1], frames);
 -             return runPendingRtEvents();;
 -         }
 - 
 -         // ---------------------------------------------------------------
 -         // Time Info
 - 
 -         const ::TimeInfo* timeInfo(PluginClass::getTimeInfo());
 - 
 -         fTimeInfo.playing = timeInfo->playing;
 -         fTimeInfo.frame   = timeInfo->frame;
 -         fTimeInfo.usecs   = timeInfo->usecs;
 -         fTimeInfo.valid   = 0x0;
 - 
 -         if (timeInfo->bbt.valid)
 -         {
 -             fTimeInfo.valid |= EngineTimeInfo::ValidBBT;
 - 
 -             fTimeInfo.bbt.bar = timeInfo->bbt.bar;
 -             fTimeInfo.bbt.beat = timeInfo->bbt.beat;
 -             fTimeInfo.bbt.tick = timeInfo->bbt.tick;
 -             fTimeInfo.bbt.barStartTick = timeInfo->bbt.barStartTick;
 - 
 -             fTimeInfo.bbt.beatsPerBar = timeInfo->bbt.beatsPerBar;
 -             fTimeInfo.bbt.beatType = timeInfo->bbt.beatType;
 - 
 -             fTimeInfo.bbt.ticksPerBeat = timeInfo->bbt.ticksPerBeat;
 -             fTimeInfo.bbt.beatsPerMinute = timeInfo->bbt.beatsPerMinute;
 -         }
 - 
 -         // ---------------------------------------------------------------
 -         // initialize input events
 - 
 -         carla_zeroStruct<EngineEvent>(pData->bufEvents.in, INTERNAL_EVENT_COUNT);
 -         {
 -             uint32_t engineEventIndex = 0;
 - 
 -             for (uint32_t i=0; i < midiEventCount && engineEventIndex < INTERNAL_EVENT_COUNT; ++i)
 -             {
 -                 const ::MidiEvent& midiEvent(midiEvents[i]);
 - 
 -                 if (midiEvent.size > 4)
 -                     continue;
 - 
 -                 const uint8_t status  = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
 -                 const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent.data);
 - 
 -                 // we don't want some events
 -                 if (status == MIDI_STATUS_PROGRAM_CHANGE)
 -                     continue;
 - 
 -                 // handle note/sound off properly
 -                 if (status == MIDI_STATUS_CONTROL_CHANGE)
 -                 {
 -                     const uint8_t control = midiEvent.data[1];
 - 
 -                     if (MIDI_IS_CONTROL_BANK_SELECT(control))
 -                         continue;
 - 
 -                     if (control == MIDI_CONTROL_ALL_SOUND_OFF || control == MIDI_CONTROL_ALL_NOTES_OFF)
 -                     {
 -                         EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]);
 -                         engineEvent.clear();
 - 
 -                         engineEvent.type    = kEngineEventTypeControl;
 -                         engineEvent.time    = midiEvent.time;
 -                         engineEvent.channel = channel;
 - 
 -                         engineEvent.ctrl.type  = (control == MIDI_CONTROL_ALL_SOUND_OFF) ? kEngineControlEventTypeAllSoundOff : kEngineControlEventTypeAllNotesOff;
 -                         engineEvent.ctrl.param = 0;
 -                         engineEvent.ctrl.value = 0.0f;
 - 
 -                         continue;
 -                     }
 -                 }
 - 
 -                 EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]);
 -                 engineEvent.clear();
 - 
 -                 engineEvent.type    = kEngineEventTypeMidi;
 -                 engineEvent.time    = midiEvent.time;
 -                 engineEvent.channel = channel;
 - 
 -                 engineEvent.midi.data[0] = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
 -                 engineEvent.midi.data[1] = midiEvent.data[1];
 -                 engineEvent.midi.data[2] = midiEvent.data[2];
 -                 engineEvent.midi.data[3] = midiEvent.data[3];
 -                 engineEvent.midi.size    = midiEvent.size;
 -             }
 -         }
 - 
 -         // ---------------------------------------------------------------
 -         // create audio buffers
 - 
 -         float* inBuf[2]  = { inBuffer[0], inBuffer[1] };
 -         float* outBuf[2] = { outBuffer[0], outBuffer[1] };
 - 
 -         // ---------------------------------------------------------------
 -         // process
 - 
 -         processRack(inBuf, outBuf, frames);
 -         runPendingRtEvents();
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin UI calls
 - 
 -     void uiShow(const bool show) override
 -     {
 -         if (show)
 -         {
 -             fThread.start();
 -         }
 -         else
 -         {
 - #if 0
 -             for (uint32_t i=0; i < pData->curPluginCount; ++i)
 -             {
 -                 CarlaPlugin* const plugin(pData->plugins[i].plugin);
 - 
 -                 if (plugin == nullptr || ! plugin->enabled())
 -                     continue;
 - 
 -                 plugin->showGui(false);
 -             }
 - #endif
 - 
 -             fThread.stop();
 -         }
 -     }
 - 
 -     void uiIdle() override
 -     {
 -         CarlaEngine::idle();
 - 
 -         switch(fThread.getUiState())
 -         {
 -         case CarlaEngineNativeThread::UiNone:
 -         case CarlaEngineNativeThread::UiShow:
 -             break;
 -         case CarlaEngineNativeThread::UiCrashed:
 -             hostUiUnavailable();
 -             break;
 -         case CarlaEngineNativeThread::UiHide:
 -             uiClosed();
 -             break;
 -         }
 -     }
 - 
 -     void uiSetParameterValue(const uint32_t index, const float value) override
 -     {
 -         if (index >= getParameterCount())
 -             return;
 - 
 -         CarlaPlugin* const plugin(pData->plugins[0].plugin);
 - 
 -         if (plugin == nullptr || ! plugin->isEnabled())
 -             return;
 - 
 -         plugin->uiParameterChange(index, value);
 -     }
 - 
 -     void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override
 -     {
 -         return;
 - 
 -         // TODO
 - 
 -         // unused
 -         (void)channel;
 -         (void)bank;
 -         (void)program;
 -     }
 - 
 -     void uiSetCustomData(const char* const key, const char* const value) override
 -     {
 -         CARLA_ASSERT(key != nullptr);
 -         CARLA_ASSERT(value != nullptr);
 -         return;
 - 
 -         // TODO
 - 
 -         // unused
 -         (void)key;
 -         (void)value;
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin state calls
 - 
 -     char* getState() const override
 -     {
 -         QString string;
 -         QTextStream out(&string);
 - 
 -         out << "<?xml version='1.0' encoding='UTF-8'?>\n";
 -         out << "<!DOCTYPE CARLA-PROJECT>\n";
 -         out << "<CARLA-PROJECT VERSION='1.0'>\n";
 - 
 -         bool firstPlugin = true;
 -         char strBuf[STR_MAX+1];
 - 
 -         for (unsigned int i=0; i < pData->curPluginCount; ++i)
 -         {
 -             CarlaPlugin* const plugin(pData->plugins[i].plugin);
 - 
 -             if (plugin != nullptr && plugin->isEnabled())
 -             {
 -                 if (! firstPlugin)
 -                     out << "\n";
 - 
 -                 plugin->getRealName(strBuf);
 - 
 -                 if (*strBuf != 0)
 -                     out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true));
 - 
 -                 QString content;
 -                 fillXmlStringFromSaveState(content, plugin->getSaveState());
 - 
 -                 out << " <Plugin>\n";
 -                 out << content;
 -                 out << " </Plugin>\n";
 - 
 -                 firstPlugin = false;
 -             }
 -         }
 - 
 -         out << "</CARLA-PROJECT>\n";
 - 
 -         return strdup(string.toUtf8().constData());
 -     }
 - 
 -     void setState(const char* const data) override
 -     {
 -         QDomDocument xml;
 -         xml.setContent(QString(data));
 - 
 -         QDomNode xmlNode(xml.documentElement());
 - 
 -         if (xmlNode.toElement().tagName() != "CARLA-PROJECT")
 -         {
 -             carla_stderr2("Not a valid Carla project");
 -             return;
 -         }
 - 
 -         QDomNode node(xmlNode.firstChild());
 - 
 -         while (! node.isNull())
 -         {
 -             if (node.toElement().tagName() == "Plugin")
 -             {
 -                 SaveState saveState;
 -                 fillSaveStateFromXmlNode(saveState, node);
 - 
 -                 CARLA_SAFE_ASSERT_CONTINUE(saveState.type != nullptr)
 - 
 -                 const void* extraStuff = nullptr;
 - 
 -                 // FIXME
 -                 //if (std::strcmp(saveState.type, "DSSI") == 0)
 -                 //    extraStuff = findDSSIGUI(saveState.binary, saveState.label);
 - 
 -                 // TODO - proper find&load plugins
 -                 if (addPlugin(getPluginTypeFromString(saveState.type), saveState.binary, saveState.name, saveState.label, extraStuff))
 -                 {
 -                     if (CarlaPlugin* plugin = getPlugin(pData->curPluginCount-1))
 -                         plugin->loadSaveState(saveState);
 -                 }
 -             }
 - 
 -             node = node.nextSibling();
 -         }
 -     }
 - 
 -     // -------------------------------------------------------------------
 - 
 - private:
 -     bool fIsRunning;
 -     CarlaEngineNativeThread fThread;
 - 
 -     PluginClassEND(CarlaEngineNative)
 -     CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNative)
 - };
 - 
 - // -----------------------------------------------------------------------
 - 
 - static const PluginDescriptor carlaDesc = {
 -     /* category  */ ::PLUGIN_CATEGORY_OTHER,
 -     /* hints     */ static_cast< ::PluginHints>(::PLUGIN_IS_SYNTH|::PLUGIN_HAS_GUI|::PLUGIN_USES_SINGLE_THREAD|::PLUGIN_USES_STATE),
 -     /* supports  */ static_cast<PluginSupports>(PLUGIN_SUPPORTS_EVERYTHING),
 -     /* audioIns  */ 2,
 -     /* audioOuts */ 2,
 -     /* midiIns   */ 1,
 -     /* midiOuts  */ 1,
 -     /* paramIns  */ 0,
 -     /* paramOuts */ 0,
 -     /* name      */ "Carla-Plugin (TESTING)",
 -     /* label     */ "carla",
 -     /* maker     */ "falkTX",
 -     /* copyright */ "GNU GPL v2+",
 -     PluginDescriptorFILL(CarlaEngineNative)
 - };
 - 
 - CARLA_EXPORT
 - void carla_register_native_plugin_carla()
 - {
 -     carla_register_native_plugin(&carlaDesc);
 - }
 - 
 - CARLA_BACKEND_END_NAMESPACE
 - 
 - // -----------------------------------------------------------------------
 - 
 - #endif // ! BUILD_BRIDGE
 
 
  |