1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-11-14 17:14:07 +01:00

Reimplement the play/record indicator in the ruler as an overlay...

... fixing the lag between the green line and the triangle for scrolling play
This commit is contained in:
Paul Licameli
2016-05-08 16:54:02 -04:00
parent d8e42b0af4
commit f9dd6b4066
4 changed files with 120 additions and 109 deletions

View File

@@ -30,30 +30,26 @@ namespace {
{
return (m >= l && m < h);
}
enum { IndicatorMediumWidth = 13 };
}
PlayIndicatorOverlay::PlayIndicatorOverlay(AudacityProject *project)
: mProject(project)
, mLastIndicatorX(-1)
, mNewIndicatorX(-1)
PlayIndicatorOverlayBase::PlayIndicatorOverlayBase(AudacityProject *project, bool isMaster)
: mProject(project)
, mIsMaster(isMaster)
{
mProject->Connect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
NULL,
this);
}
PlayIndicatorOverlay::~PlayIndicatorOverlay()
PlayIndicatorOverlayBase::~PlayIndicatorOverlayBase()
{
mProject->Disconnect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
NULL,
this);
}
std::pair<wxRect, bool> PlayIndicatorOverlay::DoGetRectangle(wxSize size)
std::pair<wxRect, bool> PlayIndicatorOverlayBase::DoGetRectangle(wxSize size)
{
wxRect rect(mLastIndicatorX, 0, 1, size.GetHeight());
auto width = mIsMaster ? 1 : IndicatorMediumWidth;
// May be excessive height, but little matter
wxRect rect(mLastIndicatorX - width / 2, 0, width, size.GetHeight());
return std::make_pair(
rect,
mLastIndicatorX != mNewIndicatorX
@@ -61,56 +57,75 @@ std::pair<wxRect, bool> PlayIndicatorOverlay::DoGetRectangle(wxSize size)
}
void PlayIndicatorOverlay::Draw(OverlayPanel &panel, wxDC &dc)
void PlayIndicatorOverlayBase::Draw(OverlayPanel &panel, wxDC &dc)
{
TrackPanel &tp = static_cast<TrackPanel&>(panel);
TrackPanelCellIterator begin(&tp, true);
TrackPanelCellIterator end(&tp, false);
// Set play/record color
bool rec = (gAudioIO->GetNumCaptureChannels() > 0);
AColor::IndicatorColor(&dc, !rec);
mLastIndicatorX = mNewIndicatorX;
if (!between_incexc(0, mLastIndicatorX, dc.GetSize().GetWidth()))
return;
const ZoomInfo &viewInfo = mProject->GetZoomInfo();
TrackPanel *const trackPanel = mProject->GetTrackPanel();
if(auto tp = dynamic_cast<TrackPanel*>(&panel)) {
wxASSERT(mIsMaster);
double pos = viewInfo.PositionToTime(mLastIndicatorX, trackPanel->GetLeftOffset());
TrackPanelCellIterator begin(tp, true);
TrackPanelCellIterator end(tp, false);
// Set play/record color
bool rec = (gAudioIO->GetNumCaptureChannels() > 0);
AColor::IndicatorColor(&dc, !rec);
mProject->GetRulerPanel()->DrawIndicator(pos, rec);
// Draw indicator in all visible tracks
for (; begin != end; ++begin)
{
TrackPanelCellIterator::value_type data(*begin);
Track *const pTrack = data.first;
if (!pTrack)
continue;
// Don't draw the indicator in label tracks
if (pTrack->GetKind() == Track::Label)
// Draw indicator in all visible tracks
for (; begin != end; ++begin)
{
continue;
}
TrackPanelCellIterator::value_type data(*begin);
Track *const pTrack = data.first;
if (!pTrack)
continue;
// Draw the NEW indicator in its NEW location
// AColor::Line includes both endpoints so use GetBottom()
const wxRect &rect = data.second;
AColor::Line(dc,
mLastIndicatorX,
rect.GetTop(),
mLastIndicatorX,
rect.GetBottom());
// Don't draw the indicator in label tracks
if (pTrack->GetKind() == Track::Label)
{
continue;
}
// Draw the NEW indicator in its NEW location
// AColor::Line includes both endpoints so use GetBottom()
const wxRect &rect = data.second;
AColor::Line(dc,
mLastIndicatorX,
rect.GetTop(),
mLastIndicatorX,
rect.GetBottom());
}
}
else if(auto ruler = dynamic_cast<AdornedRulerPanel*>(&panel)) {
wxASSERT(!mIsMaster);
ruler->DoDrawIndicator(&dc, mLastIndicatorX, !rec, IndicatorMediumWidth, false);
}
else
wxASSERT(false);
}
void PlayIndicatorOverlay::Erase(wxDC &dc, wxDC &src)
PlayIndicatorOverlay::PlayIndicatorOverlay(AudacityProject *project)
: PlayIndicatorOverlayBase(project, true)
{
Overlay::Erase(dc, src);
mProject->GetRulerPanel()->ClearIndicator();
mProject->Connect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
NULL,
this);
}
PlayIndicatorOverlay::~PlayIndicatorOverlay()
{
if (mPartner) {
auto ruler = mProject->GetRulerPanel();
if(ruler)
ruler->RemoveOverlay(mPartner.get());
}
mProject->Disconnect(EVT_TRACK_PANEL_TIMER,
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
NULL,
this);
}
void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
@@ -118,6 +133,15 @@ void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
// Let other listeners get the notification
event.Skip();
// Ensure that there is an overlay attached to the ruler
if (!mPartner) {
auto ruler = mProject->GetRulerPanel();
if (ruler) {
mPartner = std::make_unique<PlayIndicatorOverlayBase>(mProject, false);
ruler->AddOverlay(mPartner.get());
}
}
if (!mProject->IsAudioActive()) {
const auto &scrubber = mProject->GetScrubber();
if (scrubber.HasStartedScrubbing())
@@ -158,4 +182,7 @@ void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
mNewIndicatorX = viewInfo.TimeToPosition(playPos, mProject->GetTrackPanel()->GetLeftOffset());
}
if(mPartner)
mPartner->Update(mNewIndicatorX);
}

