1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-03 17:19:43 +02:00

History, Lyrics, Mixerboard windows listen for new events...

... rather than relying on other code to push updates into them.

This simplifies much other code, especially in case of Mixerboard, and
eliminates some #includes, making the code for these special windows more
decoupled from the core.
This commit is contained in:
Paul Licameli 2018-10-27 18:02:03 -04:00
commit 70fff4b28b
36 changed files with 469 additions and 606 deletions

View File

@ -241,6 +241,8 @@ It handles initialization and termination by subclassing wxApp.
/// Custom events
////////////////////////////////////////////////////////////
wxDEFINE_EVENT( EVT_CLIPBOARD_CHANGE, wxCommandEvent);
DEFINE_EVENT_TYPE(EVT_OPEN_AUDIO_FILE);
wxDEFINE_EVENT(EVT_LANGUAGE_CHANGE, wxCommandEvent);

View File

@ -50,6 +50,11 @@ void QuitAudacity();
extern bool gIsQuitting;
// An event emitted by the application whenever the global clipboard's
// contents change.
wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API,
EVT_CLIPBOARD_CHANGE, wxCommandEvent);
// Asynchronous open
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_OPEN_AUDIO_FILE, -1);

View File

@ -447,7 +447,6 @@ TimeTrack and AudioIOListener and whether the playback is looped.
#include "AudacityApp.h"
#include "AudacityException.h"
#include "Mix.h"
#include "MixerBoard.h"
#include "Resample.h"
#include "RingBuffer.h"
#include "prefs/GUISettings.h"
@ -2402,10 +2401,6 @@ void AudioIO::SetMeters()
if (mOutputMeter)
mOutputMeter->Reset(mRate, true);
MixerBoard* pMixerBoard = mOwningProject->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->ResetMeters(true);
mUpdateMeters = true;
}
@ -2659,10 +2654,6 @@ void AudioIO::StopStream()
if (mOutputMeter)
mOutputMeter->Reset(mRate, false);
MixerBoard* pMixerBoard = mOwningProject->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->ResetMeters(false);
mInputMeter.Release();
mOutputMeter = NULL;
mOwningProject = NULL;

View File

@ -31,6 +31,7 @@ undo memory so as to free up space.
#include <wx/textctrl.h>
#include "AudioIO.h"
#include "AudacityApp.h"
#include "../images/Arrow.xpm"
#include "../images/Empty9x16.xpm"
#include "HistoryWindow.h"
@ -154,6 +155,11 @@ HistoryWindow::HistoryWindow(AudacityProject *parent, UndoManager *manager):
wxTheApp->Bind(EVT_AUDIOIO_CAPTURE,
&HistoryWindow::OnAudioIO,
this);
wxTheApp->Bind(EVT_CLIPBOARD_CHANGE, &HistoryWindow::UpdateDisplay, this);
manager->Bind(EVT_UNDO_PUSHED, &HistoryWindow::UpdateDisplay, this);
manager->Bind(EVT_UNDO_MODIFIED, &HistoryWindow::UpdateDisplay, this);
manager->Bind(EVT_UNDO_RESET, &HistoryWindow::UpdateDisplay, this);
}
void HistoryWindow::OnAudioIO(wxCommandEvent& evt)
@ -168,8 +174,9 @@ void HistoryWindow::OnAudioIO(wxCommandEvent& evt)
mDiscard->Enable(!mAudioIOBusy);
}
void HistoryWindow::UpdateDisplay()
void HistoryWindow::UpdateDisplay(wxEvent& e)
{
e.Skip();
if(IsShown())
DoUpdate();
}

View File

@ -29,7 +29,7 @@ class HistoryWindow final : public wxDialogWrapper {
public:
HistoryWindow(AudacityProject * parent, UndoManager *manager);
void UpdateDisplay();
void UpdateDisplay(wxEvent &e);
private:
void OnAudioIO(wxCommandEvent & evt);

View File

@ -15,11 +15,13 @@
#include <wx/dcmemory.h>
#include <wx/mimetype.h>
#include "AudioIO.h"
#include "Lyrics.h"
#include "Internat.h"
#include "Project.h" // for GetActiveProject
#include "LabelTrack.h"
#include "commands/CommandManager.h"
#include "UndoManager.h"
BEGIN_EVENT_TABLE(HighlightTextCtrl, wxTextCtrl)
@ -80,10 +82,12 @@ END_EVENT_TABLE()
IMPLEMENT_CLASS(LyricsPanel, wxPanel)
LyricsPanel::LyricsPanel(wxWindow* parent, wxWindowID id,
AudacityProject *project,
const wxPoint& pos /*= wxDefaultPosition*/,
const wxSize& size /*= wxDefaultSize*/):
const wxSize& size /*= wxDefaultSize*/) :
wxPanelWrapper(parent, id, pos, size, wxWANTS_CHARS),
mWidth(size.x), mHeight(size.y)
, mProject(project)
{
mKaraokeHeight = mHeight;
mLyricsStyle = kBouncingBallLyrics; // default
@ -109,6 +113,16 @@ LyricsPanel::LyricsPanel(wxWindow* parent, wxWindowID id,
wxSizeEvent dummyEvent;
OnSize(dummyEvent);
#endif
parent->Bind(wxEVT_SHOW, &LyricsPanel::OnShow, this);
auto undoManager = project->GetUndoManager();
undoManager->Bind(EVT_UNDO_PUSHED, &LyricsPanel::UpdateLyrics, this);
undoManager->Bind(EVT_UNDO_MODIFIED, &LyricsPanel::UpdateLyrics, this);
undoManager->Bind(EVT_UNDO_RESET, &LyricsPanel::UpdateLyrics, this);
wxTheApp->Bind(EVT_AUDIOIO_PLAYBACK, &LyricsPanel::OnStartStop, this);
wxTheApp->Bind(EVT_AUDIOIO_CAPTURE, &LyricsPanel::OnStartStop, this);
}
LyricsPanel::~LyricsPanel()
@ -456,6 +470,55 @@ void LyricsPanel::Update(double t)
}
}
void LyricsPanel::UpdateLyrics(wxEvent &e)
{
e.Skip();
// It's crucial to not do that repopulating during playback.
if (gAudioIO->IsStreamActive()) {
mDelayedUpdate = true;
return;
}
Clear();
if (!mProject)
return;
// Lyrics come from only the first label track.
auto pLabelTrack = *mProject->GetTracks()->Any< const LabelTrack >().begin();
if (!pLabelTrack)
return;
// The code that updates the lyrics is rather expensive when there
// are a lot of labels.
// So - bail out early if the lyrics window is not visible.
// We will later force an update when the lyrics window is made visible.
auto parent = dynamic_cast<wxFrame*>(GetParent());
if( !(parent && parent->IsVisible()) )
return;
AddLabels(pLabelTrack);
Finish(pLabelTrack->GetEndTime());
Update(mProject->GetSel0());
}
void LyricsPanel::OnStartStop(wxCommandEvent &e)
{
e.Skip();
if ( !e.GetInt() && mDelayedUpdate ) {
mDelayedUpdate = false;
UpdateLyrics( e );
}
}
void LyricsPanel::OnShow(wxShowEvent &e)
{
e.Skip();
if (e.IsShown())
UpdateLyrics(e);
}
void LyricsPanel::OnKeyEvent(wxKeyEvent & event)
{
AudacityProject *project = GetActiveProject();

View File

@ -18,6 +18,7 @@
#include <wx/textctrl.h>
#include "widgets/wxPanelWrapper.h"
class AudacityProject;
class LabelTrack;
@ -80,14 +81,11 @@ class LyricsPanel final : public wxPanelWrapper
public:
LyricsPanel(wxWindow* parent, wxWindowID id,
AudacityProject *project,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize);
virtual ~LyricsPanel();
void Clear();
void AddLabels(const LabelTrack *pLT);
void Finish(double finalT);
int FindSyllable(long startChar); // Find the syllable whose char0 <= startChar <= char1.
int GetCurrentSyllableIndex() { return mCurrentSyllable; };
Syllable* GetSyllable(int nSyl) { return &(mSyllables[nSyl]); };
@ -97,6 +95,9 @@ class LyricsPanel final : public wxPanelWrapper
void SetLyricsStyle(const LyricsStyle newLyricsStyle);
void Update(double t);
void UpdateLyrics(wxEvent &e);
void OnShow(wxShowEvent& e);
void OnStartStop(wxCommandEvent &e);
//
// Event handlers
@ -116,6 +117,10 @@ class LyricsPanel final : public wxPanelWrapper
void HandleLayout();
private:
void Clear();
void AddLabels(const LabelTrack *pLT);
void Finish(double finalT);
void Add(double t, const wxString &syllable, wxString &highlightText);
unsigned int GetDefaultFontSize() const; // Depends on mLyricsStyle. Call only after mLyricsStyle is set.
@ -146,6 +151,9 @@ private:
int mTextHeight; // only for drawn text
bool mMeasurementsDone; // only for drawn text
wxWeakRef<AudacityProject> mProject;
bool mDelayedUpdate{ false };
DECLARE_EVENT_TABLE()
};

View File

@ -114,10 +114,9 @@ LyricsWindow::LyricsWindow(AudacityProject *parent):
//
//pToolBar->Realize();
mLyricsPanel = safenew LyricsPanel(this, -1, panelPos, panelSize);
mLyricsPanel = safenew LyricsPanel(this, -1, parent, panelPos, panelSize);
RTL_WORKAROUND(mLyricsPanel);
//vvv Highlight style is broken in ported version.
//switch (mLyricsPanel->GetLyricsStyle())
//{

View File

