diff --git a/c++/carla-backend/carla_backend.h b/c++/carla-backend/carla_backend.h index d23c2c3..909ae9d 100644 --- a/c++/carla-backend/carla_backend.h +++ b/c++/carla-backend/carla_backend.h @@ -51,14 +51,15 @@ const unsigned int MAX_PARAMETERS = 200; //!< Default value for the maximum numb * \see CarlaPlugin::hints() * @{ */ -const unsigned int PLUGIN_IS_BRIDGE = 0x01; //!< Plugin is a bridge (ie, BridgePlugin). This hint is required because "bridge" itself is not a plugin type. -const unsigned int PLUGIN_IS_SYNTH = 0x02; //!< Plugin is a synthesizer (produces sound). -const unsigned int PLUGIN_HAS_GUI = 0x04; //!< Plugin has its own custom GUI. -const unsigned int PLUGIN_USES_CHUNKS = 0x08; //!< Plugin uses chunks to save internal data.\see CarlaPlugin::chunkData() -const unsigned int PLUGIN_USES_SINGLE_THREAD = 0x10; //!< Plugin has its own custom GUI. -const unsigned int PLUGIN_CAN_DRYWET = 0x20; //!< Plugin can make use of Dry/Wet controls. -const unsigned int PLUGIN_CAN_VOLUME = 0x40; //!< Plugin can make use of Volume controls. -const unsigned int PLUGIN_CAN_BALANCE = 0x80; //!< Plugin can make use of Left & Right Balance controls. +const unsigned int PLUGIN_IS_BRIDGE = 0x001; //!< Plugin is a bridge (ie, BridgePlugin). This hint is required because "bridge" itself is not a plugin type. +const unsigned int PLUGIN_IS_SYNTH = 0x002; //!< Plugin is a synthesizer (produces sound). +const unsigned int PLUGIN_HAS_GUI = 0x004; //!< Plugin has its own custom GUI. +const unsigned int PLUGIN_USES_CHUNKS = 0x008; //!< Plugin uses chunks to save internal data.\see CarlaPlugin::chunkData() +const unsigned int PLUGIN_USES_SINGLE_THREAD = 0x010; //!< Plugin has its own custom GUI. +const unsigned int PLUGIN_CAN_DRYWET = 0x020; //!< Plugin can make use of Dry/Wet controls. +const unsigned int PLUGIN_CAN_VOLUME = 0x040; //!< Plugin can make use of Volume controls. +const unsigned int PLUGIN_CAN_BALANCE = 0x080; //!< Plugin can make use of Left & Right Balance controls. +const unsigned int PLUGIN_CAN_FORCE_STEREO = 0x100; //!< Plugin can be used in forced-stereo mode. /**@}*/ /*! diff --git a/c++/carla-backend/carla_native.cpp b/c++/carla-backend/carla_native.cpp index 7726bd1..3401ddc 100644 --- a/c++/carla-backend/carla_native.cpp +++ b/c++/carla-backend/carla_native.cpp @@ -78,8 +78,8 @@ public: m_type = PLUGIN_INTERNAL; - descriptor = nullptr; - handle = nullptr; + descriptor = nullptr; + handle = h2 = nullptr; host.handle = this; host.get_buffer_size = carla_host_get_buffer_size; @@ -103,16 +103,16 @@ public: { if (handle) descriptor->deactivate(handle); - //if (h2) - // descriptor->deactivate(h2); + if (h2) + descriptor->deactivate(h2); } if (descriptor->cleanup) { if (handle) descriptor->cleanup(handle); - //if (h2) - // descriptor->cleanup(h2); + if (h2) + descriptor->cleanup(h2); } } } @@ -688,7 +688,7 @@ public: param.count = params; // plugin checks - m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE); + m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO); if (aOuts > 0 && (aIns == aOuts || aIns == 1)) m_hints |= PLUGIN_CAN_DRYWET; @@ -699,6 +699,9 @@ public: if (aOuts >= 2 && aOuts%2 == 0) m_hints |= PLUGIN_CAN_BALANCE; + if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0) && mIns <= 1 && mOuts <= 1) + m_hints |= PLUGIN_CAN_FORCE_STEREO; + m_hints |= getPluginHintsFromNative(descriptor->hints); reloadPrograms(true); @@ -1561,7 +1564,7 @@ public: private: const PluginDescriptor* descriptor; - PluginHandle handle; + PluginHandle handle, h2; HostDescriptor host; bool isProcessing; @@ -1598,6 +1601,17 @@ CarlaPlugin* CarlaPlugin::newNative(const initializer& init) } plugin->reload(); + + if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) + { + if (! plugin->hints() & PLUGIN_CAN_FORCE_STEREO) + { + setLastError("Carla's rack mode can only work with Mono or Stereo Internal plugins, sorry!"); + delete plugin; + return nullptr; + } + } + plugin->registerToOsc(); return plugin; diff --git a/c++/carla-backend/dssi.cpp b/c++/carla-backend/dssi.cpp index 30fa620..0d82725 100644 --- a/c++/carla-backend/dssi.cpp +++ b/c++/carla-backend/dssi.cpp @@ -671,7 +671,7 @@ public: param.count = params; // plugin checks - m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE); + m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO); if (midi.portMin && aOut.count > 0) m_hints |= PLUGIN_IS_SYNTH; @@ -693,6 +693,9 @@ public: if (aOuts >= 2 && aOuts%2 == 0) m_hints |= PLUGIN_CAN_BALANCE; + if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0)) + m_hints |= PLUGIN_CAN_FORCE_STEREO; + reloadPrograms(true); x_client->activate(); @@ -1552,10 +1555,7 @@ CarlaPlugin* CarlaPlugin::newDSSI(const initializer& init, const void* const ext #ifndef BUILD_BRIDGE if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) { - const uint32_t ins = plugin->audioInCount(); - const uint32_t outs = plugin->audioOutCount(); - - if (ins > 2 || outs > 2 || (ins != outs && ins != 0 && outs != 0)) + if (! plugin->hints() & PLUGIN_CAN_FORCE_STEREO) { setLastError("Carla's rack mode can only work with Mono or Stereo DSSI plugins, sorry!"); delete plugin; diff --git a/c++/carla-backend/fluidsynth.cpp b/c++/carla-backend/fluidsynth.cpp index 697806c..5a22f4c 100644 --- a/c++/carla-backend/fluidsynth.cpp +++ b/c++/carla-backend/fluidsynth.cpp @@ -716,11 +716,12 @@ public: param.count = params; // plugin checks - m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE); + m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO); m_hints |= PLUGIN_IS_SYNTH; m_hints |= PLUGIN_CAN_VOLUME; m_hints |= PLUGIN_CAN_BALANCE; + m_hints |= PLUGIN_CAN_FORCE_STEREO; reloadPrograms(true); diff --git a/c++/carla-backend/ladspa.cpp b/c++/carla-backend/ladspa.cpp index cd6f016..870da60 100644 --- a/c++/carla-backend/ladspa.cpp +++ b/c++/carla-backend/ladspa.cpp @@ -651,7 +651,7 @@ public: param.count = params; // plugin checks - m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE); + m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO); if (aOuts > 0 && (aIns == aOuts || aIns == 1)) m_hints |= PLUGIN_CAN_DRYWET; @@ -662,6 +662,9 @@ public: if (aOuts >= 2 && aOuts%2 == 0) m_hints |= PLUGIN_CAN_BALANCE; + if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0)) + m_hints |= PLUGIN_CAN_FORCE_STEREO; + x_client->activate(); qDebug("LadspaPlugin::reload() - end"); @@ -1160,10 +1163,7 @@ CarlaPlugin* CarlaPlugin::newLADSPA(const initializer& init, const void* const e #ifndef BUILD_BRIDGE if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) { - const uint32_t ins = plugin->audioInCount(); - const uint32_t outs = plugin->audioOutCount(); - - if (ins > 2 || outs > 2 || (ins != outs && ins != 0 && outs != 0)) + if (! plugin->hints() & PLUGIN_CAN_FORCE_STEREO) { setLastError("Carla's rack mode can only work with Mono or Stereo LADSPA plugins, sorry!"); delete plugin; diff --git a/c++/carla-backend/linuxsampler.cpp b/c++/carla-backend/linuxsampler.cpp index 2d34209..5b8baa6 100644 --- a/c++/carla-backend/linuxsampler.cpp +++ b/c++/carla-backend/linuxsampler.cpp @@ -199,11 +199,12 @@ public: aOut.count = aOuts; // plugin checks - m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE); + m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO); m_hints |= PLUGIN_IS_SYNTH; m_hints |= PLUGIN_CAN_VOLUME; m_hints |= PLUGIN_CAN_BALANCE; + m_hints |= PLUGIN_CAN_FORCE_STEREO; reloadPrograms(true); diff --git a/c++/carla-backend/lv2.cpp b/c++/carla-backend/lv2.cpp index 7d99abe..3274bdd 100644 --- a/c++/carla-backend/lv2.cpp +++ b/c++/carla-backend/lv2.cpp @@ -54,9 +54,9 @@ const unsigned int MAX_EVENT_BUFFER = 8192; // 0x2000 * @defgroup PluginHints Plugin Hints * @{ */ -const unsigned int PLUGIN_HAS_EXTENSION_PROGRAMS = 0x100; //!< LV2 Plugin has Programs extension -const unsigned int PLUGIN_HAS_EXTENSION_STATE = 0x200; //!< LV2 Plugin has State extension -const unsigned int PLUGIN_HAS_EXTENSION_WORKER = 0x400; //!< LV2 Plugin has Worker extension +const unsigned int PLUGIN_HAS_EXTENSION_PROGRAMS = 0x1000; //!< LV2 Plugin has Programs extension +const unsigned int PLUGIN_HAS_EXTENSION_STATE = 0x2000; //!< LV2 Plugin has State extension +const unsigned int PLUGIN_HAS_EXTENSION_WORKER = 0x4000; //!< LV2 Plugin has Worker extension /**@}*/ /*! @@ -1144,8 +1144,25 @@ public: params += 1; } + // check extensions + ext.state = nullptr; + ext.worker = nullptr; + ext.programs = nullptr; + + if (descriptor->extension_data) + { + if (m_hints & PLUGIN_HAS_EXTENSION_PROGRAMS) + ext.programs = (const LV2_Programs_Interface*)descriptor->extension_data(LV2_PROGRAMS__Interface); + + if (m_hints & PLUGIN_HAS_EXTENSION_STATE) + ext.state = (const LV2_State_Interface*)descriptor->extension_data(LV2_STATE__interface); + + if (m_hints & PLUGIN_HAS_EXTENSION_WORKER) + ext.worker = (const LV2_Worker_Interface*)descriptor->extension_data(LV2_WORKER__interface); + } + #ifndef BUILD_BRIDGE - if (carlaOptions.forceStereo && (aIns == 1 || aOuts == 1) && ! h2) + if (carlaOptions.forceStereo && (aIns == 1 || aOuts == 1) && ! (h2 || ext.state || ext.worker)) { h2 = descriptor->instantiate(descriptor, sampleRate, rdf_descriptor->Bundle, features); @@ -1678,7 +1695,7 @@ public: param.count = params; // plugin checks - m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE); + m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO); if (LV2_IS_GENERATOR(rdf_descriptor->Type)) m_hints |= PLUGIN_IS_SYNTH; @@ -1692,21 +1709,15 @@ public: if (aOuts >= 2 && aOuts%2 == 0) m_hints |= PLUGIN_CAN_BALANCE; - // check extensions - ext.state = nullptr; - ext.worker = nullptr; - ext.programs = nullptr; - - if (descriptor->extension_data) + if (ext.state || ext.worker) { - if (m_hints & PLUGIN_HAS_EXTENSION_PROGRAMS) - ext.programs = (const LV2_Programs_Interface*)descriptor->extension_data(LV2_PROGRAMS__Interface); - - if (m_hints & PLUGIN_HAS_EXTENSION_STATE) - ext.state = (const LV2_State_Interface*)descriptor->extension_data(LV2_STATE__interface); - - if (m_hints & PLUGIN_HAS_EXTENSION_WORKER) - ext.worker = (const LV2_Worker_Interface*)descriptor->extension_data(LV2_WORKER__interface); + if ((aIns == 0 || aIns == 2) && (aOuts == 0 || aOuts == 2) && evIn.count <= 1 && evOut.count <= 1) + m_hints |= PLUGIN_CAN_FORCE_STEREO; + } + else + { + if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0) && evIn.count <= 1 && evOut.count <= 1) + m_hints |= PLUGIN_CAN_FORCE_STEREO; } reloadPrograms(true); @@ -4495,12 +4506,9 @@ CarlaPlugin* CarlaPlugin::newLV2(const initializer& init) #ifndef BUILD_BRIDGE if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) { - const uint32_t ins = plugin->audioInCount(); - const uint32_t outs = plugin->audioOutCount(); - - if (ins > 2 || outs > 2 || (ins != outs && ins != 0 && outs != 0)) + if (! plugin->hints() & PLUGIN_CAN_FORCE_STEREO) { - setLastError("Carla's rack mode can only work with Mono or Stereo LV2 plugins, sorry!"); + setLastError("Carla's rack mode can only work with Mono (simple) or Stereo LV2 plugins, sorry!"); delete plugin; return nullptr; } diff --git a/c++/carla-backend/vst.cpp b/c++/carla-backend/vst.cpp index 98cba2e..887d03a 100644 --- a/c++/carla-backend/vst.cpp +++ b/c++/carla-backend/vst.cpp @@ -38,10 +38,10 @@ CARLA_BACKEND_START_NAMESPACE * @defgroup PluginHints Plugin Hints * @{ */ -const unsigned int PLUGIN_CAN_PROCESS_REPLACING = 0x100; //!< VST Plugin cas use processReplacing() -const unsigned int PLUGIN_HAS_COCKOS_EXTENSIONS = 0x200; //!< VST Plugin has Cockos extensions -const unsigned int PLUGIN_USES_OLD_VSTSDK = 0x400; //!< VST Plugin uses an old VST SDK -const unsigned int PLUGIN_WANTS_MIDI_INPUT = 0x800; //!< VST Plugin wants MIDI input +const unsigned int PLUGIN_CAN_PROCESS_REPLACING = 0x1000; //!< VST Plugin cas use processReplacing() +const unsigned int PLUGIN_HAS_COCKOS_EXTENSIONS = 0x2000; //!< VST Plugin has Cockos extensions +const unsigned int PLUGIN_USES_OLD_VSTSDK = 0x4000; //!< VST Plugin uses an old VST SDK +const unsigned int PLUGIN_WANTS_MIDI_INPUT = 0x8000; //!< VST Plugin wants MIDI input /**@}*/ class VstPlugin : public CarlaPlugin @@ -687,7 +687,7 @@ public: param.count = params; // plugin checks - m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE); + m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO); intptr_t vstCategory = effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f); @@ -706,6 +706,9 @@ public: if (aOuts >= 2 && aOuts%2 == 0) m_hints |= PLUGIN_CAN_BALANCE; + if ((aIns == 0 || aIns == 2) && (aOuts == 0 || aOuts == 2)) + m_hints |= PLUGIN_CAN_FORCE_STEREO; + reloadPrograms(true); x_client->activate(); @@ -2302,13 +2305,7 @@ CarlaPlugin* CarlaPlugin::newVST(const initializer& init) #ifndef BUILD_BRIDGE if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK) { - const uint32_t ins = plugin->audioInCount(); - const uint32_t outs = plugin->audioOutCount(); - - const bool stereoInput = ins == 0 || ins == 2; - const bool stereoOutput = outs == 0 || outs == 2; - - if (! (stereoInput && stereoOutput)) + if (! plugin->hints() & PLUGIN_CAN_FORCE_STEREO) { setLastError("Carla's rack mode can only work with Stereo VST plugins, sorry!"); delete plugin; diff --git a/src/shared_carla.py b/src/shared_carla.py index d98f808..ba5ddfe 100644 --- a/src/shared_carla.py +++ b/src/shared_carla.py @@ -59,14 +59,15 @@ MAX_PLUGINS = 99 MAX_PARAMETERS = 200 # plugin hints -PLUGIN_IS_BRIDGE = 0x01 -PLUGIN_IS_SYNTH = 0x02 -PLUGIN_HAS_GUI = 0x04 -PLUGIN_USES_CHUNKS = 0x08 -PLUGIN_USES_SINGLE_THREAD = 0x10 -PLUGIN_CAN_DRYWET = 0x20 -PLUGIN_CAN_VOLUME = 0x40 -PLUGIN_CAN_BALANCE = 0x80 +PLUGIN_IS_BRIDGE = 0x001 +PLUGIN_IS_SYNTH = 0x002 +PLUGIN_HAS_GUI = 0x004 +PLUGIN_USES_CHUNKS = 0x008 +PLUGIN_USES_SINGLE_THREAD = 0x010 +PLUGIN_CAN_DRYWET = 0x020 +PLUGIN_CAN_VOLUME = 0x040 +PLUGIN_CAN_BALANCE = 0x080 +PLUGIN_CAN_FORCE_STEREO = 0x100 # parameter hints PARAMETER_IS_BOOLEAN = 0x01