Merge branch 'dynamic-contexts' into attributes-contexts
This commit is contained in:
@@ -22,7 +22,8 @@
|
||||
|
||||
*/
|
||||
|
||||
class FrameLib_DSP : public FrameLib_Block
|
||||
class FrameLib_DSP
|
||||
: public FrameLib_Block
|
||||
, public FrameLib_MethodQueue<FrameLib_DSP>::Node
|
||||
, public FrameLib_ProcessingQueue::Node
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
// Query Connections for Individual Channels
|
||||
|
||||
unsigned long FrameLib_Multistream::getInputNumChans(unsigned long inIdx)
|
||||
unsigned long FrameLib_Multistream::getInputNumStreams(unsigned long inIdx)
|
||||
{
|
||||
MultistreamConnection connection = getConnection(inIdx);
|
||||
|
||||
@@ -22,7 +22,7 @@ FrameLib_Multistream::BlockConnection FrameLib_Multistream::getInputChan(unsigne
|
||||
return connection.mObject->mOutputs[connection.mIndex][chan];
|
||||
}
|
||||
|
||||
unsigned long FrameLib_Multistream::getOrderingConnectionNumChans(unsigned long idx)
|
||||
unsigned long FrameLib_Multistream::getOrderingConnectionNumStreams(unsigned long idx)
|
||||
{
|
||||
MultistreamConnection connection = getOrderingConnection(idx);
|
||||
|
||||
@@ -39,9 +39,52 @@ FrameLib_Multistream::BlockConnection FrameLib_Multistream::getOrderingConnectio
|
||||
return connection.mObject->mOutputs[connection.mIndex][chan];
|
||||
}
|
||||
|
||||
// Update connections
|
||||
|
||||
void FrameLib_Multistream::connectionUpdate(Queue *queue)
|
||||
{
|
||||
InputStack stack;
|
||||
|
||||
for (FrameLib_Multistream *object = this; object; object = stack.pop())
|
||||
object->inputCheck(stack);
|
||||
|
||||
if (mOutputChange)
|
||||
outputUpdate(queue);
|
||||
|
||||
mOutputChange = false;
|
||||
}
|
||||
|
||||
// Update the inputs of all output dependencies
|
||||
|
||||
void FrameLib_Multistream::outputUpdate(Queue *queue)
|
||||
{
|
||||
addOutputDependencies(queue);
|
||||
}
|
||||
|
||||
// Check all the inputs are valid
|
||||
|
||||
void FrameLib_Multistream::inputCheck(InputStack& stack)
|
||||
{
|
||||
auto checkInputs = [&](const MultistreamConnection& connection)
|
||||
{
|
||||
if (!connection.mObject || connection.mObject->mOwnsStreams)
|
||||
return false;
|
||||
|
||||
stack.push(this);
|
||||
stack.push(connection.mObject);
|
||||
return true;
|
||||
};
|
||||
|
||||
// Ensure that all inputs are valid for normal and ordering connections
|
||||
|
||||
while (mInCount < getNumIns())
|
||||
if (checkInputs(getConnection(mInCount++)))
|
||||
return;
|
||||
|
||||
while (mInCount < getNumIns() + getNumOrderingConnections())
|
||||
if (checkInputs(getOrderingConnection(mInCount++ - getNumIns())))
|
||||
return;
|
||||
|
||||
mInCount = 0;
|
||||
mOutputChange |= inputUpdate();
|
||||
}
|
||||
|
||||
@@ -26,11 +26,13 @@
|
||||
|
||||
*/
|
||||
|
||||
class FrameLib_Multistream : public FrameLib_Object<FrameLib_Multistream>
|
||||
class FrameLib_Multistream
|
||||
: public FrameLib_Object<FrameLib_Multistream>
|
||||
, public FrameLib_Stack<FrameLib_Multistream, FrameLib_Multistream>::Node
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
using InputStack = FrameLib_Stack<FrameLib_Multistream, FrameLib_Multistream>;
|
||||
using BlockConnection = FrameLib_Object<FrameLib_Block>::Connection;
|
||||
using MultistreamOutput = std::vector<BlockConnection>;
|
||||
using MultistreamConnection = FrameLib_Object::Connection;
|
||||
@@ -41,12 +43,12 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
FrameLib_Multistream(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, unsigned long nStreams, unsigned long nIns, unsigned long nOuts)
|
||||
: FrameLib_Object(type, context, proxy), mNumStreams(nStreams)
|
||||
FrameLib_Multistream(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, bool ownsStreams, unsigned long nStreams, unsigned long nIns, unsigned long nOuts)
|
||||
: FrameLib_Object(type, context, proxy), mNumStreams(nStreams), mInCount(0), mOwnsStreams(ownsStreams), mOutputChange(false)
|
||||
{ setIO(nIns, nOuts); }
|
||||
|
||||
FrameLib_Multistream(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, unsigned long nStreams)
|
||||
: FrameLib_Object(type, context, proxy), mNumStreams(nStreams) {}
|
||||
FrameLib_Multistream(ObjectType type, FrameLib_Context context, FrameLib_Proxy *proxy, bool ownsStreams, unsigned long nStreams)
|
||||
: FrameLib_Object(type, context, proxy), mNumStreams(nStreams), mInCount(0), mOwnsStreams(ownsStreams), mOutputChange(false) {}
|
||||
|
||||
// Destructor
|
||||
|
||||
@@ -75,25 +77,23 @@ protected:
|
||||
|
||||
// Query Connections for Individual Channels
|
||||
|
||||
unsigned long getInputNumChans(unsigned long inIdx);
|
||||
unsigned long getInputNumStreams(unsigned long inIdx);
|
||||
BlockConnection getInputChan(unsigned long inIdx, unsigned long chan);
|
||||
|
||||
unsigned long getOrderingConnectionNumChans(unsigned long idx);
|
||||
unsigned long getOrderingConnectionNumStreams(unsigned long idx);
|
||||
BlockConnection getOrderingConnectionChan(unsigned long idx, unsigned long chan);
|
||||
|
||||
private:
|
||||
|
||||
// Connection Methods (private)
|
||||
|
||||
void connectionUpdate(Queue *queue) final
|
||||
{
|
||||
if (inputUpdate())
|
||||
outputUpdate(queue);
|
||||
}
|
||||
void connectionUpdate(Queue *queue) final;
|
||||
|
||||
virtual bool inputUpdate() = 0;
|
||||
void outputUpdate(Queue *queue);
|
||||
|
||||
|
||||
void inputCheck(InputStack& stack);
|
||||
|
||||
protected:
|
||||
|
||||
// Outputs
|
||||
@@ -103,6 +103,9 @@ protected:
|
||||
private:
|
||||
|
||||
unsigned long mNumStreams;
|
||||
unsigned long mInCount;
|
||||
bool mOwnsStreams;
|
||||
bool mOutputChange;
|
||||
};
|
||||
|
||||
|
||||
@@ -128,7 +131,7 @@ public:
|
||||
const FrameLib_Parameters::Serial *getSerialised() override { return &mSerialisedParameters; }
|
||||
|
||||
FrameLib_Expand(FrameLib_Context context, const FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy, unsigned long nStreams)
|
||||
: FrameLib_Multistream(T::sType, context, proxy, nStreams), mSerialisedParameters(serialisedParameters ? serialisedParameters->size() : 0)
|
||||
: FrameLib_Multistream(T::sType, context, proxy, true, nStreams), mSerialisedParameters(serialisedParameters ? serialisedParameters->size() : 0)
|
||||
{
|
||||
// Make first block
|
||||
|
||||
@@ -285,8 +288,8 @@ private:
|
||||
unsigned long cChannels = static_cast<unsigned long>(mBlocks.size());
|
||||
|
||||
for (unsigned long i = 0; i < getNumIns(); i++)
|
||||
if (getInputNumChans(i) > nChannels)
|
||||
nChannels = getInputNumChans(i);
|
||||
if (getInputNumStreams(i) > nChannels)
|
||||
nChannels = getInputNumStreams(i);
|
||||
|
||||
nChannels = std::max(nChannels, getNumStreams());
|
||||
|
||||
@@ -329,10 +332,10 @@ private:
|
||||
|
||||
for (unsigned long i = 0; i < getNumIns(); i++)
|
||||
{
|
||||
if (getInputNumChans(i))
|
||||
if (getInputNumStreams(i))
|
||||
{
|
||||
for (unsigned long j = 0; j < nChannels; j++)
|
||||
mBlocks[j]->addConnection(getInputChan(i, j % getInputNumChans(i)), i);
|
||||
mBlocks[j]->addConnection(getInputChan(i, j % getInputNumStreams(i)), i);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -350,9 +353,9 @@ private:
|
||||
|
||||
for (unsigned long i = 0; i < getNumOrderingConnections(); i++)
|
||||
{
|
||||
if (getOrderingConnectionNumChans(i))
|
||||
if (getOrderingConnectionNumStreams(i))
|
||||
for (unsigned long j = 0; j < nChannels; j++)
|
||||
mBlocks[j]->addOrderingConnection(getOrderingConnectionChan(i, j % getOrderingConnectionNumChans(i)));
|
||||
mBlocks[j]->addOrderingConnection(getOrderingConnectionChan(i, j % getOrderingConnectionNumStreams(i)));
|
||||
}
|
||||
|
||||
return numChansChanged;
|
||||
|
||||
@@ -441,7 +441,7 @@ protected:
|
||||
|
||||
// String With Number Helper
|
||||
|
||||
static std::string numberedString(const char *str, unsigned long idx)
|
||||
static std::string numberedString(const char *str, unsigned long idx)
|
||||
{
|
||||
std::ostringstream outStr;
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ template <class T, class TopUser, class User, class ... OtherUsers>
|
||||
struct FrameLib_Node<T, TopUser, User, OtherUsers...>
|
||||
: FrameLib_Node<T, TopUser, User>, FrameLib_Node<T, TopUser, OtherUsers...> {};
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@class FrameLib_Queue
|
||||
@@ -71,7 +70,7 @@ struct FrameLib_Node<T, TopUser, User, OtherUsers...>
|
||||
|
||||
*/
|
||||
|
||||
template <class T, class TopUser, class...OtherUsers>
|
||||
template <class T, class TopUser = void, class...OtherUsers>
|
||||
class FrameLib_Queue
|
||||
{
|
||||
|
||||
@@ -238,6 +237,87 @@ protected:
|
||||
T *mFirst;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@class FrameLib_Stack
|
||||
|
||||
@ingroup Queues
|
||||
|
||||
@brief a general purpose stack for objects of a given type (which inherits from the inner Node type)
|
||||
|
||||
An item can only be in one position in a single stack at a time but can optionally be moved to the head if pushed onto the same stack twice
|
||||
|
||||
*/
|
||||
|
||||
template <class T, class TopUser = void, class...OtherUsers>
|
||||
class FrameLib_Stack
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
using Node = FrameLib_Node<T, TopUser, FrameLib_Stack, OtherUsers...>;
|
||||
|
||||
// Constructor
|
||||
|
||||
FrameLib_Stack() : mHead(nullptr), mSize(0) {}
|
||||
|
||||
// Non-copyable
|
||||
|
||||
FrameLib_Stack(const FrameLib_Stack&) = delete;
|
||||
FrameLib_Stack& operator=(const FrameLib_Stack&) = delete;
|
||||
|
||||
// Push an item to the tail
|
||||
|
||||
void push(T* item)
|
||||
{
|
||||
assert(item && "item is null");
|
||||
assert(!queued(item) && "item is already in a queue");
|
||||
|
||||
static_cast<Node *>(item)->mNext = mHead ? mHead : item;
|
||||
mHead = item;
|
||||
mSize++;
|
||||
}
|
||||
|
||||
// Pop an item from the head
|
||||
|
||||
T *pop()
|
||||
{
|
||||
if (empty())
|
||||
return nullptr;
|
||||
|
||||
T *item = mHead;
|
||||
mHead = --mSize ? static_cast<Node *>(item)->mNext : nullptr;
|
||||
static_cast<Node *>(item)->mNext = nullptr;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
T *peek() const
|
||||
{
|
||||
return mHead;
|
||||
}
|
||||
|
||||
// Get the size
|
||||
|
||||
unsigned int size() const { return mSize; }
|
||||
|
||||
// Query if the list is empty
|
||||
|
||||
bool empty() const { return !size(); }
|
||||
|
||||
protected:
|
||||
|
||||
// Determine if the item is already in the queue
|
||||
|
||||
bool queued(T* item) const
|
||||
{
|
||||
return static_cast<Node *>(item)->mNext;
|
||||
}
|
||||
|
||||
T *mHead;
|
||||
unsigned int mSize;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@class FrameLib_LockFreeStack
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
// Constructor
|
||||
|
||||
FrameLib_Pack::FrameLib_Pack(FrameLib_Context context, const FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy, unsigned long nStreams): FrameLib_Multistream(kProcessor, context, proxy, 1), mParameters(context, proxy, &sParamInfo)
|
||||
{
|
||||
FrameLib_Pack::FrameLib_Pack(FrameLib_Context context, const FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy, unsigned long nStreams): FrameLib_Multistream(kProcessor, context, proxy, false, 1), mParameters(context, proxy, &sParamInfo)
|
||||
{
|
||||
mParameters.addInt(0, "inputs", 2, 0 );
|
||||
mParameters.setInstantiation();
|
||||
mParameters.set(serialisedParameters);
|
||||
@@ -35,13 +35,32 @@ std::string FrameLib_Pack::outputInfo(unsigned long idx, bool verbose)
|
||||
|
||||
bool FrameLib_Pack::inputUpdate()
|
||||
{
|
||||
mOutputs[0].clear();
|
||||
unsigned long size = 0;
|
||||
bool change = false;
|
||||
|
||||
// Calculate output size and check for a change of size
|
||||
|
||||
for (unsigned long i = 0; i < getNumIns(); i++)
|
||||
for (unsigned long j = 0; j < getInputNumChans(i); j++)
|
||||
mOutputs[0].push_back(getInputChan(i, j));
|
||||
size += getInputNumStreams(i);
|
||||
|
||||
return true;
|
||||
if (size != mOutputs[0].size())
|
||||
{
|
||||
mOutputs[0].resize(size);
|
||||
change = true;
|
||||
}
|
||||
|
||||
// As we assign compare every connection in turn to check for changes
|
||||
|
||||
for (unsigned long i = 0, k = 0; i < getNumIns(); i++)
|
||||
{
|
||||
for (unsigned long j = 0; j < getInputNumStreams(i); j++, k++)
|
||||
{
|
||||
change |= getInputChan(i, j) != mOutputs[0][k];
|
||||
mOutputs[0][k] = getInputChan(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
// Parameter Info
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
// Constructor
|
||||
|
||||
FrameLib_Unpack::FrameLib_Unpack(FrameLib_Context context, const FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy, unsigned long nStreams) : FrameLib_Multistream(kProcessor, context, proxy, 1), mParameters(context, proxy, &sParamInfo)
|
||||
FrameLib_Unpack::FrameLib_Unpack(FrameLib_Context context, const FrameLib_Parameters::Serial *serialisedParameters, FrameLib_Proxy *proxy, unsigned long nStreams) : FrameLib_Multistream(kProcessor, context, proxy, false, 1), mParameters(context, proxy, &sParamInfo)
|
||||
{
|
||||
mParameters.addInt(kOutputs, "outputs", 2, 0);
|
||||
mParameters.setInstantiation();
|
||||
@@ -34,13 +34,27 @@ std::string FrameLib_Unpack::outputInfo(unsigned long idx, bool verbose)
|
||||
|
||||
bool FrameLib_Unpack::inputUpdate()
|
||||
{
|
||||
bool change = false;
|
||||
|
||||
for (unsigned long i = 0; i < getNumOuts(); i++)
|
||||
mOutputs[i].clear();
|
||||
{
|
||||
bool exists = i < getInputNumStreams(0);
|
||||
bool slotExists = mOutputs[i].size();
|
||||
|
||||
// Check for changes
|
||||
|
||||
change |= exists != slotExists;
|
||||
change |= exists && slotExists && getInputChan(0, i) != mOutputs[i][0];
|
||||
|
||||
// Store current value
|
||||
|
||||
mOutputs.clear();
|
||||
|
||||
if (exists)
|
||||
mOutputs[i].push_back(getInputChan(0, i));
|
||||
}
|
||||
|
||||
for (unsigned long i = 0; i < getInputNumChans(0) && i < getNumOuts(); i++)
|
||||
mOutputs[i].push_back(getInputChan(0, i));
|
||||
|
||||
return true;
|
||||
return change;
|
||||
}
|
||||
|
||||
// Parameter Info
|
||||
|
||||
Reference in New Issue
Block a user