@ -212,7 +212,7 @@ MixerTrackCluster::MixerTrackCluster(wxWindow* parent,
.Style( DB_SLIDER )
.Orientation( wxVERTICAL ));
mSlider_Gain->SetName(_("Gain"));
this->UpdateGain();
#ifdef EXPERIMENTAL_MIDI_OUT
mSlider_Velocity =
safenew MixerTrackSlider(
@ -224,7 +224,6 @@ MixerTrackCluster::MixerTrackCluster(wxWindow* parent,
.Style( VEL_SLIDER )
.Orientation( wxVERTICAL ));
mSlider_Velocity->SetName(_("Velocity"));
this->UpdateVelocity();
#endif
// other controls and meter at right
@ -260,8 +259,6 @@ MixerTrackCluster::MixerTrackCluster(wxWindow* parent,
ASlider::Options{}.Style( PAN_SLIDER ));
mSlider_Pan->SetName(_("Pan"));
this->UpdatePan();
// mute/solo buttons stacked below Pan slider
ctrlPos.y += PAN_HEIGHT + kDoubleInset;
ctrlSize.Set(mMixerBoard->mMuteSoloWidth, MUTE_SOLO_HEIGHT);
@ -278,7 +275,6 @@ MixerTrackCluster::MixerTrackCluster(wxWindow* parent,
*(mMixerBoard->mImageMuteUp), *(mMixerBoard->mImageMuteOver),
*(mMixerBoard->mImageMuteDown), *(mMixerBoard->mImageMuteDown),
*(mMixerBoard->mImageMuteDisabled));
this->UpdateMute();
ctrlPos.y += MUTE_SOLO_HEIGHT;
mToggleButton_Solo =
@ -289,7 +285,6 @@ MixerTrackCluster::MixerTrackCluster(wxWindow* parent,
*(mMixerBoard->mImageSoloDisabled),
true); // toggle button
mToggleButton_Solo->SetName(_("Solo"));
this->UpdateSolo();
bool bSoloNone = mProject->IsSoloNone();
mToggleButton_Solo->Show(!bSoloNone);
@ -322,11 +317,12 @@ MixerTrackCluster::MixerTrackCluster(wxWindow* parent,
mMeter->SetToolTip(_("Signal Level Meter"));
#endif // wxUSE_TOOLTIPS
UpdateForStateChange();
#ifdef __WXMAC__
wxSizeEvent event(GetSize(), GetId());
event.SetEventObject(this);
GetEventHandler()->ProcessEvent(event);
UpdateGain();
#endif
}
@ -450,77 +446,51 @@ void MixerTrackCluster::ResetMeter(const bool bResetClipping)
}
// These are used by TrackPanel for synchronizing control states, etc.
// Update the controls that can be affected by state change.
// Update appearance to match the state of the track
void MixerTrackCluster::UpdateForStateChange()
{
this->UpdateName();
this->UpdatePan();
this->UpdateGain();
}
void MixerTrackCluster::UpdateName()
{
const wxString newName = mTrack->GetName();
SetName(newName);
mStaticText_TrackName->SetLabel(newName);
mStaticText_TrackName->SetName(newName);
#if wxUSE_TOOLTIPS
mStaticText_TrackName->SetToolTip(newName);
#endif
mBitmapButton_MusicalInstrument->SetBitmapLabel(
*(mMixerBoard->GetMusicalInstrumentBitmap(mTrack.get())));
Refresh();
}
if (newName != GetName()) {
SetName(newName);
mStaticText_TrackName->SetLabel(newName);
mStaticText_TrackName->SetName(newName);
#if wxUSE_TOOLTIPS
mStaticText_TrackName->SetToolTip(newName);
#endif
mBitmapButton_MusicalInstrument->SetBitmapLabel(
*(mMixerBoard->GetMusicalInstrumentBitmap(mTrack.get())));
}
void MixerTrackCluster::UpdateMute()
{
mToggleButton_Mute->SetAlternateIdx(mTrack->GetSolo() ? 1 : 0);
if (mTrack->GetMute())
mToggleButton_Mute->PushDown();
else
mToggleButton_Mute->PopUp();
}
void MixerTrackCluster::UpdateSolo()
{
bool bIsSolo = mTrack->GetSolo();
if (bIsSolo)
mToggleButton_Solo->PushDown();
else
mToggleButton_Solo->PopUp();
mToggleButton_Mute->SetAlternateIdx(bIsSolo ? 1 : 0);
}
void MixerTrackCluster::UpdatePan()
{
if (!GetWave()) {
if (!GetWave())
mSlider_Pan->Hide();
return;
}
mSlider_Pan->Set(GetWave()->GetPan());
}
else
mSlider_Pan->Set(GetWave()->GetPan());
void MixerTrackCluster::UpdateGain()
{
if (!GetWave()) {
if (!GetWave())
mSlider_Gain->Hide();
return;
}
mSlider_Gain->Set(GetWave()->GetGain());
}
else
mSlider_Gain->Set(GetWave()->GetGain());
#ifdef EXPERIMENTAL_MIDI_OUT
void MixerTrackCluster::UpdateVelocity()
{
if (!GetNote()) {
if (!GetNote())
mSlider_Velocity->Hide();
return;
}
mSlider_Velocity->Set(GetNote()->GetVelocity());
}
else
mSlider_Velocity->Set(GetNote()->GetVelocity());
#endif
}
void MixerTrackCluster::UpdateMeter(const double t0, const double t1)
{
@ -704,6 +674,8 @@ void MixerTrackCluster::OnMouseEvent(wxMouseEvent& event)
void MixerTrackCluster::OnPaint(wxPaintEvent & WXUNUSED(event))
{
UpdateForStateChange();
auto selected = mTrack->GetSelected();
wxColour col = theTheme.Colour(selected ? clrTrackInfoSelected : clrTrackInfo) ;
@ -773,8 +745,6 @@ void MixerTrackCluster::OnButton_Mute(wxCommandEvent& WXUNUSED(event))
// Update the TrackPanel correspondingly.
if (mProject->IsSoloSimple())
{
// Have to refresh all tracks.
mMixerBoard->UpdateSolo();
mProject->RedrawProject();
}
else
@ -789,12 +759,6 @@ void MixerTrackCluster::OnButton_Solo(wxCommandEvent& WXUNUSED(event))
mToggleButton_Mute->SetAlternateIdx(bIsSolo ? 1 : 0);
// Update the TrackPanel correspondingly.
if (mProject->IsSoloSimple())
{
// Have to refresh all tracks.
mMixerBoard->UpdateMute();
mMixerBoard->UpdateSolo();
}
// Bug 509: Must repaint all, as many tracks can change with one Solo change.
mProject->RedrawProject();
}
@ -874,6 +838,7 @@ void MixerBoardScrolledWindow::OnMouseEvent(wxMouseEvent& event)
BEGIN_EVENT_TABLE(MixerBoard, wxWindow)
EVT_PAINT(MixerBoard::OnPaint)
EVT_SIZE(MixerBoard::OnSize)
END_EVENT_TABLE()
@ -940,6 +905,31 @@ MixerBoard::MixerBoard(AudacityProject* pProject,
mProject->Bind(EVT_TRACK_PANEL_TIMER,
&MixerBoard::OnTimer,
this);
mProject->GetTracks()->Bind(EVT_TRACKLIST_SELECTION_CHANGE,
&MixerBoard::OnTrackChanged,
this);
mProject->GetTracks()->Bind(EVT_TRACKLIST_PERMUTED,
&MixerBoard::OnTrackSetChanged,
this);
mProject->GetTracks()->Bind(EVT_TRACKLIST_ADDITION,
&MixerBoard::OnTrackSetChanged,
this);
mProject->GetTracks()->Bind(EVT_TRACKLIST_DELETION,
&MixerBoard::OnTrackSetChanged,
this);
mProject->GetTracks()->Bind(EVT_TRACKLIST_TRACK_DATA_CHANGE,
&MixerBoard::OnTrackChanged,
this);
wxTheApp->Connect(EVT_AUDIOIO_PLAYBACK,
wxCommandEventHandler(MixerBoard::OnStartStop),
NULL,
this);
}
@ -947,7 +937,8 @@ MixerBoard::MixerBoard(AudacityProject* pProject,
void MixerBoard::UpdatePrefs()
{
mProject->RecreateMixerBoard();
// Destroys this:
static_cast<MixerBoardFrame*>(GetParent())->Recreate( mProject );
// Old approach modified things in situ.
// However with a theme change there is so much to modify, it is easier
@ -1044,53 +1035,6 @@ int MixerBoard::GetTrackClustersWidth()
kDoubleInset; // plus final right margin
}
void MixerBoard::MoveTrackCluster(const PlayableTrack* pTrack,
bool bUp) // Up in TrackPanel is left in MixerBoard.
{
MixerTrackCluster* pMixerTrackCluster;
int nIndex = FindMixerTrackCluster(pTrack, &pMixerTrackCluster);
if (pMixerTrackCluster == NULL)
return; // Couldn't find it.
wxPoint pos;
if (bUp)
{ // Move it up (left).
if (nIndex <= 0)
return; // It's already first (0), or not found (-1).
pos = pMixerTrackCluster->GetPosition();
mMixerTrackClusters[nIndex] = mMixerTrackClusters[nIndex - 1];
mMixerTrackClusters[nIndex]->Move(pos);
mMixerTrackClusters[nIndex - 1] = pMixerTrackCluster;
pMixerTrackCluster->Move(pos.x - (kInset + kMixerTrackClusterWidth), pos.y);
}
else
{ // Move it down (right).
if (((unsigned int)nIndex + 1) >= mMixerTrackClusters.size())
return; // It's already last.
pos = pMixerTrackCluster->GetPosition();
mMixerTrackClusters[nIndex] = mMixerTrackClusters[nIndex + 1];
mMixerTrackClusters[nIndex]->Move(pos);
mMixerTrackClusters[nIndex + 1] = pMixerTrackCluster;
pMixerTrackCluster->Move(pos.x + (kInset + kMixerTrackClusterWidth), pos.y);
}
}
void MixerBoard::RemoveTrackCluster(const PlayableTrack* pTrack)
{
// Find and destroy.
MixerTrackCluster* pMixerTrackCluster;
int nIndex = this->FindMixerTrackCluster(pTrack, &pMixerTrackCluster);
if (pMixerTrackCluster == NULL)
return; // Couldn't find it.
RemoveTrackCluster(nIndex);
}
void MixerBoard::RemoveTrackCluster(size_t nIndex)
{
auto pMixerTrackCluster = mMixerTrackClusters[nIndex];
@ -1164,14 +1108,6 @@ bool MixerBoard::HasSolo()
return !(( mTracks->Any<PlayableTrack>() + &PlayableTrack::GetSolo ).empty());
}
void MixerBoard::RefreshTrackCluster(const PlayableTrack* pTrack, bool bEraseBackground /*= true*/)
{
MixerTrackCluster* pMixerTrackCluster;
this->FindMixerTrackCluster(pTrack, &pMixerTrackCluster);
if (pMixerTrackCluster)
pMixerTrackCluster->Refresh(bEraseBackground);
}
void MixerBoard::RefreshTrackClusters(bool bEraseBackground /*= true*/)
{
for (unsigned int i = 0; i < mMixerTrackClusters.size(); i++)
@ -1195,80 +1131,6 @@ void MixerBoard::ResetMeters(const bool bResetClipping)
mMixerTrackClusters[i]->ResetMeter(bResetClipping);
}
void MixerBoard::UpdateName(const PlayableTrack* pTrack)
{
MixerTrackCluster* pMixerTrackCluster;
this->FindMixerTrackCluster(pTrack, &pMixerTrackCluster);
if (pMixerTrackCluster)
pMixerTrackCluster->UpdateName();
}
void MixerBoard::UpdateMute(const PlayableTrack* pTrack /*= NULL*/) // NULL means update for all tracks.
{
if (pTrack == NULL)
{
for (unsigned int i = 0; i < mMixerTrackClusters.size(); i++)
mMixerTrackClusters[i]->UpdateMute();
}
else
{
MixerTrackCluster* pMixerTrackCluster;
FindMixerTrackCluster(pTrack, &pMixerTrackCluster);
if (pMixerTrackCluster)
pMixerTrackCluster->UpdateMute();
}
}
void MixerBoard::UpdateSolo(const PlayableTrack* pTrack /*= NULL*/) // NULL means update for all tracks.
{
if (pTrack == NULL)
{
for (unsigned int i = 0; i < mMixerTrackClusters.size(); i++)
mMixerTrackClusters[i]->UpdateSolo();
}
else
{
MixerTrackCluster* pMixerTrackCluster;
FindMixerTrackCluster(pTrack, &pMixerTrackCluster);
if (pMixerTrackCluster)
pMixerTrackCluster->UpdateSolo();
}
}
void MixerBoard::UpdatePan(const PlayableTrack* pTrack)
{
if (pTrack == NULL)
{
for (unsigned int i = 0; i < mMixerTrackClusters.size(); i++)
mMixerTrackClusters[i]->UpdatePan();
}
else
{
MixerTrackCluster* pMixerTrackCluster;
FindMixerTrackCluster(pTrack, &pMixerTrackCluster);
if (pMixerTrackCluster)
pMixerTrackCluster->UpdatePan();
}
}
void MixerBoard::UpdateGain(const PlayableTrack* pTrack)
{
MixerTrackCluster* pMixerTrackCluster;
FindMixerTrackCluster(pTrack, &pMixerTrackCluster);
if (pMixerTrackCluster)
pMixerTrackCluster->UpdateGain();
}
#ifdef EXPERIMENTAL_MIDI_OUT
void MixerBoard::UpdateVelocity(const PlayableTrack* pTrack)
{
MixerTrackCluster* pMixerTrackCluster;
FindMixerTrackCluster(pTrack, &pMixerTrackCluster);
if (pMixerTrackCluster)
pMixerTrackCluster->UpdateVelocity();
}
#endif
void MixerBoard::UpdateMeters(const double t1, const bool bLoopedPlay)
{
if (!this->IsShown() || (t1 == BAD_STREAM_TIME))
@ -1440,6 +1302,17 @@ void MixerBoard::LoadMusicalInstruments()
// event handlers
void MixerBoard::OnPaint(wxPaintEvent& evt)
{
if (!mUpToDate) {
mUpToDate = true;
UpdateTrackClusters();
Refresh();
}
// Does the base class do anything for repainting?
evt.Skip();
}
void MixerBoard::OnSize(wxSizeEvent &evt)
{
// this->FitInside() doesn't work, and it doesn't happen automatically. Is wxScrolledWindow wrong?
@ -1473,6 +1346,33 @@ void MixerBoard::OnTimer(wxCommandEvent &event)
event.Skip();
}
void MixerBoard::OnTrackChanged(TrackListEvent &evt)
{
evt.Skip();
auto pTrack = evt.mpTrack.lock();
auto pPlayable = dynamic_cast<PlayableTrack*>( pTrack.get() );
if ( pPlayable ) {
MixerTrackCluster *pMixerTrackCluster;
FindMixerTrackCluster( pPlayable, &pMixerTrackCluster );
if ( pMixerTrackCluster )
pMixerTrackCluster->Refresh();
}
}
void MixerBoard::OnTrackSetChanged(wxEvent &evt)
{
evt.Skip();
mUpToDate = false;
Refresh();
}
void MixerBoard::OnStartStop(wxCommandEvent &evt)
{
evt.Skip();
bool start = evt.GetInt();
ResetMeters( start );
}
// class MixerBoardFrame
@ -1551,4 +1451,22 @@ void MixerBoardFrame::OnKeyEvent(wxKeyEvent & event)
project->GetCommandManager()->FilterKeyEvent(project, event, true);
}
void MixerBoardFrame::Recreate( AudacityProject *pProject )
{
wxPoint pos = mMixerBoard->GetPosition();
wxSize siz = mMixerBoard->GetSize();
wxSize siz2 = this->GetSize();
//wxLogDebug("Got rid of board %p", mMixerBoard );
mMixerBoard->Destroy();
mMixerBoard = NULL;
mMixerBoard = safenew MixerBoard(pProject, this, pos, siz);
//wxLogDebug("Created NEW board %p", mMixerBoard );
mMixerBoard->UpdateTrackClusters();
mMixerBoard->SetSize( siz );
this->SetSize( siz2 );
}

View File

@ -25,6 +25,8 @@
#include "widgets/ASlider.h"
#include "widgets/wxPanelWrapper.h"
class TrackListEvent;
// containment hierarchy:
// MixerBoardFrame -> MixerBoard -> MixerBoardScrolledWindow -> MixerTrackCluster(s)
@ -96,16 +98,7 @@ public:
void ResetMeter(const bool bResetClipping);
// These are used by TrackPanel for synchronizing control states.
void UpdateForStateChange(); // Update the controls that can be affected by state change.
void UpdateName();
void UpdateMute();
void UpdateSolo();
void UpdatePan();
void UpdateGain();
#ifdef EXPERIMENTAL_MIDI_OUT
void UpdateVelocity();
#endif
void UpdateForStateChange();
void UpdateMeter(const double t0, const double t1);
private:
@ -212,36 +205,23 @@ public:
void UpdateTrackClusters();
int GetTrackClustersWidth();
void MoveTrackCluster(const PlayableTrack* pTrack, bool bUp); // Up in TrackPanel is left in MixerBoard.
void RemoveTrackCluster(const PlayableTrack* pTrack);
void RemoveTrackCluster(size_t nIndex);
wxBitmap* GetMusicalInstrumentBitmap(const Track *pTrack);
bool HasSolo();
void RefreshTrackCluster(const PlayableTrack* pTrack, bool bEraseBackground = true);
void RefreshTrackClusters(bool bEraseBackground = true);
void ResizeTrackClusters();
void ResetMeters(const bool bResetClipping);
void UpdateName(const PlayableTrack* pTrack);
void UpdateMute(const PlayableTrack* pTrack = NULL); // NULL means update for all tracks.
void UpdateSolo(const PlayableTrack* pTrack = NULL); // NULL means update for all tracks.
void UpdatePan(const PlayableTrack* pTrack = NULL); // NULL means update for all tracks.
void UpdateGain(const PlayableTrack* pTrack);
#ifdef EXPERIMENTAL_MIDI_OUT
void UpdateVelocity(const PlayableTrack* pTrack);
#endif
void UpdateMeters(const double t1, const bool bLoopedPlay);
void UpdateWidth();
private:
void MakeButtonBitmap( wxMemoryDC & dc, wxBitmap & bitmap,
void ResetMeters(const bool bResetClipping);
void RemoveTrackCluster(size_t nIndex);
void MakeButtonBitmap( wxMemoryDC & dc, wxBitmap & bitmap,
wxRect & bev, const wxString & str, bool up );
void CreateMuteSoloImages();
int FindMixerTrackCluster(const PlayableTrack* pTrack,
@ -249,9 +229,12 @@ private:
void LoadMusicalInstruments();
// event handlers
void OnPaint(wxPaintEvent& evt);
void OnSize(wxSizeEvent &evt);
void OnTimer(wxCommandEvent &event);
void OnTrackSetChanged(wxEvent &event);
void OnTrackChanged(TrackListEvent &event);
void OnStartStop(wxCommandEvent &event);
public:
// mute & solo button images: Create once and store on MixerBoard for use in all MixerTrackClusters.
@ -270,6 +253,7 @@ private:
MixerBoardScrolledWindow* mScrolledWindow; // Holds the MixerTrackClusters and handles scrolling.
double mPrevT1;
TrackList* mTracks;
bool mUpToDate{ false };
public:
DECLARE_EVENT_TABLE()
@ -282,6 +266,8 @@ public:
MixerBoardFrame(AudacityProject* parent);
virtual ~MixerBoardFrame();
void Recreate(AudacityProject *pProject);
private:
// event handlers
void OnCloseWindow(wxCloseEvent &WXUNUSED(event));

View File

@ -643,6 +643,14 @@ void NoteTrack::InsertSilence(double t, double len)
// AddToDuration( len );
}
void NoteTrack::SetVelocity(float velocity)
{
if (mVelocity != velocity) {
mVelocity = velocity;
Notify();
}
}
// Call this function to manipulate the underlying sequence data. This is
// NOT the function that handles horizontal dragging.
bool NoteTrack::Shift(double t) // t is always seconds

View File

@ -114,7 +114,7 @@ class AUDACITY_DLL_API NoteTrack final
#ifdef EXPERIMENTAL_MIDI_OUT
float GetVelocity() const { return mVelocity; }
void SetVelocity(float velocity) { mVelocity = velocity; }
void SetVelocity(float velocity);
#endif
QuantizedTimeAndBeat NearestBeatTime( double time ) const;

View File

@ -100,8 +100,6 @@ scroll information. It also has some status flags.
#include "Diags.h"
#include "HistoryWindow.h"
#include "InconsistencyException.h"
#include "Lyrics.h"
#include "LyricsWindow.h"
#include "MixerBoard.h"
#include "Internat.h"
#include "import/Import.h"
@ -4591,14 +4589,9 @@ void AudacityProject::InitialState()
GetUndoManager()->StateSaved();
if (mHistoryWindow)
mHistoryWindow->UpdateDisplay();
GetMenuManager(*this).ModifyUndoMenuItems(*this);
GetMenuManager(*this).UpdateMenus(*this);
this->UpdateLyrics();
this->UpdateMixerBoard();
}
bool AudacityProject::UndoAvailable()
@ -4629,24 +4622,10 @@ void AudacityProject::PushState(const wxString &desc,
mDirty = true;
if (mHistoryWindow)
mHistoryWindow->UpdateDisplay();
GetMenuManager(*this).ModifyUndoMenuItems(*this);
GetMenuManager(*this).UpdateMenus(*this);
// Some state pushes, like changing a track gain control (& probably others),
// should not repopulate Lyrics Window and MixerBoard.
// Others, such as deleting a label or adding a wave track, obviously do.
// Could categorize these state changes, but for now...
// It's crucial to not do that repopulating during playback.
if (!gAudioIO->IsStreamActive(GetAudioIOToken()))
{
this->UpdateLyrics();
this->UpdateMixerBoard();
}
if (GetTracksFitVerticallyZoomed())
ViewActions::DoZoomFitV(*this);
if((flags & UndoPush::AUTOSAVE) != UndoPush::MINIMAL)
@ -4673,6 +4652,8 @@ void AudacityProject::ModifyState(bool bWantsAutoSave)
// Need to keep it and its tracks "t" available for Undo/Redo/SetStateTo.
void AudacityProject::PopState(const UndoState &state)
{
mViewInfo.selectedRegion = state.selectedRegion;
// Restore tags
mTags = state.tags;
@ -4717,80 +4698,19 @@ void AudacityProject::PopState(const UndoState &state)
HandleResize();
GetMenuManager(*this).UpdateMenus(*this);
this->UpdateLyrics();
this->UpdateMixerBoard();
AutoSave();
}
void AudacityProject::SetStateTo(unsigned int n)
{
const UndoState &state =
GetUndoManager()->SetStateTo(n, &mViewInfo.selectedRegion);
PopState(state);
GetUndoManager()->SetStateTo(n,
[this]( const UndoState &state ){ PopState(state); } );
HandleResize();
mTrackPanel->SetFocusedTrack(NULL);
mTrackPanel->Refresh(false);
GetMenuManager(*this).ModifyUndoMenuItems(*this);
this->UpdateLyrics();
this->UpdateMixerBoard();
}
void AudacityProject::UpdateLyrics()
{
// JKC: Previously we created a lyrics window,
// if it did not exist. But we don't need to.
if (!mLyricsWindow)
return;
// Lyrics come from only the first label track.
auto pLabelTrack = *GetTracks()->Any< const LabelTrack >().begin();
if (!pLabelTrack)
return;
// The code that updates the lyrics is rather expensive when there
// are a lot of labels.
// So - bail out early if the lyrics window is not visible.
// We will later force an update when the lyrics window is made visible.
if( !mLyricsWindow->IsVisible() )
return;
LyricsPanel* pLyricsPanel = mLyricsWindow->GetLyricsPanel();
pLyricsPanel->Clear();
pLyricsPanel->AddLabels(pLabelTrack);
pLyricsPanel->Finish(pLabelTrack->GetEndTime());
pLyricsPanel->Update(this->GetSel0());
}
void AudacityProject::UpdateMixerBoard()
{
if (!mMixerBoard)
return;
mMixerBoard->UpdateTrackClusters();
// Vaughan, 2011-01-28: AudacityProject::UpdateMixerBoard() is called on state changes,
// so don't really need to call UpdateMeters().
//mMixerBoard->UpdateMeters(gAudioIO->GetStreamTime(), (mLastPlayMode == loopedPlay));
}
void AudacityProject::RecreateMixerBoard( )
{
wxASSERT( mMixerBoard );
wxASSERT( mMixerBoardFrame );
wxPoint pos = mMixerBoard->GetPosition();
wxSize siz = mMixerBoard->GetSize();
wxSize siz2 = mMixerBoardFrame->GetSize();
//wxLogDebug("Got rid of board %p", mMixerBoard );
mMixerBoard->Destroy();
mMixerBoard = NULL;
mMixerBoard = safenew MixerBoard(this, mMixerBoardFrame, pos, siz);
mMixerBoardFrame->mMixerBoard = mMixerBoard;
//wxLogDebug("Created NEW board %p", mMixerBoard );
mMixerBoard->UpdateTrackClusters();
mMixerBoard->SetSize( siz );
mMixerBoardFrame->SetSize( siz2 );
}
//
@ -5231,12 +5151,10 @@ void AudacityProject::EditClipboardByLabel( EditDestFunction action )
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*msClipboard);
wxTheApp->AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
msClipT0 = regions.front().start;
msClipT1 = regions.back().end;
if (mHistoryWindow)
mHistoryWindow->UpdateDisplay();
}
@ -5567,14 +5485,6 @@ void AudacityProject::DoTrackMute(Track *t, bool exclusive)
{
HandleTrackMute(t, exclusive);
// Update mixer board, too.
MixerBoard* pMixerBoard = this->GetMixerBoard();
if (pMixerBoard)
{
pMixerBoard->UpdateMute(); // Update for all tracks.
pMixerBoard->UpdateSolo(); // Update for all tracks.
}
mTrackPanel->UpdateAccessibility();
mTrackPanel->Refresh(false);
}
@ -5583,14 +5493,6 @@ void AudacityProject::DoTrackSolo(Track *t, bool exclusive)
{
HandleTrackSolo(t, exclusive);
// Update mixer board, too.
MixerBoard* pMixerBoard = this->GetMixerBoard();
if (pMixerBoard)
{
pMixerBoard->UpdateMute(); // Update for all tracks.
pMixerBoard->UpdateSolo(); // Update for all tracks.
}
mTrackPanel->UpdateAccessibility();
mTrackPanel->Refresh(false);
}
@ -5639,15 +5541,6 @@ void AudacityProject::RemoveTrack(Track * toRemove)
wxString name = toRemove->GetName();
auto playable = dynamic_cast<PlayableTrack*>(toRemove);
if (playable)
{
// Update mixer board displayed tracks.
MixerBoard* pMixerBoard = this->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->RemoveTrackCluster(playable); // Will remove partner shown in same cluster.
}
auto channels = TrackList::Channels(toRemove);
// Be careful to post-increment over positions that get erased!
auto &iter = channels.first;
@ -6185,8 +6078,6 @@ void AudacityProject::SelectNone()
t->SetSelected(false);
mTrackPanel->Refresh(false);
if (mMixerBoard)
mMixerBoard->Refresh(false);
}
void AudacityProject::ZoomInByFactor( double ZoomFactor )

