diff --git a/app/node/graph.cpp b/app/node/graph.cpp index 4e467671f..84b8c8308 100644 --- a/app/node/graph.cpp +++ b/app/node/graph.cpp @@ -41,8 +41,8 @@ void NodeGraph::AddNode(Node *node) node->setParent(this); - connect(node, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SIGNAL(EdgeAdded(NodeEdgePtr))); - connect(node, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SIGNAL(EdgeRemoved(NodeEdgePtr))); + connect(node, &Node::EdgeAdded, this, &NodeGraph::EdgeAdded); + connect(node, &Node::EdgeRemoved, this, &NodeGraph::EdgeRemoved); node_children_.append(node); @@ -62,8 +62,8 @@ void NodeGraph::TakeNode(Node *node, QObject* new_parent) node->DisconnectAll(); - disconnect(node, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SIGNAL(EdgeAdded(NodeEdgePtr))); - disconnect(node, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SIGNAL(EdgeRemoved(NodeEdgePtr))); + disconnect(node, &Node::EdgeAdded, this, &NodeGraph::EdgeAdded); + disconnect(node, &Node::EdgeRemoved, this, &NodeGraph::EdgeRemoved); node->setParent(new_parent); diff --git a/app/node/input.cpp b/app/node/input.cpp index 58ffa56c9..6131a13d5 100644 --- a/app/node/input.cpp +++ b/app/node/input.cpp @@ -85,7 +85,7 @@ QString NodeInput::name() return NodeParam::name(); } -void NodeInput::Load(QXmlStreamReader *reader) +void NodeInput::Load(QXmlStreamReader *reader, QHash& param_ptrs, QList &input_connections) { XMLAttributeLoop(reader, attr) { if (attr.name() == "keyframing") { @@ -100,7 +100,7 @@ void NodeInput::Load(QXmlStreamReader *reader) int val_index = 0; XMLReadLoop(reader, "standard") { - if (reader->name() == "value") { + if (reader->isStartElement() && reader->name() == "value") { reader->readNext(); QString value_text = reader->text().toString(); @@ -118,7 +118,7 @@ void NodeInput::Load(QXmlStreamReader *reader) int track = 0; XMLReadLoop(reader, "keyframes") { - if (reader->name() == "track") { + if (reader->isStartElement() && reader->name() == "track") { XMLReadLoop(reader, "track") { if (reader->name() == "key") { rational key_time; @@ -157,8 +157,16 @@ void NodeInput::Load(QXmlStreamReader *reader) track++; } } - } else { + } else if (reader->name() == "connections") { + XMLReadLoop(reader, "connections") { + if (reader->isStartElement() && reader->name() == "connection") { + reader->readNext(); + input_connections.append({this, reader->text().toULongLong()}); + } + } + } else { + LoadInternal(reader, param_ptrs, input_connections); } } } @@ -170,8 +178,6 @@ void NodeInput::Save(QXmlStreamWriter *writer) const writer->writeAttribute("id", id()); - writer->writeAttribute("ptr", QString::number(reinterpret_cast(this))); - writer->writeAttribute("keyframing", QString::number(keyframing_)); // Write standard value @@ -216,12 +222,25 @@ void NodeInput::Save(QXmlStreamWriter *writer) const writer->writeEndElement(); // input } +void NodeInput::SaveConnections(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("connections"); + + foreach (NodeEdgePtr edge, edges_) { + writer->writeTextElement("connection", + QString::number(reinterpret_cast(edge->output()))); + } + + writer->writeEndElement(); // connections +} + + const NodeParam::DataType &NodeInput::data_type() const { return data_type_; } -void NodeInput::LoadInternal(QXmlStreamReader *reader) +void NodeInput::LoadInternal(QXmlStreamReader *reader, QHash ¶m_ptrs, QList &input_connections) { } diff --git a/app/node/input.h b/app/node/input.h index b320cf2ce..bd52593b1 100644 --- a/app/node/input.h +++ b/app/node/input.h @@ -54,7 +54,7 @@ public: virtual QString name() override; - virtual void Load(QXmlStreamReader* reader) override; + virtual void Load(QXmlStreamReader* reader, QHash& param_ptrs, QList &input_connections) override; virtual void Save(QXmlStreamWriter* writer) const override; @@ -243,11 +243,13 @@ signals: void KeyframeRemoved(NodeKeyframePtr key); protected: - virtual void LoadInternal(QXmlStreamReader* reader); + virtual void LoadInternal(QXmlStreamReader* reader, QHash& param_ptrs, QList &input_connections); virtual void SaveInternal(QXmlStreamWriter* writer) const; private: + void SaveConnections(QXmlStreamWriter* writer) const; + /** * @brief Returns whether a data type can be interpolated or not */ diff --git a/app/node/inputarray.cpp b/app/node/inputarray.cpp index ba32c8727..4d9a5272c 100644 --- a/app/node/inputarray.cpp +++ b/app/node/inputarray.cpp @@ -1,5 +1,7 @@ #include "inputarray.h" +#include + #include "common/xmlreadloop.h" #include "node.h" @@ -57,9 +59,9 @@ void NodeInputArray::SetSize(int size, bool lock) new_param->setParent(this); sub_params_.replace(i, new_param); - connect(new_param, SIGNAL(ValueChanged(rational, rational)), this, SIGNAL(ValueChanged(rational, rational))); - connect(new_param, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SIGNAL(EdgeAdded(NodeEdgePtr))); - connect(new_param, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SIGNAL(EdgeRemoved(NodeEdgePtr))); + connect(new_param, &NodeInput::ValueChanged, this, &NodeInput::ValueChanged); + connect(new_param, &NodeInput::EdgeAdded, this, &NodeInput::EdgeAdded); + connect(new_param, &NodeInput::EdgeRemoved, this, &NodeInput::EdgeRemoved); } } @@ -168,13 +170,13 @@ void NodeInputArray::RemoveAt(int index) RemoveLast(); } -void NodeInputArray::LoadInternal(QXmlStreamReader *reader) +void NodeInputArray::LoadInternal(QXmlStreamReader *reader, QHash& param_ptrs, QList &input_connections) { if (reader->name() == "subparameters") { XMLReadLoop(reader, "subparameters") { if (reader->name() == "input") { Append(); - At(GetSize() - 1)->Load(reader); + At(GetSize() - 1)->Load(reader, param_ptrs, input_connections); } } } diff --git a/app/node/inputarray.h b/app/node/inputarray.h index b6aaf4550..5ebb04fdb 100644 --- a/app/node/inputarray.h +++ b/app/node/inputarray.h @@ -33,7 +33,7 @@ signals: void SizeChanged(int size); protected: - virtual void LoadInternal(QXmlStreamReader* reader) override; + virtual void LoadInternal(QXmlStreamReader* reader, QHash ¶m_ptrs, QList &input_connections) override; virtual void SaveInternal(QXmlStreamWriter* writer) const override; diff --git a/app/node/node.cpp b/app/node/node.cpp index 1ed039ffc..1f4f05910 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -20,6 +20,7 @@ #include "node.h" +#include #include #include @@ -49,9 +50,9 @@ Node::~Node() } } -void Node::Load(QXmlStreamReader *reader) +void Node::Load(QXmlStreamReader *reader, QHash &output_ptrs, QList& input_connections, const QString& element) { - XMLReadLoop(reader, "node") { + XMLReadLoop(reader, (element.isEmpty() ? "node" : element)) { if (reader->isStartElement()) { if (reader->name() == "input" || reader->name() == "output") { QString param_id; @@ -76,15 +77,15 @@ void Node::Load(QXmlStreamReader *reader) continue; } - param->Load(reader); + param->Load(reader, output_ptrs, input_connections); } } } } -void Node::Save(QXmlStreamWriter *writer) const +void Node::Save(QXmlStreamWriter *writer, const QString &custom_name) const { - writer->writeStartElement("node"); + writer->writeStartElement(custom_name.isEmpty() ? "node" : custom_name); writer->writeAttribute("id", id()); @@ -129,8 +130,8 @@ void Node::AddParameter(NodeParam *param) params_.insert(params_.size()-1, param); } - connect(param, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SIGNAL(EdgeAdded(NodeEdgePtr))); - connect(param, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SIGNAL(EdgeRemoved(NodeEdgePtr))); + connect(param, &NodeParam::EdgeAdded, this, &Node::EdgeAdded); + connect(param, &NodeParam::EdgeRemoved, this, &Node::EdgeRemoved); if (param->type() == NodeParam::kInput) { ConnectInput(static_cast(param)); @@ -566,16 +567,16 @@ bool Node::HasParamOfType(NodeParam::Type type, bool must_be_connected) const void Node::ConnectInput(NodeInput *input) { - connect(input, SIGNAL(ValueChanged(rational, rational)), this, SLOT(InputChanged(rational, rational))); - connect(input, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(InputConnectionChanged(NodeEdgePtr))); - connect(input, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(InputConnectionChanged(NodeEdgePtr))); + connect(input, &NodeInput::ValueChanged, this, &Node::InputChanged); + connect(input, &NodeInput::EdgeAdded, this, &Node::InputConnectionChanged); + connect(input, &NodeInput::EdgeRemoved, this, &Node::InputConnectionChanged); } void Node::DisconnectInput(NodeInput *input) { - disconnect(input, SIGNAL(ValueChanged(rational, rational)), this, SLOT(InputChanged(rational, rational))); - disconnect(input, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(InputConnectionChanged(NodeEdgePtr))); - disconnect(input, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(InputConnectionChanged(NodeEdgePtr))); + disconnect(input, &NodeInput::ValueChanged, this, &Node::InputChanged); + disconnect(input, &NodeInput::EdgeAdded, this, &Node::InputConnectionChanged); + disconnect(input, &NodeInput::EdgeRemoved, this, &Node::InputConnectionChanged); } void Node::InputChanged(rational start, rational end) diff --git a/app/node/node.h b/app/node/node.h index 0b5cb317c..83378708d 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -68,12 +68,12 @@ public: /** * @brief Clear current node variables and replace them with */ - void Load(QXmlStreamReader* reader); + void Load(QXmlStreamReader* reader, QHash& param_ptrs, QList &input_connections, const QString &element = QString()); /** * @brief Save this node into a text/XML format */ - void Save(QXmlStreamWriter* writer) const; + void Save(QXmlStreamWriter* writer, const QString& custom_name = QString()) const; /** * @brief Return the name of the node diff --git a/app/node/output.cpp b/app/node/output.cpp index a04226437..319860753 100644 --- a/app/node/output.cpp +++ b/app/node/output.cpp @@ -20,6 +20,7 @@ #include "output.h" +#include "common/xmlreadloop.h" #include "node/node.h" NodeOutput::NodeOutput(const QString &id) : @@ -41,8 +42,15 @@ QString NodeOutput::name() return NodeParam::name(); } -void NodeOutput::Load(QXmlStreamReader *reader) +void NodeOutput::Load(QXmlStreamReader* reader, QHash& param_ptrs, QList &input_connections) { + XMLAttributeLoop(reader, attr) { + if (attr.name() == "ptr") { + quintptr saved_ptr = attr.value().toULongLong(); + + param_ptrs.insert(saved_ptr, this); + } + } } void NodeOutput::Save(QXmlStreamWriter *writer) const @@ -53,7 +61,5 @@ void NodeOutput::Save(QXmlStreamWriter *writer) const writer->writeAttribute("ptr", QString::number(reinterpret_cast(this))); - SaveConnections(writer); - writer->writeEndElement(); // output } diff --git a/app/node/output.h b/app/node/output.h index 479ed3f96..733b3b73b 100644 --- a/app/node/output.h +++ b/app/node/output.h @@ -42,7 +42,7 @@ public: virtual QString name() override; - virtual void Load(QXmlStreamReader *reader) override; + virtual void Load(QXmlStreamReader* reader, QHash& param_ptrs, QList &input_connections) override; virtual void Save(QXmlStreamWriter* writer) const override; diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index e1ec0933b..f85d6d1b2 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -36,9 +36,9 @@ TrackOutput::TrackOutput() : block_input_ = new NodeInputArray("block_in", NodeParam::kAny); block_input_->set_is_keyframable(false); AddInput(block_input_); - connect(block_input_, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(BlockConnected(NodeEdgePtr))); - connect(block_input_, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(BlockDisconnected(NodeEdgePtr))); - connect(block_input_, SIGNAL(SizeChanged(int)), this, SLOT(BlockListSizeChanged(int))); + connect(block_input_, &NodeInputArray::EdgeAdded, this, &TrackOutput::BlockConnected); + connect(block_input_, &NodeInputArray::EdgeRemoved, this, &TrackOutput::BlockDisconnected); + connect(block_input_, &NodeInputArray::SizeChanged, this, &TrackOutput::BlockListSizeChanged); muted_input_ = new NodeInput("muted_in", NodeParam::kBoolean); muted_input_->set_is_keyframable(false); diff --git a/app/node/output/track/tracklist.cpp b/app/node/output/track/tracklist.cpp index 512f894ab..8013391b3 100644 --- a/app/node/output/track/tracklist.cpp +++ b/app/node/output/track/tracklist.cpp @@ -28,9 +28,9 @@ TrackList::TrackList(ViewerOutput *parent, const Timeline::TrackType &type, Node track_input_(track_input), type_(type) { - connect(track_input, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(TrackConnected(NodeEdgePtr))); - connect(track_input, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(TrackDisconnected(NodeEdgePtr))); - connect(track_input, SIGNAL(SizeChanged(int)), this, SLOT(TrackListSizeChanged(int))); + connect(track_input, &NodeInputArray::EdgeAdded, this, &TrackList::TrackConnected); + connect(track_input, &NodeInputArray::EdgeRemoved, this, &TrackList::TrackDisconnected); + connect(track_input, &NodeInputArray::SizeChanged, this, &TrackList::TrackListSizeChanged); } const Timeline::TrackType &TrackList::type() const @@ -154,10 +154,10 @@ void TrackList::TrackConnected(NodeEdgePtr edge) track_cache_.replace(track_index, connected_track); - connect(connected_track, SIGNAL(BlockAdded(Block*)), this, SLOT(TrackAddedBlock(Block*))); - connect(connected_track, SIGNAL(BlockRemoved(Block*)), this, SLOT(TrackRemovedBlock(Block*))); - connect(connected_track, SIGNAL(TrackLengthChanged()), this, SLOT(UpdateTotalLength())); - connect(connected_track, SIGNAL(TrackHeightChanged(int)), this, SLOT(TrackHeightChangedSlot(int))); + connect(connected_track, &TrackOutput::BlockAdded, this, &TrackList::TrackAddedBlock); + connect(connected_track, &TrackOutput::BlockRemoved, this, &TrackList::TrackRemovedBlock); + connect(connected_track, &TrackOutput::TrackLengthChanged, this, &TrackList::UpdateTotalLength); + connect(connected_track, &TrackOutput::TrackHeightChanged, this, &TrackList::TrackHeightChangedSlot); connected_track->SetIndex(track_index); connected_track->set_track_type(type_); @@ -191,10 +191,10 @@ void TrackList::TrackDisconnected(NodeEdgePtr edge) track->SetIndex(-1); track->set_track_type(Timeline::kTrackTypeNone); - disconnect(track, SIGNAL(BlockAdded(Block*)), this, SLOT(TrackAddedBlock(Block*))); - disconnect(track, SIGNAL(BlockRemoved(Block*)), this, SLOT(TrackRemovedBlock(Block*))); - disconnect(track, SIGNAL(TrackLengthChanged()), this, SLOT(UpdateTotalLength())); - disconnect(track, SIGNAL(TrackHeightChanged(int)), this, SLOT(TrackHeightChangedSlot(int))); + disconnect(track, &TrackOutput::BlockAdded, this, &TrackList::TrackAddedBlock); + disconnect(track, &TrackOutput::BlockRemoved, this, &TrackList::TrackRemovedBlock); + disconnect(track, &TrackOutput::TrackLengthChanged, this, &TrackList::UpdateTotalLength); + disconnect(track, &TrackOutput::TrackHeightChanged, this, &TrackList::TrackHeightChangedSlot); emit TrackListChanged(); diff --git a/app/node/param.cpp b/app/node/param.cpp index d9a65fef0..d2cbd8b68 100644 --- a/app/node/param.cpp +++ b/app/node/param.cpp @@ -282,23 +282,3 @@ QByteArray NodeParam::ValueToBytesInternal(const QVariant &v) return bytes; } - -void NodeParam::SaveConnections(QXmlStreamWriter *writer) const -{ - writer->writeStartElement("connections"); - - foreach (NodeEdgePtr edge, edges_) { - NodeParam* other; - - if (edge->input() == this) { - other = edge->output(); - } else { - other = edge->input(); - } - - writer->writeTextElement("connection", - QString::number(reinterpret_cast(other))); - } - - writer->writeEndElement(); // connections -} diff --git a/app/node/param.h b/app/node/param.h index 22d2e42dc..e1419d102 100644 --- a/app/node/param.h +++ b/app/node/param.h @@ -230,10 +230,15 @@ public: virtual ~NodeParam() override; + struct SerializedConnection { + NodeInput* input; + quintptr output; + }; + /** * @brief Load function */ - virtual void Load(QXmlStreamReader* reader) = 0; + virtual void Load(QXmlStreamReader* reader, QHash& param_ptrs, QList &input_connections) = 0; /** * @brief Save function @@ -379,8 +384,6 @@ signals: void EdgeRemoved(NodeEdgePtr edge); protected: - void SaveConnections(QXmlStreamWriter* writer) const; - /** * @brief Internal list of edges */ diff --git a/app/project/item/folder/folder.cpp b/app/project/item/folder/folder.cpp index 2d4ee1eaf..956c34ca2 100644 --- a/app/project/item/folder/folder.cpp +++ b/app/project/item/folder/folder.cpp @@ -54,7 +54,7 @@ void Folder::Load(QXmlStreamReader *reader) XMLReadLoop(reader, "folder") { if (reader->isStartElement()) { - ItemPtr child = nullptr; + ItemPtr child; if (reader->name() == "folder") { child = std::make_shared(); @@ -62,12 +62,12 @@ void Folder::Load(QXmlStreamReader *reader) child = std::make_shared(); } else if (reader->name() == "sequence") { child = std::make_shared(); + } else { + continue; } - if (child) { - child->Load(reader); - add_child(child); - } + child->Load(reader); + add_child(child); } } } diff --git a/app/project/item/footage/footage.cpp b/app/project/item/footage/footage.cpp index fe36eeb25..27f98ea41 100644 --- a/app/project/item/footage/footage.cpp +++ b/app/project/item/footage/footage.cpp @@ -48,7 +48,7 @@ void Footage::Load(QXmlStreamReader *reader) } } - // FIXME: Probe here + // FIXME: Probe here? XMLReadLoop(reader, "footage") { if (reader->isStartElement()) { diff --git a/app/project/item/sequence/sequence.cpp b/app/project/item/sequence/sequence.cpp index f983c7d68..4d433f905 100644 --- a/app/project/item/sequence/sequence.cpp +++ b/app/project/item/sequence/sequence.cpp @@ -35,9 +35,11 @@ #include "panel/viewer/viewer.h" #include "ui/icons/icons.h" -Sequence::Sequence() : - viewer_output_(nullptr) +Sequence::Sequence() { + viewer_output_ = new ViewerOutput(); + viewer_output_->SetCanBeDeleted(false); + AddNode(viewer_output_); } void Sequence::Load(QXmlStreamReader *reader) @@ -45,41 +47,101 @@ void Sequence::Load(QXmlStreamReader *reader) XMLAttributeLoop(reader, attr) { if (attr.name() == "name") { set_name(attr.value().toString()); + + // Currently the only thing we care about } } + QHash output_ptrs; + QList desired_connections; + XMLReadLoop(reader, "sequence") { if (reader->isStartElement()) { - if (reader->name() == "node") { - QString node_id; + if (reader->name() == "video") { + int video_width, video_height; + rational video_timebase; - XMLAttributeLoop(reader, attr) { - if (attr.name() == "id") { - node_id = attr.value().toString(); - - // Currently the only thing we need - break; + XMLReadLoop(reader, "video") { + if (reader->isStartElement()) { + if (reader->name() == "width") { + reader->readNext(); + video_width = reader->text().toInt(); + } else if (reader->name() == "height") { + reader->readNext(); + video_height = reader->text().toInt(); + } else if (reader->name() == "timebase") { + reader->readNext(); + video_timebase = rational::fromString(reader->text().toString()); + } } } - if (node_id.isEmpty()) { - qDebug() << "Found node with no ID"; - continue; + set_video_params(VideoParams(video_width, video_height, video_timebase)); + } else if (reader->name() == "audio") { + int rate; + uint64_t layout; + + XMLReadLoop(reader, "audio") { + if (reader->isStartElement()) { + if (reader->name() == "rate") { + reader->readNext(); + rate = reader->text().toInt(); + } else if (reader->name() == "layout") { + reader->readNext(); + layout = reader->text().toULongLong(); + } + } } - Node* node = NodeFactory::CreateFromID(node_id); + set_audio_params(AudioParams(rate, layout)); + } else if (reader->name() == "node" || reader->name() == "viewer") { + Node* node; - if (!node) { - qDebug() << "Failed to load" << node_id << "- no node with that ID is installed"; - continue; + if (reader->name() == "node") { + QString node_id; + + XMLAttributeLoop(reader, attr) { + if (attr.name() == "id") { + node_id = attr.value().toString(); + + // Currently the only thing we need + break; + } + } + + if (node_id.isEmpty()) { + qDebug() << "Found node with no ID"; + continue; + } + + node = NodeFactory::CreateFromID(node_id); + + if (!node) { + qDebug() << "Failed to load" << node_id << "- no node with that ID is installed"; + continue; + } + } else { + node = viewer_output_; } - node->Load(reader); + if (node) { + node->Load(reader, output_ptrs, desired_connections, reader->name().toString()); - AddNode(node); + AddNode(node); + } } } } + + // Make connections + foreach (const NodeParam::SerializedConnection& con, desired_connections) { + NodeParam::ConnectEdge(output_ptrs.value(con.output), + con.input); + } + + // Ensure this and all children are in the main thread + // (FIXME: Weird place for this? This should probably be in ProjectLoadManager somehow) + moveToThread(qApp->thread()); } void Sequence::Save(QXmlStreamWriter *writer) const @@ -88,10 +150,29 @@ void Sequence::Save(QXmlStreamWriter *writer) const writer->writeAttribute("name", name()); + writer->writeStartElement("video"); + + writer->writeTextElement("width", QString::number(video_params().width())); + writer->writeTextElement("height", QString::number(video_params().height())); + writer->writeTextElement("timebase", video_params().time_base().toString()); + + writer->writeEndElement(); // video + + writer->writeStartElement("audio"); + + writer->writeTextElement("rate", QString::number(audio_params().sample_rate())); + writer->writeTextElement("layout", QString::number(audio_params().channel_layout())); + + writer->writeEndElement(); // audio + foreach (Node* node, nodes()) { - node->Save(writer); + if (node != viewer_output_) { + node->Save(writer); + } } + viewer_output_->Save(writer, "viewer"); + writer->writeEndElement(); // sequence } @@ -110,19 +191,11 @@ void Sequence::Open(Sequence* sequence) void Sequence::add_default_nodes() { - viewer_output_ = new ViewerOutput(); - viewer_output_->SetCanBeDeleted(false); - AddNode(viewer_output_); - // Create tracks and connect them to the viewer Node* video_track_output = viewer_output_->track_list(Timeline::kTrackTypeVideo)->AddTrack(); Node* audio_track_output = viewer_output_->track_list(Timeline::kTrackTypeAudio)->AddTrack(); NodeParam::ConnectEdge(video_track_output->output(), viewer_output_->texture_input()); NodeParam::ConnectEdge(audio_track_output->output(), viewer_output_->samples_input()); - - // Update the timebase on these nodes - set_video_params(video_params_); - set_audio_params(audio_params_); } Item::Type Sequence::type() const @@ -137,46 +210,36 @@ QIcon Sequence::icon() QString Sequence::duration() { - if (!viewer_output_) { - return QString(); - } - rational timeline_length = viewer_output_->Length(); - int64_t timestamp = Timecode::time_to_timestamp(timeline_length, video_params_.time_base()); + int64_t timestamp = Timecode::time_to_timestamp(timeline_length, video_params().time_base()); - return Timecode::timestamp_to_timecode(timestamp, video_params_.time_base(), Timecode::CurrentDisplay()); + return Timecode::timestamp_to_timecode(timestamp, video_params().time_base(), Timecode::CurrentDisplay()); } QString Sequence::rate() { - return QCoreApplication::translate("Sequence", "%1 FPS").arg(video_params_.time_base().flipped().toDouble()); + return QCoreApplication::translate("Sequence", "%1 FPS").arg(video_params().time_base().flipped().toDouble()); } -const VideoParams &Sequence::video_params() +const VideoParams &Sequence::video_params() const { - return video_params_; + return viewer_output_->video_params(); } void Sequence::set_video_params(const VideoParams &vparam) { - video_params_ = vparam; - - if (viewer_output_ != nullptr) - viewer_output_->set_video_params(video_params_); + viewer_output_->set_video_params(vparam); } -const AudioParams &Sequence::audio_params() +const AudioParams &Sequence::audio_params() const { - return audio_params_; + return viewer_output_->audio_params(); } void Sequence::set_audio_params(const AudioParams ¶ms) { - audio_params_ = params; - - if (viewer_output_ != nullptr) - viewer_output_->set_audio_params(audio_params_); + viewer_output_->set_audio_params(params); } void Sequence::set_default_parameters() diff --git a/app/project/item/sequence/sequence.h b/app/project/item/sequence/sequence.h index 6d271b80a..51e062985 100644 --- a/app/project/item/sequence/sequence.h +++ b/app/project/item/sequence/sequence.h @@ -62,10 +62,10 @@ public: virtual QString duration() override; virtual QString rate() override; - const VideoParams& video_params(); + const VideoParams& video_params() const; void set_video_params(const VideoParams& vparam); - const AudioParams& audio_params(); + const AudioParams& audio_params() const; void set_audio_params(const AudioParams& params); void set_default_parameters(); @@ -73,9 +73,6 @@ public: private: ViewerOutput* viewer_output_; - VideoParams video_params_; - - AudioParams audio_params_; }; #endif // SEQUENCE_H diff --git a/app/project/project.cpp b/app/project/project.cpp index fe737490b..24caec1e0 100644 --- a/app/project/project.cpp +++ b/app/project/project.cpp @@ -34,8 +34,23 @@ void Project::Load(QXmlStreamReader *reader) XMLReadLoop(reader, "project") { if (reader->isStartElement()) { if (reader->name() == "folder") { + // Assume this folder is our root root_.Load(reader); + + } else if (reader->name() == "colormanagement") { + + // Read color management info + XMLReadLoop(reader, "colormanagement") { + if (reader->name() == "config") { + reader->readNext(); + set_ocio_config(reader->text().toString()); + } else if (reader->name() == "default") { + reader->readNext(); + set_default_input_colorspace(reader->text().toString()); + } + } + } } } @@ -49,7 +64,13 @@ void Project::Save(QXmlStreamWriter *writer) const root_.Save(writer); - writer->writeTextElement("ocio", ocio_config_); + writer->writeStartElement("colormanagement"); + + writer->writeTextElement("config", ocio_config_); + + writer->writeTextElement("default", default_input_colorspace_); + + writer->writeEndElement(); // colormanagement writer->writeEndElement(); // project } diff --git a/app/project/projectloadmanager.cpp b/app/project/projectloadmanager.cpp index 0d138629c..ebb54f6df 100644 --- a/app/project/projectloadmanager.cpp +++ b/app/project/projectloadmanager.cpp @@ -30,6 +30,9 @@ void ProjectLoadManager::Start() project->Load(&reader); + // Ensure project is in main thread + moveToThread(qApp->thread()); + emit ProjectLoaded(project); } }