23#include <wx/bmpbuttn.h>
24#include <wx/dcclient.h>
26#include <wx/settings.h>
59#include "../images/MusicalInstruments.h"
61 #include "../images/AudacityLogo.xpm"
63 #include "../images/AudacityLogo48x48.xpm"
70#define AudacityMixerBoardTitle XO("Audacity Mixer%s")
116 wxKeyEvent *kevent = (wxKeyEvent *)event.GetEventObject();
117 int keyCode = kevent->GetKeyCode();
120 if (keyCode == WXK_LEFT || keyCode == WXK_RIGHT ||
121 keyCode == WXK_UP || keyCode == WXK_DOWN ||
122 keyCode == WXK_PAGEUP || keyCode == WXK_PAGEDOWN) {
153#ifdef EXPERIMENTAL_MIDI_OUT
167#ifdef EXPERIMENTAL_MIDI_OUT
168 EVT_SLIDER(ID_SLIDER_VELOCITY, MixerTrackCluster::OnSlider_Velocity)
183 mMixerBoard = grandParent;
187 SetName(
Verbatim( mTrack->GetName() ) );
199 mStaticText_TrackName =
203 mStaticText_TrackName->SetForegroundColour(
theTheme.
Colour(clrMedium));
204 mStaticText_TrackName->SetForegroundColour(
theTheme.
Colour(clrTrackPanelText));
205 mStaticText_TrackName->SetSize( ctrlSize );
206 mStaticText_TrackName->SetPosition( ctrlPos );
212 const int nGainSliderHeight =
224 .Orientation( wxVERTICAL ));
225 mSlider_Gain->SetName(
_(
"Gain"));
227#ifdef EXPERIMENTAL_MIDI_OUT
230 this, ID_SLIDER_VELOCITY,
236 .Orientation( wxVERTICAL ));
237 mSlider_Velocity->SetName(
_(
"Velocity"));
245 wxBitmap* bitmap = mMixerBoard->GetMusicalInstrumentBitmap(mTrack.get());
247 mBitmapButton_MusicalInstrument =
250 wxBU_AUTODRAW, wxDefaultValidator,
251 _(
"Musical Instrument"));
252 mBitmapButton_MusicalInstrument->SetName(
_(
"Musical Instrument"));
261 if (!(ctrlSize.x & 1))
271 mSlider_Pan->SetName(
_(
"Pan"));
279 *(mMixerBoard->mImageMuteUp), *(mMixerBoard->mImageMuteOver),
280 *(mMixerBoard->mImageMuteDown), *(mMixerBoard->mImageMuteDown),
281 *(mMixerBoard->mImageMuteDisabled),
283 mToggleButton_Mute->SetName(
_(
"Mute"));
284 mToggleButton_Mute->SetAlternateImages(
286 *(mMixerBoard->mImageMuteUp), *(mMixerBoard->mImageMuteOver),
287 *(mMixerBoard->mImageMuteDown), *(mMixerBoard->mImageMuteDown),
288 *(mMixerBoard->mImageMuteDisabled));
294 *(mMixerBoard->mImageSoloUp), *(mMixerBoard->mImageSoloOver),
295 *(mMixerBoard->mImageSoloDown), *(mMixerBoard->mImageSoloDown),
296 *(mMixerBoard->mImageSoloDisabled),
298 mToggleButton_Solo->SetName(
_(
"Solo"));
300 mToggleButton_Solo->Show(!bSoloNone);
305 const int nMeterHeight =
320 mMeter->SetName(
XO(
"Signal Level Meter"));
324 mStaticText_TrackName->SetToolTip(mTrack->GetName());
325 mToggleButton_Mute->SetToolTip(
XO(
"Mute"));
326 mToggleButton_Solo->SetToolTip(
XO(
"Solo"));
328 mMeter->SetToolTip(
XO(
"Signal Level Meter"));
331 UpdateForStateChange();
334 wxSizeEvent event(GetSize(), GetId());
335 event.SetEventObject(
this);
336 GetEventHandler()->ProcessEvent(event);
350 auto channels = left->Channels();
351 if (channels.size() > 1)
352 return (* ++ channels.first).get();
357#ifdef EXPERIMENTAL_MIDI_OUT
358NoteTrack *MixerTrackCluster::GetNote()
const
378 wxSize scrolledWindowClientSize = this->GetParent()->GetClientSize();
379 const int newClusterHeight =
381 wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y) +
384 this->SetSize(-1, newClusterHeight);
388 const int nGainSliderHeight =
394#ifdef EXPERIMENTAL_MIDI_OUT
395 mSlider_Velocity->SetSize(-1, nGainSliderHeight);
402 const int nRequiredHeightAboveMeter =
409 nRequiredHeightAboveMeter;
410 const int nMeterHeight = nGainSliderHeight - nRequiredHeightAboveMeter;
412 mMeter->SetSize(-1, nMeterY, -1, nMeterHeight);
428#ifdef EXPERIMENTAL_MIDI_OUT
429void MixerTrackCluster::HandleSliderVelocity(
const bool bWantPushState )
431 float fValue = mSlider_Velocity->Get();
433 GetNote()->SetVelocity(fValue);
471 const wxString newName =
mTrack->GetName();
472 if (newName != GetName()) {
489 bool bIsSolo =
mTrack->GetSolo();
506#ifdef EXPERIMENTAL_MIDI_OUT
508 mSlider_Velocity->Hide();
510 mSlider_Velocity->Set(GetNote()->GetVelocity());
517 return std::accumulate(
518 view.begin(), view.end(), 0,
520 return total + segmentView.GetSampleCount();
527 size_t copiedSamples = 0;
528 for (
const auto& segmentView : view)
530 const auto sampleCount = segmentView.GetSampleCount();
531 segmentView.Copy(buffer + copiedSamples,
sampleCount);
544 if ((t0 < 0.0) || (t1 < 0.0) || (t0 >= t1) ||
634 constexpr auto mayThrow =
false;
637 mSampleView = pTrack->GetSampleView(t0, t1, mayThrow);
646 tempFloatsArray.
reinit(nFrames);
648 catch (
const std::bad_alloc&) {
655 decltype(tempFloatsArray) meterFloatsArray;
660 meterFloatsArray.reinit(2 * nFrames );
662 catch (
const std::bad_alloc&) {
669 for (
unsigned int index = 0; index < nFrames; index++)
670 meterFloatsArray[2 * index] = tempFloatsArray[index];
676 for (
unsigned int index = 0; index < nFrames; index++)
677 meterFloatsArray[(2 * index) + 1] = tempFloatsArray[index];
682 float gain = pTrack->GetChannelGain(0);
683 for (
unsigned int index = 0; index < nFrames; index++)
684 meterFloatsArray[2 * index] *= gain;
685 gain = pTrack->GetChannelGain(1);
686 for (
unsigned int index = 0; index < nFrames; index++)
687 meterFloatsArray[(2 * index) + 1] *= gain;
689 for (
unsigned int index = 0; index < 2 * nFrames; index++)
690 if (meterFloatsArray[index] < -1.0)
691 meterFloatsArray[index] = -1.0;
692 else if (meterFloatsArray[index] > 1.0)
693 meterFloatsArray[index] = 1.0;
696 mMeter->UpdateDisplay(2, nFrames, meterFloatsArray.get());
703 return wxColour(102, 255, 102);
712 *
mTrack, bShiftDown, bControlDown,
true);
717 if (event.ButtonUp())
718 this->
HandleSelect(event.ShiftDown(), event.ControlDown());
727 auto selected =
mTrack->GetSelected();
729 wxColour col =
theTheme.
Colour(selected ? clrTrackInfoSelected : clrTrackInfo) ;
730 SetBackgroundColour( col );
732 mMeter->SetBackgroundColour( col );
740 dc.DrawRectangle(this->GetClientRect());
742 wxSize clusterSize = this->GetSize();
743 wxRect bev(0, 0, clusterSize.GetWidth() - 1, clusterSize.GetHeight() - 1);
752 const auto &state = ::wxGetMouseState();
753 this->
HandleSelect(state.ShiftDown(), state.ControlDown());
761#ifdef EXPERIMENTAL_MIDI_OUT
762void MixerTrackCluster::OnSlider_Velocity(wxCommandEvent& WXUNUSED(event))
764 this->HandleSliderVelocity();
806 bool bIsSolo =
mTrack->GetSolo();
821 int nUnderscoreIndex;
822 wxString strFilename = strXPMfilename;
823 strFilename.MakeLower();
825 while ((nUnderscoreIndex = strFilename.Find(
wxT(
'_'))) != -1)
827 strKeyword = strFilename.Left(nUnderscoreIndex);
829 strFilename = strFilename.Mid(nUnderscoreIndex + 1);
831 if (!strFilename.empty())
856: wxScrolledWindow(parent,
id, pos,
size, style)
858 mMixerBoard = parent;
868 if (event.ButtonUp())
882#define MIXER_BOARD_MIN_HEIGHT 460
885#define MIXER_BOARD_MIN_WIDTH kTripleInset + kMixerTrackClusterWidth*2 + kTripleInset
897: wxWindow(parent, -1, pos,
size)
904 mImageMuteOver = NULL;
905 mImageMuteDown = NULL;
906 mImageMuteDownWhileSolo = NULL;
907 mImageMuteDisabled = NULL;
909 mImageSoloOver = NULL;
910 mImageSoloDown = NULL;
911 mImageSoloDisabled = NULL;
916 this->LoadMusicalInstruments();
924 this->GetClientAreaOrigin(),
934 mScrolledWindow->SetBackgroundColour(
theTheme.
Colour( clrMedium ) );
937 mScrolledWindow->SetScrollRate(10, 0);
938 mScrolledWindow->SetVirtualSize(
size);
953 mPlaybackScrollerSubscription =
957 mTrackPanelSubscription =
959 switch (event.
mType) {
960 case TrackListEvent::SELECTION_CHANGE:
961 case TrackListEvent::TRACK_DATA_CHANGE:
962 OnTrackChanged(event); break;
963 case TrackListEvent::PERMUTED:
964 case TrackListEvent::ADDITION:
965 case TrackListEvent::DELETION:
966 OnTrackSetChanged(); break;
972 mAudioIOSubscription =
1000 for (
unsigned int nClusterIndex = 0; nClusterIndex <
mMixerTrackClusters.size(); nClusterIndex++)
1020 unsigned int nClusterIndex = 0;
1025 auto spTrack = pPlayableTrack->SharedPointer<
PlayableTrack>();
1026 if (nClusterIndex < nClusterCount)
1043 pMixerTrackCluster =
1046 clusterPos, clusterSize);
1047 if (pMixerTrackCluster)
1053 if (pMixerTrackCluster)
1059 else while (nClusterIndex < nClusterCount)
1083 pMixerTrackCluster->Destroy();
1095 if (pos.x != targetX)
1110 const wxString strTrackName(
1111 wxString{ pTrack->
GetName() }.MakeLower());
1112 size_t nBestItemIndex = 0;
1113 unsigned int nBestScore = 0;
1114 unsigned int nInstrIndex = 0;
1115 unsigned int nKeywordIndex;
1116 unsigned int nNumKeywords;
1117 unsigned int nPointsPerMatch;
1118 unsigned int nScore;
1124 if (nNumKeywords > 0)
1126 nPointsPerMatch = 10 / nNumKeywords;
1127 for (nKeywordIndex = 0; nKeywordIndex < nNumKeywords; nKeywordIndex++)
1139 if (nScore >= nBestScore)
1141 nBestScore = nScore;
1142 nBestItemIndex = nInstrIndex;
1162 for (
unsigned int nClusterIndex = 0; nClusterIndex <
mMixerTrackClusters.size(); nClusterIndex++)
1170 if (!this->IsShown())
1216 this->GetParent()->SetSize(newWidth +
kDoubleInset, -1);
1227 const auto translation =
str.Translation();
1228 int textWidth, textHeight;
1234 wxFont font(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
1235 GetTextExtent(translation, &textWidth, &textHeight, NULL, NULL, &font);
1238 dc.DrawRectangle(bev);
1242 wxCoord x = bev.x + (bev.width - textWidth) / 2;
1243 wxCoord y = bev.y + (bev.height - textHeight) / 2;
1246 dc.SetBackgroundMode(wxTRANSPARENT);
1247 dc.DrawText(translation, x, y);
1255 auto str =
XO(
"Mute");
1262 dc.SelectObject(bitmap);
1266 const bool down=
false;
1269 mImageMuteUp = std::make_unique<wxImage>(bitmap.ConvertToImage());
1270 mImageMuteOver = std::make_unique<wxImage>(bitmap.ConvertToImage());
1274 mImageMuteDown = std::make_unique<wxImage>(bitmap.ConvertToImage());
1283 mImageSoloUp = std::make_unique<wxImage>(bitmap.ConvertToImage());
1284 mImageSoloOver = std::make_unique<wxImage>(bitmap.ConvertToImage());
1287 mImageSoloDown = std::make_unique<wxImage>(bitmap.ConvertToImage());
1295 *hMixerTrackCluster = NULL;
1309 const struct Data {
const char *
const *bitmap; wxString
name; } table[] = {
1310 {acoustic_guitar_gtr_xpm,
wxT(
"acoustic_guitar_gtr")},
1311 {acoustic_piano_pno_xpm,
wxT(
"acoustic_piano_pno")},
1312 {back_vocal_bg_vox_xpm,
wxT(
"back_vocal_bg_vox")},
1313 {clap_xpm,
wxT(
"clap")},
1314 {drums_dr_xpm,
wxT(
"drums_dr")},
1315 {electric_bass_guitar_bs_gtr_xpm,
wxT(
"electric_bass_guitar_bs_gtr")},
1316 {electric_guitar_gtr_xpm,
wxT(
"electric_guitar_gtr")},
1317 {electric_piano_pno_key_xpm,
wxT(
"electric_piano_pno_key")},
1318 {kick_xpm,
wxT(
"kick")},
1319 {loop_xpm,
wxT(
"loop")},
1320 {organ_org_xpm,
wxT(
"organ_org")},
1321 {perc_xpm,
wxT(
"perc")},
1322 {sax_xpm,
wxT(
"sax")},
1323 {snare_xpm,
wxT(
"snare")},
1324 {string_violin_cello_xpm,
wxT(
"string_violin_cello")},
1325 {synth_xpm,
wxT(
"synth")},
1326 {tambo_xpm,
wxT(
"tambo")},
1327 {trumpet_horn_xpm,
wxT(
"trumpet_horn")},
1328 {turntable_xpm,
wxT(
"turntable")},
1329 {vibraphone_vibes_xpm,
wxT(
"vibraphone_vibes")},
1330 {vocal_vox_xpm,
wxT(
"vocal_vox")},
1333 {_default_instrument_xpm, wxEmptyString},
1339 for (
const auto &data : table) {
1340 auto bmp = std::make_unique<wxBitmap>(data.bitmap);
1341 dc.SelectObject(*bmp);
1344 std::move(bmp), data.name
1389 gAudioIO->GetStreamTime(),
1398 auto pTrack = evt.
mpTrack.lock();
1399 auto pPlayable =
dynamic_cast<PlayableTrack*
>( pTrack.get() );
1403 if ( pMixerTrackCluster )
1404 pMixerTrackCluster->Refresh();
1437 wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT)
1451 mMixerBoard->UpdateTrackClusters();
1454#if !defined(__WXMAC__) && !defined(__WXX11__)
1457 wxIcon ic{ wxICON(AudacityLogo) };
1459 wxIcon ic{wxICON(AudacityLogo48x48)};
1479#if defined(__WXMAC__)
1480 dynamic_cast<wxFrame*
>(GetParent())->Raise();
1502 commandManager.FilterKeyEvent(
project, event,
true);
1509 wxSize siz2 = this->GetSize();
1519 this->SetSize( siz2 );
1544#ifdef EXPERIMENTAL_MIDI_OUT
1566 mixerBoardFrame->Show();
1567 mixerBoardFrame->Raise();
1568 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
static CommandManager & Get(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)
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
AudacityProject * mProject
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 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).
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
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)
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.
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 UpdatePrefs(wxWindow *pParent)
void DoTrackMute(AudacityProject &project, Track *t, bool exclusive)
void DoTrackSolo(AudacityProject &project, Track *t, bool exclusive)
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