View File

@ -531,7 +531,6 @@ public:
LyricsWindow* GetLyricsWindow(bool create = false);
MixerBoardFrame* GetMixerBoardFrame(bool create = false);
MixerBoard* GetMixerBoard() { return mMixerBoard; }
HistoryWindow *GetHistoryWindow(bool create = false);
MacrosWindow *GetMacrosWindow(bool bExpanded, bool create = false);
FreqWindow *GetFreqWindow(bool create = false);
@ -601,13 +600,9 @@ public:
public:
void ModifyState(bool bWantsAutoSave); // if true, writes auto-save file. Should set only if you really want the state change restored after
// a crash, as it can take many seconds for large (eg. 10 track-hours) projects
void RecreateMixerBoard();
void PopState(const UndoState &state);
void UpdateLyrics();
void UpdateMixerBoard();
void GetRegionsByLabel( Regions &regions );
void AutoSave();

View File

@ -8,7 +8,6 @@
#include "Audacity.h"
#include "SelectionState.h"
#include "MixerBoard.h"
#include "ViewInfo.h"
#include "Track.h"
@ -34,10 +33,8 @@ void SelectionState::SelectTrackLength
viewInfo.selectedRegion.setTimes(minOffset, maxEnd);
}
void SelectionState::SelectTrack
( Track &track, bool selected, bool updateLastPicked,
MixerBoard *pMixerBoard )
void SelectionState::SelectTrack(
Track &track, bool selected, bool updateLastPicked )
{
bool wasCorrect = (selected == track.GetSelected());
@ -62,17 +59,10 @@ void SelectionState::SelectTrack
mLastPickedTrack.reset();
}
*/
// Update mixer board, but only as needed so it does not flicker.
if (!wasCorrect) {
auto pt = dynamic_cast< PlayableTrack* >( &track );
if (pMixerBoard && pt)
pMixerBoard->RefreshTrackCluster( pt );
}
}
void SelectionState::SelectRangeOfTracks
( TrackList &tracks, Track &rsTrack, Track &reTrack, MixerBoard *pMixerBoard )
( TrackList &tracks, Track &rsTrack, Track &reTrack )
{
Track *sTrack = &rsTrack, *eTrack = &reTrack;
// Swap the track pointers if needed
@ -81,17 +71,17 @@ void SelectionState::SelectRangeOfTracks
for (auto track :
tracks.Any().StartingWith(sTrack).EndingAfter(eTrack))
SelectTrack(*track, true, false, pMixerBoard);
SelectTrack(*track, true, false);
}
void SelectionState::SelectNone( TrackList &tracks, MixerBoard *pMixerBoard )
void SelectionState::SelectNone( TrackList &tracks )
{
for (auto t : tracks.Any())
SelectTrack( *t, false, false, pMixerBoard );
SelectTrack( *t, false, false );
}
void SelectionState::ChangeSelectionOnShiftClick
( TrackList &tracks, Track &track, MixerBoard *pMixerBoard )
( TrackList &tracks, Track &track )
{
// We will either extend from the first or from the last.
auto pExtendFrom = tracks.Lock(mLastPickedTrack);
@ -109,33 +99,30 @@ void SelectionState::ChangeSelectionOnShiftClick
pExtendFrom = Track::Pointer( *trackRange.rbegin() );
}
SelectNone( tracks, pMixerBoard );
SelectNone( tracks );
if( pExtendFrom )
SelectRangeOfTracks( tracks, track, *pExtendFrom, pMixerBoard );
SelectRangeOfTracks( tracks, track, *pExtendFrom );
else
SelectTrack( track, true, true, pMixerBoard );
SelectTrack( track, true, true );
mLastPickedTrack = pExtendFrom;
}
void SelectionState::HandleListSelection
( TrackList &tracks, ViewInfo &viewInfo,
Track &track, bool shift, bool ctrl, bool syncLocked, MixerBoard *pMixerBoard )
Track &track, bool shift, bool ctrl, bool syncLocked )
{
// AS: If the shift button is being held down, invert
// the selection on this track.
if (ctrl)
SelectTrack( track, !track.GetSelected(), true, pMixerBoard );
SelectTrack( track, !track.GetSelected(), true );
else {
if (shift && mLastPickedTrack.lock())
ChangeSelectionOnShiftClick( tracks, track, pMixerBoard );
ChangeSelectionOnShiftClick( tracks, track );
else {
SelectNone( tracks, pMixerBoard );
SelectTrack( track, true, true, pMixerBoard );
SelectNone( tracks );
SelectTrack( track, true, true );
SelectTrackLength( viewInfo, track, syncLocked );
}
if (pMixerBoard)
pMixerBoard->RefreshTrackClusters();
}
}

