1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-29 22:58:39 +02:00

First stab at taming the meter toolbars

This should correct at least a couple of the reported
issues.  And it also has some fixes in for multiple
project support.
This commit is contained in:
lllucius 2014-12-17 19:16:08 +00:00
parent 4fe3f855eb
commit fe42e881a5
13 changed files with 203 additions and 158 deletions

View File

@ -328,6 +328,7 @@ AudioIO *gAudioIO;
DEFINE_EVENT_TYPE(EVT_AUDIOIO_PLAYBACK);
DEFINE_EVENT_TYPE(EVT_AUDIOIO_CAPTURE);
DEFINE_EVENT_TYPE(EVT_AUDIOIO_MONITOR);
// static
int AudioIO::mNextStreamToken = 0;
@ -963,6 +964,10 @@ bool AudioIO::StartPortAudioStream(double sampleRate,
mNumPauseFrames = 0;
mPauseTime = 0;
#endif
mOwningProject = GetActiveProject();
mInputMeter = NULL;
mOutputMeter = NULL;
mLastPaError = paNoError;
// pick a rate to do the audio I/O at, from those available. The project
// rate is suggested, but we may get something else if it isn't supported
@ -1014,6 +1019,8 @@ bool AudioIO::StartPortAudioStream(double sampleRate,
playbackDeviceInfo->defaultLowOutputLatency;
else
playbackParameters->suggestedLatency = latencyDuration/1000.0;
mOutputMeter = mOwningProject->GetPlaybackMeter();
}
if( numCaptureChannels > 0)
@ -1046,7 +1053,12 @@ bool AudioIO::StartPortAudioStream(double sampleRate,
captureDeviceInfo->defaultHighInputLatency;
else
captureParameters->suggestedLatency = latencyDuration/1000.0;
mInputMeter = mOwningProject->GetCaptureMeter();
}
SetMeters();
#ifdef EXPERIMENTAL_MIDI_OUT
if (numPlaybackChannels == 0 && numCaptureChannels == 0)
return true;
@ -1118,6 +1130,10 @@ void AudioIO::StartMonitoring(double sampleRate)
// TODO: Check return value of success.
(void)success;
wxCommandEvent e(EVT_AUDIOIO_MONITOR);
e.SetInt(true);
wxTheApp->ProcessEvent(e);
// Now start the PortAudio stream!
mLastPaError = Pa_StartStream( mPortStreamV19 );
}
@ -1604,11 +1620,32 @@ bool AudioIO::StartPortMidiStream()
}
#endif
void AudioIO::SetMeters(Meter *inputMeter, Meter *outputMeter)
void AudioIO::SetCaptureMeter(Meter *meter)
{
mInputMeter = inputMeter;
mOutputMeter = outputMeter;
if (!mOwningProject || mOwningProject == GetActiveProject())
{
mInputMeter = meter;
if (mInputMeter)
{
mInputMeter->Reset(mRate, true);
}
}
}
void AudioIO::SetPlaybackMeter(Meter *meter)
{
if (!mOwningProject || mOwningProject == GetActiveProject())
{
mOutputMeter = meter;
if (mOutputMeter)
{
mOutputMeter->Reset(mRate, true);
}
}
}
void AudioIO::SetMeters()
{
if (mInputMeter)
mInputMeter->Reset(mRate, true);
if (mOutputMeter)
@ -1711,12 +1748,11 @@ void AudioIO::StopStream()
if (mNumCaptureChannels > 0)
{
wxCommandEvent e(EVT_AUDIOIO_CAPTURE);
wxCommandEvent e(mStreamToken == 0 ? EVT_AUDIOIO_MONITOR : EVT_AUDIOIO_CAPTURE);
e.SetInt(false);
wxTheApp->ProcessEvent(e);
}
#ifdef EXPERIMENTAL_MIDI_OUT
/* Stop Midi playback */
if ( mMidiStream ) {
@ -1869,11 +1905,14 @@ void AudioIO::StopStream()
if (mOutputMeter)
mOutputMeter->Reset(mRate, false);
AudacityProject* pProj = GetActiveProject();
MixerBoard* pMixerBoard = pProj->GetMixerBoard();
MixerBoard* pMixerBoard = mOwningProject->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->ResetMeters(false);
mInputMeter = NULL;
mOutputMeter = NULL;
mOwningProject = NULL;
if (mListener && mNumCaptureChannels > 0)
mListener->OnAudioIOStopRecording();

View File

@ -72,6 +72,7 @@ class AudioIOListener;
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_AUDIOIO_PLAYBACK, -1);
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_AUDIOIO_CAPTURE, -1);
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_AUDIOIO_MONITOR, -1);
class AUDACITY_DLL_API AudioIO {
@ -222,10 +223,6 @@ class AUDACITY_DLL_API AudioIO {
* GetSupported*Rate functions considerably */
void HandleDeviceChange();
/** \brief Set the current VU meters - this should be done once after
* each call to StartStream currently */
void SetMeters(Meter *inputMeter, Meter *outputMeter);
/** \brief Get a list of sample rates the output (playback) device
* supports.
*
@ -326,7 +323,14 @@ class AUDACITY_DLL_API AudioIO {
double AILAGetLastDecisionTime();
#endif
void SetCaptureMeter(Meter *meter);
void SetPlaybackMeter(Meter *meter);
private:
/** \brief Set the current VU meters - this should be done once after
* each call to StartStream currently */
void SetMeters();
/** \brief Return a valid sample rate that is supported by the current I/O
* device(s).
*
@ -526,6 +530,7 @@ private:
volatile double mLastRecordingOffset;
PaError mLastPaError;
AudacityProject *mOwningProject;
Meter *mInputMeter;
Meter *mOutputMeter;
bool mUpdateMeters;

View File

@ -752,6 +752,8 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
mMixerBoardFrame(NULL),
mFreqWindow(NULL),
mAliasMissingWarningDialog(NULL),
mPlaybackMeter(NULL),
mCaptureMeter(NULL),
mToolManager(NULL),
mbBusyImporting(false),
mAudioIOToken(-1),
@ -1919,31 +1921,6 @@ void AudacityProject::OnActivate(wxActivateEvent & event)
mTrackPanel->SetFocus();
#endif
if (mToolManager && GetActiveProject())
{
MeterToolBar *tb;
tb = (MeterToolBar *) mToolManager->GetToolBar(MeterBarID);
if (tb->IsVisible())
{
tb->Activate(mActive);
}
else
{
tb = (MeterToolBar *) mToolManager->GetToolBar(RecordMeterBarID);
if (tb->IsVisible())
{
tb->Activate(mActive);
}
tb = (MeterToolBar *) mToolManager->GetToolBar(PlayMeterBarID);
if (tb->IsVisible())
{
tb->Activate(mActive);
}
}
}
// Under Windows, focus can be "lost" when returning to
// Audacity from a different application.
//
@ -4209,6 +4186,34 @@ TranscriptionToolBar *AudacityProject::GetTranscriptionToolBar()
NULL);
}
Meter *AudacityProject::GetPlaybackMeter()
{
return mPlaybackMeter;
}
void AudacityProject::SetPlaybackMeter(Meter *playback)
{
mPlaybackMeter = playback;
if (gAudioIO)
{
gAudioIO->SetPlaybackMeter(mPlaybackMeter);
}
}
Meter *AudacityProject::GetCaptureMeter()
{
return mCaptureMeter;
}
void AudacityProject::SetCaptureMeter(Meter *capture)
{
mCaptureMeter = capture;
if (gAudioIO)
{
gAudioIO->SetCaptureMeter(mCaptureMeter);
}
}
void AudacityProject::SetStop(bool bStopped)
{
mTrackPanel->SetStop(bStopped);

View File

@ -381,6 +381,11 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame,
ToolsToolBar *GetToolsToolBar();
TranscriptionToolBar *GetTranscriptionToolBar();
Meter *GetPlaybackMeter();
void SetPlaybackMeter(Meter *playback);
Meter *GetCaptureMeter();
void SetCaptureMeter(Meter *capture);
LyricsWindow* GetLyricsWindow() { return mLyricsWindow; };
MixerBoard* GetMixerBoard() { return mMixerBoard; };
@ -532,6 +537,10 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame,
// dialog for missing alias warnings
wxDialog *mAliasMissingWarningDialog;
// Project owned meters
Meter *mPlaybackMeter;
Meter *mCaptureMeter;
public:
ToolManager *mToolManager;
bool mShowSplashScreen;

View File

@ -2592,6 +2592,8 @@ void EffectUIHost::OnFFwd(wxCommandEvent & WXUNUSED(evt))
void EffectUIHost::OnPlayback(wxCommandEvent & evt)
{
evt.Skip();
mPlaying = evt.GetInt() != 0;
if (mPlaying)
@ -2605,6 +2607,8 @@ void EffectUIHost::OnPlayback(wxCommandEvent & evt)
void EffectUIHost::OnCapture(wxCommandEvent & evt)
{
evt.Skip();
mCapturing = evt.GetInt() != 0;
mCloseBtn->SetFocus();
UpdateControls();

View File

@ -63,6 +63,7 @@
#include "../Theme.h"
#include "../Track.h"
#include "../widgets/AButton.h"
#include "../widgets/Meter.h"
IMPLEMENT_CLASS(ControlToolBar, ToolBar);
@ -599,7 +600,6 @@ void ControlToolBar::PlayPlayRegion(double t0, double t1,
//AC: If init_seek was set, now's the time to make it happen.
gAudioIO->SeekStream(init_seek);
#endif
SetVUMeters(p);
}
else {
// msmeyer: Show error message if stream could not be opened
@ -622,13 +622,6 @@ void ControlToolBar::PlayPlayRegion(double t0, double t1,
}
}
void ControlToolBar::SetVUMeters(AudacityProject *WXUNUSED(p))
{
Meter *play, *record;
MeterToolBars::GetMeters( &play, &record);
gAudioIO->SetMeters(record, play);
}
void ControlToolBar::PlayCurrentRegion(bool looped /* = false */,
bool cutpreview /* = false */)
{
@ -714,7 +707,7 @@ void ControlToolBar::StopPlaying(bool stopStream /* = true*/)
mPause->PopUp();
mPaused=false;
//Make sure you tell gAudioIO to unpause
gAudioIO->SetPaused(mPaused);
gAudioIO->SetPaused(mPaused);
ClearCutPreviewTracks();
@ -724,7 +717,16 @@ void ControlToolBar::StopPlaying(bool stopStream /* = true*/)
AudacityProject *project = GetActiveProject();
if( project ) {
project->MayStartMonitoring();
MeterToolBars::Clear();
Meter *meter = project->GetPlaybackMeter();
if( meter ) {
meter->Clear();
}
meter = project->GetPlaybackMeter();
if( meter ) {
meter->Clear();
}
}
}
@ -878,7 +880,6 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
if (success) {
p->SetAudioIOToken(token);
mBusyProject = p;
SetVUMeters(p);
}
else {
// msmeyer: Delete recently added tracks if opening stream fails

View File

@ -80,8 +80,6 @@ class ControlToolBar:public ToolBar {
virtual void Repaint(wxDC *dc);
virtual void EnableDisableButtons();
void SetVUMeters(AudacityProject *p);
virtual void ReCreateButtons();
void RegenerateToolsTooltips();

View File

@ -33,6 +33,7 @@
#include "MeterToolBar.h"
#include "../AudioIO.h"
#include "../Project.h"
#include "../widgets/Meter.h"
IMPLEMENT_CLASS(MeterToolBar, ToolBar);
@ -47,19 +48,21 @@ BEGIN_EVENT_TABLE( MeterToolBar, ToolBar )
END_EVENT_TABLE()
//Standard contructor
MeterToolBar::MeterToolBar(int WhichMeters)
: ToolBar(MeterBarID, _("Combined Meter"), wxT("CombinedMeter"), true)
MeterToolBar::MeterToolBar(AudacityProject *project, int type)
: ToolBar(type, _("Combined Meter"), wxT("CombinedMeter"), true)
{
mWhichMeters = WhichMeters;
if( mWhichMeters == kWithRecordMeter ){
mType = RecordMeterBarID;
mProject = project;
if( mType == RecordMeterBarID ){
mWhichMeters = kWithRecordMeter;
mLabel = _("Recording Meter");
mSection = wxT("RecordMeter");
}
if( mWhichMeters == kWithPlayMeter ){
mType = PlayMeterBarID;
} else if( mType == PlayMeterBarID ){
mWhichMeters = kWithPlayMeter;
mLabel = _("Playback Meter");
mSection = wxT("PlayMeter");
} else {
mWhichMeters = kWithPlayMeter | kWithRecordMeter;
}
mSizer = NULL;
mPlayMeter = NULL;
@ -68,10 +71,8 @@ MeterToolBar::MeterToolBar(int WhichMeters)
MeterToolBar::~MeterToolBar()
{
MeterToolBars::RemoveMeters(mPlayMeter, mRecordMeter);
}
void MeterToolBar::Create(wxWindow * parent)
{
ToolBar::Create(parent);
@ -117,8 +118,7 @@ void MeterToolBar::Populate()
mPlayMeter->SetLabel( _("Meter-Play"));
mSizer->Add( mPlayMeter, wxGBPosition( (mWhichMeters & kWithRecordMeter)?1:0, 0 ), wxDefaultSpan, wxEXPAND );
}
if( IsVisible() )
MeterToolBars::AddMeters( mPlayMeter, mRecordMeter );
RegenerateTooltips();
}
@ -148,15 +148,6 @@ void MeterToolBar::RegenerateTooltips()
#endif
}
bool MeterToolBar::DestroyChildren()
{
MeterToolBars::RemoveMeters( mPlayMeter, mRecordMeter );
mPlayMeter = NULL;
mRecordMeter = NULL;
return ToolBar::DestroyChildren();
}
void MeterToolBar::OnMeterPrefsUpdated(wxCommandEvent & WXUNUSED(evt))
{
UpdatePrefs();
@ -214,23 +205,28 @@ void MeterToolBar::OnSize( wxSizeEvent & WXUNUSED(event) )
bool MeterToolBar::Expose( bool show )
{
if( show )
MeterToolBars::AddMeters( mPlayMeter, mRecordMeter );
else
MeterToolBars::RemoveMeters( mPlayMeter, mRecordMeter );
bool updated = false;
if( show ) {
if( mPlayMeter ) {
mProject->SetPlaybackMeter( mPlayMeter );
}
if( mRecordMeter ) {
mProject->SetCaptureMeter( mRecordMeter );
}
} else {
if( mPlayMeter && mProject->GetPlaybackMeter() == mPlayMeter ) {
mProject->SetPlaybackMeter( NULL );
}
if( mRecordMeter && mProject->GetCaptureMeter() == mRecordMeter ) {
mProject->SetCaptureMeter( NULL );
}
}
return ToolBar::Expose( show );
}
void MeterToolBar::Activate( bool active )
{
if( active )
MeterToolBars::AddMeters( mPlayMeter, mRecordMeter );
else
MeterToolBars::RemoveMeters( mPlayMeter, mRecordMeter );
gAudioIO->SetMeters(mRecordMeter, mPlayMeter);
}
wxSize MeterToolBar::GetDockedSize()
{
const int tbs = toolbarSingle + toolbarGap;
@ -246,43 +242,3 @@ wxSize MeterToolBar::GetDockedSize()
return sz;
}
// Locally defined - we can change implementation easily later.
namespace MeterToolBars {
Meter * mPlayMeter=NULL;
Meter * mRecordMeter=NULL;
}
void MeterToolBars::AddMeters(Meter *playMeter, Meter *recordMeter)
{
if( playMeter != NULL ) mPlayMeter = playMeter;
if( recordMeter != NULL ) mRecordMeter = recordMeter;
}
void MeterToolBars::RemoveMeters(Meter *playMeter, Meter *recordMeter)
{
if( mPlayMeter == playMeter ) mPlayMeter = NULL;
if( mRecordMeter == recordMeter ) mRecordMeter = NULL;
}
void MeterToolBars::GetMeters(Meter **playMeter, Meter **recordMeter)
{
*playMeter = mPlayMeter;
*recordMeter = mRecordMeter;
}
void MeterToolBars::StartMonitoring()
{
if( mRecordMeter == NULL )
return;
wxASSERT( mRecordMeter );
mRecordMeter->StartMonitoring();
//wxASSERT( mPlayMeter );
//mPlayMeter->StartMonitoring();
}
void MeterToolBars::Clear()
{
if (mPlayMeter) mPlayMeter->Clear();
if (mRecordMeter) mRecordMeter->Clear();
}

View File

@ -32,11 +32,10 @@ class MeterToolBar:public ToolBar {
public:
MeterToolBar(int WhichMeters);
MeterToolBar(AudacityProject *project, int type);
virtual ~MeterToolBar();
void Create(wxWindow *parent);
bool DestroyChildren();
virtual void Populate();
virtual void Repaint(wxDC * WXUNUSED(dc)) {};
@ -45,7 +44,6 @@ class MeterToolBar:public ToolBar {
virtual void OnSize(wxSizeEvent & event);
virtual bool Expose( bool show );
virtual void Activate( bool active );
int GetInitialWidth() {return (mWhichMeters ==
(kWithRecordMeter + kWithPlayMeter)) ? 338 : 460;} // Separate bars used to be smaller.
@ -56,6 +54,7 @@ class MeterToolBar:public ToolBar {
void OnMeterPrefsUpdated(wxCommandEvent & evt);
void RegenerateTooltips();
AudacityProject *mProject;
int mWhichMeters;
wxGridBagSizer *mSizer;
Meter *mPlayMeter;
@ -68,15 +67,5 @@ class MeterToolBar:public ToolBar {
};
namespace MeterToolBars {
void AddMeters(Meter *playMeter, Meter *recordMeter);
void RemoveMeters(Meter *playMeter, Meter *recordMeter);
void GetMeters(Meter **playMeter, Meter **recordMeter);
void StartMonitoring();
void Clear();
//Meter *mPlayMeter;
//Meter *mRecordMeter;
};
#endif

View File

@ -298,6 +298,8 @@ ToolBar::ToolBar( int type,
mGrabber = NULL;
mResizer = NULL;
SetId(mType);
}
//
@ -384,7 +386,7 @@ bool ToolBar::Expose( bool show )
{
bool was = mVisible;
mVisible = show;
SetVisible( show );
if( IsDocked() )
{
@ -423,10 +425,6 @@ void ToolBar::Create( wxWindow *parent )
// Go do the rest of the creation
ReCreateButtons();
// Let the user see it in all its glory
Show();
mVisible = true;
}
void ToolBar::ReCreateButtons()

View File

@ -406,9 +406,9 @@ ToolManager::ToolManager( AudacityProject *parent )
// Create all of the toolbars
mBars[ ToolsBarID ] = new ToolsToolBar();
mBars[ TransportBarID ] = new ControlToolBar();
mBars[ RecordMeterBarID ] = new MeterToolBar( kWithRecordMeter );
mBars[ PlayMeterBarID ] = new MeterToolBar( kWithPlayMeter );
mBars[ MeterBarID ] = new MeterToolBar( kWithPlayMeter | kWithRecordMeter );
mBars[ RecordMeterBarID ] = new MeterToolBar( parent, RecordMeterBarID );
mBars[ PlayMeterBarID ] = new MeterToolBar( parent, PlayMeterBarID );
mBars[ MeterBarID ] = new MeterToolBar( parent, MeterBarID );
mBars[ EditBarID ] = new EditToolBar();
mBars[ MixerBarID ] = new MixerToolBar();
mBars[ TranscriptionBarID ] = new TranscriptionToolBar();
@ -469,10 +469,6 @@ void ToolManager::Reset()
{
int ndx;
// The mInputMeter and mOutputMeter may be in use if audio is playing
// when this happens.
gAudioIO->SetMeters( NULL, NULL );
// Disconnect all docked bars
for( ndx = 0; ndx < ToolBarCount; ndx++ )
{
@ -756,6 +752,10 @@ void ToolManager::ReadConfig()
{
d->ShowHide( t->GetId() );
}
else
{
t->Expose( show[ ndx ] );
}
}
}
@ -772,6 +772,10 @@ void ToolManager::ReadConfig()
{
d->ShowHide( t->GetId() );
}
else
{
t->Expose( show[ ndx ] );
}
}
}

View File

@ -187,6 +187,7 @@ enum {
};
BEGIN_EVENT_TABLE(Meter, wxPanel)
EVT_COMMAND(wxID_ANY, EVT_AUDIOIO_MONITOR, Meter::OnAudioIOMonitor)
EVT_TIMER(OnMeterUpdateID, Meter::OnMeterUpdate)
EVT_MOUSE_EVENTS(Meter::OnMouse)
EVT_ERASE_BACKGROUND(Meter::OnErase)
@ -232,6 +233,7 @@ Meter::Meter(wxWindow* parent, wxWindowID id,
mPeakHoldDuration(3),
mT(0),
mRate(0),
mMonitoring(false),
mNumBars(0),
mLayoutValid(false),
mBitmap(NULL),
@ -291,6 +293,13 @@ Meter::Meter(wxWindow* parent, wxWindowID id,
mBar[i].clipping = false;
mBar[i].isclipping = false;
}
// Register for AudioIO Monitor events
wxTheApp->Connect(EVT_AUDIOIO_MONITOR,
wxCommandEventHandler(Meter::OnAudioIOMonitor),
NULL,
this);
}
void Meter::Clear()
@ -319,6 +328,12 @@ void Meter::CreateIcon(int WXUNUSED(aquaOffset))
Meter::~Meter()
{
// Register for AudioIO Monitor events
wxTheApp->Disconnect(EVT_AUDIOIO_MONITOR,
wxCommandEventHandler(Meter::OnAudioIOMonitor),
NULL,
this);
// LLL: This prevents a crash during termination if monitoring
// is active.
if (gAudioIO->IsMonitoring())
@ -1422,6 +1437,7 @@ bool Meter::IsMeterDisabled()
void Meter::StartMonitoring()
{
bool start = !mMonitoring;
if (gAudioIO->IsMonitoring()){
gAudioIO->StopStream();
@ -1429,24 +1445,41 @@ void Meter::StartMonitoring()
wxCommandEvent dummy;
OnDisableMeter(dummy);
}
} else {
}
if (start){
if (mMeterDisabled){
wxCommandEvent dummy;
OnDisableMeter(dummy);
}
AudacityProject *p = GetActiveProject();
if (p) {
if (p){
gAudioIO->StartMonitoring(p->GetRate());
Meter *play, *record;
MeterToolBars::GetMeters( &play, &record );
gAudioIO->SetMeters(record, play);
}
// Update preferences also forces tooltips to be changed.
wxCommandEvent e(EVT_METER_PREFERENCES_CHANGED);
e.SetEventObject(this);
GetParent()->GetEventHandler()->ProcessEvent(e);
mMonitoring = true;
}
// Update preferences also forces tooltips to be changed.
wxCommandEvent e(EVT_METER_PREFERENCES_CHANGED);
e.SetEventObject(this);
GetParent()->GetEventHandler()->ProcessEvent(e);
}
void Meter::OnAudioIOMonitor(wxCommandEvent &evt)
{
evt.Skip();
if (mMonitoring && !evt.GetInt())
{
if (!mMeterDisabled){
wxCommandEvent dummy;
OnDisableMeter(dummy);
}
mMonitoring = false;
}
Refresh();
}
//

View File

@ -179,6 +179,8 @@ class Meter : public wxPanel
void OnSize(wxSizeEvent &evt);
void OnMouse(wxMouseEvent &evt);
void OnAudioIOMonitor(wxCommandEvent &evt);
void OnMeterUpdate(wxTimerEvent &evt);
void HandlePaint(wxDC &dc);
@ -232,6 +234,8 @@ class Meter : public wxPanel
long mMeterRefreshRate;
long mMeterDisabled; //is used as a bool, needs long for easy gPrefs...
bool mMonitoring;
int mNumBars;
MeterBar mBar[kMaxMeterBars];