diff --git a/app/render/backend/audiorenderbackend.cpp b/app/render/backend/audiorenderbackend.cpp index 5baf68c17..2200328c7 100644 --- a/app/render/backend/audiorenderbackend.cpp +++ b/app/render/backend/audiorenderbackend.cpp @@ -27,6 +27,8 @@ void AudioRenderBackend::SetParameters(const AudioRenderingParams ¶ms) // Regenerate the cache ID RegenerateCacheID(); + + emit ParamsChanged(); } void AudioRenderBackend::ConnectViewer(ViewerOutput *node) diff --git a/app/render/backend/audiorenderbackend.h b/app/render/backend/audiorenderbackend.h index 775d7991a..897efa8d7 100644 --- a/app/render/backend/audiorenderbackend.h +++ b/app/render/backend/audiorenderbackend.h @@ -24,6 +24,9 @@ public: QString CachePathName(); +signals: + void ParamsChanged(); + protected: virtual void ConnectViewer(ViewerOutput* node) override; diff --git a/app/widget/timelinewidget/view/timelineplayhead.cpp b/app/widget/timelinewidget/view/timelineplayhead.cpp index 0b9ea95a9..f15e9cf2d 100644 --- a/app/widget/timelinewidget/view/timelineplayhead.cpp +++ b/app/widget/timelinewidget/view/timelineplayhead.cpp @@ -22,12 +22,12 @@ #include -const QColor &TimelinePlayhead::PlayheadColor() const +const QColor &TimelinePlayhead::GetPlayheadColor() const { return playhead_color_; } -const QColor &TimelinePlayhead::PlayheadHighlightColor() const +const QColor &TimelinePlayhead::GetPlayheadHighlightColor() const { return playhead_highlight_color_; } @@ -45,10 +45,10 @@ void TimelinePlayhead::SetPlayheadHighlightColor(QColor c) void TimelinePlayhead::Draw(QPainter* painter, const QRectF& playhead_rect) const { painter->setPen(Qt::NoPen); - painter->setBrush(PlayheadHighlightColor()); + painter->setBrush(GetPlayheadHighlightColor()); painter->drawRect(playhead_rect); - painter->setPen(PlayheadColor()); + painter->setPen(GetPlayheadColor()); painter->setBrush(Qt::NoBrush); painter->drawLine(QLineF(playhead_rect.topLeft(), playhead_rect.bottomLeft())); } diff --git a/app/widget/timelinewidget/view/timelineplayhead.h b/app/widget/timelinewidget/view/timelineplayhead.h index bbdf1f934..15b2f0031 100644 --- a/app/widget/timelinewidget/view/timelineplayhead.h +++ b/app/widget/timelinewidget/view/timelineplayhead.h @@ -31,13 +31,13 @@ class TimelinePlayhead : public QWidget { Q_OBJECT - Q_PROPERTY(QColor playheadColor READ PlayheadColor WRITE SetPlayheadColor DESIGNABLE true) - Q_PROPERTY(QColor playheadHighlightColor READ PlayheadHighlightColor WRITE SetPlayheadHighlightColor DESIGNABLE true) + Q_PROPERTY(QColor playheadColor READ GetPlayheadColor WRITE SetPlayheadColor DESIGNABLE true) + Q_PROPERTY(QColor playheadHighlightColor READ GetPlayheadHighlightColor WRITE SetPlayheadHighlightColor DESIGNABLE true) public: TimelinePlayhead() = default; - const QColor& PlayheadColor() const; - const QColor& PlayheadHighlightColor() const; + const QColor& GetPlayheadColor() const; + const QColor& GetPlayheadHighlightColor() const; void SetPlayheadColor(QColor c); void SetPlayheadHighlightColor(QColor c); diff --git a/app/widget/timeruler/CMakeLists.txt b/app/widget/timeruler/CMakeLists.txt index 9fe06158f..9c7882713 100644 --- a/app/widget/timeruler/CMakeLists.txt +++ b/app/widget/timeruler/CMakeLists.txt @@ -16,6 +16,8 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} + widget/timeruler/seekablewidget.h + widget/timeruler/seekablewidget.cpp widget/timeruler/timeruler.h widget/timeruler/timeruler.cpp PARENT_SCOPE diff --git a/app/widget/timeruler/seekablewidget.cpp b/app/widget/timeruler/seekablewidget.cpp new file mode 100644 index 000000000..b24d90ae2 --- /dev/null +++ b/app/widget/timeruler/seekablewidget.cpp @@ -0,0 +1,110 @@ +#include "seekablewidget.h" + +#include +#include + +SeekableWidget::SeekableWidget(QWidget* parent) : + TimelineScaledWidget(parent), + time_(0), + timeline_points_(nullptr), + scroll_(0) +{ + +} + +void SeekableWidget::ConnectTimelinePoints(TimelinePoints *points) +{ + if (timeline_points_) { + disconnect(timeline_points_->workarea(), &TimelineWorkArea::RangeChanged, this, static_cast(&SeekableWidget::update)); + disconnect(timeline_points_->workarea(), &TimelineWorkArea::EnabledChanged, this, static_cast(&SeekableWidget::update)); + } + + timeline_points_ = points; + + if (timeline_points_) { + connect(timeline_points_->workarea(), &TimelineWorkArea::RangeChanged, this, static_cast(&SeekableWidget::update)); + connect(timeline_points_->workarea(), &TimelineWorkArea::EnabledChanged, this, static_cast(&SeekableWidget::update)); + } + + update(); +} + +const int64_t &SeekableWidget::GetTime() const +{ + return time_; +} + +const int &SeekableWidget::GetScroll() const +{ + return scroll_; +} + +void SeekableWidget::mousePressEvent(QMouseEvent *event) +{ + SeekToScreenPoint(event->pos().x()); +} + +void SeekableWidget::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton) { + SeekToScreenPoint(event->pos().x()); + } +} + +void SeekableWidget::ScaleChangedEvent(const double &) +{ + update(); +} + +TimelinePoints *SeekableWidget::timeline_points() const +{ + return timeline_points_; +} + +void SeekableWidget::SetTime(const int64_t &r) +{ + time_ = r; + + update(); +} + +void SeekableWidget::SetScroll(int s) +{ + scroll_ = s; + + update(); +} + +double SeekableWidget::ScreenToUnitFloat(int screen) +{ + return (screen + scroll_) / GetScale() / timebase_dbl(); +} + +int64_t SeekableWidget::ScreenToUnit(int screen) +{ + return qFloor(ScreenToUnitFloat(screen)); +} + +int64_t SeekableWidget::ScreenToUnitRounded(int screen) +{ + return qRound64(ScreenToUnitFloat(screen)); +} + +int SeekableWidget::UnitToScreen(int64_t unit) +{ + return qFloor(static_cast(unit) * GetScale() * timebase_dbl()) - scroll_; +} + +int SeekableWidget::TimeToScreen(const rational &time) +{ + return qFloor(time.toDouble() * GetScale()) - scroll_; +} + +void SeekableWidget::SeekToScreenPoint(int screen) +{ + int64_t timestamp = qMax(static_cast(0), ScreenToUnitRounded(screen)); + + SetTime(timestamp); + + emit TimeChanged(timestamp); +} diff --git a/app/widget/timeruler/seekablewidget.h b/app/widget/timeruler/seekablewidget.h new file mode 100644 index 000000000..9c79d20e6 --- /dev/null +++ b/app/widget/timeruler/seekablewidget.h @@ -0,0 +1,72 @@ +#ifndef SEEKABLEWIDGET_H +#define SEEKABLEWIDGET_H + +#include "common/rational.h" +#include "timeline/timelinepoints.h" +#include "widget/timelinewidget/view/timelineplayhead.h" +#include "widget/timelinewidget/timelinescaledobject.h" + +class SeekableWidget : public TimelineScaledWidget +{ + Q_OBJECT +public: + SeekableWidget(QWidget *parent = nullptr); + + const int64_t& GetTime() const; + + const int& GetScroll() const; + + void ConnectTimelinePoints(TimelinePoints* points); + +public slots: + void SetTime(const int64_t &r); + + void SetScroll(int s); + +protected: + void SeekToScreenPoint(int screen); + + virtual void mousePressEvent(QMouseEvent *event) override; + virtual void mouseMoveEvent(QMouseEvent *event) override; + + virtual void ScaleChangedEvent(const double&) override; + + TimelinePoints* timeline_points() const; + + double ScreenToUnitFloat(int screen); + + int64_t ScreenToUnit(int screen); + int64_t ScreenToUnitRounded(int screen); + + int UnitToScreen(int64_t unit); + + int TimeToScreen(const rational& time); + + inline const QColor& GetPlayheadColor() const + { + return style_.GetPlayheadColor(); + } + + inline const QColor& GetPlayheadHighlightColor() const + { + return style_.GetPlayheadHighlightColor(); + } + +signals: + /** + * @brief Signal emitted whenever the time changes on this ruler, either by user or programatically + */ + void TimeChanged(int64_t); + +private: + int64_t time_; + + TimelinePlayhead style_; + + TimelinePoints* timeline_points_; + + int scroll_; + +}; + +#endif // SEEKABLEWIDGET_H diff --git a/app/widget/timeruler/timeruler.cpp b/app/widget/timeruler/timeruler.cpp index beb0daf5c..25df8bdfe 100644 --- a/app/widget/timeruler/timeruler.cpp +++ b/app/widget/timeruler/timeruler.cpp @@ -21,9 +21,7 @@ #include "timeruler.h" #include -#include #include -#include #include "common/timecodefunctions.h" #include "common/qtutils.h" @@ -31,13 +29,10 @@ #include "core.h" TimeRuler::TimeRuler(bool text_visible, bool cache_status_visible, QWidget* parent) : - TimelineScaledWidget(parent), - scroll_(0), + SeekableWidget(parent), text_visible_(text_visible), centered_text_(true), - time_(0), - show_cache_status_(cache_status_visible), - timeline_points_(nullptr) + show_cache_status_(cache_status_visible) { QFontMetrics fm = fontMetrics(); @@ -58,28 +53,6 @@ TimeRuler::TimeRuler(bool text_visible, bool cache_status_visible, QWidget* pare UpdateHeight(); } -void TimeRuler::ConnectTimelinePoints(TimelinePoints *points) -{ - if (timeline_points_) { - disconnect(timeline_points_->workarea(), &TimelineWorkArea::RangeChanged, this, &TimeRuler::TimelineWorkareaChanged); - disconnect(timeline_points_->workarea(), &TimelineWorkArea::EnabledChanged, this, &TimeRuler::TimelineWorkareaChanged); - } - - timeline_points_ = points; - - if (timeline_points_) { - connect(timeline_points_->workarea(), &TimelineWorkArea::RangeChanged, this, &TimeRuler::TimelineWorkareaChanged); - connect(timeline_points_->workarea(), &TimelineWorkArea::EnabledChanged, this, &TimeRuler::TimelineWorkareaChanged); - } - - update(); -} - -const int64_t &TimeRuler::GetTime() -{ - return time_; -} - void TimeRuler::SetCacheStatusLength(const rational &length) { if (show_cache_status_) { @@ -91,20 +64,6 @@ void TimeRuler::SetCacheStatusLength(const rational &length) } } -void TimeRuler::SetTime(const int64_t &r) -{ - time_ = r; - - update(); -} - -void TimeRuler::SetScroll(int s) -{ - scroll_ = s; - - update(); -} - void TimeRuler::CacheInvalidatedRange(const TimeRange& range) { if (show_cache_status_) { @@ -133,15 +92,15 @@ void TimeRuler::paintEvent(QPaintEvent *) QPainter p(this); // Draw timeline points if connected - if (timeline_points_) { - if (timeline_points_->workarea()->enabled()) { - int workarea_left = qMax(0, TimeToScreen(timeline_points_->workarea()->in())); + if (timeline_points()) { + if (timeline_points()->workarea()->enabled()) { + int workarea_left = qMax(0, TimeToScreen(timeline_points()->workarea()->in())); int workarea_right; - if (timeline_points_->workarea()->out() == TimelineWorkArea::kResetOut) { + if (timeline_points()->workarea()->out() == TimelineWorkArea::kResetOut) { workarea_right = width(); } else { - workarea_right = qMin(width(), TimeToScreen(timeline_points_->workarea()->out())); + workarea_right = qMin(width(), TimeToScreen(timeline_points()->workarea()->out())); } p.fillRect(workarea_left, 0, workarea_right - workarea_left, height(), palette().highlight()); @@ -239,7 +198,7 @@ void TimeRuler::paintEvent(QPaintEvent *) const int kAverageTextWidth = 200; for (int i=-kAverageTextWidth;i(i + scroll_); + double screen_pt = static_cast(i + GetScroll()); if (long_interval > -1) { int this_long_unit = qFloor(screen_pt/long_interval); @@ -318,26 +277,14 @@ void TimeRuler::paintEvent(QPaintEvent *) } // Draw the playhead if it's on screen at the moment - int playhead_pos = UnitToScreen(time_); + int playhead_pos = UnitToScreen(GetTime()); if (playhead_pos + playhead_width_ >= 0 && playhead_pos - playhead_width_ < width()) { p.setPen(Qt::NoPen); - p.setBrush(style_.PlayheadColor()); + p.setBrush(GetPlayheadColor()); DrawPlayhead(&p, playhead_pos, line_bottom); } } -void TimeRuler::mousePressEvent(QMouseEvent *event) -{ - SeekToScreenPoint(event->pos().x()); -} - -void TimeRuler::mouseMoveEvent(QMouseEvent *event) -{ - if (event->buttons() & Qt::LeftButton) { - SeekToScreenPoint(event->pos().x()); - } -} - void TimeRuler::TimebaseChangedEvent(const rational &tb) { timebase_flipped_dbl_ = tb.flipped().toDouble(); @@ -345,11 +292,6 @@ void TimeRuler::TimebaseChangedEvent(const rational &tb) update(); } -void TimeRuler::ScaleChangedEvent(const double &) -{ - update(); -} - void TimeRuler::DrawPlayhead(QPainter *p, int x, int y) { p->setRenderHint(QPainter::Antialiasing); @@ -374,40 +316,6 @@ int TimeRuler::CacheStatusHeight() const return fontMetrics().height() / 4; } -double TimeRuler::ScreenToUnitFloat(int screen) -{ - return (screen + scroll_) / GetScale() / timebase_dbl(); -} - -int64_t TimeRuler::ScreenToUnit(int screen) -{ - return qFloor(ScreenToUnitFloat(screen)); -} - -int TimeRuler::UnitToScreen(int64_t unit) -{ - return qFloor(static_cast(unit) * GetScale() * timebase_dbl()) - scroll_; -} - -int TimeRuler::TimeToScreen(const rational &time) -{ - return qFloor(time.toDouble() * GetScale()) - scroll_; -} - -void TimeRuler::SeekToScreenPoint(int screen) -{ - int64_t timestamp = qMax(0, qRound(ScreenToUnitFloat(screen))); - - SetTime(timestamp); - - emit TimeChanged(timestamp); -} - -void TimeRuler::TimelineWorkareaChanged() -{ - update(); -} - void TimeRuler::UpdateHeight() { int height = text_height_; diff --git a/app/widget/timeruler/timeruler.h b/app/widget/timeruler/timeruler.h index 471d1b752..f926d59d3 100644 --- a/app/widget/timeruler/timeruler.h +++ b/app/widget/timeruler/timeruler.h @@ -24,13 +24,10 @@ #include #include -#include "common/rational.h" #include "common/timerange.h" -#include "timeline/timelinepoints.h" -#include "widget/timelinewidget/timelinescaledobject.h" -#include "widget/timelinewidget/view/timelineplayhead.h" +#include "seekablewidget.h" -class TimeRuler : public TimelineScaledWidget +class TimeRuler : public SeekableWidget { Q_OBJECT public: @@ -38,15 +35,7 @@ public: void SetCenteredText(bool c); - void ConnectTimelinePoints(TimelinePoints* points); - - const int64_t& GetTime(); - public slots: - void SetTime(const int64_t &r); - - void SetScroll(int s); - void CacheInvalidatedRange(const TimeRange &range); void CacheTimeReady(const rational& time); @@ -56,19 +45,8 @@ public slots: protected: virtual void paintEvent(QPaintEvent* e) override; - virtual void mousePressEvent(QMouseEvent *event) override; - virtual void mouseMoveEvent(QMouseEvent *event) override; - virtual void TimebaseChangedEvent(const rational& tb) override; - virtual void ScaleChangedEvent(const double&); - -signals: - /** - * @brief Signal emitted whenever the time changes on this ruler, either by user or programatically - */ - void TimeChanged(int64_t); - private: void UpdateHeight(); @@ -76,16 +54,6 @@ private: int CacheStatusHeight() const; - double ScreenToUnitFloat(int screen); - - int64_t ScreenToUnit(int screen); - - int UnitToScreen(int64_t unit); - - int TimeToScreen(const rational& time); - - void SeekToScreenPoint(int screen); - int text_height_; int cache_status_height_; @@ -94,29 +62,18 @@ private: int playhead_width_; - int scroll_; - bool text_visible_; bool centered_text_; double timebase_flipped_dbl_; - int64_t time_; - - TimelinePlayhead style_; - bool show_cache_status_; rational cache_length_; TimeRangeList dirty_cache_ranges_; - TimelinePoints* timeline_points_; - -private slots: - void TimelineWorkareaChanged(); - }; #endif // TIMERULER_H diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index 747296c0b..f8c329237 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -96,6 +96,7 @@ ViewerWidget::ViewerWidget(QWidget *parent) : audio_renderer_ = new AudioBackend(this); waveform_view_->SetBackend(audio_renderer_); + connect(waveform_view_, &WaveformView::TimeChanged, this, &ViewerWidget::SetTimeAndSignal); connect(PixelFormat::instance(), &PixelFormat::FormatChanged, this, &ViewerWidget::UpdateRendererParameters); @@ -109,6 +110,7 @@ void ViewerWidget::TimeChangedEvent(const int64_t &i) } controls_->SetTime(i); + waveform_view_->SetTime(i); if (GetConnectedNode() && last_time_ != i) { rational time_set = Timecode::timestamp_to_time(i, timebase()); diff --git a/app/widget/viewer/waveformview.cpp b/app/widget/viewer/waveformview.cpp index 20508eb87..a0f26c03b 100644 --- a/app/widget/viewer/waveformview.cpp +++ b/app/widget/viewer/waveformview.cpp @@ -7,7 +7,7 @@ #include "common/clamp.h" WaveformView::WaveformView(QWidget *parent) : - TimelineScaledWidget(parent), + SeekableWidget(parent), backend_(nullptr) { setAutoFillBackground(true); @@ -18,12 +18,18 @@ void WaveformView::SetBackend(AudioRenderBackend *backend) { if (backend_) { disconnect(backend_, &AudioRenderBackend::QueueComplete, this, static_cast(&WaveformView::update)); + disconnect(backend_, &AudioRenderBackend::ParamsChanged, this, &WaveformView::BackendParamsChanged); + + SetTimebase(0); } backend_ = backend; if (backend_) { connect(backend_, &AudioRenderBackend::QueueComplete, this, static_cast(&WaveformView::update)); + connect(backend_, &AudioRenderBackend::ParamsChanged, this, &WaveformView::BackendParamsChanged); + + SetTimebase(rational(1, backend_->params().sample_rate())); } update(); @@ -69,15 +75,6 @@ void WaveformView::DrawWaveform(QPainter *painter, const QRect& rect, const doub } } -void WaveformView::SetScroll(int scroll) -{ - scroll_ = scroll; - - qDebug() << "Got scroll" << scroll_; - - update(); -} - void WaveformView::paintEvent(QPaintEvent *event) { QWidget::paintEvent(event); @@ -94,6 +91,7 @@ void WaveformView::paintEvent(QPaintEvent *event) QPainter p(this); + // FIXME: Hardcoded color p.setPen(Qt::green); int channel_height = height() / params.channel_count(); @@ -101,11 +99,11 @@ void WaveformView::paintEvent(QPaintEvent *event) int drew = 0; - fs.seek(params.samples_to_bytes(GetSampleIndexFromPixel(0))); + fs.seek(params.samples_to_bytes(ScreenToUnitRounded(0))); for (int x=0; x