View File

@ -11,7 +11,6 @@
class Track;
class TrackList;
class MixerBoard;
class ViewInfo;
#include "MemoryX.h"
#include <vector>
@ -23,19 +22,17 @@ public:
static void SelectTrackLength
( ViewInfo &viewInfo, Track &track, bool syncLocked );
void SelectTrack
( Track &track,
bool selected, bool updateLastPicked, MixerBoard *pMixerBoard );
void SelectTrack(
Track &track, bool selected, bool updateLastPicked );
// Inclusive range of tracks, the limits specified in either order:
void SelectRangeOfTracks
( TrackList &tracks, Track &sTrack, Track &eTrack,
MixerBoard *pMixerBoard );
void SelectNone( TrackList &tracks, MixerBoard *pMixerBoard );
( TrackList &tracks, Track &sTrack, Track &eTrack );
void SelectNone( TrackList &tracks );
void ChangeSelectionOnShiftClick
( TrackList &tracks, Track &track, MixerBoard *pMixerBoard );
( TrackList &tracks, Track &track );
void HandleListSelection
( TrackList &tracks, ViewInfo &viewInfo, Track &track,
bool shift, bool ctrl, bool syncLocked, MixerBoard *pMixerBoard );
bool shift, bool ctrl, bool syncLocked );
private:
friend class SelectionStateChanger;

