Audacity  2.2.2
Classes | Public Types | Public Member Functions | Static Public Member Functions | Private Types | Private Member Functions | Private Attributes | Static Private Attributes | Friends | List of all members
Meter Class Referencefinal

VU Meter, for displaying recording/playback level. More...

#include <Meter.h>

Inheritance diagram for Meter:
wxPanelWrapper wxTabTraversalWrapper< wxPanel >

Classes

struct  Resetter
 
struct  State
 

Public Types

enum  Style {
  AutomaticStereo, HorizontalStereo, VerticalStereo, MixerTrackCluster,
  HorizontalStereoCompact, VerticalStereoCompact
}
 

Public Member Functions

 Meter (AudacityProject *, wxWindow *parent, wxWindowID id, bool isInput, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, Style style=HorizontalStereo, float fDecayRate=60.0f)
 
 ~Meter ()
 
bool AcceptsFocus () const override
 
bool AcceptsFocusFromKeyboard () const override
 
void SetFocusFromKbd () override
 
void UpdatePrefs ()
 
void Clear ()
 
Style GetStyle () const
 
Style GetDesiredStyle () const
 
void SetStyle (Style newStyle)
 
void Reset (double sampleRate, bool resetClipping)
 This method is thread-safe! Feel free to call from a different thread (like from an audio I/O callback). More...
 
void UpdateDisplay (unsigned numChannels, int numFrames, float *sampleData)
 Update the meters with a block of audio data. More...
 
bool IsMeterDisabled () const
 Find out if the level meter is disabled or not. More...
 
float GetMaxPeak () const
 
bool IsClipping () const
 
void StartMonitoring ()
 
void StopMonitoring ()
 
State SaveState ()
 
void RestoreState (const State &state)
 
- Public Member Functions inherited from wxPanelWrapper
 wxPanelWrapper ()
 
 wxPanelWrapper (wxWindow *parent, wxWindowID winid=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL|wxNO_BORDER, const wxString &name=_("Panel"))
 
bool Create (wxWindow *parent, wxWindowID winid=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL|wxNO_BORDER, const wxString &name=_("Panel"))
 
- Public Member Functions inherited from wxTabTraversalWrapper< wxPanel >
 wxTabTraversalWrapper (Args &&...args)
 
 ~wxTabTraversalWrapper ()
 

Static Public Member Functions

static TempAllowFocus TemporarilyAllowFocus ()
 

Private Types

using TempAllowFocus = std::unique_ptr< bool, Resetter >
 

Private Member Functions

void OnErase (wxEraseEvent &evt)
 
void OnPaint (wxPaintEvent &evt)
 
void OnSize (wxSizeEvent &evt)
 
bool InIcon (wxMouseEvent *pEvent=nullptr) const
 
void OnMouse (wxMouseEvent &evt)
 
void OnKeyDown (wxKeyEvent &evt)
 
void OnKeyUp (wxKeyEvent &evt)
 
void OnContext (wxContextMenuEvent &evt)
 
void OnSetFocus (wxFocusEvent &evt)
 
void OnKillFocus (wxFocusEvent &evt)
 
void OnAudioIOStatus (wxCommandEvent &evt)
 
void OnMeterUpdate (wxTimerEvent &evt)
 
void HandleLayout (wxDC &dc)
 
void SetActiveStyle (Style style)
 
void SetBarAndClip (int iBar, bool vert)
 
void DrawMeterBar (wxDC &dc, MeterBar *meterBar)
 
void ResetBar (MeterBar *bar, bool resetClipping)
 
void RepaintBarsNow ()
 
wxFont GetFont () const
 
void ShowMenu (const wxPoint &pos)
 
void OnMonitor (wxCommandEvent &evt)
 
void OnPreferences (wxCommandEvent &evt)
 
void OnMeterPrefsUpdated (wxCommandEvent &evt)
 
wxString Key (const wxString &key) const
 

Private Attributes

AudacityProjectmProject
 
MeterUpdateQueue mQueue
 
wxTimer mTimer
 
int mWidth
 
int mHeight
 
int mRulerWidth
 
int mRulerHeight
 
bool mIsInput
 
Style mStyle
 
Style mDesiredStyle
 
bool mGradient
 
bool mDB
 
int mDBRange
 
bool mDecay
 
float mDecayRate
 
bool mClip
 
int mNumPeakSamplesToClip
 
double mPeakHoldDuration
 
double mT
 
double mRate
 
long mMeterRefreshRate
 
long mMeterDisabled
 
bool mMonitoring
 
bool mActive
 
unsigned mNumBars
 
MeterBar mBar [kMaxMeterBars]
 
bool mLayoutValid
 
std::unique_ptr< wxBitmap > mBitmap
 
wxRect mIconRect
 
wxPoint mLeftTextPos
 
wxPoint mRightTextPos
 
wxSize mLeftSize
 
wxSize mRightSize
 
std::unique_ptr< wxBitmap > mIcon
 
wxPen mPen
 
wxPen mDisabledPen
 
wxPen mPeakPeakPen
 
wxBrush mBrush
 
wxBrush mRMSBrush
 
wxBrush mClipBrush
 
wxBrush mBkgndBrush
 
wxBrush mDisabledBkgndBrush
 
Ruler mRuler
 
wxString mLeftText
 
wxString mRightText
 
bool mIsFocused
 
wxRect mFocusRect
 
bool mAccSilent
 
bool mHighlighted {}
 

Static Private Attributes

static bool s_AcceptsFocus { false }
 

Friends

class MeterAx
 

Detailed Description

VU Meter, for displaying recording/playback level.

This is a bunch of common code that can display many different forms of VU meters and other displays.

But note that a lot of later code here assumes these are MeterToolBar meters, e.g., Meter::StartMonitoring, so these are not as generic/common as originally intended.

Definition at line 88 of file Meter.h.

Member Typedef Documentation

using Meter::TempAllowFocus = std::unique_ptr<bool, Resetter>
private

Definition at line 188 of file Meter.h.

Member Enumeration Documentation

Enumerator
AutomaticStereo 
HorizontalStereo 
VerticalStereo 
MixerTrackCluster 
HorizontalStereoCompact 
VerticalStereoCompact 

Definition at line 95 of file Meter.h.

95  {
99  MixerTrackCluster, // Doesn't show menu, icon, or L/R labels, but otherwise like VerticalStereo.
100  HorizontalStereoCompact, // Thinner.
101  VerticalStereoCompact, // Narrower.
102  };

Constructor & Destructor Documentation

Meter::Meter ( AudacityProject project,
wxWindow *  parent,
wxWindowID  id,
bool  isInput,
const wxPoint &  pos = wxDefaultPosition,
const wxSize &  size = wxDefaultSize,
Style  style = HorizontalStereo,
float  fDecayRate = 60.0f 
)

Definition at line 211 of file Meter.cpp.

