From f11447e5166679b187ee94a9113f144df631d136 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 9 Jul 2018 20:59:22 +0100 Subject: [PATCH] many many things --- effects/paneffect.cpp | 4 +- effects/volumeeffect.cpp | 11 +- icons/icons.qrc | 2 + icons/slide-disabled.png | Bin 0 -> 2435 bytes icons/slide.png | Bin 0 -> 1171 bytes io/media.h | 1 - io/previewgenerator.cpp | 2 - mainwindow.cpp | 5 + mainwindow.h | 2 + mainwindow.ui | 12 ++ olive.pro.user | 2 +- panels/project.cpp | 1 - panels/timeline.cpp | 104 ++++++------ panels/timeline.h | 28 ++-- panels/timeline.ui | 37 ++++- playback/audio.cpp | 2 +- playback/audio.h | 3 + playback/cacher.cpp | 24 ++- ui/audiomonitor.h | 2 + ui/timelinetools.h | 5 +- ui/timelinewidget.cpp | 345 ++++++++++++++++++++++----------------- ui/viewerwidget.cpp | 2 +- 22 files changed, 359 insertions(+), 235 deletions(-) create mode 100644 icons/slide-disabled.png create mode 100644 icons/slide.png diff --git a/effects/paneffect.cpp b/effects/paneffect.cpp index dd859fbe8..0ac89037e 100644 --- a/effects/paneffect.cpp +++ b/effects/paneffect.cpp @@ -50,8 +50,8 @@ void PanEffect::save(QXmlStreamWriter *stream) { void PanEffect::process_audio(quint8 *samples, int nb_bytes) { if (pan_val->value() != 0) { for (int i=0;ivalue()*0.01f, 3); if (val < 0) { diff --git a/effects/volumeeffect.cpp b/effects/volumeeffect.cpp index a90e0ed1e..546e3c99a 100644 --- a/effects/volumeeffect.cpp +++ b/effects/volumeeffect.cpp @@ -5,6 +5,7 @@ #include #include +#include "playback/audio.h" #include "ui/labelslider.h" #include "ui/collapsiblewidget.h" @@ -50,9 +51,15 @@ void VolumeEffect::save(QXmlStreamWriter* stream) { void VolumeEffect::process_audio(quint8* samples, int nb_bytes) { if (volume_val->value() != 100) { for (int i=0;ivalue()*0.01f, 3); + qint32 samp = (qint16) (((samples[i+1] & 0xFF) << 8) | (samples[i] & 0xFF)); + double val = qPow(volume_val->value()*0.01, 3); samp *= val; + if (samp > INT16_MAX) { + samp = INT16_MAX; + } else if (samp < INT16_MIN) { + samp = INT16_MIN; + } + samples[i+1] = (quint8) (samp >> 8); samples[i] = (quint8) samp; } diff --git a/icons/icons.qrc b/icons/icons.qrc index e94bd87d4..facafcbdd 100644 --- a/icons/icons.qrc +++ b/icons/icons.qrc @@ -27,5 +27,7 @@ ripple-disabled.png rolling-disabled.png slip-disabled.png + slide.png + slide-disabled.png diff --git a/icons/slide-disabled.png b/icons/slide-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..6bdb6f879421acd1a9ab99225ada1bf206aa2149 GIT binary patch literal 2435 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 literal 0 HcmV?d00001 diff --git a/io/media.h b/io/media.h index 26c34c7fe..700842dcd 100644 --- a/io/media.h +++ b/io/media.h @@ -23,7 +23,6 @@ struct MediaStream { int audio_channels; // preview thumbnail/waveform - QMutex preview_lock; bool preview_done; QImage video_preview; // TODO change to QPixmap QVector audio_preview; diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 030e26fcc..e69d9daf4 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -105,7 +105,6 @@ void PreviewGenerator::run() { // delete [] data; s->preview_done = true; - s->preview_lock.unlock(); sws_freeContext(sws_ctx); @@ -179,7 +178,6 @@ void PreviewGenerator::run() { } for (int i=0;iaudio_tracks.size();i++) { media->audio_tracks.at(i)->preview_done = true; - media->audio_tracks.at(i)->preview_lock.unlock(); } av_frame_free(&temp_frame); for (unsigned int i=0;inb_streams;i++) { diff --git a/mainwindow.cpp b/mainwindow.cpp index 4442c39c3..32ae0a584 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -526,3 +526,8 @@ void MainWindow::on_actionSeek_to_the_End_of_Pastes_triggered() void MainWindow::on_actionAdd_Default_Transition_triggered() { if (panel_timeline->focused()) panel_timeline->add_transition(); } + +void MainWindow::on_actionSlide_Tool_triggered() +{ + if (panel_timeline->focused()) panel_timeline->ui->toolSlideButton->click(); +} diff --git a/mainwindow.h b/mainwindow.h index 8797d4151..3adbca085 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -137,6 +137,8 @@ private slots: void on_actionAdd_Default_Transition_triggered(); + void on_actionSlide_Tool_triggered(); + private: Ui::MainWindow *ui; void setup_layout(); diff --git a/mainwindow.ui b/mainwindow.ui index f480292c8..ca99fd4a9 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -125,6 +125,7 @@ + @@ -268,6 +269,9 @@ Sequence... + + Ctrl+Shift+N + @@ -571,6 +575,14 @@ Ctrl+Shift+D + + + Slide Tool + + + U + + diff --git a/olive.pro.user b/olive.pro.user index 936df18b6..0faa82619 100644 --- a/olive.pro.user +++ b/olive.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/panels/project.cpp b/panels/project.cpp index 709b86d3c..0e465b92a 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -140,7 +140,6 @@ Media* Project::import_file(QString file) { } else { MediaStream* ms = new MediaStream(); ms->preview_done = false; - ms->preview_lock.lock(); ms->file_index = i; if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { bool infinite_length = (pFormatCtx->streams[i]->avg_frame_rate.den == 0); diff --git a/panels/timeline.cpp b/panels/timeline.cpp index b354bd242..a463c3a99 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -55,6 +55,7 @@ Timeline::Timeline(QWidget *parent) : tool_buttons.append(ui->toolRazorButton); tool_buttons.append(ui->toolSlipButton); tool_buttons.append(ui->toolRollingButton); + tool_buttons.append(ui->toolSlideButton); ui->toolArrowButton->click(); @@ -383,36 +384,7 @@ void Timeline::ripple(long ripple_point, long ripple_length) { void Timeline::decheck_tool_buttons(QObject* sender) { for (int i=0;isetChecked(false); - } - } -} - -void Timeline::on_toolEditButton_toggled(bool checked) -{ - if (checked) { - decheck_tool_buttons(sender()); - ui->timeline_area->setCursor(Qt::IBeamCursor); - tool = TIMELINE_TOOL_EDIT; - } -} - -void Timeline::on_toolArrowButton_toggled(bool checked) -{ - if (checked) { - decheck_tool_buttons(sender()); - ui->timeline_area->setCursor(Qt::ArrowCursor); - tool = TIMELINE_TOOL_POINTER; - } -} - -void Timeline::on_toolRazorButton_toggled(bool checked) -{ - if (checked) { - decheck_tool_buttons(sender()); - ui->timeline_area->setCursor(Qt::IBeamCursor); - tool = TIMELINE_TOOL_RAZOR; + tool_buttons[i]->setChecked(tool_buttons.at(i) == sender); } } @@ -436,33 +408,6 @@ bool Timeline::is_clip_selected(Clip* clip) { return false; } -void Timeline::on_toolRippleButton_toggled(bool checked) -{ - if (checked) { - decheck_tool_buttons(sender()); - ui->timeline_area->setCursor(Qt::ArrowCursor); - tool = TIMELINE_TOOL_RIPPLE; - } -} - -void Timeline::on_toolRollingButton_toggled(bool checked) -{ - if (checked) { - decheck_tool_buttons(sender()); - ui->timeline_area->setCursor(Qt::ArrowCursor); - tool = TIMELINE_TOOL_ROLLING; - } -} - -void Timeline::on_toolSlipButton_toggled(bool checked) -{ - if (checked) { - decheck_tool_buttons(sender()); - ui->timeline_area->setCursor(Qt::ArrowCursor); - tool = TIMELINE_TOOL_SLIP; - } -} - void Timeline::on_snappingButton_toggled(bool checked) { snapping = checked; @@ -849,3 +794,48 @@ long Timeline::getFrameFromScreenPoint(int x) { int Timeline::getScreenPointFromFrame(long frame) { return (int) round(frame*zoom); } + +void Timeline::on_toolArrowButton_clicked() { + decheck_tool_buttons(sender()); + ui->timeline_area->setCursor(Qt::ArrowCursor); + tool = TIMELINE_TOOL_POINTER; +} + +void Timeline::on_toolEditButton_clicked() { + decheck_tool_buttons(sender()); + ui->timeline_area->setCursor(Qt::IBeamCursor); + tool = TIMELINE_TOOL_EDIT; +} + +void Timeline::on_toolRippleButton_clicked() { + decheck_tool_buttons(sender()); + ui->timeline_area->setCursor(Qt::ArrowCursor); + tool = TIMELINE_TOOL_RIPPLE; +} + +void Timeline::on_toolRollingButton_clicked() { + decheck_tool_buttons(sender()); + ui->timeline_area->setCursor(Qt::ArrowCursor); + tool = TIMELINE_TOOL_ROLLING; +} + +void Timeline::on_toolRazorButton_clicked() +{ + decheck_tool_buttons(sender()); + ui->timeline_area->setCursor(Qt::IBeamCursor); + tool = TIMELINE_TOOL_RAZOR; +} + +void Timeline::on_toolSlipButton_clicked() +{ + decheck_tool_buttons(sender()); + ui->timeline_area->setCursor(Qt::ArrowCursor); + tool = TIMELINE_TOOL_SLIP; +} + +void Timeline::on_toolSlideButton_clicked() +{ + decheck_tool_buttons(sender()); + ui->timeline_area->setCursor(Qt::ArrowCursor); + tool = TIMELINE_TOOL_SLIDE; +} diff --git a/panels/timeline.h b/panels/timeline.h index 7dce03268..9fc8c69dc 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -35,6 +35,7 @@ struct Ghost { long ghost_length; long media_length; bool trim_in; + bool trimming; }; struct Selection { @@ -164,24 +165,27 @@ public slots: void repaint_timeline(); private slots: - void on_toolEditButton_toggled(bool checked); - - void on_toolArrowButton_toggled(bool checked); - - void on_toolRazorButton_toggled(bool checked); void on_pushButton_4_clicked(); - void on_pushButton_5_clicked(); - - void on_toolRippleButton_toggled(bool checked); - - void on_toolRollingButton_toggled(bool checked); - - void on_toolSlipButton_toggled(bool checked); + void on_pushButton_5_clicked(); void on_snappingButton_toggled(bool checked); + void on_toolSlideButton_clicked(); + + void on_toolArrowButton_clicked(); + + void on_toolEditButton_clicked(); + + void on_toolRippleButton_clicked(); + + void on_toolRollingButton_clicked(); + + void on_toolRazorButton_clicked(); + + void on_toolSlipButton_clicked(); + private: QVector tool_buttons; void decheck_tool_buttons(QObject* sender); diff --git a/panels/timeline.ui b/panels/timeline.ui index 7b17c0261..2b5930077 100644 --- a/panels/timeline.ui +++ b/panels/timeline.ui @@ -7,7 +7,7 @@ 0 0 523 - 363 + 376 @@ -233,7 +233,38 @@ :/icons/slip.png - :/icons/slip-disabled.png + :/icons/slip-disabled.png + + + + + 20 + 20 + + + + true + + + + + + + + 40 + 16777215 + + + + Slide Tool (U) + + + + + + + :/icons/slide.png + :/icons/slide-disabled.png @@ -331,7 +362,7 @@ 0 0 408 - 314 + 327 diff --git a/playback/audio.cpp b/playback/audio.cpp index 1eca26d6a..c51a6f7c7 100644 --- a/playback/audio.cpp +++ b/playback/audio.cpp @@ -57,7 +57,7 @@ void clear_audio_ibuffer() { int get_buffer_offset_from_frame(long frame) { if (frame >= audio_ibuffer_frame) { - return av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(sequence->audio_layout), qRound(((frame-audio_ibuffer_frame)/sequence->frame_rate)*sequence->audio_frequency), AV_SAMPLE_FMT_S16, 1); + return qFloor(av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(sequence->audio_layout), qRound(((frame-audio_ibuffer_frame)/sequence->frame_rate)*sequence->audio_frequency), AV_SAMPLE_FMT_S16, 1)/4)*4; } else { qDebug() << "[WARNING] get_buffer_offset_from_frame called incorrectly"; return 0; diff --git a/playback/audio.h b/playback/audio.h index 4e529e997..58f57fe88 100644 --- a/playback/audio.h +++ b/playback/audio.h @@ -3,6 +3,9 @@ #include +#define INT16_MAX 0x7fff +#define INT16_MIN (-INT16_MAX-1) + class QAudioOutput; class QIODevice; diff --git a/playback/cacher.cpp b/playback/cacher.cpp index f85b9e59b..60be3d933 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -15,6 +15,8 @@ extern "C" { } #include +#include +#include void cache_audio_worker(Clip* c) { int written = 0; @@ -94,10 +96,24 @@ void cache_audio_worker(Clip* c) { written = max_write; break; } else { - audio_ibuffer[c->audio_buffer_write%audio_ibuffer_size] += frame->data[0][c->frame_sample_index]; - c->audio_buffer_write++; - c->frame_sample_index++; - written++; + int upper_byte_index = (c->audio_buffer_write+1)%audio_ibuffer_size; + int lower_byte_index = (c->audio_buffer_write)%audio_ibuffer_size; + qint16 old_sample = (qint16) ((audio_ibuffer[upper_byte_index] & 0xFF) << 8 | (audio_ibuffer[lower_byte_index] & 0xFF)); + qint16 new_sample = (qint16) ((frame->data[0][c->frame_sample_index+1] & 0xFF) << 8 | (frame->data[0][c->frame_sample_index] & 0xFF)); + qint32 mixed_sample; + + mixed_sample = old_sample + new_sample; + if (mixed_sample > INT16_MAX) { + mixed_sample = INT16_MAX; + } else if (mixed_sample < INT16_MIN) { + mixed_sample = INT16_MIN; + } + + audio_ibuffer[upper_byte_index] = (quint8) (mixed_sample >> 8); + audio_ibuffer[lower_byte_index] = (quint8) mixed_sample; + c->audio_buffer_write+=2; + c->frame_sample_index+=2; + written+=2; } } if (c->frame_sample_index == nb_bytes) { diff --git a/ui/audiomonitor.h b/ui/audiomonitor.h index c22212412..00a04007f 100644 --- a/ui/audiomonitor.h +++ b/ui/audiomonitor.h @@ -3,6 +3,8 @@ #include +#define AUDIO_MONITOR_RESOLUTION 16 + class AudioMonitor : public QWidget { Q_OBJECT diff --git a/ui/timelinetools.h b/ui/timelinetools.h index 74f54fb9a..f09e4426b 100644 --- a/ui/timelinetools.h +++ b/ui/timelinetools.h @@ -7,7 +7,8 @@ #define TIMELINE_TOOL_RIPPLE 3 #define TIMELINE_TOOL_ROLLING 4 #define TIMELINE_TOOL_SLIP 5 -#define TIMELINE_TOOL_HAND 6 -#define TIMELINE_TOOL_ZOOM 7 +#define TIMELINE_TOOL_SLIDE 6 +#define TIMELINE_TOOL_HAND 7 +#define TIMELINE_TOOL_ZOOM 8 #endif // TIMELINETOOLS_H diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 77a046934..29e465ca6 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -52,8 +52,8 @@ void TimelineWidget::resizeEvent(QResizeEvent*) { void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { if (static_cast(event->source()) == panel_project->source_table) { + event->accept(); QPoint pos = event->pos(); - event->accept(); QList items = panel_project->source_table->selectedItems(); long entry_point = panel_timeline->getFrameFromScreenPoint(pos.x()); panel_timeline->drag_frame_start = entry_point + panel_timeline->getFrameFromScreenPoint(50); @@ -61,25 +61,35 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { for (int i=0;iget_media_from_tree(items.at(i)); - long duration = m->get_length_in_frames(sequence->frame_rate); - Ghost g = {0, entry_point, entry_point + duration}; + Ghost g; + g.clip = -1; g.media = m; - g.clip_in = 0; + g.old_clip_in = g.clip_in = 0; + g.in = entry_point; + entry_point += m->get_length_in_frames(sequence->frame_rate); + g.out = entry_point; + g.trimming = false; for (int j=0;jaudio_tracks.size();j++) { - g.track = j; + g.track = j; g.media_stream = m->audio_tracks.at(j); ignore_infinite_length = true; panel_timeline->ghosts.append(g); } for (int j=0;jvideo_tracks.size();j++) { - g.track = -1-j; + g.track = -1-j; g.media_stream = m->video_tracks.at(j); if (m->video_tracks[j]->infinite_length && !ignore_infinite_length) g.out = g.in + 100; panel_timeline->ghosts.append(g); - } - entry_point += duration; - } - init_ghosts(); + } + } + for (int i=0;ighosts.size();i++) { + Ghost& g = panel_timeline->ghosts[i]; + g.old_in = g.in; + g.old_out = g.out; + g.old_track = g.track; + } + +// init_ghosts(); panel_timeline->importing = true; } } @@ -87,7 +97,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { void TimelineWidget::dragMoveEvent(QDragMoveEvent *event) { if (panel_timeline->importing) { QPoint pos = event->pos(); - update_ghosts(pos); + update_ghosts(pos); panel_timeline->repaint_timeline(); } } @@ -211,6 +221,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { case TIMELINE_TOOL_RIPPLE: case TIMELINE_TOOL_SLIP: case TIMELINE_TOOL_ROLLING: + case TIMELINE_TOOL_SLIDE: { if (track_resizing) { track_resize_mouse_cache = event->pos().y(); @@ -474,10 +485,10 @@ void TimelineWidget::init_ghosts() { g.out = g.old_out = c->timeline_out; g.track = g.old_track = c->track; g.clip_in = g.old_clip_in = c->clip_in; + g.ghost_length = g.old_out - g.old_in; - if (panel_timeline->trim_target > -1 || panel_timeline->tool == TIMELINE_TOOL_SLIP) { + if (panel_timeline->trim_target > -1 || panel_timeline->tool == TIMELINE_TOOL_SLIP || panel_timeline->tool == TIMELINE_TOOL_SLIDE) { // used for trim ops - g.ghost_length = g.old_out - g.old_in; g.media_length = sequence->get_clip(g.clip)->media->get_length_in_frames(sequence->frame_rate); } } @@ -489,7 +500,7 @@ void TimelineWidget::init_ghosts() { } } -bool subvalidate_snapping(Ghost& g, long* frame_diff, long snap_point) { +bool subvalidate_snapping(const Ghost& g, long* frame_diff, long snap_point) { int snap_range = panel_timeline->get_snap_range(); long in_validator = g.old_in + *frame_diff - snap_point; long out_validator = g.old_out + *frame_diff - snap_point; @@ -508,7 +519,7 @@ bool subvalidate_snapping(Ghost& g, long* frame_diff, long snap_point) { return false; } -void validate_snapping(Ghost& g, long* frame_diff) { +void validate_snapping(const Ghost& g, long* frame_diff) { panel_timeline->snapped = false; if (panel_timeline->snapping) { if (!subvalidate_snapping(g, frame_diff, panel_timeline->playhead)) { @@ -528,48 +539,64 @@ void validate_snapping(Ghost& g, long* frame_diff) { void TimelineWidget::update_ghosts(QPoint& mouse_pos) { int mouse_track = getTrackFromScreenPoint(mouse_pos.y()); long frame_diff = panel_timeline->getFrameFromScreenPoint(mouse_pos.x()) - panel_timeline->drag_frame_start; - int track_diff = mouse_track - panel_timeline->drag_track_start; + int track_diff = (panel_timeline->tool == TIMELINE_TOOL_SLIDE) ? 0 : mouse_track - panel_timeline->drag_track_start; + long validator; - long validator; - if (panel_timeline->trim_target > -1) { // if trimming - // trim ops - - // first try to snap + // first try to snap + if (panel_timeline->tool != TIMELINE_TOOL_SLIP) { + // slipping doesn't move the clips so we don't bother snapping for it for (int i=0;ighosts.size();i++) { Ghost& g = panel_timeline->ghosts[i]; validate_snapping(g, &frame_diff); } + } - // validate ghosts - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; - Clip* c = sequence->get_clip(g.clip); + bool clips_are_movable = (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->tool == TIMELINE_TOOL_SLIDE || panel_timeline->importing); + // validate ghosts + long temp_frame_diff = frame_diff; // cache to see if we change it (thus cancelling any snap) + for (int i=0;ighosts.size();i++) { + const Ghost& g = panel_timeline->ghosts.at(i); + Clip* c = NULL; + if (g.clip != -1) c = sequence->get_clip(g.clip); + + // validate ghosts for trimming + if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { + if (!sequence->get_clip(g.clip)->media_stream->infinite_length) { + // prevent slip moving a clip below 0 clip_in + validator = g.old_clip_in - frame_diff; + if (validator < 0) frame_diff += validator; + + // prevent slip moving clip beyond media length + validator += g.ghost_length; + if (validator > g.media_length) frame_diff += validator - g.media_length; + } + } else if (g.trimming) { if (g.trim_in) { - // prevent clip length from being less than 1 frame long - validator = g.ghost_length - frame_diff; - if (validator < 1) frame_diff -= (1 - validator); + // prevent clip length from being less than 1 frame long + validator = g.ghost_length - frame_diff; + if (validator < 1) frame_diff -= (1 - validator); - // prevent timeline in from going below 0 - validator = g.old_in + frame_diff; - if (validator < 0) frame_diff -= validator; + // prevent timeline in from going below 0 + validator = g.old_in + frame_diff; + if (validator < 0) frame_diff -= validator; if (!c->media_stream->infinite_length) { - // prevent clip_in from going below 0 - validator = g.old_clip_in + frame_diff; - if (validator < 0) frame_diff -= validator; + // prevent clip_in from going below 0 + validator = g.old_clip_in + frame_diff; + if (validator < 0) frame_diff -= validator; } - } else { - // prevent clip length from being less than 1 frame long - validator = g.ghost_length + frame_diff; - if (validator < 1) frame_diff += (1 - validator); + } else { + // prevent clip length from being less than 1 frame long + validator = g.ghost_length + frame_diff; + if (validator < 1) frame_diff += (1 - validator); if (!c->media_stream->infinite_length) { - // prevent clip length exceeding media length - validator = g.ghost_length + frame_diff; - if (validator > g.media_length) frame_diff -= validator - g.media_length; + // prevent clip length exceeding media length + validator = g.ghost_length + frame_diff; + if (validator > g.media_length) frame_diff -= validator - g.media_length; } - } + } // ripple ops if (panel_timeline->tool == TIMELINE_TOOL_RIPPLE) { @@ -594,112 +621,85 @@ void TimelineWidget::update_ghosts(QPoint& mouse_pos) { } } } + } else if (clips_are_movable) { // validate ghosts for moving + // prevent clips from moving below 0 on the timeline + validator = g.old_in + frame_diff; + if (validator < 0) frame_diff -= validator; + + // prevent clips from crossing tracks + if (same_sign(g.old_track, panel_timeline->drag_track_start)) { + while (!same_sign(g.old_track, g.old_track + track_diff)) { + if (g.old_track < 0) { + track_diff--; + } else { + track_diff++; + } + } + } } + } + if (temp_frame_diff != frame_diff) { + panel_timeline->snapped = false; + } - // resize ghosts - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; + // apply changes to ghosts + for (int i=0;ighosts.size();i++) { + Ghost& g = panel_timeline->ghosts[i]; + if (g.trimming) { if (g.trim_in) { g.in = g.old_in + frame_diff; g.clip_in = g.old_clip_in + frame_diff; } else { g.out = g.old_out + frame_diff; } - } + } else if (clips_are_movable) { + g.track = g.old_track; + g.in = g.old_in + frame_diff; + g.out = g.old_out + frame_diff; - // resize selections + if (panel_timeline->importing) { + int abs_track_diff = abs(track_diff); + if (g.old_track < 0) { // clip is video + g.track -= abs_track_diff; + } else { // clip is audio + g.track += abs_track_diff; + } + } else if (same_sign(g.old_track, panel_timeline->drag_track_start)) { + g.track += track_diff; + } + } + } + + // apply changes to selections + if (panel_timeline->tool != TIMELINE_TOOL_SLIP) { for (int i=0;iselections.size();i++) { Selection& s = panel_timeline->selections[i]; - if (panel_timeline->trim_in_point) { - s.in = s.old_in + frame_diff; + if (panel_timeline->trim_target > -1) { + if (panel_timeline->trim_in_point) { + s.in = s.old_in + frame_diff; + } else { + s.out = s.old_out + frame_diff; + } } else { - s.out = s.old_out + frame_diff; + for (int i=0;iselections.size();i++) { + Selection& s = panel_timeline->selections[i]; + s.in = s.old_in + frame_diff; + s.out = s.old_out + frame_diff; + s.track = s.old_track; + if (panel_timeline->importing) { + int abs_track_diff = abs(track_diff); + if (s.old_track < 0) { + s.track -= abs_track_diff; + } else { + s.track += abs_track_diff; + } + } else { + if (same_sign(s.track, panel_timeline->drag_track_start)) s.track += track_diff; + } + } } } - } else if (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->importing) { // only move clips on pointer (not ripple or rolling) - // validate ghosts - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; - - // prevent clips from moving below 0 on the timeline - validator = g.old_in + frame_diff; - if (validator < 0) frame_diff -= validator; - - // prevent clips from crossing tracks - if (same_sign(g.old_track, panel_timeline->drag_track_start)) { - while (!same_sign(g.old_track, g.old_track + track_diff)) { - if (g.old_track < 0) { - track_diff--; - } else { - track_diff++; - } - } - } - - validate_snapping(g, &frame_diff); - } - - // move ghosts - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; - g.in = g.old_in + frame_diff; - g.out = g.old_out + frame_diff; - - g.track = g.old_track; - - if (panel_timeline->importing) { - int abs_track_diff = abs(track_diff); - if (g.old_track < 0) { // clip is video - g.track -= abs_track_diff; - } else { // clip is audio - g.track += abs_track_diff; - } - } else { - if (same_sign(g.old_track, panel_timeline->drag_track_start)) g.track += track_diff; - } - } - - // move selections - if (!panel_timeline->importing) { - for (int i=0;iselections.size();i++) { - Selection& s = panel_timeline->selections[i]; - s.in = s.old_in + frame_diff; - s.out = s.old_out + frame_diff; - s.track = s.old_track; - if (panel_timeline->importing) { - int abs_track_diff = abs(track_diff); - if (s.old_track < 0) { - s.track -= abs_track_diff; - } else { - s.track += abs_track_diff; - } - } else { - if (same_sign(s.track, panel_timeline->drag_track_start)) s.track += track_diff; - } - } - } - } else if (panel_timeline->tool == TIMELINE_TOOL_SLIP) { - // validate ghosts - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; - if (!sequence->get_clip(g.clip)->media_stream->infinite_length) { - // prevent slip moving a clip below 0 clip_in - validator = g.old_clip_in - frame_diff; - if (validator < 0) frame_diff += validator; - - // prevent slip moving clip beyond media length - validator += g.ghost_length; - if (validator > g.media_length) frame_diff += validator - g.media_length; - } - } - - // slip ghosts - for (int i=0;ighosts.size();i++) { - Ghost& g = panel_timeline->ghosts[i]; - - g.clip_in = g.old_clip_in - frame_diff; - } } } @@ -786,15 +786,31 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { if (c != NULL && panel_timeline->is_clip_selected(c)) { Ghost g; g.clip = i; + g.trimming = (panel_timeline->trim_target > -1); g.trim_in = panel_timeline->trim_in_point; panel_timeline->ghosts.append(g); } } + int size = panel_timeline->ghosts.size(); if (panel_timeline->tool == TIMELINE_TOOL_ROLLING) { - int size = panel_timeline->ghosts.size(); for (int i=0;iget_clip(panel_timeline->ghosts.at(i).clip); + + // see if any ghosts are touching, in which case flip them + for (int k=0;kget_clip(panel_timeline->ghosts.at(k).clip); + if ((panel_timeline->trim_in_point && comp_clip->timeline_out == ghost_clip->timeline_in) || + (!panel_timeline->trim_in_point && comp_clip->timeline_in == ghost_clip->timeline_out)) { + panel_timeline->ghosts[k].trim_in = !panel_timeline->trim_in_point; + } + } + } + + // then look for other clips we're touching + for (int i=0;ighosts.at(i); + Clip* ghost_clip = sequence->get_clip(g.clip); for (int j=0;jclip_count();j++) { Clip* comp_clip = sequence->get_clip(j); if (comp_clip->track == ghost_clip->track) { @@ -802,20 +818,56 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { (!panel_timeline->trim_in_point && comp_clip->timeline_in == ghost_clip->timeline_out)) { // see if this clip is already selected, and if so just switch the trim_in bool found = false; - for (int k=0;kghosts.at(k).clip == j) { - panel_timeline->ghosts[k].trim_in = !panel_timeline->trim_in_point; + int duplicate_ghost_index; + for (duplicate_ghost_index=0;duplicate_ghost_indexghosts.at(duplicate_ghost_index).clip == j) { found = true; break; } } - - if (!found) { - // add ghost for this clip with opposite trim_in - Ghost g; - g.clip = j; - g.trim_in = !panel_timeline->trim_in_point; - panel_timeline->ghosts.append(g); + if (g.trim_in == panel_timeline->trim_in_point) { + if (!found) { + // add ghost for this clip with opposite trim_in + Ghost gh; + gh.clip = j; + gh.trimming = (panel_timeline->trim_target > -1); + gh.trim_in = !panel_timeline->trim_in_point; + panel_timeline->ghosts.append(gh); + } + } else { + if (found) { + panel_timeline->ghosts.removeAt(duplicate_ghost_index); + size--; + if (duplicate_ghost_index < i) i--; + } + } + } + } + } + } + } else if (panel_timeline->tool == TIMELINE_TOOL_SLIDE) { + for (int i=0;ighosts.at(i); + Clip* ghost_clip = sequence->get_clip(g.clip); + panel_timeline->ghosts[i].trimming = false; + for (int j=0;jclip_count();j++) { + Clip* c = sequence->get_clip(j); + if (c->track == ghost_clip->track) { + bool found = false; + for (int k=0;kghosts.at(k).clip == j) { + found = true; + break; + } + } + if (!found) { + bool is_in = (c->timeline_in == ghost_clip->timeline_out); + if (is_in || c->timeline_out == ghost_clip->timeline_in) { + Ghost gh; + gh.clip = j; + gh.trimming = true; + gh.trim_in = is_in; + panel_timeline->ghosts.append(gh); } } } @@ -1134,8 +1186,9 @@ void TimelineWidget::redraw_clips() { for (int j=0;jmedia_stream->audio_channels;j++) { int mid = clip_rect.top()+channel_height*j+(channel_height/2); int offset = waveform_index+(j*2); - qint8 min = (float)clip->media_stream->audio_preview[offset] / 128.0f * (channel_height/2); - qint8 max = (float)clip->media_stream->audio_preview[offset+1] / 128.0f * (channel_height/2); + + qint8 min = (double)clip->media_stream->audio_preview.at(offset) / 128.0 * (channel_height/2); + qint8 max = (double)clip->media_stream->audio_preview.at(offset+1) / 128.0 * (channel_height/2); clip_painter.drawLine(clip_rect.left()+i, mid+min, clip_rect.left()+i, mid+max); } } diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 5a5bdb33a..4fd711c97 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -186,7 +186,7 @@ void ViewerWidget::paintGL() { long sample_cache_playhead = panel_timeline->ui->audio_monitor->sample_cache_offset + panel_timeline->ui->audio_monitor->sample_cache.size(); int buffer_offset, buffer_offset_adjusted; while ((buffer_offset = get_buffer_offset_from_frame(sample_cache_playhead)) < audio_ibuffer_read) { - buffer_offset_adjusted = buffer_offset%audio_ibuffer_size; + buffer_offset_adjusted = (buffer_offset)%audio_ibuffer_size; panel_timeline->ui->audio_monitor->sample_cache.append((qint16) ((audio_ibuffer[buffer_offset_adjusted+1] << 8) | audio_ibuffer[buffer_offset_adjusted])); sample_cache_playhead++; }