From abcb669a6c94f03a961562fdfe6a758354af4ffb Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 6 Oct 2018 20:22:43 +1000 Subject: [PATCH] implemented reversing #120 --- dialogs/speeddialog.cpp | 34 +++++++++++++++++++++++----------- playback/cacher.cpp | 5 ++++- playback/playback.cpp | 4 +++- project/clip.cpp | 2 +- project/undo.cpp | 9 ++++----- ui/timelinewidget.cpp | 6 +++++- 6 files changed, 40 insertions(+), 20 deletions(-) diff --git a/dialogs/speeddialog.cpp b/dialogs/speeddialog.cpp index be81177a2..713d2019b 100644 --- a/dialogs/speeddialog.cpp +++ b/dialogs/speeddialog.cpp @@ -296,12 +296,12 @@ void SpeedDialog::frame_rate_update() { duration->set_value((len_val == -1) ? qSNaN() : len_val, false); } -void set_speed(ComboAction* ca, Clip* c, double speed) { +void set_speed(ComboAction* ca, Clip* c, double speed, bool ripple, long& ep, long& lr) { long proposed_out = c->timeline_out; double multiplier = (c->speed / speed); proposed_out = c->timeline_in + (c->getLength() * multiplier); ca->append(new SetSpeedAction(c, speed)); - if (proposed_out > c->timeline_out) { + if (!ripple && proposed_out > c->timeline_out) { for (int i=0;isequence->clips.size();i++) { Clip* compare = c->sequence->clips.at(i); if (compare != NULL @@ -311,23 +311,31 @@ void set_speed(ComboAction* ca, Clip* c, double speed) { } } } + ep = qMin(ep, c->timeline_out); + lr = qMax(lr, proposed_out - c->timeline_out); ca->append(new MoveClipAction(c, c->timeline_in, proposed_out, c->clip_in * multiplier, c->track)); } void SpeedDialog::accept() { ComboAction* ca = new ComboAction(); + long earliest_point = LONG_MAX; + long longest_ripple = LONG_MIN; + for (int i=0;iopen) close_clip(c); - if (c->track >= 0) { - if (maintain_pitch->checkState() != Qt::PartiallyChecked) { - ca->append(new SetBool(&c->maintain_audio_pitch, maintain_pitch->isChecked())); - } + if (c->track >= 0 + && maintain_pitch->checkState() != Qt::PartiallyChecked + && c->maintain_audio_pitch != maintain_pitch->isChecked()) { + ca->append(new SetBool(&c->maintain_audio_pitch, maintain_pitch->isChecked())); } - if (reverse->checkState() != Qt::PartiallyChecked) { + if (reverse->checkState() != Qt::PartiallyChecked && c->reverse != reverse->isChecked()) { + long new_clip_in = (c->getMaximumLength() - (c->getLength() + c->clip_in)); + ca->append(new MoveClipAction(c, c->timeline_in, c->timeline_out, new_clip_in, c->track)); + c->clip_in = new_clip_in; ca->append(new SetBool(&c->reverse, reverse->isChecked())); } } @@ -336,7 +344,7 @@ void SpeedDialog::accept() { // simply set speed for (int i=0;ivalue()); + set_speed(ca, c, percent->value(), ripple->isChecked(), earliest_point, longest_ripple); } } else if (!qIsNaN(frame_rate->value())) { bool can_change_all = true; @@ -365,19 +373,23 @@ void SpeedDialog::accept() { for (int i=0;itrack < 0) { - set_speed(ca, c, frame_rate->value() / c->getMediaFrameRate()); + set_speed(ca, c, frame_rate->value() / c->getMediaFrameRate(), ripple->isChecked(), earliest_point, longest_ripple); } else if (can_change_all) { - set_speed(ca, c, frame_rate->value() / cached_fr); + set_speed(ca, c, frame_rate->value() / cached_fr, ripple->isChecked(), earliest_point, longest_ripple); } } } else if (!qIsNaN(duration->value())) { // simply set duration for (int i=0;igetLength() * c->speed) / duration->value()); + set_speed(ca, c, (c->getLength() * c->speed) / duration->value(), ripple->isChecked(), earliest_point, longest_ripple); } } + if (ripple->isChecked()) { + ca->append(new RippleCommand(clips.at(0)->sequence, earliest_point, longest_ripple)); + } + undo_stack.push(ca); panel_timeline->redraw_all_clips(true); diff --git a/playback/cacher.cpp b/playback/cacher.cpp index 414c3ce78..99a84fb9c 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -257,7 +257,8 @@ void cache_video_worker(Clip* c, long playhead, ClipCache* cache) { } } else { if (ret == AVERROR_EOF) { - c->reached_end = true; + // TODO sorta hacky? not even sure if "reached_end" serves a proper purpose anymore + if (!c->reverse) c->reached_end = true; } else { qDebug() << "[WARNING] Raw frame data could not be retrieved." << ret; error = true; @@ -559,6 +560,8 @@ void cache_clip_worker(Clip* clip, long playhead, bool write_A, bool write_B, bo } void close_clip_worker(Clip* clip) { + clip->finished_opening = false; + if (clip->media_type == MEDIA_TYPE_FOOTAGE) { // closes ffmpeg file handle and frees any memory used for caching MediaStream* ms = static_cast(clip->media)->get_stream_from_file_index(clip->track < 0, clip->media_stream); diff --git a/playback/playback.cpp b/playback/playback.cpp index 8b4e188dd..066de4f8c 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -111,7 +111,9 @@ bool get_clip_frame(Clip* c, long playhead) { long sequence_clip_time = playhead - c->timeline_in + c->clip_in; - if (c->reverse && !ms->infinite_length) sequence_clip_time = c->getMaximumLength() - sequence_clip_time - 1; + if (c->reverse && !ms->infinite_length) { + sequence_clip_time = c->getMaximumLength() - sequence_clip_time - 1; + } long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, c->getMediaFrameRate()*c->speed); diff --git a/project/clip.cpp b/project/clip.cpp index 3411eedbb..e6346ffe6 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -108,7 +108,7 @@ void Clip::reset_audio() { audio_buffer_write = 0; reached_end = false; break; - case MEDIA_TYPE_SEQUENCE: + case MEDIA_TYPE_SEQUENCE: { Sequence* nested_sequence = static_cast(media); for (int i=0;iclips.size();i++) { diff --git a/project/undo.cpp b/project/undo.cpp index 06857cbae..3b1ae82d5 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -49,6 +49,10 @@ void ComboAction::append(QUndoCommand* u) { MoveClipAction::MoveClipAction(Clip *c, long iin, long iout, long iclip_in, int itrack) : clip(c), + old_in(c->timeline_in), + old_out(c->timeline_out), + old_clip_in(c->clip_in), + old_track(c->track), new_in(iin), new_out(iout), new_clip_in(iclip_in), @@ -66,11 +70,6 @@ void MoveClipAction::undo() { } void MoveClipAction::redo() { - old_in = clip->timeline_in; - old_out = clip->timeline_out; - old_clip_in = clip->clip_in; - old_track = clip->track; - clip->timeline_in = new_in; clip->timeline_out = new_out; clip->clip_in = new_clip_in; diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 06d714822..46e84bac7 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -1732,6 +1732,10 @@ void TimelineWidget::redraw_clips() { for (int i=0;iclip_in + ((double) i/panel_timeline->zoom))/media_length) * ms->audio_preview.size())/divider)*divider; + if (clip->reverse) { + waveform_index = ms->audio_preview.size() - waveform_index; + } + int rectified_height = 0; for (int j=0;jaudio_channels;j++) { @@ -1748,7 +1752,7 @@ void TimelineWidget::redraw_clips() { clip_painter.drawLine(clip_rect.left()+i, mid+min, clip_rect.left()+i, mid+max); } } else { - qDebug() << "tried to reach" << offset + 1 << "limit:" << ms->audio_preview.size(); + qDebug() << "[WARNING] Tried to reach" << offset + 1 << ", limit:" << ms->audio_preview.size(); } }