View File

@ -91,9 +91,22 @@ void Track::Init(const Track &orig)
mChannel = orig.mChannel;
}
void Track::SetName( const wxString &n )
{
if ( mName != n ) {
mName = n;
Notify();
}
}
void Track::SetSelected(bool s)
{
mSelected = s;
if (mSelected != s) {
mSelected = s;
auto pList = mList.lock();
if (pList)
pList->SelectionEvent( Pointer( this ) );
}
}
void Track::Merge(const Track &orig)
@ -328,6 +341,13 @@ bool Track::IsSyncLockSelected() const
return false;
}
void Track::Notify( int code )
{
auto pList = mList.lock();
if (pList)
pList->DataEvent( Pointer(this), code );
}
void Track::SyncLockAdjust(double oldT1, double newT1)
{
if (newT1 > oldT1) {
@ -367,6 +387,22 @@ void PlayableTrack::Merge( const Track &orig )
AudioTrack::Merge( *pOrig );
}
void PlayableTrack::SetMute( bool m )
{
if ( mMute != m ) {
mMute = m;
Notify();
}
}
void PlayableTrack::SetSolo( bool s )
{
if ( mSolo != s ) {
mSolo = s;
Notify();
}
}
// Serialize, not with tags of its own, but as attributes within a tag.
void PlayableTrack::WriteXMLAttributes(XMLWriter &xmlFile) const
{
@ -513,9 +549,12 @@ std::pair<Track *, Track *> TrackList::FindSyncLockGroup(Track *pMember) const
// is managing. Any other classes that may be interested in get these updates
// should use TrackList::Connect() or TrackList::Bind().
//
wxDEFINE_EVENT(EVT_TRACKLIST_PERMUTED, wxCommandEvent);
wxDEFINE_EVENT(EVT_TRACKLIST_RESIZING, wxCommandEvent);
wxDEFINE_EVENT(EVT_TRACKLIST_DELETION, wxCommandEvent);
wxDEFINE_EVENT(EVT_TRACKLIST_TRACK_DATA_CHANGE, TrackListEvent);
wxDEFINE_EVENT(EVT_TRACKLIST_SELECTION_CHANGE, TrackListEvent);
wxDEFINE_EVENT(EVT_TRACKLIST_PERMUTED, TrackListEvent);
wxDEFINE_EVENT(EVT_TRACKLIST_RESIZING, TrackListEvent);
wxDEFINE_EVENT(EVT_TRACKLIST_ADDITION, TrackListEvent);
wxDEFINE_EVENT(EVT_TRACKLIST_DELETION, TrackListEvent);
// same value as in the default constructed TrackId:
long TrackList::sCounter = -1;
@ -592,26 +631,42 @@ void TrackList::RecalcPositions(TrackNodePointer node)
UpdatePendingTracks();
}
void TrackList::SelectionEvent( const std::shared_ptr<Track> &pTrack )
{
// wxWidgets will own the event object
QueueEvent(
safenew TrackListEvent{ EVT_TRACKLIST_SELECTION_CHANGE, pTrack } );
}
void TrackList::DataEvent( const std::shared_ptr<Track> &pTrack, int code )
{
// wxWidgets will own the event object
QueueEvent(
safenew TrackListEvent{ EVT_TRACKLIST_TRACK_DATA_CHANGE, pTrack, code } );
}
void TrackList::PermutationEvent()
{
auto e = std::make_unique<wxCommandEvent>(EVT_TRACKLIST_PERMUTED);
// wxWidgets will own the event object
QueueEvent(e.release());
QueueEvent( safenew TrackListEvent{ EVT_TRACKLIST_PERMUTED } );
}
void TrackList::DeletionEvent()
{
auto e = std::make_unique<wxCommandEvent>(EVT_TRACKLIST_DELETION);
// wxWidgets will own the event object
QueueEvent(e.release());
QueueEvent( safenew TrackListEvent{ EVT_TRACKLIST_DELETION } );
}
void TrackList::AdditionEvent(TrackNodePointer node)
{
// wxWidgets will own the event object
QueueEvent( safenew TrackListEvent{ EVT_TRACKLIST_ADDITION, *node.first } );
}
void TrackList::ResizingEvent(TrackNodePointer node)
{
auto e = std::make_unique<TrackListEvent>(EVT_TRACKLIST_RESIZING);
e->mpTrack = *node.first;
// wxWidgets will own the event object
QueueEvent(e.release());
QueueEvent( safenew TrackListEvent{ EVT_TRACKLIST_RESIZING, *node.first } );
}
auto TrackList::EmptyRange() const
@ -678,7 +733,7 @@ Track *TrackList::Add(std::unique_ptr<TrackKind> &&t)
pTrack->SetOwner(mSelf, n);
pTrack->SetId( TrackId{ ++sCounter } );
RecalcPositions(n);
ResizingEvent(n);
AdditionEvent(n);
return back().get();
}
@ -700,7 +755,7 @@ Track *TrackList::AddToHead(std::unique_ptr<TrackKind> &&t)
pTrack->SetOwner(mSelf, n);
pTrack->SetId( TrackId{ ++sCounter } );
RecalcPositions(n);
ResizingEvent(n);
AdditionEvent(n);
return front().get();
}
@ -717,7 +772,7 @@ Track *TrackList::Add(std::shared_ptr<TrackKind> &&t)
t->SetOwner(mSelf, n);
t->SetId( TrackId{ ++sCounter } );
RecalcPositions(n);
ResizingEvent(n);
AdditionEvent(n);
return back().get();
}
@ -794,7 +849,7 @@ auto TrackList::Replace(Track * t, ListOfTracks::value_type &&with) ->
RecalcPositions(node);
DeletionEvent();
ResizingEvent(node);
AdditionEvent(node);
}
return holder;
}

View File

@ -205,8 +205,10 @@ class AUDACITY_DLL_API Track /* not final */
wxString mName;
wxString mDefaultName;
private:
bool mSelected;
protected:
bool mLinked;
bool mMinimized;
@ -367,7 +369,7 @@ private:
virtual void Merge(const Track &orig);
wxString GetName() const { return mName; }
void SetName( const wxString &n ) { mName = n; }
void SetName( const wxString &n );
wxString GetDefaultName() const { return mDefaultName; }
void SetDefaultName( const wxString &n ) { mDefaultName = n; }
@ -714,6 +716,11 @@ public:
// Checks if sync-lock is on and any track in its sync-lock group is selected.
bool IsSyncLockSelected() const;
// Send an event to listeners when state of the track changes
// To do: define values for the argument to distinguish different parts
// of the state, perhaps with wxNewId
void Notify( int code = -1 );
// An always-true predicate useful for defining iterators
bool Any() const;
@ -763,8 +770,8 @@ public:
bool GetMute () const { return mMute; }
bool GetSolo () const { return mSolo; }
void SetMute (bool m) { mMute = m; }
void SetSolo (bool s) { mSolo = s; }
void SetMute (bool m);
void SetSolo (bool s);
void Init( const PlayableTrack &init );
void Merge( const Track &init ) override;
@ -1086,31 +1093,50 @@ template <
* Clear, and Contains, plus serialization of the list of tracks.
*/
struct TrackListEvent : public wxCommandEvent
struct TrackListEvent : public wxEvent
{
TrackListEvent(wxEventType commandType = wxEVT_NULL, int winid = 0)
: wxCommandEvent{ commandType, winid } {}
explicit
TrackListEvent(
wxEventType commandType,
const std::weak_ptr<Track> &pTrack = {}, int code = -1)
: wxEvent{ commandType }
, mpTrack{ pTrack }
, mCode{ code }
{}
TrackListEvent( const TrackListEvent& ) = default;
wxEvent *Clone() const override { return new TrackListEvent(*this); }
std::weak_ptr<Track> mpTrack;
int mCode;
};
// Posted when the set of selected tracks changes.
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_TRACKLIST_SELECTION_CHANGE, TrackListEvent);
// Posted when certain fields of a track change.
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_TRACKLIST_TRACK_DATA_CHANGE, TrackListEvent);
// Posted when tracks are reordered but otherwise unchanged.
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_TRACKLIST_PERMUTED, wxCommandEvent);
EVT_TRACKLIST_PERMUTED, TrackListEvent);
// Posted when some track was added or changed its height.
// Cast to TrackListEvent and examine mpTrack to retrieve it.
// Posted when some track changed its height.
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_TRACKLIST_RESIZING, wxCommandEvent);
EVT_TRACKLIST_RESIZING, TrackListEvent);
// Posted when a track has been added to a tracklist.
// Also posted when one track replaces another
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_TRACKLIST_ADDITION, TrackListEvent);
// Posted when a track has been deleted from a tracklist.
// Also posted when one track replaces another
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_TRACKLIST_DELETION, wxCommandEvent);
EVT_TRACKLIST_DELETION, TrackListEvent);
class TrackList final : public wxEvtHandler, public ListOfTracks
{
@ -1495,8 +1521,11 @@ private:
}
void RecalcPositions(TrackNodePointer node);
void SelectionEvent( const std::shared_ptr<Track> &pTrack );
void PermutationEvent();
void DataEvent( const std::shared_ptr<Track> &pTrack, int code );
void DeletionEvent();
void AdditionEvent(TrackNodePointer node);
void ResizingEvent(TrackNodePointer node);
void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);

View File

