diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 9a88b4f36..4bc07aba4 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -32,31 +32,31 @@ Block::Block() : next_(nullptr) { name_input_ = new NodeInput("name_in", NodeParam::kString); - name_input_->SetConnectable(false); + name_input_->set_connectable(false); name_input_->set_is_keyframable(false); AddInput(name_input_); length_input_ = new NodeInput("length_in", NodeParam::kRational); - length_input_->SetConnectable(false); + length_input_->set_connectable(false); length_input_->set_is_keyframable(false); AddInput(length_input_); disconnect(length_input_, &NodeInput::ValueChanged, this, &Block::InputChanged); connect(length_input_, &NodeInput::ValueChanged, this, &Block::LengthInputChanged); media_in_input_ = new NodeInput("media_in_in", NodeParam::kRational); - media_in_input_->SetConnectable(false); + media_in_input_->set_connectable(false); media_in_input_->set_is_keyframable(false); AddInput(media_in_input_); enabled_input_ = new NodeInput("enabled_in", NodeParam::kBoolean); - enabled_input_->SetConnectable(false); + enabled_input_->set_connectable(false); enabled_input_->set_is_keyframable(false); enabled_input_->set_standard_value(true); AddInput(enabled_input_); speed_input_ = new NodeInput("speed_in", NodeParam::kRational); speed_input_->set_standard_value(QVariant::fromValue(rational(1))); - speed_input_->SetConnectable(false); + speed_input_->set_connectable(false); speed_input_->set_is_keyframable(false); AddInput(speed_input_); diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index 851f8b9f8..5143d226c 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -113,7 +113,7 @@ void ClipBlock::Retranslate() void ClipBlock::Hash(QCryptographicHash &hash, const rational &time) const { - if (texture_input_->IsConnected()) { + if (texture_input_->is_connected()) { rational t = InputTimeAdjustment(texture_input_, TimeRange(time, time)).in(); texture_input_->get_connected_node()->Hash(hash, t); diff --git a/app/node/block/transition/transition.cpp b/app/node/block/transition/transition.cpp index e0d66e69e..3f820fd47 100644 --- a/app/node/block/transition/transition.cpp +++ b/app/node/block/transition/transition.cpp @@ -139,11 +139,11 @@ void TransitionBlock::Hash(QCryptographicHash &hash, const rational &time) const hash.addData(reinterpret_cast(&in_prog), sizeof(double)); hash.addData(reinterpret_cast(&out_prog), sizeof(double)); - if (out_block_input_->IsConnected()) { + if (out_block_input_->is_connected()) { out_block_input_->get_connected_node()->Hash(hash, time); } - if (in_block_input_->IsConnected()) { + if (in_block_input_->is_connected()) { in_block_input_->get_connected_node()->Hash(hash, time); } } diff --git a/app/node/generator/matrix/matrix.cpp b/app/node/generator/matrix/matrix.cpp index 2c27519fe..5e7116df3 100644 --- a/app/node/generator/matrix/matrix.cpp +++ b/app/node/generator/matrix/matrix.cpp @@ -44,7 +44,7 @@ MatrixGenerator::MatrixGenerator() uniform_scale_input_ = new NodeInput("uniform_scale_in", NodeParam::kBoolean, true); uniform_scale_input_->set_is_keyframable(false); - uniform_scale_input_->SetConnectable(false); + uniform_scale_input_->set_connectable(false); connect(uniform_scale_input_, &NodeInput::ValueChanged, this, &MatrixGenerator::UniformScaleChanged); AddInput(uniform_scale_input_); @@ -96,7 +96,7 @@ NodeValueTable MatrixGenerator::Value(NodeValueDatabase &value) const // Push matrix output QMatrix4x4 mat = GenerateMatrix(value); NodeValueTable output = value.Merge(); - output.Push(NodeParam::kMatrix, mat); + output.Push(NodeParam::kMatrix, mat, this); return output; } diff --git a/app/node/input.cpp b/app/node/input.cpp index db1bbb5c9..287d471ac 100644 --- a/app/node/input.cpp +++ b/app/node/input.cpp @@ -366,7 +366,7 @@ QVariant NodeInput::StringToValue(const DataType& data_type, const QString &stri void NodeInput::GetDependencies(QList &list, bool traverse, bool exclusive_only) const { - if (IsConnected() + if (is_connected() && (get_connected_output()->edges().size() == 1 || !exclusive_only)) { Node* connected = get_connected_node(); diff --git a/app/node/input/media/media.cpp b/app/node/input/media/media.cpp index b3a3697f0..839cb3d29 100644 --- a/app/node/input/media/media.cpp +++ b/app/node/input/media/media.cpp @@ -29,7 +29,7 @@ MediaInput::MediaInput() : connected_footage_(nullptr) { footage_input_ = new NodeInput("footage_in", NodeInput::kFootage); - footage_input_->SetConnectable(false); + footage_input_->set_connectable(false); footage_input_->set_is_keyframable(false); connect(footage_input_, &NodeInput::ValueChanged, this, &MediaInput::FootageChanged); AddInput(footage_input_); @@ -63,7 +63,7 @@ NodeValueTable MediaInput::Value(NodeValueDatabase &value) const rational media_duration = Timecode::timestamp_to_time(connected_footage_->duration(), connected_footage_->timebase()); - table.Push(NodeInput::kRational, QVariant::fromValue(media_duration), "length"); + table.Push(NodeInput::kRational, QVariant::fromValue(media_duration), this, "length"); } // Push buffer to the top of the stack diff --git a/app/node/input/time/timeinput.cpp b/app/node/input/time/timeinput.cpp index fee052c3c..d4df5b32b 100644 --- a/app/node/input/time/timeinput.cpp +++ b/app/node/input/time/timeinput.cpp @@ -57,6 +57,7 @@ NodeValueTable TimeInput::Value(NodeValueDatabase &value) const table.Push(NodeParam::kFloat, value[QStringLiteral("global")].Get(NodeParam::kFloat, QStringLiteral("time_in")), + this, QStringLiteral("time")); return table; diff --git a/app/node/inputarray.cpp b/app/node/inputarray.cpp index 1c288d66d..8ca54f435 100644 --- a/app/node/inputarray.cpp +++ b/app/node/inputarray.cpp @@ -126,12 +126,12 @@ void NodeInputArray::InsertAt(int index) NodeInput* this_param = sub_params_.at(i); NodeInput* prev_param = sub_params_.at(i-1); - if (this_param->IsConnected()) { + if (this_param->is_connected()) { // Disconnect whatever is at this parameter (presumably its connection has already been copied so we can just remove it) NodeParam::DisconnectEdge(this_param->edges().first()); } - if (prev_param->IsConnected()) { + if (prev_param->is_connected()) { // Get edge here (only one since it's an input) NodeEdgePtr edge = prev_param->edges().first(); @@ -161,14 +161,14 @@ void NodeInputArray::RemoveAt(int index) for (int i=index;iIsConnected()) { + if (this_param->is_connected()) { // Disconnect current edge NodeParam::DisconnectEdge(this_param->edges().first()); } if (i < sub_params_.size() - 1) { NodeInput* next_param = sub_params_.at(i + 1); - if (next_param->IsConnected()) { + if (next_param->is_connected()) { // Get edge from next param NodeEdgePtr edge = next_param->edges().first(); diff --git a/app/node/math/math/math.cpp b/app/node/math/math/math.cpp index b7fc0a56d..4839db828 100644 --- a/app/node/math/math/math.cpp +++ b/app/node/math/math/math.cpp @@ -31,7 +31,7 @@ OLIVE_NAMESPACE_ENTER MathNode::MathNode() { method_in_ = new NodeInput(QStringLiteral("method_in"), NodeParam::kCombo); - method_in_->SetConnectable(false); + method_in_->set_connectable(false); method_in_->set_is_keyframable(false); AddInput(method_in_); @@ -244,10 +244,12 @@ NodeValueTable MathNode::Value(NodeValueDatabase &value) const if (val_a.type() == NodeParam::kRational && val_b.type() == NodeParam::kRational && GetOperation() != kOpPower) { // Preserve rationals output.Push(NodeParam::kRational, - QVariant::fromValue(PerformAddSubMultDiv(val_a.data().value(), val_b.data().value()))); + QVariant::fromValue(PerformAddSubMultDiv(val_a.data().value(), val_b.data().value())), + this); } else { output.Push(NodeParam::kFloat, - PerformAll(RetrieveNumber(val_a), RetrieveNumber(val_b))); + PerformAll(RetrieveNumber(val_a), RetrieveNumber(val_b)), + this); } break; } @@ -288,7 +290,7 @@ NodeValueTable MathNode::Value(NodeValueDatabase &value) const { QMatrix4x4 mat_a = val_a.data().value(); QMatrix4x4 mat_b = val_b.data().value(); - output.Push(NodeParam::kMatrix, PerformAddSubMult(mat_a, mat_b)); + output.Push(NodeParam::kMatrix, PerformAddSubMult(mat_a, mat_b), this); break; } @@ -298,7 +300,7 @@ NodeValueTable MathNode::Value(NodeValueDatabase &value) const Color col_b = val_b.data().value(); // Only add and subtract are valid operations - output.Push(NodeParam::kColor, QVariant::fromValue(PerformAddSub(col_a, col_b))); + output.Push(NodeParam::kColor, QVariant::fromValue(PerformAddSub(col_a, col_b)), this); break; } @@ -309,7 +311,7 @@ NodeValueTable MathNode::Value(NodeValueDatabase &value) const float num = (val_a.type() == NodeParam::kColor) ? val_b.data().toFloat() : val_a.data().toFloat(); // Only multiply and divide are valid operations - output.Push(NodeParam::kColor, QVariant::fromValue(PerformMult(col, num))); + output.Push(NodeParam::kColor, QVariant::fromValue(PerformMult(col, num)), this); break; } @@ -341,7 +343,7 @@ NodeValueTable MathNode::Value(NodeValueDatabase &value) const } } - output.Push(NodeParam::kSamples, QVariant::fromValue(mixed_samples)); + output.Push(NodeParam::kSamples, QVariant::fromValue(mixed_samples), this); break; } @@ -443,17 +445,17 @@ QVector4D MathNode::RetrieveVector(const NodeValue &val) } } -void MathNode::PushVector(NodeValueTable *output, NodeParam::DataType type, const QVector4D &vec) +void MathNode::PushVector(NodeValueTable *output, NodeParam::DataType type, const QVector4D &vec) const { switch (type) { case NodeParam::kVec2: - output->Push(type, QVector2D(vec)); + output->Push(type, QVector2D(vec), this); break; case NodeParam::kVec3: - output->Push(type, QVector3D(vec)); + output->Push(type, QVector3D(vec), this); break; case NodeParam::kVec4: - output->Push(type, vec); + output->Push(type, vec, this); break; default: break; diff --git a/app/node/math/math/math.h b/app/node/math/math/math.h index 9b32fa3f7..b7fd245d0 100644 --- a/app/node/math/math/math.h +++ b/app/node/math/math/math.h @@ -134,7 +134,7 @@ private: static float RetrieveNumber(const NodeValue& val); - static void PushVector(NodeValueTable* output, NodeParam::DataType type, const QVector4D& vec); + void PushVector(NodeValueTable* output, NodeParam::DataType type, const QVector4D& vec) const; NodeInput* method_in_; diff --git a/app/node/math/merge/merge.cpp b/app/node/math/merge/merge.cpp index e5c039a6e..63e195b80 100644 --- a/app/node/math/merge/merge.cpp +++ b/app/node/math/merge/merge.cpp @@ -84,11 +84,11 @@ NodeInput *MergeNode::blend_in() const void MergeNode::Hash(QCryptographicHash &hash, const rational &time) const { - if (base_in_->IsConnected()) { + if (base_in_->is_connected()) { base_in_->get_connected_node()->Hash(hash, time); } - if (blend_in_->IsConnected()) { + if (blend_in_->is_connected()) { blend_in_->get_connected_node()->Hash(hash, time); } } diff --git a/app/node/math/trigonometry/trigonometry.cpp b/app/node/math/trigonometry/trigonometry.cpp index 9352fded8..c2f0d03ff 100644 --- a/app/node/math/trigonometry/trigonometry.cpp +++ b/app/node/math/trigonometry/trigonometry.cpp @@ -25,7 +25,7 @@ OLIVE_NAMESPACE_ENTER TrigonometryNode::TrigonometryNode() { method_in_ = new NodeInput(QStringLiteral("method_in"), NodeParam::kCombo); - method_in_->SetConnectable(false); + method_in_->set_connectable(false); method_in_->set_is_keyframable(false); AddInput(method_in_); @@ -113,7 +113,7 @@ NodeValueTable TrigonometryNode::Value(NodeValueDatabase &value) const break; } - table.Push(NodeParam::kFloat, x); + table.Push(NodeParam::kFloat, x, this); return table; } diff --git a/app/node/node.cpp b/app/node/node.cpp index 8c86ca315..9a0b73dff 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -321,7 +321,7 @@ void Node::Hash(QCryptographicHash &hash, const rational& time) const // For a single frame, we only care about one of the times rational input_time = InputTimeAdjustment(input, TimeRange(time, time)).in(); - if (input->IsConnected()) { + if (input->is_connected()) { // Traverse down this edge input->get_connected_node()->Hash(hash, input_time); } else { @@ -689,7 +689,7 @@ QList Node::TransformTimeTo(const TimeRange &time, Node *target, Node // If this input is connected, traverse it to see if we stumble across the specified `node` foreach (NodeInput* input, inputs) { - if (input->IsConnected()) { + if (input->is_connected()) { TimeRange input_adjustment = InputTimeAdjustment(input, time); Node* connected = input->get_connected_node(); @@ -710,7 +710,7 @@ QList Node::TransformTimeTo(const TimeRange &time, Node *target, Node // If this input is connected, traverse it to see if we stumble across the specified `node` foreach (NodeOutput* output, outputs) { - if (output->IsConnected()) { + if (output->is_connected()) { foreach (NodeEdgePtr edge, output->edges()) { Node* input_node = edge->input()->parentNode(); @@ -790,7 +790,7 @@ bool Node::HasParamOfType(NodeParam::Type type, bool must_be_connected) const { foreach (NodeParam* p, params_) { if (p->type() == type - && (p->IsConnected() || !must_be_connected)) { + && (p->is_connected() || !must_be_connected)) { return true; } } diff --git a/app/node/output/track/tracklist.cpp b/app/node/output/track/tracklist.cpp index 1bf9b4246..67a19c91b 100644 --- a/app/node/output/track/tracklist.cpp +++ b/app/node/output/track/tracklist.cpp @@ -99,7 +99,7 @@ TrackOutput* TrackList::AddTrack() } } - if (last_track && last_track->output()->IsConnected()) { + if (last_track && last_track->output()->is_connected()) { foreach (NodeEdgePtr edge, last_track->output()->edges()) { if (!track_input_->ContainsSubParameter(edge->input())) { switch (type_) { diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index 0007dd760..8078ade32 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -181,14 +181,14 @@ void ViewerOutput::VerifyLength() rational video_length; - if (texture_input_->IsConnected()) { + if (texture_input_->is_connected()) { NodeValueTable t = traverser.GenerateTable(texture_input_->get_connected_node(), 0, 0); video_length = t.Get(NodeParam::kNumber, "length").value(); } rational audio_length; - if (samples_input_->IsConnected()) { + if (samples_input_->is_connected()) { NodeValueTable t = traverser.GenerateTable(samples_input_->get_connected_node(), 0, 0); audio_length = t.Get(NodeParam::kNumber, "length").value(); } diff --git a/app/node/param.cpp b/app/node/param.cpp index b8f25249c..3cf7a39cb 100644 --- a/app/node/param.cpp +++ b/app/node/param.cpp @@ -88,17 +88,17 @@ int NodeParam::index() return parentNode()->IndexOfParameter(this); } -bool NodeParam::IsConnected() const +bool NodeParam::is_connected() const { return !edges_.isEmpty(); } -bool NodeParam::IsConnectable() const +bool NodeParam::is_connectable() const { return connectable_; } -void NodeParam::SetConnectable(bool connectable) +void NodeParam::set_connectable(bool connectable) { connectable_ = connectable; } @@ -117,7 +117,7 @@ void NodeParam::DisconnectAll() NodeEdgePtr NodeParam::ConnectEdge(NodeOutput *output, NodeInput *input) { - if (!input->IsConnectable()) { + if (!input->is_connectable()) { return nullptr; } diff --git a/app/node/param.h b/app/node/param.h index 167da6228..457667770 100644 --- a/app/node/param.h +++ b/app/node/param.h @@ -277,10 +277,10 @@ public: /** * @brief Returns whether anything is connected to this parameter or not */ - bool IsConnected() const; + bool is_connected() const; - bool IsConnectable() const; - void SetConnectable(bool connectable); + bool is_connectable() const; + void set_connectable(bool connectable); /** * @brief Return a list of edges (aka connections to other nodes) diff --git a/app/node/traverser.cpp b/app/node/traverser.cpp index ae10271cf..bd182001c 100644 --- a/app/node/traverser.cpp +++ b/app/node/traverser.cpp @@ -40,24 +40,13 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const TimeRa NodeValueTable table = ProcessInput(input, input_time); - // Exception for Footage types where we actually retrieve some Footage data from a decoder - if (input->data_type() == NodeParam::kFootage) { - StreamPtr stream = ResolveStreamFromInput(input); - - if (stream) { - - FootageProcessingEvent(stream, input_time, &table); - - } - } - database.Insert(input, table); } // Insert global variables NodeValueTable global; - global.Push(NodeParam::kFloat, range.in().toDouble(), QStringLiteral("time_in")); - global.Push(NodeParam::kFloat, range.out().toDouble(), QStringLiteral("time_out")); + global.Push(NodeParam::kFloat, range.in().toDouble(), nullptr, QStringLiteral("time_in")); + global.Push(NodeParam::kFloat, range.out().toDouble(), nullptr, QStringLiteral("time_out")); database.Insert(QStringLiteral("global"), global); return database; @@ -65,7 +54,7 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const TimeRa NodeValueTable NodeTraverser::ProcessInput(NodeInput* input, const TimeRange& range) { - if (input->IsConnected()) { + if (input->is_connected()) { // Value will equal something from the connected node, follow it return GenerateTable(input->get_connected_node(), range); } else if (!input->IsArray()) { @@ -73,7 +62,7 @@ NodeValueTable NodeTraverser::ProcessInput(NodeInput* input, const TimeRange& ra QVariant input_value = input->get_value_at_time(range.in()); NodeValueTable table; - table.Push(input->data_type(), input_value); + table.Push(input->data_type(), input_value, input->parentNode()); return table; } diff --git a/app/node/traverser.h b/app/node/traverser.h index 9b0512e3c..1ee3dd31f 100644 --- a/app/node/traverser.h +++ b/app/node/traverser.h @@ -39,21 +39,18 @@ public: NodeValueDatabase GenerateDatabase(const Node *node, const TimeRange &range); + static StreamPtr ResolveStreamFromInput(NodeInput* input); + protected: NodeValueTable ProcessInput(NodeInput *input, const TimeRange &range); virtual NodeValueTable GenerateBlockTable(const TrackOutput *track, const TimeRange& range); - virtual void FootageProcessingEvent(StreamPtr, const TimeRange&, NodeValueTable*) {} - virtual void ProcessNodeEvent(const Node*, const TimeRange&, NodeValueDatabase&, NodeValueTable&) {} -private: - static StreamPtr ResolveStreamFromInput(NodeInput* input); - }; OLIVE_NAMESPACE_EXIT diff --git a/app/node/value.cpp b/app/node/value.cpp index 7c0d92d90..fee1a1218 100644 --- a/app/node/value.cpp +++ b/app/node/value.cpp @@ -57,9 +57,16 @@ NodeValueTable NodeValueDatabase::Merge() const return NodeValueTable::Merge(tables_.values()); } -NodeValue::NodeValue(const NodeParam::DataType &type, const QVariant &data, const QString &tag) : +NodeValue::NodeValue() : + type_(NodeParam::kNone), + from_(nullptr) +{ +} + +NodeValue::NodeValue(const NodeParam::DataType &type, const QVariant &data, const Node *from, const QString &tag) : type_(type), data_(data), + from_(from), tag_(tag) { } @@ -97,7 +104,7 @@ NodeValue NodeValueTable::GetWithMeta(const NodeParam::DataType &type, const QSt return values_.at(value_index); } - return NodeValue(NodeParam::kNone, QVariant()); + return NodeValue(); } QVariant NodeValueTable::Take(const NodeParam::DataType &type, const QString &tag) @@ -113,7 +120,7 @@ NodeValue NodeValueTable::TakeWithMeta(const NodeParam::DataType &type, const QS return values_.takeAt(value_index); } - return NodeValue(NodeParam::kNone, QVariant()); + return NodeValue(); } void NodeValueTable::Push(const NodeValue &value) @@ -121,9 +128,9 @@ void NodeValueTable::Push(const NodeValue &value) values_.append(value); } -void NodeValueTable::Push(const NodeParam::DataType &type, const QVariant &data, const QString &tag) +void NodeValueTable::Push(const NodeParam::DataType &type, const QVariant &data, const Node* from, const QString &tag) { - Push(NodeValue(type, data, tag)); + Push(NodeValue(type, data, from, tag)); } void NodeValueTable::Prepend(const NodeValue &value) @@ -131,9 +138,9 @@ void NodeValueTable::Prepend(const NodeValue &value) values_.prepend(value); } -void NodeValueTable::Prepend(const NodeParam::DataType &type, const QVariant &data, const QString &tag) +void NodeValueTable::Prepend(const NodeParam::DataType &type, const QVariant &data, const Node* from, const QString &tag) { - Prepend(NodeValue(type, data, tag)); + Prepend(NodeValue(type, data, from, tag)); } const NodeValue &NodeValueTable::At(int index) const diff --git a/app/node/value.h b/app/node/value.h index 456ba797f..77b1212c6 100644 --- a/app/node/value.h +++ b/app/node/value.h @@ -30,8 +30,8 @@ OLIVE_NAMESPACE_ENTER class NodeValue { public: - NodeValue() = default; - NodeValue(const NodeParam::DataType& type, const QVariant& data, const QString& tag = QString()); + NodeValue(); + NodeValue(const NodeParam::DataType& type, const QVariant& data, const Node* from, const QString& tag = QString()); const NodeParam::DataType& type() const; const QVariant& data() const; @@ -42,6 +42,7 @@ public: private: NodeParam::DataType type_; QVariant data_; + const Node* from_; QString tag_; }; @@ -56,9 +57,9 @@ public: QVariant Take(const NodeParam::DataType& type, const QString& tag = QString()); NodeValue TakeWithMeta(const NodeParam::DataType& type, const QString& tag = QString()); void Push(const NodeValue& value); - void Push(const NodeParam::DataType& type, const QVariant& data, const QString& tag = QString()); + void Push(const NodeParam::DataType& type, const QVariant& data, const Node *from, const QString& tag = QString()); void Prepend(const NodeValue& value); - void Prepend(const NodeParam::DataType& type, const QVariant& data, const QString& tag = QString()); + void Prepend(const NodeParam::DataType& type, const QVariant& data, const Node *from, const QString& tag = QString()); const NodeValue& At(int index) const; NodeValue TakeAt(int index); int Count() const; diff --git a/app/render/backend/opengl/openglproxy.cpp b/app/render/backend/opengl/openglproxy.cpp index 8528244d1..8fe89dfe6 100644 --- a/app/render/backend/opengl/openglproxy.cpp +++ b/app/render/backend/opengl/openglproxy.cpp @@ -67,7 +67,7 @@ bool OpenGLProxy::Init() return true; } -NodeValue OpenGLProxy::FrameToValue(FramePtr frame, StreamPtr stream, const VideoParams& params, const RenderMode::Mode& mode) +QVariant OpenGLProxy::FrameToValue(FramePtr frame, StreamPtr stream, const VideoParams& params, const RenderMode::Mode& mode) { ImageStreamPtr video_stream = std::static_pointer_cast(stream); @@ -167,12 +167,12 @@ NodeValue OpenGLProxy::FrameToValue(FramePtr frame, StreamPtr stream, const Vide footage_tex_ref = associated_tex_ref; } - return NodeValue(NodeParam::kTexture, QVariant::fromValue(footage_tex_ref)); + return QVariant::fromValue(footage_tex_ref); } -NodeValue OpenGLProxy::PreCachedFrameToValue(FramePtr frame) +QVariant OpenGLProxy::PreCachedFrameToValue(FramePtr frame) { - return NodeValue(NodeParam::kTexture, QVariant::fromValue(texture_cache_.Get(ctx_, frame))); + return QVariant::fromValue(texture_cache_.Get(ctx_, frame)); } void OpenGLProxy::Close() @@ -185,10 +185,9 @@ void OpenGLProxy::Close() ctx_ = nullptr; } -void OpenGLProxy::RunNodeAccelerated(const Node *node, +QVariant OpenGLProxy::RunNodeAccelerated(const Node *node, const TimeRange &range, NodeValueDatabase &input_params, - NodeValueTable &output_params, const VideoParams& params) { OpenGLShaderPtr shader = shader_cache_.value(node->ShaderID(input_params)); @@ -426,7 +425,7 @@ void OpenGLProxy::RunNodeAccelerated(const Node *node, shader->release(); - output_params.Push(NodeParam::kTexture, QVariant::fromValue(output_tex)); + return QVariant::fromValue(output_tex); } void OpenGLProxy::TextureToBuffer(const QVariant& tex_in, diff --git a/app/render/backend/opengl/openglproxy.h b/app/render/backend/opengl/openglproxy.h index 6850bd675..ffb1fa56d 100644 --- a/app/render/backend/opengl/openglproxy.h +++ b/app/render/backend/opengl/openglproxy.h @@ -67,22 +67,21 @@ public: void Close(); public slots: - void RunNodeAccelerated(const OLIVE_NAMESPACE::Node *node, - const OLIVE_NAMESPACE::TimeRange &range, - OLIVE_NAMESPACE::NodeValueDatabase &input_params, - OLIVE_NAMESPACE::NodeValueTable& output_params, - const OLIVE_NAMESPACE::VideoParams ¶ms); + QVariant RunNodeAccelerated(const OLIVE_NAMESPACE::Node *node, + const OLIVE_NAMESPACE::TimeRange &range, + OLIVE_NAMESPACE::NodeValueDatabase &input_params, + const OLIVE_NAMESPACE::VideoParams ¶ms); void TextureToBuffer(const QVariant& texture, OLIVE_NAMESPACE::FramePtr frame, const QMatrix4x4& matrix); - OLIVE_NAMESPACE::NodeValue FrameToValue(OLIVE_NAMESPACE::FramePtr frame, - OLIVE_NAMESPACE::StreamPtr stream, - const OLIVE_NAMESPACE::VideoParams ¶ms, - const OLIVE_NAMESPACE::RenderMode::Mode &mode); + QVariant FrameToValue(OLIVE_NAMESPACE::FramePtr frame, + OLIVE_NAMESPACE::StreamPtr stream, + const OLIVE_NAMESPACE::VideoParams ¶ms, + const OLIVE_NAMESPACE::RenderMode::Mode &mode); - OLIVE_NAMESPACE::NodeValue PreCachedFrameToValue(OLIVE_NAMESPACE::FramePtr frame); + QVariant PreCachedFrameToValue(OLIVE_NAMESPACE::FramePtr frame); private: QOpenGLContext* ctx_; diff --git a/app/render/backend/opengl/openglworker.cpp b/app/render/backend/opengl/openglworker.cpp index e7ad361e4..f3e66dd9a 100644 --- a/app/render/backend/opengl/openglworker.cpp +++ b/app/render/backend/opengl/openglworker.cpp @@ -38,41 +38,49 @@ void OpenGLWorker::TextureToFrame(const QVariant &texture, FramePtr frame, const Q_ARG(const QMatrix4x4&, mat)); } -NodeValue OpenGLWorker::FrameToTexture(DecoderPtr decoder, StreamPtr stream, const TimeRange &range) const +QVariant OpenGLWorker::FootageFrameToTexture(StreamPtr stream, FramePtr frame) const { - FramePtr frame = decoder->RetrieveVideo(range.in(), - video_params().divider()); + QVariant value; - NodeValue value; - - if (frame) { - QMetaObject::invokeMethod(proxy_, - "FrameToValue", - Qt::BlockingQueuedConnection, - OLIVE_NS_RETURN_ARG(NodeValue, value), - OLIVE_NS_ARG(FramePtr, frame), - OLIVE_NS_ARG(StreamPtr, stream), - OLIVE_NS_CONST_ARG(VideoParams&, video_params()), - OLIVE_NS_CONST_ARG(RenderMode::Mode&, render_mode())); - } + QMetaObject::invokeMethod(proxy_, + "FrameToValue", + Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QVariant, value), + OLIVE_NS_ARG(FramePtr, frame), + OLIVE_NS_ARG(StreamPtr, stream), + OLIVE_NS_CONST_ARG(VideoParams&, video_params()), + OLIVE_NS_CONST_ARG(RenderMode::Mode&, render_mode())); return value; } -void OpenGLWorker::ProcessNodeEvent(const Node *node, const TimeRange &range, NodeValueDatabase &input_params, NodeValueTable &output_params) +QVariant OpenGLWorker::CachedFrameToTexture(FramePtr frame) const { - RenderWorker::ProcessNodeEvent(node, range, input_params, output_params); + QVariant value; - if (node->GetCapabilities(input_params) & Node::kShader) { - QMetaObject::invokeMethod(proxy_, - "RunNodeAccelerated", - Qt::BlockingQueuedConnection, - OLIVE_NS_CONST_ARG(Node*, node), - OLIVE_NS_CONST_ARG(TimeRange&, range), - OLIVE_NS_ARG(NodeValueDatabase&, input_params), - OLIVE_NS_ARG(NodeValueTable&, output_params), - OLIVE_NS_CONST_ARG(VideoParams&, video_params())); - } + QMetaObject::invokeMethod(proxy_, + "PreCachedFrameToValue", + Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QVariant, value), + OLIVE_NS_ARG(FramePtr, frame)); + + return value; +} + +QVariant OpenGLWorker::ProcessShader(const Node *node, const TimeRange &range, NodeValueDatabase &input_params) +{ + QVariant value; + + QMetaObject::invokeMethod(proxy_, + "RunNodeAccelerated", + Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QVariant, value), + OLIVE_NS_CONST_ARG(Node*, node), + OLIVE_NS_CONST_ARG(TimeRange&, range), + OLIVE_NS_ARG(NodeValueDatabase&, input_params), + OLIVE_NS_CONST_ARG(VideoParams&, video_params())); + + return value; } OLIVE_NAMESPACE_EXIT diff --git a/app/render/backend/opengl/openglworker.h b/app/render/backend/opengl/openglworker.h index 82057a034..d190d3abc 100644 --- a/app/render/backend/opengl/openglworker.h +++ b/app/render/backend/opengl/openglworker.h @@ -34,9 +34,11 @@ public: protected: virtual void TextureToFrame(const QVariant& texture, FramePtr frame, const QMatrix4x4 &mat) const override; - virtual NodeValue FrameToTexture(DecoderPtr decoder, StreamPtr stream, const TimeRange &range) const override; + virtual QVariant FootageFrameToTexture(StreamPtr stream, FramePtr frame) const override; - virtual void ProcessNodeEvent(const Node *node, const TimeRange &range, NodeValueDatabase &input_params, NodeValueTable &output_params) override; + virtual QVariant CachedFrameToTexture(FramePtr frame) const override; + + virtual QVariant ProcessShader(const Node *node, const TimeRange &range, NodeValueDatabase &input_params) override; private: OpenGLProxy* proxy_; diff --git a/app/render/backend/renderbackend.cpp b/app/render/backend/renderbackend.cpp index f2b9196b7..5281a25e5 100644 --- a/app/render/backend/renderbackend.cpp +++ b/app/render/backend/renderbackend.cpp @@ -382,7 +382,7 @@ void RenderBackend::CopyNodeInputValue(NodeInput *input) false); // Handle connections - if (input->IsConnected() || our_copy->IsConnected()) { + if (input->is_connected() || our_copy->is_connected()) { // If one of the inputs is connected, it's likely this change came from connecting or // disconnecting whatever was connected to it @@ -444,7 +444,7 @@ Node* RenderBackend::CopyNodeConnections(Node* src_node) void RenderBackend::CopyNodeMakeConnection(NodeInput* src_input, NodeInput* dst_input) { - if (src_input->IsConnected()) { + if (src_input->is_connected()) { Node* dst_node = CopyNodeConnections(src_input->get_connected_node()); NodeOutput* corresponding_output = dst_node->GetOutputWithID(src_input->get_connected_output()->id()); diff --git a/app/render/backend/renderworker.cpp b/app/render/backend/renderworker.cpp index a80c53a31..fae69ab99 100644 --- a/app/render/backend/renderworker.cpp +++ b/app/render/backend/renderworker.cpp @@ -163,7 +163,7 @@ NodeValueTable RenderWorker::GenerateBlockTable(const TrackOutput *track, const } } - merged_table.Push(NodeParam::kSamples, QVariant::fromValue(block_range_buffer)); + merged_table.Push(NodeParam::kSamples, QVariant::fromValue(block_range_buffer), track); return merged_table; @@ -172,13 +172,8 @@ NodeValueTable RenderWorker::GenerateBlockTable(const TrackOutput *track, const } } -void RenderWorker::ProcessNodeEvent(const Node *node, const TimeRange &range, NodeValueDatabase &input_params_in, NodeValueTable &output_params) +QVariant RenderWorker::ProcessSamples(const Node *node, const TimeRange &range, NodeValueDatabase &input_params_in) { - // Check if node processes samples - if (!(node->GetCapabilities(input_params_in) & Node::kSampleProcessor)) { - return; - } - // Copy database so we can make some temporary modifications to it NodeValueDatabase input_params = input_params_in; NodeInput* sample_input = node->ProcessesSamplesFrom(input_params); @@ -188,13 +183,13 @@ void RenderWorker::ProcessNodeEvent(const Node *node, const TimeRange &range, No // If there isn't one, there's nothing to do if (samples_var.isNull()) { - return; + return QVariant(); } SampleBufferPtr input_buffer = samples_var.value(); if (!input_buffer) { - return; + return QVariant(); } SampleBufferPtr output_buffer = SampleBuffer::CreateAllocated(input_buffer->audio_params(), input_buffer->sample_count()); @@ -216,7 +211,7 @@ void RenderWorker::ProcessNodeEvent(const Node *node, const TimeRange &range, No NodeInput* input = static_cast(param); // If the input isn't keyframing, we don't need to update it unless it's connected, in which case it may change - if (input->IsConnected() || input->is_keyframing()) { + if (input->is_connected() || input->is_keyframing()) { input_params.Insert(input, ProcessInput(input, TimeRange(this_sample_time, this_sample_time))); } } @@ -229,64 +224,85 @@ void RenderWorker::ProcessNodeEvent(const Node *node, const TimeRange &range, No i); } - output_params.Push(NodeParam::kSamples, QVariant::fromValue(output_buffer)); + return QVariant::fromValue(output_buffer); } -void RenderWorker::FootageProcessingEvent(StreamPtr stream, const TimeRange &input_time, NodeValueTable *table) +void RenderWorker::ProcessNodeEvent(const Node *node, const TimeRange &range, NodeValueDatabase &input_params_in, NodeValueTable &output_params) { - if (stream->type() == Stream::kVideo || stream->type() == Stream::kImage) { + // Convert footage to image/sample buffers + if (node->id() == QStringLiteral("org.olivevideoeditor.Olive.videoinput")) { + QByteArray hash = RenderBackend::HashNode(node, video_params(), range.in()); - ImageStreamPtr video_stream = std::static_pointer_cast(stream); - rational time_match = (stream->type() == Stream::kImage) ? rational() : input_time.in(); - QString colorspace_match = video_stream->get_colorspace_match_string(); + QString fn = FrameHashCache::CachePathName(hash, video_params_.format()); - NodeValue value; - bool found_cache = false; + if (QFileInfo::exists(fn)) { + FramePtr f = FrameHashCache::LoadCacheFrame(hash, video_params_.format()); - if (still_image_cache_.contains(stream.get())) { - const CachedStill& cs = still_image_cache_[stream.get()]; + QVariant cached = CachedFrameToTexture(f); - if (cs.colorspace == colorspace_match - && cs.alpha_is_associated == video_stream->premultiplied_alpha() - && cs.divider == video_params_.divider() - && cs.time == time_match) { - value = cs.texture; - found_cache = true; - } else { - still_image_cache_.remove(stream.get()); + if (!cached.isNull()) { + output_params.Push(NodeParam::kTexture, cached, node); + + // No more to do here + return; } } + } - if (!found_cache) { + QList inputs = node->GetInputsIncludingArrays(); + foreach (NodeInput* input, inputs) { + if (input->data_type() == NodeParam::kFootage) { + TimeRange input_time = node->InputTimeAdjustment(input, range); - value = GetDataFromStream(stream, input_time); + StreamPtr stream = ResolveStreamFromInput(input); - still_image_cache_.insert(stream.get(), {value, - colorspace_match, - video_stream->premultiplied_alpha(), - video_params_.divider(), - time_match}); + if (stream) { + QVariant v = ProcessFootage(stream, input_time); + if (!v.isNull()) { + if (stream->type() == Stream::kVideo || stream->type() == Stream::kImage) { + output_params.Push(NodeParam::kTexture, v, node); + } else if (stream->type() == Stream::kAudio) { + output_params.Push(NodeParam::kSamples, v, node); + } + } + } } + } - table->Push(value); + // Check if node has a shader + if (node->GetCapabilities(input_params_in) & Node::kShader) { + QVariant v = ProcessShader(node, range, input_params_in); - } else if (stream->type() == Stream::kAudio) { + if (!v.isNull()) { + output_params.Push(NodeParam::kTexture, v, node); + } + } - table->Push(GetDataFromStream(stream, input_time)); + // Check if node processes samples + if (node->GetCapabilities(input_params_in) & Node::kSampleProcessor) { + QVariant v = ProcessSamples(node, range, input_params_in); + if (!v.isNull()) { + output_params.Push(NodeParam::kSamples, v, node); + } } } -NodeValue RenderWorker::GetDataFromStream(StreamPtr stream, const TimeRange &input_time) +QVariant RenderWorker::GetDataFromStream(StreamPtr stream, const TimeRange &input_time) { DecoderPtr decoder = ResolveDecoderFromInput(stream); if (decoder) { if (stream->type() == Stream::kVideo || stream->type() == Stream::kImage) { - // Return a texture from the derived class - return FrameToTexture(decoder, stream, input_time); + FramePtr frame = decoder->RetrieveVideo(input_time.in(), + video_params().divider()); + + if (frame) { + // Return a texture from the derived class + return FootageFrameToTexture(stream, frame); + } } else if (stream->type() == Stream::kAudio) { @@ -334,13 +350,13 @@ NodeValue RenderWorker::GetDataFromStream(StreamPtr stream, const TimeRange &inp audio_params()); if (frame) { - return NodeValue(NodeParam::kSamples, QVariant::fromValue(frame)); + return QVariant::fromValue(frame); } } } } - return NodeValue(); + return QVariant(); } DecoderPtr RenderWorker::ResolveDecoderFromInput(StreamPtr stream) @@ -366,4 +382,52 @@ DecoderPtr RenderWorker::ResolveDecoderFromInput(StreamPtr stream) return decoder; } +QVariant RenderWorker::ProcessFootage(StreamPtr stream, const TimeRange &input_time) +{ + if (stream->type() == Stream::kVideo || stream->type() == Stream::kImage) { + + ImageStreamPtr video_stream = std::static_pointer_cast(stream); + rational time_match = (stream->type() == Stream::kImage) ? rational() : input_time.in(); + QString colorspace_match = video_stream->get_colorspace_match_string(); + + QVariant value; + bool found_cache = false; + + if (still_image_cache_.contains(stream.get())) { + const CachedStill& cs = still_image_cache_[stream.get()]; + + if (cs.colorspace == colorspace_match + && cs.alpha_is_associated == video_stream->premultiplied_alpha() + && cs.divider == video_params_.divider() + && cs.time == time_match) { + value = cs.texture; + found_cache = true; + } else { + still_image_cache_.remove(stream.get()); + } + } + + if (!found_cache) { + + value = GetDataFromStream(stream, input_time); + + still_image_cache_.insert(stream.get(), {value, + colorspace_match, + video_stream->premultiplied_alpha(), + video_params_.divider(), + time_match}); + + } + + return value; + + } else if (stream->type() == Stream::kAudio) { + + return GetDataFromStream(stream, input_time); + + } + + return QVariant(); +} + OLIVE_NAMESPACE_EXIT diff --git a/app/render/backend/renderworker.h b/app/render/backend/renderworker.h index aabe9f5d4..fc5f416d0 100644 --- a/app/render/backend/renderworker.h +++ b/app/render/backend/renderworker.h @@ -114,14 +114,16 @@ public: protected: virtual void TextureToFrame(const QVariant& texture, FramePtr frame, const QMatrix4x4 &mat) const = 0; - virtual NodeValue FrameToTexture(DecoderPtr decoder, StreamPtr stream, const TimeRange &range) const = 0; + virtual QVariant FootageFrameToTexture(StreamPtr stream, FramePtr frame) const = 0; - virtual void FootageProcessingEvent(StreamPtr stream, const TimeRange &input_time, NodeValueTable* table) override; + virtual QVariant CachedFrameToTexture(FramePtr frame) const = 0; virtual NodeValueTable GenerateBlockTable(const TrackOutput *track, const TimeRange &range) override; virtual void ProcessNodeEvent(const Node *node, const TimeRange &range, NodeValueDatabase &input_params_in, NodeValueTable &output_params) override; + virtual QVariant ProcessShader(const Node *node, const TimeRange &range, NodeValueDatabase &input_params) = 0; + const VideoParams& video_params() const { return video_params_; @@ -146,10 +148,14 @@ signals: void WaveformGenerated(OLIVE_NAMESPACE::TrackOutput* track, OLIVE_NAMESPACE::AudioVisualWaveform samples, OLIVE_NAMESPACE::TimeRange start); private: - NodeValue GetDataFromStream(StreamPtr stream, const TimeRange& input_time); + QVariant ProcessSamples(const Node *node, const TimeRange &range, NodeValueDatabase &input_params_in); + + QVariant GetDataFromStream(StreamPtr stream, const TimeRange& input_time); DecoderPtr ResolveDecoderFromInput(StreamPtr stream); + QVariant ProcessFootage(StreamPtr stream, const TimeRange &input_time); + RenderBackend* parent_; VideoParams video_params_; @@ -157,7 +163,7 @@ private: AudioParams audio_params_; struct CachedStill { - NodeValue texture; + QVariant texture; QString colorspace; bool alpha_is_associated; int divider; diff --git a/app/widget/nodeparamview/nodeparamviewconnectedlabel.cpp b/app/widget/nodeparamview/nodeparamviewconnectedlabel.cpp index 65ed2504d..612b14f81 100644 --- a/app/widget/nodeparamview/nodeparamviewconnectedlabel.cpp +++ b/app/widget/nodeparamview/nodeparamviewconnectedlabel.cpp @@ -60,7 +60,7 @@ void NodeParamViewConnectedLabel::UpdateConnected() { QString connection_str; - if (input_->IsConnected()) { + if (input_->is_connected()) { connection_str = input_->get_connected_node()->Name(); } else { connection_str = tr("Nothing"); diff --git a/app/widget/nodeparamview/nodeparamviewitem.cpp b/app/widget/nodeparamview/nodeparamviewitem.cpp index 262b2ee22..d9093079e 100644 --- a/app/widget/nodeparamview/nodeparamviewitem.cpp +++ b/app/widget/nodeparamview/nodeparamviewitem.cpp @@ -194,7 +194,7 @@ NodeParamViewItemBody::NodeParamViewItemBody(const QVector &inputs, } } - if (input->IsConnectable()) { + if (input->is_connectable()) { // Create clickable label used when an input is connected ui_objects.connected_label = new NodeParamViewConnectedLabel(input); connect(ui_objects.connected_label, &NodeParamViewConnectedLabel::ConnectionClicked, this, &NodeParamViewItemBody::ConnectionClicked); @@ -222,7 +222,7 @@ NodeParamViewItemBody::NodeParamViewItemBody(const QVector &inputs, input_ui_map_.insert(input, ui_objects); // Update "connected" label - if (input->IsConnectable()) { + if (input->is_connectable()) { UpdateUIForEdgeConnection(input); } @@ -310,11 +310,11 @@ void NodeParamViewItemBody::UpdateUIForEdgeConnection(NodeInput *input) const InputUI& ui_objects = input_ui_map_[input]; foreach (QWidget* w, ui_objects.widget_bridge->widgets()) { - w->setVisible(!input->IsConnected()); + w->setVisible(!input->is_connected()); } // Show/hide connection label - ui_objects.connected_label->setVisible(input->IsConnected()); + ui_objects.connected_label->setVisible(input->is_connected()); } void NodeParamViewItemBody::InputKeyframeEnableChanged(bool e) diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index 8f263a6e3..9e77af19a 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -399,7 +399,7 @@ void NodeView::mouseMoveEvent(QMouseEvent *event) if (param->type() == NodeParam::kInput) { NodeInput* input = static_cast(param); - if (input->IsConnectable()) { + if (input->is_connectable()) { if (input->data_type() & new_drop_edge->edge()->input()->data_type()) { drop_input_ = input; break; diff --git a/app/widget/nodeview/nodeviewitem.cpp b/app/widget/nodeview/nodeviewitem.cpp index f24a402a1..d3d61f318 100644 --- a/app/widget/nodeview/nodeviewitem.cpp +++ b/app/widget/nodeview/nodeviewitem.cpp @@ -177,7 +177,7 @@ void NodeViewItem::SetNode(Node *n) if (p->type() == NodeParam::kInput) { NodeInput* input = static_cast(p); - if (input->IsConnectable()) { + if (input->is_connectable()) { node_inputs_.append(input); } } diff --git a/app/widget/viewer/gizmotraverser.cpp b/app/widget/viewer/gizmotraverser.cpp index 1e77fd925..9cb0f64d0 100644 --- a/app/widget/viewer/gizmotraverser.cpp +++ b/app/widget/viewer/gizmotraverser.cpp @@ -22,17 +22,25 @@ OLIVE_NAMESPACE_ENTER -void GizmoTraverser::FootageProcessingEvent(StreamPtr stream, const TimeRange &/*input_time*/, NodeValueTable *table) +void GizmoTraverser::ProcessNodeEvent(const Node *node, const TimeRange &range, NodeValueDatabase &input_params_in, NodeValueTable &output_params) { - if (stream->type() == Stream::kVideo || stream->type() == Stream::kAudio) { + // Convert footage to image/sample buffers + QList inputs = node->GetInputsIncludingArrays(); + foreach (NodeInput* input, inputs) { + if (input->data_type() == NodeParam::kFootage) { + StreamPtr stream = ResolveStreamFromInput(input); - ImageStreamPtr image_stream = std::static_pointer_cast(stream); + if (stream + && (stream->type() == Stream::kVideo || stream->type() == Stream::kImage)) { + ImageStreamPtr image_stream = std::static_pointer_cast(stream); - table->Push(NodeParam::kTexture, QSize(image_stream->width(), - image_stream->height())); - - } else if (stream->type() == Stream::kAudio) { - // FIXME: Get samples + output_params.Push(NodeParam::kTexture, + QSize(image_stream->width(), image_stream->height()), + node); + } else if (stream->type() == Stream::kAudio) { + // FIXME: Do something... + } + } } } diff --git a/app/widget/viewer/gizmotraverser.h b/app/widget/viewer/gizmotraverser.h index 97b2cfc43..b69be083a 100644 --- a/app/widget/viewer/gizmotraverser.h +++ b/app/widget/viewer/gizmotraverser.h @@ -31,7 +31,7 @@ public: GizmoTraverser() = default; protected: - virtual void FootageProcessingEvent(StreamPtr stream, const TimeRange &input_time, NodeValueTable* table) override; + virtual void ProcessNodeEvent(const Node *node, const TimeRange &range, NodeValueDatabase &input_params_in, NodeValueTable &output_params) override; }; diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index 160f563b3..a9bf2d962 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -704,8 +704,8 @@ void ViewerWidget::UpdateStack() rational new_tb; if (GetConnectedNode() - && !GetConnectedNode()->texture_input()->IsConnected() - && GetConnectedNode()->samples_input()->IsConnected()) { + && !GetConnectedNode()->texture_input()->is_connected() + && GetConnectedNode()->samples_input()->is_connected()) { // If we have a node AND video is disconnected AND audio is connected, show waveform view stack_->setCurrentWidget(waveform_view_); new_tb = GetConnectedNode()->audio_params().time_base();