ensure objects are in the correct thread when loading
Since we load in a separate thread, when the QObject based objects are instantiated, they're created with affinity to that separate thread. Now we specifically ensure they are moved to the main thread after their creation.
This commit is contained in:
+4
-4
@@ -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);
|
||||
|
||||
|
||||
+26
-7
@@ -85,7 +85,7 @@ QString NodeInput::name()
|
||||
return NodeParam::name();
|
||||
}
|
||||
|
||||
void NodeInput::Load(QXmlStreamReader *reader)
|
||||
void NodeInput::Load(QXmlStreamReader *reader, QHash<quintptr, NodeOutput*>& param_ptrs, QList<SerializedConnection> &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<quintptr>(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<quintptr>(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<quintptr, NodeOutput *> ¶m_ptrs, QList<SerializedConnection> &input_connections)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -54,7 +54,7 @@ public:
|
||||
|
||||
virtual QString name() override;
|
||||
|
||||
virtual void Load(QXmlStreamReader* reader) override;
|
||||
virtual void Load(QXmlStreamReader* reader, QHash<quintptr, NodeOutput*>& param_ptrs, QList<SerializedConnection> &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<quintptr, NodeOutput*>& param_ptrs, QList<SerializedConnection> &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
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "inputarray.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#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<quintptr, NodeOutput*>& param_ptrs, QList<SerializedConnection> &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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ signals:
|
||||
void SizeChanged(int size);
|
||||
|
||||
protected:
|
||||
virtual void LoadInternal(QXmlStreamReader* reader) override;
|
||||
virtual void LoadInternal(QXmlStreamReader* reader, QHash<quintptr, NodeOutput *> ¶m_ptrs, QList<SerializedConnection> &input_connections) override;
|
||||
|
||||
virtual void SaveInternal(QXmlStreamWriter* writer) const override;
|
||||
|
||||
|
||||
+14
-13
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "node.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
||||
@@ -49,9 +50,9 @@ Node::~Node()
|
||||
}
|
||||
}
|
||||
|
||||
void Node::Load(QXmlStreamReader *reader)
|
||||
void Node::Load(QXmlStreamReader *reader, QHash<quintptr, NodeOutput *> &output_ptrs, QList<NodeInput::SerializedConnection>& 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<NodeInput*>(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)
|
||||
|
||||
+2
-2
@@ -68,12 +68,12 @@ public:
|
||||
/**
|
||||
* @brief Clear current node variables and replace them with
|
||||
*/
|
||||
void Load(QXmlStreamReader* reader);
|
||||
void Load(QXmlStreamReader* reader, QHash<quintptr, NodeOutput*>& param_ptrs, QList<NodeInput::SerializedConnection> &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
|
||||
|
||||
+9
-3
@@ -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<quintptr, NodeOutput*>& param_ptrs, QList<SerializedConnection> &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<quintptr>(this)));
|
||||
|
||||
SaveConnections(writer);
|
||||
|
||||
writer->writeEndElement(); // output
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
virtual QString name() override;
|
||||
|
||||
virtual void Load(QXmlStreamReader *reader) override;
|
||||
virtual void Load(QXmlStreamReader* reader, QHash<quintptr, NodeOutput*>& param_ptrs, QList<SerializedConnection> &input_connections) override;
|
||||
|
||||
virtual void Save(QXmlStreamWriter* writer) const override;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<quintptr>(other)));
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // connections
|
||||
}
|
||||
|
||||
+6
-3
@@ -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<quintptr, NodeOutput*>& param_ptrs, QList<SerializedConnection> &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
|
||||
*/
|
||||
|
||||
@@ -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<Folder>();
|
||||
@@ -62,12 +62,12 @@ void Folder::Load(QXmlStreamReader *reader)
|
||||
child = std::make_shared<Footage>();
|
||||
} else if (reader->name() == "sequence") {
|
||||
child = std::make_shared<Sequence>();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child) {
|
||||
child->Load(reader);
|
||||
add_child(child);
|
||||
}
|
||||
child->Load(reader);
|
||||
add_child(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ void Footage::Load(QXmlStreamReader *reader)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Probe here
|
||||
// FIXME: Probe here?
|
||||
|
||||
XMLReadLoop(reader, "footage") {
|
||||
if (reader->isStartElement()) {
|
||||
|
||||
@@ -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<quintptr, NodeOutput*> output_ptrs;
|
||||
QList<NodeParam::SerializedConnection> 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()
|
||||
|
||||
@@ -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
|
||||
|
||||
+22
-1
@@ -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
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ void ProjectLoadManager::Start()
|
||||
|
||||
project->Load(&reader);
|
||||
|
||||
// Ensure project is in main thread
|
||||
moveToThread(qApp->thread());
|
||||
|
||||
emit ProjectLoaded(project);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user