mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-05 14:18:53 +02:00
317 lines
9.0 KiB
C++
317 lines
9.0 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
MixerBoard.h
|
|
|
|
Vaughan Johnson, January 2007
|
|
|
|
**********************************************************************/
|
|
|
|
#include "Experimental.h"
|
|
|
|
#ifndef __AUDACITY_MIXER_BOARD__
|
|
#define __AUDACITY_MIXER_BOARD__
|
|
|
|
#include <wx/frame.h>
|
|
#include <wx/bmpbuttn.h>
|
|
#include <wx/hashmap.h>
|
|
#include <wx/image.h>
|
|
#include <wx/panel.h>
|
|
#include <wx/scrolwin.h>
|
|
#include <wx/statbmp.h>
|
|
#include <wx/stattext.h>
|
|
|
|
#include "widgets/AButton.h"
|
|
#include "widgets/ASlider.h"
|
|
#include "widgets/Meter.h"
|
|
|
|
// containment hierarchy:
|
|
// MixerBoardFrame -> MixerBoard -> MixerBoardScrolledWindow -> MixerTrackCluster(s)
|
|
|
|
|
|
// MixerTrackSlider is a subclass just to override OnMouseEvent,
|
|
// so we can know when adjustment ends, so we can PushState only then.
|
|
class MixerTrackSlider : public ASlider
|
|
{
|
|
public:
|
|
MixerTrackSlider(wxWindow * parent,
|
|
wxWindowID id,
|
|
wxString name,
|
|
const wxPoint & pos,
|
|
const wxSize & size,
|
|
int style = FRAC_SLIDER,
|
|
bool popup = true,
|
|
bool canUseShift = true,
|
|
float stepValue = STEP_CONTINUOUS,
|
|
int orientation = wxHORIZONTAL);
|
|
virtual ~MixerTrackSlider() {};
|
|
|
|
void OnMouseEvent(wxMouseEvent & event);
|
|
|
|
protected:
|
|
bool mIsPan;
|
|
|
|
public:
|
|
DECLARE_EVENT_TABLE()
|
|
};
|
|
|
|
|
|
class AudacityProject;
|
|
class MixerBoard;
|
|
#ifdef EXPERIMENTAL_MIDI_OUT
|
|
class Track;
|
|
class NoteTrack;
|
|
#endif
|
|
class WaveTrack;
|
|
|
|
class MixerTrackCluster : public wxPanel
|
|
{
|
|
public:
|
|
MixerTrackCluster(wxWindow* parent,
|
|
MixerBoard* grandParent, AudacityProject* project,
|
|
WaveTrack* pLeftTrack, WaveTrack* pRightTrack = NULL,
|
|
const wxPoint& pos = wxDefaultPosition,
|
|
const wxSize& size = wxDefaultSize);
|
|
virtual ~MixerTrackCluster() {};
|
|
|
|
void HandleResize(); // For wxSizeEvents, update gain slider and meter.
|
|
|
|
void HandleSliderGain(const bool bWantPushState = false);
|
|
void HandleSliderPan(const bool bWantPushState = false);
|
|
|
|
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();
|
|
void UpdateMeter(const double t0, const double t1);
|
|
|
|
private:
|
|
wxColour GetTrackColor();
|
|
|
|
// event handlers
|
|
void HandleSelect(const bool bShiftDown);
|
|
|
|
void OnKeyEvent(wxKeyEvent& event);
|
|
void OnMouseEvent(wxMouseEvent& event);
|
|
void OnPaint(wxPaintEvent& evt);
|
|
|
|
void OnButton_MusicalInstrument(wxCommandEvent& event);
|
|
void OnSlider_Gain(wxCommandEvent& event);
|
|
void OnSlider_Pan(wxCommandEvent& event);
|
|
void OnButton_Mute(wxCommandEvent& event);
|
|
void OnButton_Solo(wxCommandEvent& event);
|
|
//v void OnSliderScroll_Gain(wxScrollEvent& event);
|
|
|
|
public:
|
|
#ifdef EXPERIMENTAL_MIDI_OUT
|
|
// mTrack is redundant, but simplifies code that operates on either
|
|
// mLeftTrack or mNoteTrack.
|
|
Track* mTrack; // either mLeftTrack or mNoteTrack, whichever is not NULL
|
|
#endif
|
|
WaveTrack* mLeftTrack; // NULL if Note Track
|
|
WaveTrack* mRightTrack; // NULL if mono
|
|
|
|
//vvv Vaughan, 2010-11-05:
|
|
// I suggest that when this is no longer experimental, rather than all these #ifdef's,
|
|
// this be done by factoring, i.e., add two subclasses to MixerTrackCluster,
|
|
// MixerNoteTrackCluster and MixerWaveTrackCluster, such that all the common
|
|
// code is in the parent, and these #ifdef's are only around
|
|
// MixerNoteTrackCluster rather than sprinkled throughout MixerTrackCluster.
|
|
#ifdef EXPERIMENTAL_MIDI_OUT
|
|
NoteTrack* mNoteTrack; // NULL if Wave Track
|
|
#endif
|
|
|
|
private:
|
|
MixerBoard* mMixerBoard;
|
|
AudacityProject* mProject;
|
|
|
|
// controls
|
|
wxStaticText* mStaticText_TrackName;
|
|
wxBitmapButton* mBitmapButton_MusicalInstrument;
|
|
AButton* mToggleButton_Mute;
|
|
AButton* mToggleButton_Solo;
|
|
MixerTrackSlider* mSlider_Pan;
|
|
MixerTrackSlider* mSlider_Gain;
|
|
Meter* mMeter;
|
|
|
|
public:
|
|
DECLARE_EVENT_TABLE()
|
|
};
|
|
|
|
WX_DEFINE_ARRAY(MixerTrackCluster*, MixerTrackClusterArray);
|
|
|
|
|
|
class MusicalInstrument
|
|
{
|
|
public:
|
|
MusicalInstrument(wxBitmap* pBitmap, const wxString strXPMfilename);
|
|
virtual ~MusicalInstrument();
|
|
|
|
wxBitmap* mBitmap;
|
|
wxArrayString mKeywords;
|
|
};
|
|
WX_DECLARE_OBJARRAY(MusicalInstrument, MusicalInstrumentArray);
|
|
|
|
|
|
|
|
// wxScrolledWindow ignores mouse clicks in client area,
|
|
// but they don't get passed to Mixerboard.
|
|
// We need to catch them to deselect all track clusters.
|
|
class MixerBoardScrolledWindow : public wxScrolledWindow
|
|
{
|
|
public:
|
|
MixerBoardScrolledWindow(AudacityProject* project,
|
|
MixerBoard* parent, wxWindowID id = -1,
|
|
const wxPoint& pos = wxDefaultPosition,
|
|
const wxSize& size = wxDefaultSize,
|
|
long style = wxHSCROLL | wxVSCROLL);
|
|
virtual ~MixerBoardScrolledWindow();
|
|
|
|
private:
|
|
void OnMouseEvent(wxMouseEvent& event);
|
|
|
|
private:
|
|
MixerBoard* mMixerBoard;
|
|
AudacityProject* mProject;
|
|
|
|
public:
|
|
DECLARE_EVENT_TABLE()
|
|
};
|
|
|
|
|
|
class MixerBoardFrame;
|
|
class TrackList;
|
|
|
|
class MixerBoard : public wxWindow
|
|
{
|
|
friend class MixerBoardFrame;
|
|
|
|
public:
|
|
MixerBoard(AudacityProject* pProject,
|
|
wxFrame* parent,
|
|
const wxPoint& pos = wxDefaultPosition,
|
|
const wxSize& size = wxDefaultSize);
|
|
virtual ~MixerBoard();
|
|
|
|
// Add clusters for any tracks we're not yet showing.
|
|
// Update pointers for tracks we're aleady showing.
|
|
void UpdateTrackClusters();
|
|
|
|
int GetTrackClustersWidth();
|
|
#ifdef EXPERIMENTAL_MIDI_OUT
|
|
void MoveTrackCluster(const Track* pTrack, bool bUp); // Up in TrackPanel is left in MixerBoard.
|
|
void RemoveTrackCluster(const Track* pTrack);
|
|
|
|
|
|
wxBitmap* GetMusicalInstrumentBitmap(const wxString name);
|
|
#else
|
|
void MoveTrackCluster(const WaveTrack* pTrack, bool bUp); // Up in TrackPanel is left in MixerBoard.
|
|
void RemoveTrackCluster(const WaveTrack* pTrack);
|
|
|
|
|
|
wxBitmap* GetMusicalInstrumentBitmap(const WaveTrack* pLeftTrack);
|
|
#endif
|
|
|
|
bool HasSolo();
|
|
|
|
#ifdef EXPERIMENTAL_MIDI_OUT
|
|
void RefreshTrackCluster(const Track* pTrack, bool bEraseBackground = true);
|
|
#else
|
|
void RefreshTrackCluster(const WaveTrack* pTrack, bool bEraseBackground = true);
|
|
#endif
|
|
void RefreshTrackClusters(bool bEraseBackground = true);
|
|
void ResizeTrackClusters();
|
|
|
|
void ResetMeters(const bool bResetClipping);
|
|
|
|
#ifdef EXPERIMENTAL_MIDI_OUT
|
|
void UpdateName(const Track* pTrack);
|
|
void UpdateMute(const Track* pTrack = NULL); // NULL means update for all tracks.
|
|
void UpdateSolo(const Track* pTrack = NULL); // NULL means update for all tracks.
|
|
void UpdatePan(const Track* pTrack);
|
|
void UpdateGain(const Track* pTrack);
|
|
#else
|
|
void UpdateName(const WaveTrack* pTrack);
|
|
void UpdateMute(const WaveTrack* pTrack = NULL); // NULL means update for all tracks.
|
|
void UpdateSolo(const WaveTrack* pTrack = NULL); // NULL means update for all tracks.
|
|
void UpdatePan(const WaveTrack* pTrack);
|
|
void UpdateGain(const WaveTrack* pTrack);
|
|
#endif
|
|
|
|
void UpdateMeters(const double t1, const bool bLoopedPlay);
|
|
|
|
void UpdateWidth();
|
|
|
|
private:
|
|
void CreateMuteSoloImages();
|
|
#ifdef EXPERIMENTAL_MIDI_OUT
|
|
int FindMixerTrackCluster(const Track* pTrack,
|
|
MixerTrackCluster** hMixerTrackCluster) const;
|
|
#else
|
|
int FindMixerTrackCluster(const WaveTrack* pLeftTrack,
|
|
MixerTrackCluster** hMixerTrackCluster) const;
|
|
#endif
|
|
void LoadMusicalInstruments();
|
|
|
|
// event handlers
|
|
void OnSize(wxSizeEvent &evt);
|
|
|
|
|
|
public:
|
|
// mute & solo button images: Create once and store on MixerBoard for use in all MixerTrackClusters.
|
|
wxImage* mImageMuteUp;
|
|
wxImage* mImageMuteOver;
|
|
wxImage* mImageMuteDown;
|
|
wxImage* mImageMuteDownWhileSolo; // the one actually alternate image
|
|
wxImage* mImageMuteDisabled;
|
|
wxImage* mImageSoloUp;
|
|
wxImage* mImageSoloOver;
|
|
wxImage* mImageSoloDown;
|
|
wxImage* mImageSoloDisabled;
|
|
|
|
int mMuteSoloWidth;
|
|
|
|
private:
|
|
// Track clusters are maintained in the same order as the WaveTracks.
|
|
MixerTrackClusterArray mMixerTrackClusters;
|
|
|
|
MusicalInstrumentArray mMusicalInstruments;
|
|
AudacityProject* mProject;
|
|
MixerBoardScrolledWindow* mScrolledWindow; // Holds the MixerTrackClusters and handles scrolling.
|
|
double mPrevT1;
|
|
TrackList* mTracks;
|
|
|
|
public:
|
|
DECLARE_EVENT_TABLE()
|
|
};
|
|
|
|
|
|
class MixerBoardFrame : public wxFrame
|
|
{
|
|
public:
|
|
MixerBoardFrame(AudacityProject* parent);
|
|
virtual ~MixerBoardFrame();
|
|
|
|
private:
|
|
// event handlers
|
|
void OnCloseWindow(wxCloseEvent &WXUNUSED(event));
|
|
void OnMaximize(wxMaximizeEvent &event);
|
|
void OnSize(wxSizeEvent &evt);
|
|
|
|
public:
|
|
MixerBoard* mMixerBoard;
|
|
|
|
public:
|
|
DECLARE_EVENT_TABLE()
|
|
};
|
|
|
|
#endif // __AUDACITY_MIXER_BOARD__
|
|
|
|
|