diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index e05189b..14cbfac 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -11,16 +11,12 @@ under the European Union’s Horizon 2020 research and innovation programme #pragma once #include "SCBufferAdaptor.hpp" - -#include - #include #include #include #include - +#include #include - #include #include #include @@ -39,29 +35,26 @@ namespace impl { // Iterate over kr/ir inputs via callbacks from params object struct FloatControlsIter { - FloatControlsIter(float **vals, index N) - : mValues(vals) - , mSize(N) - {} - + FloatControlsIter(float** vals, index N) : mValues(vals), mSize(N) {} + float next() { return mCount >= mSize ? 0 : *mValues[mCount++]; } - - void reset(float **vals) + + void reset(float** vals) { mValues = vals; - mCount = 0; + mCount = 0; } - + index size() const noexcept { return mSize; } - + private: - float **mValues; - index mSize; - index mCount{0}; + float** mValues; + index mSize; + index mCount{0}; }; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////// - +//////////////////////////////////////////////////////////////////////////////// + // Real Time Processor template @@ -69,46 +62,52 @@ class RealTime : public SCUnit { using HostVector = FluidTensorView; using ParamSetType = typename Client::ParamSetType; - - // using Client = typename Wrapper::ClientType; public: - static void setup(InterfaceTable *ft, const char *name) + static void setup(InterfaceTable* ft, const char* name) { registerUnit(ft, name); ft->fDefineUnitCmd(name, "latency", doLatency); } - static void doLatency(Unit *unit, sc_msg_iter*) + static void doLatency(Unit* unit, sc_msg_iter*) { - float l[]{static_cast(static_cast(unit)->mClient.latency())}; - auto ft = Wrapper::getInterfaceTable(); + float l[]{ + static_cast(static_cast(unit)->mClient.latency())}; + auto ft = Wrapper::getInterfaceTable(); std::stringstream ss; ss << '/' << Wrapper::getName() << "_latency"; std::cout << ss.str() << '\n'; ft->fSendNodeReply(&unit->mParent->mNode, -1, ss.str().c_str(), 1, l); } - + RealTime() - : mControlsIterator{mInBuf + mSpecialIndex + 1,static_cast(mNumInputs) - mSpecialIndex - 1} - , mParams{Wrapper::Client::getParameterDescriptors()} - , mClient{Wrapper::setParams(mParams,mWorld->mVerbosity > 0, mWorld, mControlsIterator,true)} + : mControlsIterator{mInBuf + mSpecialIndex + 1, + static_cast(mNumInputs) - mSpecialIndex - 1}, + mParams{Wrapper::Client::getParameterDescriptors()}, + mClient{Wrapper::setParams(mParams, mWorld->mVerbosity > 0, mWorld, + mControlsIterator, true)} {} void init() { - assert(!(mClient.audioChannelsOut() > 0 && mClient.controlChannelsOut() > 0) && - "Client can't have both audio and control outputs"); + assert( + !(mClient.audioChannelsOut() > 0 && mClient.controlChannelsOut() > 0) && + "Client can't have both audio and control outputs"); - //If we don't the number of arguments we expect, the language side code is probably the wrong version - //set plugin to no-op, squawk, and bail; - if(mControlsIterator.size() != Client::getParameterDescriptors().count()) + // If we don't the number of arguments we expect, the language side code is + // probably the wrong version set plugin to no-op, squawk, and bail; + if (mControlsIterator.size() != Client::getParameterDescriptors().count()) { mCalcFunc = Wrapper::getInterfaceTable()->fClearUnitOutputs; - std::cout << "ERROR: " << Wrapper::getName() << " wrong number of arguments. Expected " - << Client::getParameterDescriptors().count() << ", got " << mControlsIterator.size() - << ". Your .sc file and binary plugin might be different versions." << std::endl; + std::cout + << "ERROR: " << Wrapper::getName() + << " wrong number of arguments. Expected " + << Client::getParameterDescriptors().count() << ", got " + << mControlsIterator.size() + << ". Your .sc file and binary plugin might be different versions." + << std::endl; return; } @@ -116,7 +115,8 @@ public: mInputConnections.reserve(asUnsigned(mClient.audioChannelsIn())); mOutputConnections.reserve(asUnsigned(mClient.audioChannelsOut())); mAudioInputs.reserve(asUnsigned(mClient.audioChannelsIn())); - mOutputs.reserve(asUnsigned(std::max(mClient.audioChannelsOut(), mClient.controlChannelsOut()))); + mOutputs.reserve(asUnsigned( + std::max(mClient.audioChannelsOut(), mClient.controlChannelsOut()))); for (index i = 0; i < mClient.audioChannelsIn(); ++i) { @@ -130,36 +130,39 @@ public: mOutputs.emplace_back(nullptr, 0, 0); } - for (index i = 0; i < mClient.controlChannelsOut(); ++i) { mOutputs.emplace_back(nullptr, 0, 0); } - + for (index i = 0; i < mClient.controlChannelsOut(); ++i) + { mOutputs.emplace_back(nullptr, 0, 0); } + mCalcFunc = make_calc_function(); Wrapper::getInterfaceTable()->fClearUnitOutputs(this, 1); } void next(int) { - mControlsIterator.reset(mInBuf + 1); //mClient.audioChannelsIn()); - Wrapper::setParams(mParams, mWorld->mVerbosity > 0, mWorld, mControlsIterator); // forward on inputs N + audio inputs as params - mParams.constrainParameterValues(); - const Unit *unit = this; + mControlsIterator.reset(mInBuf + 1); // mClient.audioChannelsIn()); + Wrapper::setParams( + mParams, mWorld->mVerbosity > 0, mWorld, + mControlsIterator); // forward on inputs N + audio inputs as params + mParams.constrainParameterValues(); + const Unit* unit = this; for (index i = 0; i < mClient.audioChannelsIn(); ++i) { if (mInputConnections[asUnsigned(i)]) - { - mAudioInputs[asUnsigned(i)].reset(IN(i), 0, fullBufferSize()); - } + { mAudioInputs[asUnsigned(i)].reset(IN(i), 0, fullBufferSize()); } } for (index i = 0; i < mClient.audioChannelsOut(); ++i) { assert(i <= std::numeric_limits::max()); - if (mOutputConnections[asUnsigned(i)]) mOutputs[asUnsigned(i)].reset(out(static_cast(i)), 0, fullBufferSize()); + if (mOutputConnections[asUnsigned(i)]) + mOutputs[asUnsigned(i)].reset(out(static_cast(i)), 0, + fullBufferSize()); } for (index i = 0; i < mClient.controlChannelsOut(); ++i) { assert(i <= std::numeric_limits::max()); mOutputs[asUnsigned(i)].reset(out(static_cast(i)), 0, 1); } - mClient.process(mAudioInputs, mOutputs,mContext); + mClient.process(mAudioInputs, mOutputs, mContext); } private: @@ -171,97 +174,107 @@ private: FluidContext mContext; protected: - ParamSetType mParams; - Client mClient; + ParamSetType mParams; + Client mClient; }; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// /// Non Real Time Processor -/// This is also a UGen, but the main action is delegated off to a worker thread, via the NRT thread. -/// The RT bit is there to allow us (a) to poll our thread and (b) emit a kr progress update +/// This is also a UGen, but the main action is delegated off to a worker +/// thread, via the NRT thread. The RT bit is there to allow us (a) to poll our +/// thread and (b) emit a kr progress update template -class NonRealTime: public SCUnit +class NonRealTime : public SCUnit { using ParamSetType = typename Client::ParamSetType; - -public: - static void setup(InterfaceTable *ft, const char *name) +public: + static void setup(InterfaceTable* ft, const char* name) { registerUnit(ft, name); ft->fDefineUnitCmd(name, "cancel", doCancel); - ft->fDefineUnitCmd(name, "queue_enabled", [](struct Unit* unit, struct sc_msg_iter* args) - { - auto w = static_cast(unit); - w->mQueueEnabled = args->geti(0); - w->mFifoMsg.Set(w->mWorld,[](FifoMsg* f) - { - auto w = static_cast(f->mData); - w->mClient.setQueueEnabled(w->mQueueEnabled); - },nullptr,w); - Wrapper::getInterfaceTable()->fSendMsgFromRT(w->mWorld, w->mFifoMsg); - }); - ft->fDefineUnitCmd(name, "synchronous", [](struct Unit* unit, struct sc_msg_iter* args) - { - auto w = static_cast(unit); - w->mSynchronous = args->geti(0); - w->mFifoMsg.Set(w->mWorld,[](FifoMsg* f) - { - auto w = static_cast(f->mData); - w->mClient.setSynchronous(w->mSynchronous); - },nullptr,w); - Wrapper::getInterfaceTable()->fSendMsgFromRT(w->mWorld, w->mFifoMsg); - }); + ft->fDefineUnitCmd( + name, "queue_enabled", [](struct Unit* unit, struct sc_msg_iter* args) { + auto w = static_cast(unit); + w->mQueueEnabled = args->geti(0); + w->mFifoMsg.Set( + w->mWorld, + [](FifoMsg* f) { + auto w = static_cast(f->mData); + w->mClient.setQueueEnabled(w->mQueueEnabled); + }, + nullptr, w); + Wrapper::getInterfaceTable()->fSendMsgFromRT(w->mWorld, w->mFifoMsg); + }); + ft->fDefineUnitCmd( + name, "synchronous", [](struct Unit* unit, struct sc_msg_iter* args) { + auto w = static_cast(unit); + w->mSynchronous = args->geti(0); + w->mFifoMsg.Set( + w->mWorld, + [](FifoMsg* f) { + auto w = static_cast(f->mData); + w->mClient.setSynchronous(w->mSynchronous); + }, + nullptr, w); + Wrapper::getInterfaceTable()->fSendMsgFromRT(w->mWorld, w->mFifoMsg); + }); } - - /// Penultimate input is the doneAction, final is blocking mode. Neither are params, so we skip them in the controlsIterator - NonRealTime() : - mControlsIterator{mInBuf,index(mNumInputs) - mSpecialIndex - 2} - , mParams{Wrapper::Client::getParameterDescriptors()} - , mClient{Wrapper::setParams(mParams,mWorld->mVerbosity > 0, mWorld, mControlsIterator,true)} - , mSynchronous{mNumInputs > 2 ? (in0(int(mNumInputs) - 1) > 0) : false} + + /// Penultimate input is the doneAction, final is blocking mode. Neither are + /// params, so we skip them in the controlsIterator + NonRealTime() + : mControlsIterator{mInBuf, index(mNumInputs) - mSpecialIndex - 2}, + mParams{Wrapper::Client::getParameterDescriptors()}, + mClient{Wrapper::setParams(mParams, mWorld->mVerbosity > 0, mWorld, + mControlsIterator, true)}, + mSynchronous{mNumInputs > 2 ? (in0(int(mNumInputs) - 1) > 0) : false} {} - + ~NonRealTime() { - if(mClient.state() == ProcessState::kProcessing) + if (mClient.state() == ProcessState::kProcessing) { std::cout << Wrapper::getName() << ": Processing cancelled \n"; - Wrapper::getInterfaceTable()->fSendNodeReply(&mParent->mNode,1,"/done",0,nullptr); + Wrapper::getInterfaceTable()->fSendNodeReply(&mParent->mNode, 1, "/done", + 0, nullptr); } - //processing will be cancelled in ~NRTThreadAdaptor() + // processing will be cancelled in ~NRTThreadAdaptor() } - + /// No option of not using a worker thread for now - /// init() sets up the NRT process via the SC NRT thread, and then sets our UGen calc function going + /// init() sets up the NRT process via the SC NRT thread, and then sets our + /// UGen calc function going void init() { mFifoMsg.Set(mWorld, initNRTJob, nullptr, this); - mWorld->ft->fSendMsgFromRT(mWorld,mFifoMsg); - //we want to poll thread roughly every 20ms + mWorld->ft->fSendMsgFromRT(mWorld, mFifoMsg); + // we want to poll thread roughly every 20ms checkThreadInterval = static_cast(0.02 / controlDur()); set_calc_function(); }; - - /// The calc function. Checks to see if we've cancelled, spits out progress, launches tidy up when complete + + /// The calc function. Checks to see if we've cancelled, spits out progress, + /// launches tidy up when complete void poll(int) { out0(0) = mDone ? 1.0 : static_cast(mClient.progress()); - if(0 == pollCounter++ && !mCheckingForDone) + if (0 == pollCounter++ && !mCheckingForDone) { mCheckingForDone = true; - mWorld->ft->fDoAsynchronousCommand(mWorld, nullptr, Wrapper::getName(), this, - postProcess, exchangeBuffers, tidyUp, destroy, - 0, nullptr); + mWorld->ft->fDoAsynchronousCommand(mWorld, nullptr, Wrapper::getName(), + this, postProcess, exchangeBuffers, + tidyUp, destroy, 0, nullptr); } pollCounter %= checkThreadInterval; } - - /// To be called on NRT thread. Validate parameters and commence processing in new thread + + /// To be called on NRT thread. Validate parameters and commence processing in + /// new thread static void initNRTJob(FifoMsg* f) { auto w = static_cast(f->mData); @@ -269,42 +282,51 @@ public: w->mCancelled = false; Result result = validateParameters(w); - + if (!result.ok()) { - std::cout << "ERROR: " << Wrapper::getName() << ": " << result.message().c_str() << std::endl; - return; + std::cout << "ERROR: " << Wrapper::getName() << ": " + << result.message().c_str() << std::endl; + return; } - w->mClient.setSynchronous(w->mSynchronous); + w->mClient.setSynchronous(w->mSynchronous); w->mClient.enqueue(w->mParams); w->mClient.process(); } /// Check result and report if bad - static bool postProcess(World*, void *data) + static bool postProcess(World*, void* data) { - auto w = static_cast(data); - Result r; + auto w = static_cast(data); + Result r; ProcessState s = w->mClient.checkProgress(r); - - if((s==ProcessState::kDone || s==ProcessState::kDoneStillProcessing) - || (w->mSynchronous && s==ProcessState::kNoProcess) ) //I think this hinges on the fact that when mSynchrous = true, this call will always be behind process() on the command FIFO, so we can assume that if the state is kNoProcess, it has run (vs never having run) + + if ((s == ProcessState::kDone || s == ProcessState::kDoneStillProcessing) || + (w->mSynchronous && + s == ProcessState::kNoProcess)) // I think this hinges on the fact that + // when mSynchrous = true, this call + // will always be behind process() on + // the command FIFO, so we can assume + // that if the state is kNoProcess, it + // has run (vs never having run) { - //Given that cancellation from the language now always happens by freeing the - //synth, this block isn't reached normally. HOwever, if someone cancels using u_cmd, this is what will fire - if(r.status() == Result::Status::kCancelled) + // Given that cancellation from the language now always happens by freeing + // the synth, this block isn't reached normally. HOwever, if someone + // cancels using u_cmd, this is what will fire + if (r.status() == Result::Status::kCancelled) { - std::cout << Wrapper::getName() << ": Processing cancelled \n"; + std::cout << Wrapper::getName() << ": Processing cancelled \n"; w->mCancelled = true; return false; } - - if(!r.ok()) + + if (!r.ok()) { - std::cout << "ERROR: " << Wrapper::getName() << ": " << r.message().c_str() << '\n'; + std::cout << "ERROR: " << Wrapper::getName() << ": " + << r.message().c_str() << '\n'; return false; } - + w->mDone = true; return true; } @@ -312,50 +334,65 @@ public: } /// swap NRT buffers back to RT-land - static bool exchangeBuffers(World *world, void *data) { return static_cast(data)->exchangeBuffers(world); } + static bool exchangeBuffers(World* world, void* data) + { + return static_cast(data)->exchangeBuffers(world); + } /// Tidy up any temporary buffers - static bool tidyUp(World *world, void *data) { return static_cast(data)->tidyUp(world); } - - /// Now we're actually properly done, call the UGen's done action (possibly destroying this instance) + static bool tidyUp(World* world, void* data) + { + return static_cast(data)->tidyUp(world); + } + + /// Now we're actually properly done, call the UGen's done action (possibly + /// destroying this instance) static void destroy(World* world, void* data) { auto w = static_cast(data); - if(w->mDone && w->mNumInputs > 2) //don't check for doneAction if UGen has no ins (there should be 3 minimum -> sig, doneAction, blocking mode) + if (w->mDone && + w->mNumInputs > + 2) // don't check for doneAction if UGen has no ins (there should be + // 3 minimum -> sig, doneAction, blocking mode) { - int doneAction = static_cast(w->in0(int(w->mNumInputs) - 2)); //doneAction is penultimate input; THIS IS THE LAW - world->ft->fDoneAction(doneAction,w); + int doneAction = static_cast( + w->in0(int(w->mNumInputs) - + 2)); // doneAction is penultimate input; THIS IS THE LAW + world->ft->fDoneAction(doneAction, w); return; } w->mCheckingForDone = false; } - - static void doCancel(Unit *unit, sc_msg_iter*) + + static void doCancel(Unit* unit, sc_msg_iter*) { - static_cast(unit)->mClient.cancel(); + static_cast(unit)->mClient.cancel(); } + private: - - static Result validateParameters(NonRealTime *w) + static Result validateParameters(NonRealTime* w) { auto results = w->mParams.constrainParameterValues(); - for (auto &r : results) + for (auto& r : results) { if (!r.ok()) return r; } return {}; } - bool exchangeBuffers(World *world) //RT thread + bool exchangeBuffers(World* world) // RT thread { mParams.template forEachParamType(world); - //At this point, we can see if we're finished and let the language know (or it can wait for the doneAction, but that takes extra time) - //use replyID to convey status (0 = normal completion, 1 = cancelled) - if(mDone) world->ft->fSendNodeReply(&mParent->mNode,0,"/done",0,nullptr); - if(mCancelled) world->ft->fSendNodeReply(&mParent->mNode,1,"/done",0,nullptr); + // At this point, we can see if we're finished and let the language know (or + // it can wait for the doneAction, but that takes extra time) use replyID to + // convey status (0 = normal completion, 1 = cancelled) + if (mDone) + world->ft->fSendNodeReply(&mParent->mNode, 0, "/done", 0, nullptr); + if (mCancelled) + world->ft->fSendNodeReply(&mParent->mNode, 1, "/done", 0, nullptr); return true; } - bool tidyUp(World *) //NRT thread + bool tidyUp(World*) // NRT thread { mParams.template forEachParamType(); return true; @@ -364,52 +401,54 @@ private: template struct AssignBuffer { - void operator()(const typename BufferT::type &p, World *w) + void operator()(const typename BufferT::type& p, World* w) { - if (auto b = static_cast(p.get())) b->assignToRT(w); + if (auto b = static_cast(p.get())) b->assignToRT(w); } }; template struct CleanUpBuffer { - void operator()(const typename BufferT::type &p) + void operator()(const typename BufferT::type& p) { - if (auto b = static_cast(p.get())) b->cleanUp(); + if (auto b = static_cast(p.get())) b->cleanUp(); } }; - - FloatControlsIter mControlsIterator; - FifoMsg mFifoMsg; - char* mCompletionMessage = nullptr; - void* mReplyAddr = nullptr; - const char *mName = nullptr; - index checkThreadInterval; - index pollCounter{0}; + + FloatControlsIter mControlsIterator; + FifoMsg mFifoMsg; + char* mCompletionMessage = nullptr; + void* mReplyAddr = nullptr; + const char* mName = nullptr; + index checkThreadInterval; + index pollCounter{0}; + protected: - ParamSetType mParams; - Client mClient; - bool mSynchronous{true}; - bool mQueueEnabled{false}; - bool mCheckingForDone{false}; //only write to this from RT thread kthx - bool mCancelled{false}; + ParamSetType mParams; + Client mClient; + bool mSynchronous{true}; + bool mQueueEnabled{false}; + bool mCheckingForDone{false}; // only write to this from RT thread kthx + bool mCancelled{false}; }; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////// - +//////////////////////////////////////////////////////////////////////////////// + /// An impossible monstrosty template -class NonRealTimeAndRealTime : public RealTime, public NonRealTime +class NonRealTimeAndRealTime : public RealTime, + public NonRealTime { - static void setup(InterfaceTable *ft, const char *name) + static void setup(InterfaceTable* ft, const char* name) { - RealTime::setup(ft, name); - NonRealTime::setup(ft, name); + RealTime::setup(ft, name); + NonRealTime::setup(ft, name); } }; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////// - +//////////////////////////////////////////////////////////////////////////////// + // Template Specialisations for NRT/RT template @@ -418,57 +457,69 @@ class FluidSCWrapperImpl; template class FluidSCWrapperImpl : public NonRealTime -{ -//public: -// FluidSCWrapperImpl(World* w, sc_msg_iter *args): NonRealTime(w,args){}; -}; +{}; template -class FluidSCWrapperImpl : public RealTime +class FluidSCWrapperImpl + : public RealTime {}; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////// - +//////////////////////////////////////////////////////////////////////////////// + // Make base class(es), full of CRTP mixin goodness template -using FluidSCWrapperBase = FluidSCWrapperImpl, isNonRealTime, isRealTime>; +using FluidSCWrapperBase = + FluidSCWrapperImpl, isNonRealTime, + isRealTime>; } // namespace impl -//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -///The main wrapper +/// The main wrapper template class FluidSCWrapper : public impl::FluidSCWrapperBase { using FloatControlsIter = impl::FloatControlsIter; - + // Iterate over arguments via callbacks from params object template struct Setter { - static constexpr index argSize = C::getParameterDescriptors().template get().fixedSize; + static constexpr index argSize = + C::getParameterDescriptors().template get().fixedSize; - auto fromArgs(World *, FloatControlsIter& args, LongT::type, int) { return args.next(); } - auto fromArgs(World *, FloatControlsIter& args, FloatT::type, int) { return args.next(); } + auto fromArgs(World*, FloatControlsIter& args, LongT::type, int) + { + return args.next(); + } + auto fromArgs(World*, FloatControlsIter& args, FloatT::type, int) + { + return args.next(); + } - auto fromArgs(World *w, ArgType args, BufferT::type, int) + auto fromArgs(World* w, ArgType args, BufferT::type, int) { - typename LongT::type bufnum = static_cast(fromArgs(w, args, LongT::type(), -1)); - return BufferT::type(bufnum >= 0 ? new SCBufferAdaptor(bufnum, w) : nullptr); + typename LongT::type bufnum = + static_cast(fromArgs(w, args, LongT::type(), -1)); + return BufferT::type(bufnum >= 0 ? new SCBufferAdaptor(bufnum, w) + : nullptr); } - - auto fromArgs(World *w, ArgType args, InputBufferT::type, int) + + auto fromArgs(World* w, ArgType args, InputBufferT::type, int) { - typename LongT::type bufnum = static_cast(fromArgs(w, args, LongT::type(), -1)); - return InputBufferT::type(bufnum >= 0 ? new SCBufferAdaptor(bufnum, w) : nullptr); + typename LongT::type bufnum = + static_cast(fromArgs(w, args, LongT::type(), -1)); + return InputBufferT::type(bufnum >= 0 ? new SCBufferAdaptor(bufnum, w) + : nullptr); } - - typename T::type operator()(World *w, ArgType args) + + typename T::type operator()(World* w, ArgType args) { ParamLiteralConvertor a; - using LiteralType = typename ParamLiteralConvertor::LiteralType; + using LiteralType = + typename ParamLiteralConvertor::LiteralType; for (index i = 0; i < argSize; i++) a[i] = static_cast(fromArgs(w, args, a[0], 0)); @@ -479,35 +530,33 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase template using ControlSetter = Setter; - - static void doVersion(Unit *, sc_msg_iter *) + + static void doVersion(Unit*, sc_msg_iter*) { - std::cout << "Fluid Corpus Manipualtion Toolkit version " << fluidVersion() << '\n'; + std::cout << "Fluid Corpus Manipualtion Toolkit version " << fluidVersion() + << '\n'; } - - + + public: using Client = C; using ParameterSetType = typename C::ParamSetType; - FluidSCWrapper() - { - impl::FluidSCWrapperBase::init(); - } + FluidSCWrapper() { impl::FluidSCWrapperBase::init(); } - static const char *getName(const char *setName = nullptr) + static const char* getName(const char* setName = nullptr) { - static const char *name = nullptr; + static const char* name = nullptr; return (name = setName ? setName : name); } - static InterfaceTable *getInterfaceTable(InterfaceTable *setTable = nullptr) + static InterfaceTable* getInterfaceTable(InterfaceTable* setTable = nullptr) { - static InterfaceTable *ft = nullptr; + static InterfaceTable* ft = nullptr; return (ft = setTable ? setTable : ft); } - static void setup(InterfaceTable *ft, const char *name) + static void setup(InterfaceTable* ft, const char* name) { getName(name); getInterfaceTable(ft); @@ -515,23 +564,28 @@ public: ft->fDefineUnitCmd(name, "version", doVersion); } - static auto& setParams(ParameterSetType& p, bool verbose, World* world, FloatControlsIter& inputs, bool constrain = false) + static auto& setParams(ParameterSetType& p, bool verbose, World* world, + FloatControlsIter& inputs, bool constrain = false) { - //We won't even try and set params if the arguments don't match - if(inputs.size() == C::getParameterDescriptors().count()) + // We won't even try and set params if the arguments don't match + if (inputs.size() == C::getParameterDescriptors().count()) + { + p.template setParameterValues(verbose, world, inputs); + if (constrain) p.constrainParameterValues(); + } + else { - p.template setParameterValues(verbose, world, inputs); - if (constrain)p.constrainParameterValues(); - } else { - std::cout << "ERROR: " << getName() << ": parameter count mismatch. Perhaps your binary plugins and SC sources are different versions\n"; - //TODO: work out how to bring any further work to a halt + std::cout << "ERROR: " << getName() + << ": parameter count mismatch. Perhaps your binary plugins " + "and SC sources are different versions\n"; + // TODO: work out how to bring any further work to a halt } return p; } }; -template class Client> -void makeSCWrapper(const char *name, InterfaceTable *ft) +template