diff --git a/app/dialog/speedduration/speedduration.cpp b/app/dialog/speedduration/speedduration.cpp index b3c7480d6..1c279ae86 100644 --- a/app/dialog/speedduration/speedduration.cpp +++ b/app/dialog/speedduration/speedduration.cpp @@ -41,7 +41,7 @@ SpeedDurationDialog::SpeedDurationDialog(const rational& timebase, const QListspeed(), this_clip->speed())) { + && prev_clip->speed() == this_clip->speed()) { same_speed = false; } @@ -75,7 +75,7 @@ SpeedDurationDialog::SpeedDurationDialog(const rational& timebase, const QListSetValue(clips_.first()->speed()); + speed_slider_->SetValue(clips_.first()->speed().toDouble()); } else { // Else, we show an invalid initial state speed_slider_->SetTristate(); @@ -208,7 +208,7 @@ void SpeedDurationDialog::accept() } else { // Otherwise we have to create a new gap GapBlock* gap = new GapBlock(); - gap->set_length(gap_length); + gap->set_length_and_media_out(gap_length); new NodeAddCommand(static_cast(clip->parent()), gap, command); new TrackInsertBlockBetweenBlocksCommand(TrackOutput::TrackFromBlock(clip), gap, clip, next_block, command); } @@ -222,18 +222,15 @@ void SpeedDurationDialog::accept() } if (change_speed) { - int64_t new_clip_duration = Timecode::time_to_timestamp(new_clip_length, timebase_); - int64_t new_media_duration = qRound(static_cast(new_clip_duration) * new_speed); - rational new_media_length = Timecode::timestamp_to_time(new_media_duration, timebase_); + rational new_block_speed = rational::fromDouble(new_speed); if (clip->is_reversed()) { - new_media_length = -new_media_length; + new_block_speed = -new_block_speed; } - rational new_media_out = clip->media_in() + new_media_length; - // Change the speed by calculating the appropriate media out point for this clip - new BlockSetMediaOutCommand(clip, new_media_out, command); + + new BlockSetSpeedCommand(clip, new_block_speed, command); } if (!reverse_speed_checkbox_->isTristate() && clip->is_reversed() != reverse_speed_checkbox_->isChecked()) { @@ -251,7 +248,7 @@ double SpeedDurationDialog::GetUnadjustedLengthTimestamp(ClipBlock *clip) const double duration = static_cast(Timecode::time_to_timestamp(clip->length(), timebase_)); // Convert duration to non-speed adjusted duration - duration *= clip->speed(); + duration *= clip->speed().toDouble(); return duration; } @@ -343,13 +340,11 @@ BlockReverseCommand::BlockReverseCommand(Block *block, QUndoCommand *parent) : void BlockReverseCommand::redo() { - rational temp = block_->media_in(); block_->set_media_in(block_->media_out()); - block_->set_media_out(temp); + block_->set_speed(-block_->speed()); } void BlockReverseCommand::undo() { - // Since it's a simple swap, we can just run redo() again redo(); } diff --git a/app/dialog/speedduration/speedduration.h b/app/dialog/speedduration/speedduration.h index 6dec3968e..69a9b2acd 100644 --- a/app/dialog/speedduration/speedduration.h +++ b/app/dialog/speedduration/speedduration.h @@ -53,6 +53,7 @@ public: private: Block* block_; + }; #endif // SPEEDDURATIONDIALOG_H diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index db61f1f59..6bb655aac 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -39,10 +39,11 @@ Block::Block() : media_in_input_->set_is_keyframable(false); AddInput(media_in_input_); - media_out_input_ = new NodeInput("media_out_in", NodeParam::kRational); - media_out_input_->SetConnectable(false); - media_out_input_->set_is_keyframable(false); - AddInput(media_out_input_); + speed_input_ = new NodeInput("speed_in", NodeParam::kRational); + speed_input_->set_standard_value(QVariant::fromValue(rational(1))); + speed_input_->SetConnectable(false); + speed_input_->set_is_keyframable(false); + AddInput(speed_input_); // A block's length must be greater than 0 set_length_and_media_out(1); @@ -78,7 +79,7 @@ rational Block::length() const return length_input_->get_standard_value().value(); } -void Block::set_length(const rational &length) +void Block::set_length_and_media_out(const rational &length) { Q_ASSERT(length > 0); @@ -89,26 +90,6 @@ void Block::set_length(const rational &length) length_input_->set_standard_value(QVariant::fromValue(length)); } -void Block::set_length_and_media_out(const rational &length) -{ - Q_ASSERT(length > 0); - - if (length == this->length()) { - return; - } - - rational media_out_diff = length - this->length(); - - // Try to maintain the same speed (which is determined by the media in to out points) - if (media_length() != this->length()) { - media_out_diff = media_out_diff / this->length() * media_length(); - } - - set_media_out(media_out() + media_out_diff); - - set_length(length); -} - void Block::set_length_and_media_in(const rational &length) { Q_ASSERT(length > 0); @@ -117,18 +98,11 @@ void Block::set_length_and_media_in(const rational &length) return; } - rational media_in_diff = this->length() - length; - - // Try to maintain the same speed (which is determined by the media in to out points) - if (media_length() != this->length()) { - media_in_diff = media_in_diff / this->length() * media_length(); - } - // Calculate media_in adjustment - set_media_in(media_in() + media_in_diff); + set_media_in(media_in() + (this->length() - length) * speed()); // Set the length without setting media out - set_length(length); + set_length_and_media_out(length); } Block *Block::previous() @@ -163,32 +137,27 @@ void Block::set_media_in(const rational &media_in) rational Block::media_out() const { - return media_out_input_->get_standard_value().value(); + return media_in() + length() * speed(); } -void Block::set_media_out(const rational &media_out) +rational Block::speed() const { - media_out_input_->set_standard_value(QVariant::fromValue(media_out)); + return speed_input_->get_standard_value().value(); } -rational Block::media_length() const +void Block::set_speed(const rational &speed) { - return media_out() - media_in(); -} - -double Block::speed() const -{ - return qAbs(media_length().toDouble() / length().toDouble()); + speed_input_->set_standard_value(QVariant::fromValue(speed)); } bool Block::is_still() const { - return (media_in() == media_out()); + return speed() == 0; } bool Block::is_reversed() const { - return (media_out() < media_in()); + return speed() < 0; } const QString &Block::block_name() const @@ -208,7 +177,7 @@ rational Block::SequenceToMediaTime(const rational &sequence_time) const return sequence_time; } - return ((sequence_time - in()) * media_length() / length()) + media_in(); + return (sequence_time - in()) * speed() + media_in(); } rational Block::MediaToSequenceTime(const rational &media_time) const @@ -218,21 +187,12 @@ rational Block::MediaToSequenceTime(const rational &media_time) const return media_time; } - return (media_time - media_in()) * length() / media_length() + in(); + return (media_time - media_in()) / speed() + in(); } void Block::CopyParameters(const Block *source, Block *dest) { dest->set_block_name(source->block_name()); - - if (source->type() == kTransition && dest->type() == kTransition) { - const TransitionBlock* src_t = static_cast(source); - TransitionBlock* dst_t = static_cast(dest); - - dst_t->set_in_and_out_offset(src_t->in_offset(), src_t->out_offset()); - } else { - dest->set_length_and_media_out(source->length()); - } } void Block::LengthInputChanged() @@ -308,8 +268,8 @@ NodeInput *Block::media_in_input() const return media_in_input_; } -NodeInput *Block::media_out_input() const +NodeInput *Block::speed_input() const { - return media_out_input_; + return speed_input_; } diff --git a/app/node/block/block.h b/app/node/block/block.h index 5733ae9b2..7976e271b 100644 --- a/app/node/block/block.h +++ b/app/node/block/block.h @@ -56,9 +56,8 @@ public: void set_out(const rational& out); rational length() const; - virtual void set_length(const rational &length); - virtual void set_length_and_media_out(const rational &length); - virtual void set_length_and_media_in(const rational &length); + void set_length_and_media_out(const rational &length); + void set_length_and_media_in(const rational &length); Block* previous(); Block* next(); @@ -69,10 +68,9 @@ public: void set_media_in(const rational& media_in); rational media_out() const; - void set_media_out(const rational& media_out); - rational media_length() const; - double speed() const; + rational speed() const; + void set_speed(const rational& speed); bool is_still() const; bool is_reversed() const; @@ -92,7 +90,7 @@ public: NodeInput* length_input() const; NodeInput* media_in_input() const; - NodeInput* media_out_input() const; + NodeInput* speed_input() const; public slots: @@ -119,7 +117,7 @@ protected: private: NodeInput* length_input_; NodeInput* media_in_input_; - NodeInput* media_out_input_; + NodeInput* speed_input_; rational in_point_; rational out_point_; diff --git a/app/node/block/transition/transition.cpp b/app/node/block/transition/transition.cpp index 1e83cb780..7e4b8c439 100644 --- a/app/node/block/transition/transition.cpp +++ b/app/node/block/transition/transition.cpp @@ -1,6 +1,8 @@ #include "transition.h" -TransitionBlock::TransitionBlock() +TransitionBlock::TransitionBlock() : + connected_out_block_(nullptr), + connected_in_block_(nullptr) { out_block_input_ = new NodeInput("out_block_in", NodeParam::kBuffer); out_block_input_->set_is_keyframable(false); @@ -9,9 +11,6 @@ TransitionBlock::TransitionBlock() in_block_input_ = new NodeInput("in_block_in", NodeParam::kBuffer); in_block_input_->set_is_keyframable(false); AddInput(in_block_input_); - - // A block's length must be greater than 0 - set_in_and_out_offset(1, 1); } Block::Type TransitionBlock::type() const @@ -35,38 +34,12 @@ void TransitionBlock::Retranslate() in_block_input_->set_name(tr("To")); } -void TransitionBlock::set_length_and_media_out(const rational &length) +rational TransitionBlock::in_offset() const { - Q_UNUSED(length) - qCritical() << "Set length is not permitted on a transition"; - abort(); + return 0; } -void TransitionBlock::set_length_and_media_in(const rational &length) +rational TransitionBlock::out_offset() const { - Q_UNUSED(length) - qCritical() << "Set length and media in is not permitted on a transition"; - abort(); -} - -const rational &TransitionBlock::in_offset() const -{ - return in_offset_; -} - -const rational &TransitionBlock::out_offset() const -{ - return out_offset_; -} - -void TransitionBlock::set_in_and_out_offset(const rational &in_offset, const rational &out_offset) -{ - in_offset_ = in_offset; - out_offset_ = out_offset; - RecalculateLength(); -} - -void TransitionBlock::RecalculateLength() -{ - Block::set_length_and_media_out(in_offset_ + out_offset_); + return 0; } diff --git a/app/node/block/transition/transition.h b/app/node/block/transition/transition.h index 21e709a09..b230f6016 100644 --- a/app/node/block/transition/transition.h +++ b/app/node/block/transition/transition.h @@ -15,23 +15,17 @@ public: virtual void Retranslate() override; - virtual void set_length_and_media_out(const rational &length) override; - virtual void set_length_and_media_in(const rational &length) override; - - const rational& in_offset() const; - const rational& out_offset() const; - void set_in_and_out_offset(const rational& in_offset, const rational& out_offset); + rational in_offset() const; + rational out_offset() const; private: - void RecalculateLength(); - NodeInput* out_block_input_; NodeInput* in_block_input_; - rational in_offset_; + Block* connected_out_block_; - rational out_offset_; + Block* connected_in_block_; }; diff --git a/app/render/backend/audiorenderworker.cpp b/app/render/backend/audiorenderworker.cpp index 25d66eba1..cf8978f5b 100644 --- a/app/render/backend/audiorenderworker.cpp +++ b/app/render/backend/audiorenderworker.cpp @@ -52,10 +52,10 @@ NodeValueTable AudioRenderWorker::RenderBlock(const TrackOutput *track, const Ti if (!samples_from_this_block.isEmpty()) { // Stretch samples here - if (b->media_length() != b->length()) { + if (b->speed() != 1) { QByteArray speed_adjusted_samples; - double clip_speed = b->speed(); + double clip_speed = b->speed().toDouble(); int sample_count = audio_params_.bytes_to_samples(samples_from_this_block.size()); diff --git a/app/render/backend/videorenderworker.cpp b/app/render/backend/videorenderworker.cpp index 75c8b295c..86745d8c6 100644 --- a/app/render/backend/videorenderworker.cpp +++ b/app/render/backend/videorenderworker.cpp @@ -90,7 +90,7 @@ void VideoRenderWorker::HashNodeRecursively(QCryptographicHash *hash, const Node // Ignore some Block attributes when hashing if (input == b->media_in_input() - || input == b->media_out_input() + || input == b->speed_input() || input == b->length_input()) { continue; } diff --git a/app/widget/timelinewidget/tool/slip.cpp b/app/widget/timelinewidget/tool/slip.cpp index f62212cdb..b13f5297e 100644 --- a/app/widget/timelinewidget/tool/slip.cpp +++ b/app/widget/timelinewidget/tool/slip.cpp @@ -75,7 +75,6 @@ void TimelineWidget::SlipTool::MouseReleaseInternal(TimelineViewMouseEvent *even Block* b = Node::ValueToPtr(ghost->data(TimelineViewGhostItem::kAttachedBlock)); new BlockSetMediaInCommand(b, ghost->GetAdjustedMediaIn(), command); - new BlockSetMediaOutCommand(b, ghost->GetAdjustedMediaIn() + b->media_length(), command); } Core::instance()->undo_stack()->pushIfHasChildren(command); diff --git a/app/widget/timelinewidget/tool/transition.cpp b/app/widget/timelinewidget/tool/transition.cpp index ec552d45e..346f49424 100644 --- a/app/widget/timelinewidget/tool/transition.cpp +++ b/app/widget/timelinewidget/tool/transition.cpp @@ -104,7 +104,8 @@ void TimelineWidget::TransitionTool::MouseRelease(TimelineViewMouseEvent *event) command); if (dual_transition_) { - transition->set_in_and_out_offset(ghost_->AdjustedLength()/2, ghost_->AdjustedLength()/2); + //transition->set_in_and_out_offset(ghost_->AdjustedLength()/2, ghost_->AdjustedLength()/2); + transition->set_length_and_media_out(ghost_->AdjustedLength()); // Block mouse is hovering over Block* active_block = Node::ValueToPtr(ghost_->data(TimelineViewGhostItem::kAttachedBlock)); @@ -129,10 +130,10 @@ void TimelineWidget::TransitionTool::MouseRelease(TimelineViewMouseEvent *event) NodeInput* transition_input_to_connect; if (ghost_->mode() == Timeline::kTrimIn) { - transition->set_in_and_out_offset(ghost_->AdjustedLength(), 0); + transition->set_length_and_media_out(ghost_->AdjustedLength()); transition_input_to_connect = transition->in_block_input(); } else { - transition->set_in_and_out_offset(0, ghost_->AdjustedLength()); + transition->set_length_and_media_out(ghost_->AdjustedLength()); transition_input_to_connect = transition->out_block_input(); } diff --git a/app/widget/timelinewidget/undo/undo.cpp b/app/widget/timelinewidget/undo/undo.cpp index b22e902db..8c2a69a40 100644 --- a/app/widget/timelinewidget/undo/undo.cpp +++ b/app/widget/timelinewidget/undo/undo.cpp @@ -48,24 +48,6 @@ void BlockResizeCommand::undo() block_->set_length_and_media_out(old_length_); } -BlockResizeWithoutMediaOutCommand::BlockResizeWithoutMediaOutCommand(Block *block, rational new_length, QUndoCommand *parent) : - QUndoCommand(parent), - block_(block), - old_length_(block->length()), - new_length_(new_length) -{ -} - -void BlockResizeWithoutMediaOutCommand::redo() -{ - block_->set_length(new_length_); -} - -void BlockResizeWithoutMediaOutCommand::undo() -{ - block_->set_length(old_length_); -} - BlockResizeWithMediaInCommand::BlockResizeWithMediaInCommand(Block *block, rational new_length, QUndoCommand *parent) : QUndoCommand(parent), block_(block), @@ -102,24 +84,6 @@ void BlockSetMediaInCommand::undo() block_->set_media_in(old_media_in_); } -BlockSetMediaOutCommand::BlockSetMediaOutCommand(Block *block, rational new_media_out, QUndoCommand *parent) : - QUndoCommand(parent), - block_(block), - old_media_out_(block->media_out()), - new_media_out_(new_media_out) -{ -} - -void BlockSetMediaOutCommand::redo() -{ - block_->set_media_out(new_media_out_); -} - -void BlockSetMediaOutCommand::undo() -{ - block_->set_media_out(old_media_out_); -} - TrackRippleRemoveBlockCommand::TrackRippleRemoveBlockCommand(TrackOutput *track, Block *block, QUndoCommand *parent) : QUndoCommand(parent), track_(track), @@ -411,13 +375,10 @@ void BlockSplitCommand::redo() Node::CopyInputs(block_, new_block_); rational new_part_length = block_->length() - (point_ - block_->in()); - rational original_media_out = block_->media_out(); block_->set_length_and_media_out(new_length_); - new_block_->set_length(new_part_length); - new_block_->set_media_in(block_->media_out()); - new_block_->set_media_out(original_media_out); + new_block_->set_length_and_media_in(new_part_length); track_->InsertBlockAfter(new_block_, block_); @@ -588,7 +549,7 @@ void TrackCleanGapsCommand::redo() new_gap_length += gap->length(); } - on_gap->set_length(new_gap_length); + on_gap->set_length_and_media_out(new_gap_length); track->UnblockInvalidateCache(); // Reset state @@ -624,7 +585,7 @@ void TrackCleanGapsCommand::undo() for (int i=merged_gaps_.size()-1;i>=0;i--) { const MergedGap& merge_info = merged_gaps_.at(i); - merge_info.merged->set_length(merge_info.original_length); + merge_info.merged->set_length_and_media_out(merge_info.original_length); GapBlock* last_gap_added = merge_info.merged; @@ -638,3 +599,21 @@ void TrackCleanGapsCommand::undo() merged_gaps_.clear(); } + +BlockSetSpeedCommand::BlockSetSpeedCommand(Block *block, const rational &new_speed, QUndoCommand *parent) : + QUndoCommand(parent), + block_(block), + old_speed_(block->speed()), + new_speed_(new_speed) +{ +} + +void BlockSetSpeedCommand::redo() +{ + block_->set_speed(new_speed_); +} + +void BlockSetSpeedCommand::undo() +{ + block_->set_speed(old_speed_); +} diff --git a/app/widget/timelinewidget/undo/undo.h b/app/widget/timelinewidget/undo/undo.h index 29b51871d..e2e91dc88 100644 --- a/app/widget/timelinewidget/undo/undo.h +++ b/app/widget/timelinewidget/undo/undo.h @@ -41,19 +41,6 @@ private: rational new_length_; }; -class BlockResizeWithoutMediaOutCommand : public QUndoCommand { -public: - BlockResizeWithoutMediaOutCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr); - - virtual void redo() override; - virtual void undo() override; - -private: - Block* block_; - rational old_length_; - rational new_length_; -}; - class BlockResizeWithMediaInCommand : public QUndoCommand { public: BlockResizeWithMediaInCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr); @@ -80,17 +67,18 @@ private: rational new_media_in_; }; -class BlockSetMediaOutCommand : public QUndoCommand { +class BlockSetSpeedCommand : public QUndoCommand { public: - BlockSetMediaOutCommand(Block* block, rational new_media_out, QUndoCommand* parent = nullptr); + BlockSetSpeedCommand(Block* block, const rational& new_speed, QUndoCommand* parent = nullptr); virtual void redo() override; virtual void undo() override; private: Block* block_; - rational old_media_out_; - rational new_media_out_; + + rational old_speed_; + rational new_speed_; }; class TrackRippleRemoveBlockCommand : public QUndoCommand {