diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index 48ef80ae7..31c93b28a 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -323,7 +323,7 @@ struct EngineTimeInfo { bool playing; uint32_t frame; - uint64_t time; + uint64_t time; // usecs uint32_t valid; EngineTimeInfoBBT bbt; diff --git a/source/backend/plugin/BridgePlugin.cpp b/source/backend/plugin/BridgePlugin.cpp index dfcb391f1..ea9788064 100644 --- a/source/backend/plugin/BridgePlugin.cpp +++ b/source/backend/plugin/BridgePlugin.cpp @@ -1007,7 +1007,6 @@ public: for (i=0; i < kData->audioOut.count; i++) carla_zeroFloat(outBuffer[i], frames); - //kData->activeBefore = kData->active; return; } diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 65b6d3cbb..eca386c3d 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -1005,13 +1005,19 @@ void CarlaPlugin::setEnabled(const bool yesNo) void CarlaPlugin::setActive(const bool active, const bool sendOsc, const bool sendCallback) { + CARLA_ASSERT(sendOsc || sendCallback); // never call this from RT + if (kData->active == active) return; - if (active) - activate(); - else - deactivate(); + { + const ScopedSingleProcessLocker spl(this, true); + + if (active) + activate(); + else + deactivate(); + } kData->active = active; diff --git a/source/backend/plugin/DssiPlugin.cpp b/source/backend/plugin/DssiPlugin.cpp index 8a7cb3f37..a92525914 100644 --- a/source/backend/plugin/DssiPlugin.cpp +++ b/source/backend/plugin/DssiPlugin.cpp @@ -1028,11 +1028,9 @@ public: { while (midiEventCount < MAX_MIDI_EVENTS && ! kData->extNotes.data.isEmpty()) { - const ExternalMidiNote& note = kData->extNotes.data.getFirst(true); + const ExternalMidiNote& note(kData->extNotes.data.getFirst(true)); - CARLA_ASSERT(note.channel >= 0); - - carla_zeroStruct(fMidiEvents[midiEventCount]); + CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); fMidiEvents[midiEventCount].type = (note.velo > 0) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF; fMidiEvents[midiEventCount].data.note.channel = note.channel; @@ -1219,22 +1217,6 @@ public: allNotesOffSent = true; } - if (fDescriptor->deactivate != nullptr) - { - fDescriptor->deactivate(fHandle); - - if (fHandle2 != nullptr) - fDescriptor->deactivate(fHandle2); - } - - if (fDescriptor->activate != nullptr) - { - fDescriptor->activate(fHandle); - - if (fHandle2 != nullptr) - fDescriptor->activate(fHandle2); - } - postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 0.0f); postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 1.0f); } @@ -1420,10 +1402,6 @@ public: } } // 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 unsigned long midiEventCount) @@ -1644,12 +1622,12 @@ public: void sampleRateChanged(const double newSampleRate) { CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate); - carla_debug("DssiPlugin::sampleRateChanged(%i) - start", newSampleRate); + carla_debug("DssiPlugin::sampleRateChanged(%g) - start", newSampleRate); // TODO (void)newSampleRate; - carla_debug("DssiPlugin::sampleRateChanged(%i) - end", newSampleRate); + carla_debug("DssiPlugin::sampleRateChanged(%g) - end", newSampleRate); } // ------------------------------------------------------------------- diff --git a/source/backend/plugin/FluidSynthPlugin.cpp b/source/backend/plugin/FluidSynthPlugin.cpp index a13bcb2c7..9e3a21b43 100644 --- a/source/backend/plugin/FluidSynthPlugin.cpp +++ b/source/backend/plugin/FluidSynthPlugin.cpp @@ -882,7 +882,6 @@ public: for (i=0; i < kData->audioOut.count; i++) carla_zeroFloat(outBuffer[i], frames); - //kData->activeBefore = kData->active; return; } @@ -920,9 +919,9 @@ public: { while (! kData->extNotes.data.isEmpty()) { - const ExternalMidiNote& note = kData->extNotes.data.getFirst(true); + const ExternalMidiNote& note(kData->extNotes.data.getFirst(true)); - CARLA_ASSERT(note.channel >= 0); + CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); if (note.velo > 0) fluid_synth_noteon(fSynth, note.channel, note.note, note.velo); @@ -1230,10 +1229,6 @@ public: } } // End of Control Output - - // -------------------------------------------------------------------------------------------------------- - - //kData->activeBefore = kData->active; } bool processSingle(float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) diff --git a/source/backend/plugin/LadspaPlugin.cpp b/source/backend/plugin/LadspaPlugin.cpp index 0734a83c7..600af8d5b 100644 --- a/source/backend/plugin/LadspaPlugin.cpp +++ b/source/backend/plugin/LadspaPlugin.cpp @@ -989,22 +989,6 @@ public: case kEngineControlEventTypeAllSoundOff: if (event.channel == kData->ctrlChannel) { - if (fDescriptor->deactivate != nullptr) - { - fDescriptor->deactivate(fHandle); - - if (fHandle2 != nullptr) - fDescriptor->deactivate(fHandle2); - } - - if (fDescriptor->activate != nullptr) - { - fDescriptor->activate(fHandle); - - if (fHandle2 != nullptr) - fDescriptor->activate(fHandle2); - } - postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 0.0f); postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 1.0f); } @@ -1067,10 +1051,6 @@ public: } } // End of Control Output - - // -------------------------------------------------------------------------------------------------------- - - //kData->activeBefore = kData->active; } bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) @@ -1273,12 +1253,12 @@ public: void sampleRateChanged(const double newSampleRate) { CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate); - carla_debug("LadspaPlugin::sampleRateChanged(%i) - start", newSampleRate); + carla_debug("LadspaPlugin::sampleRateChanged(%g) - start", newSampleRate); // TODO (void)newSampleRate; - carla_debug("LadspaPlugin::sampleRateChanged(%i) - end", newSampleRate); + carla_debug("LadspaPlugin::sampleRateChanged(%g) - end", newSampleRate); } // ------------------------------------------------------------------- diff --git a/source/backend/plugin/LinuxSamplerPlugin.cpp b/source/backend/plugin/LinuxSamplerPlugin.cpp index 94ef0972a..9738c2373 100644 --- a/source/backend/plugin/LinuxSamplerPlugin.cpp +++ b/source/backend/plugin/LinuxSamplerPlugin.cpp @@ -467,8 +467,6 @@ public: //if (kData->activeBefore) // fAudioOutputDevice->Stop(); - - //kData->activeBefore = kData->active; return; } @@ -506,9 +504,9 @@ public: { while (! kData->extNotes.data.isEmpty()) { - const ExternalMidiNote& note = kData->extNotes.data.getFirst(true); + const ExternalMidiNote& note(kData->extNotes.data.getFirst(true)); - CARLA_ASSERT(note.channel >= 0); + CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); if (note.velo > 0) fMidiInputPort->DispatchNoteOn(note.note, note.velo, note.channel, 0); @@ -801,10 +799,6 @@ public: processSingle(outBuffer, frames, 0); } // End of Plugin processing (no events) - - // -------------------------------------------------------------------------------------------------------- - - //kData->activeBefore = kData->active; } bool processSingle(float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) diff --git a/source/backend/plugin/NativePlugin.cpp b/source/backend/plugin/NativePlugin.cpp index 92710c5e1..ac84db627 100644 --- a/source/backend/plugin/NativePlugin.cpp +++ b/source/backend/plugin/NativePlugin.cpp @@ -182,8 +182,12 @@ public: { carla_debug("NativePlugin::~NativePlugin()"); - if (fIsUiVisible && fDescriptor != nullptr && fDescriptor->ui_show != nullptr && fHandle != nullptr) - fDescriptor->ui_show(fHandle, false); + // close UI + if (fHints & PLUGIN_HAS_GUI) + { + if (fIsUiVisible && fDescriptor != nullptr && fDescriptor->ui_show != nullptr && fHandle != nullptr) + fDescriptor->ui_show(fHandle, false); + } kData->singleMutex.lock(); kData->masterMutex.lock(); @@ -1183,9 +1187,11 @@ public: { fMidiEvents[k].data[0] = MIDI_STATUS_CONTROL_CHANGE + k; fMidiEvents[k].data[1] = MIDI_CONTROL_ALL_SOUND_OFF; + fMidiEvents[k].size = 2; fMidiEvents[k+i].data[0] = MIDI_STATUS_CONTROL_CHANGE + k; fMidiEvents[k+i].data[1] = MIDI_CONTROL_ALL_NOTES_OFF; + fMidiEvents[k+i].size = 2; } fMidiEventCount = MAX_MIDI_CHANNELS*2; @@ -1240,12 +1246,10 @@ public: { while (fMidiEventCount < MAX_MIDI_EVENTS*2 && ! kData->extNotes.data.isEmpty()) { - const ExternalMidiNote& note = kData->extNotes.data.getFirst(true); + const ExternalMidiNote& note(kData->extNotes.data.getFirst(true)); - CARLA_ASSERT(note.channel >= 0); + CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); - fMidiEvents[fMidiEventCount].port = 0; - fMidiEvents[fMidiEventCount].time = 0; fMidiEvents[fMidiEventCount].data[0] = (note.velo > 0) ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF; fMidiEvents[fMidiEventCount].data[0] += note.channel; fMidiEvents[fMidiEventCount].data[1] = note.note; @@ -1437,22 +1441,6 @@ public: allNotesOffSent = true; } - if (fDescriptor->deactivate != nullptr) - { - fDescriptor->deactivate(fHandle); - - if (fHandle2 != nullptr) - fDescriptor->deactivate(fHandle2); - } - - if (fDescriptor->activate != nullptr) - { - fDescriptor->activate(fHandle); - - if (fHandle2 != nullptr) - fDescriptor->activate(fHandle2); - } - postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 0.0f); postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 1.0f); } @@ -1467,6 +1455,8 @@ public: fMidiEvents[fMidiEventCount].data[0] = MIDI_STATUS_CONTROL_CHANGE + event.channel; fMidiEvents[fMidiEventCount].data[1] = MIDI_CONTROL_ALL_SOUND_OFF; fMidiEvents[fMidiEventCount].data[2] = 0; + fMidiEvents[fMidiEventCount].data[3] = 0; + fMidiEvents[fMidiEventCount].size = 2; fMidiEventCount += 1; } @@ -1493,6 +1483,8 @@ public: fMidiEvents[fMidiEventCount].data[0] = MIDI_STATUS_CONTROL_CHANGE + event.channel; fMidiEvents[fMidiEventCount].data[1] = MIDI_CONTROL_ALL_NOTES_OFF; fMidiEvents[fMidiEventCount].data[2] = 0; + fMidiEvents[fMidiEventCount].data[3] = 0; + fMidiEvents[fMidiEventCount].size = 2; fMidiEventCount += 1; } @@ -1603,10 +1595,6 @@ public: } } // End of Control and MIDI Output - - // -------------------------------------------------------------------------------------------------------- - - //kData->activeBefore = kData->active; } bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) diff --git a/source/backend/plugin/VstPlugin.cpp b/source/backend/plugin/VstPlugin.cpp index 5a794746d..b5e1a5702 100644 --- a/source/backend/plugin/VstPlugin.cpp +++ b/source/backend/plugin/VstPlugin.cpp @@ -28,6 +28,10 @@ CARLA_BACKEND_START_NAMESPACE +#if 0 +} +#endif + /*! * @defgroup PluginHints Plugin Hints * @{ @@ -42,10 +46,11 @@ class VstPlugin : public CarlaPlugin, public CarlaPluginGui::Callback { public: - VstPlugin(CarlaEngine* const engine, const unsigned short id) + VstPlugin(CarlaEngine* const engine, const unsigned int id) : CarlaPlugin(engine, id), fUnique1(1), fEffect(nullptr), + fLastChunk(nullptr), fMidiEventCount(0), fIsProcessing(false), fNeedIdle(false), @@ -53,10 +58,10 @@ public: { carla_debug("VstPlugin::VstPlugin(%p, %i)", engine, id); - carla_zeroMem(fMidiEvents, sizeof(VstMidiEvent)*MAX_MIDI_EVENTS*2); + carla_zeroStruct(fMidiEvents, MAX_MIDI_EVENTS*2); carla_zeroStruct(fTimeInfo); - for (unsigned short i=0; i < MAX_MIDI_EVENTS*2; i++) + for (unsigned short i=0; i < MAX_MIDI_EVENTS*2; ++i) fEvents.data[i] = (VstEvent*)&fMidiEvents[i]; kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_VST_GUI); @@ -70,15 +75,6 @@ public: { carla_debug("VstPlugin::~VstPlugin()"); - kData->singleMutex.lock(); - kData->masterMutex.lock(); - - // make plugin invalid - fUnique2 += 1; - - if (fEffect == nullptr) - return; - // close UI if (fHints & PLUGIN_HAS_GUI) { @@ -93,20 +89,31 @@ public: kData->osc.thread.terminate(); } } - else - dispatcher(effEditClose, 0, 0, nullptr, 0.0f); } + kData->singleMutex.lock(); + kData->masterMutex.lock(); + if (kData->active) { - dispatcher(effStopProcess, 0, 0, nullptr, 0.0f); - dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f); + deactivate(); kData->active = false; } - dispatcher(effClose, 0, 0, nullptr, 0.0f); + if (fEffect != nullptr) + { + dispatcher(effClose, 0, 0, nullptr, 0.0f); + fEffect = nullptr; + } - fEffect = nullptr; + if (fLastChunk != nullptr) + { + delete[] fLastChunk; + fLastChunk = nullptr; + } + + // make plugin invalid + fUnique2 += 1; } // ------------------------------------------------------------------- @@ -121,7 +128,6 @@ public: { CARLA_ASSERT(fEffect != nullptr); - if (fEffect != nullptr) { const intptr_t category = dispatcher(effGetPlugCategory, 0, 0, nullptr, 0.0f); @@ -164,7 +170,7 @@ public: CARLA_ASSERT(fEffect != nullptr); CARLA_ASSERT(dataPtr != nullptr); - return (fEffect != nullptr) ? dispatcher(effGetChunk, 0 /* bank */, 0, dataPtr, 0.0f) : 0; + return dispatcher(effGetChunk, 0 /* bank */, 0, dataPtr, 0.0f); } // ------------------------------------------------------------------- @@ -182,13 +188,10 @@ public: options |= PLUGIN_OPTION_FIXED_BUFFER; options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; - //if ((kData->audioIns.count() == 2 || kData->audioOuts.count() == 0) || (kData->audioIns.count() == 0 || kData->audioOuts.count() == 2)) - // options |= PLUGIN_OPTION_FORCE_STEREO; - if (fEffect->flags & effFlagsProgramChunks) options |= PLUGIN_OPTION_USE_CHUNKS; - if (kData->extraHints & PLUGIN_HINT_HAS_MIDI_IN) + if (vstPluginCanDo(fEffect, "receiveVstEvents") || vstPluginCanDo(fEffect, "receiveVstMidiEvent") || (fEffect->flags & effFlagsIsSynth) > 0 || (fHints & PLUGIN_WANTS_MIDI_INPUT)) { options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES; options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; @@ -205,47 +208,35 @@ public: CARLA_ASSERT(fEffect != nullptr); CARLA_ASSERT(parameterId < kData->param.count); - return (fEffect != nullptr) ? fEffect->getParameter(fEffect, parameterId) : 0; + return fEffect->getParameter(fEffect, parameterId); } void getLabel(char* const strBuf) { CARLA_ASSERT(fEffect != nullptr); - if (fEffect != nullptr) - dispatcher(effGetProductString, 0, 0, strBuf, 0.0f); - else - CarlaPlugin::getLabel(strBuf); + dispatcher(effGetProductString, 0, 0, strBuf, 0.0f); } void getMaker(char* const strBuf) { CARLA_ASSERT(fEffect != nullptr); - if (fEffect != nullptr) - dispatcher(effGetVendorString, 0, 0, strBuf, 0.0f); - else - CarlaPlugin::getMaker(strBuf); + dispatcher(effGetVendorString, 0, 0, strBuf, 0.0f); } void getCopyright(char* const strBuf) { CARLA_ASSERT(fEffect != nullptr); - if (fEffect != nullptr) - dispatcher(effGetVendorString, 0, 0, strBuf, 0.0f); - else - CarlaPlugin::getCopyright(strBuf); + dispatcher(effGetVendorString, 0, 0, strBuf, 0.0f); } void getRealName(char* const strBuf) { CARLA_ASSERT(fEffect != nullptr); - if (fEffect != nullptr) - dispatcher(effGetEffectName, 0, 0, strBuf, 0.0f); - else - CarlaPlugin::getRealName(strBuf); + dispatcher(effGetEffectName, 0, 0, strBuf, 0.0f); } void getParameterName(const uint32_t parameterId, char* const strBuf) @@ -253,10 +244,7 @@ public: CARLA_ASSERT(fEffect != nullptr); CARLA_ASSERT(parameterId < kData->param.count); - if (fEffect != nullptr) - dispatcher(effGetParamName, parameterId, 0, strBuf, 0.0f); - else - CarlaPlugin::getParameterName(parameterId, strBuf); + dispatcher(effGetParamName, parameterId, 0, strBuf, 0.0f); } void getParameterText(const uint32_t parameterId, char* const strBuf) @@ -264,15 +252,10 @@ public: CARLA_ASSERT(fEffect != nullptr); CARLA_ASSERT(parameterId < kData->param.count); - if (fEffect != nullptr) - { - dispatcher(effGetParamDisplay, parameterId, 0, strBuf, 0.0f); + dispatcher(effGetParamDisplay, parameterId, 0, strBuf, 0.0f); - if (*strBuf == 0) - std::sprintf(strBuf, "%f", getParameterValue(parameterId)); - } - else - CarlaPlugin::getParameterText(parameterId, strBuf); + if (*strBuf == 0) + std::sprintf(strBuf, "%f", getParameterValue(parameterId)); } void getParameterUnit(const uint32_t parameterId, char* const strBuf) @@ -280,10 +263,7 @@ public: CARLA_ASSERT(fEffect != nullptr); CARLA_ASSERT(parameterId < kData->param.count); - if (fEffect != nullptr) - dispatcher(effGetParamLabel, parameterId, 0, strBuf, 0.0f); - else - CarlaPlugin::getParameterUnit(parameterId, strBuf); + dispatcher(effGetParamLabel, parameterId, 0, strBuf, 0.0f); } // ------------------------------------------------------------------- @@ -296,24 +276,33 @@ public: const float fixedValue = kData->param.fixValue(parameterId, value); - if (fEffect != nullptr) - fEffect->setParameter(fEffect, parameterId, fixedValue); + fEffect->setParameter(fEffect, parameterId, fixedValue); CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback); } void setChunkData(const char* const stringData) { - CARLA_ASSERT(fEffect != nullptr); CARLA_ASSERT(fOptions & PLUGIN_OPTION_USE_CHUNKS); + CARLA_ASSERT(fEffect != nullptr); CARLA_ASSERT(stringData != nullptr); - // FIXME - fChunk = QByteArray::fromBase64(QByteArray(stringData)); - //fChunk.toBase64(); + if (fLastChunk != nullptr) + { + delete[] fLastChunk; + fLastChunk = nullptr; + } + + const size_t size(CarlaString(stringData).exportAsBase64Binary(&fLastChunk)); + + CARLA_ASSERT(size > 0); + CARLA_ASSERT(fLastChunk != nullptr); - const ScopedSingleProcessLocker spl(this, true); - dispatcher(effSetChunk, 0 /* bank */, fChunk.size(), fChunk.data(), 0.0f); + if (size > 0 && fLastChunk != nullptr) + { + const ScopedSingleProcessLocker spl(this, true); + dispatcher(effSetChunk, 0 /* bank */, size, fLastChunk, 0.0f); + } } void setProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) @@ -326,7 +315,7 @@ public: else if (index > static_cast(kData->prog.count)) return; - if (fEffect != nullptr && index >= 0) + if (index >= 0) { const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback)); @@ -469,7 +458,10 @@ public: // Safely disable plugin for reload const ScopedDisabler sd(this); - kData->clearBuffers(); + if (kData->active) + deactivate(); + + clearBuffers(); uint32_t aIns, aOuts, mIns, mOuts, params, j; @@ -517,7 +509,7 @@ public: CarlaString portName; // Audio Ins - for (j=0; j < aIns; j++) + for (j=0; j < aIns; ++j) { portName.clear(); @@ -534,6 +526,7 @@ public: } else portName += "input"; + portName.truncate(portNameSize); kData->audioIn.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true); @@ -541,7 +534,7 @@ public: } // Audio Outs - for (j=0; j < aOuts; j++) + for (j=0; j < aOuts; ++j) { portName.clear(); @@ -558,13 +551,14 @@ public: } else portName += "output"; + portName.truncate(portNameSize); kData->audioOut.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false); kData->audioOut.ports[j].rindex = j; } - for (j=0; j < params; j++) + for (j=0; j < params; ++j) { kData->param.data[j].type = PARAMETER_INPUT; kData->param.data[j].index = j; @@ -716,7 +710,7 @@ public: portName += ":"; } - portName += "event-in"; + portName += "events-in"; portName.truncate(portNameSize); kData->event.portIn = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true); @@ -732,7 +726,7 @@ public: portName += ":"; } - portName += "event-out"; + portName += "events-out"; portName.truncate(portNameSize); kData->event.portOut = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, false); @@ -787,33 +781,10 @@ public: if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0)) kData->extraHints |= PLUGIN_HINT_CAN_RUN_RACK; - // plugin options - fOptions = 0x0; - - fOptions |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; - - if (fEffect->flags & effFlagsProgramChunks) - fOptions |= PLUGIN_OPTION_USE_CHUNKS; - -#ifdef CARLA_OS_WIN - // Most Windows plugins have issues with this - fOptions |= PLUGIN_OPTION_FIXED_BUFFER; -#endif - - if (mIns > 0) + // dummy pre-start to get latency and wantEvents() on old plugins { - fOptions |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; - fOptions |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; - fOptions |= PLUGIN_OPTION_SEND_PITCHBEND; - fOptions |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; - } - - // dummy pre-start to catch latency and possible wantEvents() call on old plugins - { - dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f); - dispatcher(effStartProcess, 0, 0, nullptr, 0.0f); - dispatcher(effStopProcess, 0, 0, nullptr, 0.0f); - dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f); + activate(); + deactivate(); } // check latency @@ -847,9 +818,8 @@ public: bufferSizeChanged(kData->engine->getBufferSize()); reloadPrograms(true); - // always enabled, FIXME - dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f); - dispatcher(effStartProcess, 0, 0, nullptr, 0.0f); + if (kData->active) + activate(); carla_debug("VstPlugin::reload() - end"); } @@ -871,7 +841,7 @@ public: kData->prog.createNew(count); // Update names - for (i=0; i < count; i++) + for (i=0; i < count; ++i) { char strBuf[STR_MAX+1] = { 0 }; if (dispatcher(effGetProgramNameIndexed, i, 0, strBuf, 0.0f) != 1) @@ -890,7 +860,7 @@ public: { kData->engine->osc_send_control_set_program_count(fId, count); - for (i=0; i < count; i++) + for (i=0; i < count; ++i) kData->engine->osc_send_control_set_program_name(fId, i, kData->prog.names[i]); } #endif @@ -953,6 +923,18 @@ public: // ------------------------------------------------------------------- // Plugin processing + void activate() + { + dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f); + dispatcher(effStartProcess, 0, 0, nullptr, 0.0f); + } + + void deactivate() + { + dispatcher(effStopProcess, 0, 0, nullptr, 0.0f); + dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f); + } + void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) { uint32_t i, k; @@ -963,55 +945,57 @@ public: if (! kData->active) { // disable any output sound - for (i=0; i < kData->audioOut.count; i++) + for (i=0; i < kData->audioOut.count; ++i) carla_zeroFloat(outBuffer[i], frames); - //kData->activeBefore = kData->active; return; } fMidiEventCount = 0; - carla_zeroMem(fMidiEvents, sizeof(VstMidiEvent)*MAX_MIDI_EVENTS*2); + carla_zeroStruct(fMidiEvents, MAX_MIDI_EVENTS*2); // -------------------------------------------------------------------------------------------------------- - // Check if not active before + // Check if needs reset - if (kData->needsReset /*|| ! kData->activeBefore*/) + if (kData->needsReset) { + // TODO! if (fOptions & PLUGIN_OPTION_SEND_ALL_SOUND_OFF) { - for (unsigned char j=0, l=MAX_MIDI_CHANNELS; j < MAX_MIDI_CHANNELS; j++) + for (k=0, i=MAX_MIDI_CHANNELS; k < MAX_MIDI_CHANNELS; ++k) { - carla_zeroStruct(fMidiEvents[j]); - carla_zeroStruct(fMidiEvents[j+l]); - - fMidiEvents[j].type = kVstMidiType; - fMidiEvents[j].byteSize = sizeof(VstMidiEvent); - fMidiEvents[j].midiData[0] = MIDI_STATUS_CONTROL_CHANGE + j; - fMidiEvents[j].midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; - - fMidiEvents[j+l].type = kVstMidiType; - fMidiEvents[j+l].byteSize = sizeof(VstMidiEvent); - fMidiEvents[j+l].midiData[0] = MIDI_STATUS_CONTROL_CHANGE + j; - fMidiEvents[j+l].midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; + fMidiEvents[k].type = kVstMidiType; + fMidiEvents[k].byteSize = sizeof(VstMidiEvent); + fMidiEvents[k].midiData[0] = MIDI_STATUS_CONTROL_CHANGE + k; + fMidiEvents[k].midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; + + fMidiEvents[k+i].type = kVstMidiType; + fMidiEvents[k+i].byteSize = sizeof(VstMidiEvent); + fMidiEvents[k+i].midiData[0] = MIDI_STATUS_CONTROL_CHANGE + k; + fMidiEvents[k+i].midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF; } fMidiEventCount = MAX_MIDI_CHANNELS*2; } + else + { + } if (kData->latency > 0) { - for (i=0; i < kData->audioIn.count; i++) + for (i=0; i < kData->audioIn.count; ++i) carla_zeroFloat(kData->latencyBuffers[i], kData->latency); } kData->needsReset = false; } + CARLA_PROCESS_CONTINUE_CHECK; + // -------------------------------------------------------------------------------------------------------- // Set TimeInfo - const EngineTimeInfo& timeInfo = kData->engine->getTimeInfo(); + const EngineTimeInfo& timeInfo(kData->engine->getTimeInfo()); fTimeInfo.flags = kVstTransportChanged; @@ -1021,7 +1005,7 @@ public: fTimeInfo.samplePos = timeInfo.frame; fTimeInfo.sampleRate = kData->engine->getSampleRate(); - fTimeInfo.nanoSeconds = timeInfo.time*1000; + fTimeInfo.nanoSeconds = timeInfo.time/1000; fTimeInfo.flags |= kVstNanosValid; if (timeInfo.valid & EngineTimeInfo::ValidBBT) @@ -1063,10 +1047,12 @@ public: fTimeInfo.barStartPos = 0.0; } + CARLA_PROCESS_CONTINUE_CHECK; + // -------------------------------------------------------------------------------------------------------- // Event Input and Processing - if (kData->event.portIn != nullptr /*&& kData->activeBefore*/) + if (kData->event.portIn != nullptr) { // ---------------------------------------------------------------------------------------------------- // MIDI Input (External) @@ -1075,9 +1061,9 @@ public: { while (fMidiEventCount < MAX_MIDI_EVENTS*2 && ! kData->extNotes.data.isEmpty()) { - const ExternalMidiNote& note = kData->extNotes.data.getFirst(true); + const ExternalMidiNote& note(kData->extNotes.data.getFirst(true)); - carla_zeroStruct(fMidiEvents[fMidiEventCount]); + CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); fMidiEvents[fMidiEventCount].type = kVstMidiType; fMidiEvents[fMidiEventCount].byteSize = sizeof(VstMidiEvent); @@ -1103,7 +1089,7 @@ public: uint32_t startTime = 0; uint32_t timeOffset = 0; - for (i=0; i < nEvents; i++) + for (i=0; i < nEvents; ++i) { const EngineEvent& event = kData->event.portIn->getEvent(i); @@ -1123,7 +1109,7 @@ public: if (fMidiEventCount > 0) { - //carla_zeroMem(fMidiEvents, sizeof(::MidiEvent)*fMidiEventCount); + carla_zeroStruct(fMidiEvents, fMidiEventCount); fMidiEventCount = 0; } } @@ -1151,7 +1137,7 @@ public: // Control backend stuff if (event.channel == kData->ctrlChannel) { - double value; + float value; if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (fHints & PLUGIN_CAN_DRYWET) > 0) { @@ -1163,7 +1149,7 @@ public: if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (fHints & PLUGIN_CAN_VOLUME) > 0) { - value = ctrlEvent.value*127/100; + value = ctrlEvent.value*127.0f/100.0f; setVolume(value, false, false); postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value); continue; @@ -1171,23 +1157,23 @@ public: if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (fHints & PLUGIN_CAN_BALANCE) > 0) { - double left, right; - value = ctrlEvent.value/0.5 - 1.0; + float left, right; + value = ctrlEvent.value/0.5f - 1.0f; - if (value < 0.0) + if (value < 0.0f) { - left = -1.0; - right = (value*2)+1.0; + left = -1.0f; + right = (value*2.0f)+1.0f; } - else if (value > 0.0) + else if (value > 0.0f) { - left = (value*2)-1.0; - right = 1.0; + left = (value*2.0f)-1.0f; + right = 1.0f; } else { - left = -1.0; - right = 1.0; + left = -1.0f; + right = 1.0f; } setBalanceLeft(left, false, false); @@ -1199,7 +1185,7 @@ public: } // Control plugin parameters - for (k=0; k < kData->param.count; k++) + for (k=0; k < kData->param.count; ++k) { if (kData->param.data[k].midiChannel != event.channel) continue; @@ -1210,7 +1196,7 @@ public: if ((kData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0) continue; - double value; + float value; if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN) { @@ -1251,8 +1237,8 @@ public: { if (! allNotesOffSent) { - allNotesOffSent = true; sendMidiAllNotesOff(); + allNotesOffSent = true; } postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 0.0f); @@ -1377,7 +1363,7 @@ public: if (kData->event.portOut != nullptr) { // reverse lookup MIDI events - for (k = (MAX_MIDI_EVENTS*2)-1; k >= fMidiEventCount; k--) + for (k = (MAX_MIDI_EVENTS*2)-1; k >= fMidiEventCount; --k) { if (fMidiEvents[k].type == 0) break; @@ -1393,10 +1379,6 @@ public: } } // End of Control and MIDI Output - - // -------------------------------------------------------------------------------------------------------- - - //kData->activeBefore = kData->active; } bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset) @@ -1430,9 +1412,9 @@ public: } else if (! kData->singleMutex.tryLock()) { - for (i=0; i < kData->audioOut.count; i++) + for (i=0; i < kData->audioOut.count; ++i) { - for (k=0; k < frames; k++) + for (k=0; k < frames; ++k) outBuffer[i][k+timeOffset] = 0.0f; } @@ -1440,7 +1422,18 @@ public: } // -------------------------------------------------------------------------------------------------------- - // Run plugin + // Set audio buffers + + float* vstInBuffer[kData->audioIn.count]; + float* vstOutBuffer[kData->audioOut.count]; + + for (i=0; i < kData->audioIn.count; ++i) + vstInBuffer[i] = inBuffer[i]+timeOffset; + for (i=0; i < kData->audioOut.count; ++i) + vstOutBuffer[i] = outBuffer[i]+timeOffset; + + // -------------------------------------------------------------------------------------------------------- + // Set MIDI events if (fMidiEventCount > 0) { @@ -1449,19 +1442,13 @@ public: dispatcher(effProcessEvents, 0, 0, &fEvents, 0.0f); } - float* vstInBuffer[kData->audioIn.count]; - float* vstOutBuffer[kData->audioOut.count]; - - for (i=0; i < kData->audioIn.count; i++) - vstInBuffer[i] = inBuffer[i]+timeOffset; - for (i=0; i < kData->audioOut.count; i++) - vstOutBuffer[i] = outBuffer[i]+timeOffset; + // -------------------------------------------------------------------------------------------------------- + // Run plugin fIsProcessing = true; if (fHints & PLUGIN_CAN_PROCESS_REPLACING) { - fEffect->processReplacing(fEffect, (kData->audioIn.count > 0) ? vstInBuffer : nullptr, (kData->audioOut.count > 0) ? vstOutBuffer : nullptr, @@ -1469,7 +1456,7 @@ public: } else { - for (i=0; i < kData->audioOut.count; i++) + for (i=0; i < kData->audioOut.count; ++i) carla_zeroFloat(vstOutBuffer[i], frames); #if ! VST_FORCE_DEPRECATED @@ -1487,18 +1474,19 @@ public: // Post-processing (dry/wet, volume and balance) { - const bool doVolume = (fHints & PLUGIN_CAN_VOLUME) > 0 && kData->postProc.volume != 1.0f; - const bool doDryWet = (fHints & PLUGIN_CAN_DRYWET) > 0 && kData->postProc.dryWet != 1.0f; - const bool doBalance = (fHints & PLUGIN_CAN_BALANCE) > 0 && (kData->postProc.balanceLeft != -1.0f || kData->postProc.balanceRight != 1.0f); + const bool doVolume = (fHints & PLUGIN_CAN_VOLUME) != 0 && kData->postProc.volume != 1.0f; + const bool doDryWet = (fHints & PLUGIN_CAN_DRYWET) != 0 && kData->postProc.dryWet != 1.0f; + const bool doBalance = (fHints & PLUGIN_CAN_BALANCE) != 0 && (kData->postProc.balanceLeft != -1.0f || kData->postProc.balanceRight != 1.0f); + bool isPair; float bufValue, oldBufLeft[doBalance ? frames : 1]; - for (i=0; i < kData->audioOut.count; i++) + for (i=0; i < kData->audioOut.count; ++i) { // Dry/Wet if (doDryWet) { - for (k=0; k < frames; k++) + for (k=0; k < frames; ++k) { bufValue = inBuffer[(kData->audioIn.count == 1) ? 0 : i][k+timeOffset]; outBuffer[i][k+timeOffset] = (outBuffer[i][k+timeOffset] * kData->postProc.dryWet) + (bufValue * (1.0f - kData->postProc.dryWet)); @@ -1508,15 +1496,20 @@ public: // Balance if (doBalance) { - if (i % 2 == 0) + isPair = (i % 2 == 0); + + if (isPair) + { + CARLA_ASSERT(i+1 < kData->audioOut.count); carla_copyFloat(oldBufLeft, outBuffer[i]+timeOffset, frames); + } float balRangeL = (kData->postProc.balanceLeft + 1.0f)/2.0f; float balRangeR = (kData->postProc.balanceRight + 1.0f)/2.0f; - for (k=0; k < frames; k++) + for (k=0; k < frames; ++k) { - if (i % 2 == 0) + if (isPair) { // left outBuffer[i][k+timeOffset] = oldBufLeft[k] * (1.0f - balRangeL); @@ -1534,7 +1527,7 @@ public: // Volume if (doVolume) { - for (k=0; k < frames; k++) + for (k=0; k < frames; ++k) outBuffer[i][k+timeOffset] *= kData->postProc.volume; } } @@ -1549,11 +1542,11 @@ public: void bufferSizeChanged(const uint32_t newBufferSize) { + CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize); + carla_debug("VstPlugin::bufferSizeChanged(%i)", newBufferSize); + if (kData->active) - { - dispatcher(effStopProcess, 0, 0, nullptr, 0.0f); - dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f); - } + deactivate(); #if ! VST_FORCE_DEPRECATED dispatcher(effSetBlockSizeAndSampleRate, 0, newBufferSize, nullptr, kData->engine->getSampleRate()); @@ -1561,19 +1554,16 @@ public: dispatcher(effSetBlockSize, 0, newBufferSize, nullptr, 0.0f); if (kData->active) - { - dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f); - dispatcher(effStartProcess, 0, 0, nullptr, 0.0f); - } + activate(); } void sampleRateChanged(const double newSampleRate) { + CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate); + carla_debug("VstPlugin::sampleRateChanged(%g)", newSampleRate); + if (kData->active) - { - dispatcher(effStopProcess, 0, 0, nullptr, 0.0f); - dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f); - } + deactivate(); #if ! VST_FORCE_DEPRECATED dispatcher(effSetBlockSizeAndSampleRate, 0, kData->engine->getBufferSize(), nullptr, newSampleRate); @@ -1581,10 +1571,7 @@ public: dispatcher(effSetSampleRate, 0, 0, nullptr, newSampleRate); if (kData->active) - { - dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f); - dispatcher(effStartProcess, 0, 0, nullptr, 0.0f); - } + activate(); } // ------------------------------------------------------------------- @@ -1810,7 +1797,7 @@ protected: return 0; } - for (int32_t i=0; i < vstEvents->numEvents && events.numEvents < MAX_MIDI_EVENTS*2; i++) + for (int32_t i=0; i < vstEvents->numEvents && events.numEvents < MAX_MIDI_EVENTS*2; ++i) { if (! vstEvents->events[i]) break; @@ -2059,13 +2046,6 @@ protected: public: // ------------------------------------------------------------------- - // FIXME - #ifdef _WIN32 - # define OS_SEP '\\' - #else - # define OS_SEP '/' - #endif - bool init(const char* const filename, const char* const name) { CARLA_ASSERT(kData->engine != nullptr); @@ -2153,16 +2133,16 @@ public: } else { - char strBuf[STR_MAX+1] = { 0 }; + char strBuf[STR_MAX+1] = { '\0' }; dispatcher(effGetEffectName, 0, 0, strBuf, 0.0f); - if (strBuf[0] != 0) + if (strBuf[0] != '\0') { fName = kData->engine->getNewUniquePluginName(strBuf); } else { - const char* const label = strrchr(filename, OS_SEP)+1; + const char* const label = std::strrchr(filename, OS_SEP)+1; fName = kData->engine->getNewUniquePluginName(label); } } @@ -2223,6 +2203,35 @@ public: } } + // --------------------------------------------------------------- + // load plugin settings + + { + // set default options + fOptions = 0x0; + + fOptions |= PLUGIN_OPTION_FIXED_BUFFER; + fOptions |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; + + if (fEffect->flags & effFlagsProgramChunks) + fOptions |= PLUGIN_OPTION_USE_CHUNKS; + + //if (mIns > 0) + { + fOptions |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE; + fOptions |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH; + fOptions |= PLUGIN_OPTION_SEND_PITCHBEND; + fOptions |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF; + } + + // load settings + kData->idStr = "VST/"; + kData->idStr += std::strrchr(filename, OS_SEP)+1; + kData->idStr += "/"; + kData->idStr += CarlaString(uniqueId()); + fOptions = kData->loadSettings(fOptions, availableOptions()); + } + return true; } @@ -2230,7 +2239,7 @@ private: int fUnique1; AEffect* fEffect; - QByteArray fChunk; + uint8_t* fLastChunk; uint32_t fMidiEventCount; VstMidiEvent fMidiEvents[MAX_MIDI_EVENTS*2]; VstTimeInfo_R fTimeInfo; @@ -2240,12 +2249,10 @@ private: intptr_t reserved; VstEvent* data[MAX_MIDI_EVENTS*2]; -#ifndef QTCREATOR_TEST // missing proper C++11 support FixedVstEvents() : numEvents(0), reserved(0), data{0} {} -#endif } fEvents; struct GuiInfo {