@ -332,6 +332,9 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id,
mTracks->Bind(EVT_TRACKLIST_RESIZING,
&TrackPanel::OnTrackListResizing,
this);
mTracks->Bind(EVT_TRACKLIST_ADDITION,
&TrackPanel::OnTrackListResizing,
this);
mTracks->Bind(EVT_TRACKLIST_DELETION,
&TrackPanel::OnTrackListDeletion,
this);
@ -781,7 +784,7 @@ void TrackPanel::UpdateViewIfNoTracks()
}
}
void TrackPanel::OnPlayback(wxCommandEvent &e)
void TrackPanel::OnPlayback(wxEvent &e)
{
e.Skip();
// Starting or stopping of play or record affects some cursors.
@ -792,9 +795,9 @@ void TrackPanel::OnPlayback(wxCommandEvent &e)
// The tracks positions within the list have changed, so update the vertical
// ruler size for the track that triggered the event.
void TrackPanel::OnTrackListResizing(wxCommandEvent & e)
void TrackPanel::OnTrackListResizing(TrackListEvent & e)
{
auto t = static_cast<TrackListEvent&>(e).mpTrack.lock();
auto t = e.mpTrack.lock();
// A deleted track can trigger the event. In which case do nothing here.
if( t )
UpdateVRuler(t.get());
@ -802,7 +805,7 @@ void TrackPanel::OnTrackListResizing(wxCommandEvent & e)
}
// Tracks have been removed from the list.
void TrackPanel::OnTrackListDeletion(wxCommandEvent & e)
void TrackPanel::OnTrackListDeletion(wxEvent & e)
{
// copy shared_ptr for safety, as in HandleClick
auto handle = Target();

View File

@ -33,6 +33,7 @@ class LabelTrack;
class SpectrumAnalyst;
class Track;
class TrackList;
class TrackListEvent;
class TrackPanel;
class TrackArtist;
class Ruler;
@ -41,7 +42,6 @@ class AdornedRulerPanel;
class LWSlider;
class ControlToolBar; //Needed because state of controls can affect what gets drawn.
class ToolsToolBar; //Needed because state of controls can affect what gets drawn.
class MixerBoard;
class TrackPanelAx;
class TrackPanelCellIterator;
@ -257,9 +257,9 @@ class AUDACITY_DLL_API TrackPanel final : public CellularPanel {
void OnMouseEvent(wxMouseEvent & event);
void OnKeyDown(wxKeyEvent & event);
void OnPlayback(wxCommandEvent &);
void OnTrackListResizing(wxCommandEvent & event);
void OnTrackListDeletion(wxCommandEvent & event);
void OnPlayback(wxEvent &);
void OnTrackListResizing(TrackListEvent & event);
void OnTrackListDeletion(wxEvent & event);
void UpdateViewIfNoTracks(); // Call this to update mViewInfo, etc, after track(s) removal, before Refresh().
double GetMostRecentXPos();

View File

@ -38,6 +38,10 @@ UndoManager
#include <unordered_set>
wxDEFINE_EVENT(EVT_UNDO_PUSHED, wxCommandEvent);
wxDEFINE_EVENT(EVT_UNDO_MODIFIED, wxCommandEvent);
wxDEFINE_EVENT(EVT_UNDO_RESET, wxCommandEvent);
using ConstBlockFilePtr = const BlockFile*;
using Set = std::unordered_set<ConstBlockFilePtr>;
@ -245,6 +249,9 @@ void UndoManager::ModifyState(const TrackList * l,
stack[current]->state.selectedRegion = selectedRegion;
SonifyEndModifyState();
// wxWidgets will own the event object
QueueEvent( safenew wxCommandEvent{ EVT_UNDO_MODIFIED } );
}
void UndoManager::PushState(const TrackList * l,
@ -298,10 +305,12 @@ void UndoManager::PushState(const TrackList * l,
}
lastAction = longDescription;
// wxWidgets will own the event object
QueueEvent( safenew wxCommandEvent{ EVT_UNDO_PUSHED } );
}
const UndoState &UndoManager::SetStateTo
(unsigned int n, SelectedRegion *selectedRegion)
void UndoManager::SetStateTo(unsigned int n, const Consumer &consumer)
{
n -= 1;
@ -309,36 +318,36 @@ const UndoState &UndoManager::SetStateTo
current = n;
*selectedRegion = stack[current]->state.selectedRegion;
lastAction = wxT("");
mayConsolidate = false;
return stack[current]->state;
consumer( stack[current]->state );
// wxWidgets will own the event object
QueueEvent( safenew wxCommandEvent{ EVT_UNDO_RESET } );
}
const UndoState &UndoManager::Undo(SelectedRegion *selectedRegion)
void UndoManager::Undo(const Consumer &consumer)
{
wxASSERT(UndoAvailable());
current--;
*selectedRegion = stack[current]->state.selectedRegion;
lastAction = wxT("");
mayConsolidate = false;
return stack[current]->state;
consumer( stack[current]->state );
// wxWidgets will own the event object
QueueEvent( safenew wxCommandEvent{ EVT_UNDO_RESET } );
}
const UndoState &UndoManager::Redo(SelectedRegion *selectedRegion)
void UndoManager::Redo(const Consumer &consumer)
{
wxASSERT(RedoAvailable());
current++;
*selectedRegion = stack[current]->state.selectedRegion;
/*
if (!RedoAvailable()) {
*sel0 = stack[current]->sel0;
@ -355,7 +364,10 @@ const UndoState &UndoManager::Redo(SelectedRegion *selectedRegion)
lastAction = wxT("");
mayConsolidate = false;
return stack[current]->state;
consumer( stack[current]->state );
// wxWidgets will own the event object
QueueEvent( safenew wxCommandEvent{ EVT_UNDO_RESET } );
}
bool UndoManager::UnsavedChanges()

View File

@ -51,10 +51,24 @@
#include "MemoryX.h"
#include <vector>
#include <wx/event.h>
#include <wx/string.h>
#include "ondemand/ODTaskThread.h"
#include "SelectedRegion.h"
// Events emitted by UndoManager for the use of listeners
// Project state did not change, but a new state was copied into Undo history
// and any redo states were lost
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_UNDO_PUSHED, wxCommandEvent);
// Project state did not change, but current state was modified in Undo history
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_UNDO_MODIFIED, wxCommandEvent);
// Project state changed because of undo or redo or rollback; undo manager
// contents did not change other than the pointer to current state
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_UNDO_RESET, wxCommandEvent);
class Tags;
class Track;
class TrackList;
@ -90,7 +104,7 @@ inline UndoPush operator | (UndoPush a, UndoPush b)
inline UndoPush operator & (UndoPush a, UndoPush b)
{ return static_cast<UndoPush>(static_cast<int>(a) & static_cast<int>(b)); }
class AUDACITY_DLL_API UndoManager {
class AUDACITY_DLL_API UndoManager : public wxEvtHandler {
public:
UndoManager();
~UndoManager();
@ -118,9 +132,12 @@ class AUDACITY_DLL_API UndoManager {
wxLongLong_t GetLongDescription(unsigned int n, wxString *desc, wxString *size);
void SetLongDescription(unsigned int n, const wxString &desc);
const UndoState &SetStateTo(unsigned int n, SelectedRegion *selectedRegion);
const UndoState &Undo(SelectedRegion *selectedRegion);
const UndoState &Redo(SelectedRegion *selectedRegion);
// These functions accept a callback that uses the state,
// and then they emit EVT_UNDO_RESET when that has finished.
using Consumer = std::function< void( const UndoState & ) >;
void SetStateTo(unsigned int n, const Consumer &consumer);
void Undo(const Consumer &consumer);
void Redo(const Consumer &consumer);
bool UndoAvailable();
bool RedoAvailable();

View File

@ -422,7 +422,10 @@ float WaveTrack::GetGain() const
void WaveTrack::SetGain(float newGain)
{
mGain = newGain;
if (mGain != newGain) {
mGain = newGain;
Notify();
}
}
float WaveTrack::GetPan() const
@ -433,11 +436,14 @@ float WaveTrack::GetPan() const
void WaveTrack::SetPan(float newPan)
{
if (newPan > 1.0)
mPan = 1.0;
newPan = 1.0;
else if (newPan < -1.0)
mPan = -1.0;
else
newPan = -1.0;
if ( mPan != newPan ) {
mPan = newPan;
Notify();
}
}
float WaveTrack::GetChannelGain(int channel) const

View File

@ -1,8 +1,7 @@
#include "../AdornedRulerPanel.h"
#include "../HistoryWindow.h"
#include "../AudacityApp.h" // for EVT_CLIPBOARD_CHANGE
#include "../LabelTrack.h"
#include "../Menus.h"
#include "../MixerBoard.h"
#include "../NoteTrack.h"
#include "../Prefs.h"
#include "../Project.h"
@ -219,8 +218,6 @@ void DoUndo(AudacityProject &project)
{
auto trackPanel = project.GetTrackPanel();
auto &undoManager = *project.GetUndoManager();
auto &selectedRegion = project.GetViewInfo().selectedRegion;
auto mixerBoard = project.GetMixerBoard();
auto historyWindow = project.GetHistoryWindow();
if (!project.UndoAvailable()) {
@ -233,20 +230,13 @@ void DoUndo(AudacityProject &project)
return;
}
const UndoState &state = undoManager.Undo(&selectedRegion);
project.PopState(state);
undoManager.Undo(
[&]( const UndoState &state ){ project.PopState( state ); } );
trackPanel->EnsureVisible(trackPanel->GetFirstSelectedTrack());
project.RedrawProject();
if (historyWindow)
historyWindow->UpdateDisplay();
if (mixerBoard)
// Mixer board may need to change for selection state and pan/gain
mixerBoard->Refresh();
MenuManager::ModifyUndoMenuItems(project);
}
@ -264,8 +254,6 @@ void OnRedo(const CommandContext &context)
auto &project = context.project;
auto trackPanel = project.GetTrackPanel();
auto &undoManager = *project.GetUndoManager();
auto &selectedRegion = project.GetViewInfo().selectedRegion;
auto mixerBoard = project.GetMixerBoard();
auto historyWindow = project.GetHistoryWindow();
if (!project.RedoAvailable()) {
@ -277,20 +265,13 @@ void OnRedo(const CommandContext &context)
return;
}
const UndoState &state = undoManager.Redo(&selectedRegion);
project.PopState(state);
undoManager.Redo(
[&]( const UndoState &state ){ project.PopState( state ); } );
trackPanel->EnsureVisible(trackPanel->GetFirstSelectedTrack());
project.RedrawProject();
if (historyWindow)
historyWindow->UpdateDisplay();
if (mixerBoard)
// Mixer board may need to change for selection state and pan/gain
mixerBoard->Refresh();
MenuManager::ModifyUndoMenuItems(project);
}
@ -337,6 +318,7 @@ void OnCut(const CommandContext &context)
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*AudacityProject::msClipboard);
wxTheApp->AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
// Proceed to change the project. If this throws, the project will be
// rolled back by the top level handler.
@ -377,9 +359,6 @@ void OnCut(const CommandContext &context)
ruler->DrawOverlays( true );
project.RedrawProject();
if (historyWindow)
historyWindow->UpdateDisplay();
}
void OnDelete(const CommandContext &context)
@ -416,6 +395,7 @@ void OnCopy(const CommandContext &context)
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*AudacityProject::msClipboard);
wxTheApp->AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
AudacityProject::msClipT0 = selectedRegion.t0();
AudacityProject::msClipT1 = selectedRegion.t1();
@ -423,9 +403,6 @@ void OnCopy(const CommandContext &context)
//Make sure the menus/toolbar states get updated
trackPanel->Refresh(false);
if (historyWindow)
historyWindow->UpdateDisplay();
}
void OnPaste(const CommandContext &context)
@ -756,6 +733,7 @@ void OnSplitCut(const CommandContext &context)
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*AudacityProject::msClipboard);
wxTheApp->AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
AudacityProject::msClipT0 = selectedRegion.t0();
AudacityProject::msClipT1 = selectedRegion.t1();
@ -764,9 +742,6 @@ void OnSplitCut(const CommandContext &context)
project.PushState(_("Split-cut to the clipboard"), _("Split Cut"));
project.RedrawProject();
if (historyWindow)
historyWindow->UpdateDisplay();
}
void OnSplitDelete(const CommandContext &context)

View File

@ -84,7 +84,6 @@ void DoPrevTrack(
auto trackPanel = project.GetTrackPanel();
auto tracks = project.GetTracks();
auto &selectionState = project.GetSelectionState();
auto mixerBoard = project.GetMixerBoard();
Track* t = trackPanel->GetFocusedTrack();
if( t == NULL ) // if there isn't one, focus on last
@ -121,7 +120,7 @@ void DoPrevTrack(
if( tSelected && pSelected )
{
selectionState.SelectTrack
( *t, false, false, mixerBoard );
( *t, false, false );
trackPanel->SetFocusedTrack( p ); // move focus to next track up
trackPanel->EnsureVisible( p );
project.ModifyState(false);
@ -130,7 +129,7 @@ void DoPrevTrack(
if( tSelected && !pSelected )
{
selectionState.SelectTrack
( *p, true, false, mixerBoard );
( *p, true, false );
trackPanel->SetFocusedTrack( p ); // move focus to next track up
trackPanel->EnsureVisible( p );
project.ModifyState(false);
@ -139,7 +138,7 @@ void DoPrevTrack(
if( !tSelected && pSelected )
{
selectionState.SelectTrack
( *p, false, false, mixerBoard );
( *p, false, false );
trackPanel->SetFocusedTrack( p ); // move focus to next track up
trackPanel->EnsureVisible( p );
project.ModifyState(false);
@ -148,7 +147,7 @@ void DoPrevTrack(
if( !tSelected && !pSelected )
{
selectionState.SelectTrack
( *t, true, false, mixerBoard );
( *t, true, false );
trackPanel->SetFocusedTrack( p ); // move focus to next track up
trackPanel->EnsureVisible( p );
project.ModifyState(false);
@ -195,7 +194,6 @@ void DoNextTrack(
auto trackPanel = project.GetTrackPanel();
auto tracks = project.GetTracks();
auto &selectionState = project.GetSelectionState();
auto mixerBoard = project.GetMixerBoard();
auto t = trackPanel->GetFocusedTrack(); // Get currently focused track
if( t == NULL ) // if there isn't one, focus on first
@ -226,7 +224,7 @@ void DoNextTrack(
if( tSelected && nSelected )
{
selectionState.SelectTrack
( *t, false, false, mixerBoard );
( *t, false, false );
trackPanel->SetFocusedTrack( n ); // move focus to next track down
trackPanel->EnsureVisible( n );
project.ModifyState(false);
@ -235,7 +233,7 @@ void DoNextTrack(
if( tSelected && !nSelected )
{
selectionState.SelectTrack
( *n, true, false, mixerBoard );
( *n, true, false );
trackPanel->SetFocusedTrack( n ); // move focus to next track down
trackPanel->EnsureVisible( n );
project.ModifyState(false);
@ -244,7 +242,7 @@ void DoNextTrack(
if( !tSelected && nSelected )
{
selectionState.SelectTrack
( *n, false, false, mixerBoard );
( *n, false, false );
trackPanel->SetFocusedTrack( n ); // move focus to next track down
trackPanel->EnsureVisible( n );
project.ModifyState(false);
@ -253,7 +251,7 @@ void DoNextTrack(
if( !tSelected && !nSelected )
{
selectionState.SelectTrack
( *t, true, false, mixerBoard );
( *t, true, false );
trackPanel->SetFocusedTrack( n ); // move focus to next track down
trackPanel->EnsureVisible( n );
project.ModifyState(false);
@ -506,7 +504,6 @@ void OnToggle(const CommandContext &context)
auto &project = context.project;
auto trackPanel = project.GetTrackPanel();
auto &selectionState = project.GetSelectionState();
auto mixerBoard = project.GetMixerBoard();
Track *t;
@ -515,7 +512,7 @@ void OnToggle(const CommandContext &context)
return;
selectionState.SelectTrack
( *t, !t->GetSelected(), true, mixerBoard );
( *t, !t->GetSelected(), true );
trackPanel->EnsureVisible( t );
project.ModifyState(false);

View File

@ -3,7 +3,6 @@
#include "../Experimental.h"
#include "../FreqWindow.h"
#include "../Menus.h" // for PrefsListener
#include "../MixerBoard.h"
#include "../Prefs.h"
#include "../Project.h"
#include "../TimeDialog.h"
@ -23,7 +22,6 @@ void DoSelectTimeAndTracks
auto tracks = project.GetTracks();
auto trackPanel = project.GetTrackPanel();
auto &selectedRegion = project.GetViewInfo().selectedRegion;
auto mixerBoard = project.GetMixerBoard();
if( bAllTime )
selectedRegion.setTimes(
@ -35,8 +33,6 @@ void DoSelectTimeAndTracks
project.ModifyState(false);
trackPanel->Refresh(false);
if (mixerBoard)
mixerBoard->Refresh(false);
}
}
@ -467,11 +463,10 @@ void DoListSelection
auto &selectionState = project.GetSelectionState();
auto &viewInfo = project.GetViewInfo();
auto isSyncLocked = project.IsSyncLocked();
auto mixerBoard = project.GetMixerBoard();
selectionState.HandleListSelection
( *tracks, viewInfo, *t,
shift, ctrl, isSyncLocked, mixerBoard );
shift, ctrl, isSyncLocked );
if (! ctrl )
trackPanel->SetFocusedTrack(t);
@ -535,7 +530,6 @@ void OnSelectSyncLockSel(const CommandContext &context)
auto &project = context.project;
auto tracks = project.GetTracks();
auto trackPanel = project.GetTrackPanel();
auto mixerBoard = project.GetMixerBoard();
bool selected = false;
for (auto t : tracks->Any()
@ -548,8 +542,6 @@ void OnSelectSyncLockSel(const CommandContext &context)
project.ModifyState(false);
trackPanel->Refresh(false);
if (mixerBoard)
mixerBoard->Refresh(false);
}
//this pops up a dialog which allows the left selection to be set.

View File

@ -3,7 +3,7 @@
#include "../LabelTrack.h"
#include "../Menus.h"
#include "../Mix.h"
#include "../MixerBoard.h"
#include "../Prefs.h"
#include "../Project.h"
#include "../ShuttleGui.h"
@ -13,6 +13,7 @@
#include "../WaveTrack.h"
#include "../commands/CommandContext.h"
#include "../commands/CommandManager.h"
#include "../widgets/ASlider.h"
#include <wx/combobox.h>
@ -103,7 +104,6 @@ void DoMixAndRender
void DoPanTracks(AudacityProject &project, float PanValue)
{
auto tracks = project.GetTracks();
auto mixerBoard = project.GetMixerBoard();
// count selected wave tracks
const auto range = tracks->Any< WaveTrack >();
@ -115,8 +115,6 @@ void DoPanTracks(AudacityProject &project, float PanValue)
left->SetPan( PanValue );
project.RedrawProject();
if (mixerBoard)
mixerBoard->UpdatePan();
auto flags = UndoPush::AUTOSAVE;
/*i18n-hint: One or more audio tracks have been panned*/
@ -515,7 +513,6 @@ void DoRemoveTracks( AudacityProject &project )
{
auto tracks = project.GetTracks();
auto trackPanel = project.GetTrackPanel();
auto mixerBoard = project.GetMixerBoard();
std::vector<Track*> toRemove;
for (auto track : tracks->Selected())
@ -528,10 +525,6 @@ void DoRemoveTracks( AudacityProject &project )
f = *--found;
}
if (mixerBoard)
for (auto track : tracks->Selected<PlayableTrack>())
mixerBoard->RemoveTrackCluster(track);
for (auto track : toRemove)
tracks->Remove(track);
@ -554,9 +547,6 @@ void DoRemoveTracks( AudacityProject &project )
trackPanel->UpdateViewIfNoTracks();
trackPanel->Refresh(false);
if (mixerBoard)
mixerBoard->Refresh(true);
}
void DoMoveTrack
@ -564,11 +554,9 @@ void DoMoveTrack
{
auto trackPanel = project.GetTrackPanel();
auto tracks = project.GetTracks();
auto mixerBoard = project.GetMixerBoard(); // Update mixer board.
wxString longDesc, shortDesc;
auto pt = dynamic_cast<PlayableTrack*>(target);
switch (choice)
{
case OnMoveTopID:
@ -576,32 +564,27 @@ void DoMoveTrack
longDesc = _("Moved '%s' to Top");
shortDesc = _("Move Track to Top");
while (tracks->CanMoveUp(target)) {
if (tracks->Move(target, true)) {
if (mixerBoard && pt)
mixerBoard->MoveTrackCluster(pt, true);
}
}
// TODO: write TrackList::Rotate to do this in one step and avoid emitting
// an event for each swap
while (tracks->CanMoveUp(target))
tracks->Move(target, true);
break;
case OnMoveBottomID:
/* i18n-hint: Past tense of 'to move', as in 'moved audio track up'.*/
longDesc = _("Moved '%s' to Bottom");
shortDesc = _("Move Track to Bottom");
while (tracks->CanMoveDown(target)) {
if(tracks->Move(target, false)) {
if (mixerBoard && pt)
mixerBoard->MoveTrackCluster(pt, false);
}
}
// TODO: write TrackList::Rotate to do this in one step and avoid emitting
// an event for each swap
while (tracks->CanMoveDown(target))
tracks->Move(target, false);
break;
default:
bool bUp = (OnMoveUpID == choice);
if (tracks->Move(target, bUp)) {
if (mixerBoard && pt)
mixerBoard->MoveTrackCluster(pt, bUp);
}
tracks->Move(target, bUp);
longDesc =
/* i18n-hint: Past tense of 'to move', as in 'moved audio track up'.*/
bUp? _("Moved '%s' Up")
@ -847,7 +830,6 @@ void OnMuteAllTracks(const CommandContext &context)
auto tracks = project.GetTracks();
auto soloSimple = project.IsSoloSimple();
auto soloNone = project.IsSoloNone();
auto mixerBoard = project.GetMixerBoard();
for (auto pt : tracks->Any<PlayableTrack>())
{
@ -858,11 +840,6 @@ void OnMuteAllTracks(const CommandContext &context)
project.ModifyState(true);
project.RedrawProject();
if (mixerBoard) {
mixerBoard->UpdateMute();
if (soloSimple || soloNone)
mixerBoard->UpdateSolo();
}
}
void OnUnmuteAllTracks(const CommandContext &context)
@ -871,7 +848,6 @@ void OnUnmuteAllTracks(const CommandContext &context)
auto tracks = project.GetTracks();
auto soloSimple = project.IsSoloSimple();
auto soloNone = project.IsSoloNone();
auto mixerBoard = project.GetMixerBoard();
for (auto pt : tracks->Any<PlayableTrack>())
{
@ -882,11 +858,6 @@ void OnUnmuteAllTracks(const CommandContext &context)
project.ModifyState(true);
project.RedrawProject();
if (mixerBoard) {
mixerBoard->UpdateMute();
if (soloSimple || soloNone)
mixerBoard->UpdateSolo();
}
}
void OnPanLeft(const CommandContext &context)

View File

@ -191,7 +191,6 @@ void OnHistory(const CommandContext &context)
auto historyWindow = project.GetHistoryWindow(true);
historyWindow->Show();
historyWindow->Raise();
historyWindow->UpdateDisplay();
}
void OnKaraoke(const CommandContext &context)
@ -200,7 +199,6 @@ void OnKaraoke(const CommandContext &context)
auto lyricsWindow = project.GetLyricsWindow(true);
lyricsWindow->Show();
project.UpdateLyrics();
lyricsWindow->Raise();
}

View File

@ -95,15 +95,12 @@ UIHandle::Result LabelTextHandle::Click
if (!done) {
//otherwise, select all tracks
for (auto t : tracks->Any())
selectionState.SelectTrack
( *t, true, true, pProject->GetMixerBoard() );
selectionState.SelectTrack( *t, true, true );
}
// Do this after, for its effect on TrackPanel's memory of last selected
// track (which affects shift-click actions)
selectionState.SelectTrack
( *pLT, true, true,
pProject->GetMixerBoard() );
selectionState.SelectTrack( *pLT, true, true );
}
// PRL: bug1659 -- make selection change undo correctly

View File

@ -14,7 +14,6 @@
#ifdef EXPERIMENTAL_MIDI_OUT
#include "../../../../HitTestResult.h"
#include "../../../../MixerBoard.h"
#include "../../../../Project.h"
#include "../../../../RefreshCode.h"
#include "../../../../TrackPanel.h" // for TrackInfo
@ -51,10 +50,6 @@ UIHandle::Result VelocitySliderHandle::SetValue
if (pTrack) {
pTrack->SetVelocity(newValue);
MixerBoard *const pMixerBoard = pProject->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->UpdateVelocity(pTrack.get());
}
return RefreshCode::RefreshCell;

View File

@ -16,7 +16,6 @@ Paul Licameli split from TrackPanel.cpp
#include "../../../../AudioIO.h"
#include "../../../../HitTestResult.h"
#include "../../../../MixerBoard.h"
#include "../../../../Menus.h"
#include "../../../../Project.h"
#include "../../../../RefreshCode.h"
@ -944,10 +943,6 @@ void WaveTrackMenuTable::OnSwapChannels(wxCommandEvent &)
tracks->MoveUp( partner );
tracks->GroupChannels( *partner, 2 );
MixerBoard* pMixerBoard = project->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->UpdateTrackClusters();
if (hasFocus)
project->GetTrackPanel()->SetFocusedTrack(partner);

View File

@ -12,7 +12,6 @@ Paul Licameli split from TrackPanel.cpp
#include "WaveTrackSliderHandles.h"
#include "../../../../HitTestResult.h"
#include "../../../../MixerBoard.h"
#include "../../../../Project.h"
#include "../../../../RefreshCode.h"
#include "../../../../TrackPanel.h"
@ -50,10 +49,6 @@ UIHandle::Result GainSliderHandle::SetValue
for (auto channel :
TrackList::Channels(pTrack.get()))
channel->SetGain(newValue);
MixerBoard *const pMixerBoard = pProject->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->UpdateGain(pTrack.get());
}
return RefreshCode::RefreshNone;
@ -131,10 +126,6 @@ UIHandle::Result PanSliderHandle::SetValue(AudacityProject *pProject, float newV
for (auto channel :
TrackList::Channels(pTrack.get()))
channel->SetPan(newValue);
MixerBoard *const pMixerBoard = pProject->GetMixerBoard();
if (pMixerBoard)
pMixerBoard->UpdatePan(pTrack.get());
}
return result;

View File

@ -50,8 +50,7 @@ public:
// AS: If the user clicked outside all tracks, make nothing
// selected.
if ((event.ButtonDown() || event.ButtonDClick())) {
pProject->GetSelectionState().SelectNone
( *pProject->GetTracks(), pProject->GetMixerBoard() );
pProject->GetSelectionState().SelectNone( *pProject->GetTracks() );
result |= RefreshAll;
}

View File

@ -18,7 +18,6 @@ Paul Licameli split from TrackPanel.cpp
#include "../../FreqWindow.h"
#include "../../HitTestResult.h"
#include "../../Menus.h"
#include "../../MixerBoard.h"
#include "../../NumberScale.h"
#include "../../Project.h"
#include "../../RefreshCode.h"
@ -561,10 +560,9 @@ UIHandle::Result SelectHandle::Click
TrackList *const trackList = pProject->GetTracks();
// Deselect all other tracks and select this one.
selectionState.SelectNone( *trackList, pProject->GetMixerBoard() );
selectionState.SelectNone( *trackList );
selectionState.SelectTrack
( *pTrack, true, true, pProject->GetMixerBoard() );
selectionState.SelectTrack( *pTrack, true, true );
// Default behavior: select whole track
SelectionState::SelectTrackLength
@ -599,8 +597,6 @@ UIHandle::Result SelectHandle::Click
bool bShiftDown = event.ShiftDown();
bool bCtrlDown = event.ControlDown();
auto pMixerBoard = pProject->GetMixerBoard();
mSelStart = mUseSnap ? mSnapStart.outTime : mSnapStart.timeSnappedTime;
auto xx = viewInfo.TimeToPosition(mSelStart, mRect.x);
@ -608,7 +604,7 @@ UIHandle::Result SelectHandle::Click
if (bShiftDown || bCtrlDown) {
if (bShiftDown)
selectionState.ChangeSelectionOnShiftClick
( *trackList, *pTrack, pMixerBoard );
( *trackList, *pTrack );
if( bCtrlDown ){
//Commented out bIsSelected toggles, as in Track Control Panel.
//bool bIsSelected = pTrack->GetSelected();
@ -616,8 +612,7 @@ UIHandle::Result SelectHandle::Click
bool bIsSelected = false;
// Don't toggle away the last selected track.
if( !bIsSelected || trackPanel->GetSelectedTrackCount() > 1 )
selectionState.SelectTrack
( *pTrack, !bIsSelected, true, pMixerBoard );
selectionState.SelectTrack( *pTrack, !bIsSelected, true );
}
double value;
@ -767,13 +762,12 @@ UIHandle::Result SelectHandle::Click
if (startNewSelection) {
// If we didn't move a selection boundary, start a NEW selection
selectionState.SelectNone( *trackList, pMixerBoard );
selectionState.SelectNone( *trackList );
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
StartFreqSelection (viewInfo, event.m_y, mRect.y, mRect.height, pTrack);
#endif
StartSelection(pProject);
selectionState.SelectTrack
( *pTrack, true, true, pMixerBoard );
selectionState.SelectTrack( *pTrack, true, true );
trackPanel->SetFocusedTrack(pTrack);
//On-Demand: check to see if there is an OD thing associated with this track.
pTrack->TypeSwitch( [&](WaveTrack *wt) {
@ -844,11 +838,9 @@ UIHandle::Result SelectHandle::Drag
Track *sTrack = pTrack.get();
Track *eTrack = clickedTrack.get();
auto trackList = pProject->GetTracks();
auto pMixerBoard = pProject->GetMixerBoard();
if ( sTrack && eTrack && !event.ControlDown() ) {
auto &selectionState = pProject->GetSelectionState();
selectionState.SelectRangeOfTracks
( *trackList, *sTrack, *eTrack, pMixerBoard );
selectionState.SelectRangeOfTracks( *trackList, *sTrack, *eTrack );
}
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
@ -1013,10 +1005,6 @@ UIHandle::Result SelectHandle::Cancel(AudacityProject *pProject)
mSelectionStateChanger.reset();
pProject->GetViewInfo().selectedRegion = mInitialSelection;
// Refresh mixer board for change of set of selected tracks
if (MixerBoard* pMixerBoard = pProject->GetMixerBoard())
pMixerBoard->Refresh();
return RefreshCode::RefreshAll;
}

View File

@ -15,7 +15,6 @@ Paul Licameli split from TrackPanel.cpp
#include "../../HitTestResult.h"
#include "../../RefreshCode.h"
#include "../../Menus.h"
#include "../../MixerBoard.h"
#include "../../Project.h"
#include "../../TrackPanel.h" // for TrackInfo
#include "../../TrackPanelMouseEvent.h"
@ -214,11 +213,6 @@ void TrackMenuTable::OnSetName(wxCommandEvent &)
for (auto channel : TrackList::Channels(pTrack))
channel->SetName(newName);
MixerBoard *const pMixerBoard = proj->GetMixerBoard();
auto pt = dynamic_cast<PlayableTrack*>(pTrack);
if (pt && pMixerBoard)
pMixerBoard->UpdateName(pt);
proj->PushState(wxString::Format(_("Renamed '%s' to '%s'"),
oldName,
newName),

View File

@ -14,7 +14,6 @@ Paul Licameli split from TrackPanel.cpp
#include "../../Experimental.h"
#include "../../HitTestResult.h"
#include "../../Menus.h"
#include "../../MixerBoard.h"
#include "../../Project.h"
#include "../../RefreshCode.h"
#include "../../TrackPanel.h"
@ -123,21 +122,14 @@ UIHandle::Result TrackSelectHandle::Drag
if (unsafe)
return result;
MixerBoard* pMixerBoard = pProject->GetMixerBoard(); // Update mixer board, too.
if (event.m_y < mMoveUpThreshold || event.m_y < 0) {
tracks->MoveUp(mpTrack.get());
--mRearrangeCount;
if (pMixerBoard)
if(auto pPlayable = dynamic_cast< const PlayableTrack* >( mpTrack.get() ))
pMixerBoard->MoveTrackCluster(pPlayable, true /* up */);
}
else if ( event.m_y > mMoveDownThreshold
|| event.m_y > evt.whole.GetHeight() ) {
tracks->MoveDown(mpTrack.get());
++mRearrangeCount;
if (pMixerBoard)
if(auto pPlayable = dynamic_cast< const PlayableTrack* >( mpTrack.get() ))
pMixerBoard->MoveTrackCluster(pPlayable, false /* down */);
}
else
return result;