Add pitch compensation to speed effect (requires MLT git)

parent 55d0afae
Pipeline #14903 passed with stage
in 17 minutes and 20 seconds
......@@ -160,12 +160,12 @@ bool MeltJob::startJob()
return false;
}
if (m_out == -1) {
m_out = m_producer->get_playtime() - 1;
m_out = m_producer->get_length() - 1;
}
if (m_in == -1) {
m_in = 0;
}
if (m_out != m_producer->get_playtime() - 1 || m_in != 0) {
if (m_out != m_producer->get_length() - 1 || m_in != 0) {
std::swap(m_wholeProducer, m_producer);
m_producer.reset(m_wholeProducer->cut(m_in, m_out));
}
......@@ -241,9 +241,9 @@ bool MeltJob::startJob()
}
Mlt::Tractor tractor(*m_profile.get());
Mlt::Playlist playlist;
playlist.append(*m_producer.get());
Mlt::Playlist playlist(*m_profile.get());
tractor.set_track(playlist, 0);
playlist.append(*m_producer.get());
m_consumer->connect(tractor);
m_producer->set_speed(0);
m_producer->seek(0);
......
......@@ -43,9 +43,10 @@
#include <KLineEdit>
#include <mlt++/Mlt.h>
SpeedJob::SpeedJob(const QString &binId, double speed, QString destUrl)
SpeedJob::SpeedJob(const QString &binId, double speed, bool warp_pitch, QString destUrl)
: MeltJob(binId, SPEEDJOB, false, -1, -1)
, m_speed(speed)
, m_warp_pitch(warp_pitch)
, m_destUrl(std::move(destUrl))
{
m_requiresFilter = false;
......@@ -69,8 +70,15 @@ void SpeedJob::configureProducer()
if (!qFuzzyCompare(m_speed, 1.0)) {
QString resource = m_producer->get("resource");
m_producer = std::make_unique<Mlt::Producer>(*m_profile.get(), "timewarp", QStringLiteral("%1:%2").arg(QString::fromStdString(std::to_string(m_speed))).arg(resource).toUtf8().constData());
m_in /= m_speed;
m_out /= m_speed;
if (m_in > 0) {
m_in /= m_speed;
}
if (m_out > 0) {
m_out /= m_speed;
}
if (m_warp_pitch) {
m_producer->set("warp_pitch", 1);
}
}
}
......@@ -112,10 +120,13 @@ int SpeedJob::prepareJob(const std::shared_ptr<JobManager> &ptr, const std::vect
speedInput.setSuffix(QLatin1String("%"));
speedInput.setFocus();
speedInput.selectAll();
QCheckBox cb(i18n("Pitch compensation"), &d);
cb.setChecked(true);
l->addWidget(&labUrl);
l->addWidget(&fileUrl);
l->addWidget(&lab);
l->addWidget(&speedInput);
l->addWidget(&cb);
l->addWidget(&buttonBox);
d.connect(&buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
d.connect(&buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
......@@ -123,6 +134,7 @@ int SpeedJob::prepareJob(const std::shared_ptr<JobManager> &ptr, const std::vect
return -1;
}
double speed = speedInput.value();
bool warp_pitch = cb.isChecked();
std::unordered_map<QString, QString> destinations; // keys are binIds, values are path to target files
for (const auto &binId : binIds) {
QString mltfile;
......@@ -153,7 +165,7 @@ int SpeedJob::prepareJob(const std::shared_ptr<JobManager> &ptr, const std::vect
// Now we have to create the jobs objects. This is trickier than usual, since the parameters are different for each job (each clip has its own
// destination). We have to construct a lambda that does that.
auto createFn = [dest = std::move(destinations), fSpeed = speed / 100.0](const QString &id) { return std::make_shared<SpeedJob>(id, fSpeed, dest.at(id)); };
auto createFn = [dest = std::move(destinations), fSpeed = speed / 100.0, warp_pitch](const QString &id) { return std::make_shared<SpeedJob>(id, fSpeed, warp_pitch, dest.at(id)); };
// We are now all set to create the job. Note that we pass all the parameters directly through the lambda, hence there are no extra parameters to the
// function
......
......@@ -42,7 +42,7 @@ public:
/** @brief Creates a timewarp producer
@param speed The speed value
*/
SpeedJob(const QString &binId, double speed, QString destUrl);
SpeedJob(const QString &binId, double speed, bool warp_pitch, QString destUrl);
// This is a special function that prepares the stabilize job for a given list of clips.
// Namely, it displays the required UI to configure the job and call startJob with the right set of parameters
......@@ -63,5 +63,6 @@ protected:
void configureFilter() override;
double m_speed;
bool m_warp_pitch;
QString m_destUrl;
};
......@@ -69,7 +69,7 @@ ClipModel::ClipModel(const std::shared_ptr<TimelineModel> &parent, std::shared_p
});
}
int ClipModel::construct(const std::shared_ptr<TimelineModel> &parent, const QString &binClipId, int id, PlaylistState::ClipState state, double speed)
int ClipModel::construct(const std::shared_ptr<TimelineModel> &parent, const QString &binClipId, int id, PlaylistState::ClipState state, double speed, bool warp_pitch)
{
id = (id == -1 ? TimelineModel::getNextId() : id);
std::shared_ptr<ProjectClip> binClip = pCore->projectItemModel()->getClipByBinID(binClipId);
......@@ -81,6 +81,9 @@ int ClipModel::construct(const std::shared_ptr<TimelineModel> &parent, const QSt
state = stateFromBool(videoAudio);
std::shared_ptr<Mlt::Producer> cutProducer = binClip->getTimelineProducer(-1, id, state, speed);
std::shared_ptr<ClipModel> clip(new ClipModel(parent, cutProducer, binClipId, id, state, speed));
if (!qFuzzyCompare(speed, 1.)) {
cutProducer->parent().set("warp_pitch", warp_pitch ? 1 : 0);
}
TRACE_CONSTR(clip.get(), parent, binClipId, id, state, speed);
clip->setClipState_lambda(state)();
parent->registerClip(clip);
......@@ -106,11 +109,16 @@ int ClipModel::construct(const std::shared_ptr<TimelineModel> &parent, const QSt
state = stateFromBool(videoAudio);
double speed = 1.0;
bool warp_pitch = false;
if (QString::fromUtf8(producer->parent().get("mlt_service")) == QLatin1String("timewarp")) {
speed = producer->parent().get_double("warp_speed");
warp_pitch = producer->parent().get_int("warp_pitch");
}
auto result = binClip->giveMasterAndGetTimelineProducer(id, producer, state);
std::shared_ptr<ClipModel> clip(new ClipModel(parent, result.first, binClipId, id, state, speed));
if (warp_pitch) {
result.first->parent().set("warp_pitch", 1);
}
clip->setClipState_lambda(state)();
parent->registerClip(clip);
clip->m_effectStack->importEffects(producer, state, result.second);
......@@ -432,16 +440,12 @@ void ClipModel::refreshProducerFromBin(int trackId)
refreshProducerFromBin(trackId, m_currentState);
}
bool ClipModel::useTimewarpProducer(double speed, bool changeDuration, Fun &undo, Fun &redo)
bool ClipModel::useTimewarpProducer(double speed, bool pitchCompensate, bool changeDuration, Fun &undo, Fun &redo)
{
if (m_endlessResize) {
// no timewarp for endless producers
return false;
}
if (qFuzzyCompare(speed, m_speed)) {
// nothing to do
return true;
}
std::function<bool(void)> local_undo = []() { return true; };
std::function<bool(void)> local_redo = []() { return true; };
double previousSpeed = getSpeed();
......@@ -457,8 +461,9 @@ bool ClipModel::useTimewarpProducer(double speed, bool changeDuration, Fun &undo
} else if (previousSpeed < 0) {
revertSpeed = true;
}
auto operation = useTimewarpProducer_lambda(speed);
auto reverse = useTimewarpProducer_lambda(previousSpeed);
bool hasPitch = getIntProperty(QStringLiteral("warp_pitch"));
auto operation = useTimewarpProducer_lambda(speed, pitchCompensate);
auto reverse = useTimewarpProducer_lambda(previousSpeed, hasPitch);
if (revertSpeed || (changeDuration && oldOut >= newDuration)) {
// in that case, we are going to shrink the clip when changing the producer. We must undo that when reloading the old producer
reverse = [reverse, oldIn, oldOut, this]() {
......@@ -506,12 +511,13 @@ bool ClipModel::useTimewarpProducer(double speed, bool changeDuration, Fun &undo
return false;
}
Fun ClipModel::useTimewarpProducer_lambda(double speed)
Fun ClipModel::useTimewarpProducer_lambda(double speed, bool pitchCompensate)
{
QWriteLocker locker(&m_lock);
return [speed, this]() {
return [speed, pitchCompensate, this]() {
qDebug() << "timeWarp producer" << speed;
refreshProducerFromBin(m_currentTrackId, m_currentState, speed);
m_producer->parent().set("warp_pitch", pitchCompensate ? 1 : 0);
if (m_currentTrackId > -1) {
if (auto ptr = m_parent.lock()) {
QModelIndex ix = ptr->makeClipIndexFromID(m_id);
......@@ -730,6 +736,9 @@ QDomElement ClipModel::toXml(QDomDocument &document)
}
}
container.setAttribute(QStringLiteral("speed"), m_speed);
if (!qFuzzyCompare(m_speed, 1.)) {
container.setAttribute(QStringLiteral("warp_pitch"), getIntProperty(QStringLiteral("warp_pitch")));
}
container.appendChild(m_effectStack->toXml(document));
return container;
}
......
......@@ -57,7 +57,7 @@ public:
@param binClip is the id of the bin clip associated
@param id Requested id of the clip. Automatic if -1
*/
static int construct(const std::shared_ptr<TimelineModel> &parent, const QString &binClipId, int id, PlaylistState::ClipState state, double speed = 1.);
static int construct(const std::shared_ptr<TimelineModel> &parent, const QString &binClipId, int id, PlaylistState::ClipState state, double speed = 1., bool warp_pitch = false);
/* @brief Creates a clip, which references itself to the parent timeline
Returns the (unique) id of the created clip
......@@ -182,9 +182,9 @@ protected:
/* @brief This functions replaces the current producer with a slowmotion one
It also resizes the producer so that set of frames contained in the clip is the same
*/
bool useTimewarpProducer(double speed, bool changeDuration, Fun &undo, Fun &redo);
bool useTimewarpProducer(double speed, bool pitchCompensate, bool changeDuration, Fun &undo, Fun &redo);
// @brief Lambda that merely changes the speed (in and out are untouched)
Fun useTimewarpProducer_lambda(double speed);
Fun useTimewarpProducer_lambda(double speed, bool pitchCompensate);
/** @brief Returns the marker model associated with this clip */
std::shared_ptr<MarkerListModel> getMarkerModel() const;
......
......@@ -64,7 +64,8 @@ bool TimelineFunctions::cloneClip(const std::shared_ptr<TimelineItemModel> &time
{
// Special case: slowmotion clips
double clipSpeed = timeline->m_allClips[clipId]->getSpeed();
bool res = timeline->requestClipCreation(timeline->getClipBinId(clipId), newId, state, clipSpeed, undo, redo);
bool warp_pitch = timeline->m_allClips[clipId]->getIntProperty(QStringLiteral("warp_pitch"));
bool res = timeline->requestClipCreation(timeline->getClipBinId(clipId), newId, state, clipSpeed, warp_pitch, undo, redo);
timeline->m_allClips[newId]->m_endlessResize = timeline->m_allClips[clipId]->m_endlessResize;
// copy useful timeline properties
......@@ -1430,8 +1431,12 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
int curTrackId = tracksMap.value(prod.attribute(QStringLiteral("track")).toInt());
int pos = prod.attribute(QStringLiteral("position")).toInt() - offset;
double speed = locale.toDouble(prod.attribute(QStringLiteral("speed")));
bool warp_pitch = false;
if (!qFuzzyCompare(speed, 1.)) {
warp_pitch = prod.attribute(QStringLiteral("warp_pitch")).toInt();
}
int newId;
bool created = timeline->requestClipCreation(originalId, newId, timeline->getTrackById_const(curTrackId)->trackType(), speed, undo, redo);
bool created = timeline->requestClipCreation(originalId, newId, timeline->getTrackById_const(curTrackId)->trackType(), speed, warp_pitch, undo, redo);
if (created) {
// Master producer is ready
// ids.removeAll(originalId);
......
......@@ -97,7 +97,7 @@ RTTR_REGISTRATION
// .method("requestCompositionInsertion", select_overload<bool(const QString &, int, int, int, std::unique_ptr<Mlt::Properties>, int &, bool)>(
// &TimelineModel::requestCompositionInsertion))(
// parameter_names("transitionId", "trackId", "position", "length", "transProps", "id", "logUndo"))
.method("requestClipTimeWarp", select_overload<bool(int, double,bool)>(&TimelineModel::requestClipTimeWarp))(parameter_names("clipId", "speed","changeDuration"));
.method("requestClipTimeWarp", select_overload<bool(int, double,bool,bool)>(&TimelineModel::requestClipTimeWarp))(parameter_names("clipId", "speed","pitchCompensate","changeDuration"));
}
int TimelineModel::next_id = 0;
......@@ -928,7 +928,7 @@ int TimelineModel::suggestCompositionMove(int compoId, int trackId, int position
return currentPos;
}
bool TimelineModel::requestClipCreation(const QString &binClipId, int &id, PlaylistState::ClipState state, double speed, Fun &undo, Fun &redo)
bool TimelineModel::requestClipCreation(const QString &binClipId, int &id, PlaylistState::ClipState state, double speed, bool warp_pitch, Fun &undo, Fun &redo)
{
qDebug() << "requestClipCreation " << binClipId;
QString bid = binClipId;
......@@ -947,7 +947,7 @@ bool TimelineModel::requestClipCreation(const QString &binClipId, int &id, Playl
int clipId = TimelineModel::getNextId();
id = clipId;
Fun local_undo = deregisterClip_lambda(clipId);
ClipModel::construct(shared_from_this(), bid, clipId, state, speed);
ClipModel::construct(shared_from_this(), bid, clipId, state, speed, warp_pitch);
auto clip = m_allClips[clipId];
Fun local_redo = [clip, this, state]() {
// We capture a shared_ptr to the clip, which means that as long as this undo object lives, the clip object is not deleted. To insert it back it is
......@@ -1040,7 +1040,7 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
return false;
}
bool audioDrop = getTrackById_const(trackId)->isAudioTrack();
res = requestClipCreation(binClipId, id, getTrackById_const(trackId)->trackType(), 1.0, local_undo, local_redo);
res = requestClipCreation(binClipId, id, getTrackById_const(trackId)->trackType(), 1.0, false, local_undo, local_redo);
res = res && requestClipMove(id, trackId, position, true, refreshView, logUndo, logUndo, local_undo, local_redo);
int target_track;
if (audioDrop) {
......@@ -1075,7 +1075,7 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
std::function<bool(void)> audio_undo = []() { return true; };
std::function<bool(void)> audio_redo = []() { return true; };
int newId;
res = requestClipCreation(binClipId, newId, audioDrop ? PlaylistState::VideoOnly : PlaylistState::AudioOnly, 1.0, audio_undo, audio_redo);
res = requestClipCreation(binClipId, newId, audioDrop ? PlaylistState::VideoOnly : PlaylistState::AudioOnly, 1.0, false, audio_undo, audio_redo);
if (res) {
bool move = false;
while (!move && !possibleTracks.isEmpty()) {
......@@ -1110,7 +1110,7 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
if (normalisedBinId.startsWith(QLatin1Char('A')) || normalisedBinId.startsWith(QLatin1Char('V'))) {
normalisedBinId.remove(0, 1);
}
res = requestClipCreation(normalisedBinId, id, dropType, 1.0, local_undo, local_redo);
res = requestClipCreation(normalisedBinId, id, dropType, 1.0, false, local_undo, local_redo);
res = res && requestClipMove(id, trackId, position, true, refreshView, logUndo, logUndo, local_undo, local_redo);
}
if (!res) {
......@@ -1904,7 +1904,8 @@ int TimelineModel::requestClipResizeAndTimeWarp(int itemId, int size, bool right
pos += getItemPlaytime(id) - size;
}
result = getTrackById(tid)->requestClipDeletion(id, true, true, undo, redo, false, true);
result = result && requestClipTimeWarp(id, speed, true, undo, redo);
bool pitchCompensate = m_allClips[id]->getIntProperty(QStringLiteral("warp_pitch"));
result = result && requestClipTimeWarp(id, speed, pitchCompensate, true, undo, redo);
result = result && requestItemResize(id, size, true, true, undo, redo);
result = result && getTrackById(tid)->requestClipInsertion(id, pos, true, true, undo, redo);
if (!result) {
......@@ -3381,12 +3382,9 @@ void TimelineModel::requestClipUpdate(int clipId, const QVector<int> &roles)
notifyChange(modelIndex, modelIndex, roles);
}
bool TimelineModel::requestClipTimeWarp(int clipId, double speed, bool changeDuration, Fun &undo, Fun &redo)
bool TimelineModel::requestClipTimeWarp(int clipId, double speed, bool pitchCompensate, bool changeDuration, Fun &undo, Fun &redo)
{
QWriteLocker locker(&m_lock);
if (qFuzzyCompare(speed, m_allClips[clipId]->getSpeed())) {
return true;
}
std::function<bool(void)> local_undo = []() { return true; };
std::function<bool(void)> local_redo = []() { return true; };
int oldPos = getClipPosition(clipId);
......@@ -3397,7 +3395,8 @@ bool TimelineModel::requestClipTimeWarp(int clipId, double speed, bool changeDur
success = success && getTrackById(trackId)->requestClipDeletion(clipId, true, true, local_undo, local_redo, false, false);
}
if (success) {
success = m_allClips[clipId]->useTimewarpProducer(speed, changeDuration, local_undo, local_redo);
qDebug()<<"Warp pass 3";
success = m_allClips[clipId]->useTimewarpProducer(speed, pitchCompensate, changeDuration, local_undo, local_redo);
}
if (trackId != -1) {
success = success && getTrackById(trackId)->requestClipInsertion(clipId, oldPos, true, true, local_undo, local_redo);
......@@ -3410,9 +3409,12 @@ bool TimelineModel::requestClipTimeWarp(int clipId, double speed, bool changeDur
return success;
}
bool TimelineModel::requestClipTimeWarp(int clipId, double speed, bool changeDuration)
bool TimelineModel::requestClipTimeWarp(int clipId, double speed, bool pitchCompensate, bool changeDuration)
{
QWriteLocker locker(&m_lock);
if (qFuzzyCompare(speed, m_allClips[clipId]->getSpeed()) && pitchCompensate == m_allClips[clipId]->getIntProperty("warp_pitch")) {
return true;
}
TRACE(clipId, speed);
Fun undo = []() { return true; };
Fun redo = []() { return true; };
......@@ -3423,10 +3425,10 @@ bool TimelineModel::requestClipTimeWarp(int clipId, double speed, bool changeDur
// Check if clip has a split partner
int splitId = m_groups->getSplitPartner(clipId);
if (splitId > -1) {
result = requestClipTimeWarp(splitId, speed / 100.0, changeDuration, undo, redo);
result = requestClipTimeWarp(splitId, speed / 100.0, pitchCompensate, changeDuration, undo, redo);
}
if (result) {
result = requestClipTimeWarp(clipId, speed / 100.0, changeDuration, undo, redo);
result = requestClipTimeWarp(clipId, speed / 100.0, pitchCompensate, changeDuration, undo, redo);
}
if (!result) {
pCore->displayMessage(i18n("Change speed failed"), ErrorMessage);
......@@ -3436,7 +3438,7 @@ bool TimelineModel::requestClipTimeWarp(int clipId, double speed, bool changeDur
}
} else {
// If clip is not inserted on a track, we just change the producer
result = m_allClips[clipId]->useTimewarpProducer(speed, changeDuration, undo, redo);
result = m_allClips[clipId]->useTimewarpProducer(speed, pitchCompensate, changeDuration, undo, redo);
}
if (result) {
PUSH_UNDO(undo, redo, i18n("Change clip speed"));
......
......@@ -410,7 +410,7 @@ protected:
@param id: return parameter for the id of the newly created clip.
@param state: The desired clip state (original, audio/video only).
*/
bool requestClipCreation(const QString &binClipId, int &id, PlaylistState::ClipState state, double speed, Fun &undo, Fun &redo);
bool requestClipCreation(const QString &binClipId, int &id, PlaylistState::ClipState state, double speed, bool warp_pitch, Fun &undo, Fun &redo);
/* @brief Switch item selection status */
void setSelected(int itemId, bool sel);
......@@ -637,10 +637,10 @@ public:
This functions create an undo object and also apply the effect to the corresponding audio if there is any.
Returns true on success, false otherwise (and nothing is modified)
*/
Q_INVOKABLE bool requestClipTimeWarp(int clipId, double speed, bool changeDuration);
Q_INVOKABLE bool requestClipTimeWarp(int clipId, double speed, bool pitchCompensate, bool changeDuration);
/* @brief Same function as above, but doesn't check for paired audio and accumulate undo/redo
*/
bool requestClipTimeWarp(int clipId, double speed, bool changeDuration, Fun &undo, Fun &redo);
bool requestClipTimeWarp(int clipId, double speed, bool pitchCompensate, bool changeDuration, Fun &undo, Fun &redo);
void replugClip(int clipId);
......
......@@ -27,7 +27,7 @@
#include <KMessageWidget>
#include <QtMath>
SpeedDialog::SpeedDialog(QWidget *parent, double speed, double minSpeed, double maxSpeed, bool reversed)
SpeedDialog::SpeedDialog(QWidget *parent, double speed, double minSpeed, double maxSpeed, bool reversed, bool pitch_compensate)
: QDialog(parent)
, ui(new Ui::ClipSpeed_UI)
{
......@@ -48,6 +48,7 @@ SpeedDialog::SpeedDialog(QWidget *parent, double speed, double minSpeed, double
}
ui->speedSpin->setValue(speed);
ui->speedSlider->setValue(qLn(speed) * 12);
ui->pitchCompensate->setChecked(pitch_compensate);
// Info widget
KMessageWidget *infoMessage = new KMessageWidget(this);
......@@ -86,3 +87,8 @@ double SpeedDialog::getValue() const
}
return val;
}
bool SpeedDialog::getPitchCompensate() const
{
return ui->pitchCompensate->isChecked();
}
......@@ -33,10 +33,11 @@ class SpeedDialog : public QDialog
Q_OBJECT
public:
explicit SpeedDialog(QWidget *parent, double speed, double minSpeed, double maxSpeed, bool reversed);
explicit SpeedDialog(QWidget *parent, double speed, double minSpeed, double maxSpeed, bool reversed, bool pitch_compensate);
~SpeedDialog();
double getValue() const;
bool getPitchCompensate() const;
private:
Ui::ClipSpeed_UI *ui;
......
......@@ -1617,6 +1617,7 @@ void TimelineController::changeItemSpeed(int clipId, double speed)
pCore->displayMessage(i18n("No item to edit"), InformationMessage, 500);
return;
}
bool pitchCompensate = m_model->m_allClips[clipId]->getIntProperty(QStringLiteral("warp_pitch"));
if (qFuzzyCompare(speed, -1)) {
speed = 100 * m_model->getClipSpeed(clipId);
double duration = m_model->getItemPlaytime(clipId);
......@@ -1634,14 +1635,15 @@ void TimelineController::changeItemSpeed(int clipId, double speed)
minSpeed = std::max(minSpeed, minSpeed2);
maxSpeed = std::min(maxSpeed, maxSpeed2);
}
QScopedPointer<SpeedDialog> d(new SpeedDialog(QApplication::activeWindow(), std::abs(speed), minSpeed, maxSpeed, speed < 0));
QScopedPointer<SpeedDialog> d(new SpeedDialog(QApplication::activeWindow(), std::abs(speed), minSpeed, maxSpeed, speed < 0, pitchCompensate));
if (d->exec() != QDialog::Accepted) {
return;
}
speed = d->getValue();
pitchCompensate = d->getPitchCompensate();
qDebug() << "requesting speed " << speed;
}
m_model->requestClipTimeWarp(clipId, speed, true);
m_model->requestClipTimeWarp(clipId, speed, pitchCompensate, true);
}
void TimelineController::switchCompositing(int mode)
......
......@@ -6,15 +6,15 @@
<rect>
<x>0</x>
<y>0</y>
<width>476</width>
<height>140</height>
<width>622</width>
<height>244</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="2">
<item row="6" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
......@@ -37,27 +37,6 @@
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="destination_layout">
<item>
<widget class="QLabel" name="label_dest">
<property name="text">
<string>Destination</string>
</property>
</widget>
</item>
<item>
<widget class="KUrlRequester" name="kurlrequester">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
......@@ -114,13 +93,6 @@
</item>
</layout>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Reverse clip</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<layout class="QHBoxLayout" name="infoLayout">
<property name="topMargin">
......@@ -128,12 +100,47 @@
</property>
</layout>
</item>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="destination_layout">
<item>
<widget class="QLabel" name="label_dest">
<property name="text">
<string>Destination</string>
</property>
</widget>
</item>
<item>
<widget class="KUrlRequester" name="kurlrequester">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="pitchCompensate">
<property name="text">
<string>Pitch compensation</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Reverse clip</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KUrlRequester</class>
<extends>QFrame</extends>
<extends>QWidget</extends>
<header>kurlrequester.h</header>
<container>1</container>
</customwidget>
......
......@@ -1144,7 +1144,7 @@ TEST_CASE("Undo and Redo", "[ClipModel]")
int temp;
Fun undo = []() { return true; };
Fun redo = []() { return true; };
REQUIRE_FALSE(timeline->requestClipCreation("impossible bin id", temp, PlaylistState::VideoOnly, 1., undo, redo));
REQUIRE_FALSE(timeline->requestClipCreation("impossible bin id", temp, PlaylistState::VideoOnly, 1., false, undo, redo));
}
auto state0 = [&]() {
......@@ -1158,7 +1158,7 @@ TEST_CASE("Undo and Redo", "[ClipModel]")
{
Fun undo = []() { return true; };
Fun redo = []() { return true; };
REQUIRE(timeline->requestClipCreation(binId3, cid3, PlaylistState::VideoOnly, 1., undo, redo));
REQUIRE(timeline->requestClipCreation(binId3, cid3, PlaylistState::VideoOnly, 1., false, undo, redo));
pCore->pushUndo(undo, redo, QString());
}
......@@ -1175,7 +1175,7 @@ TEST_CASE("Undo and Redo", "[ClipModel]")
{
Fun undo = []() { return true; };
Fun redo = []() { return true; };
REQUIRE(timeline->requestClipCreation(binId4, cid4, PlaylistState::VideoOnly, 1., undo, redo));
REQUIRE(timeline->requestClipCreation(binId4, cid4, PlaylistState::VideoOnly, 1., false, undo, redo));
pCore->pushUndo(undo, redo, QString());
}
......@@ -1638,7 +1638,7 @@ TEST_CASE("Undo and Redo", "[ClipModel]")
{
std::function<bool(void)> undo = []() { return true; };
std::function<bool(void)> redo = []() { return true; };
REQUIRE(timeline->requestClipCreation(binId, cid6, PlaylistState::VideoOnly, 1., undo, redo));
REQUIRE(timeline->requestClipCreation(binId, cid6, PlaylistState::VideoOnly, 1., false, undo, redo));
pCore->pushUndo(undo, redo, QString());
}
int l = timeline->getClipPlaytime(cid6);
......
......@@ -59,7 +59,7 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
std::function<bool(void)> undo = []() { return true; };
std::function<bool(void)> redo = []() { return true; };
REQUIRE(timeline->requestClipTimeWarp(cid3, 0.1, true, undo, redo));
REQUIRE(timeline->requestClipTimeWarp(cid3, 0.1, false, true, undo, redo));
CHECK_UPDATE(TimelineModel::SpeedRole);
REQUIRE(timeline->getClipSpeed(cid3) == 0.1);
......@@ -81,7 +81,7 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
std::function<bool(void)> undo2 = []() { return true; };
std::function<bool(void)> redo2 = []() { return true; };
REQUIRE(timeline->requestClipTimeWarp(cid3, 1.2, true, undo2, redo2));
REQUIRE(timeline->requestClipTimeWarp(cid3, 1.2, false, true, undo2, redo2));
CHECK_UPDATE(TimelineModel::SpeedRole);
REQUIRE(timeline->getClipSpeed(cid3) == 1.2);
......@@ -102,7 +102,7 @@ TEST_CASE("Test of timewarping", "[Timewarp]")
int curLength = timeline->getClipPlaytime(cid3);
// This is the limit, should work
REQUIRE(timeline->requestClipTimeWarp(cid3, double(curLength), true, undo2, redo2));