diff --git a/effects/effect.cpp b/effects/effect.cpp index 1814bce08..21a27df41 100644 --- a/effects/effect.cpp +++ b/effects/effect.cpp @@ -536,7 +536,7 @@ void EffectRow::goto_previous_key() { key = qMax(comp, key); } } - if (key != LONG_MIN) panel_timeline->seek(key); + if (key != LONG_MIN) panel_sequence_viewer->seek(key); } void EffectRow::toggle_key() { @@ -570,7 +570,7 @@ void EffectRow::goto_next_key() { key = qMin(comp, key); } } - if (key != LONG_MAX) panel_timeline->seek(key); + if (key != LONG_MAX) panel_sequence_viewer->seek(key); } EffectField* EffectRow::add_field(int type, int colspan) { diff --git a/io/exportthread.cpp b/io/exportthread.cpp index 2f1ff9aa6..dda505b5f 100644 --- a/io/exportthread.cpp +++ b/io/exportthread.cpp @@ -307,7 +307,7 @@ bool ExportThread::setupContainer() { } void ExportThread::run() { - panel_timeline->pause(); + panel_sequence_viewer->pause(); if (!panel_sequence_viewer->viewer_widget->context()->makeCurrent(&surface)) { qDebug() << "[ERROR] Make current failed"; @@ -335,8 +335,8 @@ void ExportThread::run() { } } - panel_timeline->seek(start_frame); - panel_timeline->reset_all_audio(); + panel_sequence_viewer->seek(start_frame); + panel_sequence_viewer->reset_all_audio(); QOpenGLFramebufferObject fbo(sequence->width, sequence->height, QOpenGLFramebufferObject::CombinedDepthStencil, GL_TEXTURE_RECTANGLE); fbo.bind(); diff --git a/mainwindow.cpp b/mainwindow.cpp index 8d257b451..0cabaa8bd 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -455,35 +455,35 @@ void MainWindow::on_actionReset_to_default_layout_triggered() void MainWindow::on_actionGo_to_start_triggered() { if (sequence != NULL && (panel_timeline->focused() || panel_sequence_viewer->hasFocus() || panel_effect_controls->keyframe_focus())) { - panel_timeline->go_to_start(); + panel_sequence_viewer->go_to_start(); } } void MainWindow::on_actionPrevious_Frame_triggered() { if (sequence != NULL && (panel_timeline->focused() || panel_sequence_viewer->hasFocus() || panel_effect_controls->keyframe_focus())) { - panel_timeline->previous_frame(); + panel_sequence_viewer->previous_frame(); } } void MainWindow::on_actionNext_Frame_triggered() { if (sequence != NULL && (panel_timeline->focused() || panel_sequence_viewer->hasFocus() || panel_effect_controls->keyframe_focus())) { - panel_timeline->next_frame(); + panel_sequence_viewer->next_frame(); } } void MainWindow::on_actionGo_to_End_triggered() { if (sequence != NULL && (panel_timeline->focused() || panel_sequence_viewer->hasFocus() || panel_effect_controls->keyframe_focus())) { - panel_timeline->go_to_end(); + panel_sequence_viewer->go_to_end(); } } void MainWindow::on_actionPlay_Pause_triggered() { if (sequence != NULL && (panel_timeline->focused() || panel_sequence_viewer->hasFocus() || panel_effect_controls->keyframe_focus())) { - panel_timeline->toggle_play(); + panel_sequence_viewer->toggle_play(); } } diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 0d316e33d..90369c9eb 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -39,7 +39,6 @@ void draw_selection_rectangle(QPainter& painter, const QRect& rect) { Timeline::Timeline(QWidget *parent) : QDockWidget(parent), - playing(false), cursor_frame(0), cursor_track(0), zoom(1.0), @@ -58,13 +57,14 @@ Timeline::Timeline(QWidget *parent) : ui(new Ui::Timeline), last_frame(0), creating(false), - queue_audio_reset(false), scroll(0) { default_track_height = (QGuiApplication::primaryScreen()->logicalDotsPerInch() / 96) * TRACK_DEFAULT_HEIGHT; ui->setupUi(this); + ui->headers->viewer = panel_sequence_viewer; + /* --- TEMPORARY --- * I feel like the rolling edit tool is unnecessary, but just * in case I change my mind, I'm leaving all the functionality @@ -95,8 +95,6 @@ Timeline::Timeline(QWidget *parent) : connect(ui->audioScrollbar, SIGNAL(valueChanged(int)), ui->audio_area, SLOT(setScroll(int))); update_sequence(); - - connect(&playback_updater, SIGNAL(timeout()), this, SLOT(repaint_timeline())); } Timeline::~Timeline() @@ -104,18 +102,6 @@ Timeline::~Timeline() delete ui; } -void Timeline::go_to_start() { - seek(0); -} - -void Timeline::previous_frame() { - if (sequence->playhead > 0) seek(sequence->playhead-1); -} - -void Timeline::next_frame() { - seek(sequence->playhead+1); -} - void Timeline::previous_cut() { if (sequence->playhead > 0) { long p_cut = 0; @@ -129,7 +115,7 @@ void Timeline::previous_cut() { } } } - seek(p_cut); + panel_sequence_viewer->seek(p_cut); } } @@ -148,62 +134,7 @@ void Timeline::next_cut() { } } } - if (seek_enabled) seek(n_cut); -} - -void Timeline::reset_all_audio() { - // reset all clip audio - if (sequence != NULL) { - audio_ibuffer_frame = sequence->playhead; - audio_ibuffer_timecode = (double) audio_ibuffer_frame / sequence->frame_rate; - - for (int i=0;iclips.size();i++) { - Clip* c = sequence->clips.at(i); - if (c != NULL) { - c->reset_audio(); - } - } - } - ui->audio_monitor->reset(); - clear_audio_ibuffer(); -} - -void Timeline::seek(long p) { - pause(); - sequence->playhead = p; - queue_audio_reset = true; - repaint_timeline(false); -} - -void Timeline::toggle_play() { - if (playing) { - pause(); - } else { - play(); - } -} - -void Timeline::play() { - if (queue_audio_reset) { - reset_all_audio(); - queue_audio_reset = false; - } - playhead_start = sequence->playhead; - start_msecs = QDateTime::currentMSecsSinceEpoch(); - playback_updater.start(); - playing = true; - panel_sequence_viewer->set_playpause_icon(false); - audio_thread->notifyReceiver(); -} - -void Timeline::pause() { - playing = false; - panel_sequence_viewer->set_playpause_icon(true); - playback_updater.stop(); -} - -void Timeline::go_to_end() { - seek(sequence->getEndFrame()); + if (seek_enabled) panel_sequence_viewer->seek(n_cut); } int Timeline::get_track_height_size(bool video) { @@ -277,9 +208,7 @@ void Timeline::update_sequence() { setWindowTitle("Timeline: "); } else { setWindowTitle("Timeline: " + sequence->name); - reset_all_audio(); repaint_timeline(false); - playback_updater.setInterval(qFloor(1000 / sequence->frame_rate)); } } @@ -293,11 +222,9 @@ bool Timeline::focused() { void Timeline::repaint_timeline(bool changed) { if (changed) { - reset_all_audio(); + panel_sequence_viewer->reset_all_audio(); update_effect_controls(); - if (!playing) panel_sequence_viewer->viewer_widget->update(); - } else if (playing) { - sequence->playhead = round(playhead_start + ((QDateTime::currentMSecsSinceEpoch()-start_msecs) * 0.001 * sequence->frame_rate)); + if (!panel_sequence_viewer->playing) panel_sequence_viewer->viewer_widget->update(); } ui->headers->update(); @@ -832,7 +759,7 @@ void Timeline::paste() { repaint_timeline(true); if (config.paste_seeks) { - seek(paste_end); + panel_sequence_viewer->seek(paste_end); } } } @@ -890,7 +817,7 @@ void Timeline::ripple_to_in_point(bool in) { repaint_timeline(true); - if (in) seek(in_point); + if (in) panel_sequence_viewer->seek(in_point); } } } @@ -1071,7 +998,7 @@ bool Timeline::snap_to_point(long point, long* l) { bool Timeline::snap_to_timeline(long* l, bool use_playhead, bool use_markers, bool use_workarea) { snapped = false; if (snapping) { - if (use_playhead && !playing) { + if (use_playhead && !panel_sequence_viewer->playing) { // snap to playhead if (snap_to_point(sequence->playhead, l)) return true; } diff --git a/panels/timeline.h b/panels/timeline.h index e1c844568..0126d5e8d 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -7,7 +7,6 @@ #include #include #include -#include #define TRACK_DEFAULT_HEIGHT 40 @@ -96,6 +95,8 @@ public: void set_in_point(); void set_out_point(); void delete_in_out(bool ripple); + void previous_cut(); + void next_cut(); int getTimelineScreenPointFromFrame(long frame); long getTimelineFrameFromScreenPoint(int x); @@ -107,22 +108,6 @@ public: bool snap_to_timeline(long* l, bool use_playhead, bool use_markers, bool use_workarea); void set_marker(); - // playback functions - void go_to_start(); - void previous_frame(); - void next_frame(); - void previous_cut(); - void next_cut(); - void seek(long p); - void toggle_play(); - void play(); - void pause(); - void go_to_end(); - bool playing; - long playhead_start; - qint64 start_msecs; - QTimer playback_updater; - // shared information int tool; long cursor_frame; @@ -179,8 +164,6 @@ public: bool creating; int creatingObject; - void reset_all_audio(); - Ui::Timeline *ui; public slots: void repaint_timeline(bool changed = false); @@ -218,8 +201,7 @@ private: void decheck_tool_buttons(QObject* sender); void set_tool(int tool); long last_frame; - QVector clip_clipboard; - bool queue_audio_reset; + QVector clip_clipboard; int scroll; int default_track_height; diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 6af110d55..d62df4a09 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -7,6 +7,8 @@ #include "panels/panels.h" #include "io/config.h" #include "io/media.h" +#include "ui/audiomonitor.h" +#include "ui_timeline.h" #define FRAMES_IN_ONE_MINUTE 1798 // 1800 - 2 #define FRAMES_IN_TEN_MINUTES 17978 // (FRAMES_IN_ONE_MINUTE * 10) - 2 @@ -17,14 +19,18 @@ extern "C" { #include } +#include #include Viewer::Viewer(QWidget *parent) : QDockWidget(parent), ui(new Ui::Viewer), - seq(NULL) + seq(NULL), + queue_audio_reset(false), + playing(false) { ui->setupUi(this); + ui->headers->viewer = this; ui->headers->show_text(false); ui->glViewerPane->child = ui->openGLWidget; viewer_widget = ui->openGLWidget; @@ -36,6 +42,8 @@ Viewer::Viewer(QWidget *parent) : ui->currentTimecode->set_display_type(LABELSLIDER_FRAMENUMBER); connect(ui->currentTimecode, SIGNAL(valueChanged()), this, SLOT(update_playhead())); + connect(&playback_updater, SIGNAL(timeout()), this, SLOT(timer_update())); + update_playhead_timecode(0); update_end_timecode(); } @@ -48,6 +56,23 @@ void Viewer::set_main_sequence() { set_sequence(true, sequence); } +void Viewer::reset_all_audio() { + // reset all clip audio + if (seq != NULL) { + audio_ibuffer_frame = seq->playhead; + audio_ibuffer_timecode = (double) audio_ibuffer_frame / seq->frame_rate; + + for (int i=0;iclips.size();i++) { + Clip* c = seq->clips.at(i); + if (c != NULL) { + c->reset_audio(); + } + } + } + // panel_timeline->ui->audio_monitor->reset(); + clear_audio_ibuffer(); +} + QString frame_to_timecode(long f, int view, double frame_rate) { if (view == TIMECODE_FRAMES) { return QString::number(f); @@ -115,6 +140,56 @@ bool frame_rate_is_droppable(float rate) { return (rate == 23.976f || rate == 29.97f || rate == 59.94f); } +void Viewer::seek(long p) { + pause(); + seq->playhead = p; + queue_audio_reset = true; + panel_timeline->repaint_timeline(false); +} + +void Viewer::go_to_start() { + seek(0); +} + +void Viewer::previous_frame() { + if (seq->playhead > 0) seek(seq->playhead-1); +} + +void Viewer::next_frame() { + seek(seq->playhead+1); +} + +void Viewer::toggle_play() { + if (playing) { + pause(); + } else { + play(); + } +} + +void Viewer::play() { + if (queue_audio_reset) { + reset_all_audio(); + queue_audio_reset = false; + } + playhead_start = seq->playhead; + start_msecs = QDateTime::currentMSecsSinceEpoch(); + playback_updater.start(); + playing = true; + panel_sequence_viewer->set_playpause_icon(false); + audio_thread->notifyReceiver(); +} + +void Viewer::pause() { + playing = false; + panel_sequence_viewer->set_playpause_icon(true); + playback_updater.stop(); +} + +void Viewer::go_to_end() { + seek(seq->getEndFrame()); +} + void Viewer::update_playhead_timecode(long p) { ui->currentTimecode->set_value(p, false); } @@ -137,30 +212,37 @@ void Viewer::set_media(int type, void* media) { } void Viewer::on_pushButton_clicked() { - panel_timeline->go_to_start(); + go_to_start(); } void Viewer::on_pushButton_5_clicked() { - panel_timeline->go_to_end(); + go_to_end(); } void Viewer::on_pushButton_2_clicked() { - panel_timeline->previous_frame(); + previous_frame(); } void Viewer::on_pushButton_4_clicked() { - panel_timeline->next_frame(); + next_frame(); } void Viewer::on_pushButton_3_clicked() { - panel_timeline->toggle_play(); + toggle_play(); } void Viewer::update_playhead() { - panel_timeline->seek(ui->currentTimecode->value()); + seek(ui->currentTimecode->value()); +} + +void Viewer::timer_update() { + seq->playhead = round(playhead_start + ((QDateTime::currentMSecsSinceEpoch()-start_msecs) * 0.001 * seq->frame_rate)); + if (main_sequence) panel_timeline->repaint_timeline(false); } void Viewer::set_sequence(bool main, Sequence *s) { + reset_all_audio(); + main_sequence = main; seq = (main) ? sequence : s; viewer_widget->display_sequence = seq; @@ -180,6 +262,8 @@ void Viewer::set_sequence(bool main, Sequence *s) { init_audio(); if (!null_sequence) { + playback_updater.setInterval(qFloor(1000 / seq->frame_rate)); + config.timecode_view = (frame_rate_is_droppable(seq->frame_rate)) ? TIMECODE_DROP : TIMECODE_NONDROP; update_playhead_timecode(seq->playhead); diff --git a/panels/viewer.h b/panels/viewer.h index 6925f58ff..1c1ac4f0c 100644 --- a/panels/viewer.h +++ b/panels/viewer.h @@ -2,6 +2,7 @@ #define VIEWER_H #include +#include class Timeline; class ViewerWidget; @@ -29,6 +30,22 @@ public: void update_playhead_timecode(long p); void update_end_timecode(); + // playback functions + void go_to_start(); + void previous_frame(); + void next_frame(); + void seek(long p); + void toggle_play(); + void play(); + void pause(); + void go_to_end(); + bool playing; + long playhead_start; + qint64 start_msecs; + QTimer playback_updater; + + void reset_all_audio(); + ViewerWidget* viewer_widget; Ui::Viewer *ui; @@ -39,10 +56,12 @@ private slots: void on_pushButton_4_clicked(); void on_pushButton_3_clicked(); void update_playhead(); + void timer_update(); private: void set_sequence(bool main, Sequence* s); bool main_sequence; Sequence* seq; + bool queue_audio_reset; }; #endif // VIEWER_H diff --git a/playback/audio.cpp b/playback/audio.cpp index a8f6428fd..aa3c03dcb 100644 --- a/playback/audio.cpp +++ b/playback/audio.cpp @@ -4,6 +4,7 @@ #include "panels/panels.h" #include "panels/timeline.h" +#include "panels/viewer.h" #include "ui_timeline.h" #include @@ -112,7 +113,7 @@ void AudioSenderThread::run() { cond.wait(&lock); if (close) { break; - } else if (panel_timeline->playing) { + } else if (panel_sequence_viewer->playing) { int written_bytes = 0; int adjusted_read_index = audio_ibuffer_read%audio_ibuffer_size; diff --git a/ui/timelineheader.cpp b/ui/timelineheader.cpp index 16c534a7d..55f2eca33 100644 --- a/ui/timelineheader.cpp +++ b/ui/timelineheader.cpp @@ -54,7 +54,7 @@ void TimelineHeader::set_playhead(int mouse_x) { long frame = getHeaderFrameFromScreenPoint(mouse_x); if (snapping) panel_timeline->snap_to_timeline(&frame, false, true, true); if (frame != sequence->playhead) { - panel_timeline->seek(frame); + viewer->seek(frame); } } diff --git a/ui/timelineheader.h b/ui/timelineheader.h index 3ea910269..a7b61df2e 100644 --- a/ui/timelineheader.h +++ b/ui/timelineheader.h @@ -4,6 +4,7 @@ #include #include class QScrollArea; +class Viewer; class TimelineHeader : public QWidget { @@ -13,6 +14,8 @@ public: void set_in_point(long p); void set_out_point(long p); + Viewer* viewer; + bool snapping; void show_text(bool enable); diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index e20f1c87d..980650268 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -653,7 +653,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { sequence->selections.append(s); if (config.select_also_seeks) { - panel_timeline->seek(clip->timeline_in); + panel_sequence_viewer->seek(clip->timeline_in); } // if alt is not down, select links @@ -686,7 +686,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) { } break; case TIMELINE_TOOL_EDIT: - if (config.edit_tool_also_seeks) panel_timeline->seek(panel_timeline->drag_frame_start); + if (config.edit_tool_also_seeks) panel_sequence_viewer->seek(panel_timeline->drag_frame_start); panel_timeline->selecting = true; break; case TIMELINE_TOOL_RAZOR: @@ -1341,7 +1341,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { } if (config.edit_tool_also_seeks) { - panel_timeline->seek(qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame)); + panel_sequence_viewer->seek(qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame)); } else { panel_timeline->repaint_timeline(false); } diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 27cfa9117..8662ae03d 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -453,7 +453,7 @@ void ViewerWidget::paintGL() { // compose video preview glClearColor(0, 0, 0, 0); - compose_sequence(NULL, (panel_timeline->playing || rendering)); + compose_sequence(NULL, (panel_sequence_viewer->playing || rendering)); if (texture_failed) { if (rendering) {