diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp index 01e53460f..966e24c51 100644 --- a/source/backend/CarlaPlugin.hpp +++ b/source/backend/CarlaPlugin.hpp @@ -34,7 +34,7 @@ CARLA_BACKEND_START_NAMESPACE } // Fix editor indentation #endif -#ifndef BUILD_BRIDGE +#if 1//ndef BUILD_BRIDGE /*! * TODO. */ diff --git a/source/backend/Makefile.mk b/source/backend/Makefile.mk index 9b06125a4..24661960d 100644 --- a/source/backend/Makefile.mk +++ b/source/backend/Makefile.mk @@ -14,10 +14,11 @@ LINK_FLAGS += -lpthread # -------------------------------------------------------------- +BUILD_CXX_FLAGS += -DWANT_NATIVE + ifeq ($(CARLA_PLUGIN_SUPPORT),true) -# BUILD_C_FLAGS += -DWANT_LV2 -# BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST -BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI +BUILD_C_FLAGS += -DWANT_LV2 +BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST endif ifeq ($(CARLA_RTAUDIO_SUPPORT),true) @@ -35,7 +36,7 @@ BUILD_CXX_FLAGS += -DWANT_FLUIDSYNTH endif ifeq ($(HAVE_LINUXSAMPLER),true) -# BUILD_CXX_FLAGS += -DWANT_LINUXSAMPLER +BUILD_CXX_FLAGS += -DWANT_LINUXSAMPLER endif ifeq ($(HAVE_SUIL),true) diff --git a/source/backend/plugin/CarlaBridge.cpp b/source/backend/plugin/BridgePlugin.cpp similarity index 100% rename from source/backend/plugin/CarlaBridge.cpp rename to source/backend/plugin/BridgePlugin.cpp diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 5fac3cecc..7fe1ea406 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -1256,6 +1256,7 @@ void CarlaPlugin::postponeRtEvent(const PluginPostRtEventType type, const int32_ void CarlaPlugin::postRtEventsRun() { + // TODO: optimize unsigned short k = 0; PluginPostRtEvent listData[MAX_RT_EVENTS]; diff --git a/source/backend/plugin/DssiPlugin.cpp b/source/backend/plugin/DssiPlugin.cpp index 60a6aed58..75c0f50db 100644 --- a/source/backend/plugin/DssiPlugin.cpp +++ b/source/backend/plugin/DssiPlugin.cpp @@ -904,7 +904,7 @@ public: // -------------------------------------------------------------------------------------------------------- // Check if not active before - if (! kData->activeBefore) + if (kData->needsReset || ! kData->activeBefore) { if (kData->event.portIn != nullptr) { @@ -931,6 +931,17 @@ public: carla_zeroFloat(kData->latencyBuffers[i], kData->latency); } + if (kData->activeBefore) + { + if (fDescriptor->deactivate != nullptr) + { + fDescriptor->deactivate(fHandle); + + if (fHandle2 != nullptr) + fDescriptor->deactivate(fHandle2); + } + } + if (fDescriptor->activate != nullptr) { fDescriptor->activate(fHandle); @@ -938,6 +949,8 @@ public: if (fHandle2 != nullptr) fDescriptor->activate(fHandle2); } + + kData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- @@ -977,6 +990,7 @@ public: bool sampleAccurate = (fHints & PLUGIN_OPTION_FIXED_BUFFER) == 0; uint32_t time, nEvents = kData->event.portIn->getEventCount(); + uint32_t startTime = 0; uint32_t timeOffset = 0; uint32_t nextBankId = 0; @@ -996,10 +1010,18 @@ public: if (time > timeOffset && sampleAccurate) { - processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset, midiEventCount); - midiEventCount = 0; - nextBankId = 0; - timeOffset = time; + if (processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset, midiEventCount)) + { + midiEventCount = 0; + timeOffset = time; + + if (kData->midiprog.current >= 0 && kData->midiprog.count > 0) + nextBankId = kData->midiprog.data[kData->midiprog.current].bank; + else + nextBankId = 0; + } + else + startTime += timeOffset; } // Control change @@ -1158,8 +1180,7 @@ public: carla_zeroStruct(fMidiEvents[midiEventCount]); - if (! sampleAccurate) - fMidiEvents[midiEventCount].time.tick = time; + fMidiEvents[midiEventCount].time.tick = sampleAccurate ? startTime : time; fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_CONTROLLER; fMidiEvents[midiEventCount].data.control.channel = event.channel; @@ -1183,8 +1204,7 @@ public: carla_zeroStruct(fMidiEvents[midiEventCount]); - if (! sampleAccurate) - fMidiEvents[midiEventCount].time.tick = time; + fMidiEvents[midiEventCount].time.tick = sampleAccurate ? startTime : time; fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_CONTROLLER; fMidiEvents[midiEventCount].data.control.channel = event.channel; @@ -1214,8 +1234,7 @@ public: carla_zeroStruct(fMidiEvents[midiEventCount]); - if (! sampleAccurate) - fMidiEvents[midiEventCount].time.tick = time - timeOffset; + fMidiEvents[midiEventCount].time.tick = sampleAccurate ? startTime : time; if (MIDI_IS_STATUS_NOTE_OFF(status)) { @@ -1321,12 +1340,91 @@ public: CARLA_PROCESS_CONTINUE_CHECK; + // -------------------------------------------------------------------------------------------------------- + // Control Output + + if (kData->event.portOut != nullptr) + { + float value; + + for (k=0; k < kData->param.count; k++) + { + if (kData->param.data[k].type != PARAMETER_OUTPUT) + continue; + + kData->param.ranges[k].fixValue(fParamBuffers[k]); + + if (kData->param.data[k].midiCC > 0) + { + value = kData->param.ranges[k].normalizeValue(fParamBuffers[k]); + kData->event.portOut->writeControlEvent(0, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); + } + } + + } // End of Control Output + + // -------------------------------------------------------------------------------------------------------- + + kData->activeBefore = kData->active; + } + + bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset, const uint32_t midiEventCount) + { + uint32_t i, k; + + // -------------------------------------------------------------------------------------------------------- + // Try lock, silence otherwise + + if (! kData->mutex.tryLock()) + { + for (i=0; i < kData->audioOut.count; i++) + { + for (k=0; k < frames; k++) + outBuffer[i][k+timeOffset] = 0.0f; + } + + return false; + } + + // -------------------------------------------------------------------------------------------------------- + // Fill plugin buffers + + for (i=0; i < kData->audioIn.count; i++) + carla_copyFloat(fAudioInBuffers[i], inBuffer[i]+timeOffset, frames); + for (i=0; i < kData->audioOut.count; i++) + carla_zeroFloat(fAudioOutBuffers[i], frames); + + // -------------------------------------------------------------------------------------------------------- + // Run plugin + + if (fDssiDescriptor->run_synth != nullptr) + { + fDssiDescriptor->run_synth(fHandle, frames, fMidiEvents, midiEventCount); + + if (fHandle2 != nullptr) + fDssiDescriptor->run_synth(fHandle2, frames, fMidiEvents, midiEventCount); + } + else if (fDssiDescriptor->run_multiple_synths != nullptr) + { + unsigned long instances = (fHandle2 != nullptr) ? 2 : 1; + LADSPA_Handle handlePtr[2] = { fHandle, fHandle2 }; + snd_seq_event_t* midiEventsPtr[2] = { fMidiEvents, fMidiEvents }; + unsigned long midiEventCountPtr[2] = { midiEventCount, midiEventCount }; + fDssiDescriptor->run_multiple_synths(instances, handlePtr, frames, midiEventsPtr, midiEventCountPtr); + } + else + { + fDescriptor->run(fHandle, frames); + + if (fHandle2 != nullptr) + fDescriptor->run(fHandle2, frames); + } + // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) { const bool doDryWet = (fHints & PLUGIN_CAN_DRYWET) > 0 && kData->postProc.dryWet != 1.0f; - const bool doVolume = (fHints & PLUGIN_CAN_VOLUME) > 0 && kData->postProc.volume != 1.0f; const bool doBalance = (fHints & PLUGIN_CAN_BALANCE) > 0 && (kData->postProc.balanceLeft != -1.0f || kData->postProc.balanceRight != 1.0f); float bufValue, oldBufLeft[doBalance ? frames : 1]; @@ -1336,17 +1434,6 @@ public: // Dry/Wet if (doDryWet) { -#if 0 - for (k=0; k < frames; k++) - { - if (k < m_latency && m_latency < frames) - bufValue = (aIn.count == 1) ? m_latencyBuffers[0][k] : m_latencyBuffers[i][k]; - else - bufValue = (aIn.count == 1) ? inBuffer[0][k-m_latency] : inBuffer[i][k-m_latency]; - - outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(bufValue*(1.0-x_dryWet)); - } -#endif for (k=0; k < frames; k++) { // TODO @@ -1355,9 +1442,8 @@ public: //else // bufValue = (kData->audioIn.count == 1) ? inBuffer[0][k-m_latency] : inBuffer[i][k-m_latency]; - bufValue = inBuffer[ (kData->audioIn.count == 1) ? 0 : i ][k]; - - outBuffer[i][k] = (outBuffer[i][k] * kData->postProc.dryWet) + (bufValue * (1.0f - kData->postProc.dryWet)); + bufValue = fAudioInBuffers[(kData->audioIn.count == 1) ? 0 : i][k]; + fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * kData->postProc.dryWet) + (bufValue * (1.0f - kData->postProc.dryWet)); } } @@ -1365,7 +1451,7 @@ public: if (doBalance) { if (i % 2 == 0) - carla_copyFloat(oldBufLeft, outBuffer[i], frames); + carla_copyFloat(oldBufLeft, fAudioOutBuffers[i], frames); float balRangeL = (kData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (kData->postProc.balanceRight + 1.0f)/2.0f; @@ -1375,23 +1461,22 @@ public: if (i % 2 == 0) { // left - outBuffer[i][k] = oldBufLeft[k] * (1.0f - balRangeL); - outBuffer[i][k] += outBuffer[i+1][k] * (1.0f - balRangeR); + fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL); + fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR); } else { // right - outBuffer[i][k] = outBuffer[i][k] * balRangeR; - outBuffer[i][k] += oldBufLeft[k] * balRangeL; + fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR; + fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL; } } } - // Volume - if (doVolume) + // Volume (and buffer copy) { for (k=0; k < frames; k++) - outBuffer[i][k] *= kData->postProc.volume; + outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k] * kData->postProc.volume; } } @@ -1405,71 +1490,10 @@ public: #endif } // End of Post-processing - CARLA_PROCESS_CONTINUE_CHECK; - - // -------------------------------------------------------------------------------------------------------- - // Control Output - - if (kData->event.portOut != nullptr) - { - float value; - - for (k=0; k < kData->param.count; k++) - { - if (kData->param.data[k].type != PARAMETER_OUTPUT) - continue; - - kData->param.ranges[k].fixValue(fParamBuffers[k]); - - if (kData->param.data[k].midiCC > 0) - { - value = kData->param.ranges[k].normalizeValue(fParamBuffers[k]); - kData->event.portOut->writeControlEvent(0, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); - } - } - - } // End of Control Output - // -------------------------------------------------------------------------------------------------------- - kData->activeBefore = kData->active; - } - - void processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset, const uint32_t midiEventCount) - { - for (uint32_t i=0; i < kData->audioIn.count; i++) - carla_copyFloat(fAudioInBuffers[i], inBuffer[i]+timeOffset, frames); - for (uint32_t i=0; i < kData->audioOut.count; i++) - carla_zeroFloat(fAudioOutBuffers[i], frames); - - if (fDssiDescriptor->run_synth != nullptr) - { - fDssiDescriptor->run_synth(fHandle, frames, fMidiEvents, midiEventCount); - - if (fHandle2 != nullptr) - fDssiDescriptor->run_synth(fHandle2, frames, fMidiEvents, midiEventCount); - } - else if (fDssiDescriptor->run_multiple_synths != nullptr) - { - unsigned long instances = (fHandle2 != nullptr) ? 2 : 1; - LADSPA_Handle handlePtr[2] = { fHandle, fHandle2 }; - snd_seq_event_t* midiEventsPtr[2] = { fMidiEvents, fMidiEvents }; - unsigned long midiEventCountPtr[2] = { midiEventCount, midiEventCount }; - fDssiDescriptor->run_multiple_synths(instances, handlePtr, frames, midiEventsPtr, midiEventCountPtr); - } - else - { - fDescriptor->run(fHandle, frames); - - if (fHandle2 != nullptr) - fDescriptor->run(fHandle2, frames); - } - - for (uint32_t i=0, k; i < kData->audioOut.count; i++) - { - for (k=0; k < frames; k++) - outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k]; - } + kData->mutex.unlock(); + return true; } void bufferSizeChanged(const uint32_t newBufferSize) diff --git a/source/backend/plugin/FluidSynthPlugin.cpp b/source/backend/plugin/FluidSynthPlugin.cpp index 7851c097b..27b2288c3 100644 --- a/source/backend/plugin/FluidSynthPlugin.cpp +++ b/source/backend/plugin/FluidSynthPlugin.cpp @@ -823,6 +823,7 @@ public: //f_sfont->free(f_sfont); +#ifndef BUILD_BRIDGE // Update OSC Names if (kData->engine->isOscControlRegistered()) { @@ -831,6 +832,7 @@ public: for (i=0; i < kData->midiprog.count; i++) kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name); } +#endif if (init) { @@ -891,7 +893,7 @@ public: // -------------------------------------------------------------------------------------------------------- // Check if active before - if (! kData->activeBefore) + if (kData->needsReset || ! kData->activeBefore) { for (int c=0; c < MAX_MIDI_CHANNELS; c++) { @@ -903,12 +905,14 @@ public: fluid_synth_cc(f_synth, c, MIDI_CONTROL_ALL_NOTES_OFF, 0); #endif } + + kData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- // Event Input and Processing - else + if (kData->activeBefore) { // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) diff --git a/source/backend/plugin/LadspaPlugin.cpp b/source/backend/plugin/LadspaPlugin.cpp index 256aa20e5..6b585d45c 100644 --- a/source/backend/plugin/LadspaPlugin.cpp +++ b/source/backend/plugin/LadspaPlugin.cpp @@ -805,7 +805,7 @@ public: fDescriptor->activate(fHandle2); } - kData->needsReset = false; + kData->needsReset = false; } // -------------------------------------------------------------------------------------------------------- diff --git a/source/backend/plugin/LinuxSamplerPlugin.cpp b/source/backend/plugin/LinuxSamplerPlugin.cpp index e857547bd..dfe75c6a9 100644 --- a/source/backend/plugin/LinuxSamplerPlugin.cpp +++ b/source/backend/plugin/LinuxSamplerPlugin.cpp @@ -15,8 +15,6 @@ * For a full copy of the GNU General Public License see the GPL.txt file */ -// TODO - setMidiProgram() - #include "CarlaPluginInternal.hpp" #ifdef WANT_LINUXSAMPLER @@ -24,6 +22,10 @@ #include "linuxsampler/EngineFactory.h" #include +#include + +// TODO - setMidiProgram() + namespace LinuxSampler { // ----------------------------------------------------------------------- @@ -40,11 +42,11 @@ class AudioOutputDevicePlugin : public AudioOutputDevice public: AudioOutputDevicePlugin(CarlaBackend::CarlaEngine* const engine, CarlaBackend::CarlaPlugin* const plugin) : AudioOutputDevice(std::map()), - m_engine(engine), - m_plugin(plugin) + kEngine(engine), + kPlugin(plugin) { - CARLA_ASSERT(engine); - CARLA_ASSERT(plugin); + CARLA_ASSERT(engine != nullptr); + CARLA_ASSERT(plugin != nullptr); } // ------------------------------------------------------------------- @@ -56,7 +58,7 @@ public: bool IsPlaying() { - return m_engine->isRunning() && m_plugin->enabled(); + return (kEngine->isRunning() && kPlugin->enabled()); } void Stop() @@ -65,12 +67,12 @@ public: uint MaxSamplesPerCycle() { - return m_engine->getBufferSize(); + return kEngine->getBufferSize(); } uint SampleRate() { - return m_engine->getSampleRate(); + return kEngine->getSampleRate(); } String Driver() @@ -86,14 +88,14 @@ public: // ------------------------------------------------------------------- // Give public access to the RenderAudio call - int Render(uint samples) + int Render(const uint samples) { return RenderAudio(samples); } private: - CarlaBackend::CarlaEngine* const m_engine; - CarlaBackend::CarlaPlugin* const m_plugin; + CarlaBackend::CarlaEngine* const kEngine; + CarlaBackend::CarlaPlugin* const kPlugin; }; // ----------------------------------------------------------------------- @@ -129,7 +131,7 @@ public: } // ------------------------------------------------------------------- - // Properly delete port (deconstructor is protected) + // Properly delete port (destructor is protected) void DeleteMidiPort(MidiInputPort* const port) { @@ -138,7 +140,7 @@ public: // ------------------------------------------------------------------- // MIDI Port implementation for this plugin MIDI input driver - // (Constructor and deconstructor are protected) + // (Constructor and destructor are protected) class MidiInputPortPlugin : public MidiInputPort { @@ -155,75 +157,67 @@ public: // ----------------------------------------------------------------------- -#include - CARLA_BACKEND_START_NAMESPACE -/*! - * @defgroup CarlaBackendLinuxSamplerPlugin Carla Backend LinuxSampler Plugin - * - * The Carla Backend LinuxSampler Plugin.\n - * http://www.linuxsampler.org/ - * @{ - */ - class LinuxSamplerPlugin : public CarlaPlugin { public: - LinuxSamplerPlugin(CarlaEngine* const engine_, const unsigned short id, const bool isGIG) - : CarlaPlugin(engine_, id) + LinuxSamplerPlugin(CarlaEngine* const engine, const unsigned short id, const bool isGIG) + : CarlaPlugin(engine, id), + kIsGIG(isGIG) { - carla_debug("LinuxSamplerPlugin::LinuxSamplerPlugin()"); - - m_type = isGIG ? PLUGIN_GIG : PLUGIN_SFZ; + carla_debug("LinuxSamplerPlugin::LinuxSamplerPlugin(%p, %i, %s)", engine, id, bool2str(isGIG)); - sampler = new LinuxSampler::Sampler; - sampler_channel = nullptr; + fSampler = new LinuxSampler::Sampler; + fSamplerChannel = nullptr; - engine = nullptr; - engine_channel = nullptr; - instrument = nullptr; + fEngine = nullptr; + fEngineChannel = nullptr; - audioOutputDevice = new LinuxSampler::AudioOutputDevicePlugin(engine_, this); - midiInputDevice = new LinuxSampler::MidiInputDevicePlugin(sampler); - midiInputPort = midiInputDevice->CreateMidiPort(); + fAudioOutputDevice = new LinuxSampler::AudioOutputDevicePlugin(engine, this); + fMidiInputDevice = new LinuxSampler::MidiInputDevicePlugin(fSampler); + fMidiInputPort = fMidiInputDevice->CreateMidiPort(); - m_isGIG = isGIG; - m_label = nullptr; - m_maker = nullptr; + fInstrument = nullptr; } ~LinuxSamplerPlugin() { carla_debug("LinuxSamplerPlugin::~LinuxSamplerPlugin()"); - if (m_activeBefore) - audioOutputDevice->Stop(); + if (kData->activeBefore) + fAudioOutputDevice->Stop(); - if (sampler_channel) + if (fEngine != nullptr) { - midiInputPort->Disconnect(sampler_channel->GetEngineChannel()); - sampler->RemoveSamplerChannel(sampler_channel); - } - - midiInputDevice->DeleteMidiPort(midiInputPort); + if (fSamplerChannel != nullptr) + { + fMidiInputPort->Disconnect(fSamplerChannel->GetEngineChannel()); + fEngineChannel->DisconnectAudioOutputDevice(); + fSampler->RemoveSamplerChannel(fSamplerChannel); + } - delete audioOutputDevice; - delete midiInputDevice; - delete sampler; + LinuxSampler::EngineFactory::Destroy(fEngine); + } - instrumentIds.clear(); + // destructor is private + fMidiInputDevice->DeleteMidiPort(fMidiInputPort); - if (m_label) - free((void*)m_label); + delete fMidiInputDevice; + delete fAudioOutputDevice; + delete fSampler; - if (m_maker) - free((void*)m_maker); + fInstrumentIds.clear(); } // ------------------------------------------------------------------- // Information (base) + PluginType type() const + { + return kIsGIG ? PLUGIN_GIG : PLUGIN_SFZ; + } + PluginCategory category() { return PLUGIN_CATEGORY_SYNTH; @@ -234,12 +228,12 @@ public: void getLabel(char* const strBuf) { - strncpy(strBuf, m_label, STR_MAX); + std::strncpy(strBuf, (const char*)fLabel, STR_MAX); } void getMaker(char* const strBuf) { - strncpy(strBuf, m_maker, STR_MAX); + std::strncpy(strBuf, (const char*)fMaker, STR_MAX); } void getCopyright(char* const strBuf) @@ -249,7 +243,7 @@ public: void getRealName(char* const strBuf) { - strncpy(strBuf, m_name, STR_MAX); + std::strncpy(strBuf, (const char*)fRealName, STR_MAX); } // ------------------------------------------------------------------- @@ -258,117 +252,103 @@ public: void reload() { carla_debug("LinuxSamplerPlugin::reload() - start"); - CARLA_ASSERT(instrument); + CARLA_ASSERT(kData->engine != nullptr); + CARLA_ASSERT(fInstrument != nullptr); - const ProcessMode processMode(x_engine->getOptions().processMode); + const ProcessMode processMode(kData->engine->getProccessMode()); // Safely disable plugin for reload - const ScopedDisabler m(this); + const ScopedDisabler sd(this); - if (x_client->isActive()) - x_client->deactivate(); + if (kData->client->isActive()) + kData->client->deactivate(); - // Remove client ports - removeClientPorts(); - - // Delete old data deleteBuffers(); uint32_t aOuts; aOuts = 2; - aOut.ports = new CarlaEngineAudioPort*[aOuts]; - aOut.rindexes = new uint32_t[aOuts]; + kData->audioOut.createNew(aOuts); - const int portNameSize = x_engine->maxPortNameSize(); + const int portNameSize = kData->engine->maxPortNameSize(); CarlaString portName; // --------------------------------------- // Audio Outputs { + // out-left portName.clear(); if (processMode == PROCESS_MODE_SINGLE_CLIENT) { - portName = m_name; + portName = fName; portName += ":"; } portName += "out-left"; portName.truncate(portNameSize); - aOut.ports[0] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, false); - aOut.rindexes[0] = 0; - } + kData->audioOut.ports[0].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false); + kData->audioOut.ports[0].rindex = 0; - { + // out-right portName.clear(); if (processMode == PROCESS_MODE_SINGLE_CLIENT) { - portName = m_name; + portName = fName; portName += ":"; } portName += "out-right"; portName.truncate(portNameSize); - aOut.ports[1] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, false); - aOut.rindexes[1] = 1; + kData->audioOut.ports[1].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false); + kData->audioOut.ports[1].rindex = 1; } // --------------------------------------- - // Control Input + // Event Input { portName.clear(); if (processMode == PROCESS_MODE_SINGLE_CLIENT) { - portName = m_name; + portName = fName; portName += ":"; } - portName += "control-in"; + portName += "event-in"; portName.truncate(portNameSize); - param.portCin = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, true); + kData->event.portIn = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true); } // --------------------------------------- - // MIDI Input - - { - portName.clear(); - - if (processMode == PROCESS_MODE_SINGLE_CLIENT) - { - portName = m_name; - portName += ":"; - } - portName += "midi-in"; - portName.truncate(portNameSize); - - midi.portMin = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, true); - } - - // --------------------------------------- + // plugin checks + fHints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO); - aOut.count = aOuts; + fHints |= PLUGIN_IS_SYNTH; + fHints |= PLUGIN_CAN_VOLUME; + fHints |= PLUGIN_CAN_BALANCE; + fHints |= PLUGIN_CAN_FORCE_STEREO; - // plugin checks - m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_CAN_FORCE_STEREO); + // plugin options + kData->availOptions &= ~(PLUGIN_OPTION_FIXED_BUFFER | PLUGIN_OPTION_SELF_AUTOMATION | PLUGIN_OPTION_SEND_ALL_SOUND_OFF | PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH | PLUGIN_OPTION_SEND_PITCHBEND); - m_hints |= PLUGIN_IS_SYNTH; - m_hints |= PLUGIN_CAN_VOLUME; - m_hints |= PLUGIN_CAN_BALANCE; - m_hints |= PLUGIN_CAN_FORCE_STEREO; + // always available if needed + kData->availOptions |= PLUGIN_OPTION_SELF_AUTOMATION; + kData->availOptions |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; + kData->availOptions |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; + kData->availOptions |= PLUGIN_OPTION_SEND_PITCHBEND; + bufferSizeChanged(kData->engine->getBufferSize()); reloadPrograms(true); - x_client->activate(); + kData->client->activate(); carla_debug("LinuxSamplerPlugin::reload() - end"); } @@ -378,55 +358,47 @@ public: carla_debug("LinuxSamplerPlugin::reloadPrograms(%s)", bool2str(init)); // Delete old programs - if (midiprog.count > 0) - { - for (uint32_t i=0; i < midiprog.count; i++) - free((void*)midiprog.data[i].name); - - delete[] midiprog.data; - } - - midiprog.count = 0; - midiprog.data = nullptr; + kData->midiprog.clear(); // Query new programs - uint32_t i = 0; - midiprog.count += instrumentIds.size(); + uint32_t i, count = 0; fInstrumentIds.size(); // sound kits must always have at least 1 midi-program - CARLA_ASSERT(midiprog.count > 0); + CARLA_SAFE_ASSERT(count > 0); // FIXME + + if (count == 0) + return; - if (midiprog.count > 0) - midiprog.data = new MidiProgramData[midiprog.count]; + kData->midiprog.createNew(count); // Update data - for (i=0; i < midiprog.count; i++) + for (i=0; i < kData->midiprog.count; i++) { - LinuxSampler::InstrumentManager::instrument_info_t info = instrument->GetInstrumentInfo(instrumentIds[i]); + LinuxSampler::InstrumentManager::instrument_info_t info = fInstrument->GetInstrumentInfo(fInstrumentIds[i]); - // FIXME - use % 128 stuff - midiprog.data[i].bank = 0; - midiprog.data[i].program = i; - midiprog.data[i].name = strdup(info.InstrumentName.c_str()); + kData->midiprog.data[i].bank = i / 128; + kData->midiprog.data[i].program = i % 128; + kData->midiprog.data[i].name = carla_strdup(info.InstrumentName.c_str()); } +#ifndef BUILD_BRIDGE // Update OSC Names - if (x_engine->isOscControlRegistered()) + if (kData->engine->isOscControlRegistered()) { - x_engine->osc_send_control_set_midi_program_count(m_id, midiprog.count); + kData->engine->osc_send_control_set_midi_program_count(fId, kData->midiprog.count); - for (i=0; i < midiprog.count; i++) - x_engine->osc_send_control_set_midi_program_data(m_id, i, midiprog.data[i].bank, midiprog.data[i].program, midiprog.data[i].name); + for (i=0; i < kData->midiprog.count; i++) + kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name); } +#endif if (init) { - if (midiprog.count > 0) - setMidiProgram(0, false, false, false, true); + setMidiProgram(0, false, false, false, true); } else { - x_engine->callback(CALLBACK_RELOAD_PROGRAMS, m_id, 0, 0, 0.0, nullptr); + kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr); } } @@ -436,509 +408,576 @@ public: void process(float** const, float** const outBuffer, const uint32_t frames) { uint32_t i, k; - uint32_t midiEventCount = 0; - double aOutsPeak[2] = { 0.0 }; + // -------------------------------------------------------------------------------------------------------- + // Check if active + + if (! kData->active) + { + // disable any output sound + for (i=0; i < kData->audioOut.count; i++) + carla_zeroFloat(outBuffer[i], frames); + + if (kData->activeBefore) + fAudioOutputDevice->Stop(); + + kData->activeBefore = kData->active; + return; + } - CARLA_PROCESS_CONTINUE_CHECK; + // -------------------------------------------------------------------------------------------------------- + // Check if not active before + + if (kData->needsReset || ! kData->activeBefore) + { + if (kData->event.portIn != nullptr) + { + for (k=0, i=MAX_MIDI_CHANNELS; k < MAX_MIDI_CHANNELS; k++) + { + fMidiInputPort->DispatchControlChange(MIDI_CONTROL_ALL_SOUND_OFF, 0, k, 0); + fMidiInputPort->DispatchControlChange(MIDI_CONTROL_ALL_NOTES_OFF, 0, k, 0); + } + } + + if (kData->activeBefore) + fAudioOutputDevice->Stop(); + + fAudioOutputDevice->Play(); + + kData->needsReset = false; + } // -------------------------------------------------------------------------------------------------------- - // Parameters Input [Automation] + // Event Input and Processing - if (m_active && m_activeBefore) + if (kData->event.portIn != nullptr && kData->activeBefore) { + // ---------------------------------------------------------------------------------------------------- + // MIDI Input (External) + + if (kData->extNotes.mutex.tryLock()) + { + while (! kData->extNotes.data.isEmpty()) + { + const ExternalMidiNote& note = kData->extNotes.data.getFirst(true); + + CARLA_ASSERT(note.channel >= 0); + + if (note.velo > 0) + fMidiInputPort->DispatchNoteOn(note.note, note.velo, note.channel, 0); + else + fMidiInputPort->DispatchNoteOff(note.note, note.velo, note.channel, 0); + } + + kData->extNotes.mutex.unlock(); + + } // End of MIDI Input (External) + + // ---------------------------------------------------------------------------------------------------- + // Event Input (System) + bool allNotesOffSent = false; + bool sampleAccurate = (fHints & PLUGIN_OPTION_FIXED_BUFFER) == 0; - const CarlaEngineControlEvent* cinEvent; - uint32_t time, nEvents = param.portCin->getEventCount(); + uint32_t time, nEvents = kData->event.portIn->getEventCount(); + uint32_t startTime = 0; + uint32_t timeOffset = 0; uint32_t nextBankId = 0; - if (midiprog.current >= 0 && midiprog.count > 0) - nextBankId = midiprog.data[midiprog.current].bank; + if (kData->midiprog.current >= 0 && kData->midiprog.count > 0) + nextBankId = kData->midiprog.data[kData->midiprog.current].bank; for (i=0; i < nEvents; i++) { - cinEvent = param.portCin->getEvent(i); + const EngineEvent& event = kData->event.portIn->getEvent(i); - if (! cinEvent) - continue; - - time = cinEvent->time; + time = event.time; if (time >= frames) continue; + CARLA_ASSERT_INT2(time >= timeOffset, time, timeOffset); + + if (time > timeOffset && sampleAccurate) + { + if (processSingle(outBuffer, time - timeOffset, timeOffset)) + { + timeOffset = time; + + if (kData->midiprog.current >= 0 && kData->midiprog.count > 0) + nextBankId = kData->midiprog.data[kData->midiprog.current].bank; + else + nextBankId = 0; + } + else + startTime += timeOffset; + } + // Control change - switch (cinEvent->type) + switch (event.type) { - case CarlaEngineNullEvent: + case kEngineEventTypeNull: break; - case CarlaEngineParameterChangeEvent: + case kEngineEventTypeControl: { - double value; + const EngineControlEvent& ctrlEvent = event.ctrl; - // Control backend stuff - if (cinEvent->channel == m_ctrlInChannel) + switch (ctrlEvent.type) { - if (MIDI_IS_CONTROL_BREATH_CONTROLLER(cinEvent->parameter) && (m_hints & PLUGIN_CAN_DRYWET) > 0) - { - value = cinEvent->value; - setDryWet(value, false, false); - postponeEvent(PluginPostEventParameterChange, PARAMETER_DRYWET, 0, value); - continue; - } - - if (MIDI_IS_CONTROL_CHANNEL_VOLUME(cinEvent->parameter) && (m_hints & PLUGIN_CAN_VOLUME) > 0) - { - value = cinEvent->value*127/100; - setVolume(value, false, false); - postponeEvent(PluginPostEventParameterChange, PARAMETER_VOLUME, 0, value); - continue; - } + case kEngineControlEventTypeNull: + break; - if (MIDI_IS_CONTROL_BALANCE(cinEvent->parameter) && (m_hints & PLUGIN_CAN_BALANCE) > 0) + case kEngineControlEventTypeParameter: + { + // Control backend stuff + if (event.channel == kData->ctrlChannel) { - double left, right; - value = cinEvent->value/0.5 - 1.0; + double value; - if (value < 0.0) + if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (fHints & PLUGIN_CAN_DRYWET) > 0) { - left = -1.0; - right = (value*2)+1.0; + value = ctrlEvent.value; + setDryWet(value, false, false); + postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value); + continue; } - else if (value > 0.0) + + if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (fHints & PLUGIN_CAN_VOLUME) > 0) { - left = (value*2)-1.0; - right = 1.0; + value = ctrlEvent.value*127/100; + setVolume(value, false, false); + postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value); + continue; } - else + + if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (fHints & PLUGIN_CAN_BALANCE) > 0) { - left = -1.0; - right = 1.0; + double left, right; + value = ctrlEvent.value/0.5 - 1.0; + + if (value < 0.0) + { + left = -1.0; + right = (value*2)+1.0; + } + else if (value > 0.0) + { + left = (value*2)-1.0; + right = 1.0; + } + else + { + left = -1.0; + right = 1.0; + } + + setBalanceLeft(left, false, false); + setBalanceRight(right, false, false); + postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left); + postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right); + continue; } - - setBalanceLeft(left, false, false); - setBalanceRight(right, false, false); - postponeEvent(PluginPostEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left); - postponeEvent(PluginPostEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right); - continue; } - } -#if 0 - // Control plugin parameters - for (k=0; k < param.count; k++) - { - if (param.data[k].midiChannel != cinEvent->channel) - continue; - if (param.data[k].midiCC != cinEvent->parameter) - continue; - if (param.data[k].type != PARAMETER_INPUT) - continue; - - if (param.data[k].hints & PARAMETER_IS_AUTOMABLE) + // Control plugin parameters + for (k=0; k < kData->param.count; k++) { - if (param.data[k].hints & PARAMETER_IS_BOOLEAN) + if (kData->param.data[k].midiChannel != event.channel) + continue; + if (kData->param.data[k].midiCC != ctrlEvent.param) + continue; + if (kData->param.data[k].type != PARAMETER_INPUT) + continue; + if ((kData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) + continue; + + double value; + + if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN) { - value = cinEvent->value < 0.5 ? param.ranges[k].min : param.ranges[k].max; + value = (ctrlEvent.value < 0.5) ? kData->param.ranges[k].min : kData->param.ranges[k].max; } else { - value = cinEvent->value * (param.ranges[k].max - param.ranges[k].min) + param.ranges[k].min; + // FIXME - ranges call for this + value = ctrlEvent.value * (kData->param.ranges[k].max - kData->param.ranges[k].min) + kData->param.ranges[k].min; - if (param.data[k].hints & PARAMETER_IS_INTEGER) - value = rint(value); + if (kData->param.data[k].hints & PARAMETER_IS_INTEGER) + value = std::rint(value); } setParameterValue(k, value, false, false, false); - postponeEvent(PluginPostEventParameterChange, k, 0, value); + postponeRtEvent(kPluginPostRtEventParameterChange, k, 0, value); } - } -#endif - break; - } - - case CarlaEngineMidiBankChangeEvent: - if (cinEvent->channel == m_ctrlInChannel) - nextBankId = rint(cinEvent->value); - break; + break; + } - case CarlaEngineMidiProgramChangeEvent: - if (cinEvent->channel == m_ctrlInChannel) - { - uint32_t nextProgramId = rint(cinEvent->value); + case kEngineControlEventTypeMidiBank: + if (event.channel == kData->ctrlChannel) + nextBankId = ctrlEvent.param; + break; - for (k=0; k < midiprog.count; k++) + case kEngineControlEventTypeMidiProgram: + if (event.channel == kData->ctrlChannel) { - if (midiprog.data[k].bank == nextBankId && midiprog.data[k].program == nextProgramId) + const uint32_t nextProgramId = ctrlEvent.param; + + for (k=0; k < kData->midiprog.count; k++) { - setMidiProgram(k, false, false, false, false); - postponeEvent(PluginPostEventMidiProgramChange, k, 0, 0.0); - break; + if (kData->midiprog.data[k].bank == nextBankId && kData->midiprog.data[k].program == nextProgramId) + { + setMidiProgram(k, false, false, false, false); + postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0); + break; + } } } - } - break; - - case CarlaEngineAllSoundOffEvent: - if (cinEvent->channel == m_ctrlInChannel) - { - if (midi.portMin && ! allNotesOffSent) - sendMidiAllNotesOff(); + break; - audioOutputDevice->Stop(); - audioOutputDevice->Play(); + case kEngineControlEventTypeAllSoundOff: + if (event.channel == kData->ctrlChannel) + { + if (! allNotesOffSent) + sendMidiAllNotesOff(); - postponeEvent(PluginPostEventParameterChange, PARAMETER_ACTIVE, 0, 0.0); - postponeEvent(PluginPostEventParameterChange, PARAMETER_ACTIVE, 0, 1.0); + fAudioOutputDevice->Stop(); + fAudioOutputDevice->Play(); - allNotesOffSent = true; - } - break; + postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 0.0); + postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 1.0); - case CarlaEngineAllNotesOffEvent: - if (cinEvent->channel == m_ctrlInChannel) - { - if (midi.portMin && ! allNotesOffSent) - sendMidiAllNotesOff(); + allNotesOffSent = true; + } - allNotesOffSent = true; - } - break; - } - } - } // End of Parameters Input + fMidiInputPort->DispatchControlChange(MIDI_CONTROL_ALL_SOUND_OFF, 0, k, sampleAccurate ? startTime : time); - CARLA_PROCESS_CONTINUE_CHECK; + break; - // -------------------------------------------------------------------------------------------------------- - // MIDI Input + case kEngineControlEventTypeAllNotesOff: + if (event.channel == kData->ctrlChannel) + { + if (! allNotesOffSent) + sendMidiAllNotesOff(); - if (m_active && m_activeBefore) - { - // ---------------------------------------------------------------------------------------------------- - // MIDI Input (External) + allNotesOffSent = true; + } - { - engineMidiLock(); + fMidiInputPort->DispatchControlChange(MIDI_CONTROL_ALL_NOTES_OFF, 0, k, sampleAccurate ? startTime : time); - for (i=0; i < MAX_MIDI_EVENTS && midiEventCount < MAX_MIDI_EVENTS; i++) - { - if (extMidiNotes[i].channel < 0) break; + } - if (extMidiNotes[i].velo) - midiInputPort->DispatchNoteOn(extMidiNotes[i].note, extMidiNotes[i].velo, m_ctrlInChannel, 0); - else - midiInputPort->DispatchNoteOff(extMidiNotes[i].note, extMidiNotes[i].velo, m_ctrlInChannel, 0); - - extMidiNotes[i].channel = -1; // mark as invalid - midiEventCount += 1; + break; } - engineMidiUnlock(); - - } // End of MIDI Input (External) - - CARLA_PROCESS_CONTINUE_CHECK; - - // ---------------------------------------------------------------------------------------------------- - // MIDI Input (System) - - { - const CarlaEngineMidiEvent* minEvent; - uint32_t time, nEvents = midi.portMin->getEventCount(); - - for (i=0; i < nEvents && midiEventCount < MAX_MIDI_EVENTS; i++) + case kEngineEventTypeMidi: { - minEvent = midi.portMin->getEvent(i); - - if (! minEvent) - continue; - - time = minEvent->time; - - if (time >= frames) - continue; + const EngineMidiEvent& midiEvent = event.midi; - uint8_t status = minEvent->data[0]; - uint8_t channel = status & 0x0F; + uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent.data); + uint8_t channel = event.channel; - // Fix bad note-off - if (MIDI_IS_STATUS_NOTE_ON(status) && minEvent->data[2] == 0) + // Fix bad note-off (per DSSI spec) + if (MIDI_IS_STATUS_NOTE_ON(status) && midiEvent.data[2] == 0) status -= 0x10; + int32_t fragmentPos = sampleAccurate ? startTime : time; + if (MIDI_IS_STATUS_NOTE_OFF(status)) { - uint8_t note = minEvent->data[1]; + const uint8_t note = midiEvent.data[1]; - midiInputPort->DispatchNoteOff(note, 0, channel, time); + fMidiInputPort->DispatchNoteOff(note, 0, channel, fragmentPos); - postponeEvent(PluginPostEventNoteOff, channel, note, 0.0); + postponeRtEvent(kPluginPostRtEventNoteOff, channel, note, 0.0); } else if (MIDI_IS_STATUS_NOTE_ON(status)) { - uint8_t note = minEvent->data[1]; - uint8_t velo = minEvent->data[2]; + const uint8_t note = midiEvent.data[1]; + const uint8_t velo = midiEvent.data[2]; - midiInputPort->DispatchNoteOn(note, velo, channel, time); + fMidiInputPort->DispatchNoteOn(note, velo, channel, fragmentPos); - postponeEvent(PluginPostEventNoteOn, channel, note, velo); + postponeRtEvent(kPluginPostRtEventNoteOn, channel, note, velo); } else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status)) { - //uint8_t note = minEvent->data[1]; - //uint8_t pressure = minEvent->data[2]; + //const uint8_t note = midiEvent.data[1]; + //const uint8_t pressure = midiEvent.data[2]; - // TODO, not in linuxsampler API? + // unsupported + } + else if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (fHints & PLUGIN_OPTION_SELF_AUTOMATION) != 0) + { + const uint8_t control = midiEvent.data[1]; + const uint8_t value = midiEvent.data[2]; + + fMidiInputPort->DispatchControlChange(control, value, channel, fragmentPos); } else if (MIDI_IS_STATUS_AFTERTOUCH(status)) { - uint8_t pressure = minEvent->data[1]; + //const uint8_t pressure = midiEvent.data[1]; - midiInputPort->DispatchControlChange(MIDI_STATUS_AFTERTOUCH, pressure, channel, time); + // unsupported } else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status)) { - uint8_t lsb = minEvent->data[1]; - uint8_t msb = minEvent->data[2]; + const uint8_t lsb = midiEvent.data[1]; + const uint8_t msb = midiEvent.data[2]; - midiInputPort->DispatchPitchbend(((msb << 7) | lsb) - 8192, channel, time); + fMidiInputPort->DispatchPitchbend(((msb << 7) | lsb) - 8192, channel, fragmentPos); } - else - continue; - midiEventCount += 1; + break; + } } - } // End of MIDI Input (System) + } + + kData->postRtEvents.trySplice(); - } // End of MIDI Input + if (frames > timeOffset) + processSingle(outBuffer, frames - timeOffset, timeOffset); - CARLA_PROCESS_CONTINUE_CHECK; + } // End of Event Input and Processing // -------------------------------------------------------------------------------------------------------- - // Plugin processing + // Plugin processing (no events) - if (m_active) + else { - if (! m_activeBefore) - { - for (int c=0; c < MAX_MIDI_CHANNELS; c++) - { - midiInputPort->DispatchControlChange(MIDI_CONTROL_ALL_SOUND_OFF, 0, c); - midiInputPort->DispatchControlChange(MIDI_CONTROL_ALL_NOTES_OFF, 0, c); - } + processSingle(outBuffer, frames, 0); - audioOutputDevice->Play(); - } + } // End of Plugin processing (no events) - audioOutputDevice->Channel(0)->SetBuffer(outBuffer[0]); - audioOutputDevice->Channel(1)->SetBuffer(outBuffer[1]); - // QUESTION: Need to clear it before? - audioOutputDevice->Render(frames); - } - else + // -------------------------------------------------------------------------------------------------------- + + kData->activeBefore = kData->active; + } + + bool processSingle(float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) + { + uint32_t i, k; + + // -------------------------------------------------------------------------------------------------------- + // Try lock, silence otherwise + + if (! kData->mutex.tryLock()) { - if (m_activeBefore) - audioOutputDevice->Stop(); + for (i=0; i < kData->audioOut.count; i++) + { + for (k=0; k < frames; k++) + outBuffer[i][k+timeOffset] = 0.0f; + } + + return false; } - CARLA_PROCESS_CONTINUE_CHECK; + // -------------------------------------------------------------------------------------------------------- + // Run plugin + + fAudioOutputDevice->Channel(0)->SetBuffer(outBuffer[0] + timeOffset); + fAudioOutputDevice->Channel(1)->SetBuffer(outBuffer[1] + timeOffset); + // QUESTION: Need to clear it before? + fAudioOutputDevice->Render(frames); // -------------------------------------------------------------------------------------------------------- // Post-processing (dry/wet, volume and balance) - if (m_active) { - bool do_volume = x_volume != 1.0; - bool do_balance = (x_balanceLeft != -1.0 || x_balanceRight != 1.0); + const bool doVolume = (fHints & PLUGIN_CAN_VOLUME) > 0 && kData->postProc.volume != 1.0f; + const bool doBalance = (fHints & PLUGIN_CAN_BALANCE) > 0 && (kData->postProc.balanceLeft != -1.0f || kData->postProc.balanceRight != 1.0f); - double bal_rangeL, bal_rangeR; - float oldBufLeft[do_balance ? frames : 0]; + float oldBufLeft[doBalance ? frames : 1]; - for (i=0; i < aOut.count; i++) + for (i=0; i < kData->audioOut.count; i++) { // Balance - if (do_balance) + if (doBalance) { - if (i%2 == 0) + if (i % 2 == 0) carla_copyFloat(oldBufLeft, outBuffer[i], frames); - bal_rangeL = (x_balanceLeft+1.0)/2; - bal_rangeR = (x_balanceRight+1.0)/2; + float balRangeL = (kData->postProc.balanceLeft + 1.0f)/2.0f; + float balRangeR = (kData->postProc.balanceRight + 1.0f)/2.0f; for (k=0; k < frames; k++) { - if (i%2 == 0) + if (i % 2 == 0) { - // left output - outBuffer[i][k] = oldBufLeft[k]*(1.0-bal_rangeL); - outBuffer[i][k] += outBuffer[i+1][k]*(1.0-bal_rangeR); + // left + outBuffer[i][k] = oldBufLeft[k] * (1.0f - balRangeL); + outBuffer[i][k] += outBuffer[i+1][k] * (1.0f - balRangeR); } else { // right - outBuffer[i][k] = outBuffer[i][k]*bal_rangeR; - outBuffer[i][k] += oldBufLeft[k]*bal_rangeL; + outBuffer[i][k] = outBuffer[i][k] * balRangeR; + outBuffer[i][k] += oldBufLeft[k] * balRangeL; } } } // Volume - if (do_volume) + if (doVolume) { for (k=0; k < frames; k++) - outBuffer[i][k] *= x_volume; - } - - // Output VU - if (x_engine->getOptions().processMode != PROCESS_MODE_CONTINUOUS_RACK) - { - for (k=0; i < 2 && k < frames; k++) - { - if (std::abs(outBuffer[i][k]) > aOutsPeak[i]) - aOutsPeak[i] = std::abs(outBuffer[i][k]); - } + outBuffer[i][k+timeOffset] *= kData->postProc.volume; } } - } - else - { - // disable any output sound if not active - for (i=0; i < aOut.count; i++) - carla_zeroF(outBuffer[i], frames); - - aOutsPeak[0] = 0.0; - aOutsPeak[1] = 0.0; } // End of Post-processing - CARLA_PROCESS_CONTINUE_CHECK; - // -------------------------------------------------------------------------------------------------------- - // Peak Values - - x_engine->setOutputPeak(m_id, 0, aOutsPeak[0]); - x_engine->setOutputPeak(m_id, 1, aOutsPeak[1]); - m_activeBefore = m_active; + kData->mutex.unlock(); + return true; } // ------------------------------------------------------------------- bool init(const char* filename, const char* const name, const char* label) { - QFileInfo file(filename); + CARLA_ASSERT(kData->engine != nullptr); + CARLA_ASSERT(kData->client == nullptr); + CARLA_ASSERT(filename != nullptr); + CARLA_ASSERT(label != nullptr); - if (file.exists() && file.isFile() && file.isReadable()) + // --------------------------------------------------------------- + // Check if file exists { - const char* stype = m_isGIG ? "gig" : "sfz"; + QFileInfo file(filename); - try { - engine = LinuxSampler::EngineFactory::Create(stype); - } - catch (LinuxSampler::Exception& e) + if (! (file.exists() && file.isFile() && file.isReadable())) { - x_engine->setLastError(e.what()); + kData->engine->setLastError("Requested file is not valid or does not exist"); return false; } + } - try { - instrument = engine->GetInstrumentManager(); - } - catch (LinuxSampler::Exception& e) - { - x_engine->setLastError(e.what()); - return false; - } + // --------------------------------------------------------------- + // Create the LinuxSampler Engine + const char* const stype = kIsGIG ? "gig" : "sfz"; - try { - instrumentIds = instrument->GetInstrumentFileContent(filename); - } - catch (LinuxSampler::Exception& e) - { - x_engine->setLastError(e.what()); - return false; - } + try { + fEngine = LinuxSampler::EngineFactory::Create(stype); + } + catch (LinuxSampler::Exception& e) + { + kData->engine->setLastError(e.what()); + return false; + } - if (instrumentIds.size() > 0) - { - LinuxSampler::InstrumentManager::instrument_info_t info = instrument->GetInstrumentInfo(instrumentIds[0]); - - m_label = strdup(info.Product.c_str()); - m_maker = strdup(info.Artists.c_str()); - m_filename = strdup(filename); - - if (name) - m_name = x_engine->getUniquePluginName(name); - else - m_name = x_engine->getUniquePluginName(label && label[0] ? label : info.InstrumentName.c_str()); - - sampler_channel = sampler->AddSamplerChannel(); - sampler_channel->SetEngineType(stype); - sampler_channel->SetAudioOutputDevice(audioOutputDevice); - //sampler_channel->SetMidiInputDevice(midiInputDevice); - //sampler_channel->SetMidiInputChannel(LinuxSampler::midi_chan_1); - midiInputPort->Connect(sampler_channel->GetEngineChannel(), LinuxSampler::midi_chan_all); - - engine_channel = sampler_channel->GetEngineChannel(); - engine_channel->Connect(audioOutputDevice); - engine_channel->PrepareLoadInstrument(filename, 0); // todo - find instrument from label - engine_channel->LoadInstrument(); - engine_channel->Volume(LinuxSampler::VOLUME_MAX); - - x_client = x_engine->addClient(this); - - if (x_client->isOk()) - return true; - else - x_engine->setLastError("Failed to register plugin client"); - } - else - x_engine->setLastError("Failed to find any instruments"); + // --------------------------------------------------------------- + // Get the Engine's Instrument Manager + + try { + fInstrument = fEngine->GetInstrumentManager(); + } + catch (LinuxSampler::Exception& e) + { + kData->engine->setLastError(e.what()); + LinuxSampler::EngineFactory::Destroy(fEngine); + return false; + } + + // --------------------------------------------------------------- + // Load the Instrument via filename + + try { + fInstrumentIds = fInstrument->GetInstrumentFileContent(filename); + } + catch (LinuxSampler::Exception& e) + { + kData->engine->setLastError(e.what()); + LinuxSampler::EngineFactory::Destroy(fEngine); + return false; + } + + // --------------------------------------------------------------- + // Get info + + if (fInstrumentIds.size() == 0) + { + kData->engine->setLastError("Failed to find any instruments"); + LinuxSampler::EngineFactory::Destroy(fEngine); + return false; } else - x_engine->setLastError("Requested file is not valid or does not exist"); + { + LinuxSampler::InstrumentManager::instrument_info_t info = fInstrument->GetInstrumentInfo(fInstrumentIds[0]); + + fRealName = info.InstrumentName.c_str(); + fLabel = info.Product.c_str(); + fMaker = info.Artists.c_str(); + fFilename = filename; + + if (name != nullptr) + fName = kData->engine->getNewUniquePluginName(name); + else + fName = kData->engine->getNewUniquePluginName((const char*)fRealName); + } + + // --------------------------------------------------------------- + // Register client + + kData->client = kData->engine->addClient(this); + + if (kData->client == nullptr || ! kData->client->isOk()) + { + kData->engine->setLastError("Failed to register plugin client"); + LinuxSampler::EngineFactory::Destroy(fEngine); + return false; + } + + // --------------------------------------------------------------- + // Init LinuxSampler stuff + + fSamplerChannel = fSampler->AddSamplerChannel(); + fSamplerChannel->SetEngineType(stype); + fSamplerChannel->SetAudioOutputDevice(fAudioOutputDevice); + + fEngineChannel = fSamplerChannel->GetEngineChannel(); + fEngineChannel->Connect(fAudioOutputDevice); + fEngineChannel->PrepareLoadInstrument(filename, 0); // todo - find instrument from label + fEngineChannel->LoadInstrument(); + fEngineChannel->Volume(LinuxSampler::VOLUME_MAX); - return false; + fMidiInputPort->Connect(fSamplerChannel->GetEngineChannel(), LinuxSampler::midi_chan_all); + + return true; } // ------------------------------------------------------------------- - static CarlaPlugin* newLinuxSampler(const initializer& init, bool isGIG); + static CarlaPlugin* newLinuxSampler(const Initializer& init, bool isGIG); private: - LinuxSampler::Sampler* sampler; - LinuxSampler::SamplerChannel* sampler_channel; - LinuxSampler::Engine* engine; - LinuxSampler::EngineChannel* engine_channel; - LinuxSampler::InstrumentManager* instrument; - std::vector instrumentIds; - - LinuxSampler::AudioOutputDevicePlugin* audioOutputDevice; - LinuxSampler::MidiInputDevicePlugin* midiInputDevice; - LinuxSampler::MidiInputPort* midiInputPort; - - bool m_isGIG; - const char* m_label; - const char* m_maker; + const bool kIsGIG; + CarlaString fRealName; + CarlaString fLabel; + CarlaString fMaker; + + LinuxSampler::Sampler* fSampler; + LinuxSampler::SamplerChannel* fSamplerChannel; + + LinuxSampler::Engine* fEngine; + LinuxSampler::EngineChannel* fEngineChannel; + + LinuxSampler::AudioOutputDevicePlugin* fAudioOutputDevice; + LinuxSampler::MidiInputDevicePlugin* fMidiInputDevice; + LinuxSampler::MidiInputPort* fMidiInputPort; + + LinuxSampler::InstrumentManager* fInstrument; + std::vector fInstrumentIds; }; CarlaPlugin* LinuxSamplerPlugin::newLinuxSampler(const Initializer& init, bool isGIG) { - carla_debug("LinuxSamplerPlugin::newLinuxSampler(%p, \"%s\", \"%s\", \"%s\", %s)", init.engine, init.filename, init.name, init.label, bool2str(isGIG)); + carla_debug("LinuxSamplerPlugin::newLinuxSampler({%p, \"%s\", \"%s\", \"%s\"}, %s)", init.engine, init.filename, init.name, init.label, bool2str(isGIG)); - short id = init.engine->getNewPluginId(); - - if (id < 0 || id > init.engine->maxPluginNumber()) - { - init.engine->setLastError("Maximum number of plugins reached"); - return nullptr; - } - - LinuxSamplerPlugin* const plugin = new LinuxSamplerPlugin(init.engine, id, isGIG); + LinuxSamplerPlugin* const plugin = new LinuxSamplerPlugin(init.engine, init.id, isGIG); if (! plugin->init(init.filename, init.name, init.label)) { @@ -952,19 +991,17 @@ CarlaPlugin* LinuxSamplerPlugin::newLinuxSampler(const Initializer& init, bool i return plugin; } -/**@}*/ - CARLA_BACKEND_END_NAMESPACE #else // WANT_LINUXSAMPLER -//# warning linuxsampler not available (no GIG and SFZ support) +# warning linuxsampler not available (no GIG and SFZ support) #endif CARLA_BACKEND_START_NAMESPACE CarlaPlugin* CarlaPlugin::newGIG(const Initializer& init) { - carla_debug("CarlaPlugin::newGIG(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label); + carla_debug("CarlaPlugin::newGIG({%p, \"%s\", \"%s\", \"%s\"})", init.engine, init.filename, init.name, init.label); #ifdef WANT_LINUXSAMPLER return LinuxSamplerPlugin::newLinuxSampler(init, true); #else @@ -975,7 +1012,7 @@ CarlaPlugin* CarlaPlugin::newGIG(const Initializer& init) CarlaPlugin* CarlaPlugin::newSFZ(const Initializer& init) { - carla_debug("CarlaPlugin::newSFZ(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label); + carla_debug("CarlaPlugin::newSFZ({%p, \"%s\", \"%s\", \"%s\"})", init.engine, init.filename, init.name, init.label); #ifdef WANT_LINUXSAMPLER return LinuxSamplerPlugin::newLinuxSampler(init, false); #else diff --git a/source/backend/plugin/Lv2Plugin.cpp b/source/backend/plugin/Lv2Plugin.cpp index 290144190..28c4972c8 100644 --- a/source/backend/plugin/Lv2Plugin.cpp +++ b/source/backend/plugin/Lv2Plugin.cpp @@ -19,11 +19,14 @@ #ifdef WANT_LV2 -#include "carla_lib_utils.hpp" -#include "carla_lv2_utils.hpp" +#include "CarlaLv2Utils.hpp" +#include "CarlaLibUtils.hpp" -#include "lv2_atom_queue.hpp" +#include "Lv2AtomQueue.hpp" + +extern "C" { #include "rtmempool/rtmempool.h" +} #include @@ -43,14 +46,7 @@ struct SuilInstanceImpl { CARLA_BACKEND_START_NAMESPACE -/*! - * @defgroup CarlaBackendLv2Plugin Carla Backend LV2 Plugin - * - * The Carla Backend LV2 Plugin.\n - * http://lv2plug.in/ - * @{ - */ - +#if 0 // static max values const unsigned int MAX_EVENT_BUFFER = 8192; // 0x2000 @@ -143,10 +139,12 @@ const uint32_t CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE = 18; const uint32_t CARLA_URI_MAP_ID_COUNT = 19; /**@}*/ +// ----------------------------------------------------- + struct Lv2EventData { uint32_t type; uint32_t rindex; - CarlaEngineMidiPort* port; + CarlaEngineEventPort* port; union { LV2_Atom_Sequence* atom; LV2_Event_Buffer* event; @@ -186,13 +184,22 @@ struct Lv2PluginOptions { sampleRate(0.0) {} }; +// ----------------------------------------------------- + Lv2PluginOptions lv2Options; +#endif + +Lv2WorldClass lv2World; + +// ----------------------------------------------------- LV2_Atom_Event* getLv2AtomEvent(LV2_Atom_Sequence* const atom, const uint32_t offset) { return (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atom) + offset); } +// ----------------------------------------------------- + class Lv2Plugin : public CarlaPlugin { public: @@ -201,6 +208,7 @@ public: { carla_debug("Lv2Plugin::Lv2Plugin(%p, %i)", engine, id); +#if 0 m_type = PLUGIN_LV2; m_count += 1; @@ -309,6 +317,7 @@ public: ft.options[3] = lv2Options.oSampleRate; ft.options[4] = lv2Options.oNull; } +#endif lv2World.init(); } @@ -316,6 +325,7 @@ public: ~Lv2Plugin() { carla_debug("Lv2Plugin::~Lv2Plugin()"); +#if 0 m_count -= 1; // close UI @@ -486,11 +496,18 @@ public: ft.stateMakePath = nullptr; ft.stateMapPath = nullptr; } +#endif } // ------------------------------------------------------------------- // Information (base) + PluginType type() const + { + return PLUGIN_LV2; + } + +#if 0 PluginCategory category() { CARLA_ASSERT(rdf_descriptor); @@ -4518,8 +4535,10 @@ public: return true; } +#endif private: +#if 0 LV2_Handle handle, h2; const LV2_Descriptor* descriptor; const LV2_RDF_Descriptor* rdf_descriptor; @@ -4576,20 +4595,20 @@ private: LV2_State_Make_Path* stateMakePath; LV2_State_Map_Path* stateMapPath; } ft; +#endif }; -/**@}*/ - // ------------------------------------------------------------------- // static data -unsigned int Lv2Plugin::m_count = 0; -std::set Lv2Plugin::libDescs; +//unsigned int Lv2Plugin::m_count = 0; +//std::set Lv2Plugin::libDescs; -Lv2Plugin::Ft Lv2Plugin::ft = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; +//Lv2Plugin::Ft Lv2Plugin::ft = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; // ------------------------------------------------------------------------------------------------------------------- +#if 0 int CarlaEngineOsc::handleMsgLv2AtomTransfer(CARLA_ENGINE_OSC_HANDLE_ARGS2) { carla_debug("CarlaOsc::handleMsgLv2AtomTransfer()"); @@ -4631,11 +4650,12 @@ int CarlaEngineOsc::handleMsgLv2EventTransfer(CARLA_ENGINE_OSC_HANDLE_ARGS2) return 0; } +#endif CARLA_BACKEND_END_NAMESPACE #else // WANT_LV2 -//# warning Building without LV2 support +# warning Building without LV2 support #endif CARLA_BACKEND_START_NAMESPACE @@ -4645,17 +4665,9 @@ CarlaPlugin* CarlaPlugin::newLV2(const Initializer& init) carla_debug("CarlaPlugin::newLV2(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label); #ifdef WANT_LV2 - short id = init.engine->getNewPluginId(); - - if (id < 0 || id > init.engine->maxPluginNumber()) - { - init.engine->setLastError("Maximum number of plugins reached"); - return nullptr; - } - - Lv2Plugin* const plugin = new Lv2Plugin(init.engine, id); + Lv2Plugin* const plugin = new Lv2Plugin(init.engine, init.id); - if (! plugin->init(init.filename, init.name, init.label)) + //if (! plugin->init(init.filename, init.name, init.label)) { delete plugin; return nullptr; @@ -4663,7 +4675,7 @@ CarlaPlugin* CarlaPlugin::newLV2(const Initializer& init) plugin->reload(); - if (init.engine->getOptions().processMode == PROCESS_MODE_CONTINUOUS_RACK) + if (init.engine->getProccessMode() == PROCESS_MODE_CONTINUOUS_RACK) { if (! (plugin->hints() & PLUGIN_CAN_FORCE_STEREO)) { @@ -4674,7 +4686,7 @@ CarlaPlugin* CarlaPlugin::newLV2(const Initializer& init) } plugin->registerToOscClient(); - plugin->updateUi(); + //plugin->updateUi(); return plugin; #else diff --git a/source/backend/plugin/Makefile b/source/backend/plugin/Makefile index 0a35ecffd..7c7c0f919 100644 --- a/source/backend/plugin/Makefile +++ b/source/backend/plugin/Makefile @@ -31,7 +31,7 @@ endif OBJS = \ CarlaPlugin.cpp.o \ CarlaPluginThread.cpp.o \ - CarlaBridge.cpp.o \ + BridgePlugin.cpp.o \ NativePlugin.cpp.o \ LadspaPlugin.cpp.o \ DssiPlugin.cpp.o \ diff --git a/source/backend/plugin/NativePlugin.cpp b/source/backend/plugin/NativePlugin.cpp index 33c7d2798..b566b4356 100644 --- a/source/backend/plugin/NativePlugin.cpp +++ b/source/backend/plugin/NativePlugin.cpp @@ -17,6 +17,8 @@ #include "CarlaPluginInternal.hpp" +#ifdef WANT_NATIVE + #include CARLA_BACKEND_START_NAMESPACE @@ -1630,23 +1632,23 @@ public: static size_t getPluginCount() { maybeFirstInit(); - return sPluginDescriptors.size(); + return sPluginDescriptors.count(); } - static const PluginDescriptor* getPlugin(const size_t index) + static const PluginDescriptor* getPluginDescriptor(const size_t index) { maybeFirstInit(); - CARLA_ASSERT(index < sPluginDescriptors.size()); + CARLA_ASSERT(index < sPluginDescriptors.count()); - if (index < sPluginDescriptors.size()) - return sPluginDescriptors[index]; + if (index < sPluginDescriptors.count()) + return sPluginDescriptors.getAt(index); return nullptr; } static void registerPlugin(const PluginDescriptor* desc) { - sPluginDescriptors.push_back(desc); + sPluginDescriptors.append(desc); } static void maybeFirstInit() @@ -1693,9 +1695,10 @@ public: // --------------------------------------------------------------- // get descriptor that matches label - for (size_t i=0; i < sPluginDescriptors.size(); i++) + // FIXME - use itenerator when available + for (size_t i=0; i < sPluginDescriptors.count(); i++) { - fDescriptor = sPluginDescriptors[i]; + fDescriptor = sPluginDescriptors.getAt(i); if (fDescriptor == nullptr) break; @@ -1765,7 +1768,7 @@ private: ::TimeInfo fTimeInfo; static bool sFirstInit; - static std::vector sPluginDescriptors; + static NonRtList sPluginDescriptors; // ------------------------------------------------------------------- @@ -1786,7 +1789,7 @@ private: return handlePtr->handleGetTimeInfo(); } - static bool carla_host_write_midi_event(HostHandle handle, const MidiEvent* event) + static bool carla_host_write_midi_event(HostHandle handle, const ::MidiEvent* event) { return handlePtr->handleWriteMidiEvent(event); } @@ -1810,24 +1813,49 @@ private: }; bool NativePlugin::sFirstInit = true; -std::vector NativePlugin::sPluginDescriptors; +NonRtList NativePlugin::sPluginDescriptors; -// ----------------------------------------------------------------------- +CARLA_BACKEND_END_NAMESPACE + +void carla_register_native_plugin(const PluginDescriptor* desc) +{ + CARLA_BACKEND_USE_NAMESPACE + NativePlugin::registerPlugin(desc); +} + +#else // WANT_NATIVE +# warning Building without Internal plugin support +#endif + +CARLA_BACKEND_START_NAMESPACE size_t CarlaPlugin::getNativePluginCount() { +#ifdef WANT_NATIVE return NativePlugin::getPluginCount(); +#else + return 0; +#endif } const PluginDescriptor* CarlaPlugin::getNativePluginDescriptor(const size_t index) { - return NativePlugin::getPlugin(index); +#ifdef WANT_NATIVE + return NativePlugin::getPluginDescriptor(index); +#else + return nullptr; + // unused + (void)index; +#endif } +// ----------------------------------------------------------------------- + CarlaPlugin* CarlaPlugin::newNative(const Initializer& init) { carla_debug("CarlaPlugin::newNative(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label); +#ifdef WANT_NATIVE NativePlugin* const plugin = new NativePlugin(init.engine, init.id); if (! plugin->init(init.name, init.label)) @@ -1848,16 +1876,10 @@ CarlaPlugin* CarlaPlugin::newNative(const Initializer& init) plugin->registerToOscClient(); return plugin; +#else + init.engine->setLastError("Internal plugins not available"); + return nullptr; +#endif } -// ----------------------------------------------------------------------- - CARLA_BACKEND_END_NAMESPACE - -void carla_register_native_plugin(const PluginDescriptor* desc) -{ - CARLA_BACKEND_USE_NAMESPACE - NativePlugin::registerPlugin(desc); -} - -// ----------------------------------------------------------------------- diff --git a/source/backend/plugin/VstPlugin.cpp b/source/backend/plugin/VstPlugin.cpp index 420ea0485..4a8c43c23 100644 --- a/source/backend/plugin/VstPlugin.cpp +++ b/source/backend/plugin/VstPlugin.cpp @@ -27,13 +27,6 @@ CARLA_BACKEND_START_NAMESPACE -/*! - * @defgroup CarlaBackendVstPlugin Carla Backend VST Plugin - * - * The Carla Backend VST Plugin. - * @{ - */ - /*! * @defgroup PluginHints Plugin Hints * @{ @@ -52,6 +45,7 @@ public: { carla_debug("VstPlugin::VstPlugin(%p, %i)", engine, id); +#if 0 m_type = PLUGIN_VST; effect = nullptr; @@ -76,12 +70,14 @@ public: // make plugin valid srand(id); unique1 = unique2 = rand(); +#endif } ~VstPlugin() { carla_debug("VstPlugin::~VstPlugin()"); +#if 0 // make plugin invalid unique2 += 1; @@ -116,11 +112,18 @@ public: effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f); effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f); } +#endif } // ------------------------------------------------------------------- // Information (base) + PluginType type() const + { + return PLUGIN_VST; + } + +#if 0 PluginCategory category() { CARLA_ASSERT(effect); @@ -2344,6 +2347,7 @@ public: return true; } +#endif private: int unique1; @@ -2361,7 +2365,7 @@ private: VstTimeInfo_R vstTimeInfo; struct { - GuiType type; + //GuiType type; bool visible; int width; int height; @@ -2376,12 +2380,10 @@ private: VstPlugin* VstPlugin::lastVstPlugin = nullptr; -/**@}*/ - CARLA_BACKEND_END_NAMESPACE #else // WANT_VST -//# warning Building without VST support +# warning Building without VST support #endif CARLA_BACKEND_START_NAMESPACE @@ -2391,17 +2393,9 @@ CarlaPlugin* CarlaPlugin::newVST(const Initializer& init) carla_debug("CarlaPlugin::newVST(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label); #ifdef WANT_VST - short id = init.engine->getNewPluginId(); - - if (id < 0 || id > init.engine->maxPluginNumber()) - { - init.engine->setLastError("Maximum number of plugins reached"); - return nullptr; - } - - VstPlugin* const plugin = new VstPlugin(init.engine, id); + VstPlugin* const plugin = new VstPlugin(init.engine, init.id); - if (! plugin->init(init.filename, init.name, init.label)) + //if (! plugin->init(init.filename, init.name, init.label)) { delete plugin; return nullptr; @@ -2409,7 +2403,7 @@ CarlaPlugin* CarlaPlugin::newVST(const Initializer& init) plugin->reload(); - if (init.engine->getOptions().processMode == PROCESS_MODE_CONTINUOUS_RACK) + if (init.engine->getProccessMode() == PROCESS_MODE_CONTINUOUS_RACK) { if (! (plugin->hints() & PLUGIN_CAN_FORCE_STEREO)) { diff --git a/source/backend/standalone/Makefile b/source/backend/standalone/Makefile index a61406c4f..42b9b94c4 100644 --- a/source/backend/standalone/Makefile +++ b/source/backend/standalone/Makefile @@ -56,6 +56,7 @@ LIBS = ../libcarla_engine.a LIBS += ../libcarla_plugin.a LIBS += ../libcarla_native.a LIBS += ../../libs/rtmempool.a +LIBS += ../../libs/lilv.a OBJS = \ CarlaStandalone.cpp.o diff --git a/source/bridges/qtcreator/carla-bridge-plugin.pro b/source/bridges/qtcreator/carla-bridge-plugin.pro index 0d5fd9286..0e76910f0 100644 --- a/source/bridges/qtcreator/carla-bridge-plugin.pro +++ b/source/bridges/qtcreator/carla-bridge-plugin.pro @@ -3,7 +3,7 @@ QT = core gui xml CONFIG = debug link_pkgconfig qt warn_on -PKGCONFIG = jack liblo +PKGCONFIG = jack liblo fluidsynth linuxsampler TARGET = carla-bridge-qtcreator TEMPLATE = app @@ -36,6 +36,7 @@ SOURCES += \ SOURCES += \ ../../backend/plugin/CarlaPlugin.cpp \ ../../backend/plugin/CarlaPluginThread.cpp \ + ../../backend/plugin/BridgePlugin.cpp \ ../../backend/plugin/NativePlugin.cpp \ ../../backend/plugin/LadspaPlugin.cpp \ ../../backend/plugin/DssiPlugin.cpp \ @@ -112,8 +113,8 @@ DEFINES += DEBUG DEFINES += BUILD_BRIDGE BUILD_BRIDGE_PLUGIN BRIDGE_PLUGIN DEFINES += WANT_JACK -DEFINES += WANT_LADSPA WANT_DSSI -# WANT_LV2 WANT_VST +DEFINES += WANT_NATIVE WANT_LADSPA WANT_DSSI WANT_LV2 WANT_VST +DEFINES += WANT_FLUIDSYNTH WANT_LINUXSAMPLER LIBS = -ldl \ ../../libs/lilv.a \ diff --git a/source/utils/Lv2AtomQueue.hpp b/source/utils/Lv2AtomQueue.hpp index b2d83fe14..c1bea39ec 100644 --- a/source/utils/Lv2AtomQueue.hpp +++ b/source/utils/Lv2AtomQueue.hpp @@ -73,9 +73,9 @@ public: return full; } - bool lock() + void lock() { - return mutex.lock(); + mutex.lock(); } bool tryLock() @@ -83,9 +83,9 @@ public: return mutex.tryLock(); } - bool unlock() + void unlock() { - return mutex.unlock(); + mutex.unlock(); } void put(const uint32_t portIndex, const LV2_Atom* const atom)