diff --git a/source/backend/CarlaBackend.h b/source/backend/CarlaBackend.h index 4a3896295..5f3b668e6 100644 --- a/source/backend/CarlaBackend.h +++ b/source/backend/CarlaBackend.h @@ -463,25 +463,31 @@ typedef enum { */ PLUGIN_AU = 6, + /*! + * ReWire plugin. + * @note Windows and MacOS only + */ + PLUGIN_REWIRE = 7, + /*! * Single CSD file (Csound). */ - PLUGIN_FILE_CSD = 7, + PLUGIN_FILE_CSD = 8, /*! * Single GIG file. */ - PLUGIN_FILE_GIG = 8, + PLUGIN_FILE_GIG = 9, /*! * Single SF2 file (SoundFont). */ - PLUGIN_FILE_SF2 = 9, + PLUGIN_FILE_SF2 = 10, /*! * Single SFZ file. */ - PLUGIN_FILE_SFZ = 10 + PLUGIN_FILE_SFZ = 11 } PluginType; diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp index 7882b142c..34628b7f0 100644 --- a/source/backend/CarlaPlugin.hpp +++ b/source/backend/CarlaPlugin.hpp @@ -840,6 +840,7 @@ public: static CarlaPlugin* newLV2(const Initializer& init); static CarlaPlugin* newVST(const Initializer& init); static CarlaPlugin* newAU(const Initializer& init); + static CarlaPlugin* newReWire(const Initializer& init); static CarlaPlugin* newCsound(const Initializer& init); static CarlaPlugin* newJuce(const Initializer& init, const char* const format); diff --git a/source/backend/Makefile.mk b/source/backend/Makefile.mk index 32d9ebc77..6886d469e 100644 --- a/source/backend/Makefile.mk +++ b/source/backend/Makefile.mk @@ -16,7 +16,7 @@ BUILD_CXX_FLAGS += $(LIBLO_FLAGS) BUILD_CXX_FLAGS += -DWANT_NATIVE ifeq ($(CARLA_PLUGIN_SUPPORT),true) -BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST +BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST -DWANT_AU -DWANT_REWIRE ifeq ($(CARLA_VESTIGE_HEADER),true) BUILD_CXX_FLAGS += -DVESTIGE_HEADER endif diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index e192f893a..9c641e3f7 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -891,6 +891,10 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, cons plugin = CarlaPlugin::newAU(initializer); break; + case PLUGIN_REWIRE: + plugin = CarlaPlugin::newReWire(initializer); + break; + case PLUGIN_FILE_CSD: plugin = CarlaPlugin::newFileCSD(initializer); break; diff --git a/source/backend/plugin/CarlaPluginUi.cpp b/source/backend/plugin/CarlaPluginUi.cpp index 931ab4a69..ee26cc5e5 100644 --- a/source/backend/plugin/CarlaPluginUi.cpp +++ b/source/backend/plugin/CarlaPluginUi.cpp @@ -294,14 +294,18 @@ bool CarlaPluginUi::tryTransientWinIdMatch(const ulong pid, const char* const ui #ifdef CARLA_OS_MAC CarlaPluginUi* CarlaPluginUi::newCocoa(CloseCallback* cb) { - return new CocoaPluginUi(cb); + //return new CocoaPluginUi(cb); + return nullptr; + (void)cb; } #endif #ifdef CARLA_OS_WIN CarlaPluginUi* CarlaPluginUi::newWindows(CloseCallback* cb) { - return new WindowsPluginUi(cb); + //return new WindowsPluginUi(cb); + return nullptr; + (void)cb; } #endif diff --git a/source/backend/plugin/Makefile b/source/backend/plugin/Makefile index cdb716c6f..d19fadd88 100644 --- a/source/backend/plugin/Makefile +++ b/source/backend/plugin/Makefile @@ -27,6 +27,7 @@ OBJS = \ Lv2Plugin.cpp.o \ VstPlugin.cpp.o \ AuPlugin.cpp.o \ + ReWirePlugin.cpp.o \ CsoundPlugin.cpp.o \ JucePlugin.cpp.o \ FluidSynthPlugin.cpp.o \ @@ -87,6 +88,9 @@ VstPlugin.cpp.o: VstPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) AuPlugin.cpp.o: AuPlugin.cpp $(CARLA_PLUGIN_HPP) $(CARLA_ENGINE_HPP) $(CARLA_UTILS_HPP) $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ +ReWirePlugin.cpp.o: ReWirePlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CARLA_LIB_UTILS_HPP) $(CARLA_MATH_UTILS_HPP) + $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ + CsoundPlugin.cpp.o: CsoundPlugin.cpp $(CARLA_PLUGIN_INTERNAL_HPP) $(CARLA_ENGINE_HPP) $(CXX) $< $(BUILD_CXX_FLAGS) $(CSOUND_FLAGS) -c -o $@ diff --git a/source/backend/plugin/ReWirePlugin.cpp b/source/backend/plugin/ReWirePlugin.cpp new file mode 100644 index 000000000..3f13a5fbc --- /dev/null +++ b/source/backend/plugin/ReWirePlugin.cpp @@ -0,0 +1,1084 @@ +/* + * Carla ReWire Plugin + * Copyright (C) 2014 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#include "CarlaPluginInternal.hpp" +#include "CarlaEngine.hpp" + +#ifdef WANT_REWIRE + +#include "CarlaLibUtils.hpp" +#include "CarlaMathUtils.hpp" + +// ----------------------------------------------------- + +CARLA_BACKEND_START_NAMESPACE + +#if 0 +} +#endif + +// ----------------------------------------------------------------------- +// ReWire assumes sizeof(long) == 4 + +typedef int32_t rlong; +typedef uint32_t rulong; + +static_assert(sizeof(rlong) == 4, "Incorrect rlong size"); +static_assert(sizeof(rulong) == 4, "Incorrect rulong size"); + +// rewire is not for linux, so for easy testing+development, we can skip this +#ifndef CARLA_OS_LINUX +static_assert(sizeof(long) == 4, "Incorrect long size"); +static_assert(sizeof(ulong) == 4, "Incorrect ulong size"); +static_assert(sizeof(long) == sizeof(rlong), "long size mismatch"); +static_assert(sizeof(ulong) == sizeof(rulong), "ulon size mismatch"); +#endif + +struct RwOpenInfo { + rulong size1; // 16 + rulong size2; // 12 + rlong sampleRate; + rlong bufferSize; +}; + +struct RwDevInfo { + rulong size; // 8288 + char name[32]; + rlong channelCount; // max limited to 255 + char channelNames[256][32]; + rulong defaultChannels[8]; + rulong stereoPairs[4]; + rulong eventBufferSize; + rlong version; +}; + +struct RwAudioInfo { + rulong size; // 12 + rlong sampleRate; + rlong bufferSize; +}; + +struct RwBusInfo { + rulong size; // 40 + rulong channel; + char name[32]; +}; + +struct RwEventInfo { + rulong size; // 132 FIXME? + rulong bus[32]; +}; + +struct RwEvent { // 24 + ushort type; + uchar d1, d2; + rulong s1, s2, s3, s4, s5; +}; + +struct RwEventBuffer { + rulong size1; // 20 + rulong size2; // 24 (of RwEvent) + rulong count; + rulong maxCount; +#ifndef CARLA_OS_LINUX // pointers on 64bit linux are size 8, skip this + RwEvent* buf; +#else + rulong buf; +#endif +}; + +struct RwAudioInInfo { + rulong size; // 1116 + RwEventBuffer evBuf; + rulong channels[8]; +#ifndef CARLA_OS_LINUX // pointers on 64bit linux are size 8, skip this + float* audioBuf[256]; +#else + rulong audioBuf[256]; +#endif + rlong tickStart; + rulong frames; + rulong playMode; + rulong tempo; // bpm + rulong signNumerator; + rulong signDenominator; + rlong loopStartPos; + rlong loopEndPos; + rulong loopOn; +}; + +struct RwAudioOutInfo { + rulong size; // 56 + RwEventBuffer evBuf; + rulong channels[8]; +}; + +static_assert(sizeof(RwOpenInfo) == 16, "Incorrect ReWire struct size"); +static_assert(sizeof(RwDevInfo) == 8288, "Incorrect ReWire struct size"); +static_assert(sizeof(RwAudioInfo) == 12, "Incorrect ReWire struct size"); +static_assert(sizeof(RwBusInfo) == 40, "Incorrect ReWire struct size"); +static_assert(sizeof(RwEventInfo) == 132, "Incorrect ReWire struct size"); +static_assert(sizeof(RwEvent) == 24, "Incorrect ReWire struct size"); +static_assert(sizeof(RwEventBuffer) == 20, "Incorrect ReWire struct size"); +static_assert(sizeof(RwAudioInInfo) == 1116, "Incorrect ReWire struct size"); +static_assert(sizeof(RwAudioOutInfo) == 56, "Incorrect ReWire struct size"); + +// ----------------------------------------------------------------------- + +typedef void (*Fn_RWDEFCloseDevice)(); +typedef void (*Fn_RWDEFDriveAudio)(RwAudioInInfo* in, RwAudioOutInfo* out); +typedef void (*Fn_RWDEFGetDeviceInfo)(RwDevInfo* info); +typedef void (*Fn_RWDEFGetDeviceNameAndVersion)(long* version, char* name); +typedef void (*Fn_RWDEFGetEventBusInfo)(ushort index, RwBusInfo* info); +typedef void (*Fn_RWDEFGetEventChannelInfo)(void* v1, void* v2); +typedef void (*Fn_RWDEFGetEventControllerInfo)(void* v1, ushort index, void* v2); +typedef void (*Fn_RWDEFGetEventInfo)(RwEventInfo* info); +typedef void (*Fn_RWDEFGetEventNoteInfo)(void* v1, ushort index, void* v2); +typedef void (*Fn_RWDEFIdle)(); +typedef char (*Fn_RWDEFIsCloseOK)(); +typedef char (*Fn_RWDEFIsPanelAppLaunched)(); +typedef int (*Fn_RWDEFLaunchPanelApp)(); +typedef int (*Fn_RWDEFOpenDevice)(RwOpenInfo* info); +typedef int (*Fn_RWDEFQuitPanelApp)(); +typedef void (*Fn_RWDEFSetAudioInfo)(RwAudioInfo* info); + +// ----------------------------------------------------------------------------- + +struct RewireBridge { + void* lib; + + Fn_RWDEFCloseDevice RWDEFCloseDevice; + Fn_RWDEFDriveAudio RWDEFDriveAudio; + Fn_RWDEFGetDeviceInfo RWDEFGetDeviceInfo; + Fn_RWDEFGetDeviceNameAndVersion RWDEFGetDeviceNameAndVersion; + Fn_RWDEFGetEventBusInfo RWDEFGetEventBusInfo; + Fn_RWDEFGetEventChannelInfo RWDEFGetEventChannelInfo; + Fn_RWDEFGetEventControllerInfo RWDEFGetEventControllerInfo; + Fn_RWDEFGetEventInfo RWDEFGetEventInfo; + Fn_RWDEFGetEventNoteInfo RWDEFGetEventNoteInfo; + Fn_RWDEFIdle RWDEFIdle; + Fn_RWDEFIsCloseOK RWDEFIsCloseOK; + Fn_RWDEFIsPanelAppLaunched RWDEFIsPanelAppLaunched; + Fn_RWDEFLaunchPanelApp RWDEFLaunchPanelApp; + Fn_RWDEFOpenDevice RWDEFOpenDevice; + Fn_RWDEFQuitPanelApp RWDEFQuitPanelApp; + Fn_RWDEFSetAudioInfo RWDEFSetAudioInfo; + + RewireBridge() + : lib(nullptr), + RWDEFCloseDevice(nullptr), + RWDEFDriveAudio(nullptr), + RWDEFGetDeviceInfo(nullptr), + RWDEFGetDeviceNameAndVersion(nullptr), + RWDEFGetEventBusInfo(nullptr), + RWDEFGetEventChannelInfo(nullptr), + RWDEFGetEventControllerInfo(nullptr), + RWDEFGetEventInfo(nullptr), + RWDEFGetEventNoteInfo(nullptr), + RWDEFIdle(nullptr), + RWDEFIsCloseOK(nullptr), + RWDEFIsPanelAppLaunched(nullptr), + RWDEFLaunchPanelApp(nullptr), + RWDEFOpenDevice(nullptr), + RWDEFQuitPanelApp(nullptr), + RWDEFSetAudioInfo(nullptr) {} + + ~RewireBridge() + { + cleanup(); + } + + int init(const char* const filename) + { + CARLA_SAFE_ASSERT_RETURN(lib == nullptr, -2); + CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', -2); + + lib = lib_open(filename); + + if (lib == nullptr) + return -1; + + #define JOIN(a, b) a ## b + #define LIB_SYMBOL(NAME) NAME = (Fn_##NAME)lib_symbol(lib, #NAME); if (NAME == nullptr) cleanup(); return -2; + + LIB_SYMBOL(RWDEFCloseDevice) + LIB_SYMBOL(RWDEFDriveAudio) + LIB_SYMBOL(RWDEFGetDeviceInfo) + LIB_SYMBOL(RWDEFGetDeviceNameAndVersion) + LIB_SYMBOL(RWDEFGetEventBusInfo) + LIB_SYMBOL(RWDEFGetEventChannelInfo) + LIB_SYMBOL(RWDEFGetEventControllerInfo) + LIB_SYMBOL(RWDEFGetEventInfo) + LIB_SYMBOL(RWDEFGetEventNoteInfo) + LIB_SYMBOL(RWDEFIdle) + LIB_SYMBOL(RWDEFIsCloseOK) + LIB_SYMBOL(RWDEFIsPanelAppLaunched) + LIB_SYMBOL(RWDEFLaunchPanelApp) + LIB_SYMBOL(RWDEFOpenDevice) + LIB_SYMBOL(RWDEFQuitPanelApp) + LIB_SYMBOL(RWDEFSetAudioInfo) + + #undef JOIN + #undef LIB_SYMBOL + + return 0; + } + + void cleanup() + { + if (lib != nullptr) + { + lib_close(lib); + lib = nullptr; + } + + RWDEFCloseDevice = nullptr; + RWDEFDriveAudio = nullptr; + RWDEFGetDeviceInfo = nullptr; + RWDEFGetDeviceNameAndVersion = nullptr; + RWDEFGetEventBusInfo = nullptr; + RWDEFGetEventChannelInfo = nullptr; + RWDEFGetEventControllerInfo = nullptr; + RWDEFGetEventInfo = nullptr; + RWDEFGetEventNoteInfo = nullptr; + RWDEFIdle = nullptr; + RWDEFIsCloseOK = nullptr; + RWDEFIsPanelAppLaunched = nullptr; + RWDEFLaunchPanelApp = nullptr; + RWDEFOpenDevice = nullptr; + RWDEFQuitPanelApp = nullptr; + RWDEFSetAudioInfo = nullptr; + } +}; + +// ----------------------------------------------------- + +class ReWirePlugin : public CarlaPlugin +{ +public: + ReWirePlugin(CarlaEngine* const engine, const unsigned int id) + : CarlaPlugin(engine, id), + fIsOpen(false), + fIsPanelLaunched(false), + fLabel(nullptr) + { + carla_debug("ReWirePlugin::ReWirePlugin(%p, %i)", engine, id); + + carla_zeroStruct(fRwAudioIn); + fRwAudioIn.size = sizeof(RwAudioInInfo); + + carla_zeroStruct(fRwAudioOut); + fRwAudioOut.size = sizeof(RwAudioOutInfo); + } + + ~ReWirePlugin() override + { + carla_debug("ReWirePlugin::~ReWirePlugin()"); + + // close panel + if (fIsPanelLaunched) + { + fRw.RWDEFQuitPanelApp(); + fIsPanelLaunched = false; + } + + pData->singleMutex.lock(); + pData->masterMutex.lock(); + + if (pData->client != nullptr && pData->client->isActive()) + pData->client->deactivate(); + + if (pData->active) + { + deactivate(); + pData->active = false; + } + + if (fIsOpen) + { + for (; fRw.RWDEFIsCloseOK() == 0;) + carla_msleep(2); + + fRw.RWDEFCloseDevice(); + fIsOpen = false; + } + + if (fLabel != nullptr) + { + delete[] fLabel; + fLabel = nullptr; + } + + clearBuffers(); + } + + // ------------------------------------------------------------------- + // Information (base) + + PluginType getType() const noexcept override + { + return PLUGIN_REWIRE; + } + + PluginCategory getCategory() const noexcept override + { + return PLUGIN_CATEGORY_SYNTH; + } + + // ------------------------------------------------------------------- + // Information (count) + + // nothing + + // ------------------------------------------------------------------- + // Information (current data) + + int32_t getChunkData(void** const dataPtr) const noexcept override + { + CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0); + CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr, 0); + CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0); + + // TODO + + return 0; + } + + // ------------------------------------------------------------------- + // Information (per-plugin data) + + unsigned int getOptionsAvailable() const noexcept override + { + unsigned int options = 0x0; + + if (getMidiInCount() > 0) + { + options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; + options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; + options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; + options |= PLUGIN_OPTION_SEND_PITCHBEND; + options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; + } + + return options; + } + + float getParameterValue(const uint32_t parameterId) const noexcept override + { + CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f); + + // TODO + + return 0.0f; + } + + void getLabel(char* const strBuf) const noexcept override + { + CARLA_SAFE_ASSERT_RETURN(fLabel != nullptr,) + + std::strcpy(strBuf, fLabel); + } + + void getRealName(char* const strBuf) const noexcept override + { + CARLA_SAFE_ASSERT_RETURN(fLabel != nullptr,) + + std::strcpy(strBuf, fLabel); + } + + void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override + { + CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,); + CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); + + // TODO + CarlaPlugin::getParameterName(parameterId, strBuf); + } + + void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override + { + CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,); + CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); + + // TODO + CarlaPlugin::getParameterUnit(parameterId, strBuf); + } + + // ------------------------------------------------------------------- + // Set data (state) + + // nothing + + // ------------------------------------------------------------------- + // Set data (internal stuff) + + // nothing + + // ------------------------------------------------------------------- + // Set data (plugin-specific stuff) + + void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override + { + CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,); + CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); + + const float fixedValue(pData->param.getFixedValue(parameterId, value)); + + // TODO + + CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); + } + + void setChunkData(const char* const stringData) override + { + CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,); + CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,); + CARLA_SAFE_ASSERT_RETURN(stringData != nullptr,); + + // TODO + } + + // ------------------------------------------------------------------- + // Set ui stuff + + void showCustomUI(const bool yesNo) override + { + if (yesNo) + { + if (! fRw.RWDEFIsPanelAppLaunched()) + fRw.RWDEFLaunchPanelApp(); + fIsPanelLaunched = true; + } + else + { + if (fRw.RWDEFIsPanelAppLaunched()) + fRw.RWDEFQuitPanelApp(); + fIsPanelLaunched = false; + } + } + + void idle() override + { + // check if panel has been closed + if (fIsPanelLaunched && ! fRw.RWDEFIsPanelAppLaunched()) + { + fIsPanelLaunched = true; + pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr); + } + + CarlaPlugin::idle(); + } + + // ------------------------------------------------------------------- + // Plugin state + + void reload() override + { + CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,); + CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,); + carla_debug("ReWirePlugin::reload() - start"); + + const EngineProcessMode processMode(pData->engine->getProccessMode()); + + // Safely disable plugin for reload + const ScopedDisabler sd(this); + + if (pData->active) + deactivate(); + + clearBuffers(); + + uint32_t aIns, aOuts, mIns, mOuts, params; + + bool needsCtrlIn, needsCtrlOut; + needsCtrlIn = needsCtrlOut = false; + + RwDevInfo devInfo; + carla_zeroStruct(devInfo); + devInfo.size = sizeof(RwDevInfo); + + fRw.RWDEFGetDeviceInfo(&devInfo); + + if (devInfo.channelCount > 0) + aIns = aOuts = static_cast(devInfo.channelCount); + + mIns = mOuts = 0; // TODO, should always be 1 + + params = 0; // TODO? + + if (aIns > 0) + { + pData->audioIn.createNew(aIns); + } + + if (aOuts > 0) + { + pData->audioOut.createNew(aOuts); + needsCtrlIn = true; + } + + if (params > 0) + { + pData->param.createNew(params, false); + needsCtrlIn = true; + } + + const uint portNameSize(pData->engine->getMaxPortNameSize()); + CarlaString portName; + + // Audio Ins + for (uint32_t j=0; j < aIns; ++j) + { + portName.clear(); + + if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) + { + portName = pData->name; + portName += ":"; + } + + portName += "i"; + portName += devInfo.channelNames[j]; + + portName.truncate(portNameSize); + + pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true); + pData->audioIn.ports[j].rindex = j; + } + + // Audio Outs + for (uint32_t j=0; j < aOuts; ++j) + { + portName.clear(); + + if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) + { + portName = pData->name; + portName += ":"; + } + + portName += "o"; + portName += devInfo.channelNames[j]; + portName.truncate(portNameSize); + + pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false); + pData->audioOut.ports[j].rindex = j; + } + + if (needsCtrlIn) + { + portName.clear(); + + if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) + { + portName = pData->name; + portName += ":"; + } + + portName += "events-in"; + portName.truncate(portNameSize); + + pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true); + } + + if (needsCtrlOut) + { + portName.clear(); + + if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT) + { + portName = pData->name; + portName += ":"; + } + + portName += "events-out"; + portName.truncate(portNameSize); + + pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false); + } + + // plugin hints + pData->hints = 0x0; + + pData->hints |= PLUGIN_IS_SYNTH; + pData->hints |= PLUGIN_HAS_CUSTOM_UI; + + if (aOuts > 0 && (aIns == aOuts || aIns == 1)) + pData->hints |= PLUGIN_CAN_DRYWET; + + if (aOuts > 0) + pData->hints |= PLUGIN_CAN_VOLUME; + + if (aOuts >= 2 && aOuts % 2 == 0) + pData->hints |= PLUGIN_CAN_BALANCE; + + // extra plugin hints + pData->extraHints = 0x0; + + if (mIns > 0) + pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN; + + if (mOuts > 0) + pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT; + + if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0)) + pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK; + + bufferSizeChanged(pData->engine->getBufferSize()); + + if (pData->active) + activate(); + + carla_debug("ReWirePlugin::reload() - end"); + } + + // ------------------------------------------------------------------- + // Plugin processing + + void activate() noexcept override + { + CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,); + + // TODO + } + + void deactivate() noexcept override + { + CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,); + + // TODO + } + + void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override + { + // -------------------------------------------------------------------------------------------------------- + // Check if active + + if (! pData->active) + { + // disable any output sound + for (uint32_t i=0; i < pData->audioOut.count; ++i) + FLOAT_CLEAR(outBuffer[i], frames); + return; + } + + // -------------------------------------------------------------------------------------------------------- + // Check if needs reset + + if (pData->needsReset) + { + if (pData->latency > 0) + { + for (uint32_t i=0; i < pData->audioIn.count; ++i) + FLOAT_CLEAR(pData->latencyBuffers[i], pData->latency); + } + + pData->needsReset = false; + } + + // -------------------------------------------------------------------------------------------------------- + // Set TimeInfo + + const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo()); + + //fRwAudioIn.playMode; // ??? + //fRwAudioIn.frames = timeInfo.frame; // not sure if buf or tranport frames + + if (timeInfo.valid & EngineTimeInfo::kValidBBT) + { + double ppqBar = double(timeInfo.bbt.bar - 1) * timeInfo.bbt.beatsPerBar; + double ppqBeat = double(timeInfo.bbt.beat - 1); + double ppqTick = double(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat; + + // PPQ Pos, ??? + fRwAudioIn.tickStart = static_cast(ppqBar + ppqBeat + ppqTick); + + // Tempo + fRwAudioIn.tempo = static_cast(timeInfo.bbt.beatsPerMinute); + + // Bars + //fTimeInfo.barStartPos = ppqBar; + + // Time Signature + fRwAudioIn.signNumerator = static_cast(timeInfo.bbt.beatsPerBar); + fRwAudioIn.signDenominator = static_cast(timeInfo.bbt.beatType); + } + else + { + fRwAudioIn.tickStart = 0; + fRwAudioIn.tempo = 120; + fRwAudioIn.signNumerator = 4; + fRwAudioIn.signDenominator = 4; + } + + // -------------------------------------------------------------------------------------------------------- + // Plugin processing (no events) + + { + processSingle(inBuffer, outBuffer, frames, 0); + + } // End of Plugin processing (no events) + } + + bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) + { + CARLA_SAFE_ASSERT_RETURN(frames > 0, false); + + if (pData->audioIn.count > 0) + { + CARLA_SAFE_ASSERT_RETURN(inBuffer != nullptr, false); + } + if (pData->audioOut.count > 0) + { + CARLA_SAFE_ASSERT_RETURN(outBuffer != nullptr, false); + } + + // -------------------------------------------------------------------------------------------------------- + // Try lock, silence otherwise + + if (pData->engine->isOffline()) + { + pData->singleMutex.lock(); + } + else if (! pData->singleMutex.tryLock()) + { + for (uint32_t i=0; i < pData->audioOut.count; ++i) + { + for (uint32_t k=0; k < frames; ++k) + outBuffer[i][k+timeOffset] = 0.0f; + } + + return false; + } + + // -------------------------------------------------------------------------------------------------------- + // Set audio buffers + + //rulong channels[8]; + fRwAudioIn.frames = frames; + +#ifndef CARLA_OS_LINUX + for (uint32_t i=0; i < pData->audioOut.count; ++i) + { + fRwAudioIn.audioBuf[i] = outBuffer[i]+timeOffset; + FLOAT_COPY(fRwAudioIn.audioBuf[i], inBuffer[i]+timeOffset, frames); + } +#endif + + // -------------------------------------------------------------------------------------------------------- + // Run plugin + + fRw.RWDEFDriveAudio(&fRwAudioIn, &fRwAudioOut); + +#ifndef BUILD_BRIDGE + // -------------------------------------------------------------------------------------------------------- + // Post-processing (dry/wet, volume and balance) + + { + const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && pData->postProc.volume != 1.0f; + const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && pData->postProc.dryWet != 1.0f; + const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && (pData->postProc.balanceLeft != -1.0f || pData->postProc.balanceRight != 1.0f); + + bool isPair; + float bufValue, oldBufLeft[doBalance ? frames : 1]; + + for (uint32_t i=0; i < pData->audioOut.count; ++i) + { + // Dry/Wet + if (doDryWet) + { + for (uint32_t k=0; k < frames; ++k) + { + bufValue = inBuffer[(pData->audioIn.count == 1) ? 0 : i][k+timeOffset]; + outBuffer[i][k+timeOffset] = (outBuffer[i][k+timeOffset] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); + } + } + + // Balance + if (doBalance) + { + isPair = (i % 2 == 0); + + if (isPair) + { + CARLA_ASSERT(i+1 < pData->audioOut.count); + FLOAT_COPY(oldBufLeft, outBuffer[i]+timeOffset, frames); + } + + float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f; + float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f; + + for (uint32_t k=0; k < frames; ++k) + { + if (isPair) + { + // left + outBuffer[i][k+timeOffset] = oldBufLeft[k] * (1.0f - balRangeL); + outBuffer[i][k+timeOffset] += outBuffer[i+1][k+timeOffset] * (1.0f - balRangeR); + } + else + { + // right + outBuffer[i][k+timeOffset] = outBuffer[i][k+timeOffset] * balRangeR; + outBuffer[i][k+timeOffset] += oldBufLeft[k] * balRangeL; + } + } + } + + // Volume + if (doVolume) + { + for (uint32_t k=0; k < frames; ++k) + outBuffer[i][k+timeOffset] *= pData->postProc.volume; + } + } + + } // End of Post-processing +#endif + + // -------------------------------------------------------------------------------------------------------- + + pData->singleMutex.unlock(); + return true; + } + + void bufferSizeChanged(const uint32_t newBufferSize) override + { + CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize); + carla_debug("ReWirePlugin::bufferSizeChanged(%i)", newBufferSize); + + if (pData->active) + deactivate(); + + RwAudioInfo audioInfo; + audioInfo.size = sizeof(RwAudioInfo); + audioInfo.bufferSize = static_cast(newBufferSize); + audioInfo.sampleRate = static_cast(pData->engine->getSampleRate()); + + fRw.RWDEFSetAudioInfo(&audioInfo); + + if (pData->active) + activate(); + } + + void sampleRateChanged(const double newSampleRate) override + { + CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate); + carla_debug("ReWirePlugin::sampleRateChanged(%g)", newSampleRate); + + if (pData->active) + deactivate(); + + RwAudioInfo audioInfo; + audioInfo.size = sizeof(RwAudioInfo); + audioInfo.bufferSize = static_cast(pData->engine->getBufferSize()); + audioInfo.sampleRate = static_cast(newSampleRate); + + fRw.RWDEFSetAudioInfo(&audioInfo); + + if (pData->active) + activate(); + } + + // ------------------------------------------------------------------- + // Plugin buffers + + // nothing + + // ------------------------------------------------------------------- + // Post-poned UI Stuff + + // nothing + + // ------------------------------------------------------------------- + +protected: + // TODO + + // ------------------------------------------------------------------- + +public: + bool init(const char* const filename, const char* const name) + { + CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); + + // --------------------------------------------------------------- + // first checks + + if (pData->client != nullptr) + { + pData->engine->setLastError("Plugin client is already registered"); + return false; + } + + if (filename == nullptr || filename[0] == '\0') + { + pData->engine->setLastError("null filename"); + return false; + } + + // --------------------------------------------------------------- + // open DLL + + int ret = fRw.init(filename); + + if (ret != 0) + { + if (ret == -1) + pData->engine->setLastError(lib_error(filename)); + else + pData->engine->setLastError("Not a valid ReWire application"); + return false; + } + + // --------------------------------------------------------------- + // get info + + long version; + char nameBuf[STR_MAX+1]; + carla_zeroChar(nameBuf, STR_MAX+1); + fRw.RWDEFGetDeviceNameAndVersion(&version, nameBuf); + + if (nameBuf[0] == '\0') + { + pData->engine->setLastError("ReWire application has no name"); + return false; + } + + fLabel = carla_strdup(nameBuf); + + if (name != nullptr && name[0] != '\0') + pData->name = pData->engine->getUniquePluginName(name); + else + pData->name = pData->engine->getUniquePluginName(nameBuf); + + pData->filename = carla_strdup(filename); + + // --------------------------------------------------------------- + // register client + + pData->client = pData->engine->addClient(this); + + if (pData->client == nullptr || ! pData->client->isOk()) + { + pData->engine->setLastError("Failed to register plugin client"); + return false; + } + + // --------------------------------------------------------------- + // initialize app + + RwOpenInfo info; + info.size1 = sizeof(RwOpenInfo); + info.size2 = 12; + info.bufferSize = static_cast(pData->engine->getBufferSize()); + info.sampleRate = static_cast(pData->engine->getSampleRate()); + + ret = fRw.RWDEFOpenDevice(&info); + + carla_stdout("RW open ret = %i", ret); + + // TODO check ret + fIsOpen = true; + + // --------------------------------------------------------------- + // load plugin settings + + { + // set default options + pData->options = 0x0; + + pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; + pData->options |= PLUGIN_OPTION_USE_CHUNKS; + + // TODO + if (getMidiInCount() > 0) + { + pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; + pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; + pData->options |= PLUGIN_OPTION_SEND_PITCHBEND; + pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; + } + + // set identifier string + CarlaString identifier("ReWire/"); + identifier += fLabel; + pData->identifier = identifier.dup(); + + // load settings + pData->options = pData->loadSettings(pData->options, getOptionsAvailable()); + + // ignore settings, we need this anyway + pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; + pData->options |= PLUGIN_OPTION_USE_CHUNKS; + } + + return true; + } + +private: + RewireBridge fRw; + RwAudioInInfo fRwAudioIn; + RwAudioOutInfo fRwAudioOut; + + bool fIsOpen; + bool fIsPanelLaunched; + const char* fLabel; + + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ReWirePlugin) +}; + +CARLA_BACKEND_END_NAMESPACE + +#endif // WANT_REWIRE + +// ------------------------------------------------------------------------------------------------------------------- + +CARLA_BACKEND_START_NAMESPACE + +CarlaPlugin* CarlaPlugin::newReWire(const Initializer& init) +{ + carla_debug("CarlaPlugin::newReWire({%p, \"%s\", \"%s\"})", init.engine, init.filename, init.name); + +#ifdef WANT_REWIRE + ReWirePlugin* const plugin(new ReWirePlugin(init.engine, init.id)); + + if (! plugin->init(init.filename, init.name)) + { + delete plugin; + return nullptr; + } + + plugin->reload(); + + if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && ! plugin->canRunInRack()) + { + init.engine->setLastError("Carla's rack mode can only work with Stereo ReWire applications, sorry!"); + delete plugin; + return nullptr; + } + + return plugin; +#else + init.engine->setLastError("ReWire support not available"); + return nullptr; +#endif +} + +CARLA_BACKEND_END_NAMESPACE + +// ------------------------------------------------------------------------------------------------------------------- diff --git a/source/backend/standalone/CarlaStandalone.cpp b/source/backend/standalone/CarlaStandalone.cpp index 8c99c095a..c887b78ad 100644 --- a/source/backend/standalone/CarlaStandalone.cpp +++ b/source/backend/standalone/CarlaStandalone.cpp @@ -30,6 +30,10 @@ #include +#ifdef BUILD_BRIDGE +# undef HAVE_JUCE +#endif + #ifdef HAVE_JUCE # include "juce_gui_basics.h" using juce::initialiseJuce_GUI; diff --git a/source/bridges/Makefile b/source/bridges/Makefile index dab395362..efc89b1cc 100644 --- a/source/bridges/Makefile +++ b/source/bridges/Makefile @@ -419,6 +419,7 @@ OBJS_NATIVE += \ ../backend/plugin/Lv2Plugin__native.o \ ../backend/plugin/VstPlugin__native.o \ ../backend/plugin/AuPlugin__native.o \ + ../backend/plugin/ReWirePlugin__native.o \ ../backend/plugin/CsoundPlugin__native.o \ ../backend/plugin/JucePlugin__native.o \ ../backend/plugin/FluidSynthPlugin__native.o \ @@ -463,171 +464,200 @@ carla-bridge-native: $(OBJS_NATIVE) $(LIBS_NATIVE) # -------------------------------------------------------------- # posix32 -# OBJS_POSIX32 = CarlaBridgePlugin__posix32.o \ -# CarlaBridgeClient__posix32.o CarlaBridgeOsc__posix32.o -# -# # carla-engine -# OBJS_POSIX32 += \ -# ../backend/engine/CarlaEngine__posix32.o \ -# ../backend/engine/CarlaEngineOsc__posix32.o \ -# ../backend/engine/CarlaEngineThread__posix32.o \ -# ../backend/engine/CarlaEngineJack__posix32.o \ -# ../backend/engine/CarlaEngineBridge__posix32.o -# -# # carla-plugin -# OBJS_POSIX32 += \ -# ../backend/plugin/CarlaPlugin__posix32.o \ -# ../backend/plugin/CarlaPluginThread__posix32.o \ -# ../backend/plugin/NativePlugin__posix32.o \ -# ../backend/plugin/LadspaPlugin__posix32.o \ -# ../backend/plugin/DssiPlugin__posix32.o \ -# ../backend/plugin/Lv2Plugin__posix32.o \ -# ../backend/plugin/VstPlugin__posix32.o \ -# ../backend/plugin/Vst3Plugin__posix32.o \ -# ../backend/plugin/FluidSynthPlugin__posix32.o \ -# ../backend/plugin/LinuxSamplerPlugin__posix32.o +OBJS_POSIX32 = CarlaBridgePlugin__posix32.o \ + CarlaBridgeClient__posix32.o CarlaBridgeOsc__posix32.o + +# carla-engine +OBJS_POSIX32 += \ + ../backend/engine/CarlaEngine__posix32.o \ + ../backend/engine/CarlaEngineInternal__posix32.o \ + ../backend/engine/CarlaEngineOsc__posix32.o \ + ../backend/engine/CarlaEngineThread__posix32.o \ + ../backend/engine/CarlaEngineJack__posix32.o \ + ../backend/engine/CarlaEngineBridge__posix32.o + +# carla-plugin +OBJS_POSIX32 += \ + ../backend/plugin/CarlaPlugin__posix32.o \ + ../backend/plugin/CarlaPluginInternal__posix32.o \ + ../backend/plugin/CarlaPluginThread__posix32.o \ + ../backend/plugin/CarlaPluginUi__posix32.o \ + ../backend/plugin/NativePlugin__posix32.o \ + ../backend/plugin/LadspaPlugin__posix32.o \ + ../backend/plugin/DssiPlugin__posix32.o \ + ../backend/plugin/Lv2Plugin__posix32.o \ + ../backend/plugin/VstPlugin__posix32.o \ + ../backend/plugin/AuPlugin__posix32.o \ + ../backend/plugin/ReWirePlugin__posix32.o \ + ../backend/plugin/CsoundPlugin__posix32.o \ + ../backend/plugin/JucePlugin__posix32.o \ + ../backend/plugin/FluidSynthPlugin__posix32.o \ + ../backend/plugin/LinuxSamplerPlugin__posix32.o # carla-standalone -# OBJS_POSIX32 += \ -# ../backend/standalone/CarlaStandalone__posix32.o -# -# # libs -# OBJS_POSIX32 += \ -# ../modules/lilv.posix32.a \ -# ../modules/rtmempool.posix32.a -# -# carla-bridge-posix32: $(OBJS_POSIX32) -# $(CXX) $(OBJS_POSIX32) $(POSIX_LINK_FLAGS) $(POSIX_32BIT_FLAGS) -o $@ -# -# %__posix32.o: %.cpp -# $(CXX) $< $(POSIX_BUILD_FLAGS) $(POSIX_32BIT_FLAGS) -c -o $@ +OBJS_POSIX32 += \ + ../backend/standalone/CarlaStandalone__posix32.o + +# libs +LIBS_POSIX32 = \ + ../modules/lilv.posix32.a \ + ../modules/rtmempool.posix32.a + +carla-bridge-posix32: $(OBJS_POSIX32) $(LIBS_POSIX32) + $(CXX) $(OBJS_POSIX32) -Wl,--start-group $(LIBS_POSIX32) -Wl,--end-group $(POSIX_LINK_FLAGS) $(POSIX_32BIT_FLAGS) -o $@ + +%__posix32.o: %.cpp + $(CXX) $< $(POSIX_BUILD_FLAGS) $(POSIX_32BIT_FLAGS) -c -o $@ # -------------------------------------------------------------- # posix64 -# OBJS_POSIX64 = CarlaBridgePlugin__posix64.o \ -# CarlaBridgeClient__posix64.o CarlaBridgeOsc__posix64.o -# -# # carla-engine -# OBJS_POSIX64 += \ -# ../backend/engine/CarlaEngine__posix64.o \ -# ../backend/engine/CarlaEngineOsc__posix64.o \ -# ../backend/engine/CarlaEngineThread__posix64.o \ -# ../backend/engine/CarlaEngineJack__posix64.o \ -# ../backend/engine/CarlaEngineBridge__posix64.o -# -# # carla-plugin -# OBJS_POSIX64 += \ -# ../backend/plugin/CarlaPlugin__posix64.o \ -# ../backend/plugin/CarlaPluginThread__posix64.o \ -# ../backend/plugin/NativePlugin__posix64.o \ -# ../backend/plugin/LadspaPlugin__posix64.o \ -# ../backend/plugin/DssiPlugin__posix64.o \ -# ../backend/plugin/Lv2Plugin__posix64.o \ -# ../backend/plugin/VstPlugin__posix64.o \ -# ../backend/plugin/Vst3Plugin__posix64.o \ -# ../backend/plugin/FluidSynthPlugin__posix64.o \ -# ../backend/plugin/LinuxSamplerPlugin__posix64.o +OBJS_POSIX64 = CarlaBridgePlugin__posix64.o \ + CarlaBridgeClient__posix64.o CarlaBridgeOsc__posix64.o + +# carla-engine +OBJS_POSIX64 += \ + ../backend/engine/CarlaEngine__posix64.o \ + ../backend/engine/CarlaEngineInternal__posix64.o \ + ../backend/engine/CarlaEngineOsc__posix64.o \ + ../backend/engine/CarlaEngineThread__posix64.o \ + ../backend/engine/CarlaEngineJack__posix64.o \ + ../backend/engine/CarlaEngineBridge__posix64.o + +# carla-plugin +OBJS_POSIX64 += \ + ../backend/plugin/CarlaPlugin__posix64.o \ + ../backend/plugin/CarlaPluginInternal__posix64.o \ + ../backend/plugin/CarlaPluginThread__posix64.o \ + ../backend/plugin/CarlaPluginUi__posix64.o \ + ../backend/plugin/NativePlugin__posix64.o \ + ../backend/plugin/LadspaPlugin__posix64.o \ + ../backend/plugin/DssiPlugin__posix64.o \ + ../backend/plugin/Lv2Plugin__posix64.o \ + ../backend/plugin/VstPlugin__posix64.o \ + ../backend/plugin/AuPlugin__posix32.o \ + ../backend/plugin/ReWirePlugin__posix64.o \ + ../backend/plugin/CsoundPlugin__posix64.o \ + ../backend/plugin/JucePlugin__posix64.o \ + ../backend/plugin/FluidSynthPlugin__posix64.o \ + ../backend/plugin/LinuxSamplerPlugin__posix64.o # carla-standalone -# OBJS_POSIX64 += \ -# ../backend/standalone/CarlaStandalone__posix64.o -# -# # libs -# OBJS_POSIX64 += \ -# ../modules/lilv.posix64.a \ -# ../modules/rtmempool.posix64.a +OBJS_POSIX64 += \ + ../backend/standalone/CarlaStandalone__posix64.o -# carla-bridge-posix64: $(OBJS_POSIX64) -# $(CXX) $(OBJS_POSIX64) $(POSIX_LINK_FLAGS) $(POSIX_64BIT_FLAGS) -o $@ -# -# %__posix64.o: %.cpp -# $(CXX) $< $(POSIX_BUILD_FLAGS) $(POSIX_64BIT_FLAGS) -c -o $@ +# libs +LIBS_POSIX64 = \ + ../modules/lilv.posix64.a \ + ../modules/rtmempool.posix64.a + +carla-bridge-posix64: $(OBJS_POSIX64) $(LIBS_POSIX64) + $(CXX) $(OBJS_POSIX64) -Wl,--start-group $(LIBS_POSIX64) -Wl,--end-group $(POSIX_LINK_FLAGS) $(POSIX_64BIT_FLAGS) -o $@ + +%__posix64.o: %.cpp + $(CXX) $< $(POSIX_BUILD_FLAGS) $(POSIX_64BIT_FLAGS) -c -o $@ # -------------------------------------------------------------- # win32 -# OBJS_WIN32 = CarlaBridgePlugin__win32.o \ -# CarlaBridgeClient__win32.o CarlaBridgeOsc__win32.o -# -# # carla-engine -# OBJS_WIN32 += \ -# ../backend/engine/CarlaEngine__win32.o \ -# ../backend/engine/CarlaEngineOsc__win32.o \ -# ../backend/engine/CarlaEngineThread__win32.o \ -# ../backend/engine/CarlaEngineBridge__win32.o \ -# ../backend/engine/CarlaEngineJack__win32.o -# -# # carla-plugin -# OBJS_WIN32 += \ -# ../backend/plugin/CarlaPlugin__win32.o \ -# ../backend/plugin/CarlaPluginThread__win32.o \ -# ../backend/plugin/NativePlugin__win32.o \ -# ../backend/plugin/LadspaPlugin__win32.o \ -# ../backend/plugin/DssiPlugin__win32.o \ -# ../backend/plugin/Lv2Plugin__win32.o \ -# ../backend/plugin/VstPlugin__win32.o \ -# ../backend/plugin/Vst3Plugin__win32.o \ -# ../backend/plugin/FluidSynthPlugin__win32.o \ -# ../backend/plugin/LinuxSamplerPlugin__win32.o +OBJS_WIN32 = CarlaBridgePlugin__win32.o \ + CarlaBridgeClient__win32.o CarlaBridgeOsc__win32.o + +# carla-engine +OBJS_WIN32 += \ + ../backend/engine/CarlaEngine__win32.o \ + ../backend/engine/CarlaEngineInternal__win32.o \ + ../backend/engine/CarlaEngineOsc__win32.o \ + ../backend/engine/CarlaEngineThread__win32.o \ + ../backend/engine/CarlaEngineBridge__win32.o \ + ../backend/engine/CarlaEngineJack__win32.o + +# carla-plugin +OBJS_WIN32 += \ + ../backend/plugin/CarlaPlugin__win32.o \ + ../backend/plugin/CarlaPluginInternal__win32.o \ + ../backend/plugin/CarlaPluginThread__win32.o \ + ../backend/plugin/CarlaPluginUi__win32.o \ + ../backend/plugin/NativePlugin__win32.o \ + ../backend/plugin/LadspaPlugin__win32.o \ + ../backend/plugin/DssiPlugin__win32.o \ + ../backend/plugin/Lv2Plugin__win32.o \ + ../backend/plugin/VstPlugin__win32.o \ + ../backend/plugin/AuPlugin__win32.o \ + ../backend/plugin/ReWirePlugin__win32.o \ + ../backend/plugin/CsoundPlugin__win32.o \ + ../backend/plugin/JucePlugin__win32.o \ + ../backend/plugin/FluidSynthPlugin__win32.o \ + ../backend/plugin/LinuxSamplerPlugin__win32.o # carla-standalone -# OBJS_WIN32 += \ -# ../backend/standalone/CarlaStandalone__win32.o -# -# # libs -# OBJS_WIN32 += \ -# ../modules/juce_core.win32.a \ -# ../modules/lilv.win32.a \ -# ../modules/rtmempool.win32.a - -# carla-bridge-win32.exe: $(OBJS_WIN32) ../modules/jackbridge-win32.dll -# $(CXX) $(OBJS_WIN32) $(WIN_32BIT_FLAGS) $(WIN_LINK_FLAGS) -ljackbridge-win32 -o $@ -# -# %__win32.o: %.cpp -# $(CXX) $< $(WIN_BUILD_FLAGS) $(WIN_32BIT_FLAGS) -c -o $@ +OBJS_WIN32 += \ + ../backend/standalone/CarlaStandalone__win32.o + +# libs +LIBS_WIN32 = \ + ../modules/lilv.win32.a \ + ../modules/rtmempool.win32.a + +ifeq ($(HAVE_JUCE),true) +LIBS_WIN32 += \ + ../modules/juce_audio_basics.win32.a \ + ../modules/juce_core.win32.a +endif + +carla-bridge-win32.exe: $(OBJS_WIN32) $(LIBS_WIN32) ../modules/jackbridge-win32.dll + $(CXX) $(OBJS_WIN32) -Wl,--start-group $(LIBS_WIN32) -Wl,--end-group $(WIN_LINK_FLAGS) $(WIN_32BIT_FLAGS) -ljackbridge-win32 -o $@ + +%__win32.o: %.cpp + $(CXX) $< $(WIN_BUILD_FLAGS) $(WIN_32BIT_FLAGS) -c -o $@ # -------------------------------------------------------------- # win64 -# OBJS_WIN64 = CarlaBridgePlugin__win64.o \ -# CarlaBridgeClient__win64.o CarlaBridgeOsc__win64.o -# -# # carla-engine -# OBJS_WIN64 += \ -# ../backend/engine/CarlaEngine__win64.o \ -# ../backend/engine/CarlaEngineOsc__win64.o \ -# ../backend/engine/CarlaEngineThread__win64.o \ -# ../backend/engine/CarlaEngineBridge__win64.o \ -# ../backend/engine/CarlaEngineJack__win64.o -# -# # carla-plugin -# OBJS_WIN64 += \ -# ../backend/plugin/CarlaPlugin__win64.o \ -# ../backend/plugin/CarlaPluginThread__win64.o \ -# ../backend/plugin/NativePlugin__win64.o \ -# ../backend/plugin/LadspaPlugin__win64.o \ -# ../backend/plugin/DssiPlugin__win64.o \ -# ../backend/plugin/Lv2Plugin__win64.o \ -# ../backend/plugin/VstPlugin__win64.o \ -# ../backend/plugin/Vst3Plugin__win64.o \ -# ../backend/plugin/FluidSynthPlugin__win64.o \ -# ../backend/plugin/LinuxSamplerPlugin__win64.o -# -# # carla-standalone -# OBJS_WIN64 += \ -# ../backend/standalone/CarlaStandalone__win64.o -# -# # libs -# OBJS_WIN64 += \ -# ../modules/lilv.win64.a \ -# ../modules/rtmempool.win64.a -# -# carla-bridge-win64.exe: $(OBJS_WIN64) ../modules/jackbridge-win64.dll -# $(CXX) $(OBJS_WIN64) $(WIN_64BIT_FLAGS) $(WIN_LINK_FLAGS) -ljackbridge-win64 -o $@ -# -# %__win64.o: %.cpp -# $(CXX) $< $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) -c -o $@ +OBJS_WIN64 = CarlaBridgePlugin__win64.o \ + CarlaBridgeClient__win64.o CarlaBridgeOsc__win64.o + +# carla-engine +OBJS_WIN64 += \ + ../backend/engine/CarlaEngine__win64.o \ + ../backend/engine/CarlaEngineInternal__win64.o \ + ../backend/engine/CarlaEngineOsc__win64.o \ + ../backend/engine/CarlaEngineThread__win64.o \ + ../backend/engine/CarlaEngineBridge__win64.o \ + ../backend/engine/CarlaEngineJack__win64.o + +# carla-plugin +OBJS_WIN64 += \ + ../backend/plugin/CarlaPlugin__win64.o \ + ../backend/plugin/CarlaPluginInternal__win64.o \ + ../backend/plugin/CarlaPluginThread__win64.o \ + ../backend/plugin/CarlaPluginUi__win64.o \ + ../backend/plugin/NativePlugin__win64.o \ + ../backend/plugin/LadspaPlugin__win64.o \ + ../backend/plugin/DssiPlugin__win64.o \ + ../backend/plugin/Lv2Plugin__win64.o \ + ../backend/plugin/VstPlugin__win64.o \ + ../backend/plugin/AuPlugin__win64.o \ + ../backend/plugin/ReWirePlugin__win64.o \ + ../backend/plugin/CsoundPlugin__win64.o \ + ../backend/plugin/JucePlugin__win64.o \ + ../backend/plugin/FluidSynthPlugin__win64.o \ + ../backend/plugin/LinuxSamplerPlugin__win64.o + +# carla-standalone +OBJS_WIN64 += \ + ../backend/standalone/CarlaStandalone__win64.o + +# libs +LIBS_WIN64 = \ + ../modules/lilv.win64.a \ + ../modules/rtmempool.win64.a + +carla-bridge-win64.exe: $(OBJS_WIN64) $(LIBS_WIN64) ../modules/jackbridge-win64.dll + $(CXX) $(OBJS_WIN64) -Wl,--start-group $(LIBS_WIN32) -Wl,--end-group $(WIN_LINK_FLAGS) $(WIN_64BIT_FLAGS) -ljackbridge-win64 -o $@ + +%__win64.o: %.cpp + $(CXX) $< $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) -c -o $@ # -------------------------------------------------------------- @@ -638,10 +668,10 @@ clean: rm -f carla-bridge-vst-carbon carla-bridge-vst-cocoa carla-bridge-vst-x11 rm -f carla-bridge-native carla-bridge-posix32 carla-bridge-posix64 rm -f $(OBJS_NATIVE) -# rm -f $(OBJS_POSIX32) -# rm -f $(OBJS_POSIX64) -# rm -f $(OBJS_WIN32) -# rm -f $(OBJS_WIN64) + rm -f $(OBJS_POSIX32) + rm -f $(OBJS_POSIX64) + rm -f $(OBJS_WIN32) + rm -f $(OBJS_WIN64) debug: $(MAKE) DEBUG=true @@ -654,8 +684,17 @@ doxygen: carla_bridge.doxygen .FORCE: .PHONY: .FORCE -# ../modules/juce_core.%.a: .FORCE -# $(MAKE) -C ../modules juce_core_$* +../modules/jackbridge-win32.dll: .FORCE + $(MAKE) -C ../modules jackbridge-win32e + +../modules/jackbridge-win64.dll: .FORCE + $(MAKE) -C ../modules jackbridge-win64e + +../modules/juce_audio_basics.%.a: .FORCE + $(MAKE) -C ../modules juce_audio_basics_$* + +../modules/juce_core.%.a: .FORCE + $(MAKE) -C ../modules juce_core_$* ../modules/lilv.%.a: .FORCE $(MAKE) -C ../modules lilv_$* diff --git a/source/carla_backend.py b/source/carla_backend.py index f24a5dcf2..c5a3ada6d 100644 --- a/source/carla_backend.py +++ b/source/carla_backend.py @@ -351,17 +351,21 @@ PLUGIN_VST = 5 # @note MacOS only PLUGIN_AU = 6 +# ReWire plugin. +# @note Windows and MacOS only +PLUGIN_REWIRE = 7 + # Single CSD file (Csound). -PLUGIN_FILE_CSD = 7 +PLUGIN_FILE_CSD = 8 # Single GIG file. -PLUGIN_FILE_GIG = 8 +PLUGIN_FILE_GIG = 9 # Single SF2 file (SoundFont). -PLUGIN_FILE_SF2 = 9 +PLUGIN_FILE_SF2 = 10 # Single SFZ file. -PLUGIN_FILE_SFZ = 10 +PLUGIN_FILE_SFZ = 11 # ------------------------------------------------------------------------------------------------------------ # Plugin Category diff --git a/source/carla_widgets.py b/source/carla_widgets.py index 1059bc254..34f04dd17 100755 --- a/source/carla_widgets.py +++ b/source/carla_widgets.py @@ -560,6 +560,8 @@ class PluginEdit(QDialog): self.ui.le_type.setText("VST") elif pluginType == PLUGIN_AU: self.ui.le_type.setText("AU") + elif pluginType == PLUGIN_REWIRE: + self.ui.le_type.setText("ReWire") elif pluginType == PLUGIN_FILE_CSD: self.ui.le_type.setText("CSD") elif pluginType == PLUGIN_FILE_GIG: diff --git a/source/modules/Makefile b/source/modules/Makefile index 6efc4d05c..8ac55f9fb 100644 --- a/source/modules/Makefile +++ b/source/modules/Makefile @@ -142,12 +142,18 @@ jackbridge: jackbridge-win32: $(MAKE) -C jackbridge win32 +jackbridge-win32e: + $(MAKE) -C jackbridge win32e + jackbridge-win64: $(MAKE) -C jackbridge win64 jackbridge-wine32: $(MAKE) -C jackbridge wine32 +jackbridge-win64e: + $(MAKE) -C jackbridge win64e + jackbridge-wine64: $(MAKE) -C jackbridge wine64 diff --git a/source/modules/jackbridge/Makefile b/source/modules/jackbridge/Makefile index 24009cd6c..352351c9c 100644 --- a/source/modules/jackbridge/Makefile +++ b/source/modules/jackbridge/Makefile @@ -17,7 +17,9 @@ OBJS = JackBridge1.cpp.o JackBridge2.cpp.o OBJS_posix32 = JackBridge1.cpp.posix32.o JackBridge2.cpp.posix32.o OBJS_posix64 = JackBridge1.cpp.posix64.o JackBridge2.cpp.posix64.o OBJS_win32 = JackBridge1.cpp.win32.o JackBridge2.cpp.win32.o +OBJS_win32e = JackBridge1.cpp.win32e.o JackBridge2.cpp.win32e.o OBJS_win64 = JackBridge1.cpp.win64.o JackBridge2.cpp.win64.o +OBJS_win64e = JackBridge1.cpp.win64e.o JackBridge2.cpp.win64e.o # -------------------------------------------------------------- @@ -27,6 +29,8 @@ posix32: ../jackbridge.posix32.a posix64: ../jackbridge.posix64.a win32: ../jackbridge.win32.a win64: ../jackbridge.win64.a +win32e: ../jackbridge-win32.dll +win64e: ../jackbridge-win64.dll # -------------------------------------------------------------- @@ -53,6 +57,12 @@ win64: ../jackbridge.win64.a ../libjackbridge.dll: $(OBJS) $(CXX) $^ -shared $(LINK_FLAGS) -o $@ +../jackbridge-win32.dll: $(OBJS_win32e) + $(CXX) $^ -shared $(LINK_FLAGS) -Wl,--output-def,$@.def,--out-implib,$@.a -o $@ + +../jackbridge-win64.dll: $(OBJS_win64e) + $(CXX) $^ -shared $(LINK_FLAGS) -Wl,--output-def,$@.def,--out-implib,$@.a -o $@ + ../libjackbridge.dylib: $(OBJS) $(CXX) $^ -dynamiclib $(LINK_FLAGS) -o $@ @@ -61,9 +71,6 @@ win64: ../jackbridge.win64.a # -------------------------------------------------------------- -%.cpp.o: %.cpp - $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ - %.posix32.o: % $(CXX) $< $(BUILD_CXX_FLAGS) $(32BIT_FLAGS) -c -o $@ @@ -76,6 +83,15 @@ win64: ../jackbridge.win64.a %.win64.o: % $(CXX) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -c -o $@ +%.win32e.o: % + $(CXX) $< $(BUILD_CXX_FLAGS) $(32BIT_FLAGS) -DJACKBRIDGE_DUMMY=1 -DJACKBRIDGE_EXPORT -w -c -o $@ + +%.win64e.o: % + $(CXX) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -DJACKBRIDGE_DUMMY=1 -DJACKBRIDGE_EXPORT -w -c -o $@ + +%.cpp.o: %.cpp + $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ + # -------------------------------------------------------------- clean: diff --git a/source/tests/Rewire.cpp b/source/tests/Rewire.cpp index d7c8248ea..1091da832 100644 --- a/source/tests/Rewire.cpp +++ b/source/tests/Rewire.cpp @@ -19,185 +19,6 @@ // ----------------------------------------------------------------------- -struct OpenInfo { - ulong size1; // ?? - ulong size2; // 12 - long sampleRate; - long bufferSize; -}; - -struct DevInfo { - ulong size; // 8288 - char name[32]; - long channelCount; // max limited to 255 - char channelNames[256][32]; - unsigned long defaultChannels[8]; - unsigned long stereoPairs[4]; - unsigned long eventBufferSize; - long version; -}; - -struct AudioInfo { - ulong size; // 12 - long sampleRate; - long bufferSize; -}; - -struct BusInfo { - ulong size; // 40 - ulong channel; - char name[32]; -}; - -struct EventInfo { - ulong size; // 36 - ulong bus[32]; -}; - -struct Event { // 24 - ushort type; - uchar d1, d2; - ulong s1, s2, s3, s4, s5; -}; - -struct EventBuffer { - ulong size1; // 20 - ulong size2; // 24 - ulong count; - ulong maxCount; - Event* buf; -}; - -struct AudioInInfo { - ulong size; // 1116 - EventBuffer evBuf; - unsigned long channels[8]; - float* audioBuf[256]; - long tickStart; - ulong frames; - ulong playMode; - ulong tempo; // bpm - ulong signNumerator; - ulong signDenominator; - long loopStartPos; - long loopEndPos; - ulong loopOn; -} ReWireDriveParams; - -struct AudioOutInfo { - ulong size; // 56 - EventBuffer evBuf; - ulong channels[8]; -}; - -// ----------------------------------------------------------------------- - -typedef void (*Fn_RWDEFCloseDevice)(); -typedef void (*Fn_RWDEFDriveAudio)(AudioInInfo* in, AudioOutInfo* out); -typedef void (*Fn_RWDEFGetDeviceInfo)(DevInfo* info); -typedef void (*Fn_RWDEFGetDeviceNameAndVersion)(long* version, char* name); -typedef void (*Fn_RWDEFGetEventBusInfo)(ushort index, BusInfo* info); -typedef void (*Fn_RWDEFGetEventChannelInfo)(void* v1, void* v2); -typedef void (*Fn_RWDEFGetEventControllerInfo)(void* v1, ushort index, void* v2); -typedef void (*Fn_RWDEFGetEventInfo)(EventInfo* info); -typedef void (*Fn_RWDEFGetEventNoteInfo)(void* v1, ushort index, void* v2); -typedef void (*Fn_RWDEFIdle)(); -typedef char (*Fn_RWDEFIsCloseOK)(); -typedef char (*Fn_RWDEFIsPanelAppLaunched)(); -typedef int (*Fn_RWDEFLaunchPanelApp)(); -typedef int (*Fn_RWDEFOpenDevice)(OpenInfo* info); -typedef int (*Fn_RWDEFQuitPanelApp)(); -typedef void (*Fn_RWDEFSetAudioInfo)(AudioInfo* info); - -// ----------------------------------------------------------------------------- - -struct RewireBridge { - void* lib; - - Fn_RWDEFCloseDevice RWDEFCloseDevice; - Fn_RWDEFDriveAudio RWDEFDriveAudio; - Fn_RWDEFGetDeviceInfo RWDEFGetDeviceInfo; - Fn_RWDEFGetDeviceNameAndVersion RWDEFGetDeviceNameAndVersion; - Fn_RWDEFGetEventBusInfo RWDEFGetEventBusInfo; - Fn_RWDEFGetEventChannelInfo RWDEFGetEventChannelInfo; - Fn_RWDEFGetEventControllerInfo RWDEFGetEventControllerInfo; - Fn_RWDEFGetEventInfo RWDEFGetEventInfo; - Fn_RWDEFGetEventNoteInfo RWDEFGetEventNoteInfo; - Fn_RWDEFIdle RWDEFIdle; - Fn_RWDEFIsCloseOK RWDEFIsCloseOK; - Fn_RWDEFIsPanelAppLaunched RWDEFIsPanelAppLaunched; - Fn_RWDEFLaunchPanelApp RWDEFLaunchPanelApp; - Fn_RWDEFOpenDevice RWDEFOpenDevice; - Fn_RWDEFQuitPanelApp RWDEFQuitPanelApp; - Fn_RWDEFSetAudioInfo RWDEFSetAudioInfo; - - RewireBridge(const char* const filename) - : lib(nullptr), - RWDEFCloseDevice(nullptr), - RWDEFDriveAudio(nullptr), - RWDEFGetDeviceInfo(nullptr), - RWDEFGetDeviceNameAndVersion(nullptr), - RWDEFGetEventBusInfo(nullptr), - RWDEFGetEventChannelInfo(nullptr), - RWDEFGetEventControllerInfo(nullptr), - RWDEFGetEventInfo(nullptr), - RWDEFGetEventNoteInfo(nullptr), - RWDEFIdle(nullptr), - RWDEFIsCloseOK(nullptr), - RWDEFIsPanelAppLaunched(nullptr), - RWDEFLaunchPanelApp(nullptr), - RWDEFOpenDevice(nullptr), - RWDEFQuitPanelApp(nullptr), - RWDEFSetAudioInfo(nullptr) - { - lib = lib_open(filename); - - if (lib == nullptr) - { - fprintf(stderr, "Failed to load DLL, reason:\n%s\n", lib_error(filename)); - return; - } - else - { - fprintf(stdout, "loaded sucessfully!\n"); - } - - #define JOIN(a, b) a ## b - #define LIB_SYMBOL(NAME) NAME = (Fn_##NAME)lib_symbol(lib, #NAME); - - LIB_SYMBOL(RWDEFCloseDevice) - LIB_SYMBOL(RWDEFDriveAudio) - LIB_SYMBOL(RWDEFGetDeviceInfo) - LIB_SYMBOL(RWDEFGetDeviceNameAndVersion) - LIB_SYMBOL(RWDEFGetEventBusInfo) - LIB_SYMBOL(RWDEFGetEventChannelInfo) - LIB_SYMBOL(RWDEFGetEventControllerInfo) - LIB_SYMBOL(RWDEFGetEventInfo) - LIB_SYMBOL(RWDEFGetEventNoteInfo) - LIB_SYMBOL(RWDEFIdle) - LIB_SYMBOL(RWDEFIsCloseOK) - LIB_SYMBOL(RWDEFIsPanelAppLaunched) - LIB_SYMBOL(RWDEFLaunchPanelApp) - LIB_SYMBOL(RWDEFOpenDevice) - LIB_SYMBOL(RWDEFQuitPanelApp) - LIB_SYMBOL(RWDEFSetAudioInfo) - - #undef JOIN - #undef LIB_SYMBOL - } - - ~RewireBridge() - { - if (lib != nullptr) - { - lib_close(lib); - lib = nullptr; - } - } -}; - -// ----------------------------------------------------------------------- - int main(/*int argc, char* argv[]*/) { static const char* const filename = "C:\\Program Files\\Waves\\ReWire\\WavesReWireDevice.dll"; diff --git a/source/utils/CarlaBackendUtils.hpp b/source/utils/CarlaBackendUtils.hpp index a130982fd..cdbed4101 100644 --- a/source/utils/CarlaBackendUtils.hpp +++ b/source/utils/CarlaBackendUtils.hpp @@ -99,6 +99,8 @@ const char* PluginType2Str(const PluginType type) noexcept return "PLUGIN_VST"; case PLUGIN_AU: return "PLUGIN_AU"; + case PLUGIN_REWIRE: + return "PLUGIN_REWIRE"; case PLUGIN_FILE_CSD: return "PLUGIN_FILE_CSD"; case PLUGIN_FILE_GIG: @@ -400,6 +402,8 @@ const char* getPluginTypeAsString(const PluginType type) noexcept return "VST"; case PLUGIN_AU: return "AU"; + case PLUGIN_REWIRE: + return "ReWire"; case PLUGIN_FILE_CSD: return "CSD"; case PLUGIN_FILE_GIG: @@ -437,6 +441,8 @@ PluginType getPluginTypeFromString(const char* const ctype) return PLUGIN_VST; if (stype == "au") return PLUGIN_AU; + if (stype == "rewire") + return PLUGIN_REWIRE; if (stype == "csd") return PLUGIN_FILE_CSD; if (stype == "gig") diff --git a/source/utils/CarlaShmUtils.hpp b/source/utils/CarlaShmUtils.hpp index 9c0921475..7bc22344a 100644 --- a/source/utils/CarlaShmUtils.hpp +++ b/source/utils/CarlaShmUtils.hpp @@ -62,7 +62,7 @@ void carla_shm_init(shm_t& shm) static inline shm_t carla_shm_create(const char* const name) { - CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullShm); + CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullCarlaShm); shm_t ret; ret.shm = nullptr; // TODO @@ -74,7 +74,7 @@ shm_t carla_shm_create(const char* const name) static inline shm_t carla_shm_attach(const char* const name) { - CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullShm); + CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullCarlaShm); shm_t ret; ret.shm = CreateFileA(name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); @@ -86,7 +86,7 @@ shm_t carla_shm_attach(const char* const name) static inline shm_t carla_shm_attach_linux(const char* const name) { - CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullShm); + CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', gNullCarlaShm); char shmName[std::strlen(name)+10]; std::strcpy(shmName, "/dev/shm/"); diff --git a/source/utils/CarlaStateUtils.cpp b/source/utils/CarlaStateUtils.cpp index 8a161e8e2..92f12c670 100644 --- a/source/utils/CarlaStateUtils.cpp +++ b/source/utils/CarlaStateUtils.cpp @@ -445,6 +445,9 @@ void fillXmlStringFromSaveState(QString& content, const SaveState& saveState) info += QString(" %1\n").arg(xmlSafeString(saveState.binary, true)); info += QString(" %1\n").arg(saveState.uniqueID); break; + case PLUGIN_REWIRE: + info += QString(" \n").arg(xmlSafeString(saveState.label, true)); + break; case PLUGIN_FILE_CSD: case PLUGIN_FILE_GIG: case PLUGIN_FILE_SF2: