23#include <wx/bmpbuttn.h>
24#include <wx/dcclient.h>
26#include <wx/settings.h>
61#include "../images/MusicalInstruments.h"
63 #include "../images/AudacityLogo.xpm"
65 #include "../images/AudacityLogo48x48.xpm"
72#define AudacityMixerBoardTitle XO("Audacity Mixer%s")
118 wxKeyEvent *kevent = (wxKeyEvent *)event.GetEventObject();
119 int keyCode = kevent->GetKeyCode();
122 if (keyCode == WXK_LEFT || keyCode == WXK_RIGHT ||
123 keyCode == WXK_UP || keyCode == WXK_DOWN ||
124 keyCode == WXK_PAGEUP || keyCode == WXK_PAGEDOWN) {
181 mMixerBoard = grandParent;
185 SetName(
Verbatim( mTrack->GetName() ) );
197 mStaticText_TrackName =
201 mStaticText_TrackName->SetForegroundColour(
theTheme.
Colour(clrMedium));
202 mStaticText_TrackName->SetForegroundColour(
theTheme.
Colour(clrTrackPanelText));
203 mStaticText_TrackName->SetSize( ctrlSize );
204 mStaticText_TrackName->SetPosition( ctrlPos );
210 const int nGainSliderHeight =
222 .Orientation( wxVERTICAL ));
223 mSlider_Gain->SetName(
_(
"Gain"));
233 .Orientation( wxVERTICAL ));
234 mSlider_Velocity->SetName(
_(
"Velocity"));
241 wxBitmap* bitmap = mMixerBoard->GetMusicalInstrumentBitmap(mTrack.get());
243 mBitmapButton_MusicalInstrument =
246 wxBU_AUTODRAW, wxDefaultValidator,
247 _(
"Musical Instrument"));
248 mBitmapButton_MusicalInstrument->SetName(
_(
"Musical Instrument"));
257 if (!(ctrlSize.x & 1))
267 mSlider_Pan->SetName(
_(
"Pan"));
275 *(mMixerBoard->mImageMuteUp), *(mMixerBoard->mImageMuteOver),
276 *(mMixerBoard->mImageMuteDown), *(mMixerBoard->mImageMuteDown),
277 *(mMixerBoard->mImageMuteDisabled),
279 mToggleButton_Mute->SetName(
_(
"Mute"));
280 mToggleButton_Mute->SetAlternateImages(
282 *(mMixerBoard->mImageMuteUp), *(mMixerBoard->mImageMuteOver),
283 *(mMixerBoard->mImageMuteDown), *(mMixerBoard->mImageMuteDown),
284 *(mMixerBoard->mImageMuteDisabled));
290 *(mMixerBoard->mImageSoloUp), *(mMixerBoard->mImageSoloOver),
291 *(mMixerBoard->mImageSoloDown), *(mMixerBoard->mImageSoloDown),
292 *(mMixerBoard->mImageSoloDisabled),
294 mToggleButton_Solo->SetName(
_(
"Solo"));
299 const int nMeterHeight =
314 mMeter->SetName(
XO(
"Signal Level Meter"));
318 mStaticText_TrackName->SetToolTip(mTrack->GetName());
319 mToggleButton_Mute->SetToolTip(
XO(
"Mute"));
320 mToggleButton_Solo->SetToolTip(
XO(
"Solo"));
322 mMeter->SetToolTip(
XO(
"Signal Level Meter"));
325 UpdateForStateChange();
328 wxSizeEvent event(GetSize(), GetId());
329 event.SetEventObject(
this);
330 GetEventHandler()->ProcessEvent(event);
344 auto channels = left->Channels();
345 if (channels.size() > 1)
346 return (* ++ channels.first).get();
360void MixerTrackCluster::UpdatePrefs()
370 wxSize scrolledWindowClientSize = this->GetParent()->GetClientSize();
371 const int newClusterHeight =
373 wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y) +
376 this->SetSize(-1, newClusterHeight);
380 const int nGainSliderHeight =
388 const int nRequiredHeightAboveMeter =
395 nRequiredHeightAboveMeter;
396 const int nMeterHeight = nGainSliderHeight - nRequiredHeightAboveMeter;
398 mMeter->SetSize(-1, nMeterY, -1, nMeterHeight);
455 const wxString newName =
mTrack->GetName();
456 if (newName != GetName()) {
473 bool bIsSolo =
mTrack->GetSolo();
499 return std::accumulate(
500 view.begin(), view.end(), 0,
502 return total + segmentView.GetSampleCount();
509 size_t copiedSamples = 0;
510 for (
const auto& segmentView : view)
512 const auto sampleCount = segmentView.GetSampleCount();
513 segmentView.Copy(buffer + copiedSamples,
sampleCount);
526 if ((t0 < 0.0) || (t1 < 0.0) || (t0 >= t1) ||
612 constexpr auto mayThrow =
false;
615 mSampleView = pTrack->GetSampleView(t0, t1, mayThrow);
624 tempFloatsArray.
reinit(nFrames);
626 catch (
const std::bad_alloc&) {
633 decltype(tempFloatsArray) meterFloatsArray;
638 meterFloatsArray.reinit(2 * nFrames );
640 catch (
const std::bad_alloc&) {
647 for (
unsigned int index = 0; index < nFrames; index++)
648 meterFloatsArray[2 * index] = tempFloatsArray[index];
654 for (
unsigned int index = 0; index < nFrames; index++)
655 meterFloatsArray[(2 * index) + 1] = tempFloatsArray[index];
660 float gain = pTrack->GetChannelGain(0);
661 for (
unsigned int index = 0; index < nFrames; index++)
662 meterFloatsArray[2 * index] *= gain;
663 gain = pTrack->GetChannelGain(1);
664 for (
unsigned int index = 0; index < nFrames; index++)
665 meterFloatsArray[(2 * index) + 1] *= gain;
667 for (
unsigned int index = 0; index < 2 * nFrames; index++)
668 if (meterFloatsArray[index] < -1.0)
669 meterFloatsArray[index] = -1.0;
670 else if (meterFloatsArray[index] > 1.0)
671 meterFloatsArray[index] = 1.0;
674 mMeter->UpdateDisplay(2, nFrames, meterFloatsArray.get());
681 return wxColour(102, 255, 102);
690 *
mTrack, bShiftDown, bControlDown,
true);
695 if (event.ButtonUp())
696 this->
HandleSelect(event.ShiftDown(), event.ControlDown());
705 auto selected =
mTrack->GetSelected();
707 wxColour col =
theTheme.
Colour(selected ? clrTrackInfoSelected : clrTrackInfo) ;
708 SetBackgroundColour( col );
710 mMeter->SetBackgroundColour( col );
718 dc.DrawRectangle(this->GetClientRect());
720 wxSize clusterSize = this->GetSize();
721 wxRect bev(0, 0, clusterSize.GetWidth() - 1, clusterSize.GetHeight() - 1);
730 const auto &state = ::wxGetMouseState();
731 this->
HandleSelect(state.ShiftDown(), state.ControlDown());
782 bool bIsSolo =
mTrack->GetSolo();
797 int nUnderscoreIndex;
798 wxString strFilename = strXPMfilename;
799 strFilename.MakeLower();
801 while ((nUnderscoreIndex = strFilename.Find(
wxT(
'_'))) != -1)
803 strKeyword = strFilename.Left(nUnderscoreIndex);
805 strFilename = strFilename.Mid(nUnderscoreIndex + 1);
807 if (!strFilename.empty())
832: wxScrolledWindow(parent,
id, pos,
size,
style)
834 mMixerBoard = parent;
844 if (event.ButtonUp())
858#define MIXER_BOARD_MIN_HEIGHT 460
861#define MIXER_BOARD_MIN_WIDTH kTripleInset + kMixerTrackClusterWidth*2 + kTripleInset
873: wxWindow(parent, -1, pos,
size)
880 mImageMuteOver = NULL;
881 mImageMuteDown = NULL;
882 mImageMuteDownWhileSolo = NULL;
883 mImageMuteDisabled = NULL;
885 mImageSoloOver = NULL;
886 mImageSoloDown = NULL;
887 mImageSoloDisabled = NULL;
892 this->LoadMusicalInstruments();
900 this->GetClientAreaOrigin(),
906 mScrolledWindow->SetBackgroundColour(
theTheme.
Colour( clrMedium ) );
909 mScrolledWindow->SetScrollRate(10, 0);
910 mScrolledWindow->SetVirtualSize(
size);
925 mPlaybackScrollerSubscription =
929 mTrackPanelSubscription =
931 switch (event.mType) {
932 case TrackListEvent::SELECTION_CHANGE:
933 case TrackListEvent::TRACK_DATA_CHANGE:
934 OnTrackChanged(event); break;
935 case TrackListEvent::PERMUTED:
936 case TrackListEvent::ADDITION:
937 case TrackListEvent::DELETION:
938 OnTrackSetChanged(); break;
944 mAudioIOSubscription =
972 for (
unsigned int nClusterIndex = 0; nClusterIndex <
mMixerTrackClusters.size(); nClusterIndex++)
992 unsigned int nClusterIndex = 0;
997 auto spTrack = pPlayableTrack->SharedPointer<
PlayableTrack>();
1001 if (nClusterIndex < nClusterCount)
1018 pMixerTrackCluster =
1020 *spTrack, clusterPos, clusterSize);
1021 if (pMixerTrackCluster)
1027 if (pMixerTrackCluster)
1033 else while (nClusterIndex < nClusterCount)
1057 pMixerTrackCluster->Destroy();
1069 if (pos.x != targetX)
1084 const wxString strTrackName(
1085 wxString{ pTrack->
GetName() }.MakeLower());
1086 size_t nBestItemIndex = 0;
1087 unsigned int nBestScore = 0;
1088 unsigned int nInstrIndex = 0;
1089 unsigned int nKeywordIndex;
1090 unsigned int nNumKeywords;
1091 unsigned int nPointsPerMatch;
1092 unsigned int nScore;
1098 if (nNumKeywords > 0)
1100 nPointsPerMatch = 10 / nNumKeywords;
1101 for (nKeywordIndex = 0; nKeywordIndex < nNumKeywords; nKeywordIndex++)
1113 if (nScore >= nBestScore)
1115 nBestScore = nScore;
1116 nBestItemIndex = nInstrIndex;
1136 for (
unsigned int nClusterIndex = 0; nClusterIndex <
mMixerTrackClusters.size(); nClusterIndex++)
1144 if (!this->IsShown())
1190 this->GetParent()->SetSize(newWidth +
kDoubleInset, -1);
1201 const auto translation =
str.Translation();
1202 int textWidth, textHeight;
1208 wxFont font(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
1209 GetTextExtent(translation, &textWidth, &textHeight, NULL, NULL, &font);
1212 dc.DrawRectangle(bev);
1216 wxCoord x = bev.x + (bev.width - textWidth) / 2;
1217 wxCoord y = bev.y + (bev.height - textHeight) / 2;
1220 dc.SetBackgroundMode(wxTRANSPARENT);
1221 dc.DrawText(translation, x, y);
1229 auto str =
XO(
"Mute");
1236 dc.SelectObject(bitmap);
1240 const bool down=
false;
1243 mImageMuteUp = std::make_unique<wxImage>(bitmap.ConvertToImage());
1244 mImageMuteOver = std::make_unique<wxImage>(bitmap.ConvertToImage());
1248 mImageMuteDown = std::make_unique<wxImage>(bitmap.ConvertToImage());
1257 mImageSoloUp = std::make_unique<wxImage>(bitmap.ConvertToImage());
1258 mImageSoloOver = std::make_unique<wxImage>(bitmap.ConvertToImage());
1261 mImageSoloDown = std::make_unique<wxImage>(bitmap.ConvertToImage());
1269 *hMixerTrackCluster = NULL;
1283 const struct Data {
const char *
const *bitmap; wxString
name; } table[] = {
1284 {acoustic_guitar_gtr_xpm,
wxT(
"acoustic_guitar_gtr")},
1285 {acoustic_piano_pno_xpm,
wxT(
"acoustic_piano_pno")},
1286 {back_vocal_bg_vox_xpm,
wxT(
"back_vocal_bg_vox")},
1287 {clap_xpm,
wxT(
"clap")},
1288 {drums_dr_xpm,
wxT(
"drums_dr")},
1289 {electric_bass_guitar_bs_gtr_xpm,
wxT(
"electric_bass_guitar_bs_gtr")},
1290 {electric_guitar_gtr_xpm,
wxT(
"electric_guitar_gtr")},
1291 {electric_piano_pno_key_xpm,
wxT(
"electric_piano_pno_key")},
1292 {kick_xpm,
wxT(
"kick")},
1293 {loop_xpm,
wxT(
"loop")},
1294 {organ_org_xpm,
wxT(
"organ_org")},
1295 {perc_xpm,
wxT(
"perc")},
1296 {sax_xpm,
wxT(
"sax")},
1297 {snare_xpm,
wxT(
"snare")},
1298 {string_violin_cello_xpm,
wxT(
"string_violin_cello")},
1299 {synth_xpm,
wxT(
"synth")},
1300 {tambo_xpm,
wxT(
"tambo")},
1301 {trumpet_horn_xpm,
wxT(
"trumpet_horn")},
1302 {turntable_xpm,
wxT(
"turntable")},
1303 {vibraphone_vibes_xpm,
wxT(
"vibraphone_vibes")},
1304 {vocal_vox_xpm,
wxT(
"vocal_vox")},
1307 {_default_instrument_xpm, wxEmptyString},
1313 for (
const auto &data : table) {
1314 auto bmp = std::make_unique<wxBitmap>(data.bitmap);
1315 dc.SelectObject(*bmp);
1318 std::move(bmp), data.name
1363 gAudioIO->GetStreamTime(),
1372 auto pTrack = evt.
mpTrack.lock();
1373 auto pPlayable =
dynamic_cast<PlayableTrack*
>( pTrack.get() );
1377 if ( pMixerTrackCluster )
1378 pMixerTrackCluster->Refresh();
1411 wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT)
1425 mMixerBoard->UpdateTrackClusters();
1428#if !defined(__WXMAC__) && !defined(__WXX11__)
1431 wxIcon ic{ wxICON(AudacityLogo) };
1433 wxIcon ic{wxICON(AudacityLogo48x48)};
1453#if defined(__WXMAC__)
1454 dynamic_cast<wxFrame*
>(GetParent())->Raise();
1482 wxSize siz2 = this->GetSize();
1492 this->SetSize( siz2 );
1537 mixerBoardFrame->Show();
1538 mixerBoardFrame->Raise();
1539 mixerBoardFrame->SetFocus();
wxEVT_COMMAND_BUTTON_CLICKED
An audio segment is either a whole clip or the silence between clips. Views allow shared references t...
std::vector< AudioSegmentSampleView > ChannelSampleView
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
XXO("&Cut/Copy/Paste Toolbar")
#define RTL_WORKAROUND(pWnd)
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
const int MUSICAL_INSTRUMENT_HEIGHT_AND_WIDTH
const int kMixerTrackClusterWidth
const int kQuadrupleInset
const int MUTE_SOLO_HEIGHT
const int kLeftSideStackWidth
#define MIXER_BOARD_MIN_WIDTH
const int kRightSideStackWidth
const int TRACK_NAME_HEIGHT
#define MIXER_BOARD_MIN_HEIGHT
const wxSize kDefaultSize
#define AudacityMixerBoardTitle
@ ID_BITMAPBUTTON_MUSICAL_INSTRUMENT
EnumSetting< SoloBehavior > TracksBehaviorsSolo
ProjectFileIOMessage
Subscribe to ProjectFileIO to receive messages; always in idle time.
@ ProjectTitleChange
A normal occurrence.
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
AUDACITY_DLL_API AttachedWindows & GetAttachedWindows(AudacityProject &project)
accessors for certain important windows associated with each project
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
static void Bevel2(wxDC &dc, bool up, const wxRect &r, bool bSel=false, bool bHighlight=false)
static void Bevel(wxDC &dc, bool up, const wxRect &r)
static void MediumTrackInfo(wxDC *dc, bool selected)
static void UseThemeColour(wxDC *dc, int iBrush, int iPen=-1, int alpha=255)
ASlider is a custom slider, allowing for a slicker look and feel.
void OnMouseEvent(wxMouseEvent &event)
bool SetBackgroundColour(const wxColour &colour) override
float Get(bool convert=true)
void reinit(Integral count, bool initialize=false)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
const wxString & GetProjectName() const
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
MeterPanel is a panel that paints the meter used for monitoring or playback.
void OnKeyEvent(wxKeyEvent &evt)
void OnMaximize(wxMaximizeEvent &event)
void OnCloseWindow(wxCloseEvent &WXUNUSED(event))
AudacityProject * mProject
void OnSize(wxSizeEvent &evt)
virtual ~MixerBoardFrame()
void Recreate(AudacityProject *pProject)
void OnSize(wxSizeEvent &evt)
void OnStartStop(AudioIOEvent)
int FindMixerTrackCluster(const PlayableTrack *pTrack, MixerTrackCluster **hMixerTrackCluster) const
std::unique_ptr< wxImage > mImageMuteDownWhileSolo
void ResizeTrackClusters()
MusicalInstrumentArray mMusicalInstruments
void UpdateMeters(const double t1, const bool bLoopedPlay)
void OnPaint(wxPaintEvent &evt)
std::unique_ptr< wxImage > mImageMuteDown
std::unique_ptr< wxImage > mImageMuteDisabled
std::unique_ptr< wxImage > mImageMuteOver
std::unique_ptr< wxImage > mImageSoloDown
void MakeButtonBitmap(wxMemoryDC &dc, wxBitmap &bitmap, wxRect &bev, const TranslatableString &str, bool up)
void UpdatePrefs() override
void OnTimer(Observer::Message)
MixerBoardScrolledWindow * mScrolledWindow
std::unique_ptr< wxImage > mImageMuteUp
wxBitmap * GetMusicalInstrumentBitmap(const Track *pTrack)
void OnTrackChanged(const TrackListEvent &event)
void UpdateTrackClusters()
void ResetMeters(const bool bResetClipping)
std::unique_ptr< wxImage > mImageSoloDisabled
std::unique_ptr< wxImage > mImageSoloUp
int GetTrackClustersWidth()
void RemoveTrackCluster(size_t nIndex)
void CreateMuteSoloImages()
std::unique_ptr< wxImage > mImageSoloOver
void LoadMusicalInstruments()
AudacityProject * mProject
std::vector< MixerTrackCluster * > mMixerTrackClusters
void RefreshTrackClusters(bool bEraseBackground=true)
void HandleSliderVelocity(const bool bWantPushState=false)
wxBitmapButton * mBitmapButton_MusicalInstrument
void OnSlider_Gain(wxCommandEvent &event)
void HandleSliderGain(const bool bWantPushState=false)
MixerTrackSlider * mSlider_Gain
void UpdateForStateChange()
void OnButton_MusicalInstrument(wxCommandEvent &event)
std::shared_ptr< PlayableTrack > mTrack
Invariant not null.
AudacityProject * mProject
NoteTrack * GetNote() const
void ResetMeter(const bool bResetClipping)
void OnSlider_Pan(wxCommandEvent &event)
WaveTrack * GetWave() const
AButton * mToggleButton_Mute
ChannelGroupSampleView mSampleView
wxWeakRef< MeterPanel > mMeter
void UpdateMeter(const double t0, const double t1)
void OnPaint(wxPaintEvent &evt)
void OnButton_Mute(wxCommandEvent &event)
WaveChannel * GetRight() const
void HandleSelect(bool bShiftDown, bool bControlDown)
void OnMouseEvent(wxMouseEvent &event)
void OnSlider_Velocity(wxCommandEvent &event)
MixerTrackSlider * mSlider_Velocity
void OnButton_Solo(wxCommandEvent &event)
MixerTrackSlider * mSlider_Pan
void HandleSliderPan(const bool bWantPushState=false)
auStaticText * mStaticText_TrackName
AButton * mToggleButton_Solo
void OnCaptureKey(wxCommandEvent &event)
void OnFocus(wxFocusEvent &event)
void OnMouseEvent(wxMouseEvent &event)
MusicalInstrument(std::unique_ptr< wxBitmap > &&pBitmap, const wxString &strXPMfilename)
virtual ~MusicalInstrument()
std::unique_ptr< wxBitmap > mBitmap
A Track that is used for Midi notes. (Somewhat old code).
void SetVelocity(float velocity)
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
static PendingTracks & Get(AudacityProject &project)
AudioTrack subclass that can also be audibly replayed by the program.
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
static ProjectAudioManager & Get(AudacityProject &project)
PlayMode GetLastPlayMode() const
static ProjectFileIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
PlaybackScroller & GetPlaybackScroller()
static ProjectWindow & Get(AudacityProject &project)
Generates classes whose instances register items at construction.
wxColour & Colour(int iIndex)
Abstract base class for an object holding data associated with points on a time axis.
const wxString & GetName() const
Name is always the same for all channels of a group.
auto Any() -> TrackIterRange< TrackType >
static TrackList & Get(AudacityProject &project)
static TrackPanel & Get(AudacityProject &project)
void RefreshTrack(Track *trk, bool refreshbacking=true)
Holds a msgid for the translation catalog; may also bind format arguments.
static Viewport & Get(AudacityProject &project)
A Track that contains audio waveform data.
void SetPan(float newPan)
void SetGain(float newGain)
is like wxStaticText, except it can be themed. wxStaticText can't be.
Positions or offsets within audio files need a wide type.
void OnFocus(wxWindow &window, wxFocusEvent &event)
a function useful to implement a focus event handler The window releases the keyboard if the event is...
void SelectNone(AudacityProject &project)
void DoListSelection(AudacityProject &project, Track &t, bool shift, bool ctrl, bool modifyState)
AUDACITY_DLL_API void DoTrackSolo(AudacityProject &project, Track &track, bool exclusive)
AUDACITY_DLL_API void DoTrackMute(AudacityProject &project, Track &track, bool exclusive)
"exclusive" mute means mute the chosen track and unmute all others.
const ReservedCommandFlag & PlayableTracksExistFlag()
size_t GetNumSamplesInView(const ChannelSampleView &view)
void FillBufferWithSampleView(float *buffer, const ChannelSampleView &view)
AttachedWindows::RegisteredFactory sMixerBoardKey
void OnMixerBoard(const CommandContext &context)
double GetRate(const Track &track)
enum AudioIOEvent::Type type
Default message type for Publisher.
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
const std::weak_ptr< Track > mpTrack