From 7c7db5c9331b6b1e98a46d4871ed15dcabe9f374 Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Sun, 27 Sep 2020 00:05:47 +0100 Subject: [PATCH] Check footage in use before deleteing Initial very hacky implementation that checks if the footgae is in use before deleting it and makes sure all refernences to it are properly cleaned up. Also added IsMedia() function to Node to simplify things a bit. --- app/node/input/media/audio/audio.cpp | 5 ++ app/node/input/media/audio/audio.h | 2 + app/node/input/media/media.cpp | 5 ++ app/node/input/media/media.h | 6 +++ app/node/input/media/video/video.cpp | 5 ++ app/node/input/media/video/video.h | 2 + app/node/node.cpp | 5 ++ app/node/node.h | 9 ++++ .../projectexplorer/projectexplorer.cpp | 51 +++++++++++++++++++ 9 files changed, 90 insertions(+) diff --git a/app/node/input/media/audio/audio.cpp b/app/node/input/media/audio/audio.cpp index 5f34543ec..49463aa22 100644 --- a/app/node/input/media/audio/audio.cpp +++ b/app/node/input/media/audio/audio.cpp @@ -27,6 +27,11 @@ Node *AudioInput::copy() const return new AudioInput(); } +Stream::Type AudioInput::type() const +{ + return Stream::kAudio; +} + QString AudioInput::Name() const { return tr("Audio Input"); diff --git a/app/node/input/media/audio/audio.h b/app/node/input/media/audio/audio.h index 62914b693..5cebdcc3c 100644 --- a/app/node/input/media/audio/audio.h +++ b/app/node/input/media/audio/audio.h @@ -32,6 +32,8 @@ public: virtual Node* copy() const override; + virtual Stream::Type type() const override; + virtual QString Name() const override; virtual QString ShortName() const override; virtual QString id() const override; diff --git a/app/node/input/media/media.cpp b/app/node/input/media/media.cpp index c0e1b3feb..8bfe11bb9 100644 --- a/app/node/input/media/media.cpp +++ b/app/node/input/media/media.cpp @@ -50,6 +50,11 @@ void MediaInput::SetFootage(StreamPtr f) footage_input_->set_standard_value(QVariant::fromValue(f)); } +bool MediaInput::IsMedia() const +{ + return true; +} + void MediaInput::Retranslate() { footage_input_->set_name(tr("Footage")); diff --git a/app/node/input/media/media.h b/app/node/input/media/media.h index ba89f3168..8934e321e 100644 --- a/app/node/input/media/media.h +++ b/app/node/input/media/media.h @@ -23,6 +23,7 @@ #include "codec/decoder.h" #include "node/node.h" +#include "project/item/footage/stream.h" OLIVE_NAMESPACE_ENTER @@ -35,11 +36,16 @@ class MediaInput : public Node public: MediaInput(); + virtual Stream::Type type() const = 0; + virtual QList Category() const override; StreamPtr footage(); void SetFootage(StreamPtr f); + virtual bool IsMedia() const override; + + virtual void Retranslate() override; virtual NodeValueTable Value(NodeValueDatabase& value) const override; diff --git a/app/node/input/media/video/video.cpp b/app/node/input/media/video/video.cpp index d451daeaf..c02aeaf39 100644 --- a/app/node/input/media/video/video.cpp +++ b/app/node/input/media/video/video.cpp @@ -36,6 +36,11 @@ Node *VideoInput::copy() const return new VideoInput(); } +Stream::Type VideoInput::type() const +{ + return Stream::kVideo; +} + QString VideoInput::Name() const { return tr("Video Input"); diff --git a/app/node/input/media/video/video.h b/app/node/input/media/video/video.h index 3ef9f54e8..7000ea82b 100644 --- a/app/node/input/media/video/video.h +++ b/app/node/input/media/video/video.h @@ -35,6 +35,8 @@ public: virtual Node* copy() const override; + virtual Stream::Type type() const override; + virtual QString Name() const override; virtual QString ShortName() const override; virtual QString id() const override; diff --git a/app/node/node.cpp b/app/node/node.cpp index 15e28512a..feda8c540 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -440,6 +440,11 @@ bool Node::IsTrack() const return false; } +bool Node::IsMedia() const +{ + return false; +} + const QList& Node::parameters() const { return params_; diff --git a/app/node/node.h b/app/node/node.h index ba05359ce..478d1e1ab 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -363,6 +363,15 @@ public: */ virtual bool IsTrack() const; + + /** + * @brief Returns whether this Node is a "Media" type or not + * + * You shouldn't ever need to override this since all derivatives of Media will automatically have this set to true. + * It's just a more convenient way of checking than dynamic_casting. + */ + virtual bool IsMedia() const; + /** * @brief The main processing function * diff --git a/app/widget/projectexplorer/projectexplorer.cpp b/app/widget/projectexplorer/projectexplorer.cpp index 0a1dd0ab7..b47cbbaa7 100644 --- a/app/widget/projectexplorer/projectexplorer.cpp +++ b/app/widget/projectexplorer/projectexplorer.cpp @@ -558,6 +558,57 @@ void ProjectExplorer::DeleteSelected() } } + if (item_ptr->type() == Item::kFootage) { + // Get all sequences + QList sequences = model_.project()->get_items_of_type(Item::kSequence); + + // If no sequences exist we don't need to do anything clever here + if (!sequences.isEmpty()) { + // Footage can contain multiple streams, all of which need to be dealt with + foreach (StreamPtr stream, static_cast(item_ptr.get())->streams()) { + + // Check each sequence to see if it contains the footage in question + foreach (ItemPtr seq, sequences) { + + Sequence* s = static_cast(seq.get()); + + // Loop through nodes to find our Footage node + foreach (Node* node, s->nodes()) { + + // Check if node is of the right type + if (node->IsMedia() && static_cast(node)->type() == stream.get()->type()) { + // Check the streams are the same + if (static_cast(node)->footage() == stream) { + // Loop through nodes and set any that point to the Footage node to null + foreach (Node* check_node, s->nodes()) { + // Skip itself + if (check_node == node) { + continue; + } + if (check_node->GetImmediateDependencies().contains(node)) { + QList inputs = check_node->GetInputsIncludingArrays(); + + foreach (NodeInput* input, inputs) { + foreach (NodeEdgePtr edge, input->edges()) { + Node* connected = edge->output()->parentNode(); + + if (connected == node) { + input->DisconnectEdge(edge); + } + } + } + } + } + static_cast(node)->SetFootage(nullptr); + break; + } + } + } + } + } + } + } + new ProjectViewModel::RemoveItemCommand(&model_, item_ptr, command); }