218 : wxPanelWrapper(parent, id, pos, size, wxTAB_TRAVERSAL | wxNO_BORDER | wxWANTS_CHARS),
219  mProject(project),
220  mQueue(1024),
221  mWidth(size.x),
222  mHeight(size.y),
223  mIsInput(isInput),
224  mDesiredStyle(style),
225  mGradient(true),
226  mDB(true),
228  mDecay(true),
229  mDecayRate(fDecayRate),
230  mClip(true),
233  mT(0),
234  mRate(0),
235  mMonitoring(false),
236  mActive(false),
237  mNumBars(0),
238  mLayoutValid(false),
239  mBitmap{},
240  mIcon{},
241  mAccSilent(false)
242 {
243  // i18n-hint: Noun (the meter is used for playback or record level monitoring)
244  SetName( _("Meter") );
245  // Suppress warnings about the header file
246  wxUnusedVar(SpeakerMenu_xpm);
247  wxUnusedVar(MicMenu_xpm);
248  wxUnusedVar(PrefStyles);
249 
251 
252  mIsFocused = false;
253 
254 #if wxUSE_ACCESSIBILITY
255  SetAccessible(safenew MeterAx(this));
256 #endif
257 
258  // Do this BEFORE UpdatePrefs()!
261  mRuler.SetLabelEdges(true);
262  //mRuler.SetTickColour( wxColour( 0,0,255 ) );
263 
264  UpdatePrefs();
265 
266  wxColour backgroundColour = theTheme.Colour( clrMedium);
267  mBkgndBrush = wxBrush(backgroundColour, wxSOLID);
268 
269  mPeakPeakPen = wxPen(theTheme.Colour( clrMeterPeak), 1, wxSOLID);
270  mDisabledPen = wxPen(theTheme.Colour( clrMeterDisabledPen), 1, wxSOLID);
271 
272  // Register for our preference update event
273  wxTheApp->Connect(EVT_METER_PREFERENCES_CHANGED,
274  wxCommandEventHandler(Meter::OnMeterPrefsUpdated),
275  NULL,
276  this);
277 
278  if (mIsInput) {
279  wxTheApp->Connect(EVT_AUDIOIO_MONITOR,
280  wxCommandEventHandler(Meter::OnAudioIOStatus),
281  NULL,
282  this);
283  wxTheApp->Connect(EVT_AUDIOIO_CAPTURE,
284  wxCommandEventHandler(Meter::OnAudioIOStatus),
285  NULL,
286  this);
287 
288  mPen = wxPen( theTheme.Colour( clrMeterInputPen ), 1, wxSOLID);
289  mBrush = wxBrush( theTheme.Colour( clrMeterInputBrush ), wxSOLID);
290  mRMSBrush = wxBrush( theTheme.Colour( clrMeterInputRMSBrush ), wxSOLID);
291  mClipBrush = wxBrush( theTheme.Colour( clrMeterInputClipBrush ), wxSOLID);
292 // mLightPen = wxPen( theTheme.Colour( clrMeterInputLightPen ), 1, wxSOLID);
293 // mDarkPen = wxPen( theTheme.Colour( clrMeterInputDarkPen ), 1, wxSOLID);
294  }
295  else {
296  // Register for AudioIO events
297  wxTheApp->Connect(EVT_AUDIOIO_PLAYBACK,
298  wxCommandEventHandler(Meter::OnAudioIOStatus),
299  NULL,
300  this);
301 
302  mPen = wxPen( theTheme.Colour( clrMeterOutputPen ), 1, wxSOLID);
303  mBrush = wxBrush( theTheme.Colour( clrMeterOutputBrush ), wxSOLID);
304  mRMSBrush = wxBrush( theTheme.Colour( clrMeterOutputRMSBrush ), wxSOLID);
305  mClipBrush = wxBrush( theTheme.Colour( clrMeterOutputClipBrush ), wxSOLID);
306 // mLightPen = wxPen( theTheme.Colour( clrMeterOutputLightPen ), 1, wxSOLID);
307 // mDarkPen = wxPen( theTheme.Colour( clrMeterOutputDarkPen ), 1, wxSOLID);
308  }
309 
310 // mDisabledBkgndBrush = wxBrush(theTheme.Colour( clrMeterDisabledBrush), wxSOLID);
311  // No longer show a difference in the background colour when not monitoring.
312  // We have the tip instead.
314 
315  // MixerTrackCluster style has no menu, so disallows SetStyle, so never needs icon.
316  if (mStyle != MixerTrackCluster)
317  {
318  if(mIsInput)
319  {
320  //mIcon = NEW wxBitmap(MicMenuNarrow_xpm);
321  mIcon = std::make_unique<wxBitmap>(wxBitmap(theTheme.Bitmap(bmpMic)));
322  }
323  else
324  {
325  //mIcon = NEW wxBitmap(SpeakerMenuNarrow_xpm);
326  mIcon = std::make_unique<wxBitmap>(wxBitmap(theTheme.Bitmap(bmpSpeaker)));
327  }
328  }
329 
330  mTimer.SetOwner(this, OnMeterUpdateID);
331  // TODO: Yikes. Hard coded sample rate.
332  // JKC: I've looked at this, and it's benignish. It just means that the meter
333  // balistics are right for 44KHz and a bit more frisky than they should be
334  // for higher sample rates.
335  Reset(44100.0, true);
336 }
bool mIsInput
Definition: Meter.h:240
double mRate
Definition: Meter.h:253
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:215
bool mActive
Definition: Meter.h:259
int mNumPeakSamplesToClip
Definition: Meter.h:250
void UpdatePrefs()
Definition: Meter.cpp:378
bool mAccSilent
Definition: Meter.h:291
wxBrush mRMSBrush
Definition: Meter.h:277
float mDecayRate
Definition: Meter.h:248
static const wxChar * PrefStyles[]
Definition: Meter.cpp:181
void OnMeterPrefsUpdated(wxCommandEvent &evt)
Definition: Meter.cpp:1925
friend class MeterAx
Definition: Meter.h:293
bool mIsFocused
Definition: Meter.h:285
void OnAudioIOStatus(wxCommandEvent &evt)
Definition: Meter.cpp:1842
Style mStyle
Definition: Meter.h:242
bool mGradient
Definition: Meter.h:244
int mDBRange
Definition: Meter.h:246
bool mClip
Definition: Meter.h:249
wxBrush mDisabledBkgndBrush
Definition: Meter.h:280
#define safenew
Definition: Audacity.h:223
bool mDB
Definition: Meter.h:245
wxPen mPeakPeakPen
Definition: Meter.h:275
wxBitmap & Bitmap(int iIndex)
Definition: Theme.cpp:1233
wxPen mDisabledPen
Definition: Meter.h:274
#define ENV_DB_RANGE
Definition: GUISettings.h:16
bool mDecay
Definition: Meter.h:247
double mT
Definition: Meter.h:252
bool mMonitoring
Definition: Meter.h:257
int mWidth
Definition: Meter.h:234
void SetLabelEdges(bool labelEdges)
Definition: Ruler.cpp:272
int mHeight
Definition: Meter.h:235
void SetFlip(bool flip)
Definition: Ruler.cpp:285
Ruler mRuler
Definition: Meter.h:281
wxPen mPen
Definition: Meter.h:273
AudacityProject * mProject
Definition: Meter.h:230
bool mLayoutValid
Definition: Meter.h:264
std::unique_ptr< wxBitmap > mIcon
Definition: Meter.h:272
Style mDesiredStyle
Definition: Meter.h:243
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
wxBrush mBrush
Definition: Meter.h:276
wxTimer mTimer
Definition: Meter.h:232
MeterUpdateQueue mQueue
Definition: Meter.h:231
std::unique_ptr< wxBitmap > mBitmap
Definition: Meter.h:266
wxBrush mClipBrush
Definition: Meter.h:278
wxBrush mBkgndBrush
Definition: Meter.h:279
void SetFonts(const wxFont &minorFont, const wxFont &majorFont, const wxFont &minorMinorFont)
Definition: Ruler.cpp:303
unsigned mNumBars
Definition: Meter.h:261
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1214
wxFont GetFont() const
Definition: Meter.cpp:1110
double mPeakHoldDuration
Definition: Meter.h:251
void Reset(double sampleRate, bool resetClipping)
This method is thread-safe! Feel free to call from a different thread (like from an audio I/O callbac...
Definition: Meter.cpp:863
Meter::~Meter ( )

Definition at line 343 of file Meter.cpp.

References gAudioIO, AudioIO::GetCaptureMeter(), AudioIO::IsMonitoring(), mIsInput, OnAudioIOStatus(), OnMeterPrefsUpdated(), and AudioIO::StopStream().

344 {
345  if (mIsInput)
346  {
347  // Unregister for AudioIO events
348  wxTheApp->Disconnect(EVT_AUDIOIO_MONITOR,
349  wxCommandEventHandler(Meter::OnAudioIOStatus),
350  NULL,
351  this);
352  wxTheApp->Disconnect(EVT_AUDIOIO_CAPTURE,
353  wxCommandEventHandler(Meter::OnAudioIOStatus),
354  NULL,
355  this);
356  }
357  else
358  {
359  wxTheApp->Disconnect(EVT_AUDIOIO_PLAYBACK,
360  wxCommandEventHandler(Meter::OnAudioIOStatus),
361  NULL,
362  this);
363  }
364 
365  // Unregister for our preference update event
366  wxTheApp->Disconnect(EVT_METER_PREFERENCES_CHANGED,
367  wxCommandEventHandler(Meter::OnMeterPrefsUpdated),
368  NULL,
369  this);
370 
371  // LLL: This prevents a crash during termination if monitoring
372  // is active.
373  if (gAudioIO && gAudioIO->IsMonitoring())
374  if( gAudioIO->GetCaptureMeter() == this )
375  gAudioIO->StopStream();
376 }
bool mIsInput
Definition: Meter.h:240
void StopStream()
Stop recording, playback or input monitoring.
Definition: AudioIO.cpp:2521
void OnMeterPrefsUpdated(wxCommandEvent &evt)
Definition: Meter.cpp:1925
void OnAudioIOStatus(wxCommandEvent &evt)
Definition: Meter.cpp:1842
Meter * GetCaptureMeter()
Definition: AudioIO.cpp:2502
AudioIO * gAudioIO
Definition: AudioIO.cpp:481
bool IsMonitoring()
Returns true if we're monitoring input (but not recording or playing actual audio) ...
Definition: AudioIO.cpp:2922

Member Function Documentation

bool Meter::AcceptsFocus ( ) const
inlineoverride

Definition at line 115 of file Meter.h.

References s_AcceptsFocus.

115 { return s_AcceptsFocus; }
static bool s_AcceptsFocus
Definition: Meter.h:186
bool Meter::AcceptsFocusFromKeyboard ( ) const
inlineoverride

Definition at line 116 of file Meter.h.

116 { return true; }
void Meter::Clear ( )

Definition at line 338 of file Meter.cpp.

References MeterUpdateQueue::Clear(), and mQueue.

Referenced by ControlToolBar::StopPlaying().

339 {
340  mQueue.Clear();
341 }
MeterUpdateQueue mQueue
Definition: Meter.h:231
void Clear()
Definition: Meter.cpp:126
void Meter::DrawMeterBar ( wxDC &  dc,
MeterBar meterBar 
)
private

Definition at line 1550 of file Meter.cpp.

References MeterBar::clipping, AColor::Line(), mBitmap, mBkgndBrush, mClip, mDisabledBkgndBrush, mGradient, mMeterDisabled, mPeakPeakPen, mPen, MeterBar::peak, MeterBar::peakHold, MeterBar::peakPeakHold, MeterBar::r, MeterBar::rClip, MeterBar::rms, and MeterBar::vert.

Referenced by OnPaint().

1551 {
1552  // Cache some metrics
1553  wxCoord x = bar->r.GetLeft();
1554  wxCoord y = bar->r.GetTop();
1555  wxCoord w = bar->r.GetWidth();
1556  wxCoord h = bar->r.GetHeight();
1557  wxCoord ht;
1558  wxCoord wd;
1559 
1560  // Setup for erasing the background
1561  dc.SetPen(*wxTRANSPARENT_PEN);
1563 
1564  if (mGradient)
1565  {
1566  // Map the predrawn bitmap into the source DC
1567  wxMemoryDC srcDC;
1568  srcDC.SelectObject(*mBitmap);
1569 
1570  if (bar->vert)
1571  {
1572  // Copy as much of the predrawn meter bar as is required for the
1573  // current peak.
1574  // (h - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1575  ht = (int)(bar->peak * (h - 1) + 0.5);
1576 
1577  // Blank out the rest
1578  if (h - ht)
1579  {
1580  // ht includes peak value...not really needed but doesn't hurt
1581  dc.DrawRectangle(x, y, w, h - ht);
1582  }
1583 
1584  // Copy as much of the predrawn meter bar as is required for the
1585  // current peak.
1586  // +/-1 to include the peak position
1587  if (ht)
1588  {
1589  dc.Blit(x, y + h - ht - 1, w, ht + 1, &srcDC, x, y + h - ht - 1);
1590  }
1591 
1592  // Draw the "recent" peak hold line using the predrawn meter bar so that
1593  // it will be the same color as the original level.
1594  // (h - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1595  ht = (int)(bar->peakHold * (h - 1) + 0.5);
1596  if (ht > 1)
1597  {
1598  dc.Blit(x, y + h - ht - 1, w, 2, &srcDC, x, y + h - ht - 1);
1599  }
1600 
1601  // Draw the "maximum" peak hold line
1602  // (h - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1603  dc.SetPen(mPeakPeakPen);
1604  ht = (int)(bar->peakPeakHold * (h - 1) + 0.5);
1605  if (ht > 0)
1606  {
1607  AColor::Line(dc, x, y + h - ht - 1, x + w - 1, y + h - ht - 1);
1608  if (ht > 1)
1609  {
1610  AColor::Line(dc, x, y + h - ht, x + w - 1, y + h - ht);
1611  }
1612  }
1613  }
1614  else
1615  {
1616  // Calculate the peak position
1617  // (w - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1618  wd = (int)(bar->peak * (w - 1) + 0.5);
1619 
1620  // Blank out the rest
1621  if (w - wd)
1622  {
1623  // wd includes peak value...not really needed but doesn't hurt
1624  dc.DrawRectangle(x + wd, y, w - wd, h);
1625  }
1626 
1627  // Copy as much of the predrawn meter bar as is required for the
1628  // current peak. But, only blit() if there's something to copy
1629  // to prevent display corruption.
1630  // +1 to include peak position
1631  if (wd)
1632  {
1633  dc.Blit(x, y, wd + 1, h, &srcDC, x, y);
1634  }
1635 
1636  // Draw the "recent" peak hold line using the predrawn meter bar so that
1637  // it will be the same color as the original level.
1638  // -1 to give a 2 pixel width
1639  wd = (int)(bar->peakHold * (w - 1) + 0.5);
1640  if (wd > 1)
1641  {
1642  dc.Blit(x + wd - 1, y, 2, h, &srcDC, x + wd, y);
1643  }
1644 
1645  // Draw the "maximum" peak hold line using a themed color
1646  // (w - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1647  dc.SetPen(mPeakPeakPen);
1648  wd = (int)(bar->peakPeakHold * (w - 1) + 0.5);
1649  if (wd > 0)
1650  {
1651  AColor::Line(dc, x + wd, y, x + wd, y + h - 1);
1652  if (wd > 1)
1653  {
1654  AColor::Line(dc, x + wd - 1, y, x + wd - 1, y + h - 1);
1655  }
1656  }
1657  }
1658 
1659  // No longer need the source DC, so unselect the predrawn bitmap
1660  srcDC.SelectObject(wxNullBitmap);
1661  }
1662  else
1663  {
1664  if (bar->vert)
1665  {
1666  // Calculate the peak position
1667  // (h - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1668  ht = (int)(bar->peak * (h - 1) + 0.5);
1669 
1670  // Blank out the rest
1671  if (h - ht)
1672  {
1673  // ht includes peak value...not really needed but doesn't hurt
1674  dc.DrawRectangle(x, y, w, h - ht);
1675  }
1676 
1677  // Draw the peak level
1678  // +/-1 to include the peak position
1679  dc.SetPen(*wxTRANSPARENT_PEN);
1680  dc.SetBrush(mMeterDisabled ? mDisabledBkgndBrush : mBrush);
1681  if (ht)
1682  {
1683  dc.DrawRectangle(x, y + h - ht - 1, w, ht + 1);
1684  }
1685 
1686  // Draw the "recent" peak hold line
1687  // (h - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1688  dc.SetPen(mPen);
1689  int ht = (int)(bar->peakHold * (h - 1) + 0.5);
1690  if (ht > 0)
1691  {
1692  AColor::Line(dc, x, y + h - ht - 1, x + w - 1, y + h - ht - 1);
1693  if (ht > 1)
1694  {
1695  AColor::Line(dc, x, y + h - ht, x + w - 1, y + h - ht);
1696  }
1697  }
1698 
1699  // Calculate the rms position
1700  // (h - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1701  // +1 to include the rms position
1702  ht = (int)(bar->rms * (h - 1) + 0.5);
1703 
1704  // Draw the RMS level
1705  dc.SetPen(*wxTRANSPARENT_PEN);
1706  dc.SetBrush(mMeterDisabled ? mDisabledBkgndBrush : mRMSBrush);
1707  if (ht)
1708  {
1709  dc.DrawRectangle(x, y + h - ht - 1, w, ht + 1);
1710  }
1711 
1712  // Draw the "maximum" peak hold line
1713  // (h - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1714  dc.SetPen(mPeakPeakPen);
1715  ht = (int)(bar->peakPeakHold * (h - 1) + 0.5);
1716  if (ht > 0)
1717  {
1718  AColor::Line(dc, x, y + h - ht - 1, x + w - 1, y + h - ht - 1);
1719  if (ht > 1)
1720  {
1721  AColor::Line(dc, x, y + h - ht, x + w - 1, y + h - ht);
1722  }
1723  }
1724  }
1725  else
1726  {
1727  // Calculate the peak position
1728  // (w - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1729  wd = (int)(bar->peak * (w - 1) + 0.5);
1730 
1731  // Blank out the rest
1732  if (w - wd)
1733  {
1734  // wd includes peak value...not really needed but doesn't hurt
1735  dc.DrawRectangle(x + wd, y, w - wd, h);
1736  }
1737 
1738  // Draw the peak level
1739  // +1 to include peak position
1740  dc.SetPen(*wxTRANSPARENT_PEN);
1741  dc.SetBrush(mMeterDisabled ? mDisabledBkgndBrush : mBrush);
1742  if (wd)
1743  {
1744  dc.DrawRectangle(x, y, wd + 1, h);
1745  }
1746 
1747  // Draw the "recent" peak hold line
1748  // (w - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1749  dc.SetPen(mPen);
1750  wd = (int)(bar->peakHold * (w - 1) + 0.5);
1751  if (wd > 0)
1752  {
1753  AColor::Line(dc, x + wd, y, x + wd, y + h - 1);
1754  if (wd > 1)
1755  {
1756  AColor::Line(dc, x + wd - 1, y, x + wd - 1, y + h - 1);
1757  }
1758  }
1759 
1760  // Calculate the rms position
1761  // (w - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1762  wd = (int)(bar->rms * (w - 1) + 0.5);
1763 
1764  // Draw the rms level
1765  // +1 to include the rms position
1766  dc.SetPen(*wxTRANSPARENT_PEN);
1767  dc.SetBrush(mMeterDisabled ? mDisabledBkgndBrush : mRMSBrush);
1768  if (wd)
1769  {
1770  dc.DrawRectangle(x, y, wd + 1, h);
1771  }
1772 
1773  // Draw the "maximum" peak hold line using a themed color
1774  // (w - 1) corresponds to the mRuler.SetBounds() in HandleLayout()
1775  dc.SetPen(mPeakPeakPen);
1776  wd = (int)(bar->peakPeakHold * (w - 1) + 0.5);
1777  if (wd > 0)
1778  {
1779  AColor::Line(dc, x + wd, y, x + wd, y + h - 1);
1780  if (wd > 1)
1781  {
1782  AColor::Line(dc, x + wd - 1, y, x + wd - 1, y + h - 1);
1783  }
1784  }
1785  }
1786  }
1787 
1788  // If meter had a clipping indicator, draw or erase it
1789  // LLL: At least I assume that's what "mClip" is supposed to be for as
1790  // it is always "true".
1791  if (mClip)
1792  {
1793  if (bar->clipping)
1794  {
1795  dc.SetBrush(mClipBrush);
1796  }
1797  else
1798  {
1799  dc.SetBrush(mMeterDisabled ? mDisabledBkgndBrush : mBkgndBrush);
1800  }
1801  dc.SetPen(*wxTRANSPARENT_PEN);
1802  wxRect r(bar->rClip.GetX() + 1,
1803  bar->rClip.GetY() + 1,
1804  bar->rClip.GetWidth() - 1,
1805  bar->rClip.GetHeight() - 1);
1806  dc.DrawRectangle(r);
1807  }
1808 }
wxBrush mRMSBrush
Definition: Meter.h:277
bool mGradient
Definition: Meter.h:244
bool mClip
Definition: Meter.h:249
wxBrush mDisabledBkgndBrush
Definition: Meter.h:280
wxPen mPeakPeakPen
Definition: Meter.h:275
long mMeterDisabled
Definition: Meter.h:255
wxPen mPen
Definition: Meter.h:273
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:122
wxBrush mBrush
Definition: Meter.h:276
std::unique_ptr< wxBitmap > mBitmap
Definition: Meter.h:266
wxBrush mClipBrush
Definition: Meter.h:278
wxBrush mBkgndBrush
Definition: Meter.h:279
Style Meter::GetDesiredStyle ( ) const
inline

Definition at line 124 of file Meter.h.

References mDesiredStyle.

124 { return mDesiredStyle; }
Style mDesiredStyle
Definition: Meter.h:243
wxFont Meter::GetFont ( ) const
private

Definition at line 1110 of file Meter.cpp.

Referenced by HandleLayout(), and OnPaint().

1111 {
1112  int fontSize = 10;
1113 #if defined __WXMSW__
1114  fontSize = 8;
1115 #endif
1116 
1117  return wxFont(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
1118 }
float Meter::GetMaxPeak ( ) const

Definition at line 1100 of file Meter.cpp.

References mBar, and mNumBars.

Referenced by audacityAudioCallback().

1101 {
1102  float maxPeak = 0.;
1103 
1104  for(unsigned int j=0; j<mNumBars; j++)
1105  maxPeak = mBar[j].peak > maxPeak ? mBar[j].peak : maxPeak;
1106 
1107  return(maxPeak);
1108 }
MeterBar mBar[kMaxMeterBars]
Definition: Meter.h:262
unsigned mNumBars
Definition: Meter.h:261
Style Meter::GetStyle ( ) const
inline

Definition at line 123 of file Meter.h.

References mStyle.

123 { return mStyle; }
Style mStyle
Definition: Meter.h:242
void Meter::HandleLayout ( wxDC &  dc)
private

Definition at line 1227 of file Meter.cpp.

References _(), AutomaticStereo, MeterBar::b, gap, GetFont(), HorizontalStereo, HorizontalStereoCompact, intmax(), mBar, mDesiredStyle, mHeight, mIcon, mIconRect, mLayoutValid, mLeftSize, mLeftText, mLeftTextPos, mNumBars, mRightSize, mRightText, mRightTextPos, mRuler, mRulerHeight, mRulerWidth, mStyle, mWidth, Ruler::OfflimitsPixels(), MeterBar::r, SetActiveStyle(), SetBarAndClip(), Ruler::SetBounds(), VerticalStereo, and VerticalStereoCompact.

Referenced by OnPaint().

1228 {
1229  // Refresh to reflect any language changes
1230  /* i18n-hint: One-letter abbreviation for Left, in VU Meter */
1231  mLeftText = _("L");
1232  /* i18n-hint: One-letter abbreviation for Right, in VU Meter */
1233  mRightText = _("R");
1234 
1235  dc.SetFont(GetFont());
1236  int iconWidth = 0;
1237  int iconHeight = 0;
1238  int width = mWidth;
1239  int height = mHeight;
1240  int left = 0;
1241  int top = 0;
1242  int barw;
1243  int barh;
1244  int lside;
1245  int rside;
1246 
1247  // MixerTrackCluster has no L/R labels or icon
1248  if (mStyle != MixerTrackCluster)
1249  {
1251  {
1252  SetActiveStyle(width > height ? HorizontalStereo : VerticalStereo);
1253  }
1254 
1256  {
1258  }
1260  {
1262  }
1263 
1264  iconWidth = mIcon->GetWidth();
1265  iconHeight = mIcon->GetHeight();
1266  if (mLeftSize.GetWidth() == 0) // Not yet initialized to dc.
1267  {
1268  dc.GetTextExtent(mLeftText, &mLeftSize.x, &mLeftSize.y);
1269  dc.GetTextExtent(mRightText, &mRightSize.x, &mRightSize.y);
1270  }
1271  }
1272 
1273  int ltxtWidth = mLeftSize.GetWidth();
1274  int ltxtHeight = mLeftSize.GetHeight();
1275  int rtxtWidth = mRightSize.GetWidth();
1276  int rtxtHeight = mRightSize.GetHeight();
1277 
1278  switch (mStyle)
1279  {
1280  default:
1281  wxPrintf(wxT("Style not handled yet!\n"));
1282  break;
1283  case MixerTrackCluster:
1284  // width is now the entire width of the meter canvas
1285  width -= mRulerWidth + left;
1286 
1287  // height is now the entire height of the meter canvas
1288  height -= top + gap;
1289 
1290  // barw is half of the canvas while allowing for a gap between meters
1291  barw = (width - gap) / 2;
1292 
1293  // barh is now the height of the canvas
1294  barh = height;
1295 
1296  // We always have 2 bars
1297  mNumBars = 2;
1298 
1299  // Save dimensions of the left bevel
1300  mBar[0].b = wxRect(left, top, barw, barh);
1301 
1302  // Save dimensions of the right bevel
1303  mBar[1].b = mBar[0].b;
1304  mBar[1].b.SetLeft(mBar[0].b.GetRight() + 1 + gap); // +1 for right edge
1305 
1306  // Set bar and clipping indicator dimensions
1307  SetBarAndClip(0, true);
1308  SetBarAndClip(1, true);
1309 
1310  mRuler.SetBounds(mBar[1].r.GetRight() + 1, // +1 for the bevel
1311  mBar[1].r.GetTop(),
1312  mWidth,
1313  mBar[1].r.GetBottom());
1314  mRuler.OfflimitsPixels(0, 0);
1315  break;
1316  case VerticalStereo:
1317  // Determine required width of each side;
1318  lside = intmax(iconWidth, ltxtWidth);
1319  rside = intmax(mRulerWidth, rtxtWidth);
1320 
1321  // left is now the right edge of the icon or L label
1322  left = lside;
1323 
1324  // Ensure there's a margin between top edge of window and the meters
1325  top = gap;
1326 
1327  // Position the icon
1328  mIconRect.SetX(left - iconWidth);
1329  mIconRect.SetY(top);
1330  mIconRect.SetWidth(iconWidth);
1331  mIconRect.SetHeight(iconHeight);
1332 
1333  // Position the L/R labels
1334  mLeftTextPos = wxPoint(left - ltxtWidth - gap, height - gap - ltxtHeight);
1335  mRightTextPos = wxPoint(width - rside - gap, height - gap - rtxtHeight);
1336 
1337  // left is now left edge of left bar
1338  left += gap;
1339 
1340  // width is now the entire width of the meter canvas
1341  width -= gap + rside + gap + left;
1342 
1343  // height is now the entire height of the meter canvas
1344  height -= top + gap;
1345 
1346  // barw is half of the canvas while allowing for a gap between meters
1347  barw = (width - gap) / 2;
1348 
1349  // barh is now the height of the canvas
1350  barh = height;
1351 
1352  // We always have 2 bars
1353  mNumBars = 2;
1354 
1355  // Save dimensions of the left bevel
1356  mBar[0].b = wxRect(left, top, barw, barh);
1357 
1358  // Save dimensions of the right bevel
1359  mBar[1].b = mBar[0].b;
1360  mBar[1].b.SetLeft(mBar[0].b.GetRight() + 1 + gap); // +1 for right edge
1361 
1362  // Set bar and clipping indicator dimensions
1363  SetBarAndClip(0, true);
1364  SetBarAndClip(1, true);
1365 
1366  mRuler.SetBounds(mBar[1].r.GetRight() + 1, // +1 for the bevel
1367  mBar[1].r.GetTop(),
1368  mWidth,
1369  mBar[1].r.GetBottom());
1370  mRuler.OfflimitsPixels(mRightTextPos.y - gap, mBar[1].r.GetBottom());
1371  break;
1372  case VerticalStereoCompact:
1373  // Ensure there's a margin between top edge of window and the meters
1374  top = gap;
1375 
1376  // Position the icon
1377  mIconRect.SetX((width - iconWidth) / 2);
1378  mIconRect.SetY(top);
1379  mIconRect.SetWidth(iconWidth);
1380  mIconRect.SetHeight(iconHeight);
1381 
1382  // top is now the top of the bar
1383  top += iconHeight + gap;
1384 
1385  // height is now the entire height of the meter canvas
1386  height -= top + gap + ltxtHeight + gap;
1387 
1388  // barw is half of the canvas while allowing for a gap between meters
1389  barw = (width / 2) - gap;
1390 
1391  // barh is now the height of the canvas
1392  barh = height;
1393 
1394  // We always have 2 bars
1395  mNumBars = 2;
1396 
1397  // Save dimensions of the left bevel
1398  mBar[0].b = wxRect(left, top, barw, barh);
1399 
1400  // Save dimensions of the right bevel
1401  mBar[1].b = mBar[0].b;
1402  mBar[1].b.SetLeft(mBar[0].b.GetRight() + 1 + gap); // +1 for right edge
1403 
1404  // Set bar and clipping indicator dimensions
1405  SetBarAndClip(0, true);
1406  SetBarAndClip(1, true);
1407 
1408  // L/R is centered horizontally under each bar
1409  mLeftTextPos = wxPoint(mBar[0].b.GetLeft() + ((mBar[0].b.GetWidth() - ltxtWidth) / 2), top + barh + gap);
1410  mRightTextPos = wxPoint(mBar[1].b.GetLeft() + ((mBar[1].b.GetWidth() - rtxtWidth) / 2), top + barh + gap);
1411 
1413  mBar[1].r.GetTop(),
1414  (mWidth - mRulerWidth) / 2,
1415  mBar[1].r.GetBottom());
1416  mRuler.OfflimitsPixels(0, 0);
1417  break;
1418  case HorizontalStereo:
1419  // Button right next to dragger.
1420  left = 0;
1421 
1422  // Add a gap between bottom of icon and bottom of window
1423  height -= gap;
1424 
1425  // Create icon rectangle
1426  mIconRect.SetX(left);
1427  mIconRect.SetY(height - iconHeight);
1428  mIconRect.SetWidth(iconWidth);
1429  mIconRect.SetHeight(iconHeight);
1430  left = gap;
1431 
1432  // Make sure there's room for icon and gap between the bottom of the meter and icon
1433  height -= iconHeight + gap;
1434 
1435  // L/R is centered vertically and to the left of a each bar
1436  mLeftTextPos = wxPoint(left, (height / 4) - ltxtHeight / 2);
1437  mRightTextPos = wxPoint(left, (height * 3 / 4) - rtxtHeight / 2);
1438 
1439  // Add width of widest of the L/R characters
1440  left += intmax(ltxtWidth, rtxtWidth); //, iconWidth);
1441 
1442  // Add gap between L/R and meter bevel
1443  left += gap;
1444 
1445  // width is now the entire width of the meter canvas
1446  width -= left;
1447 
1448  // barw is now the width of the canvas minus gap between canvas and right window edge
1449  barw = width - gap;
1450 
1451  // barh is half of the canvas while allowing for a gap between meters
1452  barh = (height - gap) / 2;
1453 
1454  // We always have 2 bars
1455  mNumBars = 2;
1456 
1457  // Save dimensions of the top bevel
1458  mBar[0].b = wxRect(left, top, barw, barh);
1459 
1460  // Save dimensions of the bottom bevel
1461  mBar[1].b = mBar[0].b;
1462  mBar[1].b.SetTop(mBar[0].b.GetBottom() + 1 + gap); // +1 for bottom edge
1463 
1464  // Set bar and clipping indicator dimensions
1465  SetBarAndClip(0, false);
1466  SetBarAndClip(1, false);
1467 
1468  mRuler.SetBounds(mBar[1].r.GetLeft(),
1469  mBar[1].r.GetBottom() + 1, // +1 to fit below bevel
1470  mBar[1].r.GetRight(),
1471  mHeight - mBar[1].r.GetBottom() + 1);
1472  mRuler.OfflimitsPixels(0, mIconRect.GetRight() - 4);
1473  break;
1475  // Button right next to dragger.
1476  left = 0;
1477 
1478  // Create icon rectangle
1479  mIconRect.SetX(left);
1480  mIconRect.SetY((height - iconHeight) / 2 -1);
1481  mIconRect.SetWidth(iconWidth);
1482  mIconRect.SetHeight(iconHeight);
1483 
1484  left = gap;
1485  // Add width of icon and gap between icon and L/R
1486  left += iconWidth + gap;
1487 
1488  // L/R is centered vertically and to the left of a each bar
1489  mLeftTextPos = wxPoint(left, (height / 4) - (ltxtHeight / 2));
1490  mRightTextPos = wxPoint(left, (height * 3 / 4) - (ltxtHeight / 2));
1491 
1492  // Add width of widest of the L/R characters and a gap between labels and meter bevel
1493  left += intmax(ltxtWidth, rtxtWidth) + gap;
1494 
1495  // width is now the entire width of the meter canvas
1496  width -= left;
1497 
1498  // barw is now the width of the canvas minus gap between canvas and window edge
1499  barw = width - gap;
1500 
1501  // barh is half of the canvas while allowing for a gap between meters
1502  barh = (height - gap) / 2;
1503 
1504  // We always have 2 bars
1505  mNumBars = 2;
1506 
1507  // Save dimensions of the top bevel
1508  mBar[0].b = wxRect(left, top, barw, barh);
1509 
1510  // Save dimensions of the bottom bevel
1511  // Since the bars butt up against the window's top and bottom edges, we need
1512  // to include an extra pixel in the bottom bar when the window height and
1513  // meter height do not exactly match.
1514  mBar[1].b = mBar[0].b;
1515  mBar[1].b.SetTop(mBar[0].b.GetBottom() + 1 + gap); // +1 for bottom bevel
1516  mBar[1].b.SetHeight(mHeight - mBar[1].b.GetTop() - 1); // +1 for bottom bevel
1517 
1518  // Add clipping indicators - do after setting bar/bevel dimensions above
1519  SetBarAndClip(0, false);
1520  SetBarAndClip(1, false);
1521 
1522  mRuler.SetBounds(mBar[1].r.GetLeft(),
1523  mBar[1].b.GetTop() - (mRulerHeight / 2),
1524  mBar[1].r.GetRight(),
1525  mBar[1].b.GetTop() - (mRulerHeight / 2));
1526  mRuler.OfflimitsPixels(0, 0);
1527  break;
1528  }
1529 
1530  mLayoutValid = true;
1531 }
MeterBar mBar[kMaxMeterBars]
Definition: Meter.h:262
static int intmax(int a, int b)
Definition: Meter.cpp:898
wxSize mLeftSize
Definition: Meter.h:270
int mRulerHeight
Definition: Meter.h:238
wxString mLeftText
Definition: Meter.h:282
wxRect mIconRect
Definition: Meter.h:267
wxRect r
Definition: Meter.h:35
wxString mRightText
Definition: Meter.h:283
wxRect b
Definition: Meter.h:34
void SetBounds(int left, int top, int right, int bottom)
Definition: Ruler.cpp:356
Style mStyle
Definition: Meter.h:242
int mRulerWidth
Definition: Meter.h:237
void SetActiveStyle(Style style)
Definition: Meter.cpp:1143
int mWidth
Definition: Meter.h:234
static const int gap
Definition: Meter.cpp:176
int mHeight
Definition: Meter.h:235
wxPoint mLeftTextPos
Definition: Meter.h:268
Ruler mRuler
Definition: Meter.h:281
bool mLayoutValid
Definition: Meter.h:264
std::unique_ptr< wxBitmap > mIcon
Definition: Meter.h:272
Style mDesiredStyle
Definition: Meter.h:243
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
unsigned mNumBars
Definition: Meter.h:261
void OfflimitsPixels(int start, int end)
Definition: Ruler.cpp:331
wxSize mRightSize
Definition: Meter.h:271
wxFont GetFont() const
Definition: Meter.cpp:1110
wxPoint mRightTextPos
Definition: Meter.h:269
void SetBarAndClip(int iBar, bool vert)
Definition: Meter.cpp:1184
bool Meter::InIcon ( wxMouseEvent *  pEvent = nullptr) const
private

Definition at line 689 of file Meter.cpp.

References mIconRect.

Referenced by OnMouse(), and OnPaint().

690 {
691  auto point = pEvent ? pEvent->GetPosition() : ScreenToClient(::wxGetMousePosition());
692  return mIconRect.Contains(point);
693 }
wxRect mIconRect
Definition: Meter.h:267
bool Meter::IsClipping ( ) const

Definition at line 1135 of file Meter.cpp.

References kMaxMeterBars, and mBar.

1136 {
1137  for (int c = 0; c < kMaxMeterBars; c++)
1138  if (mBar[c].isclipping)
1139  return true;
1140  return false;
1141 }
MeterBar mBar[kMaxMeterBars]
Definition: Meter.h:262
const int kMaxMeterBars
Definition: Meter.h:30
bool Meter::IsMeterDisabled ( ) const

Find out if the level meter is disabled or not.

This method is thread-safe! Feel free to call from a different thread (like from an audio I/O callback).

Definition at line 1810 of file Meter.cpp.

References mMeterDisabled.

Referenced by audacityAudioCallback().

1811 {
1812  return mMeterDisabled != 0;
1813 }
long mMeterDisabled
Definition: Meter.h:255
wxString Meter::Key ( const wxString &  key) const
private

Definition at line 2065 of file Meter.cpp.

References mIsInput, and mStyle.

Referenced by OnPreferences(), and UpdatePrefs().

2066 {
2067  if (mStyle == MixerTrackCluster)
2068  {
2069  return wxT("/Meter/Mixerboard/") + key;
2070  }
2071 
2072  if (mIsInput)
2073  {
2074  return wxT("/Meter/Input/") + key;
2075  }
2076 
2077  return wxT("/Meter/Output/") + key;
2078 }
bool mIsInput
Definition: Meter.h:240
Style mStyle
Definition: Meter.h:242
void Meter::OnAudioIOStatus ( wxCommandEvent &  evt)
private

Definition at line 1842 of file Meter.cpp.

References mActive, mMeterRefreshRate, mMonitoring, mProject, and mTimer.

Referenced by ~Meter().

1843 {
1844  evt.Skip();
1845  AudacityProject *p = (AudacityProject *) evt.GetEventObject();
1846 
1847  mActive = (evt.GetInt() != 0) && (p == mProject);
1848 
1849  if( mActive ){
1850  mTimer.Start(1000 / mMeterRefreshRate);
1851  if (evt.GetEventType() == EVT_AUDIOIO_MONITOR)
1852  mMonitoring = mActive;
1853  } else {
1854  mTimer.Stop();
1855  mMonitoring = false;
1856  }
1857 
1858  // Only refresh is we're the active meter
1859  if (IsShownOnScreen())
1860  Refresh(false);
1861 }
bool mActive
Definition: Meter.h:259
long mMeterRefreshRate
Definition: Meter.h:254
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:161
bool mMonitoring
Definition: Meter.h:257
AudacityProject * mProject
Definition: Meter.h:230
wxTimer mTimer
Definition: Meter.h:232
void Meter::OnContext ( wxContextMenuEvent &  evt)
private

Definition at line 760 of file Meter.cpp.

References mIconRect, mStyle, and ShowMenu().

761 {
762 #if defined(__WXMSW__)
763  if (mHadKeyDown)
764 #endif
765  if (mStyle != MixerTrackCluster) // MixerTrackCluster style has no menu.
766  {
767  ShowMenu(wxPoint(mIconRect.x + 1, mIconRect.y + mIconRect.height + 1));
768  }
769  else
770  {
771  evt.Skip();
772  }
773 
774 #if defined(__WXMSW__)
775  mHadKeyDown = false;
776 #endif
777 }
wxRect mIconRect
Definition: Meter.h:267
Style mStyle
Definition: Meter.h:242
void ShowMenu(const wxPoint &pos)
Definition: Meter.cpp:1888
void Meter::OnErase ( wxEraseEvent &  evt)
private

Definition at line 422 of file Meter.cpp.

423 {
424  // Ignore it to prevent flashing
425 }
void Meter::OnKeyDown ( wxKeyEvent &  evt)
private

Definition at line 779 of file Meter.cpp.

780 {
781  switch (evt.GetKeyCode())
782  {
783  // These are handled in the OnKeyUp handler because, on Windows at least, the
784  // key up event will be passed on to the menu if we show it here. This causes
785  // the default sound to be heard if assigned.
786  //
787  // But, again on Windows, when the user selects a menu item, it is handled by
788  // the menu and the key up event is passed along to our OnKeyUp() handler, so
789  // we have to ignore it, otherwise we'd just show the menu again.
790  case WXK_RETURN:
791  case WXK_NUMPAD_ENTER:
792  case WXK_WINDOWS_MENU:
793  case WXK_MENU:
794 #if defined(__WXMSW__)
795  mHadKeyDown = true;
796 #endif
797  break;
798  case WXK_RIGHT:
799  Navigate(wxNavigationKeyEvent::IsForward);
800  break;
801  case WXK_LEFT:
802  Navigate(wxNavigationKeyEvent::IsBackward);
803  break;
804  case WXK_TAB:
805  if (evt.ShiftDown())
806  Navigate(wxNavigationKeyEvent::IsBackward);
807  else
808  Navigate(wxNavigationKeyEvent::IsForward);
809  break;
810  default:
811  evt.Skip();
812  break;
813  }
814 }
void Meter::OnKeyUp ( wxKeyEvent &  evt)
private

Definition at line 816 of file Meter.cpp.

References mIconRect, mStyle, and ShowMenu().

817 {
818  switch (evt.GetKeyCode())
819  {
820  case WXK_RETURN:
821  case WXK_NUMPAD_ENTER:
822 #if defined(__WXMSW__)
823  if (mHadKeyDown)
824 #endif
825  if (mStyle != MixerTrackCluster) // MixerTrackCluster style has no menu.
826  {
827  ShowMenu(wxPoint(mIconRect.x + 1, mIconRect.y + mIconRect.height + 1));
828  }
829 #if defined(__WXMSW__)
830  mHadKeyDown = false;
831 #endif
832  break;
833  default:
834  evt.Skip();
835  break;
836  }
837 }
wxRect mIconRect
Definition: Meter.h:267
Style mStyle
Definition: Meter.h:242
void ShowMenu(const wxPoint &pos)
Definition: Meter.cpp:1888
void Meter::OnKillFocus ( wxFocusEvent &  evt)
private

Definition at line 845 of file Meter.cpp.

References mIsFocused.

846 {
847  mIsFocused = false;
848  Refresh(false);
849 }
bool mIsFocused
Definition: Meter.h:285
void Meter::OnMeterPrefsUpdated ( wxCommandEvent &  evt)
private

Definition at line 1925 of file Meter.cpp.

References UpdatePrefs().

Referenced by ~Meter().

1926 {
1927  evt.Skip();
1928 
1929  UpdatePrefs();
1930 
1931  Refresh(false);
1932 }
void UpdatePrefs()
Definition: Meter.cpp:378
void Meter::OnMeterUpdate ( wxTimerEvent &  evt)
private

Definition at line 1004 of file Meter.cpp.

References MeterUpdateQueue::Clear(), MeterBar::clipping, MeterUpdateMsg::clipping, DB_TO_LINEAR(), floatMax(), gAudioIO, MeterUpdateQueue::Get(), MeterUpdateMsg::headPeakCount, MeterBar::isclipping, mBar, mDB, mDBRange, mDecay, mDecayRate, mIsInput, mMeterDisabled, mNumBars, mNumPeakSamplesToClip, mPeakHoldDuration, mQueue, mRate, mT, MeterUpdateMsg::numFrames, MeterBar::peak, MeterUpdateMsg::peak, MeterBar::peakHold, MeterBar::peakHoldTime, MeterBar::peakPeakHold, RepaintBarsNow(), MeterBar::rms, MeterUpdateMsg::rms, MeterBar::tailPeakCount, MeterUpdateMsg::tailPeakCount, and ToDB().

1005 {
1006  MeterUpdateMsg msg;
1007  int numChanges = 0;
1008 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
1009  double maxPeak = 0.0;
1010  bool discarded = false;
1011 #endif
1012 
1013  // We shouldn't receive any events if the meter is disabled, but clear it to be safe
1014  if (mMeterDisabled) {
1015  mQueue.Clear();
1016  return;
1017  }
1018 
1019  // There may have been several update messages since the last
1020  // time we got to this function. Catch up to real-time by
1021  // popping them off until there are none left. It is necessary
1022  // to process all of them, otherwise we won't handle peaks and
1023  // peak-hold bars correctly.
1024  while(mQueue.Get(msg)) {
1025  numChanges++;
1026  double deltaT = msg.numFrames / mRate;
1027 
1028  mT += deltaT;
1029  for(unsigned int j=0; j<mNumBars; j++) {
1030  mBar[j].isclipping = false;
1031 
1032  //
1033  if (mDB) {
1034  msg.peak[j] = ToDB(msg.peak[j], mDBRange);
1035  msg.rms[j] = ToDB(msg.rms[j], mDBRange);
1036  }
1037 
1038  if (mDecay) {
1039  if (mDB) {
1040  float decayAmount = mDecayRate * deltaT / mDBRange;
1041  mBar[j].peak = floatMax(msg.peak[j],
1042  mBar[j].peak - decayAmount);
1043  }
1044  else {
1045  double decayAmount = mDecayRate * deltaT;
1046  double decayFactor = DB_TO_LINEAR(-decayAmount);
1047  mBar[j].peak = floatMax(msg.peak[j],
1048  mBar[j].peak * decayFactor);
1049  }
1050  }
1051  else
1052  mBar[j].peak = msg.peak[j];
1053 
1054  // This smooths out the RMS signal
1055  float smooth = pow(0.9, (double)msg.numFrames/1024.0);
1056  mBar[j].rms = mBar[j].rms * smooth + msg.rms[j] * (1.0 - smooth);
1057 
1058  if (mT - mBar[j].peakHoldTime > mPeakHoldDuration ||
1059  mBar[j].peak > mBar[j].peakHold) {
1060  mBar[j].peakHold = mBar[j].peak;
1061  mBar[j].peakHoldTime = mT;
1062  }
1063 
1064  if (mBar[j].peak > mBar[j].peakPeakHold )
1065  mBar[j].peakPeakHold = mBar[j].peak;
1066 
1067  if (msg.clipping[j] ||
1068  mBar[j].tailPeakCount+msg.headPeakCount[j] >=
1070  mBar[j].clipping = true;
1071  mBar[j].isclipping = true;
1072  }
1073 
1074  mBar[j].tailPeakCount = msg.tailPeakCount[j];
1075 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
1076  if (mT > gAudioIO->AILAGetLastDecisionTime()) {
1077  discarded = false;
1078  maxPeak = msg.peak[j] > maxPeak ? msg.peak[j] : maxPeak;
1079  wxPrintf("%[email protected]%f ", msg.peak[j], mT);
1080  }
1081  else {
1082  discarded = true;
1083  wxPrintf("%[email protected]%f discarded\n", msg.peak[j], mT);
1084  }
1085 #endif
1086  }
1087  } // while
1088 
1089  if (numChanges > 0) {
1090  #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
1091  if (gAudioIO->AILAIsActive() && mIsInput && !discarded) {
1092  gAudioIO->AILAProcess(maxPeak);
1093  putchar('\n');
1094  }
1095  #endif
1096  RepaintBarsNow();
1097  }
1098 }
MeterBar mBar[kMaxMeterBars]
Definition: Meter.h:262
bool mIsInput
Definition: Meter.h:240
double mRate
Definition: Meter.h:253
float rms[kMaxMeterBars]
Definition: Meter.h:52
int mNumPeakSamplesToClip
Definition: Meter.h:250
float mDecayRate
Definition: Meter.h:248
static float floatMax(float a, float b)
Definition: Meter.cpp:886
int tailPeakCount[kMaxMeterBars]
Definition: Meter.h:55
int mDBRange
Definition: Meter.h:246
bool clipping[kMaxMeterBars]
Definition: Meter.h:53
static float ToDB(float v, float range)
Definition: Meter.cpp:913
bool Get(MeterUpdateMsg &msg)
Definition: Meter.cpp:155
bool mDB
Definition: Meter.h:245
bool mDecay
Definition: Meter.h:247
float rms
Definition: Meter.h:37
int tailPeakCount
Definition: Meter.h:43
double mT
Definition: Meter.h:252
float peak[kMaxMeterBars]
Definition: Meter.h:51
bool isclipping
Definition: Meter.h:42
double peakHoldTime
Definition: Meter.h:39
long mMeterDisabled
Definition: Meter.h:255
float peakPeakHold
Definition: Meter.h:44
float peakHold
Definition: Meter.h:38
Message used to update the Meter.
Definition: Meter.h:47
int numFrames
Definition: Meter.h:50
AudioIO * gAudioIO
Definition: AudioIO.cpp:481
MeterUpdateQueue mQueue
Definition: Meter.h:231
int headPeakCount[kMaxMeterBars]
Definition: Meter.h:54
bool clipping
Definition: Meter.h:41
float peak
Definition: Meter.h:36
unsigned mNumBars
Definition: Meter.h:261
const double MIN_Threshold_Linear DB_TO_LINEAR(MIN_Threshold_dB)
double mPeakHoldDuration
Definition: Meter.h:251
void RepaintBarsNow()
Definition: Meter.cpp:1533
void Clear()
Definition: Meter.cpp:126
void Meter::OnMonitor ( wxCommandEvent &  evt)
private

Definition at line 1920 of file Meter.cpp.

References StartMonitoring().

1921 {
1922  StartMonitoring();
1923 }
void StartMonitoring()
Definition: Meter.cpp:1815
void Meter::OnMouse ( wxMouseEvent &  evt)
private

Definition at line 695 of file Meter.cpp.

References _(), GetActiveProject(), InIcon(), mActive, mHighlighted, mIconRect, mIsInput, mLayoutValid, mMonitoring, mRate, mStyle, OnMonitorID, OnPreferencesID, Reset(), ShowMenu(), StartMonitoring(), and AudacityProject::TP_DisplayStatusMessage().

696 {
697  bool shouldHighlight = InIcon(&evt);
698  if ((evt.GetEventType() == wxEVT_MOTION || evt.Entering() || evt.Leaving()) &&
699  (mHighlighted != shouldHighlight)) {
700  mHighlighted = shouldHighlight;
701  mLayoutValid = false;
702  Refresh();
703  }
704 
705  if (mStyle == MixerTrackCluster) // MixerTrackCluster style has no menu.
706  return;
707 
708  #if wxUSE_TOOLTIPS // Not available in wxX11
709  if (evt.Leaving()){
711  }
712  else if (evt.Entering()) {
713  // Display the tooltip in the status bar
714  wxToolTip * pTip = this->GetToolTip();
715  if( pTip ) {
716  wxString tipText = pTip->GetTip();
718  }
719  }
720  #endif
721 
722  if (evt.RightDown() ||
723  (evt.ButtonDown() && InIcon(&evt)))
724  {
725  wxMenu menu;
726  // Note: these should be kept in the same order as the enum
727  if (mIsInput) {
728  wxMenuItem *mi;
729  if (mMonitoring)
730  mi = menu.Append(OnMonitorID, _("Stop Monitoring"));
731  else
732  mi = menu.Append(OnMonitorID, _("Start Monitoring"));
733  mi->Enable(!mActive || mMonitoring);
734  }
735 
736  menu.Append(OnPreferencesID, _("Options..."));
737 
738  if (evt.RightDown()) {
739  ShowMenu(evt.GetPosition());
740  }
741  else {
742  ShowMenu(wxPoint(mIconRect.x + 1, mIconRect.y + mIconRect.height + 1));
743  }
744  }
745  else if (evt.LeftDown()) {
746  if (mIsInput) {
747  if (mActive && !mMonitoring) {
748  Reset(mRate, true);
749  }
750  else {
751  StartMonitoring();
752  }
753  }
754  else {
755  Reset(mRate, true);
756  }
757  }
758 }
bool mIsInput
Definition: Meter.h:240
double mRate
Definition: Meter.h:253
void StartMonitoring()
Definition: Meter.cpp:1815
bool mActive
Definition: Meter.h:259
wxRect mIconRect
Definition: Meter.h:267
Style mStyle
Definition: Meter.h:242
bool mHighlighted
Definition: Meter.h:295
bool mMonitoring
Definition: Meter.h:257
bool InIcon(wxMouseEvent *pEvent=nullptr) const
Definition: Meter.cpp:689
void ShowMenu(const wxPoint &pos)
Definition: Meter.cpp:1888
void TP_DisplayStatusMessage(const wxString &msg) override
Definition: Project.cpp:5140
bool mLayoutValid
Definition: Meter.h:264
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:302
void Reset(double sampleRate, bool resetClipping)
This method is thread-safe! Feel free to call from a different thread (like from an audio I/O callbac...
Definition: Meter.cpp:863
void Meter::OnPaint ( wxPaintEvent &  evt)
private

Definition at line 427 of file Meter.cpp.

References _(), MeterBar::b, AColor::Bevel(), ThemeBase::Bitmap(), ThemeBase::Colour(), ThemeBase::ColourDistance(), Ruler::Draw(), AColor::DrawFocus(), DrawMeterBar(), gap, GetFont(), HandleLayout(), HorizontalStereoCompact, InIcon(), mActive, mBar, mBitmap, mBkgndBrush, mClip, mDB, mDBRange, mGradient, mHeight, mIcon, mIconRect, mIsFocused, mIsInput, mLayoutValid, mLeftText, mLeftTextPos, mNumBars, mRightText, mRightTextPos, mRuler, mStyle, mWidth, MeterBar::r, Ruler::SetTickColour(), theTheme, and VerticalStereoCompact.

428 {
429 #if defined(__WXMAC__)
430  auto paintDC = std::make_unique<wxPaintDC>(this);
431 #else
432  std::unique_ptr<wxDC> paintDC{ wxAutoBufferedPaintDCFactory(this) };
433 #endif
434  wxDC & destDC = *paintDC;
435  wxColour clrText = theTheme.Colour( clrTrackPanelText );
436  wxColour clrBoxFill = theTheme.Colour( clrMedium );
437 
438  if (mLayoutValid == false)
439  {
440  // Create a NEW one using current size and select into the DC
441  mBitmap = std::make_unique<wxBitmap>();
442  mBitmap->Create(mWidth, mHeight, destDC);
443  wxMemoryDC dc;
444  dc.SelectObject(*mBitmap);
445 
446  // Go calculate all of the layout metrics
447  HandleLayout(dc);
448 
449  // Start with a clean background
450  // LLL: Should research USE_AQUA_THEME usefulness...
451 //#ifndef USE_AQUA_THEME
452 #ifdef EXPERIMENTAL_THEMING
453  //if( !mMeterDisabled )
454  //{
455  // mBkgndBrush.SetColour( GetParent()->GetBackgroundColour() );
456  //}
457 #endif
458 
459  dc.SetPen(*wxTRANSPARENT_PEN);
460  dc.SetBrush(mBkgndBrush);
461  dc.DrawRectangle(0, 0, mWidth, mHeight);
462 //#endif
463 
464  // MixerTrackCluster style has no icon or L/R labels
465  if (mStyle != MixerTrackCluster)
466  {
467  bool highlight = InIcon();
468  dc.DrawBitmap( theTheme.Bitmap( highlight ?
469  bmpHiliteUpButtonSmall : bmpUpButtonSmall ),
470  mIconRect.GetPosition(), false );
471 
472  dc.DrawBitmap(*mIcon, mIconRect.GetPosition(), true);
473  dc.SetFont(GetFont());
474  dc.SetTextForeground( clrText );
475  dc.SetTextBackground( clrBoxFill );
476  dc.DrawText(mLeftText, mLeftTextPos.x, mLeftTextPos.y);
477  dc.DrawText(mRightText, mRightTextPos.x, mRightTextPos.y);
478  }
479 
480  // Setup the colors for the 3 sections of the meter bars
481  wxColor green(117, 215, 112);
482  wxColor yellow(255, 255, 0);
483  wxColor red(255, 0, 0);
484 
485  // Draw the meter bars at maximum levels
486  for (unsigned int i = 0; i < mNumBars; i++)
487  {
488  // Give it a recessed look
489  AColor::Bevel(dc, false, mBar[i].b);
490 
491  // Draw the clip indicator bevel
492  if (mClip)
493  {
494  AColor::Bevel(dc, false, mBar[i].rClip);
495  }
496 
497  // Cache bar rect
498  wxRect r = mBar[i].r;
499 
500  if (mGradient)
501  {
502  // Calculate the size of the two gradiant segments of the meter
503  double gradw;
504  double gradh;
505  if (mDB)
506  {
507  gradw = (double) r.GetWidth() / mDBRange * 6.0;
508  gradh = (double) r.GetHeight() / mDBRange * 6.0;
509  }
510  else
511  {
512  gradw = (double) r.GetWidth() / 100 * 25;
513  gradh = (double) r.GetHeight() / 100 * 25;
514  }
515 
516  if (mBar[i].vert)
517  {
518  // Draw the "critical" segment (starts at top of meter and works down)
519  r.SetHeight(gradh);
520  dc.GradientFillLinear(r, red, yellow, wxSOUTH);
521 
522  // Draw the "warning" segment
523  r.SetTop(r.GetBottom());
524  dc.GradientFillLinear(r, yellow, green, wxSOUTH);
525 
526  // Draw the "safe" segment
527  r.SetTop(r.GetBottom());
528  r.SetBottom(mBar[i].r.GetBottom());
529  dc.SetPen(*wxTRANSPARENT_PEN);
530  dc.SetBrush(green);
531  dc.DrawRectangle(r);
532  }
533  else
534  {
535  // Draw the "safe" segment
536  r.SetWidth(r.GetWidth() - (int) (gradw + gradw + 0.5));
537  dc.SetPen(*wxTRANSPARENT_PEN);
538  dc.SetBrush(green);
539  dc.DrawRectangle(r);
540 
541  // Draw the "warning" segment
542  r.SetLeft(r.GetRight() + 1);
543  r.SetWidth(floor(gradw));
544  dc.GradientFillLinear(r, green, yellow);
545 
546  // Draw the "critical" segment
547  r.SetLeft(r.GetRight() + 1);
548  r.SetRight(mBar[i].r.GetRight());
549  dc.GradientFillLinear(r, yellow, red);
550  }
551 #ifdef EXPERIMENTAL_METER_LED_STYLE
552  if (!mBar[i].vert)
553  {
554  wxRect r = mBar[i].r;
555  wxPen BackgroundPen;
556  BackgroundPen.SetColour( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE) );
557  dc.SetPen( BackgroundPen );
558  int i;
559  for(i=0;i<r.width;i++)
560  {
561  // 2 pixel spacing between the LEDs
562  if( (i%7)<2 ){
563  dc.DrawLine( i+r.x, r.y, i+r.x, r.y+r.height );
564  } else {
565  // The LEDs have triangular ends.
566  // This code shapes the ends.
567  int j = abs( (i%7)-4);
568  dc.DrawLine( i+r.x, r.y, i+r.x, r.y+j +1);
569  dc.DrawLine( i+r.x, r.y+r.height-j, i+r.x, r.y+r.height );
570  }
571  }
572  }
573 #endif
574  }
575  }
576  mRuler.SetTickColour( clrText );
577  dc.SetTextForeground( clrText );
578  // Draw the ruler
579 #ifndef EXPERIMENTAL_DA
580  mRuler.Draw(dc);
581 #endif
582 
583  // Bitmap created...unselect
584  dc.SelectObject(wxNullBitmap);
585  }
586 
587  // Copy predrawn bitmap to the dest DC
588  destDC.DrawBitmap(*mBitmap, 0, 0);
589 
590  // Go draw the meter bars, Left & Right channels using current levels
591  for (unsigned int i = 0; i < mNumBars; i++)
592  {
593  DrawMeterBar(destDC, &mBar[i]);
594  }
595 
596  destDC.SetTextForeground( clrText );
597 
598 #ifndef EXPERIMENTAL_DA
599  // We can have numbers over the bars, in which case we have to draw them each time.
601  {
602  mRuler.SetTickColour( clrText );
603  // If the text colour is too similar to the meter colour, then we need a background
604  // for the text. We require a total of at least one full-scale RGB difference.
605  int d = theTheme.ColourDistance( clrText, theTheme.Colour( clrMeterOutputRMSBrush ) );
606  if( d < 256 )
607  {
608  destDC.SetBackgroundMode( wxSOLID );
609  destDC.SetTextBackground( clrBoxFill );
610  }
611  mRuler.Draw(destDC);
612  }
613 #endif
614 
615  // Let the user know they can click to start monitoring
616  if( mIsInput && !mActive )
617  {
618  destDC.SetFont( GetFont() );
619  wxArrayString texts;
620 
621  texts.Add( _("Click to Start Monitoring") );
622  texts.Add( _("Click for Monitoring") );
623  texts.Add( _("Click to Start") );
624  texts.Add( _("Click") );
625 
626  for( size_t i = 0, cnt = texts.GetCount(); i < cnt; i++ )
627  {
628  wxString Text = wxT(" ") + texts[i] + wxT(" ");
629  wxSize Siz = destDC.GetTextExtent( Text );
630  Siz.SetWidth( Siz.GetWidth() + gap );
631  Siz.SetHeight( Siz.GetHeight() + gap );
632 
633  if( mBar[0].vert)
634  {
635  if( Siz.GetWidth() < mBar[0].r.GetHeight() )
636  {
637  wxRect r( mBar[1].b.GetLeft() - (int) (Siz.GetHeight() / 2.0) + 0.5,
638  mBar[0].r.GetTop() + (int) ((mBar[0].r.GetHeight() - Siz.GetWidth()) / 2.0) + 0.5,
639  Siz.GetHeight(),
640  Siz.GetWidth() );
641 
642  destDC.SetBrush( wxBrush( clrBoxFill ) );
643  destDC.SetPen( *wxWHITE_PEN );
644  destDC.DrawRectangle( r );
645  destDC.SetBackgroundMode( wxTRANSPARENT );
646  r.SetTop( r.GetBottom() + (gap / 2) );
647  destDC.SetTextForeground( clrText );
648  destDC.DrawRotatedText( Text, r.GetPosition(), 90 );
649  break;
650  }
651  }
652  else
653  {
654  if( Siz.GetWidth() < mBar[0].r.GetWidth() )
655  {
656  wxRect r( mBar[0].r.GetLeft() + (int) ((mBar[0].r.GetWidth() - Siz.GetWidth()) / 2.0) + 0.5,
657  mBar[1].b.GetTop() - (int) (Siz.GetHeight() / 2.0) + 0.5,
658  Siz.GetWidth(),
659  Siz.GetHeight() );
660 
661  destDC.SetBrush( wxBrush( clrBoxFill ) );
662  destDC.SetPen( *wxWHITE_PEN );
663  destDC.DrawRectangle( r );
664  destDC.SetBackgroundMode( wxTRANSPARENT );
665  r.SetLeft( r.GetLeft() + (gap / 2) );
666  r.SetTop( r.GetTop() + (gap / 2));
667  destDC.SetTextForeground( clrText );
668  destDC.DrawText( Text, r.GetPosition() );
669  break;
670  }
671  }
672  }
673  }
674 
675  if (mIsFocused)
676  {
677  wxRect r = mIconRect;
678  AColor::DrawFocus(destDC, r.Inflate(1, 1));
679  }
680 }
MeterBar mBar[kMaxMeterBars]
Definition: Meter.h:262
bool mIsInput
Definition: Meter.h:240
void Draw(wxDC &dc)
Definition: Ruler.cpp:1307
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:215
int ColourDistance(wxColour &From, wxColour &To)
Definition: Theme.cpp:372
bool mActive
Definition: Meter.h:259
wxString mLeftText
Definition: Meter.h:282
wxRect mIconRect
Definition: Meter.h:267
wxRect r
Definition: Meter.h:35
wxString mRightText
Definition: Meter.h:283
wxRect b
Definition: Meter.h:34
bool mIsFocused
Definition: Meter.h:285
Style mStyle
Definition: Meter.h:242
void HandleLayout(wxDC &dc)
Definition: Meter.cpp:1227
bool mGradient
Definition: Meter.h:244
int mDBRange
Definition: Meter.h:246
static void DrawFocus(wxDC &dc, wxRect &r)
Definition: AColor.cpp:171
bool mClip
Definition: Meter.h:249
bool mDB
Definition: Meter.h:245
wxBitmap & Bitmap(int iIndex)
Definition: Theme.cpp:1233
static void Bevel(wxDC &dc, bool up, const wxRect &r)
Definition: AColor.cpp:202
int mWidth
Definition: Meter.h:234
static const int gap
Definition: Meter.cpp:176
int mHeight
Definition: Meter.h:235
wxPoint mLeftTextPos
Definition: Meter.h:268
Ruler mRuler
Definition: Meter.h:281
bool InIcon(wxMouseEvent *pEvent=nullptr) const
Definition: Meter.cpp:689
bool mLayoutValid
Definition: Meter.h:264
std::unique_ptr< wxBitmap > mIcon
Definition: Meter.h:272
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
void SetTickColour(const wxColour &colour)
Definition: Ruler.h:150
std::unique_ptr< wxBitmap > mBitmap
Definition: Meter.h:266
wxBrush mBkgndBrush
Definition: Meter.h:279
unsigned mNumBars
Definition: Meter.h:261
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1214
void DrawMeterBar(wxDC &dc, MeterBar *meterBar)
Definition: Meter.cpp:1550
wxFont GetFont() const
Definition: Meter.cpp:1110
wxPoint mRightTextPos
Definition: Meter.h:269
void Meter::OnPreferences ( wxCommandEvent &  evt)
private

Definition at line 1934 of file Meter.cpp.

References _(), ShuttleGuiBase::AddFixedText(), ShuttleGuiBase::AddRadioButton(), ShuttleGuiBase::AddRadioButtonToGroup(), ShuttleGui::AddStandardButtons(), ShuttleGuiBase::AddTextBox(), AutomaticStereo, eIsCreating, ShuttleGuiBase::EndHorizontalLay(), ShuttleGuiBase::EndStatic(), ShuttleGuiBase::EndVerticalLay(), GetActiveProject(), gPrefs, HorizontalStereo, Key(), MAX_REFRESH_RATE, mDB, mDesiredStyle, mGradient, MIN_REFRESH_RATE, mIsInput, mMeterRefreshRate, ShuttleGuiBase::StartHorizontalLay(), ShuttleGuiBase::StartStatic(), ShuttleGuiBase::StartVerticalLay(), and VerticalStereo.

1935 {
1936  wxTextCtrl *rate;
1937  wxRadioButton *gradient;
1938  wxRadioButton *rms;
1939  wxRadioButton *db;
1940  wxRadioButton *linear;
1941  wxRadioButton *automatic;
1942  wxRadioButton *horizontal;
1943  wxRadioButton *vertical;
1944  int meterRefreshRate = mMeterRefreshRate;
1945 
1946  wxString title(mIsInput ? _("Recording Meter Options") : _("Playback Meter Options"));
1947 
1948  // Dialog is a child of the project, rather than of the toolbar.
1949  // This determines where it pops up.
1950 
1951  wxDialogWrapper dlg(GetActiveProject(), wxID_ANY, title);
1952  dlg.SetName(dlg.GetTitle());
1953  ShuttleGui S(&dlg, eIsCreating);
1954  S.StartVerticalLay();
1955  {
1956  S.StartStatic(_("Refresh Rate"), 0);
1957  {
1958  S.AddFixedText(_("Higher refresh rates make the meter show more frequent\nchanges. A rate of 30 per second or less should prevent\nthe meter affecting audio quality on slower machines."));
1959  S.StartHorizontalLay();
1960  {
1961  rate = S.AddTextBox(_("Meter refresh rate per second [1-100]: "),
1962  wxString::Format(wxT("%d"), meterRefreshRate),
1963  10);
1964  rate->SetName(_("Meter refresh rate per second [1-100]"));
1965  IntegerValidator<long> vld(&mMeterRefreshRate);
1966 
1967  vld.SetRange(MIN_REFRESH_RATE, MAX_REFRESH_RATE);
1968  rate->SetValidator(vld);
1969  }
1970  S.EndHorizontalLay();
1971  }
1972  S.EndStatic();
1973 
1974  S.StartHorizontalLay();
1975  {
1976  S.StartStatic(_("Meter Style"), 0);
1977  {
1978  S.StartVerticalLay();
1979  {
1980  gradient = S.AddRadioButton(_("Gradient"));
1981  gradient->SetName(_("Gradient"));
1982  gradient->SetValue(mGradient);
1983 
1984  rms = S.AddRadioButtonToGroup(_("RMS"));
1985  rms->SetName(_("RMS"));
1986  rms->SetValue(!mGradient);
1987  }
1988  S.EndVerticalLay();
1989  }
1990  S.EndStatic();
1991 
1992  S.StartStatic(_("Meter Type"), 0);
1993  {
1994  S.StartVerticalLay();
1995  {
1996  db = S.AddRadioButton(_("dB"));
1997  db->SetName(_("dB"));
1998  db->SetValue(mDB);
1999 
2000  linear = S.AddRadioButtonToGroup(_("Linear"));
2001  linear->SetName(_("Linear"));
2002  linear->SetValue(!mDB);
2003  }
2004  S.EndVerticalLay();
2005  }
2006  S.EndStatic();
2007 
2008  S.StartStatic(_("Orientation"), 1);
2009  {
2010  S.StartVerticalLay();
2011  {
2012  automatic = S.AddRadioButton(_("Automatic"));
2013  automatic->SetName(_("Automatic"));
2014  automatic->SetValue(mDesiredStyle == AutomaticStereo);
2015 
2016  horizontal = S.AddRadioButtonToGroup(_("Horizontal"));
2017  horizontal->SetName(_("Horizontal"));
2018  horizontal->SetValue(mDesiredStyle == HorizontalStereo);
2019 
2020  vertical = S.AddRadioButtonToGroup(_("Vertical"));
2021  vertical->SetName(_("Vertical"));
2022  vertical->SetValue(mDesiredStyle == VerticalStereo);
2023  }
2024  S.EndVerticalLay();
2025  }
2026  S.EndStatic();
2027  }
2028  S.EndHorizontalLay();
2029  S.AddStandardButtons();
2030  }
2031  S.EndVerticalLay();
2032  dlg.Layout();
2033  dlg.Fit();
2034 
2035  dlg.CenterOnParent();
2036 
2037  if (dlg.ShowModal() == wxID_OK)
2038  {
2039  wxArrayString style;
2040  style.Add(wxT("AutomaticStereo"));
2041  style.Add(wxT("HorizontalStereo"));
2042  style.Add(wxT("VerticalStereo"));
2043 
2044  int s = 0;
2045  s = automatic->GetValue() ? 0 : s;
2046  s = horizontal->GetValue() ? 1 : s;
2047  s = vertical->GetValue() ? 2 : s;
2048 
2049  gPrefs->Write(Key(wxT("Style")), style[s]);
2050  gPrefs->Write(Key(wxT("Bars")), gradient->GetValue() ? wxT("Gradient") : wxT("RMS"));
2051  gPrefs->Write(Key(wxT("Type")), db->GetValue() ? wxT("dB") : wxT("Linear"));
2052  gPrefs->Write(Key(wxT("RefreshRate")), rate->GetValue());
2053 
2054  gPrefs->Flush();
2055 
2056  // Currently, there are 2 playback meters and 2 record meters and any number of
2057  // mixerboard meters, so we have to send out an preferences updated message to
2058  // ensure they all update themselves.
2059  wxCommandEvent e(EVT_METER_PREFERENCES_CHANGED);
2060  e.SetEventObject(this);
2061  GetParent()->GetEventHandler()->ProcessEvent(e);
2062  }
2063 }
bool mIsInput
Definition: Meter.h:240
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:366
long mMeterRefreshRate
Definition: Meter.h:254
bool mGradient
Definition: Meter.h:244
static const long MIN_REFRESH_RATE
Definition: Meter.cpp:76
bool mDB
Definition: Meter.h:245
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
Style mDesiredStyle
Definition: Meter.h:243
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:302
wxString Key(const wxString &key) const
Definition: Meter.cpp:2065
static const long MAX_REFRESH_RATE
Definition: Meter.cpp:77
void Meter::OnSetFocus ( wxFocusEvent &  evt)
private

Definition at line 839 of file Meter.cpp.

References mIsFocused.

840 {
841  mIsFocused = true;
842  Refresh(false);
843 }
bool mIsFocused
Definition: Meter.h:285
void Meter::OnSize ( wxSizeEvent &  evt)
private

Definition at line 682 of file Meter.cpp.

References mHeight, mLayoutValid, and mWidth.

683 {
684  GetClientSize(&mWidth, &mHeight);
685 
686  mLayoutValid = false;
687 }
int mWidth
Definition: Meter.h:234
int mHeight
Definition: Meter.h:235
bool mLayoutValid
Definition: Meter.h:264
void Meter::RepaintBarsNow ( )
private

Definition at line 1533 of file Meter.cpp.

References mLayoutValid, and mNumBars.

Referenced by OnMeterUpdate().

1534 {
1535  if (mLayoutValid)
1536  {
1537  // Invalidate the bars so they get redrawn
1538  for (unsigned int i = 0; i < mNumBars; i++)
1539  {
1540  Refresh(false);
1541  }
1542 
1543  // Immediate redraw (using wxPaintDC)
1544  Update();
1545 
1546  return;
1547  }
1548 }
bool mLayoutValid
Definition: Meter.h:264
unsigned mNumBars
Definition: Meter.h:261
void Meter::Reset ( double  sampleRate,
bool  resetClipping 
)

This method is thread-safe! Feel free to call from a different thread (like from an audio I/O callback).

Definition at line 863 of file Meter.cpp.

References MeterUpdateQueue::Clear(), kMaxMeterBars, mBar, mLayoutValid, mMeterRefreshRate, mQueue, mRate, mT, mTimer, and ResetBar().

Referenced by OnMouse(), MixerTrackCluster::ResetMeter(), AudioIO::SetCaptureMeter(), AudioIO::SetMeters(), AudioIO::SetPlaybackMeter(), AudioIO::StopStream(), and UpdatePrefs().

864 {
865  mT = 0;
866  mRate = sampleRate;
867  for (int j = 0; j < kMaxMeterBars; j++)
868  {
869  ResetBar(&mBar[j], resetClipping);
870  }
871 
872  // wxTimers seem to be a little unreliable - sometimes they stop for
873  // no good reason, so this "primes" it every now and then...
874  mTimer.Stop();
875 
876  // While it's stopped, empty the queue
877  mQueue.Clear();
878 
879  mLayoutValid = false;
880 
881  mTimer.Start(1000 / mMeterRefreshRate);
882 
883  Refresh(false);
884 }
MeterBar mBar[kMaxMeterBars]
Definition: Meter.h:262
double mRate
Definition: Meter.h:253
void ResetBar(MeterBar *bar, bool resetClipping)
Definition: Meter.cpp:1120
long mMeterRefreshRate
Definition: Meter.h:254
double mT
Definition: Meter.h:252
bool mLayoutValid
Definition: Meter.h:264
const int kMaxMeterBars
Definition: Meter.h:30
wxTimer mTimer
Definition: Meter.h:232
MeterUpdateQueue mQueue
Definition: Meter.h:231
void Clear()
Definition: Meter.cpp:126
void Meter::ResetBar ( MeterBar bar,
bool  resetClipping 
)
private

Definition at line 1120 of file Meter.cpp.

References MeterBar::clipping, MeterBar::isclipping, MeterBar::peak, MeterBar::peakHold, MeterBar::peakHoldTime, MeterBar::peakPeakHold, MeterBar::rms, and MeterBar::tailPeakCount.

Referenced by Reset().

1121 {
1122  b->peak = 0.0;
1123  b->rms = 0.0;
1124  b->peakHold = 0.0;
1125  b->peakHoldTime = 0.0;
1126  if (resetClipping)
1127  {
1128  b->clipping = false;
1129  b->peakPeakHold = 0.0;
1130  }
1131  b->isclipping = false;
1132  b->tailPeakCount = 0;
1133 }
void Meter::RestoreState ( const State state)

Definition at line 1871 of file Meter.cpp.

References Meter::State::mActive, mActive, mMeterRefreshRate, Meter::State::mMonitoring, mMonitoring, Meter::State::mSaved, and mTimer.

Referenced by MeterToolBar::ReCreateButtons().

1872 {
1873  if (!state.mSaved)
1874  return;
1875 
1876  mMonitoring = state.mMonitoring;
1877  mActive = state.mActive;
1878  //wxLogDebug("Restore state for %p, is %i", this, mActive );
1879 
1880  if (mActive)
1881  mTimer.Start(1000 / mMeterRefreshRate);
1882 }
bool mActive
Definition: Meter.h:259
long mMeterRefreshRate
Definition: Meter.h:254
bool mMonitoring
Definition: Meter.h:257
wxTimer mTimer
Definition: Meter.h:232
auto Meter::SaveState ( )

Definition at line 1866 of file Meter.cpp.

Referenced by MeterToolBar::ReCreateButtons().

1867 {
1868  return { true, mMonitoring, mActive };
1869 }
bool mActive
Definition: Meter.h:259
bool mMonitoring
Definition: Meter.h:257
void Meter::SetActiveStyle ( Style  style)
private

Definition at line 1143 of file Meter.cpp.

References Ruler::GetMaxSize(), HorizontalStereo, HorizontalStereoCompact, Ruler::LinearDBFormat, mDB, mDBRange, mRuler, mRulerHeight, mRulerWidth, mStyle, Ruler::RealFormat, Ruler::SetBounds(), Ruler::SetFormat(), Ruler::SetOrientation(), and Ruler::SetRange().

Referenced by HandleLayout(), SetStyle(), and UpdatePrefs().

1144 {
1145  mStyle = newStyle;
1146 
1147  // Set dummy ruler bounds so width/height can be retrieved
1148  // NOTE: Make sure the Right and Bottom values are large enough to
1149  // ensure full width/height of digits get calculated.
1150  mRuler.SetBounds(0, 0, 500, 500);
1151 
1152  if (mDB)
1153  {
1156  {
1157  mRuler.SetOrientation(wxHORIZONTAL);
1158  mRuler.SetRange(-mDBRange, 0);
1159  }
1160  else
1161  {
1162  mRuler.SetOrientation(wxVERTICAL);
1163  mRuler.SetRange(0, -mDBRange);
1164  }
1165  }
1166  else
1167  {
1170  {
1171  mRuler.SetOrientation(wxHORIZONTAL);
1172  mRuler.SetRange(0, 1);
1173  }
1174  else
1175  {
1176  mRuler.SetOrientation(wxVERTICAL);
1177  mRuler.SetRange(1, 0);
1178  }
1179  }
1180 
1182 }
int mRulerHeight
Definition: Meter.h:238
void SetBounds(int left, int top, int right, int bottom)
Definition: Ruler.cpp:356
void GetMaxSize(wxCoord *width, wxCoord *height)
Definition: Ruler.cpp:1533
Style mStyle
Definition: Meter.h:242
int mDBRange
Definition: Meter.h:246
void SetOrientation(int orient)
Definition: Ruler.cpp:220
bool mDB
Definition: Meter.h:245
int mRulerWidth
Definition: Meter.h:237
Ruler mRuler
Definition: Meter.h:281
void SetFormat(RulerFormat format)
Definition: Ruler.cpp:186
void SetRange(double min, double max)
Definition: Ruler.cpp:234
void Meter::SetBarAndClip ( int  iBar,
bool  vert 
)
private

Definition at line 1184 of file Meter.cpp.

References MeterBar::b, gap, mBar, mClip, MeterBar::r, MeterBar::rClip, and MeterBar::vert.

Referenced by HandleLayout().

1185 {
1186  // Save the orientation
1187  mBar[iBar].vert = vert;
1188 
1189  // Create the bar rectangle and educe to fit inside the bevel
1190  mBar[iBar].r = mBar[iBar].b;
1191  mBar[iBar].r.x += 1;
1192  mBar[iBar].r.width -= 1;
1193  mBar[iBar].r.y += 1;
1194  mBar[iBar].r.height -= 1;
1195 
1196  if (vert)
1197  {
1198  if (mClip)
1199  {
1200  // Create the clip rectangle
1201  mBar[iBar].rClip = mBar[iBar].b;
1202  mBar[iBar].rClip.height = 3;
1203 
1204  // Make room for the clipping indicator
1205  mBar[iBar].b.y += 3 + gap;
1206  mBar[iBar].b.height -= 3 + gap;
1207  mBar[iBar].r.y += 3 + gap;
1208  mBar[iBar].r.height -= 3 + gap;
1209  }
1210  }
1211  else
1212  {
1213  if (mClip)
1214  {
1215  // Make room for the clipping indicator
1216  mBar[iBar].b.width -= 4;
1217  mBar[iBar].r.width -= 4;
1218 
1219  // Create the indicator rectangle
1220  mBar[iBar].rClip = mBar[iBar].b;
1221  mBar[iBar].rClip.x = mBar[iBar].b.GetRight() + 1 + gap; // +1 for bevel
1222  mBar[iBar].rClip.width = 3;
1223  }
1224  }
1225 }
MeterBar mBar[kMaxMeterBars]
Definition: Meter.h:262
wxRect r
Definition: Meter.h:35
wxRect b
Definition: Meter.h:34
bool mClip
Definition: Meter.h:249
bool vert
Definition: Meter.h:33
wxRect rClip
Definition: Meter.h:40
static const int gap
Definition: Meter.cpp:176
void Meter::SetFocusFromKbd ( )
override

Definition at line 2090 of file Meter.cpp.

References TemporarilyAllowFocus().

2091 {
2092  auto temp = TemporarilyAllowFocus();
2093  SetFocus();
2094 }
static TempAllowFocus TemporarilyAllowFocus()
Definition: Meter.cpp:2082
void Meter::SetStyle ( Style  newStyle)

Definition at line 851 of file Meter.cpp.

References AutomaticStereo, mDesiredStyle, mLayoutValid, mStyle, and SetActiveStyle().

852 {
853  if (mStyle != newStyle && mDesiredStyle == AutomaticStereo)
854  {
855  SetActiveStyle(newStyle);
856 
857  mLayoutValid = false;
858 
859  Refresh(false);
860  }
861 }
Style mStyle
Definition: Meter.h:242
void SetActiveStyle(Style style)
Definition: Meter.cpp:1143
bool mLayoutValid
Definition: Meter.h:264
Style mDesiredStyle
Definition: Meter.h:243
void Meter::ShowMenu ( const wxPoint &  pos)
private

Definition at line 1888 of file Meter.cpp.

References _(), mAccSilent, mActive, mIsInput, mMonitoring, OnMonitorID, and OnPreferencesID.

Referenced by OnContext(), OnKeyUp(), and OnMouse().

1889 {
1890  wxMenu menu;
1891  // Note: these should be kept in the same order as the enum
1892  if (mIsInput) {
1893  wxMenuItem *mi;
1894  if (mMonitoring)
1895  mi = menu.Append(OnMonitorID, _("Stop Monitoring"));
1896  else
1897  mi = menu.Append(OnMonitorID, _("Start Monitoring"));
1898  mi->Enable(!mActive || mMonitoring);
1899  }
1900 
1901  menu.Append(OnPreferencesID, _("Options..."));
1902 
1903  mAccSilent = true; // temporarily make screen readers say (close to) nothing on focus events
1904 
1905  PopupMenu(&menu, pos);
1906 
1907  /* if stop/start monitoring was chosen in the menu, then by this point
1908  OnMonitoring has been called and variables which affect the accessibility
1909  name have been updated so it's now ok for screen readers to read the name of
1910  the button */
1911  mAccSilent = false;
1912 #if wxUSE_ACCESSIBILITY
1913  GetAccessible()->NotifyEvent(wxACC_EVENT_OBJECT_FOCUS,
1914  this,
1915  wxOBJID_CLIENT,
1916  wxACC_SELF);
1917 #endif
1918 }
bool mIsInput
Definition: Meter.h:240
bool mActive
Definition: Meter.h:259
bool mAccSilent
Definition: Meter.h:291
bool mMonitoring
Definition: Meter.h:257
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
void Meter::StartMonitoring ( )

Definition at line 1815 of file Meter.cpp.

References gAudioIO, GetActiveProject(), AudacityProject::GetRate(), AudioIO::IsBusy(), AudioIO::IsMonitoring(), mLayoutValid, mMonitoring, AudioIO::StartMonitoring(), and AudioIO::StopStream().

Referenced by OnMonitor(), and OnMouse().

1816 {
1817  bool start = !mMonitoring;
1818 
1819  if (gAudioIO->IsMonitoring()){
1820  gAudioIO->StopStream();
1821  }
1822 
1823  if (start && !gAudioIO->IsBusy()){
1825  if (p){
1827  }
1828 
1829  mLayoutValid = false;
1830 
1831  Refresh(false);
1832  }
1833 }
void StopStream()
Stop recording, playback or input monitoring.
Definition: AudioIO.cpp:2521
bool IsBusy()
Returns true if audio i/o is busy starting, stopping, playing, or recording.
Definition: AudioIO.cpp:2890
void StartMonitoring(double sampleRate)
Start up Portaudio for capture and recording as needed for input monitoring and software playthrough ...
Definition: AudioIO.cpp:1818
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:161
bool mMonitoring
Definition: Meter.h:257
bool mLayoutValid
Definition: Meter.h:264
AudioIO * gAudioIO
Definition: AudioIO.cpp:481
bool IsMonitoring()
Returns true if we're monitoring input (but not recording or playing actual audio) ...
Definition: AudioIO.cpp:2922
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:302
double GetRate() const
Definition: Project.h:184
void Meter::StopMonitoring ( )

Definition at line 1835 of file Meter.cpp.

References gAudioIO, AudioIO::IsMonitoring(), mMonitoring, and AudioIO::StopStream().

1835  {
1836  mMonitoring = false;
1837  if (gAudioIO->IsMonitoring()){
1838  gAudioIO->StopStream();
1839  }
1840 }
void StopStream()
Stop recording, playback or input monitoring.
Definition: AudioIO.cpp:2521
bool mMonitoring
Definition: Meter.h:257
AudioIO * gAudioIO
Definition: AudioIO.cpp:481
bool IsMonitoring()
Returns true if we're monitoring input (but not recording or playing actual audio) ...
Definition: AudioIO.cpp:2922
auto Meter::TemporarilyAllowFocus ( )
static

Definition at line 2082 of file Meter.cpp.

Referenced by AudacityProject::NextOrPrevFrame(), ToolManager::RestoreFocus(), and SetFocusFromKbd().

2082  {
2083  s_AcceptsFocus = true;
2084  return TempAllowFocus{ &s_AcceptsFocus };
2085 }
std::unique_ptr< bool, Resetter > TempAllowFocus
Definition: Meter.h:188
static bool s_AcceptsFocus
Definition: Meter.h:186
void Meter::UpdateDisplay ( unsigned  numChannels,
int  numFrames,
float *  sampleData 
)

Update the meters with a block of audio data.

Process the supplied block of audio data, extracting the peak and RMS levels to send to the meter. Also record runs of clipped samples to detect clipping that lies on block boundaries. This method is thread-safe! Feel free to call from a different thread (like from an audio I/O callback).

First overload:

Parameters
numChannelsThe number of channels of audio being played back or recorded.
numFramesThe number of frames (samples) in this data block. It is assumed that there are the same number of frames in each channel.
sampleDataThe audio data itself, as interleaved samples. So indexing through the array we get the first sample of channel, first sample of channel 2 etc up to the first sample of channel (numChannels), then the second sample of channel 1, second sample of channel 2, and so to the second sample of channel (numChannels). The last sample in the array will be the (numFrames) sample for channel (numChannels).

The second overload is for ease of use in MixerBoard.

Definition at line 923 of file Meter.cpp.

References MeterUpdateMsg::clipping, floatMax(), MeterUpdateMsg::headPeakCount, MAX_AUDIO, min(), mNumBars, mNumPeakSamplesToClip, mQueue, MeterUpdateMsg::numFrames, MeterUpdateMsg::peak, MeterUpdateQueue::Put(), MeterUpdateMsg::rms, and MeterUpdateMsg::tailPeakCount.

Referenced by audacityAudioCallback(), and MixerTrackCluster::UpdateMeter().

924 {
925  float *sptr = sampleData;
926  auto num = std::min(numChannels, mNumBars);
927  MeterUpdateMsg msg;
928 
929  memset(&msg, 0, sizeof(msg));
930  msg.numFrames = numFrames;
931 
932  for(int i=0; i<numFrames; i++) {
933  for(unsigned int j=0; j<num; j++) {
934  msg.peak[j] = floatMax(msg.peak[j], fabs(sptr[j]));
935  msg.rms[j] += sptr[j]*sptr[j];
936 
937  // In addition to looking for mNumPeakSamplesToClip peaked
938  // samples in a row, also send the number of peaked samples
939  // at the head and tail, in case there's a run of peaked samples
940  // that crosses block boundaries
941  if (fabs(sptr[j])>=MAX_AUDIO) {
942  if (msg.headPeakCount[j]==i)
943  msg.headPeakCount[j]++;
944  msg.tailPeakCount[j]++;
946  msg.clipping[j] = true;
947  }
948  else
949  msg.tailPeakCount[j] = 0;
950  }
951  sptr += numChannels;
952  }
953  for(unsigned int j=0; j<mNumBars; j++)
954  msg.rms[j] = sqrt(msg.rms[j]/numFrames);
955 
956  mQueue.Put(msg);
957 }
float rms[kMaxMeterBars]
Definition: Meter.h:52
int mNumPeakSamplesToClip
Definition: Meter.h:250
static float floatMax(float a, float b)
Definition: Meter.cpp:886
int tailPeakCount[kMaxMeterBars]
Definition: Meter.h:55
bool clipping[kMaxMeterBars]
Definition: Meter.h:53
bool Put(MeterUpdateMsg &msg)
Definition: Meter.cpp:134
float peak[kMaxMeterBars]
Definition: Meter.h:51
int min(int a, int b)
Message used to update the Meter.
Definition: Meter.h:47
int numFrames
Definition: Meter.h:50
MeterUpdateQueue mQueue
Definition: Meter.h:231
int headPeakCount[kMaxMeterBars]
Definition: Meter.h:54
unsigned mNumBars
Definition: Meter.h:261
#define MAX_AUDIO
Definition: Audacity.h:212
void Meter::UpdatePrefs ( )

Definition at line 378 of file Meter.cpp.

References AutomaticStereo, ENV_DB_KEY, ENV_DB_RANGE, gPrefs, HorizontalStereo, Key(), MAX_REFRESH_RATE, mDB, mDBRange, mDesiredStyle, mGradient, min(), MIN_REFRESH_RATE, mLayoutValid, mLeftSize, mMeterDisabled, mMeterRefreshRate, mRate, mRightSize, Reset(), SetActiveStyle(), and VerticalStereo.

Referenced by OnMeterPrefsUpdated(), MeterToolBar::UpdatePrefs(), and MixerTrackCluster::UpdatePrefs().

379 {
381 
384  gPrefs->Read(Key(wxT("RefreshRate")), 30)));
385  mGradient = gPrefs->Read(Key(wxT("Bars")), wxT("Gradient")) == wxT("Gradient");
386  mDB = gPrefs->Read(Key(wxT("Type")), wxT("dB")) == wxT("dB");
387  mMeterDisabled = gPrefs->Read(Key(wxT("Disabled")), (long)0);
388 
390  {
391  wxString style = gPrefs->Read(Key(wxT("Style")));
392  if (style == wxT("AutomaticStereo"))
393  {
395  }
396  else if (style == wxT("HorizontalStereo"))
397  {
399  }
400  else if (style == wxT("VerticalStereo"))
401  {
403  }
404  else
405  {
407  }
408  }
409 
410  // Set the desired orientation (resets ruler orientation)
412 
413  // Reset to ensure NEW size is retrieved when language changes
414  mLeftSize = wxSize(0, 0);
415  mRightSize = wxSize(0, 0);
416 
417  Reset(mRate, false);
418 
419  mLayoutValid = false;
420 }
double mRate
Definition: Meter.h:253
wxSize mLeftSize
Definition: Meter.h:270
#define ENV_DB_KEY
Definition: GUISettings.h:15
long mMeterRefreshRate
Definition: Meter.h:254
bool mGradient
Definition: Meter.h:244
int mDBRange
Definition: Meter.h:246
static const long MIN_REFRESH_RATE
Definition: Meter.cpp:76
bool mDB
Definition: Meter.h:245
#define ENV_DB_RANGE
Definition: GUISettings.h:16
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
void SetActiveStyle(Style style)
Definition: Meter.cpp:1143
int min(int a, int b)
long mMeterDisabled
Definition: Meter.h:255
bool mLayoutValid
Definition: Meter.h:264
Style mDesiredStyle
Definition: Meter.h:243
wxString Key(const wxString &key) const
Definition: Meter.cpp:2065
wxSize mRightSize
Definition: Meter.h:271
void Reset(double sampleRate, bool resetClipping)
This method is thread-safe! Feel free to call from a different thread (like from an audio I/O callbac...
Definition: Meter.cpp:863
static const long MAX_REFRESH_RATE
Definition: Meter.cpp:77

Friends And Related Function Documentation

friend class MeterAx
friend

Definition at line 293 of file Meter.h.

Member Data Documentation

bool Meter::mAccSilent
private

Definition at line 291 of file Meter.h.

Referenced by ShowMenu().

bool Meter::mActive
private

Definition at line 259 of file Meter.h.

Referenced by OnAudioIOStatus(), OnMouse(), OnPaint(), RestoreState(), and ShowMenu().

MeterBar Meter::mBar[kMaxMeterBars]
private

Definition at line 262 of file Meter.h.

Referenced by GetMaxPeak(), HandleLayout(), IsClipping(), OnMeterUpdate(), OnPaint(), Reset(), and SetBarAndClip().

std::unique_ptr<wxBitmap> Meter::mBitmap
private

Definition at line 266 of file Meter.h.

Referenced by DrawMeterBar(), and OnPaint().

wxBrush Meter::mBkgndBrush
private

Definition at line 279 of file Meter.h.

Referenced by DrawMeterBar(), and OnPaint().

wxBrush Meter::mBrush
private

Definition at line 276 of file Meter.h.

bool Meter::mClip
private

Definition at line 249 of file Meter.h.

Referenced by DrawMeterBar(), OnPaint(), and SetBarAndClip().

wxBrush Meter::mClipBrush
private

Definition at line 278 of file Meter.h.

bool Meter::mDB
private

Definition at line 245 of file Meter.h.

Referenced by OnMeterUpdate(), OnPaint(), OnPreferences(), SetActiveStyle(), and UpdatePrefs().

int Meter::mDBRange
private

Definition at line 246 of file Meter.h.

Referenced by OnMeterUpdate(), OnPaint(), SetActiveStyle(), and UpdatePrefs().

bool Meter::mDecay
private

Definition at line 247 of file Meter.h.

Referenced by OnMeterUpdate().

float Meter::mDecayRate
private

Definition at line 248 of file Meter.h.

Referenced by OnMeterUpdate().

Style Meter::mDesiredStyle
private

Definition at line 243 of file Meter.h.

Referenced by GetDesiredStyle(), HandleLayout(), OnPreferences(), SetStyle(), and UpdatePrefs().

wxBrush Meter::mDisabledBkgndBrush
private

Definition at line 280 of file Meter.h.

Referenced by DrawMeterBar().

wxPen Meter::mDisabledPen
private

Definition at line 274 of file Meter.h.

wxRect Meter::mFocusRect
private

Definition at line 286 of file Meter.h.

bool Meter::mGradient
private

Definition at line 244 of file Meter.h.

Referenced by DrawMeterBar(), OnPaint(), OnPreferences(), and UpdatePrefs().

int Meter::mHeight
private

Definition at line 235 of file Meter.h.

Referenced by HandleLayout(), OnPaint(), and OnSize().

bool Meter::mHighlighted {}
private

Definition at line 295 of file Meter.h.

Referenced by OnMouse().

std::unique_ptr<wxBitmap> Meter::mIcon
private

Definition at line 272 of file Meter.h.

Referenced by HandleLayout(), and OnPaint().

wxRect Meter::mIconRect
private

Definition at line 267 of file Meter.h.

Referenced by HandleLayout(), InIcon(), OnContext(), OnKeyUp(), OnMouse(), and OnPaint().

bool Meter::mIsFocused
private

Definition at line 285 of file Meter.h.

Referenced by OnKillFocus(), OnPaint(), and OnSetFocus().

bool Meter::mIsInput
private

Definition at line 240 of file Meter.h.

Referenced by Key(), OnMeterUpdate(), OnMouse(), OnPaint(), OnPreferences(), ShowMenu(), and ~Meter().

bool Meter::mLayoutValid
private
wxSize Meter::mLeftSize
private

Definition at line 270 of file Meter.h.

Referenced by HandleLayout(), and UpdatePrefs().

wxString Meter::mLeftText
private

Definition at line 282 of file Meter.h.

Referenced by HandleLayout(), and OnPaint().

wxPoint Meter::mLeftTextPos
private

Definition at line 268 of file Meter.h.

Referenced by HandleLayout(), and OnPaint().

long Meter::mMeterDisabled
private

Definition at line 255 of file Meter.h.

Referenced by DrawMeterBar(), IsMeterDisabled(), OnMeterUpdate(), and UpdatePrefs().

long Meter::mMeterRefreshRate
private

Definition at line 254 of file Meter.h.

Referenced by OnAudioIOStatus(), OnPreferences(), Reset(), RestoreState(), and UpdatePrefs().

bool Meter::mMonitoring
private
unsigned Meter::mNumBars
private

Definition at line 261 of file Meter.h.

Referenced by GetMaxPeak(), HandleLayout(), OnMeterUpdate(), OnPaint(), RepaintBarsNow(), and UpdateDisplay().

int Meter::mNumPeakSamplesToClip
private

Definition at line 250 of file Meter.h.

Referenced by OnMeterUpdate(), and UpdateDisplay().

double Meter::mPeakHoldDuration
private

Definition at line 251 of file Meter.h.

Referenced by OnMeterUpdate().

wxPen Meter::mPeakPeakPen
private

Definition at line 275 of file Meter.h.

Referenced by DrawMeterBar().

wxPen Meter::mPen
private

Definition at line 273 of file Meter.h.

Referenced by DrawMeterBar().

AudacityProject* Meter::mProject
private

Definition at line 230 of file Meter.h.

Referenced by OnAudioIOStatus().

MeterUpdateQueue Meter::mQueue
private

Definition at line 231 of file Meter.h.

Referenced by Clear(), OnMeterUpdate(), Reset(), and UpdateDisplay().

double Meter::mRate
private

Definition at line 253 of file Meter.h.

Referenced by OnMeterUpdate(), OnMouse(), Reset(), and UpdatePrefs().

wxSize Meter::mRightSize
private

Definition at line 271 of file Meter.h.

Referenced by HandleLayout(), and UpdatePrefs().

wxString Meter::mRightText
private

Definition at line 283 of file Meter.h.

Referenced by HandleLayout(), and OnPaint().

wxPoint Meter::mRightTextPos
private

Definition at line 269 of file Meter.h.

Referenced by HandleLayout(), and OnPaint().

wxBrush Meter::mRMSBrush
private

Definition at line 277 of file Meter.h.

Ruler Meter::mRuler
private

Definition at line 281 of file Meter.h.

Referenced by HandleLayout(), OnPaint(), and SetActiveStyle().

int Meter::mRulerHeight
private

Definition at line 238 of file Meter.h.

Referenced by HandleLayout(), and SetActiveStyle().

int Meter::mRulerWidth
private

Definition at line 237 of file Meter.h.

Referenced by HandleLayout(), and SetActiveStyle().

Style Meter::mStyle
private
double Meter::mT
private

Definition at line 252 of file Meter.h.

Referenced by OnMeterUpdate(), and Reset().

wxTimer Meter::mTimer
private

Definition at line 232 of file Meter.h.

Referenced by OnAudioIOStatus(), Reset(), and RestoreState().

int Meter::mWidth
private

Definition at line 234 of file Meter.h.

Referenced by HandleLayout(), OnPaint(), and OnSize().

bool Meter::s_AcceptsFocus { false }
staticprivate

Definition at line 186 of file Meter.h.

Referenced by AcceptsFocus().


The documentation for this class was generated from the following files: