removed speed/duration dialog
This is the first step in what will eventually be keyframable time remapping. The speed/duration dialog was a holdover from 0.1 and we can probably do better here.
This commit is contained in:
@@ -27,7 +27,6 @@ add_subdirectory(projectproperties)
|
||||
add_subdirectory(rendercancel)
|
||||
add_subdirectory(richtext)
|
||||
add_subdirectory(sequence)
|
||||
add_subdirectory(speedduration)
|
||||
add_subdirectory(task)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2019 Olive Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
dialog/speedduration/speedduration.h
|
||||
dialog/speedduration/speedduration.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -1,354 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "speedduration.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "core.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
#include "widget/timelinewidget/undo/undo.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
SpeedDurationDialog::SpeedDurationDialog(const rational& timebase, const QList<ClipBlock *> &clips, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
clips_(clips),
|
||||
timebase_(timebase)
|
||||
{
|
||||
setWindowTitle(tr("Speed/Duration"));
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
{
|
||||
// Create groupbox for the speed/duration
|
||||
QGroupBox* speed_groupbox = new QGroupBox(tr("Speed/Duration"));
|
||||
layout->addWidget(speed_groupbox);
|
||||
QGridLayout* speed_layout = new QGridLayout(speed_groupbox);
|
||||
|
||||
int row = 0;
|
||||
|
||||
// For any other clips that are selected, determine if they share speeds and lengths. If they don't, the UI can't
|
||||
// show them all as having the same parameters
|
||||
bool same_speed = true;
|
||||
bool same_duration = true;
|
||||
bool all_reversed = true;
|
||||
|
||||
for (int i=1;i<clips.size();i++) {
|
||||
ClipBlock* prev_clip = clips_.at(i-1);
|
||||
ClipBlock* this_clip = clips_.at(i);
|
||||
|
||||
// Check if the speeds are different
|
||||
if (same_speed
|
||||
&& qAbs(prev_clip->speed()) != qAbs(this_clip->speed())) {
|
||||
same_speed = false;
|
||||
}
|
||||
|
||||
// Check if the durations are different
|
||||
if (same_duration
|
||||
&& prev_clip->length() != this_clip->length()) {
|
||||
same_duration = false;
|
||||
}
|
||||
|
||||
// Check if all are reversed
|
||||
if (all_reversed
|
||||
&& prev_clip->is_reversed() != this_clip->is_reversed()) {
|
||||
all_reversed = false;
|
||||
}
|
||||
|
||||
// If we've already determined both are different, no need to continue
|
||||
if (!same_speed
|
||||
&& !same_duration
|
||||
&& !all_reversed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
speed_layout->addWidget(new QLabel(tr("Speed:")), row, 0);
|
||||
|
||||
// Create "Speed" slider
|
||||
speed_slider_ = new FloatSlider();
|
||||
speed_slider_->SetMinimum(0);
|
||||
speed_slider_->SetDisplayType(FloatSlider::kPercentage);
|
||||
speed_slider_->SetDefaultValue(1);
|
||||
speed_layout->addWidget(speed_slider_, row, 1);
|
||||
|
||||
if (same_speed) {
|
||||
// All clips share the same speed so we can show the value
|
||||
speed_slider_->SetValue(qAbs(clips_.first()->speed().toDouble()));
|
||||
} else {
|
||||
// Else, we show an invalid initial state
|
||||
speed_slider_->SetTristate();
|
||||
}
|
||||
|
||||
row++;
|
||||
|
||||
speed_layout->addWidget(new QLabel(tr("Duration:")), row, 0);
|
||||
|
||||
// Create "Duration" slider
|
||||
duration_slider_ = new TimeSlider();
|
||||
duration_slider_->SetTimebase(timebase_);
|
||||
duration_slider_->SetMinimum(1);
|
||||
speed_layout->addWidget(duration_slider_, row, 1);
|
||||
|
||||
// Calculate duration that would occur if the speed was 100%
|
||||
duration_slider_->SetDefaultValue(GetUnadjustedLengthTimestamp(clips_.first()));
|
||||
|
||||
if (same_duration) {
|
||||
duration_slider_->SetValue(Timecode::time_to_timestamp(clips_.first()->length(), timebase_));
|
||||
} else {
|
||||
duration_slider_->SetTristate();
|
||||
}
|
||||
|
||||
row++;
|
||||
|
||||
link_speed_and_duration_ = new QCheckBox(tr("Link Speed and Duration"));
|
||||
link_speed_and_duration_->setChecked(true);
|
||||
speed_layout->addWidget(link_speed_and_duration_, row, 0, 1, 2);
|
||||
|
||||
// Pick up when the speed or duration slider changes so we can programmatically link them
|
||||
connect(speed_slider_, &FloatSlider::ValueChanged, this, &SpeedDurationDialog::SpeedChanged);
|
||||
connect(duration_slider_, &TimeSlider::ValueChanged, this, &SpeedDurationDialog::DurationChanged);
|
||||
|
||||
reverse_speed_checkbox_ = new QCheckBox(tr("Reverse Speed"));
|
||||
if (all_reversed) {
|
||||
reverse_speed_checkbox_->setChecked(clips_.first()->is_reversed());
|
||||
} else {
|
||||
reverse_speed_checkbox_->setTristate();
|
||||
}
|
||||
layout->addWidget(reverse_speed_checkbox_);
|
||||
}
|
||||
|
||||
maintain_audio_pitch_checkbox_ = new QCheckBox(tr("Maintain Audio Pitch"));
|
||||
layout->addWidget(maintain_audio_pitch_checkbox_);
|
||||
|
||||
ripple_clips_checkbox_ = new QCheckBox(tr("Ripple Clips"));
|
||||
layout->addWidget(ripple_clips_checkbox_);
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
buttons->setCenterButtons(true);
|
||||
layout->addWidget(buttons);
|
||||
connect(buttons, &QDialogButtonBox::accepted, this, &SpeedDurationDialog::accept);
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, &SpeedDurationDialog::reject);
|
||||
}
|
||||
|
||||
void SpeedDurationDialog::accept()
|
||||
{
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
|
||||
bool change_duration = !duration_slider_->IsTristate() || (!speed_slider_->IsTristate() && link_speed_and_duration_->isChecked());
|
||||
bool change_speed = !speed_slider_->IsTristate() || (!duration_slider_->IsTristate() && link_speed_and_duration_->isChecked());
|
||||
|
||||
foreach (ClipBlock* clip, clips_) {
|
||||
double new_speed = speed_slider_->GetValue();
|
||||
|
||||
if (change_duration) {
|
||||
// Change the duration
|
||||
int64_t current_duration = Timecode::time_to_timestamp(clip->length(), timebase_);
|
||||
int64_t new_duration = current_duration;
|
||||
|
||||
// Check if we're getting the duration value directly from the slider or calculating it from the speed
|
||||
if (duration_slider_->IsTristate()) {
|
||||
// Calculate duration from speed
|
||||
new_duration = GetAdjustedDuration(clip, new_speed);
|
||||
} else {
|
||||
// Get duration directly from slider
|
||||
new_duration = duration_slider_->GetValue();
|
||||
|
||||
// Check if we're calculating the speed from this duration
|
||||
if (speed_slider_->IsTristate() && change_speed) {
|
||||
// If we're here, the duration is going to override the speed
|
||||
new_speed = GetAdjustedSpeed(clip, new_duration);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_duration != current_duration) {
|
||||
// Calculate new clip length
|
||||
rational new_clip_length = Timecode::timestamp_to_time(new_duration, timebase_);
|
||||
|
||||
if (ripple_clips_checkbox_->isChecked()) {
|
||||
|
||||
// FIXME: Make this a REAL ripple...
|
||||
new BlockResizeCommand(clip, new_clip_length, command);
|
||||
|
||||
} else {
|
||||
|
||||
// If "ripple clips" isn't checked, we may be limited to how much we can change the length
|
||||
Block* next_block = clip->next();
|
||||
if (next_block) {
|
||||
if (new_clip_length > clip->length()) {
|
||||
if (next_block->type() == Block::kGap) {
|
||||
// Check if next clip is a gap, and if so we can take it all up
|
||||
new_clip_length = qMin(next_block->out(), clip->in() + new_clip_length);
|
||||
} else {
|
||||
// Otherwise we can't extend any further
|
||||
new_clip_length = clip->length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_clip_length != clip->length()) {
|
||||
new BlockTrimCommand(TrackOutput::TrackFromBlock(clip), clip, new_clip_length, Timeline::kTrimOut, command);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (change_speed) {
|
||||
rational new_block_speed = rational::fromDouble(new_speed);
|
||||
|
||||
if (clip->is_reversed()) {
|
||||
new_block_speed = -new_block_speed;
|
||||
}
|
||||
|
||||
// Change the speed
|
||||
new BlockSetSpeedCommand(clip, new_block_speed, command);
|
||||
}
|
||||
|
||||
if (!reverse_speed_checkbox_->isTristate()
|
||||
&& clip->is_reversed() != reverse_speed_checkbox_->isChecked()) {
|
||||
new BlockReverseCommand(clip, command);
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
double SpeedDurationDialog::GetUnadjustedLengthTimestamp(ClipBlock *clip) const
|
||||
{
|
||||
double duration = static_cast<double>(Timecode::time_to_timestamp(clip->length(), timebase_));
|
||||
|
||||
// Convert duration to non-speed adjusted duration
|
||||
duration *= qAbs(clip->speed().toDouble());
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
int64_t SpeedDurationDialog::GetAdjustedDuration(ClipBlock *clip, const double &new_speed) const
|
||||
{
|
||||
double duration = GetUnadjustedLengthTimestamp(clip);
|
||||
|
||||
// Re-adjust by new speed
|
||||
duration /= new_speed;
|
||||
|
||||
// Return rounded time
|
||||
return qRound64(duration);
|
||||
}
|
||||
|
||||
double SpeedDurationDialog::GetAdjustedSpeed(ClipBlock *clip, const int64_t &new_duration) const
|
||||
{
|
||||
double duration = GetUnadjustedLengthTimestamp(clip);
|
||||
|
||||
// Create a fraction of the original duration over the new duration
|
||||
duration /= static_cast<double>(new_duration);
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
void SpeedDurationDialog::SpeedChanged()
|
||||
{
|
||||
if (link_speed_and_duration_->isChecked()) {
|
||||
double new_speed = speed_slider_->GetValue();
|
||||
|
||||
if (qIsNull(new_speed)) {
|
||||
// A speed of 0 is considered a still frame. Since we can't divide by zero and a still frame could be any length,
|
||||
// we don't bother updating the
|
||||
return;
|
||||
}
|
||||
|
||||
bool same_durations = true;
|
||||
int64_t new_duration = GetAdjustedDuration(clips_.first(), new_speed);
|
||||
|
||||
for (int i=1;i<clips_.size();i++) {
|
||||
// Calculate what this clip's duration will be
|
||||
int64_t this_clip_duration = GetAdjustedDuration(clips_.at(i), new_speed);
|
||||
|
||||
// If they won't be the same, we won't show the value
|
||||
if (this_clip_duration != new_duration) {
|
||||
same_durations = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (same_durations) {
|
||||
duration_slider_->SetValue(new_duration);
|
||||
} else {
|
||||
duration_slider_->SetTristate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpeedDurationDialog::DurationChanged()
|
||||
{
|
||||
if (link_speed_and_duration_->isChecked()) {
|
||||
int64_t new_duration = duration_slider_->GetValue();
|
||||
|
||||
bool same_speeds = true;
|
||||
double new_speed = GetAdjustedSpeed(clips_.first(), new_duration);
|
||||
|
||||
for (int i=1;i<clips_.size();i++) {
|
||||
double this_clip_speed = GetAdjustedSpeed(clips_.at(i), new_duration);
|
||||
|
||||
if (!qFuzzyCompare(this_clip_speed, new_speed)) {
|
||||
same_speeds = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (same_speeds) {
|
||||
speed_slider_->SetValue(new_speed);
|
||||
} else {
|
||||
speed_slider_->SetTristate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlockReverseCommand::BlockReverseCommand(Block *block, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
block_(block)
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockReverseCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockReverseCommand::redo_internal()
|
||||
{
|
||||
block_->set_media_in(block_->media_out());
|
||||
block_->set_speed(-block_->speed());
|
||||
}
|
||||
|
||||
void BlockReverseCommand::undo_internal()
|
||||
{
|
||||
redo_internal();
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -1,86 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef SPEEDDURATIONDIALOG_H
|
||||
#define SPEEDDURATIONDIALOG_H
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
|
||||
#include "node/block/clip/clip.h"
|
||||
#include "node/output/track/track.h"
|
||||
#include "widget/slider/floatslider.h"
|
||||
#include "widget/slider/timeslider.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class SpeedDurationDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SpeedDurationDialog(const rational& timebase, const QList<ClipBlock*>& clips, QWidget* parent = nullptr);
|
||||
|
||||
public slots:
|
||||
virtual void accept() override;
|
||||
|
||||
private:
|
||||
double GetUnadjustedLengthTimestamp(ClipBlock* clip) const;
|
||||
|
||||
int64_t GetAdjustedDuration(ClipBlock* clip, const double& new_speed) const;
|
||||
|
||||
double GetAdjustedSpeed(ClipBlock* clip, const int64_t& new_duration) const;
|
||||
|
||||
QList<ClipBlock*> clips_;
|
||||
|
||||
FloatSlider* speed_slider_;
|
||||
TimeSlider* duration_slider_;
|
||||
|
||||
rational timebase_;
|
||||
|
||||
QCheckBox* link_speed_and_duration_;
|
||||
QCheckBox* reverse_speed_checkbox_;
|
||||
QCheckBox* maintain_audio_pitch_checkbox_;
|
||||
QCheckBox* ripple_clips_checkbox_;
|
||||
|
||||
private slots:
|
||||
void SpeedChanged();
|
||||
|
||||
void DurationChanged();
|
||||
};
|
||||
|
||||
class BlockReverseCommand : public UndoCommand {
|
||||
public:
|
||||
BlockReverseCommand(Block* block, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Block* block_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // SPEEDDURATIONDIALOG_H
|
||||
+39
-32
@@ -49,10 +49,8 @@ Block::Block() :
|
||||
enabled_input_->set_standard_value(true);
|
||||
AddInput(enabled_input_);
|
||||
|
||||
speed_input_ = new NodeInput("speed_in", NodeParam::kRational);
|
||||
speed_input_->set_standard_value(QVariant::fromValue(rational(1)));
|
||||
speed_input_->set_connectable(false);
|
||||
speed_input_->set_is_keyframable(false);
|
||||
speed_input_ = new NodeInput("speed_in", NodeParam::kFloat);
|
||||
speed_input_->set_standard_value(1.0);
|
||||
AddInput(speed_input_);
|
||||
|
||||
// A block's length must be greater than 0
|
||||
@@ -113,7 +111,7 @@ void Block::set_length_and_media_in(const rational &length)
|
||||
}
|
||||
|
||||
// Calculate media_in adjustment
|
||||
set_media_in(media_in() + (this->length() - length) * speed());
|
||||
set_media_in(SequenceToMediaTime(in() + (this->length() - length)));
|
||||
|
||||
rational old_length = this->length();
|
||||
|
||||
@@ -153,31 +151,6 @@ void Block::set_media_in(const rational &media_in)
|
||||
media_in_input_->set_standard_value(QVariant::fromValue(media_in));
|
||||
}
|
||||
|
||||
rational Block::media_out() const
|
||||
{
|
||||
return media_in() + length() * speed();
|
||||
}
|
||||
|
||||
rational Block::speed() const
|
||||
{
|
||||
return speed_input_->get_standard_value().value<rational>();
|
||||
}
|
||||
|
||||
void Block::set_speed(const rational &speed)
|
||||
{
|
||||
speed_input_->set_standard_value(QVariant::fromValue(speed));
|
||||
}
|
||||
|
||||
bool Block::is_still() const
|
||||
{
|
||||
return speed() == 0;
|
||||
}
|
||||
|
||||
bool Block::is_reversed() const
|
||||
{
|
||||
return speed() < 0;
|
||||
}
|
||||
|
||||
bool Block::is_enabled() const
|
||||
{
|
||||
return enabled_input_->get_standard_value().toBool();
|
||||
@@ -197,7 +170,24 @@ rational Block::SequenceToMediaTime(const rational &sequence_time) const
|
||||
return sequence_time;
|
||||
}
|
||||
|
||||
return (sequence_time - in()) * speed() + media_in();
|
||||
rational local_time = sequence_time - in();
|
||||
|
||||
// FIXME: Doesn't handle reversing
|
||||
if (speed_input_->is_keyframing() || speed_input_->is_connected()) {
|
||||
// FIXME: We'll need to calculate the speed hoo boy
|
||||
} else {
|
||||
double speed_value = speed_input_->get_standard_value().toDouble();
|
||||
|
||||
if (qIsNull(speed_value)) {
|
||||
// Effectively holds the frame at the in point
|
||||
local_time = 0;
|
||||
} else if (!qFuzzyCompare(speed_value, 1.0)) {
|
||||
// Multiply time
|
||||
local_time = rational::fromDouble(local_time.toDouble() * speed_value);
|
||||
}
|
||||
}
|
||||
|
||||
return local_time + media_in();
|
||||
}
|
||||
|
||||
rational Block::MediaToSequenceTime(const rational &media_time) const
|
||||
@@ -207,7 +197,24 @@ rational Block::MediaToSequenceTime(const rational &media_time) const
|
||||
return media_time;
|
||||
}
|
||||
|
||||
return (media_time - media_in()) / speed() + in();
|
||||
rational sequence_time = media_time - media_in();
|
||||
|
||||
// FIXME: Doesn't handle reversing
|
||||
if (speed_input_->is_keyframing() || speed_input_->is_connected()) {
|
||||
// FIXME: We'll need to calculate the speed hoo boy
|
||||
} else {
|
||||
double speed_value = speed_input_->get_standard_value().toDouble();
|
||||
|
||||
if (qIsNull(speed_value)) {
|
||||
// Effectively holds the frame at the in point, also prevents divide by zero
|
||||
sequence_time = 0;
|
||||
} else if (!qFuzzyCompare(speed_value, 1.0)) {
|
||||
// Multiply time
|
||||
sequence_time = rational::fromDouble(sequence_time.toDouble() / speed_value);
|
||||
}
|
||||
}
|
||||
|
||||
return sequence_time + in();
|
||||
}
|
||||
|
||||
void Block::LoadInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data)
|
||||
|
||||
@@ -62,13 +62,6 @@ public:
|
||||
rational media_in() const;
|
||||
void set_media_in(const rational& media_in);
|
||||
|
||||
rational media_out() const;
|
||||
|
||||
rational speed() const;
|
||||
void set_speed(const rational& speed);
|
||||
bool is_still() const;
|
||||
bool is_reversed() const;
|
||||
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool e);
|
||||
|
||||
|
||||
@@ -189,16 +189,19 @@ NodeValueTable RenderWorker::GenerateBlockTable(const TrackOutput *track, const
|
||||
continue;
|
||||
}
|
||||
|
||||
// Stretch samples here
|
||||
rational abs_speed = qAbs(b->speed());
|
||||
// FIXME: Doesn't handle reversing
|
||||
if (b->speed_input()->is_keyframing() || b->speed_input()->is_connected()) {
|
||||
// FIXME: We'll need to calculate the speed hoo boy
|
||||
} else {
|
||||
double speed_value = b->speed_input()->get_standard_value().toDouble();
|
||||
|
||||
if (abs_speed != 1) {
|
||||
samples_from_this_block->speed(abs_speed.toDouble());
|
||||
}
|
||||
|
||||
if (b->is_reversed()) {
|
||||
// Reverse the audio buffer
|
||||
samples_from_this_block->reverse();
|
||||
if (qIsNull(speed_value)) {
|
||||
// Just silence, don't think there's any other practical application of 0 speed audio
|
||||
samples_from_this_block->fill(0);
|
||||
} else if (!qFuzzyCompare(speed_value, 1.0)) {
|
||||
// Multiply time
|
||||
samples_from_this_block->speed(speed_value);
|
||||
}
|
||||
}
|
||||
|
||||
int copy_length = qMin(max_dest_sz, samples_from_this_block->sample_count());
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "common/range.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "dialog/sequence/sequence.h"
|
||||
#include "dialog/speedduration/speedduration.h"
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "tool/tool.h"
|
||||
#include "trackview/trackview.h"
|
||||
@@ -1070,11 +1069,6 @@ void TimelineWidget::ShowContextMenu()
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
QAction* speed_duration_action = menu.addAction(tr("Speed/Duration"));
|
||||
connect(speed_duration_action, &QAction::triggered, this, &TimelineWidget::ShowSpeedDurationDialog);
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
QAction* properties_action = menu.addAction(tr("Properties"));
|
||||
connect(properties_action, &QAction::triggered, this, [this](){
|
||||
QList<TimelineViewBlockItem*> block_items = GetSelectedBlocks();
|
||||
@@ -1104,26 +1098,6 @@ void TimelineWidget::ShowContextMenu()
|
||||
menu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void TimelineWidget::ShowSpeedDurationDialog()
|
||||
{
|
||||
QList<TimelineViewBlockItem*> selected = GetSelectedBlocks();
|
||||
QList<ClipBlock*> selected_clips;
|
||||
|
||||
foreach (TimelineViewBlockItem* item, selected) {
|
||||
if (item->block()->type() == Block::kClip) {
|
||||
selected_clips.append(static_cast<ClipBlock*>(item->block()));
|
||||
}
|
||||
}
|
||||
|
||||
if (selected_clips.isEmpty()) {
|
||||
// SpeedDurationDialog expects at least one clip
|
||||
return;
|
||||
}
|
||||
|
||||
SpeedDurationDialog speed_diag(timebase(), selected_clips, this);
|
||||
speed_diag.exec();
|
||||
}
|
||||
|
||||
void TimelineWidget::DeferredScrollAction()
|
||||
{
|
||||
scrollbar()->setValue(deferred_scroll_value_);
|
||||
|
||||
@@ -558,8 +558,6 @@ private slots:
|
||||
|
||||
void ShowContextMenu();
|
||||
|
||||
void ShowSpeedDurationDialog();
|
||||
|
||||
void DeferredScrollAction();
|
||||
|
||||
void ShowSequenceDialog();
|
||||
|
||||
@@ -596,29 +596,6 @@ Project *BlockSplitPreservingLinksCommand::GetRelevantProject() const
|
||||
return static_cast<Sequence*>(blocks_.first()->parent())->project();
|
||||
}
|
||||
|
||||
BlockSetSpeedCommand::BlockSetSpeedCommand(Block *block, const rational &new_speed, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
block_(block),
|
||||
old_speed_(block->speed()),
|
||||
new_speed_(new_speed)
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockSetSpeedCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockSetSpeedCommand::redo_internal()
|
||||
{
|
||||
block_->set_speed(new_speed_);
|
||||
}
|
||||
|
||||
void BlockSetSpeedCommand::undo_internal()
|
||||
{
|
||||
block_->set_speed(old_speed_);
|
||||
}
|
||||
|
||||
TimelineRippleDeleteGapsAtRegionsCommand::TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput *vo, const TimeRangeList ®ions, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
timeline_(vo),
|
||||
|
||||
@@ -113,23 +113,6 @@ private:
|
||||
rational new_media_in_;
|
||||
};
|
||||
|
||||
class BlockSetSpeedCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSetSpeedCommand(Block* block, const rational& new_speed, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Block* block_;
|
||||
|
||||
rational old_speed_;
|
||||
rational new_speed_;
|
||||
};
|
||||
|
||||
class TrackRippleRemoveBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackRippleRemoveBlockCommand(TrackOutput* track, Block* block, QUndoCommand* parent = nullptr);
|
||||
|
||||
Reference in New Issue
Block a user