Merge branch 'dynamic-contexts' into attributes-contexts

This commit is contained in:
Alex Harker
2020-02-01 17:26:26 +00:00
7 changed files with 199 additions and 39 deletions
+2 -1
View File
@@ -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
{
+45 -2
View File
@@ -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();
}
+24 -21
View File
@@ -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;
+1 -1
View File
@@ -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;
+82 -2
View File
@@ -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
+25 -6
View File
@@ -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
+20 -6
View File
@@ -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