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_Volume->SetName(
_(
"Volume"));
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 volume = pTrack->GetChannelVolume(0);
661 for (
unsigned int index = 0; index < nFrames; index++)
662 meterFloatsArray[2 * index] *= volume;
663 volume = pTrack->GetChannelVolume(1);
664 for (
unsigned int index = 0; index < nFrames; index++)
665 meterFloatsArray[(2 * index) + 1] *= volume;
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());
767 bool bIsSolo =
mTrack->GetSolo();
782 int nUnderscoreIndex;
783 wxString strFilename = strXPMfilename;
784 strFilename.MakeLower();
786 while ((nUnderscoreIndex = strFilename.Find(
wxT(
'_'))) != -1)
788 strKeyword = strFilename.Left(nUnderscoreIndex);
790 strFilename = strFilename.Mid(nUnderscoreIndex + 1);
792 if (!strFilename.empty())
817: wxScrolledWindow(parent,
id, pos,
size,
style)
819 mMixerBoard = parent;
829 if (event.ButtonUp())
843#define MIXER_BOARD_MIN_HEIGHT 460
846#define MIXER_BOARD_MIN_WIDTH kTripleInset + kMixerTrackClusterWidth*2 + kTripleInset
858: wxWindow(parent, -1, pos,
size)
865 mImageMuteOver = NULL;
866 mImageMuteDown = NULL;
867 mImageMuteDownWhileSolo = NULL;
868 mImageMuteDisabled = NULL;
870 mImageSoloOver = NULL;
871 mImageSoloDown = NULL;
872 mImageSoloDisabled = NULL;
877 this->LoadMusicalInstruments();
885 this->GetClientAreaOrigin(),
891 mScrolledWindow->SetBackgroundColour(
theTheme.
Colour( clrMedium ) );
894 mScrolledWindow->SetScrollRate(10, 0);
895 mScrolledWindow->SetVirtualSize(
size);
910 mPlaybackScrollerSubscription =
914 mTrackPanelSubscription =
916 switch (event.mType) {
917 case TrackListEvent::SELECTION_CHANGE:
918 case TrackListEvent::TRACK_DATA_CHANGE:
919 OnTrackChanged(event); break;
920 case TrackListEvent::PERMUTED:
921 case TrackListEvent::ADDITION:
922 case TrackListEvent::DELETION:
923 OnTrackSetChanged(); break;
929 mAudioIOSubscription =
957 for (
unsigned int nClusterIndex = 0; nClusterIndex <
mMixerTrackClusters.size(); nClusterIndex++)
977 unsigned int nClusterIndex = 0;
982 auto spTrack = pPlayableTrack->SharedPointer<
PlayableTrack>();
986 if (nClusterIndex < nClusterCount)
1003 pMixerTrackCluster =
1005 *spTrack, clusterPos, clusterSize);
1006 if (pMixerTrackCluster)
1012 if (pMixerTrackCluster)
1018 else while (nClusterIndex < nClusterCount)
1042 pMixerTrackCluster->Destroy();
1054 if (pos.x != targetX)
1069 const wxString strTrackName(
1070 wxString{ pTrack->
GetName() }.MakeLower());
1071 size_t nBestItemIndex = 0;
1072 unsigned int nBestScore = 0;
1073 unsigned int nInstrIndex = 0;
1074 unsigned int nKeywordIndex;
1075 unsigned int nNumKeywords;
1076 unsigned int nPointsPerMatch;
1077 unsigned int nScore;
1083 if (nNumKeywords > 0)
1085 nPointsPerMatch = 10 / nNumKeywords;
1086 for (nKeywordIndex = 0; nKeywordIndex < nNumKeywords; nKeywordIndex++)
1098 if (nScore >= nBestScore)
1100 nBestScore = nScore;
1101 nBestItemIndex = nInstrIndex;
1121 for (
unsigned int nClusterIndex = 0; nClusterIndex <
mMixerTrackClusters.size(); nClusterIndex++)
1129 if (!this->IsShown())
1175 this->GetParent()->SetSize(newWidth +
kDoubleInset, -1);
1186 const auto translation =
str.Translation();
1187 int textWidth, textHeight;
1193 wxFont font(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
1194 GetTextExtent(translation, &textWidth, &textHeight, NULL, NULL, &font);
1197 dc.DrawRectangle(bev);
1201 wxCoord x = bev.x + (bev.width - textWidth) / 2;
1202 wxCoord y = bev.y + (bev.height - textHeight) / 2;
1205 dc.SetBackgroundMode(wxTRANSPARENT);
1206 dc.DrawText(translation, x, y);
1214 auto str =
XO(
"Mute");
1221 dc.SelectObject(bitmap);
1225 const bool down=
false;
1228 mImageMuteUp = std::make_unique<wxImage>(bitmap.ConvertToImage());
1229 mImageMuteOver = std::make_unique<wxImage>(bitmap.ConvertToImage());
1233 mImageMuteDown = std::make_unique<wxImage>(bitmap.ConvertToImage());
1242 mImageSoloUp = std::make_unique<wxImage>(bitmap.ConvertToImage());
1243 mImageSoloOver = std::make_unique<wxImage>(bitmap.ConvertToImage());
1246 mImageSoloDown = std::make_unique<wxImage>(bitmap.ConvertToImage());
1254 *hMixerTrackCluster = NULL;
1268 const struct Data {
const char *
const *bitmap; wxString
name; } table[] = {
1269 {acoustic_guitar_gtr_xpm,
wxT(
"acoustic_guitar_gtr")},
1270 {acoustic_piano_pno_xpm,
wxT(
"acoustic_piano_pno")},
1271 {back_vocal_bg_vox_xpm,
wxT(
"back_vocal_bg_vox")},
1272 {clap_xpm,
wxT(
"clap")},
1273 {drums_dr_xpm,
wxT(
"drums_dr")},
1274 {electric_bass_guitar_bs_gtr_xpm,
wxT(
"electric_bass_guitar_bs_gtr")},
1275 {electric_guitar_gtr_xpm,
wxT(
"electric_guitar_gtr")},
1276 {electric_piano_pno_key_xpm,
wxT(
"electric_piano_pno_key")},
1277 {kick_xpm,
wxT(
"kick")},
1278 {loop_xpm,
wxT(
"loop")},
1279 {organ_org_xpm,
wxT(
"organ_org")},
1280 {perc_xpm,
wxT(
"perc")},
1281 {sax_xpm,
wxT(
"sax")},
1282 {snare_xpm,
wxT(
"snare")},
1283 {string_violin_cello_xpm,
wxT(
"string_violin_cello")},
1284 {synth_xpm,
wxT(
"synth")},
1285 {tambo_xpm,
wxT(
"tambo")},
1286 {trumpet_horn_xpm,
wxT(
"trumpet_horn")},
1287 {turntable_xpm,
wxT(
"turntable")},
1288 {vibraphone_vibes_xpm,
wxT(
"vibraphone_vibes")},
1289 {vocal_vox_xpm,
wxT(
"vocal_vox")},
1292 {_default_instrument_xpm, wxEmptyString},
1298 for (
const auto &data : table) {
1299 auto bmp = std::make_unique<wxBitmap>(data.bitmap);
1300 dc.SelectObject(*bmp);
1303 std::move(bmp), data.name
1348 gAudioIO->GetStreamTime(),
1357 auto pTrack = evt.
mpTrack.lock();
1358 auto pPlayable =
dynamic_cast<PlayableTrack*
>( pTrack.get() );
1362 if ( pMixerTrackCluster )
1363 pMixerTrackCluster->Refresh();
1396 wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT)
1410 mMixerBoard->UpdateTrackClusters();
1413#if !defined(__WXMAC__) && !defined(__WXX11__)
1416 wxIcon ic{ wxICON(AudacityLogo) };
1418 wxIcon ic{wxICON(AudacityLogo48x48)};
1438#if defined(__WXMAC__)
1439 dynamic_cast<wxFrame*
>(GetParent())->Raise();
1467 wxSize siz2 = this->GetSize();
1477 this->SetSize( siz2 );
1522 mixerBoardFrame->Show();
1523 mixerBoardFrame->Raise();
1524 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
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)
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
MixerTrackSlider * mSlider_Volume
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 SetVolume(float newVolume)
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