diff --git a/source/backend/plugin/DssiPlugin.cpp b/source/backend/plugin/DssiPlugin.cpp index 906562d99..69782a9ab 100644 --- a/source/backend/plugin/DssiPlugin.cpp +++ b/source/backend/plugin/DssiPlugin.cpp @@ -48,7 +48,8 @@ public: fUiFilename(nullptr), fAudioInBuffers(nullptr), fAudioOutBuffers(nullptr), - fParamBuffers(nullptr) + fParamBuffers(nullptr), + fLatencyIndex(-1) { carla_debug("DssiPlugin::DssiPlugin(%p, %i)", engine, id); @@ -90,14 +91,14 @@ public: { try { fDescriptor->cleanup(fHandle); - } catch(...) {} + } CARLA_SAFE_EXCEPTION("DSSI cleanup"); } if (fHandle2 != nullptr) { try { fDescriptor->cleanup(fHandle2); - } catch(...) {} + } CARLA_SAFE_EXCEPTION("DSSI cleanup #2"); } } @@ -186,7 +187,8 @@ public: if (! isDssiVst) { - options |= PLUGIN_OPTION_FIXED_BUFFERS; + if (fLatencyIndex == -1) + options |= PLUGIN_OPTION_FIXED_BUFFERS; if (pData->engine->getProccessMode() != ENGINE_PROCESS_MODE_CONTINUOUS_RACK) { @@ -222,70 +224,64 @@ public: void getLabel(char* const strBuf) const noexcept override { - CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); + CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf)); + CARLA_SAFE_ASSERT_RETURN(fDescriptor->Label != nullptr, nullStrBuf(strBuf)); - if (fDescriptor->Label != nullptr) - { - std::strncpy(strBuf, fDescriptor->Label, STR_MAX); - return; - } - - CarlaPlugin::getLabel(strBuf); + std::strncpy(strBuf, fDescriptor->Label, STR_MAX); } void getMaker(char* const strBuf) const noexcept override { - CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); + CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf)); + CARLA_SAFE_ASSERT_RETURN(fDescriptor->Maker != nullptr, nullStrBuf(strBuf)); - if (fDescriptor->Maker != nullptr) - { - std::strncpy(strBuf, fDescriptor->Maker, STR_MAX); - return; - } - - CarlaPlugin::getMaker(strBuf); + std::strncpy(strBuf, fDescriptor->Maker, STR_MAX); } void getCopyright(char* const strBuf) const noexcept override { - CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); + CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf)); + CARLA_SAFE_ASSERT_RETURN(fDescriptor->Copyright != nullptr, nullStrBuf(strBuf)); - if (fDescriptor->Copyright != nullptr) - { - std::strncpy(strBuf, fDescriptor->Copyright, STR_MAX); - return; - } - - CarlaPlugin::getCopyright(strBuf); + std::strncpy(strBuf, fDescriptor->Copyright, STR_MAX); } void getRealName(char* const strBuf) const noexcept override { - CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); + CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf)); + CARLA_SAFE_ASSERT_RETURN(fDescriptor->Name != nullptr, nullStrBuf(strBuf)); - if (fDescriptor->Name != nullptr) - { - std::strncpy(strBuf, fDescriptor->Name, STR_MAX); + std::strncpy(strBuf, fDescriptor->Name, STR_MAX); + } + + void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override + { + CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf)); + CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, nullStrBuf(strBuf)); + + const int32_t rindex(pData->param.data[parameterId].rindex); + + CARLA_SAFE_ASSERT_RETURN(rindex < static_cast(fDescriptor->PortCount), nullStrBuf(strBuf)); + CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, nullStrBuf(strBuf)); + + if (getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, true)) return; - } - CarlaPlugin::getRealName(strBuf); + std::strncpy(strBuf, fDescriptor->PortNames[rindex], STR_MAX); } - void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override + void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override { - CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,); - CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,); + CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, nullStrBuf(strBuf)); const int32_t rindex(pData->param.data[parameterId].rindex); - if (rindex < static_cast(fDescriptor->PortCount) && fDescriptor->PortNames[rindex] != nullptr) - { - std::strncpy(strBuf, fDescriptor->PortNames[rindex], STR_MAX); + CARLA_SAFE_ASSERT_RETURN(rindex < static_cast(fDescriptor->PortCount), nullStrBuf(strBuf)); + + if (getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, false)) return; - } - CarlaPlugin::getParameterName(parameterId, strBuf); + nullStrBuf(strBuf); } // ------------------------------------------------------------------- @@ -447,7 +443,7 @@ public: clearBuffers(); const float sampleRate(static_cast(pData->engine->getSampleRate())); - const uint32_t portCount(static_cast(fDescriptor->PortCount)); + const uint32_t portCount(getSafePortCount()); uint32_t aIns, aOuts, mIns, params; aIns = aOuts = mIns = params = 0; @@ -458,26 +454,19 @@ public: bool needsCtrlIn, needsCtrlOut; needsCtrlIn = needsCtrlOut = false; - if (portCount > 0) + for (uint32_t i=0; i < portCount; ++i) { - CARLA_ASSERT(fDescriptor->PortDescriptors != nullptr); - CARLA_ASSERT(fDescriptor->PortRangeHints != nullptr); - CARLA_ASSERT(fDescriptor->PortNames != nullptr); + const LADSPA_PortDescriptor portType(fDescriptor->PortDescriptors[i]); - for (uint32_t i=0; i < portCount; ++i) + if (LADSPA_IS_PORT_AUDIO(portType)) { - const LADSPA_PortDescriptor portType = fDescriptor->PortDescriptors[i]; - - if (LADSPA_IS_PORT_AUDIO(portType)) - { - if (LADSPA_IS_PORT_INPUT(portType)) - aIns += 1; - else if (LADSPA_IS_PORT_OUTPUT(portType)) - aOuts += 1; - } - else if (LADSPA_IS_PORT_CONTROL(portType)) - params += 1; + if (LADSPA_IS_PORT_INPUT(portType)) + aIns += 1; + else if (LADSPA_IS_PORT_OUTPUT(portType)) + aOuts += 1; } + else if (LADSPA_IS_PORT_CONTROL(portType)) + params += 1; } if ((pData->options & PLUGIN_OPTION_FORCE_STEREO) != 0 && (aIns == 1 || aOuts == 1)) @@ -485,8 +474,8 @@ public: if (fHandle2 == nullptr) { try { - fHandle2 = fDescriptor->instantiate(fDescriptor, (ulong)sampleRate); - } catch(...) {} + fHandle2 = fDescriptor->instantiate(fDescriptor, static_cast(sampleRate)); + } CARLA_SAFE_EXCEPTION("DSSI instantiate #2"); } if (fHandle2 != nullptr) @@ -546,8 +535,6 @@ public: const LADSPA_PortDescriptor portType = fDescriptor->PortDescriptors[i]; const LADSPA_PortRangeHint portRangeHints = fDescriptor->PortRangeHints[i]; - CARLA_ASSERT(fDescriptor->PortNames[i] != nullptr); - if (LADSPA_IS_PORT_AUDIO(portType)) { portName.clear(); @@ -558,7 +545,34 @@ public: portName += ":"; } - portName += fDescriptor->PortNames[i]; + if (fDescriptor->PortNames[i] != nullptr && fDescriptor->PortNames[i][0] != '\0') + { + portName += fDescriptor->PortNames[i]; + } + else + { + if (LADSPA_IS_PORT_INPUT(portType)) + { + if (aIns > 1) + { + portName += "audio-in_"; + portName += CarlaString(iAudioIn+1); + } + else + portName += "audio-in"; + } + else + { + if (aOuts > 1) + { + portName += "audio-out_"; + portName += CarlaString(iAudioOut+1); + } + else + portName += "audio-out"; + } + } + portName.truncate(portNameSize); if (LADSPA_IS_PORT_INPUT(portType)) @@ -596,6 +610,8 @@ public: pData->param.data[j].index = static_cast(j); pData->param.data[j].rindex = static_cast(i); + const char* const paramName(fDescriptor->PortNames[i] != nullptr ? fDescriptor->PortNames[i] : "unknown"); + float min, max, def, step, stepSmall, stepLarge; // min value @@ -611,11 +627,13 @@ public: max = 1.0f; if (min > max) - max = min; - - if (max - min == 0.0f) { - carla_stderr2("WARNING - Broken plugin parameter '%s': max - min == 0.0f", fDescriptor->PortNames[i]); + carla_stderr2("WARNING - Broken plugin parameter '%s': min > max", paramName); + min = max - 0.1f; + } + else if (min == max) + { + carla_stderr2("WARNING - Broken plugin parameter '%s': min == maxf", paramName); max = min + 0.1f; } @@ -651,7 +669,7 @@ public: } else { - float range = max - min; + const float range = max - min; step = range/100.0f; stepSmall = range/1000.0f; stepLarge = range/10.0f; @@ -680,7 +698,7 @@ public: { pData->param.data[j].type = PARAMETER_OUTPUT; - if (std::strcmp(fDescriptor->PortNames[i], "latency") == 0 || std::strcmp(fDescriptor->PortNames[i], "_latency") == 0) + if (std::strcmp(paramName, "latency") == 0 || std::strcmp(paramName, "_latency") == 0) { min = 0.0f; max = sampleRate; @@ -688,6 +706,7 @@ public: step = 1.0f; stepSmall = 1.0f; stepLarge = 1.0f; + fLatencyIndex = static_cast(j); pData->param.special[j] = PARAMETER_SPECIAL_LATENCY; } else @@ -699,7 +718,6 @@ public: } else { - pData->param.data[j].type = PARAMETER_UNKNOWN; carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)"); } @@ -717,20 +735,32 @@ public: // Start parameters in their default values fParamBuffers[j] = def; - fDescriptor->connect_port(fHandle, i, &fParamBuffers[j]); + try { + fDescriptor->connect_port(fHandle, i, &fParamBuffers[j]); + } CARLA_SAFE_EXCEPTION("DSSI connect_port parameter"); if (fHandle2 != nullptr) - fDescriptor->connect_port(fHandle2, i, &fParamBuffers[j]); + { + try { + fDescriptor->connect_port(fHandle2, i, &fParamBuffers[j]); + } CARLA_SAFE_EXCEPTION("DSSI connect_port parameter #2"); + } } else { // Not Audio or Control carla_stderr2("ERROR - Got a broken Port (neither Audio or Control)"); - fDescriptor->connect_port(fHandle, i, nullptr); + try { + fDescriptor->connect_port(fHandle, i, nullptr); + } CARLA_SAFE_EXCEPTION("DSSI connect_port null"); if (fHandle2 != nullptr) - fDescriptor->connect_port(fHandle2, i, nullptr); + { + try { + fDescriptor->connect_port(fHandle2, i, nullptr); + } CARLA_SAFE_EXCEPTION("DSSI connect_port null #2"); + } } } @@ -780,6 +810,7 @@ public: if (fUiFilename != nullptr) pData->hints |= PLUGIN_HAS_CUSTOM_UI; +#ifndef BUILD_BRIDGE if (aOuts > 0 && (aIns == aOuts || aIns == 1)) pData->hints |= PLUGIN_CAN_DRYWET; @@ -788,6 +819,7 @@ public: if (aOuts >= 2 && aOuts % 2 == 0) pData->hints |= PLUGIN_CAN_BALANCE; +#endif // extra plugin hints pData->extraHints = 0x0; @@ -799,55 +831,70 @@ public: pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK; // check latency - if (pData->hints & PLUGIN_CAN_DRYWET) + if (fLatencyIndex >= 0) { - for (uint32_t i=0; i < pData->param.count; ++i) - { - if (pData->param.special[i] != PARAMETER_SPECIAL_LATENCY) - continue; + // we need to pre-run the plugin so it can update its latency control-port - // we need to pre-run the plugin so it can update its latency control-port + float tmpIn[aIns][2]; + float tmpOut[aOuts][2]; - float tmpIn[aIns][2]; - float tmpOut[aOuts][2]; - - for (uint32_t j=0; j < aIns; ++j) - { - tmpIn[j][0] = 0.0f; - tmpIn[j][1] = 0.0f; + for (uint32_t j=0; j < aIns; ++j) + { + tmpIn[j][0] = 0.0f; + tmpIn[j][1] = 0.0f; + try { fDescriptor->connect_port(fHandle, pData->audioIn.ports[j].rindex, tmpIn[j]); - } + } CARLA_SAFE_EXCEPTION("DSSI connect_port latency input"); + } - for (uint32_t j=0; j < aOuts; ++j) - { - tmpOut[j][0] = 0.0f; - tmpOut[j][1] = 0.0f; + for (uint32_t j=0; j < aOuts; ++j) + { + tmpOut[j][0] = 0.0f; + tmpOut[j][1] = 0.0f; + try { fDescriptor->connect_port(fHandle, pData->audioOut.ports[j].rindex, tmpOut[j]); - } + } CARLA_SAFE_EXCEPTION("DSSI connect_port latency output"); + } - if (fDescriptor->activate != nullptr) + if (fDescriptor->activate != nullptr) + { + try { fDescriptor->activate(fHandle); + } CARLA_SAFE_EXCEPTION("DSSI latency activate"); + } + try { fDescriptor->run(fHandle, 2); + } CARLA_SAFE_EXCEPTION("DSSI latency run"); - if (fDescriptor->deactivate != nullptr) + if (fDescriptor->deactivate != nullptr) + { + try { fDescriptor->deactivate(fHandle); + } CARLA_SAFE_EXCEPTION("DSSI latency deactivate"); + } - const uint32_t latency = (uint32_t)fParamBuffers[i]; + const int32_t latency(static_cast(fParamBuffers[fLatencyIndex])); - if (pData->latency != latency) + if (latency >= 0) + { + const uint32_t ulatency(static_cast(latency)); + + if (pData->latency != ulatency) { - pData->latency = latency; - pData->client->setLatency(latency); + carla_stdout("latency = %i", latency); + + pData->latency = ulatency; + pData->client->setLatency(ulatency); #ifndef BUILD_BRIDGE pData->recreateLatencyBuffers(); #endif } - - break; } + else + carla_safe_assert_int("latency >= 0", __FILE__, __LINE__, latency); } bufferSizeChanged(pData->engine->getBufferSize()); @@ -963,15 +1010,38 @@ public: { try { fDescriptor->activate(fHandle); - } catch(...) {} + } CARLA_SAFE_EXCEPTION("DSSI activate"); if (fHandle2 != nullptr) { try { fDescriptor->activate(fHandle2); - } catch(...) {} + } CARLA_SAFE_EXCEPTION("DSSI activate #2"); } } + + if (fLatencyIndex < 0) + return; + + const int32_t latency(static_cast(fParamBuffers[fLatencyIndex])); + CARLA_SAFE_ASSERT_RETURN(latency >= 0,); + + const uint32_t ulatency(static_cast(latency)); + + if (pData->latency != ulatency) + { + carla_stdout("latency changed to %i", latency); + + pData->latency = ulatency; + pData->client->setLatency(ulatency); +#ifndef BUILD_BRIDGE + try { + pData->recreateLatencyBuffers(); // FIXME + } CARLA_SAFE_EXCEPTION("DSSI recreateLatencyBuffers()"); +#endif + } + else + carla_stdout("latency still the same %i", latency); } void deactivate() noexcept override @@ -983,13 +1053,13 @@ public: { try { fDescriptor->deactivate(fHandle); - } catch(...) {} + } CARLA_SAFE_EXCEPTION("DSSI deactivate"); if (fHandle2 != nullptr) { try { fDescriptor->deactivate(fHandle2); - } catch(...) {} + } CARLA_SAFE_EXCEPTION("DSSI deactivate #2"); } } } @@ -1088,8 +1158,8 @@ public: // ---------------------------------------------------------------------------------------------------- // Event Input (System) - bool allNotesOffSent = false; - bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; + bool allNotesOffSent = false; + const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; uint32_t numEvents = pData->event.portIn->getEventCount(); uint32_t startTime = 0; @@ -1435,7 +1505,27 @@ public: } // End of Plugin processing (no events) - CARLA_PROCESS_CONTINUE_CHECK; + // -------------------------------------------------------------------------------------------------------- + // Latency, save values for next callback + + if (pData->latency > 0) + { + if (pData->latency <= frames) + { + for (uint32_t i=0; i < pData->audioIn.count; ++i) + FLOAT_COPY(pData->latencyBuffers[i], inBuffer[i]+(frames-pData->latency), pData->latency); + } + else + { + for (uint32_t i=0, j, k; i < pData->audioIn.count; ++i) + { + for (k=0; k < pData->latency-frames; ++k) + pData->latencyBuffers[i][k] = pData->latencyBuffers[i][k+frames]; + for (j=0; k < pData->latency; ++j, ++k) + pData->latencyBuffers[i][k] = inBuffer[i][j]; + } + } + } // -------------------------------------------------------------------------------------------------------- // Control Output @@ -1507,6 +1597,8 @@ public: // -------------------------------------------------------------------------------------------------------- // Run plugin + // TODO - try catch + if (fDssiDescriptor->run_synth != nullptr) { fDssiDescriptor->run_synth(fHandle, frames, fMidiEvents, midiEventCount); @@ -1537,6 +1629,7 @@ public: { const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && pData->postProc.dryWet != 1.0f; const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && (pData->postProc.balanceLeft != -1.0f || pData->postProc.balanceRight != 1.0f); + const bool isMono = (pData->audioIn.count == 1); bool isPair; float bufValue, oldBufLeft[doBalance ? frames : 1]; @@ -1548,13 +1641,13 @@ public: { for (uint32_t k=0; k < frames; ++k) { - // TODO - //if (k < pData->latency && pData->latency < frames) - // bufValue = (pData->audioIn.count == 1) ? pData->latencyBuffers[0][k] : pData->latencyBuffers[i][k]; - //else - // bufValue = (pData->audioIn.count == 1) ? inBuffer[0][k-m_latency] : inBuffer[i][k-m_latency]; + if (k < pData->latency) + bufValue = pData->latencyBuffers[isMono ? 0 : i][k]; + else if (pData->latency < frames) + bufValue = fAudioInBuffers[isMono ? 0 : i][k-pData->latency]; + else + bufValue = fAudioInBuffers[isMono ? 0 : i][k]; - bufValue = fAudioInBuffers[(pData->audioIn.count == 1) ? 0 : i][k]; fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); } } @@ -1597,14 +1690,6 @@ public: } } -#if 0 - // Latency, save values for next callback, TODO - if (pData->latency > 0 && pData->latency < frames) - { - for (i=0; i < pData->audioIn.count; ++i) - FLOAT_COPY(pData->latencyBuffers[i], inBuffer[i] + (frames - pData->latency), pData->latency); - } -#endif } // End of Post-processing #else // BUILD_BRIDGE @@ -1645,13 +1730,19 @@ public: for (uint32_t i=0; i < pData->audioIn.count; ++i) { CARLA_ASSERT(fAudioInBuffers[i] != nullptr); - fDescriptor->connect_port(fHandle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]); + + try { + fDescriptor->connect_port(fHandle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]); + } CARLA_SAFE_EXCEPTION("DSSI connect_port audio input"); } for (uint32_t i=0; i < pData->audioOut.count; ++i) { CARLA_ASSERT(fAudioOutBuffers[i] != nullptr); - fDescriptor->connect_port(fHandle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]); + + try { + fDescriptor->connect_port(fHandle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]); + } CARLA_SAFE_EXCEPTION("DSSI connect_port audio output"); } } else @@ -1662,8 +1753,13 @@ public: CARLA_ASSERT(fAudioInBuffers[0] != nullptr); CARLA_ASSERT(fAudioInBuffers[1] != nullptr); - fDescriptor->connect_port(fHandle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]); - fDescriptor->connect_port(fHandle2, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]); + try { + fDescriptor->connect_port(fHandle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]); + } CARLA_SAFE_EXCEPTION("DSSI connect_port audio input #1"); + + try { + fDescriptor->connect_port(fHandle2, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]); + } CARLA_SAFE_EXCEPTION("DSSI connect_port audio input #2"); } if (pData->audioOut.count > 0) @@ -1672,8 +1768,13 @@ public: CARLA_ASSERT(fAudioOutBuffers[0] != nullptr); CARLA_ASSERT(fAudioOutBuffers[1] != nullptr); - fDescriptor->connect_port(fHandle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]); - fDescriptor->connect_port(fHandle2, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]); + try { + fDescriptor->connect_port(fHandle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]); + } CARLA_SAFE_EXCEPTION("DSSI connect_port audio output #1"); + + try { + fDescriptor->connect_port(fHandle2, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]); + } CARLA_SAFE_EXCEPTION("DSSI connect_port audio output #2"); } } @@ -1857,10 +1958,46 @@ public: // get descriptor that matches label ulong i = 0; - while ((fDssiDescriptor = descFn(i++)) != nullptr) + + for (;;) { + try { + fDssiDescriptor = descFn(i++); + } + catch(...) { + carla_stderr2("Caught exception when trying to get LADSPA descriptor"); + fDescriptor = nullptr; + fDssiDescriptor = nullptr; + break; + } + + if (fDssiDescriptor == nullptr) + break; + fDescriptor = fDssiDescriptor->LADSPA_Plugin; - if (fDescriptor != nullptr && fDescriptor->Label != nullptr && std::strcmp(fDescriptor->Label, label) == 0) + + if (fDescriptor == nullptr) + { + carla_stderr2("WARNING - Missing LADSPA interface, will not use this plugin"); + fDssiDescriptor = nullptr; + break; + } + if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0') + { + carla_stderr2("WARNING - Got an invalid label, will not use this plugin"); + fDescriptor = nullptr; + fDssiDescriptor = nullptr; + break; + } + if (fDescriptor->run == nullptr) + { + carla_stderr2("WARNING - Plugin has no run, cannot use it"); + fDescriptor = nullptr; + fDssiDescriptor = nullptr; + break; + } + + if (std::strcmp(fDescriptor->Label, label) == 0) break; } @@ -1910,7 +2047,7 @@ public: try { fHandle = fDescriptor->instantiate(fDescriptor, (ulong)pData->engine->getSampleRate()); - } catch(...) {} + } CARLA_SAFE_EXCEPTION("DSSI instantiate"); if (fHandle == nullptr) { @@ -1956,7 +2093,7 @@ public: pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES; - if (isDssiVst) + if (fLatencyIndex >= 0 || isDssiVst) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; if (pData->engine->getOptions().forceStereo) @@ -1993,7 +2130,7 @@ public: pData->options = pData->loadSettings(pData->options, getOptionsAvailable()); // ignore settings, we need this anyway - if (isDssiVst) + if (fLatencyIndex >= 0 || isDssiVst) pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; #endif } @@ -2015,10 +2152,72 @@ private: float** fAudioInBuffers; float** fAudioOutBuffers; float* fParamBuffers; + int32_t fLatencyIndex; // -1 if invalid + snd_seq_event_t fMidiEvents[kPluginMaxMidiEvents]; // ------------------------------------------------------------------- + uint32_t getSafePortCount() const noexcept + { + if (fDescriptor->PortCount == 0) + return 0; + + CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortDescriptors != nullptr, 0); + CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortRangeHints != nullptr, 0); + CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames != nullptr, 0); + + return static_cast(fDescriptor->PortCount); + } + + bool getSeparatedParameterNameOrUnit(const char* const paramName, char* const strBuf, const bool wantName) const noexcept + { + if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, true)) + return true; + if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, false)) + return true; + return false; + } + + bool _getSeparatedParameterNameOrUnitImpl(const char* const paramName, char* const strBuf, const bool wantName, const bool useBracket) const noexcept + { + const char* const sepBracketStart(std::strstr(paramName, useBracket ? " [" : " (")); + + if (sepBracketStart == nullptr) + return false; + + const char* const sepBracketEnd(std::strstr(sepBracketStart, useBracket ? "]" : ")")); + + if (sepBracketEnd == nullptr) + return false; + + const size_t unitSize(static_cast(sepBracketEnd-sepBracketStart-2)); + + if (unitSize > 7) // very unlikely to have such big unit + return false; + + const size_t sepIndex(std::strlen(paramName)-unitSize-3); + + // just in case + if (sepIndex > STR_MAX) + return false; + + if (wantName) + { + std::strncpy(strBuf, paramName, sepIndex); + strBuf[sepIndex] = '\0'; + } + else + { + std::strncpy(strBuf, paramName+(sepIndex+2), unitSize); + strBuf[unitSize] = '\0'; + } + + return true; + } + + // ------------------------------------------------------------------- + static LinkedList sMultiSynthList; static bool addUniqueMultiSynth(const char* const label) noexcept @@ -2062,6 +2261,8 @@ private: } } + // ------------------------------------------------------------------- + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DssiPlugin) }; diff --git a/source/backend/plugin/LadspaPlugin.cpp b/source/backend/plugin/LadspaPlugin.cpp index 995937bb6..a1a4bf387 100644 --- a/source/backend/plugin/LadspaPlugin.cpp +++ b/source/backend/plugin/LadspaPlugin.cpp @@ -350,6 +350,8 @@ public: } } + CARLA_SAFE_ASSERT_RETURN(rindex < static_cast(fDescriptor->PortCount), nullStrBuf(strBuf)); + if (getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, false)) return; @@ -911,7 +913,9 @@ public: pData->latency = ulatency; pData->client->setLatency(ulatency); #ifndef BUILD_BRIDGE - pData->recreateLatencyBuffers(); + try { + pData->recreateLatencyBuffers(); // FIXME + } CARLA_SAFE_EXCEPTION("LADSPA recreateLatencyBuffers()"); #endif } else @@ -1633,6 +1637,8 @@ private: float* fParamBuffers; int32_t fLatencyIndex; // -1 if invalid + // ------------------------------------------------------------------- + uint32_t getSafePortCount() const noexcept { if (fDescriptor->PortCount == 0) @@ -1691,6 +1697,8 @@ private: return true; } + // ------------------------------------------------------------------- + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LadspaPlugin) };