remove shifts, operations, and make caches node-agnostic
This commit is contained in:
+7
-19
@@ -48,11 +48,13 @@ Node::Node() :
|
|||||||
can_be_deleted_(true),
|
can_be_deleted_(true),
|
||||||
override_color_(-1),
|
override_color_(-1),
|
||||||
folder_(nullptr),
|
folder_(nullptr),
|
||||||
operation_stack_(0),
|
|
||||||
cache_result_(false),
|
cache_result_(false),
|
||||||
flags_(kNone)
|
flags_(kNone)
|
||||||
{
|
{
|
||||||
AddInput(kEnabledInput, NodeValue::kBoolean, true);
|
AddInput(kEnabledInput, NodeValue::kBoolean, true);
|
||||||
|
|
||||||
|
video_cache_ = new FrameHashCache(this);
|
||||||
|
audio_cache_ = new AudioPlaybackCache(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::~Node()
|
Node::~Node()
|
||||||
@@ -933,18 +935,6 @@ void Node::InvalidateCache(const TimeRange &range, const QString &from, int elem
|
|||||||
SendInvalidateCache(range, options);
|
SendInvalidateCache(range, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::BeginOperation()
|
|
||||||
{
|
|
||||||
// Increase operation stack
|
|
||||||
operation_stack_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Node::EndOperation()
|
|
||||||
{
|
|
||||||
// Decrease operation stack
|
|
||||||
operation_stack_--;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeRange Node::InputTimeAdjustment(const QString &, int, const TimeRange &input_time) const
|
TimeRange Node::InputTimeAdjustment(const QString &, int, const TimeRange &input_time) const
|
||||||
{
|
{
|
||||||
// Default behavior is no time adjustment at all
|
// Default behavior is no time adjustment at all
|
||||||
@@ -1118,13 +1108,11 @@ Node *Node::CopyNodeInGraph(Node *node, MultiUndoCommand *command)
|
|||||||
|
|
||||||
void Node::SendInvalidateCache(const TimeRange &range, const InvalidateCacheOptions &options)
|
void Node::SendInvalidateCache(const TimeRange &range, const InvalidateCacheOptions &options)
|
||||||
{
|
{
|
||||||
if (GetOperationStack() == 0) {
|
for (const OutputConnection& conn : output_connections_) {
|
||||||
for (const OutputConnection& conn : output_connections_) {
|
// Send clear cache signal to the Node
|
||||||
// Send clear cache signal to the Node
|
const NodeInput& in = conn.second;
|
||||||
const NodeInput& in = conn.second;
|
|
||||||
|
|
||||||
in.node()->InvalidateCache(range, in.input(), in.element(), options);
|
in.node()->InvalidateCache(range, in.input(), in.element(), options);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-20
@@ -39,6 +39,8 @@
|
|||||||
#include "node/inputimmediate.h"
|
#include "node/inputimmediate.h"
|
||||||
#include "node/param.h"
|
#include "node/param.h"
|
||||||
#include "render/audioparams.h"
|
#include "render/audioparams.h"
|
||||||
|
#include "render/audioplaybackcache.h"
|
||||||
|
#include "render/framehashcache.h"
|
||||||
#include "render/job/generatejob.h"
|
#include "render/job/generatejob.h"
|
||||||
#include "render/job/samplejob.h"
|
#include "render/job/samplejob.h"
|
||||||
#include "render/job/shaderjob.h"
|
#include "render/job/shaderjob.h"
|
||||||
@@ -219,6 +221,16 @@ public:
|
|||||||
return HasInputWithID(id);
|
return HasInputWithID(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameHashCache* video_frame_cache() const
|
||||||
|
{
|
||||||
|
return video_cache_;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioPlaybackCache* audio_playback_cache() const
|
||||||
|
{
|
||||||
|
return audio_cache_;
|
||||||
|
}
|
||||||
|
|
||||||
struct Position
|
struct Position
|
||||||
{
|
{
|
||||||
Position(const QPointF &p = QPointF(0, 0), bool e = false)
|
Position(const QPointF &p = QPointF(0, 0), bool e = false)
|
||||||
@@ -798,19 +810,6 @@ public:
|
|||||||
InvalidateCache(range, from.input(), from.element(), options);
|
InvalidateCache(range, from.input(), from.element(), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Limits cache invalidation temporarily
|
|
||||||
*
|
|
||||||
* If you intend to do a number of operations in quick succession, you can optimize it by running
|
|
||||||
* this function with EndOperation().
|
|
||||||
*/
|
|
||||||
virtual void BeginOperation();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Stops limiting cache invalidation and flushes changes
|
|
||||||
*/
|
|
||||||
virtual void EndOperation();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adjusts time that should be sent to nodes connected to certain inputs.
|
* @brief Adjusts time that should be sent to nodes connected to certain inputs.
|
||||||
*
|
*
|
||||||
@@ -1030,11 +1029,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void IgnoreInvalidationsFrom(const QString &input_id);
|
void IgnoreInvalidationsFrom(const QString &input_id);
|
||||||
|
|
||||||
int GetOperationStack() const
|
|
||||||
{
|
|
||||||
return operation_stack_;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GizmoScaleHandles {
|
enum GizmoScaleHandles {
|
||||||
kGizmoScaleTopLeft,
|
kGizmoScaleTopLeft,
|
||||||
kGizmoScaleTopCenter,
|
kGizmoScaleTopCenter,
|
||||||
@@ -1392,8 +1386,6 @@ private:
|
|||||||
|
|
||||||
Folder* folder_;
|
Folder* folder_;
|
||||||
|
|
||||||
int operation_stack_;
|
|
||||||
|
|
||||||
bool cache_result_;
|
bool cache_result_;
|
||||||
|
|
||||||
QMap<InputElementPair, ValueHint> value_hints_;
|
QMap<InputElementPair, ValueHint> value_hints_;
|
||||||
@@ -1406,6 +1398,10 @@ private:
|
|||||||
|
|
||||||
QString effect_input_;
|
QString effect_input_;
|
||||||
|
|
||||||
|
FrameHashCache *video_cache_;
|
||||||
|
|
||||||
|
AudioPlaybackCache *audio_cache_;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
/**
|
/**
|
||||||
* @brief Slot when a keyframe's time changes to keep the keyframes correctly sorted by time
|
* @brief Slot when a keyframe's time changes to keep the keyframes correctly sorted by time
|
||||||
|
|||||||
@@ -406,10 +406,6 @@ QVector<Block *> Track::BlocksAtTimeRange(const TimeRange &range) const
|
|||||||
|
|
||||||
void Track::InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options)
|
void Track::InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options)
|
||||||
{
|
{
|
||||||
if (GetOperationStack() != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeRange limited;
|
TimeRange limited;
|
||||||
|
|
||||||
const Block* b;
|
const Block* b;
|
||||||
@@ -465,69 +461,49 @@ void Track::InsertBlockAfter(Block *block, Block *before)
|
|||||||
|
|
||||||
void Track::PrependBlock(Block *block)
|
void Track::PrependBlock(Block *block)
|
||||||
{
|
{
|
||||||
BeginOperation();
|
|
||||||
|
|
||||||
InputArrayPrepend(kBlockInput);
|
InputArrayPrepend(kBlockInput);
|
||||||
Node::ConnectEdge(block, NodeInput(this, kBlockInput, 0));
|
Node::ConnectEdge(block, NodeInput(this, kBlockInput, 0));
|
||||||
|
|
||||||
EndOperation();
|
|
||||||
|
|
||||||
// Everything has shifted at this point
|
// Everything has shifted at this point
|
||||||
Node::InvalidateCache(TimeRange(0, track_length()), kBlockInput);
|
Node::InvalidateCache(TimeRange(0, track_length()), kBlockInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Track::InsertBlockAtIndex(Block *block, int index)
|
void Track::InsertBlockAtIndex(Block *block, int index)
|
||||||
{
|
{
|
||||||
BeginOperation();
|
|
||||||
|
|
||||||
int insert_index = GetArrayIndexFromCacheIndex(index);
|
int insert_index = GetArrayIndexFromCacheIndex(index);
|
||||||
InputArrayInsert(kBlockInput, insert_index);
|
InputArrayInsert(kBlockInput, insert_index);
|
||||||
Node::ConnectEdge(block, NodeInput(this, kBlockInput, insert_index));
|
Node::ConnectEdge(block, NodeInput(this, kBlockInput, insert_index));
|
||||||
|
|
||||||
EndOperation();
|
|
||||||
|
|
||||||
Node::InvalidateCache(TimeRange(block->in(), track_length()), kBlockInput);
|
Node::InvalidateCache(TimeRange(block->in(), track_length()), kBlockInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Track::AppendBlock(Block *block)
|
void Track::AppendBlock(Block *block)
|
||||||
{
|
{
|
||||||
BeginOperation();
|
|
||||||
|
|
||||||
InputArrayAppend(kBlockInput);
|
InputArrayAppend(kBlockInput);
|
||||||
Node::ConnectEdge(block, NodeInput(this, kBlockInput, InputArraySize(kBlockInput) - 1));
|
Node::ConnectEdge(block, NodeInput(this, kBlockInput, InputArraySize(kBlockInput) - 1));
|
||||||
|
|
||||||
EndOperation();
|
|
||||||
|
|
||||||
// Invalidate area that block was added to
|
// Invalidate area that block was added to
|
||||||
Node::InvalidateCache(TimeRange(block->in(), block->out()), kBlockInput);
|
Node::InvalidateCache(TimeRange(block->in(), block->out()), kBlockInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Track::RippleRemoveBlock(Block *block)
|
void Track::RippleRemoveBlock(Block *block)
|
||||||
{
|
{
|
||||||
BeginOperation();
|
|
||||||
|
|
||||||
rational remove_in = block->in();
|
rational remove_in = block->in();
|
||||||
rational remove_out = block->out();
|
rational remove_out = block->out();
|
||||||
|
|
||||||
InputArrayRemove(kBlockInput, GetArrayIndexFromBlock(block));
|
InputArrayRemove(kBlockInput, GetArrayIndexFromBlock(block));
|
||||||
|
|
||||||
EndOperation();
|
|
||||||
|
|
||||||
Node::InvalidateCache(TimeRange(remove_in, qMax(track_length(), remove_out)), kBlockInput);
|
Node::InvalidateCache(TimeRange(remove_in, qMax(track_length(), remove_out)), kBlockInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Track::ReplaceBlock(Block *old, Block *replace)
|
void Track::ReplaceBlock(Block *old, Block *replace)
|
||||||
{
|
{
|
||||||
BeginOperation();
|
|
||||||
|
|
||||||
int index_of_old_block = GetArrayIndexFromBlock(old);
|
int index_of_old_block = GetArrayIndexFromBlock(old);
|
||||||
|
|
||||||
DisconnectEdge(old, NodeInput(this, kBlockInput, index_of_old_block));
|
DisconnectEdge(old, NodeInput(this, kBlockInput, index_of_old_block));
|
||||||
|
|
||||||
ConnectEdge(replace, NodeInput(this, kBlockInput, index_of_old_block));
|
ConnectEdge(replace, NodeInput(this, kBlockInput, index_of_old_block));
|
||||||
|
|
||||||
EndOperation();
|
|
||||||
|
|
||||||
if (old->length() == replace->length()) {
|
if (old->length() == replace->length()) {
|
||||||
Node::InvalidateCache(TimeRange(replace->in(), replace->out()), kBlockInput);
|
Node::InvalidateCache(TimeRange(replace->in(), replace->out()), kBlockInput);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ ViewerOutput::ViewerOutput(bool create_buffer_inputs, bool create_default_stream
|
|||||||
last_length_(0),
|
last_length_(0),
|
||||||
video_length_(0),
|
video_length_(0),
|
||||||
audio_length_(0),
|
audio_length_(0),
|
||||||
video_frame_cache_(this),
|
|
||||||
audio_playback_cache_(this),
|
|
||||||
video_cache_enabled_(true),
|
video_cache_enabled_(true),
|
||||||
audio_cache_enabled_(true)
|
audio_cache_enabled_(true)
|
||||||
{
|
{
|
||||||
@@ -229,30 +227,6 @@ void ViewerOutput::set_default_parameters()
|
|||||||
SetVideoAutoCacheEnabled(OLIVE_CONFIG("DefaultSequenceAutoCache").toBool());
|
SetVideoAutoCacheEnabled(OLIVE_CONFIG("DefaultSequenceAutoCache").toBool());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewerOutput::ShiftVideoCache(const rational &from, const rational &to)
|
|
||||||
{
|
|
||||||
if (video_cache_enabled_) {
|
|
||||||
video_frame_cache_.Shift(from, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShiftVideoEvent(from, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewerOutput::ShiftAudioCache(const rational &from, const rational &to)
|
|
||||||
{
|
|
||||||
if (audio_cache_enabled_) {
|
|
||||||
audio_playback_cache_.Shift(from, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShiftAudioEvent(from, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewerOutput::ShiftCache(const rational &from, const rational &to)
|
|
||||||
{
|
|
||||||
ShiftVideoCache(from, to);
|
|
||||||
ShiftAudioCache(from, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewerOutput::InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options)
|
void ViewerOutput::InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options)
|
||||||
{
|
{
|
||||||
Q_UNUSED(element)
|
Q_UNUSED(element)
|
||||||
@@ -264,9 +238,9 @@ void ViewerOutput::InvalidateCache(const TimeRange& range, const QString& from,
|
|||||||
|
|
||||||
if (invalidated_range.in() != invalidated_range.out()) {
|
if (invalidated_range.in() != invalidated_range.out()) {
|
||||||
if (from == kTextureInput || from == kVideoParamsInput) {
|
if (from == kTextureInput || from == kVideoParamsInput) {
|
||||||
video_frame_cache_.Invalidate(invalidated_range);
|
video_frame_cache()->Invalidate(invalidated_range);
|
||||||
} else {
|
} else {
|
||||||
audio_playback_cache_.Invalidate(invalidated_range);
|
audio_playback_cache()->Invalidate(invalidated_range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,7 +428,7 @@ void ViewerOutput::InputValueChangedEvent(const QString &input, int element)
|
|||||||
|
|
||||||
if (frame_rate_changed) {
|
if (frame_rate_changed) {
|
||||||
if (video_cache_enabled_) {
|
if (video_cache_enabled_) {
|
||||||
video_frame_cache_.SetTimebase(new_video_params.frame_rate_as_time_base());
|
video_frame_cache()->SetTimebase(new_video_params.frame_rate_as_time_base());
|
||||||
}
|
}
|
||||||
emit FrameRateChanged(new_video_params.frame_rate());
|
emit FrameRateChanged(new_video_params.frame_rate());
|
||||||
}
|
}
|
||||||
@@ -476,7 +450,7 @@ void ViewerOutput::InputValueChangedEvent(const QString &input, int element)
|
|||||||
emit AudioParamsChanged();
|
emit AudioParamsChanged();
|
||||||
|
|
||||||
if (audio_cache_enabled_) {
|
if (audio_cache_enabled_) {
|
||||||
audio_playback_cache_.SetParameters(GetAudioParams());
|
audio_playback_cache()->SetParameters(GetAudioParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
cached_audio_params_ = new_audio_params;
|
cached_audio_params_ = new_audio_params;
|
||||||
@@ -487,18 +461,6 @@ void ViewerOutput::InputValueChangedEvent(const QString &input, int element)
|
|||||||
super::InputValueChangedEvent(input, element);
|
super::InputValueChangedEvent(input, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewerOutput::ShiftVideoEvent(const rational &from, const rational &to)
|
|
||||||
{
|
|
||||||
Q_UNUSED(from)
|
|
||||||
Q_UNUSED(to)
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewerOutput::ShiftAudioEvent(const rational &from, const rational &to)
|
|
||||||
{
|
|
||||||
Q_UNUSED(from)
|
|
||||||
Q_UNUSED(to)
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewerOutput::set_parameters_from_footage(const QVector<ViewerOutput *> footage)
|
void ViewerOutput::set_parameters_from_footage(const QVector<ViewerOutput *> footage)
|
||||||
{
|
{
|
||||||
foreach (ViewerOutput* f, footage) {
|
foreach (ViewerOutput* f, footage) {
|
||||||
|
|||||||
@@ -60,10 +60,6 @@ public:
|
|||||||
|
|
||||||
void set_parameters_from_footage(const QVector<ViewerOutput *> footage);
|
void set_parameters_from_footage(const QVector<ViewerOutput *> footage);
|
||||||
|
|
||||||
void ShiftVideoCache(const rational& from, const rational& to);
|
|
||||||
void ShiftAudioCache(const rational& from, const rational& to);
|
|
||||||
void ShiftCache(const rational& from, const rational& to);
|
|
||||||
|
|
||||||
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options) override;
|
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options) override;
|
||||||
|
|
||||||
VideoParams GetVideoParams(int index = 0) const
|
VideoParams GetVideoParams(int index = 0) const
|
||||||
@@ -146,16 +142,6 @@ public:
|
|||||||
const rational &GetVideoLength() const { return video_length_; }
|
const rational &GetVideoLength() const { return video_length_; }
|
||||||
const rational &GetAudioLength() const { return audio_length_; }
|
const rational &GetAudioLength() const { return audio_length_; }
|
||||||
|
|
||||||
FrameHashCache* video_frame_cache()
|
|
||||||
{
|
|
||||||
return &video_frame_cache_;
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioPlaybackCache* audio_playback_cache()
|
|
||||||
{
|
|
||||||
return &audio_playback_cache_;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimelinePoints* GetTimelinePoints()
|
TimelinePoints* GetTimelinePoints()
|
||||||
{
|
{
|
||||||
return timeline_points_;
|
return timeline_points_;
|
||||||
@@ -253,10 +239,6 @@ protected:
|
|||||||
|
|
||||||
virtual rational VerifyLengthInternal(Track::Type type) const;
|
virtual rational VerifyLengthInternal(Track::Type type) const;
|
||||||
|
|
||||||
virtual void ShiftVideoEvent(const rational &from, const rational &to);
|
|
||||||
|
|
||||||
virtual void ShiftAudioEvent(const rational &from, const rational &to);
|
|
||||||
|
|
||||||
virtual void InputValueChangedEvent(const QString& input, int element) override;
|
virtual void InputValueChangedEvent(const QString& input, int element) override;
|
||||||
|
|
||||||
int AddStream(Track::Type type, const QVariant &value);
|
int AddStream(Track::Type type, const QVariant &value);
|
||||||
@@ -266,10 +248,6 @@ private:
|
|||||||
rational video_length_;
|
rational video_length_;
|
||||||
rational audio_length_;
|
rational audio_length_;
|
||||||
|
|
||||||
FrameHashCache video_frame_cache_;
|
|
||||||
|
|
||||||
AudioPlaybackCache audio_playback_cache_;
|
|
||||||
|
|
||||||
VideoParams cached_video_params_;
|
VideoParams cached_video_params_;
|
||||||
|
|
||||||
AudioParams cached_audio_params_;
|
AudioParams cached_audio_params_;
|
||||||
|
|||||||
@@ -170,108 +170,6 @@ void AudioPlaybackCache::WriteSilence(const TimeRange &range)
|
|||||||
WritePCM(range, {range}, SampleBuffer());
|
WritePCM(range, {range}, SampleBuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlaybackCache::ShiftEvent(const rational &from_in_time, const rational &to_in_time)
|
|
||||||
{
|
|
||||||
visual_.Shift(from_in_time, to_in_time);
|
|
||||||
|
|
||||||
qint64 to = params_.time_to_bytes_per_channel(to_in_time);
|
|
||||||
qint64 from = params_.time_to_bytes_per_channel(from_in_time);
|
|
||||||
|
|
||||||
if (from >= playlist_.GetLength()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int to_seg_index = playlist_.GetIndexOfPosition(to);
|
|
||||||
int from_seg_index = playlist_.GetIndexOfPosition(from);
|
|
||||||
|
|
||||||
qint64 from_seg_start = playlist_.at(from_seg_index).offset();
|
|
||||||
qint64 from_seg_end = playlist_.at(from_seg_index).end();
|
|
||||||
|
|
||||||
if (from < to) {
|
|
||||||
// Shifting forwards, we must insert a new region and split a segment in half if necessary
|
|
||||||
int insert_index;
|
|
||||||
|
|
||||||
// Determine at what part of the array we'll be insert into
|
|
||||||
if (from == from_seg_start) {
|
|
||||||
insert_index = from_seg_index;
|
|
||||||
} else {
|
|
||||||
insert_index = from_seg_index + 1;
|
|
||||||
|
|
||||||
if (from < from_seg_end) {
|
|
||||||
// Split from segment into two
|
|
||||||
Segment second = CloneSegment(playlist_.at(from_seg_index));
|
|
||||||
|
|
||||||
TrimSegmentOut(&playlist_[from_seg_index], from - from_seg_start);
|
|
||||||
TrimSegmentIn(&second, from_seg_end - from);
|
|
||||||
|
|
||||||
playlist_.insert(insert_index, second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert silent segments
|
|
||||||
qint64 time_to_insert = to - from;
|
|
||||||
|
|
||||||
while (time_to_insert) {
|
|
||||||
qint64 new_seg_sz = qMin(kDefaultSegmentSizePerChannel, time_to_insert);
|
|
||||||
|
|
||||||
// Set offset to 0 for now and fill it in later
|
|
||||||
playlist_.insert(insert_index, CreateSegment(new_seg_sz, 0));
|
|
||||||
|
|
||||||
time_to_insert -= new_seg_sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateOffsetsFrom(insert_index);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Shifting backwards, we'll be removing segments and truncating them if necessary
|
|
||||||
qint64 to_seg_start = playlist_.at(to_seg_index).offset();
|
|
||||||
qint64 to_seg_end = playlist_.at(to_seg_index).end();
|
|
||||||
|
|
||||||
if (to_seg_index == from_seg_index) {
|
|
||||||
if (to > to_seg_start && from < from_seg_end) {
|
|
||||||
// Duplicate segment into two segments and trim each side to move the space in between
|
|
||||||
Segment second = CloneSegment(playlist_.at(to_seg_index));
|
|
||||||
from_seg_index++;
|
|
||||||
playlist_.insert(from_seg_index, second);
|
|
||||||
|
|
||||||
TrimSegmentOut(&playlist_[to_seg_index], to - to_seg_start);
|
|
||||||
TrimSegmentIn(&playlist_[from_seg_index], to_seg_end - from);
|
|
||||||
} else if (to == to_seg_start && from == from_seg_end) {
|
|
||||||
// Segment contains entire shift area, just remove it
|
|
||||||
RemoveSegmentFromArray(to_seg_index);
|
|
||||||
} else if (to == to_seg_start) {
|
|
||||||
// Trim segment in
|
|
||||||
TrimSegmentIn(&playlist_[to_seg_index], to_seg_end - from);
|
|
||||||
} else {
|
|
||||||
// Assume from == to_seg_end
|
|
||||||
TrimSegmentOut(&playlist_[to_seg_index], to_seg_end - to);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Remove any segments between if there are any
|
|
||||||
while (from_seg_index != to_seg_index+1) {
|
|
||||||
RemoveSegmentFromArray(to_seg_index+1);
|
|
||||||
from_seg_index--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from == from_seg_end) {
|
|
||||||
RemoveSegmentFromArray(from_seg_index);
|
|
||||||
} else {
|
|
||||||
// Assume from > from_seg_start and trim its in point
|
|
||||||
TrimSegmentIn(&playlist_[from_seg_index], from_seg_end - from);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to == to_seg_start) {
|
|
||||||
// Assume from >= to_seg_end, remove "to" segment
|
|
||||||
RemoveSegmentFromArray(to_seg_index);
|
|
||||||
} else {
|
|
||||||
TrimSegmentOut(&playlist_[to_seg_index], to_seg_end - to);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateOffsetsFrom(to_seg_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioPlaybackCache::Segment AudioPlaybackCache::CloneSegment(const AudioPlaybackCache::Segment &s) const
|
AudioPlaybackCache::Segment AudioPlaybackCache::CloneSegment(const AudioPlaybackCache::Segment &s) const
|
||||||
{
|
{
|
||||||
Segment new_seg = s;
|
Segment new_seg = s;
|
||||||
@@ -318,9 +216,11 @@ QString AudioPlaybackCache::GenerateSegmentFilename() const
|
|||||||
{
|
{
|
||||||
QString new_seg_filename;
|
QString new_seg_filename;
|
||||||
|
|
||||||
|
QDir cache_dir(QDir(GetCacheDirectory()).filePath(GetUuid().toString()));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
uint32_t r = QRandomGenerator::global()->generate();
|
uint32_t r = QRandomGenerator::global()->generate();
|
||||||
new_seg_filename = QDir(GetCacheDirectory()).filePath(QStringLiteral("%1.pcm").arg(r));
|
new_seg_filename = cache_dir.filePath(QStringLiteral("%1.pcm").arg(r));
|
||||||
} while (QFileInfo::exists(new_seg_filename));
|
} while (QFileInfo::exists(new_seg_filename));
|
||||||
|
|
||||||
return new_seg_filename;
|
return new_seg_filename;
|
||||||
@@ -402,7 +302,7 @@ AudioPlaybackCache::PlaybackDevice *AudioPlaybackCache::CreatePlaybackDevice(QOb
|
|||||||
PlaybackDevice *d = new PlaybackDevice(playlist_, params_.bytes_per_sample_per_channel(), parent);
|
PlaybackDevice *d = new PlaybackDevice(playlist_, params_.bytes_per_sample_per_channel(), parent);
|
||||||
|
|
||||||
// If we're child of a viewer, set the data limit so audio doesn't play beyond the length
|
// If we're child of a viewer, set the data limit so audio doesn't play beyond the length
|
||||||
if (ViewerOutput *viewer = viewer_parent()) {
|
if (ViewerOutput *viewer = dynamic_cast<ViewerOutput*>(this->parent())) {
|
||||||
d->SetDataLimit(params_.time_to_bytes_per_channel(viewer->GetAudioLength()));
|
d->SetDataLimit(params_.time_to_bytes_per_channel(viewer->GetAudioLength()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,9 +208,6 @@ public:
|
|||||||
signals:
|
signals:
|
||||||
void ParametersChanged();
|
void ParametersChanged();
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void ShiftEvent(const rational& from, const rational& to) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const qint64 kDefaultSegmentSizePerChannel;
|
static const qint64 kDefaultSegmentSizePerChannel;
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ void FrameHashCache::ValidateTime(const rational &time)
|
|||||||
|
|
||||||
bool FrameHashCache::SaveCacheFrame(const int64_t &time, FramePtr frame) const
|
bool FrameHashCache::SaveCacheFrame(const int64_t &time, FramePtr frame) const
|
||||||
{
|
{
|
||||||
return SaveCacheFrame(GetCacheDirectory(), uuid_, time, frame);
|
return SaveCacheFrame(GetCacheDirectory(), GetUuid(), time, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FrameHashCache::SaveCacheFrame(const QString &cache_path, const QUuid &uuid, const int64_t &time, FramePtr frame)
|
bool FrameHashCache::SaveCacheFrame(const QString &cache_path, const QUuid &uuid, const int64_t &time, FramePtr frame)
|
||||||
@@ -125,7 +125,7 @@ FramePtr FrameHashCache::LoadCacheFrame(const QString &cache_path, const QUuid &
|
|||||||
|
|
||||||
FramePtr FrameHashCache::LoadCacheFrame(const int64_t &hash) const
|
FramePtr FrameHashCache::LoadCacheFrame(const int64_t &hash) const
|
||||||
{
|
{
|
||||||
return LoadCacheFrame(GetCacheDirectory(), uuid_, hash);
|
return LoadCacheFrame(GetCacheDirectory(), GetUuid(), hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
|
FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
|
||||||
@@ -212,7 +212,7 @@ void FrameHashCache::HashDeleted(const QString& path, const QString &filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QFileInfo info(filename);
|
QFileInfo info(filename);
|
||||||
if (uuid_.toString() != info.dir().dirName()) {
|
if (GetUuid().toString() != info.dir().dirName()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,12 +229,12 @@ void FrameHashCache::ProjectInvalidated(Project *p)
|
|||||||
|
|
||||||
QString FrameHashCache::CachePathName(const int64_t &time) const
|
QString FrameHashCache::CachePathName(const int64_t &time) const
|
||||||
{
|
{
|
||||||
return CachePathName(GetCacheDirectory(), uuid_, time);
|
return CachePathName(GetCacheDirectory(), GetUuid(), time);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FrameHashCache::CachePathName(const rational &time) const
|
QString FrameHashCache::CachePathName(const rational &time) const
|
||||||
{
|
{
|
||||||
return CachePathName(GetCacheDirectory(), uuid_, time, timebase_);
|
return CachePathName(GetCacheDirectory(), GetUuid(), time, timebase_);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FrameHashCache::CachePathName(const QString &cache_path, const QUuid &cache_id, const int64_t &time)
|
QString FrameHashCache::CachePathName(const QString &cache_path, const QUuid &cache_id, const int64_t &time)
|
||||||
|
|||||||
@@ -21,9 +21,6 @@
|
|||||||
#ifndef VIDEORENDERFRAMECACHE_H
|
#ifndef VIDEORENDERFRAMECACHE_H
|
||||||
#define VIDEORENDERFRAMECACHE_H
|
#define VIDEORENDERFRAMECACHE_H
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QUuid>
|
|
||||||
|
|
||||||
#include "common/rational.h"
|
#include "common/rational.h"
|
||||||
#include "common/timecodefunctions.h"
|
#include "common/timecodefunctions.h"
|
||||||
#include "common/timerange.h"
|
#include "common/timerange.h"
|
||||||
@@ -39,9 +36,6 @@ class FrameHashCache : public PlaybackCache
|
|||||||
public:
|
public:
|
||||||
FrameHashCache(QObject* parent = nullptr);
|
FrameHashCache(QObject* parent = nullptr);
|
||||||
|
|
||||||
const QUuid &GetUuid() const { return uuid_; }
|
|
||||||
void SetUuid(const QUuid &u) { uuid_ = u; }
|
|
||||||
|
|
||||||
const rational &GetTimebase() const { return timebase_; }
|
const rational &GetTimebase() const { return timebase_; }
|
||||||
|
|
||||||
void SetTimebase(const rational& tb);
|
void SetTimebase(const rational& tb);
|
||||||
@@ -86,8 +80,6 @@ private:
|
|||||||
|
|
||||||
rational timebase_;
|
rational timebase_;
|
||||||
|
|
||||||
QUuid uuid_;
|
|
||||||
|
|
||||||
static const QString kCacheFormatExtension;
|
static const QString kCacheFormatExtension;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
@@ -43,40 +43,16 @@ void PlaybackCache::Invalidate(const TimeRange &r, bool signal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node *PlaybackCache::parent() const
|
||||||
|
{
|
||||||
|
return dynamic_cast<Node*>(QObject::parent());
|
||||||
|
}
|
||||||
|
|
||||||
void PlaybackCache::InvalidateAll()
|
void PlaybackCache::InvalidateAll()
|
||||||
{
|
{
|
||||||
Invalidate(TimeRange(0, RATIONAL_MAX));
|
Invalidate(TimeRange(0, RATIONAL_MAX));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaybackCache::Shift(rational from, rational to)
|
|
||||||
{
|
|
||||||
if (from == to) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// An region between `from` and `to` will be inserted or spliced out
|
|
||||||
TimeRangeList ranges_to_shift = validated_.Intersects(TimeRange(from, RATIONAL_MAX));
|
|
||||||
|
|
||||||
// Remove all ranges starting at to
|
|
||||||
validated_.remove(TimeRange(qMin(from, to), RATIONAL_MAX));
|
|
||||||
|
|
||||||
// Restore ranges shifted
|
|
||||||
rational diff = to - from;
|
|
||||||
foreach (const TimeRange& r, ranges_to_shift) {
|
|
||||||
validated_.insert(r + diff);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell derivatives that a shift has occurred
|
|
||||||
ShiftEvent(from, to);
|
|
||||||
|
|
||||||
// Emit signals
|
|
||||||
emit Shifted(from, to);
|
|
||||||
|
|
||||||
if (diff > 0) {
|
|
||||||
//emit Invalidated(TimeRange(from, to));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlaybackCache::Validate(const TimeRange &r, bool signal)
|
void PlaybackCache::Validate(const TimeRange &r, bool signal)
|
||||||
{
|
{
|
||||||
validated_.insert(r);
|
validated_.insert(r);
|
||||||
@@ -90,15 +66,17 @@ void PlaybackCache::InvalidateEvent(const TimeRange &)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaybackCache::ShiftEvent(const rational &, const rational &)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Project *PlaybackCache::GetProject() const
|
Project *PlaybackCache::GetProject() const
|
||||||
{
|
{
|
||||||
return Project::GetProjectFromObject(this);
|
return Project::GetProjectFromObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlaybackCache::PlaybackCache(QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
uuid_ = QUuid::createUuid();
|
||||||
|
}
|
||||||
|
|
||||||
TimeRangeList PlaybackCache::GetInvalidatedRanges(TimeRange intersecting)
|
TimeRangeList PlaybackCache::GetInvalidatedRanges(TimeRange intersecting)
|
||||||
{
|
{
|
||||||
TimeRangeList invalidated;
|
TimeRangeList invalidated;
|
||||||
@@ -133,9 +111,4 @@ QString PlaybackCache::GetCacheDirectory() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewerOutput *PlaybackCache::viewer_parent() const
|
|
||||||
{
|
|
||||||
return dynamic_cast<ViewerOutput*>(parent());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-13
@@ -21,14 +21,15 @@
|
|||||||
#ifndef PLAYBACKCACHE_H
|
#ifndef PLAYBACKCACHE_H
|
||||||
#define PLAYBACKCACHE_H
|
#define PLAYBACKCACHE_H
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
#include "common/jobtime.h"
|
#include "common/jobtime.h"
|
||||||
#include "common/timerange.h"
|
#include "common/timerange.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
|
class Node;
|
||||||
class Project;
|
class Project;
|
||||||
class ViewerOutput;
|
class ViewerOutput;
|
||||||
|
|
||||||
@@ -36,10 +37,10 @@ class PlaybackCache : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
PlaybackCache(QObject* parent = nullptr) :
|
PlaybackCache(QObject* parent = nullptr);
|
||||||
QObject(parent)
|
|
||||||
{
|
const QUuid &GetUuid() const { return uuid_; }
|
||||||
}
|
void SetUuid(const QUuid &u) { uuid_ = u; }
|
||||||
|
|
||||||
TimeRangeList GetInvalidatedRanges(TimeRange intersecting);
|
TimeRangeList GetInvalidatedRanges(TimeRange intersecting);
|
||||||
TimeRangeList GetInvalidatedRanges(const rational &length)
|
TimeRangeList GetInvalidatedRanges(const rational &length)
|
||||||
@@ -55,36 +56,32 @@ public:
|
|||||||
|
|
||||||
QString GetCacheDirectory() const;
|
QString GetCacheDirectory() const;
|
||||||
|
|
||||||
ViewerOutput *viewer_parent() const;
|
|
||||||
|
|
||||||
void Invalidate(const TimeRange& r, bool signal = true);
|
void Invalidate(const TimeRange& r, bool signal = true);
|
||||||
|
|
||||||
const TimeRangeList &GetValidatedRanges() const { return validated_; }
|
const TimeRangeList &GetValidatedRanges() const { return validated_; }
|
||||||
|
|
||||||
|
Node *parent() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void InvalidateAll();
|
void InvalidateAll();
|
||||||
|
|
||||||
void Shift(rational from, rational to);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Invalidated(const olive::TimeRange& r);
|
void Invalidated(const olive::TimeRange& r);
|
||||||
|
|
||||||
void Validated(const olive::TimeRange& r);
|
void Validated(const olive::TimeRange& r);
|
||||||
|
|
||||||
void Shifted(const olive::rational& from, const olive::rational& to);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Validate(const TimeRange& r, bool signal = true);
|
void Validate(const TimeRange& r, bool signal = true);
|
||||||
|
|
||||||
virtual void InvalidateEvent(const TimeRange& range);
|
virtual void InvalidateEvent(const TimeRange& range);
|
||||||
|
|
||||||
virtual void ShiftEvent(const rational& from, const rational& to);
|
|
||||||
|
|
||||||
Project* GetProject() const;
|
Project* GetProject() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TimeRangeList validated_;
|
TimeRangeList validated_;
|
||||||
|
|
||||||
|
QUuid uuid_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -557,7 +557,9 @@ RenderTicketWatcher* PreviewAutoCacher::RenderFrame(const rational& time, Render
|
|||||||
watcher->setProperty("job", QVariant::fromValue(last_update_time_));
|
watcher->setProperty("job", QVariant::fromValue(last_update_time_));
|
||||||
connect(watcher, &RenderTicketWatcher::Finished, this, &PreviewAutoCacher::VideoRendered);
|
connect(watcher, &RenderTicketWatcher::Finished, this, &PreviewAutoCacher::VideoRendered);
|
||||||
video_tasks_.insert(watcher, time);
|
video_tasks_.insert(watcher, time);
|
||||||
watcher->SetTicket(RenderManager::instance()->RenderFrame(copied_viewer_node_,
|
watcher->SetTicket(RenderManager::instance()->RenderFrame(copied_viewer_node_->GetConnectedTextureOutput(),
|
||||||
|
copied_viewer_node_->GetVideoParams(),
|
||||||
|
copied_viewer_node_->GetAudioParams(),
|
||||||
copied_color_manager_,
|
copied_color_manager_,
|
||||||
time,
|
time,
|
||||||
RenderMode::kOffline,
|
RenderMode::kOffline,
|
||||||
@@ -574,7 +576,7 @@ RenderTicketPtr PreviewAutoCacher::RenderAudio(const TimeRange &r, bool generate
|
|||||||
connect(watcher, &RenderTicketWatcher::Finished, this, &PreviewAutoCacher::AudioRendered);
|
connect(watcher, &RenderTicketWatcher::Finished, this, &PreviewAutoCacher::AudioRendered);
|
||||||
audio_tasks_.insert(watcher, r);
|
audio_tasks_.insert(watcher, r);
|
||||||
|
|
||||||
RenderTicketPtr ticket = RenderManager::instance()->RenderAudio(copied_viewer_node_, r, RenderMode::kOffline, generate_waveforms, priority);
|
RenderTicketPtr ticket = RenderManager::instance()->RenderAudio(copied_viewer_node_->GetConnectedSampleOutput(), r, copied_viewer_node_->GetAudioParams(), RenderMode::kOffline, generate_waveforms, priority);
|
||||||
watcher->SetTicket(ticket);
|
watcher->SetTicket(ticket);
|
||||||
return ticket;
|
return ticket;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,16 +76,16 @@ RenderManager::~RenderManager()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderTicketPtr RenderManager::RenderFrame(ViewerOutput *viewer, ColorManager* color_manager,
|
RenderTicketPtr RenderManager::RenderFrame(Node *node, const VideoParams &vparam, const AudioParams ¶m,
|
||||||
const rational& time, RenderMode::Mode mode,
|
ColorManager* color_manager, const rational& time, RenderMode::Mode mode,
|
||||||
FrameHashCache* cache, RenderTicketPriority priority, ReturnType return_type)
|
FrameHashCache* cache, RenderTicketPriority priority, ReturnType return_type)
|
||||||
{
|
{
|
||||||
return RenderFrame(viewer,
|
return RenderFrame(node,
|
||||||
color_manager,
|
color_manager,
|
||||||
time,
|
time,
|
||||||
mode,
|
mode,
|
||||||
viewer->GetVideoParams(),
|
vparam,
|
||||||
viewer->GetAudioParams(),
|
param,
|
||||||
QSize(0, 0),
|
QSize(0, 0),
|
||||||
QMatrix4x4(),
|
QMatrix4x4(),
|
||||||
VideoParams::kFormatInvalid,
|
VideoParams::kFormatInvalid,
|
||||||
@@ -95,7 +95,7 @@ RenderTicketPtr RenderManager::RenderFrame(ViewerOutput *viewer, ColorManager* c
|
|||||||
return_type);
|
return_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderTicketPtr RenderManager::RenderFrame(ViewerOutput *viewer, ColorManager* color_manager,
|
RenderTicketPtr RenderManager::RenderFrame(Node *node, ColorManager* color_manager,
|
||||||
const rational& time, RenderMode::Mode mode,
|
const rational& time, RenderMode::Mode mode,
|
||||||
const VideoParams &video_params, const AudioParams &audio_params,
|
const VideoParams &video_params, const AudioParams &audio_params,
|
||||||
const QSize& force_size,
|
const QSize& force_size,
|
||||||
@@ -106,7 +106,7 @@ RenderTicketPtr RenderManager::RenderFrame(ViewerOutput *viewer, ColorManager* c
|
|||||||
// Create ticket
|
// Create ticket
|
||||||
RenderTicketPtr ticket = std::make_shared<RenderTicket>();
|
RenderTicketPtr ticket = std::make_shared<RenderTicket>();
|
||||||
|
|
||||||
ticket->setProperty("viewer", Node::PtrToValue(viewer));
|
ticket->setProperty("node", Node::PtrToValue(node));
|
||||||
ticket->setProperty("time", QVariant::fromValue(time));
|
ticket->setProperty("time", QVariant::fromValue(time));
|
||||||
ticket->setProperty("size", force_size);
|
ticket->setProperty("size", force_size);
|
||||||
ticket->setProperty("matrix", force_matrix);
|
ticket->setProperty("matrix", force_matrix);
|
||||||
@@ -130,17 +130,12 @@ RenderTicketPtr RenderManager::RenderFrame(ViewerOutput *viewer, ColorManager* c
|
|||||||
return ticket;
|
return ticket;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderTicketPtr RenderManager::RenderAudio(ViewerOutput* viewer, const TimeRange& r, RenderMode::Mode mode, bool generate_waveforms, RenderTicketPriority priority)
|
RenderTicketPtr RenderManager::RenderAudio(Node *node, const TimeRange &r, const AudioParams ¶ms, RenderMode::Mode mode, bool generate_waveforms, RenderTicketPriority priority)
|
||||||
{
|
|
||||||
return RenderAudio(viewer, r, viewer->GetAudioParams(), mode, generate_waveforms, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderTicketPtr RenderManager::RenderAudio(ViewerOutput* viewer, const TimeRange &r, const AudioParams ¶ms, RenderMode::Mode mode, bool generate_waveforms, RenderTicketPriority priority)
|
|
||||||
{
|
{
|
||||||
// Create ticket
|
// Create ticket
|
||||||
RenderTicketPtr ticket = std::make_shared<RenderTicket>();
|
RenderTicketPtr ticket = std::make_shared<RenderTicket>();
|
||||||
|
|
||||||
ticket->setProperty("viewer", Node::PtrToValue(viewer));
|
ticket->setProperty("node", Node::PtrToValue(node));
|
||||||
ticket->setProperty("time", QVariant::fromValue(r));
|
ticket->setProperty("time", QVariant::fromValue(r));
|
||||||
ticket->setProperty("type", kTypeAudio);
|
ticket->setProperty("type", kTypeAudio);
|
||||||
ticket->setProperty("mode", mode);
|
ticket->setProperty("mode", mode);
|
||||||
|
|||||||
@@ -76,10 +76,10 @@ public:
|
|||||||
*
|
*
|
||||||
* This function is thread-safe.
|
* This function is thread-safe.
|
||||||
*/
|
*/
|
||||||
RenderTicketPtr RenderFrame(ViewerOutput *viewer, ColorManager* color_manager,
|
RenderTicketPtr RenderFrame(Node *node, const VideoParams &vparam, const AudioParams ¶m, ColorManager* color_manager,
|
||||||
const rational& time, RenderMode::Mode mode,
|
const rational& time, RenderMode::Mode mode,
|
||||||
FrameHashCache* cache = nullptr, RenderTicketPriority priority = RenderTicketPriority::kNormal, ReturnType return_type = kFrame);
|
FrameHashCache* cache = nullptr, RenderTicketPriority priority = RenderTicketPriority::kNormal, ReturnType return_type = kFrame);
|
||||||
RenderTicketPtr RenderFrame(ViewerOutput* viewer, ColorManager* color_manager,
|
RenderTicketPtr RenderFrame(Node *node, ColorManager* color_manager,
|
||||||
const rational& time, RenderMode::Mode mode,
|
const rational& time, RenderMode::Mode mode,
|
||||||
const VideoParams& video_params, const AudioParams& audio_params,
|
const VideoParams& video_params, const AudioParams& audio_params,
|
||||||
const QSize& force_size,
|
const QSize& force_size,
|
||||||
@@ -94,8 +94,7 @@ public:
|
|||||||
*
|
*
|
||||||
* This function is thread-safe.
|
* This function is thread-safe.
|
||||||
*/
|
*/
|
||||||
RenderTicketPtr RenderAudio(ViewerOutput* viewer, const TimeRange& r, const AudioParams& params, RenderMode::Mode mode, bool generate_waveforms, RenderTicketPriority priority = RenderTicketPriority::kNormal);
|
RenderTicketPtr RenderAudio(Node *viewer, const TimeRange& r, const AudioParams& params, RenderMode::Mode mode, bool generate_waveforms, RenderTicketPriority priority = RenderTicketPriority::kNormal);
|
||||||
RenderTicketPtr RenderAudio(ViewerOutput *viewer, const TimeRange& r, RenderMode::Mode mode, bool generate_waveforms, RenderTicketPriority priority = RenderTicketPriority::kNormal);
|
|
||||||
|
|
||||||
virtual void RunTicket(RenderTicketPtr ticket) const override;
|
virtual void RunTicket(RenderTicketPtr ticket) const override;
|
||||||
|
|
||||||
|
|||||||
@@ -46,13 +46,12 @@ RenderProcessor::RenderProcessor(RenderTicketPtr ticket, Renderer *render_ctx, D
|
|||||||
|
|
||||||
TexturePtr RenderProcessor::GenerateTexture(const rational &time, const rational &frame_length)
|
TexturePtr RenderProcessor::GenerateTexture(const rational &time, const rational &frame_length)
|
||||||
{
|
{
|
||||||
ViewerOutput* viewer = Node::ValueToPtr<ViewerOutput>(ticket_->property("viewer"));
|
|
||||||
|
|
||||||
TimeRange range = TimeRange(time, time + frame_length);
|
TimeRange range = TimeRange(time, time + frame_length);
|
||||||
|
|
||||||
NodeValueTable table;
|
NodeValueTable table;
|
||||||
if (Node *texture_output = viewer->GetConnectedTextureOutput()) {
|
if (Node* node = Node::ValueToPtr<Node>(ticket_->property("node"))) {
|
||||||
table = GenerateTable(texture_output, range);
|
table = GenerateTable(node, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeValue tex_val = table.Get(NodeValue::kTexture);
|
NodeValue tex_val = table.Get(NodeValue::kTexture);
|
||||||
@@ -205,12 +204,11 @@ void RenderProcessor::Run()
|
|||||||
}
|
}
|
||||||
case RenderManager::kTypeAudio:
|
case RenderManager::kTypeAudio:
|
||||||
{
|
{
|
||||||
ViewerOutput* viewer = Node::ValueToPtr<ViewerOutput>(ticket_->property("viewer"));
|
|
||||||
TimeRange time = ticket_->property("time").value<TimeRange>();
|
TimeRange time = ticket_->property("time").value<TimeRange>();
|
||||||
|
|
||||||
NodeValueTable table;
|
NodeValueTable table;
|
||||||
if (Node *texture_output = viewer->GetConnectedSampleOutput()) {
|
if (Node* node = Node::ValueToPtr<Node>(ticket_->property("node"))) {
|
||||||
table = GenerateTable(texture_output, time);
|
table = GenerateTable(node, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeValue sample_val = table.Get(NodeValue::kSamples);
|
NodeValue sample_val = table.Get(NodeValue::kSamples);
|
||||||
|
|||||||
@@ -416,8 +416,7 @@ void TimelineWidget::SplitAtPlayhead()
|
|||||||
void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
||||||
bool remove_from_graph,
|
bool remove_from_graph,
|
||||||
MultiUndoCommand *command,
|
MultiUndoCommand *command,
|
||||||
bool handle_transitions,
|
bool handle_transitions)
|
||||||
bool handle_invalidations)
|
|
||||||
{
|
{
|
||||||
foreach (Block* b, blocks) {
|
foreach (Block* b, blocks) {
|
||||||
if (dynamic_cast<GapBlock*>(b)) {
|
if (dynamic_cast<GapBlock*>(b)) {
|
||||||
@@ -428,7 +427,7 @@ void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
|||||||
|
|
||||||
Track* original_track = b->track();
|
Track* original_track = b->track();
|
||||||
|
|
||||||
command->add_child(new TrackReplaceBlockWithGapCommand(original_track, b, handle_transitions, handle_invalidations));
|
command->add_child(new TrackReplaceBlockWithGapCommand(original_track, b, handle_transitions));
|
||||||
|
|
||||||
if (remove_from_graph) {
|
if (remove_from_graph) {
|
||||||
command->add_child(new NodeRemoveWithExclusiveDependenciesAndDisconnect(b));
|
command->add_child(new NodeRemoveWithExclusiveDependenciesAndDisconnect(b));
|
||||||
@@ -482,7 +481,7 @@ void TimelineWidget::DeleteSelected(bool ripple)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replace clips with gaps (effectively deleting them)
|
// Replace clips with gaps (effectively deleting them)
|
||||||
ReplaceBlocksWithGaps(clips_to_delete, true, command, false, !ripple);
|
ReplaceBlocksWithGaps(clips_to_delete, true, command, false);
|
||||||
|
|
||||||
// Insert ripple command now that it's all cleaned up gaps
|
// Insert ripple command now that it's all cleaned up gaps
|
||||||
TimelineRippleDeleteGapsAtRegionsCommand *ripple_command = nullptr;
|
TimelineRippleDeleteGapsAtRegionsCommand *ripple_command = nullptr;
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public:
|
|||||||
|
|
||||||
void RestoreSplitterState(const QByteArray& state);
|
void RestoreSplitterState(const QByteArray& state);
|
||||||
|
|
||||||
static void ReplaceBlocksWithGaps(const QVector<Block *> &blocks, bool remove_from_graph, MultiUndoCommand *command, bool handle_transitions = true, bool handle_invalidations = true);
|
static void ReplaceBlocksWithGaps(const QVector<Block *> &blocks, bool remove_from_graph, MultiUndoCommand *command, bool handle_transitions = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the QGraphicsItem at a particular scene position
|
* @brief Retrieve the QGraphicsItem at a particular scene position
|
||||||
|
|||||||
@@ -208,8 +208,6 @@ void TransitionRemoveCommand::redo()
|
|||||||
|
|
||||||
Q_ASSERT(out_block_ || in_block_);
|
Q_ASSERT(out_block_ || in_block_);
|
||||||
|
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
TimeRange invalidate_range(block_->in(), block_->out());
|
TimeRange invalidate_range(block_->in(), block_->out());
|
||||||
|
|
||||||
if (in_block_) {
|
if (in_block_) {
|
||||||
@@ -230,10 +228,6 @@ void TransitionRemoveCommand::redo()
|
|||||||
|
|
||||||
track_->RippleRemoveBlock(block_);
|
track_->RippleRemoveBlock(block_);
|
||||||
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
track_->Node::InvalidateCache(invalidate_range, Track::kBlockInput);
|
|
||||||
|
|
||||||
if (remove_from_graph_) {
|
if (remove_from_graph_) {
|
||||||
if (!remove_command_) {
|
if (!remove_command_) {
|
||||||
remove_command_ = CreateRemoveCommand(block_);
|
remove_command_ = CreateRemoveCommand(block_);
|
||||||
@@ -249,8 +243,6 @@ void TransitionRemoveCommand::undo()
|
|||||||
remove_command_->undo_now();
|
remove_command_->undo_now();
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
if (in_block_) {
|
if (in_block_) {
|
||||||
track_->InsertBlockBefore(block_, in_block_);
|
track_->InsertBlockBefore(block_, in_block_);
|
||||||
} else {
|
} else {
|
||||||
@@ -275,10 +267,6 @@ void TransitionRemoveCommand::undo()
|
|||||||
if (out_block_) {
|
if (out_block_) {
|
||||||
out_block_->set_length_and_media_out(out_block_->length() - block_->out_offset());
|
out_block_->set_length_and_media_out(out_block_->length() - block_->out_offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
track_->Node::InvalidateCache(TimeRange(block_->in(), block_->out()), Track::kBlockInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -287,11 +275,8 @@ void TransitionRemoveCommand::undo()
|
|||||||
void TrackListInsertGaps::prepare()
|
void TrackListInsertGaps::prepare()
|
||||||
{
|
{
|
||||||
// Determine if all tracks will be affected, which will allow us to make some optimizations
|
// Determine if all tracks will be affected, which will allow us to make some optimizations
|
||||||
all_tracks_unlocked_ = true;
|
|
||||||
|
|
||||||
foreach (Track* track, track_list_->GetTracks()) {
|
foreach (Track* track, track_list_->GetTracks()) {
|
||||||
if (track->IsLocked()) {
|
if (track->IsLocked()) {
|
||||||
all_tracks_unlocked_ = false;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,19 +331,6 @@ void TrackListInsertGaps::prepare()
|
|||||||
|
|
||||||
void TrackListInsertGaps::redo()
|
void TrackListInsertGaps::redo()
|
||||||
{
|
{
|
||||||
if (all_tracks_unlocked_) {
|
|
||||||
// Optimize by shifting over since we have a constant amount of time being inserted
|
|
||||||
if (track_list_->type() == Track::kVideo) {
|
|
||||||
track_list_->parent()->ShiftVideoCache(point_, point_ + length_);
|
|
||||||
} else if (track_list_->type() == Track::kAudio) {
|
|
||||||
track_list_->parent()->ShiftAudioCache(point_, point_ + length_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->BeginOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Block* gap, gaps_to_extend_) {
|
foreach (Block* gap, gaps_to_extend_) {
|
||||||
gap->set_length_and_media_out(gap->length() + length_);
|
gap->set_length_and_media_out(gap->length() + length_);
|
||||||
}
|
}
|
||||||
@@ -371,33 +343,10 @@ void TrackListInsertGaps::redo()
|
|||||||
add_gap.gap->setParent(add_gap.track->parent());
|
add_gap.gap->setParent(add_gap.track->parent());
|
||||||
add_gap.track->InsertBlockAfter(add_gap.gap, add_gap.before);
|
add_gap.track->InsertBlockAfter(add_gap.gap, add_gap.before);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->EndOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!all_tracks_unlocked_) {
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->Node::InvalidateCache(TimeRange(point_, RATIONAL_MAX), Track::kBlockInput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackListInsertGaps::undo()
|
void TrackListInsertGaps::undo()
|
||||||
{
|
{
|
||||||
if (all_tracks_unlocked_) {
|
|
||||||
// Optimize by shifting over since we have a constant amount of time being inserted
|
|
||||||
if (track_list_->type() == Track::kVideo) {
|
|
||||||
track_list_->parent()->ShiftVideoCache(point_ + length_, point_);
|
|
||||||
} else if (track_list_->type() == Track::kAudio) {
|
|
||||||
track_list_->parent()->ShiftAudioCache(point_ + length_, point_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->BeginOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove added gaps
|
// Remove added gaps
|
||||||
foreach (auto add_gap, gaps_added_) {
|
foreach (auto add_gap, gaps_added_) {
|
||||||
add_gap.gap->track()->RippleRemoveBlock(add_gap.gap);
|
add_gap.gap->track()->RippleRemoveBlock(add_gap.gap);
|
||||||
@@ -413,16 +362,6 @@ void TrackListInsertGaps::undo()
|
|||||||
foreach (Block* gap, gaps_to_extend_) {
|
foreach (Block* gap, gaps_to_extend_) {
|
||||||
gap->set_length_and_media_out(gap->length() - length_);
|
gap->set_length_and_media_out(gap->length() - length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->EndOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!all_tracks_unlocked_) {
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->Node::InvalidateCache(TimeRange(point_, RATIONAL_MAX), Track::kBlockInput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -440,8 +379,6 @@ void TrackReplaceBlockWithGapCommand::redo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (block_->next()) {
|
if (block_->next()) {
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
// Invalidate the range inhabited by this block
|
// Invalidate the range inhabited by this block
|
||||||
TimeRange invalidate_range(block_->in(), block_->out());
|
TimeRange invalidate_range(block_->in(), block_->out());
|
||||||
|
|
||||||
@@ -488,12 +425,6 @@ void TrackReplaceBlockWithGapCommand::redo()
|
|||||||
track_->ReplaceBlock(block_, our_gap_);
|
track_->ReplaceBlock(block_, our_gap_);
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
if (handle_invalidations_) {
|
|
||||||
track_->Node::InvalidateCache(invalidate_range, Track::kBlockInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Block is at the end of the track, simply remove it
|
// Block is at the end of the track, simply remove it
|
||||||
Block* preceding = block_->previous();
|
Block* preceding = block_->previous();
|
||||||
@@ -512,8 +443,6 @@ void TrackReplaceBlockWithGapCommand::redo()
|
|||||||
void TrackReplaceBlockWithGapCommand::undo()
|
void TrackReplaceBlockWithGapCommand::undo()
|
||||||
{
|
{
|
||||||
if (our_gap_ || existing_gap_) {
|
if (our_gap_ || existing_gap_) {
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
if (our_gap_) {
|
if (our_gap_) {
|
||||||
|
|
||||||
// We made this gap, simply swap our gap back
|
// We made this gap, simply swap our gap back
|
||||||
@@ -547,11 +476,6 @@ void TrackReplaceBlockWithGapCommand::undo()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
if (handle_invalidations_) {
|
|
||||||
track_->Node::InvalidateCache(TimeRange(block_->in(), block_->out()), Track::kBlockInput);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Our gap and existing gap were both null, our block must have been at the end and thus
|
// Our gap and existing gap were both null, our block must have been at the end and thus
|
||||||
|
|||||||
@@ -233,14 +233,13 @@ private:
|
|||||||
|
|
||||||
class TrackReplaceBlockWithGapCommand : public UndoCommand {
|
class TrackReplaceBlockWithGapCommand : public UndoCommand {
|
||||||
public:
|
public:
|
||||||
TrackReplaceBlockWithGapCommand(Track* track, Block* block, bool handle_transitions = true, bool handle_invalidations = true) :
|
TrackReplaceBlockWithGapCommand(Track* track, Block* block, bool handle_transitions = true) :
|
||||||
track_(track),
|
track_(track),
|
||||||
block_(block),
|
block_(block),
|
||||||
existing_gap_(nullptr),
|
existing_gap_(nullptr),
|
||||||
existing_merged_gap_(nullptr),
|
existing_merged_gap_(nullptr),
|
||||||
our_gap_(nullptr),
|
our_gap_(nullptr),
|
||||||
handle_transitions_(handle_transitions),
|
handle_transitions_(handle_transitions)
|
||||||
handle_invalidations_(handle_invalidations)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +265,6 @@ private:
|
|||||||
GapBlock* our_gap_;
|
GapBlock* our_gap_;
|
||||||
|
|
||||||
bool handle_transitions_;
|
bool handle_transitions_;
|
||||||
bool handle_invalidations_;
|
|
||||||
|
|
||||||
QObject memory_manager_;
|
QObject memory_manager_;
|
||||||
|
|
||||||
@@ -344,8 +342,6 @@ private:
|
|||||||
|
|
||||||
QVector<Track*> working_tracks_;
|
QVector<Track*> working_tracks_;
|
||||||
|
|
||||||
bool all_tracks_unlocked_;
|
|
||||||
|
|
||||||
QVector<Block*> gaps_to_extend_;
|
QVector<Block*> gaps_to_extend_;
|
||||||
|
|
||||||
struct AddGap {
|
struct AddGap {
|
||||||
@@ -362,62 +358,6 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NodeBeginOperationCommand : public UndoCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NodeBeginOperationCommand(Node *node) :
|
|
||||||
node_(node)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual Project* GetRelevantProject() const override
|
|
||||||
{
|
|
||||||
return node_->project();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void redo() override
|
|
||||||
{
|
|
||||||
node_->BeginOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void undo() override
|
|
||||||
{
|
|
||||||
node_->EndOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Node *node_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class NodeEndOperationCommand : public UndoCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NodeEndOperationCommand(Node *node) :
|
|
||||||
node_(node)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual Project* GetRelevantProject() const override
|
|
||||||
{
|
|
||||||
return node_->project();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void redo() override
|
|
||||||
{
|
|
||||||
node_->EndOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void undo() override
|
|
||||||
{
|
|
||||||
node_->BeginOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Node *node_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TIMELINEUNDOGENERAL_H
|
#endif // TIMELINEUNDOGENERAL_H
|
||||||
|
|||||||
@@ -36,9 +36,6 @@ void BlockTrimCommand::redo()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin an operation since we'll be doing a lot
|
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
// Determine how much time to invalidate
|
// Determine how much time to invalidate
|
||||||
TimeRange invalidate_range;
|
TimeRange invalidate_range;
|
||||||
|
|
||||||
@@ -82,14 +79,10 @@ void BlockTrimCommand::redo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
if (dynamic_cast<TransitionBlock*>(block_)) {
|
if (dynamic_cast<TransitionBlock*>(block_)) {
|
||||||
// Whole transition needs to be invalidated
|
// Whole transition needs to be invalidated
|
||||||
invalidate_range = block_->range();
|
invalidate_range = block_->range();
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->Node::InvalidateCache(invalidate_range, Track::kBlockInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockTrimCommand::undo()
|
void BlockTrimCommand::undo()
|
||||||
@@ -98,8 +91,6 @@ void BlockTrimCommand::undo()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
// Will be POSITIVE if trimming shorter and NEGATIVE if trimming longer
|
// Will be POSITIVE if trimming shorter and NEGATIVE if trimming longer
|
||||||
if (needs_adjacent_) {
|
if (needs_adjacent_) {
|
||||||
if (we_created_adjacent_) {
|
if (we_created_adjacent_) {
|
||||||
@@ -146,10 +137,6 @@ void BlockTrimCommand::undo()
|
|||||||
// Whole transition needs to be invalidated
|
// Whole transition needs to be invalidated
|
||||||
invalidate_range = block_->range();
|
invalidate_range = block_->range();
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
track_->Node::InvalidateCache(invalidate_range, Track::kBlockInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockTrimCommand::prepare()
|
void BlockTrimCommand::prepare()
|
||||||
@@ -200,8 +187,6 @@ void TrackSlideCommand::redo()
|
|||||||
// Make sure all movement blocks' old positions are invalidated
|
// Make sure all movement blocks' old positions are invalidated
|
||||||
TimeRange invalidate_range(blocks_.first()->in(), blocks_.last()->out());
|
TimeRange invalidate_range(blocks_.first()->in(), blocks_.last()->out());
|
||||||
|
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
// We will always have an in adjacent if there was a valid slide
|
// We will always have an in adjacent if there was a valid slide
|
||||||
if (we_created_in_adjacent_) {
|
if (we_created_in_adjacent_) {
|
||||||
// We created in adjacent, so all we have to do is insert it
|
// We created in adjacent, so all we have to do is insert it
|
||||||
@@ -246,13 +231,9 @@ void TrackSlideCommand::redo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
// Make sure all movement blocks' new positions are invalidated
|
// Make sure all movement blocks' new positions are invalidated
|
||||||
invalidate_range.set_range(qMin(invalidate_range.in(), blocks_.first()->in()),
|
invalidate_range.set_range(qMin(invalidate_range.in(), blocks_.first()->in()),
|
||||||
qMax(invalidate_range.out(), blocks_.last()->out()));
|
qMax(invalidate_range.out(), blocks_.last()->out()));
|
||||||
|
|
||||||
track_->Node::InvalidateCache(invalidate_range, Track::kBlockInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -261,8 +242,6 @@ void TrackSlideCommand::undo()
|
|||||||
// Make sure all movement blocks' old positions are invalidated
|
// Make sure all movement blocks' old positions are invalidated
|
||||||
TimeRange invalidate_range(blocks_.first()->in(), blocks_.last()->out());
|
TimeRange invalidate_range(blocks_.first()->in(), blocks_.last()->out());
|
||||||
|
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
if (we_created_in_adjacent_) {
|
if (we_created_in_adjacent_) {
|
||||||
// We created this, so we can remove it now
|
// We created this, so we can remove it now
|
||||||
track_->RippleRemoveBlock(in_adjacent_);
|
track_->RippleRemoveBlock(in_adjacent_);
|
||||||
@@ -287,13 +266,9 @@ void TrackSlideCommand::undo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
// Make sure all movement blocks' new positions are invalidated
|
// Make sure all movement blocks' new positions are invalidated
|
||||||
invalidate_range.set_range(qMin(invalidate_range.in(), blocks_.first()->in()),
|
invalidate_range.set_range(qMin(invalidate_range.in(), blocks_.first()->in()),
|
||||||
qMax(invalidate_range.out(), blocks_.last()->out()));
|
qMax(invalidate_range.out(), blocks_.last()->out()));
|
||||||
|
|
||||||
track_->Node::InvalidateCache(invalidate_range, Track::kBlockInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackSlideCommand::prepare()
|
void TrackSlideCommand::prepare()
|
||||||
@@ -328,8 +303,6 @@ TrackPlaceBlockCommand::~TrackPlaceBlockCommand()
|
|||||||
|
|
||||||
void TrackPlaceBlockCommand::redo()
|
void TrackPlaceBlockCommand::redo()
|
||||||
{
|
{
|
||||||
TimeRangeList ranges_to_invalidate;
|
|
||||||
|
|
||||||
// Determine if we need to add tracks
|
// Determine if we need to add tracks
|
||||||
if (track_index_ >= timeline_->GetTracks().size()) {
|
if (track_index_ >= timeline_->GetTracks().size()) {
|
||||||
if (add_track_commands_.isEmpty()) {
|
if (add_track_commands_.isEmpty()) {
|
||||||
@@ -348,8 +321,6 @@ void TrackPlaceBlockCommand::redo()
|
|||||||
|
|
||||||
Track* track = timeline_->GetTrackAt(track_index_);
|
Track* track = timeline_->GetTrackAt(track_index_);
|
||||||
|
|
||||||
track->BeginOperation();
|
|
||||||
|
|
||||||
bool append = (in_ >= track->track_length());
|
bool append = (in_ >= track->track_length());
|
||||||
|
|
||||||
// Check if the placement location is past the end of the timeline
|
// Check if the placement location is past the end of the timeline
|
||||||
@@ -362,7 +333,6 @@ void TrackPlaceBlockCommand::redo()
|
|||||||
}
|
}
|
||||||
gap_->setParent(track->parent());
|
gap_->setParent(track->parent());
|
||||||
track->AppendBlock(gap_);
|
track->AppendBlock(gap_);
|
||||||
ranges_to_invalidate.insert(gap_->range());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
track->AppendBlock(insert_);
|
track->AppendBlock(insert_);
|
||||||
@@ -376,14 +346,6 @@ void TrackPlaceBlockCommand::redo()
|
|||||||
ripple_remove_command_->redo_now();
|
ripple_remove_command_->redo_now();
|
||||||
track->InsertBlockAfter(insert_, ripple_remove_command_->GetInsertionIndex());
|
track->InsertBlockAfter(insert_, ripple_remove_command_->GetInsertionIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
track->EndOperation();
|
|
||||||
|
|
||||||
ranges_to_invalidate.insert(insert_->range());
|
|
||||||
|
|
||||||
foreach (const TimeRange &r, ranges_to_invalidate) {
|
|
||||||
track->Node::InvalidateCache(r, Track::kBlockInput);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackPlaceBlockCommand::undo()
|
void TrackPlaceBlockCommand::undo()
|
||||||
@@ -393,7 +355,6 @@ void TrackPlaceBlockCommand::undo()
|
|||||||
TimeRange insert_range(insert_->in(), insert_->out());
|
TimeRange insert_range(insert_->in(), insert_->out());
|
||||||
|
|
||||||
// Firstly, remove our insert
|
// Firstly, remove our insert
|
||||||
t->BeginOperation();
|
|
||||||
t->RippleRemoveBlock(insert_);
|
t->RippleRemoveBlock(insert_);
|
||||||
|
|
||||||
if (ripple_remove_command_) {
|
if (ripple_remove_command_) {
|
||||||
@@ -403,9 +364,6 @@ void TrackPlaceBlockCommand::undo()
|
|||||||
t->RippleRemoveBlock(gap_);
|
t->RippleRemoveBlock(gap_);
|
||||||
gap_->setParent(&memory_manager_);
|
gap_->setParent(&memory_manager_);
|
||||||
}
|
}
|
||||||
t->EndOperation();
|
|
||||||
|
|
||||||
t->Node::InvalidateCache(insert_range, Track::kBlockInput);
|
|
||||||
|
|
||||||
// Remove tracks if we added them
|
// Remove tracks if we added them
|
||||||
for (int i=add_track_commands_.size()-1; i>=0; i--) {
|
for (int i=add_track_commands_.size()-1; i>=0; i--) {
|
||||||
|
|||||||
@@ -106,8 +106,6 @@ void TrackRippleRemoveAreaCommand::prepare()
|
|||||||
|
|
||||||
void TrackRippleRemoveAreaCommand::redo()
|
void TrackRippleRemoveAreaCommand::redo()
|
||||||
{
|
{
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
if (splice_split_command_) {
|
if (splice_split_command_) {
|
||||||
// We're just splicing
|
// We're just splicing
|
||||||
splice_split_command_->redo_now();
|
splice_split_command_->redo_now();
|
||||||
@@ -145,17 +143,10 @@ void TrackRippleRemoveAreaCommand::redo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
track_->Node::InvalidateCache(TimeRange(range_.in(), RATIONAL_MAX), Track::kBlockInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackRippleRemoveAreaCommand::undo()
|
void TrackRippleRemoveAreaCommand::undo()
|
||||||
{
|
{
|
||||||
// Begin operations
|
|
||||||
track_->BeginOperation();
|
|
||||||
|
|
||||||
if (splice_split_command_) {
|
if (splice_split_command_) {
|
||||||
splice_split_command_->undo_now();
|
splice_split_command_->undo_now();
|
||||||
} else {
|
} else {
|
||||||
@@ -176,85 +167,36 @@ void TrackRippleRemoveAreaCommand::undo()
|
|||||||
track_->InsertBlockAfter(op.block, op.before);
|
track_->InsertBlockAfter(op.block, op.before);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// End operations and invalidate
|
|
||||||
track_->EndOperation();
|
|
||||||
|
|
||||||
track_->Node::InvalidateCache(TimeRange(range_.in(), RATIONAL_MAX), Track::kBlockInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// TrackListRippleRemoveAreaCommand
|
// TrackListRippleRemoveAreaCommand
|
||||||
//
|
//
|
||||||
|
void TrackListRippleRemoveAreaCommand::prepare()
|
||||||
|
{
|
||||||
|
foreach (Track* track, list_->GetTracks()) {
|
||||||
|
if (track->IsLocked()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackRippleRemoveAreaCommand* c = new TrackRippleRemoveAreaCommand(track, range_);
|
||||||
|
commands_.append(c);
|
||||||
|
working_tracks_.append(track);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TrackListRippleRemoveAreaCommand::redo()
|
void TrackListRippleRemoveAreaCommand::redo()
|
||||||
{
|
{
|
||||||
// Code that's only run on the first redo
|
|
||||||
if (commands_.isEmpty()) {
|
|
||||||
all_tracks_unlocked_ = true;
|
|
||||||
|
|
||||||
foreach (Track* track, list_->GetTracks()) {
|
|
||||||
if (track->IsLocked()) {
|
|
||||||
all_tracks_unlocked_ = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackRippleRemoveAreaCommand* c = new TrackRippleRemoveAreaCommand(track, range_);
|
|
||||||
commands_.append(c);
|
|
||||||
working_tracks_.append(track);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all_tracks_unlocked_) {
|
|
||||||
// We can optimize here by simply shifting the whole cache forward instead of re-caching
|
|
||||||
// everything following this time
|
|
||||||
if (list_->type() == Track::kVideo) {
|
|
||||||
list_->parent()->ShiftVideoCache(range_.out(), range_.in());
|
|
||||||
} else if (list_->type() == Track::kAudio) {
|
|
||||||
list_->parent()->ShiftAudioCache(range_.out(), range_.in());
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->BeginOperation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (TrackRippleRemoveAreaCommand* c, commands_) {
|
foreach (TrackRippleRemoveAreaCommand* c, commands_) {
|
||||||
c->redo_now();
|
c->redo_now();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all_tracks_unlocked_) {
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->EndOperation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackListRippleRemoveAreaCommand::undo()
|
void TrackListRippleRemoveAreaCommand::undo()
|
||||||
{
|
{
|
||||||
if (all_tracks_unlocked_) {
|
|
||||||
// We can optimize here by simply shifting the whole cache forward instead of re-caching
|
|
||||||
// everything following this time
|
|
||||||
if (list_->type() == Track::kVideo) {
|
|
||||||
list_->parent()->ShiftVideoCache(range_.in(), range_.out());
|
|
||||||
} else if (list_->type() == Track::kAudio) {
|
|
||||||
list_->parent()->ShiftAudioCache(range_.in(), range_.out());
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->BeginOperation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (TrackRippleRemoveAreaCommand* c, commands_) {
|
foreach (TrackRippleRemoveAreaCommand* c, commands_) {
|
||||||
c->undo_now();
|
c->undo_now();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all_tracks_unlocked_) {
|
|
||||||
foreach (Track* track, working_tracks_) {
|
|
||||||
track->EndOperation();
|
|
||||||
track->Node::InvalidateCache(range_, Track::kBlockInput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -282,7 +224,6 @@ TrackListRippleToolCommand::TrackListRippleToolCommand(TrackList* track_list,
|
|||||||
ripple_movement_(ripple_movement),
|
ripple_movement_(ripple_movement),
|
||||||
movement_mode_(movement_mode)
|
movement_mode_(movement_mode)
|
||||||
{
|
{
|
||||||
all_tracks_unlocked_ = (info_.size() == track_list_->GetTrackCount());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackListRippleToolCommand::ripple(bool redo)
|
void TrackListRippleToolCommand::ripple(bool redo)
|
||||||
@@ -324,9 +265,6 @@ void TrackListRippleToolCommand::ripple(bool redo)
|
|||||||
rational pre_shift;
|
rational pre_shift;
|
||||||
rational post_shift;
|
rational post_shift;
|
||||||
|
|
||||||
// Begin operation so we can invalidate better later
|
|
||||||
track->BeginOperation();
|
|
||||||
|
|
||||||
if (info.append_gap) {
|
if (info.append_gap) {
|
||||||
|
|
||||||
// Rather than rippling the referenced block, we'll insert a gap and ripple with that
|
// Rather than rippling the referenced block, we'll insert a gap and ripple with that
|
||||||
@@ -429,29 +367,6 @@ void TrackListRippleToolCommand::ripple(bool redo)
|
|||||||
pre_latest_out = qMax(pre_latest_out, pre_shift);
|
pre_latest_out = qMax(pre_latest_out, pre_shift);
|
||||||
post_latest_out = qMax(post_latest_out, post_shift);
|
post_latest_out = qMax(post_latest_out, post_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all_tracks_unlocked_) {
|
|
||||||
// We rippled all the tracks, so we can shift the whole cache
|
|
||||||
if (track_list_->type() == Track::kVideo) {
|
|
||||||
track_list_->parent()->ShiftVideoCache(pre_latest_out, post_latest_out);
|
|
||||||
} else if (track_list_->type() == Track::kAudio) {
|
|
||||||
track_list_->parent()->ShiftAudioCache(pre_latest_out, post_latest_out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it=working_data_.cbegin(); it!=working_data_.cend(); it++) {
|
|
||||||
Track* track = it.key();
|
|
||||||
|
|
||||||
track->EndOperation();
|
|
||||||
|
|
||||||
if (!all_tracks_unlocked_) {
|
|
||||||
// If we're not shifting, the whole track must get invalidated
|
|
||||||
track->Node::InvalidateCache(TimeRange(it.value().earliest_point_of_change, RATIONAL_MAX), Track::kBlockInput);
|
|
||||||
} else if (pre_latest_out < post_latest_out) {
|
|
||||||
// If we're here, then a new section has been rippled in that needs to be rendered
|
|
||||||
track->Node::InvalidateCache(TimeRange(pre_latest_out, post_latest_out), Track::kBlockInput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -513,11 +428,8 @@ void TimelineRippleDeleteGapsAtRegionsCommand::prepare()
|
|||||||
// Determine which gaps will be involved in this operation
|
// Determine which gaps will be involved in this operation
|
||||||
QVector<GapBlock*> gaps;
|
QVector<GapBlock*> gaps;
|
||||||
|
|
||||||
bool all_tracks_unlocked = true;
|
|
||||||
|
|
||||||
foreach (Track* track, timeline_->GetTracks()) {
|
foreach (Track* track, timeline_->GetTracks()) {
|
||||||
if (track->IsLocked()) {
|
if (track->IsLocked()) {
|
||||||
all_tracks_unlocked = false;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,24 +485,12 @@ void TimelineRippleDeleteGapsAtRegionsCommand::prepare()
|
|||||||
|
|
||||||
if (ripple_length > 0) {
|
if (ripple_length > 0) {
|
||||||
foreach (GapBlock *gap, gaps) {
|
foreach (GapBlock *gap, gaps) {
|
||||||
if (all_tracks_unlocked) {
|
|
||||||
commands_.append(new NodeBeginOperationCommand(gap->track()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gap_lengths.value(gap) == ripple_length) {
|
if (gap_lengths.value(gap) == ripple_length) {
|
||||||
commands_.append(new TrackRippleRemoveBlockCommand(gap->track(), gap));
|
commands_.append(new TrackRippleRemoveBlockCommand(gap->track(), gap));
|
||||||
} else {
|
} else {
|
||||||
gap_lengths[gap] -= ripple_length;
|
gap_lengths[gap] -= ripple_length;
|
||||||
commands_.append(new BlockResizeCommand(gap, gap_lengths.value(gap)));
|
commands_.append(new BlockResizeCommand(gap, gap_lengths.value(gap)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (all_tracks_unlocked) {
|
|
||||||
commands_.append(new NodeEndOperationCommand(gap->track()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all_tracks_unlocked) {
|
|
||||||
commands_.append(new TimelineShiftCacheCommand(timeline_, latest_point, latest_point - ripple_length));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -610,14 +510,4 @@ void TimelineRippleDeleteGapsAtRegionsCommand::undo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineShiftCacheCommand::redo()
|
|
||||||
{
|
|
||||||
timeline_->ShiftCache(from_, to_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimelineShiftCacheCommand::undo()
|
|
||||||
{
|
|
||||||
timeline_->ShiftCache(to_, from_);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void prepare() override;
|
||||||
|
|
||||||
virtual void redo() override;
|
virtual void redo() override;
|
||||||
|
|
||||||
virtual void undo() override;
|
virtual void undo() override;
|
||||||
@@ -130,8 +132,6 @@ private:
|
|||||||
|
|
||||||
TimeRange range_;
|
TimeRange range_;
|
||||||
|
|
||||||
bool all_tracks_unlocked_;
|
|
||||||
|
|
||||||
QVector<TrackRippleRemoveAreaCommand*> commands_;
|
QVector<TrackRippleRemoveAreaCommand*> commands_;
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -200,8 +200,6 @@ private:
|
|||||||
|
|
||||||
QObject memory_manager_;
|
QObject memory_manager_;
|
||||||
|
|
||||||
bool all_tracks_unlocked_;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimelineRippleDeleteGapsAtRegionsCommand : public UndoCommand
|
class TimelineRippleDeleteGapsAtRegionsCommand : public UndoCommand
|
||||||
@@ -250,34 +248,6 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimelineShiftCacheCommand : public UndoCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TimelineShiftCacheCommand(Sequence* timeline, const rational &from, const rational &to) :
|
|
||||||
timeline_(timeline),
|
|
||||||
from_(from),
|
|
||||||
to_(to)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual Project* GetRelevantProject() const override
|
|
||||||
{
|
|
||||||
return timeline_->project();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void redo() override;
|
|
||||||
|
|
||||||
virtual void undo() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Sequence* timeline_;
|
|
||||||
|
|
||||||
rational from_;
|
|
||||||
|
|
||||||
rational to_;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TIMELINEUNDORIPPLE_H
|
#endif // TIMELINEUNDORIPPLE_H
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ void BlockSplitCommand::redo()
|
|||||||
|
|
||||||
// Begin an operation
|
// Begin an operation
|
||||||
Track* track = block_->track();
|
Track* track = block_->track();
|
||||||
track->BeginOperation();
|
|
||||||
|
|
||||||
// Set lengths
|
// Set lengths
|
||||||
block_->set_length_and_media_out(new_length);
|
block_->set_length_and_media_out(new_length);
|
||||||
@@ -76,16 +75,12 @@ void BlockSplitCommand::redo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
track->EndOperation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockSplitCommand::undo()
|
void BlockSplitCommand::undo()
|
||||||
{
|
{
|
||||||
Track* track = block_->track();
|
Track* track = block_->track();
|
||||||
|
|
||||||
track->BeginOperation();
|
|
||||||
|
|
||||||
if (moved_transition_.IsValid()) {
|
if (moved_transition_.IsValid()) {
|
||||||
Node::DisconnectEdge(new_block(), moved_transition_);
|
Node::DisconnectEdge(new_block(), moved_transition_);
|
||||||
Node::ConnectEdge(block_, moved_transition_);
|
Node::ConnectEdge(block_, moved_transition_);
|
||||||
@@ -96,8 +91,6 @@ void BlockSplitCommand::undo()
|
|||||||
|
|
||||||
// If we ran a reconnect command, disconnect now
|
// If we ran a reconnect command, disconnect now
|
||||||
reconnect_tree_command_->undo_now();
|
reconnect_tree_command_->undo_now();
|
||||||
|
|
||||||
track->EndOperation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ void TimeRuler::SetPlaybackCache(PlaybackCache *cache)
|
|||||||
if (playback_cache_) {
|
if (playback_cache_) {
|
||||||
disconnect(playback_cache_, &PlaybackCache::Invalidated, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
disconnect(playback_cache_, &PlaybackCache::Invalidated, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
||||||
disconnect(playback_cache_, &PlaybackCache::Validated, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
disconnect(playback_cache_, &PlaybackCache::Validated, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
||||||
disconnect(playback_cache_, &PlaybackCache::Shifted, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
playback_cache_ = cache;
|
playback_cache_ = cache;
|
||||||
@@ -90,7 +89,6 @@ void TimeRuler::SetPlaybackCache(PlaybackCache *cache)
|
|||||||
if (playback_cache_) {
|
if (playback_cache_) {
|
||||||
connect(playback_cache_, &PlaybackCache::Invalidated, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
connect(playback_cache_, &PlaybackCache::Invalidated, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
||||||
connect(playback_cache_, &PlaybackCache::Validated, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
connect(playback_cache_, &PlaybackCache::Validated, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
||||||
connect(playback_cache_, &PlaybackCache::Shifted, viewport(), static_cast<void(QWidget::*)()>(&QWidget::update));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update();
|
update();
|
||||||
@@ -257,35 +255,37 @@ void TimeRuler::drawForeground(QPainter *p, const QRectF &rect)
|
|||||||
// If cache status is enabled
|
// If cache status is enabled
|
||||||
if (show_cache_status_ && playback_cache_) {
|
if (show_cache_status_ && playback_cache_) {
|
||||||
// FIXME: Hardcoded to get video length, if we ever need audio length, this will have to change
|
// FIXME: Hardcoded to get video length, if we ever need audio length, this will have to change
|
||||||
rational len = playback_cache_->viewer_parent()->GetVideoLength();
|
if (ViewerOutput *viewer = dynamic_cast<ViewerOutput*>(playback_cache_->parent())) {
|
||||||
int lim_left = GetScroll();
|
rational len = viewer->GetVideoLength();
|
||||||
int lim_right = lim_left + width();
|
int lim_left = GetScroll();
|
||||||
|
int lim_right = lim_left + width();
|
||||||
|
|
||||||
int cache_screen_length = TimeToScene(len);
|
int cache_screen_length = TimeToScene(len);
|
||||||
|
|
||||||
if (cache_screen_length > 0) {
|
if (cache_screen_length > 0) {
|
||||||
int cache_y = height() - cache_status_height_;
|
int cache_y = height() - cache_status_height_;
|
||||||
|
|
||||||
p->fillRect(0, cache_y, cache_screen_length, cache_status_height_, Qt::green);
|
p->fillRect(0, cache_y, cache_screen_length, cache_status_height_, Qt::green);
|
||||||
|
|
||||||
foreach (const TimeRange& range, playback_cache_->GetInvalidatedRanges(len)) {
|
foreach (const TimeRange& range, playback_cache_->GetInvalidatedRanges(len)) {
|
||||||
int range_left = TimeToScene(range.in());
|
int range_left = TimeToScene(range.in());
|
||||||
if (range_left >= width()) {
|
if (range_left >= width()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int range_right = TimeToScene(range.out());
|
||||||
|
if (range_right < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adjusted_left = qMax(lim_left, range_left);
|
||||||
|
|
||||||
|
p->fillRect(adjusted_left,
|
||||||
|
cache_y,
|
||||||
|
qMin(lim_right, range_right) - adjusted_left,
|
||||||
|
cache_status_height_,
|
||||||
|
Qt::red);
|
||||||
}
|
}
|
||||||
|
|
||||||
int range_right = TimeToScene(range.out());
|
|
||||||
if (range_right < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int adjusted_left = qMax(lim_left, range_left);
|
|
||||||
|
|
||||||
p->fillRect(adjusted_left,
|
|
||||||
cache_y,
|
|
||||||
qMin(lim_right, range_right) - adjusted_left,
|
|
||||||
cache_status_height_,
|
|
||||||
Qt::red);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,7 +205,6 @@ void ViewerWidget::ConnectNodeEvent(ViewerOutput *n)
|
|||||||
connect(n, &ViewerOutput::VideoParamsChanged, this, &ViewerWidget::UpdateRendererVideoParameters);
|
connect(n, &ViewerOutput::VideoParamsChanged, this, &ViewerWidget::UpdateRendererVideoParameters);
|
||||||
connect(n, &ViewerOutput::AudioParamsChanged, this, &ViewerWidget::UpdateRendererAudioParameters);
|
connect(n, &ViewerOutput::AudioParamsChanged, this, &ViewerWidget::UpdateRendererAudioParameters);
|
||||||
connect(n->video_frame_cache(), &FrameHashCache::Invalidated, this, &ViewerWidget::ViewerInvalidatedVideoRange);
|
connect(n->video_frame_cache(), &FrameHashCache::Invalidated, this, &ViewerWidget::ViewerInvalidatedVideoRange);
|
||||||
connect(n->video_frame_cache(), &FrameHashCache::Shifted, this, &ViewerWidget::ViewerShiftedRange);
|
|
||||||
connect(n, &ViewerOutput::TextureInputChanged, this, &ViewerWidget::UpdateStack);
|
connect(n, &ViewerOutput::TextureInputChanged, this, &ViewerWidget::UpdateStack);
|
||||||
|
|
||||||
VideoParams vp = n->GetVideoParams();
|
VideoParams vp = n->GetVideoParams();
|
||||||
@@ -250,7 +249,6 @@ void ViewerWidget::DisconnectNodeEvent(ViewerOutput *n)
|
|||||||
disconnect(n, &ViewerOutput::VideoParamsChanged, this, &ViewerWidget::UpdateRendererVideoParameters);
|
disconnect(n, &ViewerOutput::VideoParamsChanged, this, &ViewerWidget::UpdateRendererVideoParameters);
|
||||||
disconnect(n, &ViewerOutput::AudioParamsChanged, this, &ViewerWidget::UpdateRendererAudioParameters);
|
disconnect(n, &ViewerOutput::AudioParamsChanged, this, &ViewerWidget::UpdateRendererAudioParameters);
|
||||||
disconnect(n->video_frame_cache(), &FrameHashCache::Invalidated, this, &ViewerWidget::ViewerInvalidatedVideoRange);
|
disconnect(n->video_frame_cache(), &FrameHashCache::Invalidated, this, &ViewerWidget::ViewerInvalidatedVideoRange);
|
||||||
disconnect(n->video_frame_cache(), &FrameHashCache::Shifted, this, &ViewerWidget::ViewerShiftedRange);
|
|
||||||
disconnect(n, &ViewerOutput::TextureInputChanged, this, &ViewerWidget::UpdateStack);
|
disconnect(n, &ViewerOutput::TextureInputChanged, this, &ViewerWidget::UpdateStack);
|
||||||
|
|
||||||
CloseAudioProcessor();
|
CloseAudioProcessor();
|
||||||
@@ -1556,13 +1554,6 @@ void ViewerWidget::ManualSwitchToWaveform(bool e)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewerWidget::ViewerShiftedRange(const rational &from, const rational &to)
|
|
||||||
{
|
|
||||||
if (GetTime() >= qMin(from, to)) {
|
|
||||||
QMetaObject::invokeMethod(this, &ViewerWidget::UpdateTextureFromNode, Qt::QueuedConnection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewerWidget::DragEntered(QDragEnterEvent* event)
|
void ViewerWidget::DragEntered(QDragEnterEvent* event)
|
||||||
{
|
{
|
||||||
if (event->mimeData()->formats().contains(Project::kItemMimeType)) {
|
if (event->mimeData()->formats().contains(Project::kItemMimeType)) {
|
||||||
|
|||||||
@@ -291,8 +291,6 @@ private slots:
|
|||||||
|
|
||||||
void SetZoomFromMenu(QAction* action);
|
void SetZoomFromMenu(QAction* action);
|
||||||
|
|
||||||
void ViewerShiftedRange(const olive::rational& from, const olive::rational& to);
|
|
||||||
|
|
||||||
void UpdateStack();
|
void UpdateStack();
|
||||||
|
|
||||||
void ContextMenuSetFullScreen(QAction* action);
|
void ContextMenuSetFullScreen(QAction* action);
|
||||||
|
|||||||
Reference in New Issue
Block a user