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:
commit
70fff4b28b
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
16
src/Lyrics.h
16
src/Lyrics.h
@ -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()
|
||||
};
|
||||
|
||||
|
@ -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())
|
||||
//{
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
119
src/Project.cpp
119
src/Project.cpp
@ -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 )
|
||||
|
@ -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 ®ions );
|
||||
|
||||
void AutoSave();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
51
src/Track.h
51
src/Track.h
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user