|
|
|
@@ -39,12 +39,14 @@ const double Track::kTrackHeightInterval = 0.5;
|
|
|
|
|
|
|
|
|
|
const QString Track::kBlockInput = QStringLiteral("block_in");
|
|
|
|
|
const QString Track::kMutedInput = QStringLiteral("muted_in");
|
|
|
|
|
const QString Track::kArrayMapInput = QStringLiteral("arraymap_in");
|
|
|
|
|
|
|
|
|
|
Track::Track() :
|
|
|
|
|
track_type_(Track::kNone),
|
|
|
|
|
index_(-1),
|
|
|
|
|
locked_(false),
|
|
|
|
|
sequence_(nullptr)
|
|
|
|
|
sequence_(nullptr),
|
|
|
|
|
ignore_arraymap_(0)
|
|
|
|
|
{
|
|
|
|
|
AddInput(kBlockInput, NodeValue::kNone, InputFlags(kInputFlagArray | kInputFlagNotKeyframable | kInputFlagHidden));
|
|
|
|
|
|
|
|
|
@@ -54,6 +56,9 @@ Track::Track() :
|
|
|
|
|
|
|
|
|
|
AddInput(kMutedInput, NodeValue::kBoolean, false, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
|
|
|
|
|
|
|
|
|
AddInput(kArrayMapInput, NodeValue::kBinary, InputFlags(kInputFlagStatic | kInputFlagHidden));
|
|
|
|
|
IgnoreInvalidationsFrom(kArrayMapInput);
|
|
|
|
|
|
|
|
|
|
// Set default height
|
|
|
|
|
track_height_ = kTrackHeightDefault;
|
|
|
|
|
}
|
|
|
|
@@ -194,7 +199,7 @@ void Track::SetTrackHeight(const double &height)
|
|
|
|
|
emit TrackHeightChanged(track_height_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Track::InputConnectedEvent(const QString &input, int element, Node *output)
|
|
|
|
|
/*void Track::InputConnectedEvent(const QString &input, int element, Node *output)
|
|
|
|
|
{
|
|
|
|
|
if (input == kBlockInput) {
|
|
|
|
|
if (element == -1) {
|
|
|
|
@@ -321,7 +326,7 @@ void Track::InputDisconnectedEvent(const QString &input, int element, Node *outp
|
|
|
|
|
|
|
|
|
|
Node::InvalidateCache(invalidate_range, kBlockInput);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
void Track::InputValueChangedEvent(const QString &input, int element)
|
|
|
|
|
{
|
|
|
|
@@ -329,6 +334,34 @@ void Track::InputValueChangedEvent(const QString &input, int element)
|
|
|
|
|
|
|
|
|
|
if (input == kMutedInput) {
|
|
|
|
|
emit MutedChanged(IsMuted());
|
|
|
|
|
} else if (input == kArrayMapInput) {
|
|
|
|
|
if (ignore_arraymap_ > 0) {
|
|
|
|
|
qDebug() << "ignored our own array map update";
|
|
|
|
|
ignore_arraymap_--;
|
|
|
|
|
} else {
|
|
|
|
|
qDebug() << "received REAL array map update";
|
|
|
|
|
|
|
|
|
|
block_array_indexes_ = GetStandardValue(kArrayMapInput).value< QVector<int> >();
|
|
|
|
|
blocks_.reserve(block_array_indexes_.size());
|
|
|
|
|
Block *prev = nullptr;
|
|
|
|
|
for (int i = 0; i < block_array_indexes_.size(); i++) {
|
|
|
|
|
Block *b = static_cast<Block*>(GetConnectedOutput(kBlockInput, block_array_indexes_.at(i)));
|
|
|
|
|
|
|
|
|
|
Block::set_previous_next(prev, b);
|
|
|
|
|
|
|
|
|
|
if (b) {
|
|
|
|
|
blocks_.append(b);
|
|
|
|
|
prev = b;
|
|
|
|
|
} else {
|
|
|
|
|
block_array_indexes_.removeAt(i);
|
|
|
|
|
i--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (prev) {
|
|
|
|
|
prev->set_next(nullptr);
|
|
|
|
|
}
|
|
|
|
|
UpdateInOutFrom(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -488,39 +521,48 @@ void Track::InsertBlockAfter(Block *block, Block *before)
|
|
|
|
|
|
|
|
|
|
Q_ASSERT(before_index >= 0);
|
|
|
|
|
|
|
|
|
|
if (before_index == blocks_.size() - 1) {
|
|
|
|
|
AppendBlock(block);
|
|
|
|
|
} else {
|
|
|
|
|
InsertBlockAtIndex(block, before_index + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Track::PrependBlock(Block *block)
|
|
|
|
|
{
|
|
|
|
|
InputArrayPrepend(kBlockInput);
|
|
|
|
|
Node::ConnectEdge(block, NodeInput(this, kBlockInput, 0));
|
|
|
|
|
|
|
|
|
|
// Everything has shifted at this point
|
|
|
|
|
Node::InvalidateCache(TimeRange(0, track_length()), kBlockInput);
|
|
|
|
|
InsertBlockAtIndex(block, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Track::InsertBlockAtIndex(Block *block, int index)
|
|
|
|
|
{
|
|
|
|
|
int insert_index = GetArrayIndexFromCacheIndex(index);
|
|
|
|
|
InputArrayInsert(kBlockInput, insert_index);
|
|
|
|
|
Node::ConnectEdge(block, NodeInput(this, kBlockInput, insert_index));
|
|
|
|
|
// Set track
|
|
|
|
|
Q_ASSERT(block->track() == nullptr);
|
|
|
|
|
block->set_track(this);
|
|
|
|
|
|
|
|
|
|
// Update array
|
|
|
|
|
int array_index = ConnectBlock(block);
|
|
|
|
|
blocks_.insert(index, block);
|
|
|
|
|
block_array_indexes_.insert(index, array_index);
|
|
|
|
|
|
|
|
|
|
// Handle previous/next
|
|
|
|
|
Block *previous = (index > 0) ? blocks_.at(index - 1) : nullptr;
|
|
|
|
|
Block *next = (index < blocks_.size()-1) ? blocks_.at(index + 1) : nullptr ;
|
|
|
|
|
Block::set_previous_next(previous, block);
|
|
|
|
|
Block::set_previous_next(block, next);
|
|
|
|
|
|
|
|
|
|
// Update in/out
|
|
|
|
|
UpdateInOutFrom(index);
|
|
|
|
|
|
|
|
|
|
connect(block, &Block::LengthChanged, this, &Track::BlockLengthChanged);
|
|
|
|
|
|
|
|
|
|
Node::InvalidateCache(TimeRange(block->in(), track_length()), kBlockInput);
|
|
|
|
|
|
|
|
|
|
emit BlockAdded(block);
|
|
|
|
|
|
|
|
|
|
ignore_arraymap_++;
|
|
|
|
|
SetStandardValue(kArrayMapInput, QVariant::fromValue(block_array_indexes_));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Track::AppendBlock(Block *block)
|
|
|
|
|
{
|
|
|
|
|
InputArrayAppend(kBlockInput);
|
|
|
|
|
Node::ConnectEdge(block, NodeInput(this, kBlockInput, InputArraySize(kBlockInput) - 1));
|
|
|
|
|
|
|
|
|
|
// Invalidate area that block was added to
|
|
|
|
|
Node::InvalidateCache(TimeRange(block->in(), block->out()), kBlockInput);
|
|
|
|
|
InsertBlockAtIndex(block, blocks_.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Track::RippleRemoveBlock(Block *block)
|
|
|
|
@@ -528,24 +570,87 @@ void Track::RippleRemoveBlock(Block *block)
|
|
|
|
|
rational remove_in = block->in();
|
|
|
|
|
rational remove_out = block->out();
|
|
|
|
|
|
|
|
|
|
InputArrayRemove(kBlockInput, GetArrayIndexFromBlock(block));
|
|
|
|
|
emit BlockRemoved(block);
|
|
|
|
|
|
|
|
|
|
// Set track
|
|
|
|
|
Q_ASSERT(block->track() == this);
|
|
|
|
|
block->set_track(nullptr);
|
|
|
|
|
|
|
|
|
|
// Update array
|
|
|
|
|
int index = blocks_.indexOf(block);
|
|
|
|
|
Q_ASSERT(index != -1);
|
|
|
|
|
|
|
|
|
|
int array_index = block_array_indexes_.at(index);
|
|
|
|
|
|
|
|
|
|
blocks_.removeAt(index);
|
|
|
|
|
block_array_indexes_.removeAt(index);
|
|
|
|
|
|
|
|
|
|
Node::DisconnectEdge(block, NodeInput(this, kBlockInput, array_index));
|
|
|
|
|
empty_inputs_.push_back(array_index);
|
|
|
|
|
disconnect(block, &Block::LengthChanged, this, &Track::BlockLengthChanged);
|
|
|
|
|
|
|
|
|
|
// Handle previous/next
|
|
|
|
|
Block *previous = (index > 0) ? blocks_.at(index - 1) : nullptr;
|
|
|
|
|
Block *next = (index < blocks_.size()) ? blocks_.at(index) : nullptr;
|
|
|
|
|
Block::set_previous_next(previous, next);
|
|
|
|
|
block->set_previous(nullptr);
|
|
|
|
|
block->set_next(nullptr);
|
|
|
|
|
|
|
|
|
|
// Update in/outs
|
|
|
|
|
UpdateInOutFrom(index);
|
|
|
|
|
|
|
|
|
|
Node::InvalidateCache(TimeRange(remove_in, qMax(track_length(), remove_out)), kBlockInput);
|
|
|
|
|
|
|
|
|
|
ignore_arraymap_++;
|
|
|
|
|
SetStandardValue(kArrayMapInput, QVariant::fromValue(block_array_indexes_));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Track::ReplaceBlock(Block *old, Block *replace)
|
|
|
|
|
{
|
|
|
|
|
int index_of_old_block = GetArrayIndexFromBlock(old);
|
|
|
|
|
emit BlockRemoved(old);
|
|
|
|
|
|
|
|
|
|
// Set track
|
|
|
|
|
Q_ASSERT(old->track() == this);
|
|
|
|
|
old->set_track(nullptr);
|
|
|
|
|
|
|
|
|
|
Q_ASSERT(replace->track() == nullptr);
|
|
|
|
|
replace->set_track(this);
|
|
|
|
|
|
|
|
|
|
// Update array
|
|
|
|
|
int cache_index = blocks_.indexOf(old);
|
|
|
|
|
int index_of_old_block = GetArrayIndexFromCacheIndex(cache_index);
|
|
|
|
|
|
|
|
|
|
DisconnectEdge(old, NodeInput(this, kBlockInput, index_of_old_block));
|
|
|
|
|
|
|
|
|
|
ConnectEdge(replace, NodeInput(this, kBlockInput, index_of_old_block));
|
|
|
|
|
blocks_.replace(cache_index, replace);
|
|
|
|
|
disconnect(old, &Block::LengthChanged, this, &Track::BlockLengthChanged);
|
|
|
|
|
connect(replace, &Block::LengthChanged, this, &Track::BlockLengthChanged);
|
|
|
|
|
|
|
|
|
|
// Handle previous/next
|
|
|
|
|
replace->set_previous(old->previous());
|
|
|
|
|
replace->set_next(old->next());
|
|
|
|
|
old->set_previous(nullptr);
|
|
|
|
|
old->set_next(nullptr);
|
|
|
|
|
if (replace->previous()) {
|
|
|
|
|
replace->previous()->set_next(replace);
|
|
|
|
|
}
|
|
|
|
|
if (replace->next()) {
|
|
|
|
|
replace->next()->set_previous(replace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (old->length() == replace->length()) {
|
|
|
|
|
Node::InvalidateCache(TimeRange(replace->in(), replace->out()), kBlockInput);
|
|
|
|
|
} else {
|
|
|
|
|
// Update in/outs
|
|
|
|
|
UpdateInOutFrom(cache_index);
|
|
|
|
|
|
|
|
|
|
Node::InvalidateCache(TimeRange(replace->in(), track_length()), kBlockInput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
emit BlockAdded(replace);
|
|
|
|
|
|
|
|
|
|
ignore_arraymap_++;
|
|
|
|
|
SetStandardValue(kArrayMapInput, QVariant::fromValue(block_array_indexes_));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rational Track::track_length() const
|
|
|
|
@@ -734,6 +839,23 @@ void Track::ProcessAudioTrack(const NodeValueRow &value, const NodeGlobals &glob
|
|
|
|
|
table->Push(NodeValue::kSamples, QVariant::fromValue(block_range_buffer), this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Track::ConnectBlock(Block *b)
|
|
|
|
|
{
|
|
|
|
|
if (!empty_inputs_.empty()) {
|
|
|
|
|
int index = empty_inputs_.front();
|
|
|
|
|
empty_inputs_.pop_front();
|
|
|
|
|
|
|
|
|
|
Node::ConnectEdge(b, NodeInput(this, kBlockInput, index));
|
|
|
|
|
|
|
|
|
|
return index;
|
|
|
|
|
} else {
|
|
|
|
|
int old_sz = InputArraySize(kBlockInput);
|
|
|
|
|
InputArrayAppend(kBlockInput);
|
|
|
|
|
Node::ConnectEdge(b, NodeInput(this, kBlockInput, old_sz));
|
|
|
|
|
return old_sz;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Track::BlockLengthChanged()
|
|
|
|
|
{
|
|
|
|
|
// Assumes sender is a Block
|
|
|
|
|