View File

@@ -12,28 +12,44 @@ Paul Licameli split from TrackPanel.cpp
#define __AUDACITY_PLAY_INDICATOR_OVERLAY__
#include <wx/event.h>
#include "../../MemoryX.h"
#include "../../widgets/Overlay.h"
class AudacityProject;
class PlayIndicatorOverlay final : public wxEvtHandler, public Overlay
// Common class for overlaying track panel or ruler
class PlayIndicatorOverlayBase : public wxEvtHandler, public Overlay
{
public:
PlayIndicatorOverlayBase(AudacityProject *project, bool isMaster);
virtual ~PlayIndicatorOverlayBase();
void Update(int newIndicatorX) { mNewIndicatorX = newIndicatorX; }
private:
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
void Draw(OverlayPanel &panel, wxDC &dc) override;
protected:
AudacityProject *const mProject;
const bool mIsMaster;
int mLastIndicatorX { -1 };
int mNewIndicatorX { -1 };
};
// Master object for track panel, creates the other object for the ruler
class PlayIndicatorOverlay final : public PlayIndicatorOverlayBase
{
public:
PlayIndicatorOverlay(AudacityProject *project);
virtual ~PlayIndicatorOverlay();
private:
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
void Draw(OverlayPanel &panel, wxDC &dc) override;
void Erase(wxDC &dc, wxDC &src) override;
void OnTimer(wxCommandEvent &event);
AudacityProject *mProject;
int mLastIndicatorX;
int mNewIndicatorX;
std::unique_ptr<PlayIndicatorOverlayBase> mPartner;
};
#endif