From a2f496781686692b6bf35426604ef2490b5eeeae Mon Sep 17 00:00:00 2001 From: Alex Harker Date: Tue, 22 Aug 2023 14:51:06 +0100 Subject: [PATCH] Rework Max wrapper to allow multiple inputs and different IO sizes for control objects --- source/include/FluidMaxWrapper.hpp | 137 +++++++++++++---------------- 1 file changed, 62 insertions(+), 75 deletions(-) diff --git a/source/include/FluidMaxWrapper.hpp b/source/include/FluidMaxWrapper.hpp index cf1c309e..e2dd2050 100644 --- a/source/include/FluidMaxWrapper.hpp +++ b/source/include/FluidMaxWrapper.hpp @@ -588,19 +588,29 @@ class FluidMaxWrapper void operator()(FluidMaxWrapper* x, long ac, t_atom* av) { FluidContext c; - + + index whichIn = proxy_getinlet((t_object *)x); + atom_getdouble_array(std::min(x->mListSize, ac), av, std::min(x->mListSize, ac), - x->mInputListData[0].data()); - x->mClient.process(x->mInputListViews, x->mOutputListViews, c); + x->mInputListData[whichIn].data()); - for (index i = asSigned(x->mDataOutlets.size()) - 1; i >= 0; --i) + if (!whichIn) { - atom_setdouble_array( - std::min(x->mListSize, ac), x->mOutputListAtoms.data(), - std::min(x->mListSize, ac), x->mOutputListData[i].data()); - outlet_list(x->mDataOutlets[i], nullptr, x->mListSize, - x->mOutputListAtoms.data()); + x->mClient.process(x->mInputListViews, x->mOutputListViews, c); + + index outSize = isControlOutFollowsIn ? std::min(x->mListSize, ac) : x->mClient.controlChannelsOut().size; + + for (index i = asSigned(x->mDataOutlets.size()) - 1; i >= 0; --i) + { + assert(x->mOutputListData[i].size() == outSize); + atom_setdouble_array(outSize, + x->mOutputListAtoms.data(), + outSize, + x->mOutputListData[i].data()); + outlet_list(x->mDataOutlets[i], nullptr, outSize, + x->mOutputListAtoms.data()); + } } } }; @@ -1252,7 +1262,7 @@ class FluidMaxWrapper //TODO: this implicitly assumes no audio in? if (index controlInputs = mClient.controlChannelsIn()) { - if(mListSize) + if (mListSize) { mInputListData.resize(controlInputs, mListSize); for (index i = 1; i <= controlInputs; ++i) @@ -1262,9 +1272,9 @@ class FluidMaxWrapper //we already have a left inlet, but do we need more? index newInlets = controlInputs - 1; mProxies.reserve(newInlets); - for (index i = 1; i <= newInlets; ++i) + for (index i = newInlets; i >= 1; --i) mProxies.push_back( - proxy_new(this, static_cast(i + 1), &this->mProxyNumber)); + proxy_new(this, static_cast(i), &this->mProxyNumber)); } //new proxy inlets for any additional input buffers beyond the first @@ -1355,9 +1365,9 @@ class FluidMaxWrapper if (mClient.controlChannelsOut().count) { - index outputSize = mClient.controlChannelsOut().max > -1 - ? mClient.controlChannelsOut().max - : mListSize; + index outputSize = isControlOutFollowsIn + ? mListSize + : mClient.controlChannelsOut().max; if (outputSize) { @@ -1462,12 +1472,12 @@ class FluidMaxWrapper { void* x = object_alloc(getClass()); new (x) FluidMaxWrapper(sym, ac, av); - if (static_cast(attr_args_offset(static_cast(ac), av)) - isControlIn > + if (static_cast(attr_args_offset(static_cast(ac), av)) - isControlOutFollowsIn> ParamDescType::NumFixedParams + ParamDescType::NumPrimaryParams) { object_warn((t_object*) x, "Too many arguments. Got %d, expect at most %d", ac, - ParamDescType::NumFixedParams + ParamDescType::NumPrimaryParams + isControlIn); + ParamDescType::NumFixedParams + ParamDescType::NumPrimaryParams + isControlOutFollowsIn); } return x; @@ -1477,7 +1487,6 @@ class FluidMaxWrapper static void makeClass(const char* className) { - static constexpr bool AudioInput = isAudioIn; const ParamDescType& p = Client::getParameterDescriptors(); const auto& m = Client::getMessageDescriptors(); @@ -1488,13 +1497,16 @@ class FluidMaxWrapper if (isControlIn) { class_addmethod(getClass(), (method) handleList, "list", A_GIMME, 0); + } + + if (isControlOutFollowsIn) + { t_object* a = attr_offset_new("autosize", USESYM(atom_long), 0, nullptr, nullptr, calcoffset(FluidMaxWrapper, mAutosize)); class_addattr(getClass(), a); CLASS_ATTR_FILTER_CLIP(getClass(), "autosize", 0, 1); CLASS_ATTR_STYLE_LABEL(getClass(), "autosize", 0, "onoff", - "Set auto size for list output"); - + "Set auto resizing of list input and output"); } class_addmethod(getClass(), (method) doNotify, "notify", A_CANT, 0); @@ -1520,9 +1532,8 @@ class FluidMaxWrapper p.template iterateMutable(); p.template iterateFixed(); - //for non-audio classes, give us cold inlets for non-left - if(!AudioInput) + if (!AudioInput) class_addmethod(getClass(), (method)stdinletinfo, "inletinfo", A_CANT, 0); class_dumpout_wrap(getClass()); @@ -1555,72 +1566,48 @@ class FluidMaxWrapper void resizeListHandlers(index newSize) { + if (mListSize != newSize) + { + mListSize = newSize; index numIns = mClient.controlChannelsIn(); - mListSize = newSize; - if(mListSize) + mInputListData.resize(numIns, mListSize); + mInputListViews.clear(); + for (index i = 0; i < numIns; ++i) { - mInputListData.resize(numIns,mListSize); - mInputListViews.clear(); - for (index i = 0; i < numIns; ++i) - { - mInputListViews.emplace_back(mInputListData.row(i)); - } - - index outputSize = mClient.controlChannelsOut().size > -1 - ? mClient.controlChannelsOut().size - : mListSize; + mInputListViews.emplace_back(mInputListData.row(i)); + } - mOutputListData.resize(mClient.controlChannelsOut().count, outputSize); - mOutputListAtoms.reserve(outputSize); + if (isControlOutFollowsIn) + { + mOutputListData.resize(mClient.controlChannelsOut().count, mListSize); + mOutputListAtoms.reserve(mListSize); mOutputListViews.clear(); for (index i = 0; i < mClient.controlChannelsOut().count; ++i) { mOutputListViews.emplace_back(mOutputListData.row(i)); } } + } } - static void doList(FluidMaxWrapper* x, t_symbol*, long ac, t_atom* av) - { - -// if(!isr() && x->mAutosize && (ac != x->mListSize)) x->resizeListHandlers(ac); - x->mListHandler(x, ac, av); - } - - static void doListResize(FluidMaxWrapper* x, t_symbol*, long ac, t_atom*) + static void handleList(FluidMaxWrapper* x, t_symbol* /*s*/, long ac, t_atom* av) { - x->resizeListHandlers(ac); - } - - - static void handleList(FluidMaxWrapper* x, t_symbol* s, long ac, t_atom* av) - { - if(!x->mListSize && !x->mAutosize) - { - object_error((t_object*)x, "No list size argument nor autosize enabled: can't do anything"); - return; - } - - if(isr()) - { - if(x->mAutosize && ac != x->mListSize) - { - object_warn((t_object*)x, "input list size (%d) != object argument (%d) and autosize is enabled: this operation will be deferred",ac,x->mListSize); - defer(x, method(doListResize), s, static_cast(ac), av); - defer(x, (method) doList, s, static_cast(ac), av); - return; - } + if (!x->mListSize && !x->mAutosize) + { + object_error((t_object*)x, "No list size argument nor autosize enabled: can't do anything"); + return; + } - if(!x->mAutosize && ac != x->mListSize) - { - object_warn((t_object*)x, "bad input list size (%d), expect %d",ac,x->mListSize); - return; - } - } - else if(ac != x->mListSize) doListResize(x,s,ac,av); - - doList(x,s,ac,av); + if (!x->mAutosize && ac != x->mListSize) + { + object_warn((t_object*)x, "bad input list size (%d), expect %d",ac,x->mListSize); + return; + } + + if (x->mAutosize) + x->resizeListHandlers(ac); + x->mListHandler(x, ac, av); } static void doSharedClientRefer(FluidMaxWrapper* x, t_symbol* newName) @@ -1753,7 +1740,7 @@ class FluidMaxWrapper { long argCount{0}; - if(isControlIn) + if (isControlOutFollowsIn) { mListSize = atom_getlong(av); numArgs -= 1;