Audacity  2.3.1
PlayIndicatorOverlay.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 PlayIndicatorOverlay.cpp
6 
7 Paul Licameli split from TrackPanel.cpp
8 
9 **********************************************************************/
10 
11 #include "../../Audacity.h"
12 #include "PlayIndicatorOverlay.h"
13 
14 #include "../../AColor.h"
15 #include "../../AdornedRulerPanel.h"
16 #include "../../AudioIO.h"
17 #include "../../Project.h"
18 #include "../../TrackPanel.h"
19 #include "Scrubbing.h"
20 
21 #include <wx/dc.h>
22 
23 #include <algorithm>
24 
25 namespace {
26  template < class LOW, class MID, class HIGH >
27  bool between_incexc(LOW l, MID m, HIGH h)
28  {
29  return (m >= l && m < h);
30  }
31 
32  enum { IndicatorMediumWidth = 13 };
33 }
34 
36 : mProject(project)
37 , mIsMaster(isMaster)
38 {
39 }
40 
42 {
43 }
44 
45 std::pair<wxRect, bool> PlayIndicatorOverlayBase::DoGetRectangle(wxSize size)
46 {
47  auto width = mIsMaster ? 1 : IndicatorMediumWidth;
48 
49  // May be excessive height, but little matter
50  wxRect rect(mLastIndicatorX - width / 2, 0, width, size.GetHeight());
51  return {
52  rect,
55  };
56 }
57 
58 
60 {
61  // Set play/record color
62  bool rec = gAudioIO->IsCapturing();
63  AColor::IndicatorColor(&dc, !rec);
64 
65  if (mIsMaster
67  // Detect transition to recording during punch and roll; make ruler
68  // change its button color too
69  const auto ruler = mProject->GetRulerPanel();
70  ruler->UpdateButtonStates();
71  ruler->Refresh();
72  }
74 
76  if (!between_incexc(0, mLastIndicatorX, dc.GetSize().GetWidth()))
77  return;
78 
79  if(auto tp = dynamic_cast<TrackPanel*>(&panel)) {
80  wxASSERT(mIsMaster);
81 
82  // Draw indicator in all visible tracks
83  tp->VisitCells( [&]( const wxRect &rect, TrackPanelCell &cell ) {
84  const auto pTrack = dynamic_cast<Track*>(&cell);
85  if (pTrack) pTrack->TypeSwitch(
86  [](LabelTrack *) {
87  // Don't draw the indicator in label tracks
88  },
89  [&](Track *) {
90  // Draw the NEW indicator in its NEW location
91  // AColor::Line includes both endpoints so use GetBottom()
92  AColor::Line(dc,
94  rect.GetTop(),
96  rect.GetBottom());
97  }
98  );
99  } );
100  }
101  else if(auto ruler = dynamic_cast<AdornedRulerPanel*>(&panel)) {
102  wxASSERT(!mIsMaster);
103 
104  ruler->DoDrawIndicator(&dc, mLastIndicatorX, !rec, IndicatorMediumWidth, false, false);
105  }
106  else
107  wxASSERT(false);
108 }
109 
111 : PlayIndicatorOverlayBase(project, true)
112 {
113  mProject->Bind(EVT_TRACK_PANEL_TIMER,
115  this);
116 }
117 
119 {
120  if (mPartner) {
121  auto ruler = mProject->GetRulerPanel();
122  if(ruler)
123  ruler->RemoveOverlay(mPartner.get());
124  }
125 }
126 
127 void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
128 {
129  // Let other listeners get the notification
130  event.Skip();
131 
132  // Ensure that there is an overlay attached to the ruler
133  if (!mPartner) {
134  auto ruler = mProject->GetRulerPanel();
135  if (ruler) {
136  mPartner = std::make_unique<PlayIndicatorOverlayBase>(mProject, false);
137  ruler->AddOverlay(mPartner.get());
138  }
139  }
140 
141  auto trackPanel = mProject->GetTrackPanel();
142  int width;
143  trackPanel->GetTracksUsableArea(&width, nullptr);
144 
145  if (!mProject->IsAudioActive()) {
146  mNewIndicatorX = -1;
147  mNewIsCapturing = false;
148  const auto &scrubber = mProject->GetScrubber();
149  if (scrubber.HasMark()) {
150  auto position = scrubber.GetScrubStartPosition();
151  const auto offset = trackPanel->GetLeftOffset();
152  if(position >= trackPanel->GetLeftOffset() &&
153  position < offset + width)
154  mNewIndicatorX = position;
155  }
156  }
157  else {
158  ViewInfo &viewInfo = mProject->GetViewInfo();
159 
160  // Calculate the horizontal position of the indicator
161  const double playPos = viewInfo.mRecentStreamTime;
162 
164  const Mode mode = mProject->GetPlaybackScroller().GetMode();
165  const bool pinned = ( mode == Mode::Pinned || mode == Mode::Right );
166 
167  // Use a small tolerance to avoid flicker of play head pinned all the way
168  // left or right
169  const auto tolerance = pinned ? 1.5 * kTimerInterval / 1000.0 : 0;
170  bool onScreen = playPos >= 0.0 &&
171  between_incexc(viewInfo.h - tolerance,
172  playPos,
173  mProject->GetScreenEndTime() + tolerance);
174 
175  // This displays the audio time, too...
177 
178  // BG: Scroll screen if option is set
179  if( viewInfo.bUpdateTrackIndicator &&
180  playPos >= 0 && !onScreen ) {
181  // msmeyer: But only if not playing looped or in one-second mode
182  // PRL: and not scrolling with play/record head fixed
183  if (!pinned &&
186  !gAudioIO->IsPaused())
187  {
188  auto newPos = playPos;
189  if (playPos < viewInfo.h) {
190  // This is possible when scrubbing backwards.
191  // We want to page leftward by (at least) a whole screen, not
192  // just a little bit equal to the scrubbing poll interval
193  // duration.
194  newPos = viewInfo.OffsetTimeByPixels( newPos, -width );
195  newPos = std::max( newPos, mProject->ScrollingLowerBoundTime() );
196  }
197  mProject->TP_ScrollWindow(newPos);
198  // Might yet be off screen, check it
199  onScreen = playPos >= 0.0 &&
200  between_incexc(viewInfo.h,
201  playPos,
203  }
204  }
205 
206  // Always update scrollbars even if not scrolling the window. This is
207  // important when NEW audio is recorded, because this can change the
208  // length of the project and therefore the appearance of the scrollbar.
210 
211  if (onScreen)
212  mNewIndicatorX = viewInfo.TimeToPosition(playPos, trackPanel->GetLeftOffset());
213  else
214  mNewIndicatorX = -1;
215 
217  }
218 
219  if(mPartner)
220  mPartner->Update(mNewIndicatorX);
221 }
bool bUpdateTrackIndicator
Definition: ViewInfo.h:184
ViewInfo is used mainly to hold the zooming, selection and scroll information. It also has some statu...
Definition: ViewInfo.h:143
Scrubber & GetScrubber()
Definition: Project.h:786
R TypeSwitch(const Functions &...functions)
Definition: Track.h:630
std::unique_ptr< PlayIndicatorOverlayBase > mPartner
bool IsCapturing() const
Definition: AudioIO.cpp:5789
double OffsetTimeByPixels(double time, wxInt64 offset, bool ignoreFisheye=false) const
Definition: ViewInfo.h:77
PlayIndicatorOverlayBase(AudacityProject *project, bool isMaster)
bool RemoveOverlay(Overlay *pOverlay)
double h
Definition: ViewInfo.h:47
void TP_RedrawScrollbars() override
Definition: Project.cpp:5077
AudacityProject *const mProject
static void IndicatorColor(wxDC *dc, bool bIsNotRecording)
Definition: AColor.cpp:367
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:113
void GetTracksUsableArea(int *width, int *height) const
Definition: TrackPanel.cpp:328
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:174
void TP_ScrollWindow(double scrollto) override
Definition: Project.cpp:1932
const int kTimerInterval
double ScrollingLowerBoundTime() const
Definition: Project.cpp:1893
AdornedRulerPanel * GetRulerPanel()
Definition: Project.cpp:1517
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:191
wxInt64 TimeToPosition(double time, wxInt64 origin=0, bool ignoreFisheye=false) const
STM: Converts a project time to screen x position.
Definition: ViewInfo.cpp:59
bool IsAudioActive() const
Definition: Project.cpp:1532
PlayIndicatorOverlay(AudacityProject *project)
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:122
PlayMode mLastPlayMode
Definition: Project.h:554
std::pair< wxRect, bool > DoGetRectangle(wxSize size) override
AudioIO * gAudioIO
Definition: AudioIO.cpp:491
PlaybackScroller & GetPlaybackScroller()
Definition: Project.h:827
double GetScreenEndTime() const
Definition: Project.cpp:5630
bool IsPaused() const
Find out if playback / recording is currently paused.
Definition: AudioIO.cpp:2709
double mRecentStreamTime
Definition: ViewInfo.h:191
void OnTimer(wxCommandEvent &event)
TrackPanel * GetTrackPanel()
Definition: Project.h:324
void TP_DisplaySelection() override
Definition: Project.cpp:5006
wxCoord GetScrubStartPosition() const
Definition: Scrubbing.h:93
const ViewInfo & GetViewInfo() const
Definition: Project.h:224
void Draw(OverlayPanel &panel, wxDC &dc) override