mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-02 00:49:33 +02:00
MIDI play changes for TrackPanel, MixerBoard; conditionally compiled
This commit is contained in:
commit
08e57f3836
@ -728,7 +728,7 @@ void AudacityProject::CreateMenusAndCommands()
|
||||
AudioIONotBusyFlag);
|
||||
|
||||
c->AddItem(wxT("Karaoke"), _("&Karaoke..."), FN(OnKaraoke), LabelTracksExistFlag, LabelTracksExistFlag);
|
||||
c->AddItem(wxT("MixerBoard"), _("&Mixer Board..."), FN(OnMixerBoard), WaveTracksExistFlag, WaveTracksExistFlag);
|
||||
c->AddItem(wxT("MixerBoard"), _("&Mixer Board..."), FN(OnMixerBoard), PlayableTracksExistFlag, PlayableTracksExistFlag);
|
||||
|
||||
c->AddSeparator();
|
||||
|
||||
@ -1836,6 +1836,7 @@ CommandFlag AudacityProject::GetUpdateFlags(bool checkActive)
|
||||
}
|
||||
else if (t->GetKind() == Track::Wave) {
|
||||
flags |= WaveTracksExistFlag;
|
||||
flags |= PlayableTracksExistFlag;
|
||||
if (t->GetSelected()) {
|
||||
flags |= TracksSelectedFlag;
|
||||
if (t->GetLinked()) {
|
||||
@ -1853,6 +1854,9 @@ CommandFlag AudacityProject::GetUpdateFlags(bool checkActive)
|
||||
NoteTrack *nt = (NoteTrack *) t;
|
||||
|
||||
flags |= NoteTracksExistFlag;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
flags |= PlayableTracksExistFlag;
|
||||
#endif
|
||||
|
||||
if (nt->GetSelected()) {
|
||||
flags |= TracksSelectedFlag;
|
||||
|
@ -24,7 +24,9 @@
|
||||
#include "AColor.h"
|
||||
#include "AudioIO.h"
|
||||
|
||||
#ifdef USE_MIDI
|
||||
#include "NoteTrack.h"
|
||||
#endif
|
||||
|
||||
#include "Project.h"
|
||||
#include "TrackPanel.h" // for EVT_TRACK_PANEL_TIMER
|
||||
@ -137,6 +139,9 @@ enum {
|
||||
ID_BITMAPBUTTON_MUSICAL_INSTRUMENT = 13000,
|
||||
ID_SLIDER_PAN,
|
||||
ID_SLIDER_GAIN,
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
ID_SLIDER_VELOCITY,
|
||||
#endif
|
||||
ID_TOGGLEBUTTON_MUTE,
|
||||
ID_TOGGLEBUTTON_SOLO,
|
||||
};
|
||||
@ -148,6 +153,9 @@ BEGIN_EVENT_TABLE(MixerTrackCluster, wxPanelWrapper)
|
||||
EVT_BUTTON(ID_BITMAPBUTTON_MUSICAL_INSTRUMENT, MixerTrackCluster::OnButton_MusicalInstrument)
|
||||
EVT_SLIDER(ID_SLIDER_PAN, MixerTrackCluster::OnSlider_Pan)
|
||||
EVT_SLIDER(ID_SLIDER_GAIN, MixerTrackCluster::OnSlider_Gain)
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
EVT_SLIDER(ID_SLIDER_VELOCITY, MixerTrackCluster::OnSlider_Velocity)
|
||||
#endif
|
||||
//v EVT_COMMAND_SCROLL(ID_SLIDER_GAIN, MixerTrackCluster::OnSliderScroll_Gain)
|
||||
EVT_COMMAND(ID_TOGGLEBUTTON_MUTE, wxEVT_COMMAND_BUTTON_CLICKED, MixerTrackCluster::OnButton_Mute)
|
||||
EVT_COMMAND(ID_TOGGLEBUTTON_SOLO, wxEVT_COMMAND_BUTTON_CLICKED, MixerTrackCluster::OnButton_Solo)
|
||||
@ -184,37 +192,33 @@ MixerTrackCluster::MixerTrackCluster(wxWindow* parent,
|
||||
// mStaticText_TrackName->SetBackgroundColour(this->GetTrackColor());
|
||||
|
||||
|
||||
// gain slider at left
|
||||
// gain and velocity sliders at left (both in same place)
|
||||
ctrlPos.x = kDoubleInset;
|
||||
ctrlPos.y += TRACK_NAME_HEIGHT + kDoubleInset;
|
||||
const int nGainSliderHeight =
|
||||
size.GetHeight() - ctrlPos.y - kQuadrupleInset;
|
||||
ctrlSize.Set(kLeftSideStackWidth - kQuadrupleInset, nGainSliderHeight);
|
||||
|
||||
#ifdef USE_MIDI
|
||||
if (GetNote()) {
|
||||
mSlider_Gain =
|
||||
safenew MixerTrackSlider(
|
||||
this, ID_SLIDER_GAIN,
|
||||
/* i18n-hint: title of the MIDI Velocity slider */
|
||||
_("Velocity"),
|
||||
ctrlPos, ctrlSize, VEL_SLIDER, true,
|
||||
true, 0.0, wxVERTICAL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
mSlider_Gain =
|
||||
safenew MixerTrackSlider(
|
||||
this, ID_SLIDER_GAIN,
|
||||
/* i18n-hint: title of the Gain slider, used to adjust the volume */
|
||||
_("Gain"),
|
||||
ctrlPos, ctrlSize, DB_SLIDER, true,
|
||||
true, 0.0, wxVERTICAL);
|
||||
|
||||
mSlider_Gain =
|
||||
safenew MixerTrackSlider(
|
||||
this, ID_SLIDER_GAIN,
|
||||
/* i18n-hint: title of the Gain slider, used to adjust the volume */
|
||||
_("Gain"),
|
||||
ctrlPos, ctrlSize, DB_SLIDER, true,
|
||||
true, 0.0, wxVERTICAL);
|
||||
mSlider_Gain->SetName(_("Gain"));
|
||||
|
||||
this->UpdateGain();
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
mSlider_Velocity =
|
||||
safenew MixerTrackSlider(
|
||||
this, ID_SLIDER_VELOCITY,
|
||||
/* i18n-hint: title of the MIDI Velocity slider */
|
||||
_("Velocity"),
|
||||
ctrlPos, ctrlSize, VEL_SLIDER, true,
|
||||
true, 0.0, wxVERTICAL);
|
||||
mSlider_Velocity->SetName(_("Velocity"));
|
||||
this->UpdateVelocity();
|
||||
#endif
|
||||
|
||||
// other controls and meter at right
|
||||
|
||||
@ -329,7 +333,7 @@ WaveTrack *MixerTrackCluster::GetRight() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef USE_MIDI
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
NoteTrack *MixerTrackCluster::GetNote() const
|
||||
{
|
||||
return dynamic_cast< NoteTrack * >( mTrack );
|
||||
@ -361,6 +365,9 @@ void MixerTrackCluster::HandleResize() // For wxSizeEvents, update gain slider a
|
||||
TRACK_NAME_HEIGHT + kDoubleInset) - // mStaticText_TrackName + margin
|
||||
kQuadrupleInset; // margin below gain slider
|
||||
mSlider_Gain->SetSize(-1, nGainSliderHeight);
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
mSlider_Velocity->SetSize(-1, nGainSliderHeight);
|
||||
#endif
|
||||
|
||||
bool bSoloNone = mProject->IsSoloNone();
|
||||
|
||||
@ -384,10 +391,6 @@ void MixerTrackCluster::HandleSliderGain(const bool bWantPushState /*= false*/)
|
||||
float fValue = mSlider_Gain->Get();
|
||||
if (GetWave())
|
||||
GetWave()->SetGain(fValue);
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
else
|
||||
GetNote()->SetVelocity(fValue);
|
||||
#endif
|
||||
if (GetRight())
|
||||
GetRight()->SetGain(fValue);
|
||||
|
||||
@ -397,6 +400,20 @@ void MixerTrackCluster::HandleSliderGain(const bool bWantPushState /*= false*/)
|
||||
mProject->TP_PushState(_("Moved gain slider"), _("Gain"), UndoPush::CONSOLIDATE );
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void MixerTrackCluster::HandleSliderVelocity(const bool bWantPushState /*= false*/)
|
||||
{
|
||||
float fValue = mSlider_Velocity->Get();
|
||||
if (GetNote())
|
||||
GetNote()->SetVelocity(fValue);
|
||||
|
||||
// Update the TrackPanel correspondingly.
|
||||
mProject->RefreshTPTrack(mTrack);
|
||||
if (bWantPushState)
|
||||
mProject->TP_PushState(_("Moved velocity slider"), _("Velocity"), UndoPush::CONSOLIDATE);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MixerTrackCluster::HandleSliderPan(const bool bWantPushState /*= false*/)
|
||||
{
|
||||
float fValue = mSlider_Pan->Get();
|
||||
@ -462,28 +479,33 @@ void MixerTrackCluster::UpdateSolo()
|
||||
|
||||
void MixerTrackCluster::UpdatePan()
|
||||
{
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
if (!GetWave()) {
|
||||
mSlider_Pan->Hide();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
mSlider_Pan->Set(GetWave()->GetPan());
|
||||
}
|
||||
|
||||
void MixerTrackCluster::UpdateGain()
|
||||
{
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
if (!GetWave()) {
|
||||
mSlider_Gain->SetStyle(VEL_SLIDER);
|
||||
mSlider_Gain->Set(GetNote()->GetVelocity());
|
||||
mSlider_Gain->Hide();
|
||||
return;
|
||||
}
|
||||
mSlider_Gain->SetStyle(DB_SLIDER);
|
||||
#endif
|
||||
mSlider_Gain->Set(GetWave()->GetGain());
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void MixerTrackCluster::UpdateVelocity()
|
||||
{
|
||||
if (!GetNote()) {
|
||||
mSlider_Velocity->Hide();
|
||||
return;
|
||||
}
|
||||
mSlider_Velocity->Set(GetNote()->GetVelocity());
|
||||
}
|
||||
#endif
|
||||
|
||||
void MixerTrackCluster::UpdateMeter(const double t0, const double t1)
|
||||
{
|
||||
// NoteTracks do not (currently) register on meters. It would probably be
|
||||
@ -696,6 +718,13 @@ void MixerTrackCluster::OnSlider_Gain(wxCommandEvent& WXUNUSED(event))
|
||||
this->HandleSliderGain();
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void MixerTrackCluster::OnSlider_Velocity(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
this->HandleSliderVelocity();
|
||||
}
|
||||
#endif
|
||||
|
||||
//v void MixerTrackCluster::OnSliderScroll_Gain(wxScrollEvent& WXUNUSED(event))
|
||||
//{
|
||||
//int sliderValue = (int)(mSlider_Gain->Get()); //v mSlider_Gain->GetValue();
|
||||
@ -1209,6 +1238,16 @@ void MixerBoard::UpdateGain(const PlayableTrack* pTrack)
|
||||
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))
|
||||
|
@ -64,7 +64,9 @@ class Meter;
|
||||
class MixerBoard;
|
||||
|
||||
class Track;
|
||||
#ifdef USE_MIDI
|
||||
class NoteTrack;
|
||||
#endif
|
||||
class PlayableTrack;
|
||||
|
||||
class WaveTrack;
|
||||
@ -81,13 +83,18 @@ public:
|
||||
|
||||
WaveTrack *GetWave() const;
|
||||
WaveTrack *GetRight() const;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
NoteTrack *GetNote() const;
|
||||
#endif
|
||||
|
||||
void UpdatePrefs();
|
||||
|
||||
void HandleResize(); // For wxSizeEvents, update gain slider and meter.
|
||||
|
||||
void HandleSliderGain(const bool bWantPushState = false);
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void HandleSliderVelocity(const bool bWantPushState = false);
|
||||
#endif
|
||||
void HandleSliderPan(const bool bWantPushState = false);
|
||||
|
||||
void ResetMeter(const bool bResetClipping);
|
||||
@ -99,6 +106,9 @@ public:
|
||||
void UpdateSolo();
|
||||
void UpdatePan();
|
||||
void UpdateGain();
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void UpdateVelocity();
|
||||
#endif
|
||||
void UpdateMeter(const double t0, const double t1);
|
||||
|
||||
private:
|
||||
@ -113,6 +123,9 @@ private:
|
||||
|
||||
void OnButton_MusicalInstrument(wxCommandEvent& event);
|
||||
void OnSlider_Gain(wxCommandEvent& event);
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void OnSlider_Velocity(wxCommandEvent& event);
|
||||
#endif
|
||||
void OnSlider_Pan(wxCommandEvent& event);
|
||||
void OnButton_Mute(wxCommandEvent& event);
|
||||
void OnButton_Solo(wxCommandEvent& event);
|
||||
@ -133,6 +146,9 @@ private:
|
||||
AButton* mToggleButton_Solo;
|
||||
MixerTrackSlider* mSlider_Pan;
|
||||
MixerTrackSlider* mSlider_Gain;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
MixerTrackSlider* mSlider_Velocity;
|
||||
#endif
|
||||
Meter* mMeter;
|
||||
|
||||
public:
|
||||
@ -222,6 +238,9 @@ public:
|
||||
void UpdateSolo(const PlayableTrack* pTrack = NULL); // NULL means update for all tracks.
|
||||
void UpdatePan(const PlayableTrack* pTrack);
|
||||
void UpdateGain(const PlayableTrack* pTrack);
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void UpdateVelocity(const PlayableTrack* pTrack);
|
||||
#endif
|
||||
|
||||
void UpdateMeters(const double t1, const bool bLoopedPlay);
|
||||
|
||||
|
@ -177,11 +177,6 @@ class AUDACITY_DLL_API NoteTrack final
|
||||
void StartVScroll();
|
||||
void VScroll(int start, int end);
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
wxRect GetGainPlacementRect() const { return mGainPlacementRect; }
|
||||
void SetGainPlacementRect(const wxRect &r) { mGainPlacementRect = r; }
|
||||
#endif
|
||||
|
||||
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
|
||||
XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
|
||||
void WriteXML(XMLWriter &xmlFile) const override;
|
||||
@ -224,7 +219,6 @@ class AUDACITY_DLL_API NoteTrack final
|
||||
int mPitchHeight;
|
||||
int mVisibleChannels; // bit set of visible channels
|
||||
int mLastMidiPosition;
|
||||
wxRect mGainPlacementRect;
|
||||
};
|
||||
|
||||
#endif // USE_MIDI
|
||||
|
@ -1182,7 +1182,8 @@ void TrackPanel::HandleInterruptedDrag()
|
||||
IsGainSliding,
|
||||
IsPanSliding,
|
||||
WasOverCutLine,
|
||||
IsStretching
|
||||
IsStretching,
|
||||
IsVelocitySliding
|
||||
*/
|
||||
// The bogus id isn't used anywhere, but may help with debugging.
|
||||
// as this is sending a bogus mouse up. The mouse button is still actually down
|
||||
@ -4841,7 +4842,7 @@ void TrackPanel::HandleMutingSoloing(wxMouseEvent & event, bool solo)
|
||||
}
|
||||
|
||||
wxRect buttonRect;
|
||||
mTrackInfo.GetMuteSoloRect(rect, buttonRect, solo, HasSoloButton());
|
||||
mTrackInfo.GetMuteSoloRect(rect, buttonRect, solo, HasSoloButton(), t);
|
||||
|
||||
wxClientDC dc(this);
|
||||
|
||||
@ -4906,6 +4907,7 @@ void TrackPanel::HandleSliders(wxMouseEvent &event, bool pan)
|
||||
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
|
||||
bool panZero = false;
|
||||
#endif
|
||||
wxASSERT(mCapturedTrack->GetKind() == Track::Wave);
|
||||
|
||||
// On the Mac, we'll lose track capture if the slider dialog
|
||||
// is displayed, but it doesn't hurt to do this for all plats.
|
||||
@ -4924,20 +4926,15 @@ void TrackPanel::HandleSliders(wxMouseEvent &event, bool pan)
|
||||
|
||||
float newValue = slider->Get();
|
||||
MixerBoard* pMixerBoard = this->GetMixerBoard(); // Update mixer board, too.
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
if (capturedTrack->GetKind() == Track::Wave)
|
||||
#endif
|
||||
{
|
||||
const auto wt = static_cast<WaveTrack*>(capturedTrack);
|
||||
|
||||
// Assume linked track is wave or null
|
||||
const auto link = static_cast<WaveTrack *>(wt->GetLink());
|
||||
const auto link = static_cast<WaveTrack *>(capturedTrack->GetLink());
|
||||
|
||||
if (pan) {
|
||||
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
|
||||
panZero = wt->SetPan(newValue);
|
||||
panZero = capturedTrack->SetPan(newValue);
|
||||
#else
|
||||
wt->SetPan(newValue);
|
||||
capturedTrack->SetPan(newValue);
|
||||
#endif
|
||||
if (link)
|
||||
link->SetPan(newValue);
|
||||
@ -4947,51 +4944,57 @@ void TrackPanel::HandleSliders(wxMouseEvent &event, bool pan)
|
||||
#endif
|
||||
|
||||
if (pMixerBoard)
|
||||
pMixerBoard->UpdatePan(wt);
|
||||
pMixerBoard->UpdatePan(capturedTrack);
|
||||
}
|
||||
else {
|
||||
wt->SetGain(newValue);
|
||||
capturedTrack->SetGain(newValue);
|
||||
if (link)
|
||||
link->SetGain(newValue);
|
||||
|
||||
if (pMixerBoard)
|
||||
pMixerBoard->UpdateGain(wt);
|
||||
pMixerBoard->UpdateGain(capturedTrack);
|
||||
}
|
||||
}
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
else {
|
||||
// mCapturedTrack is not wave...
|
||||
if (!pan) {
|
||||
// .. so assume it is note
|
||||
static_cast<NoteTrack*>(mCapturedTrack)->SetVelocity(newValue);
|
||||
#ifdef EXPERIMENTAL_MIXER_BOARD
|
||||
if (pMixerBoard)
|
||||
// probably should modify UpdateGain to take a track that is
|
||||
// either a WaveTrack or a NoteTrack.
|
||||
pMixerBoard->UpdateGain((WaveTrack*)capturedTrack);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
RefreshTrack(capturedTrack);
|
||||
|
||||
if (event.ButtonUp()) {
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
if (capturedTrack->GetKind() == Track::Wave) {
|
||||
#endif
|
||||
MakeParentPushState(pan ? _("Moved pan slider") : _("Moved gain slider"),
|
||||
pan ? _("Pan") : _("Gain"),
|
||||
UndoPush::CONSOLIDATE);
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
} else {
|
||||
MakeParentPushState(_("Moved velocity slider"), _("Velocity"), UndoPush::CONSOLIDATE);
|
||||
}
|
||||
#endif
|
||||
SetCapturedTrack( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void TrackPanel::HandleVelocitySlider(wxMouseEvent &event)
|
||||
{
|
||||
wxASSERT(mCapturedTrack->GetKind() == Track::Note);
|
||||
NoteTrack *capturedTrack = (NoteTrack *) mCapturedTrack;
|
||||
|
||||
LWSlider *slider = mTrackInfo.VelocitySlider(capturedTrack, true);
|
||||
|
||||
slider->OnMouseEvent(event);
|
||||
|
||||
//If we have a double-click, do this...
|
||||
if (event.LeftDClick())
|
||||
mMouseCapture = IsUncaptured;
|
||||
|
||||
float newValue = slider->Get();
|
||||
capturedTrack->SetVelocity(newValue);
|
||||
|
||||
MixerBoard* pMixerBoard = this->GetMixerBoard(); // Update mixer board, too.
|
||||
|
||||
if (pMixerBoard) {
|
||||
pMixerBoard->UpdateVelocity(capturedTrack);
|
||||
}
|
||||
RefreshTrack(capturedTrack);
|
||||
if (event.ButtonUp()) {
|
||||
MakeParentPushState(_("Moved velocity slider"), _("Velocity"), UndoPush::CONSOLIDATE);
|
||||
SetCapturedTrack(NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// The tracks positions within the list have changed, so update the vertical
|
||||
// ruler size for the track that triggered the event.
|
||||
void TrackPanel::OnTrackListResized(wxCommandEvent & e)
|
||||
@ -5092,7 +5095,7 @@ void TrackPanel::HandleLabelClick(wxMouseEvent & event)
|
||||
{
|
||||
// DM: Check Mute and Solo buttons on WaveTracks:
|
||||
if (MuteSoloFunc(t, rect, event.m_x, event.m_y, false) ||
|
||||
MuteSoloFunc(t, rect, event.m_x, event.m_y, true))
|
||||
MuteSoloFunc(t, rect, event.m_x, event.m_y, true))
|
||||
return;
|
||||
|
||||
if (GainFunc(t, rect, event, event.m_x, event.m_y))
|
||||
@ -5107,21 +5110,11 @@ void TrackPanel::HandleLabelClick(wxMouseEvent & event)
|
||||
{
|
||||
wxRect midiRect;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
// this is an awful hack: make a NEW rectangle at an offset because
|
||||
// MuteSoloFunc thinks buttons are located below some text, e.g.
|
||||
// "Mono, 44100Hz 32-bit float", but this is not true for a Note track
|
||||
wxRect muteSoloRect(rect);
|
||||
muteSoloRect.y -= 34; // subtract the height of wave track text
|
||||
if (MuteSoloFunc(t, muteSoloRect, event.m_x, event.m_y, false) ||
|
||||
MuteSoloFunc(t, muteSoloRect, event.m_x, event.m_y, true))
|
||||
if (isleft && (MuteSoloFunc(t, rect, event.m_x, event.m_y, false) ||
|
||||
MuteSoloFunc(t, rect, event.m_x, event.m_y, true)))
|
||||
return;
|
||||
|
||||
// this is a similar hack: GainFunc expects a Wave track slider, so it's
|
||||
// looking in the wrong place. We pass it a bogus rectangle created when
|
||||
// the slider was placed to "fake" GainFunc into finding the slider in
|
||||
// its actual location.
|
||||
if (GainFunc(t, ((NoteTrack *) t)->GetGainPlacementRect(),
|
||||
event, event.m_x, event.m_y))
|
||||
if (isleft && VelocityFunc(t, rect, event, event.m_x, event.m_y))
|
||||
return;
|
||||
#endif
|
||||
mTrackInfo.GetTrackControlsRect(rect, midiRect);
|
||||
@ -5287,6 +5280,23 @@ bool TrackPanel::PanFunc(Track * t, wxRect rect, wxMouseEvent &event,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
bool TrackPanel::VelocityFunc(Track * t, wxRect rect, wxMouseEvent &event,
|
||||
int x, int y)
|
||||
{
|
||||
wxRect sliderRect;
|
||||
mTrackInfo.GetVelocityRect(rect, sliderRect);
|
||||
if (!sliderRect.Contains(x, y))
|
||||
return false;
|
||||
|
||||
SetCapturedTrack(t, IsVelocitySliding);
|
||||
mCapturedRect = rect;
|
||||
HandleVelocitySlider(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Mute or solo the given track (t). If solo is true, we're
|
||||
/// soloing, otherwise we're muting. Basically, check and see
|
||||
/// whether x and y fall within the area of the appropriate button.
|
||||
@ -5294,7 +5304,7 @@ bool TrackPanel::MuteSoloFunc(Track * t, wxRect rect, int x, int y,
|
||||
bool solo)
|
||||
{
|
||||
wxRect buttonRect;
|
||||
mTrackInfo.GetMuteSoloRect(rect, buttonRect, solo, HasSoloButton());
|
||||
mTrackInfo.GetMuteSoloRect(rect, buttonRect, solo, HasSoloButton(), t);
|
||||
if (!buttonRect.Contains(x, y))
|
||||
return false;
|
||||
|
||||
@ -6182,6 +6192,11 @@ try
|
||||
case IsPanSliding:
|
||||
HandleSliders(event, true);
|
||||
break;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
case IsVelocitySliding:
|
||||
HandleVelocitySlider(event);
|
||||
break;
|
||||
#endif
|
||||
case IsMinimizing:
|
||||
HandleMinimizing(event);
|
||||
break;
|
||||
@ -7222,11 +7237,6 @@ void TrackPanel::DrawOutside(Track * t, wxDC * dc, const wxRect & rec,
|
||||
|
||||
#ifdef USE_MIDI
|
||||
else if (bIsNote) {
|
||||
// Note tracks do not have text, e.g. "Mono, 44100Hz, 32-bit float", so
|
||||
// Mute & Solo button goes higher. To preserve existing AudioTrack code,
|
||||
// we move the buttons up by pretending track is higher (at lower y)
|
||||
rect.y -= 34;
|
||||
rect.height += 34;
|
||||
wxRect midiRect;
|
||||
mTrackInfo.GetTrackControlsRect(trackRect, midiRect);
|
||||
// Offset by height of Solo/Mute buttons:
|
||||
@ -7234,36 +7244,22 @@ void TrackPanel::DrawOutside(Track * t, wxDC * dc, const wxRect & rec,
|
||||
midiRect.height -= 21; // allow room for minimize button at bottom
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
// the offset 2 is just to leave a little space between channel buttons
|
||||
// and velocity slider (if any)
|
||||
int h = ((NoteTrack *) t)->DrawLabelControls(*dc, midiRect) + 2;
|
||||
((NoteTrack *)t)->DrawLabelControls(*dc, midiRect);
|
||||
|
||||
// Draw some lines for MuteSolo buttons:
|
||||
if (rect.height > 84) {
|
||||
AColor::Line(*dc, rect.x+48 , rect.y+50, rect.x+48, rect.y + 66);
|
||||
// bevel below mute/solo
|
||||
AColor::Line(*dc, rect.x, rect.y + 66, mTrackInfo.GetTrackInfoWidth(), rect.y + 66);
|
||||
}
|
||||
mTrackInfo.DrawMuteSolo(dc, rect, t,
|
||||
(captured && mMouseCapture == IsMuting), false, HasSoloButton());
|
||||
mTrackInfo.DrawMuteSolo(dc, rect, t,
|
||||
(captured && mMouseCapture == IsSoloing), true, HasSoloButton());
|
||||
// Draw some lines for MuteSolo buttons (normally handled by DrawBordersWithin but not done for note tracks)
|
||||
if (rect.height > 48) {
|
||||
// Note: offset up by 34 units
|
||||
AColor::Line(*dc, rect.x + 48, rect.y + 16, rect.x + 48, rect.y + 32); // between mute/solo
|
||||
AColor::Line(*dc, rect.x, rect.y + 32, kTrackInfoWidth, rect.y + 32); // below mute/solo
|
||||
}
|
||||
mTrackInfo.DrawMuteSolo(dc, rect, t,
|
||||
(captured && mMouseCapture == IsMuting), false, HasSoloButton());
|
||||
mTrackInfo.DrawMuteSolo(dc, rect, t,
|
||||
(captured && mMouseCapture == IsSoloing), true, HasSoloButton());
|
||||
|
||||
// place a volume control below channel buttons (this will
|
||||
// control an offset to midi velocity).
|
||||
// DrawVelocitySlider places slider assuming this is a Wave track
|
||||
// and using a large offset to leave room for other things,
|
||||
// so here we make a fake rectangle as if it is for a Wave
|
||||
// track, but it is offset to place the slider properly in
|
||||
// a Note track. This whole placement thing should be redesigned
|
||||
// to lay out different types of tracks and controls
|
||||
wxRect gr; // gr is gain rectangle where slider is drawn
|
||||
mTrackInfo.GetGainRect(rect, gr);
|
||||
rect.y = rect.y + h - gr.y; // ultimately want slider at rect.y + h
|
||||
rect.height = rect.height - h + gr.y;
|
||||
// save for mouse hit detect:
|
||||
((NoteTrack *) t)->SetGainPlacementRect(rect);
|
||||
mTrackInfo.DrawVelocitySlider(dc, (NoteTrack *) t, rect);
|
||||
// Place a volume control below channel buttons (this will
|
||||
// control an offset to midi velocity).
|
||||
mTrackInfo.DrawVelocitySlider(dc, (NoteTrack *)t, rect, captured);
|
||||
#endif
|
||||
}
|
||||
#endif // USE_MIDI
|
||||
@ -9015,6 +9011,22 @@ TrackInfo::TrackInfo(TrackPanel * pParentIn)
|
||||
PAN_SLIDER);
|
||||
mPanCaptured->SetDefaultValue(0.0);
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
GetVelocityRect(rect, sliderRect);
|
||||
|
||||
/* i18n-hint: Title of the Velocity slider, used to adjust the volume of note tracks */
|
||||
mVelocity = std::make_unique<LWSlider>(pParent, _("Velocity"),
|
||||
wxPoint(sliderRect.x, sliderRect.y),
|
||||
wxSize(sliderRect.width, sliderRect.height),
|
||||
VEL_SLIDER);
|
||||
mVelocity->SetDefaultValue(0.0);
|
||||
mVelocityCaptured = std::make_unique<LWSlider>(pParent, _("Velocity"),
|
||||
wxPoint(sliderRect.x, sliderRect.y),
|
||||
wxSize(sliderRect.width, sliderRect.height),
|
||||
VEL_SLIDER);
|
||||
mVelocityCaptured->SetDefaultValue(0.0);
|
||||
#endif
|
||||
|
||||
UpdatePrefs();
|
||||
}
|
||||
|
||||
@ -9043,10 +9055,20 @@ void TrackInfo::GetTitleBarRect(const wxRect & rect, wxRect & dest) const
|
||||
dest.height = kTrackInfoBtnSize;
|
||||
}
|
||||
|
||||
void TrackInfo::GetMuteSoloRect(const wxRect & rect, wxRect & dest, bool solo, bool bHasSoloButton) const
|
||||
void TrackInfo::GetMuteSoloRect(const wxRect & rect, wxRect & dest, bool solo, bool bHasSoloButton, const Track *pTrack) const
|
||||
{
|
||||
dest.x = rect.x ;
|
||||
dest.x = rect.x;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
if (pTrack->GetKind() == Track::Note)
|
||||
dest.y = rect.y + 16;
|
||||
else
|
||||
{
|
||||
wxASSERT(pTrack->GetKind() == Track::Wave);
|
||||
dest.y = rect.y + 50;
|
||||
}
|
||||
#else
|
||||
dest.y = rect.y + 50;
|
||||
#endif
|
||||
dest.width = 48;
|
||||
dest.height = kTrackInfoBtnSize;
|
||||
|
||||
@ -9076,6 +9098,16 @@ void TrackInfo::GetPanRect(const wxRect & rect, wxRect & dest) const
|
||||
dest.height = 25;
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void TrackInfo::GetVelocityRect(const wxRect & rect, wxRect & dest) const
|
||||
{
|
||||
dest.x = rect.x + 7;
|
||||
dest.y = rect.y + 100;
|
||||
dest.width = 84;
|
||||
dest.height = 25;
|
||||
}
|
||||
#endif
|
||||
|
||||
void TrackInfo::GetMinimizeRect(const wxRect & rect, wxRect &dest) const
|
||||
{
|
||||
const int kBlankWidth = kTrackInfoBtnSize + 4;
|
||||
@ -9264,7 +9296,7 @@ void TrackInfo::DrawMuteSolo(wxDC * dc, const wxRect & rect, Track * t,
|
||||
wxRect bev;
|
||||
if( solo && !bHasSoloButton )
|
||||
return;
|
||||
GetMuteSoloRect(rect, bev, solo, bHasSoloButton);
|
||||
GetMuteSoloRect(rect, bev, solo, bHasSoloButton, t);
|
||||
bev.Inflate(-1, -1);
|
||||
|
||||
if (bev.y + bev.height >= rect.y + rect.height - 19)
|
||||
@ -9342,27 +9374,6 @@ void TrackInfo::DrawMinimize(wxDC * dc, const wxRect & rect, Track * t, bool dow
|
||||
AColor::BevelTrackInfo(*dc, !down, bev);
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void TrackInfo::DrawVelocitySlider(wxDC *dc, NoteTrack *t, wxRect rect) const
|
||||
{
|
||||
wxRect gainRect;
|
||||
int index = t->GetIndex();
|
||||
|
||||
//EnsureSufficientSliders(index);
|
||||
|
||||
GetGainRect(rect, gainRect);
|
||||
if (gainRect.y + gainRect.height < rect.y + rect.height - 19) {
|
||||
auto &gain = mGain; // mGains[index];
|
||||
gain->SetStyle(VEL_SLIDER);
|
||||
GainSlider(index)->Move(wxPoint(gainRect.x, gainRect.y));
|
||||
GainSlider(index)->Set(t->GetVelocity());
|
||||
GainSlider(index)->OnPaint(*dc
|
||||
// , t->GetSelected()
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void TrackInfo::DrawSliders(wxDC *dc, WaveTrack *t, wxRect rect, bool captured) const
|
||||
{
|
||||
wxRect sliderRect;
|
||||
@ -9378,6 +9389,18 @@ void TrackInfo::DrawSliders(wxDC *dc, WaveTrack *t, wxRect rect, bool captured)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void TrackInfo::DrawVelocitySlider(wxDC *dc, NoteTrack *t, wxRect rect, bool captured) const
|
||||
{
|
||||
wxRect sliderRect;
|
||||
|
||||
GetVelocityRect(rect, sliderRect);
|
||||
if (sliderRect.y + sliderRect.height < rect.y + rect.height - 19) {
|
||||
VelocitySlider(t, captured)->OnPaint(*dc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LWSlider * TrackInfo::GainSlider(WaveTrack *t, bool captured) const
|
||||
{
|
||||
wxRect rect(kLeftInset, t->GetY() - pParent->GetViewInfo()->vpos + kTopInset, 1, t->GetHeight());
|
||||
@ -9412,6 +9435,25 @@ LWSlider * TrackInfo::PanSlider(WaveTrack *t, bool captured) const
|
||||
return (captured ? mPanCaptured : mPan).get();
|
||||
}
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
LWSlider * TrackInfo::VelocitySlider(NoteTrack *t, bool captured) const
|
||||
{
|
||||
wxRect rect(kLeftInset, t->GetY() - pParent->GetViewInfo()->vpos + kTopInset, 1, t->GetHeight());
|
||||
wxRect sliderRect;
|
||||
GetVelocityRect(rect, sliderRect);
|
||||
|
||||
wxPoint pos = sliderRect.GetPosition();
|
||||
float velocity = t->GetVelocity();
|
||||
|
||||
mVelocity->Move(pos);
|
||||
mVelocity->Set(velocity);
|
||||
mVelocityCaptured->Move(pos);
|
||||
mVelocityCaptured->Set(velocity);
|
||||
|
||||
return (captured ? mVelocityCaptured : mVelocity).get();
|
||||
}
|
||||
#endif
|
||||
|
||||
void TrackInfo::UpdatePrefs()
|
||||
{
|
||||
// Calculation of best font size depends on language, so it should be redone in case
|
||||
|
@ -92,10 +92,10 @@ private:
|
||||
void DrawTitleBar(wxDC * dc, const wxRect & rect, Track * t, bool down) const;
|
||||
void DrawMuteSolo(wxDC * dc, const wxRect & rect, Track * t, bool down, bool solo, bool bHasSoloButton) const;
|
||||
void DrawVRuler(wxDC * dc, const wxRect & rect, Track * t) const;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void DrawVelocitySlider(wxDC * dc, NoteTrack *t, wxRect rect) const ;
|
||||
#endif
|
||||
void DrawSliders(wxDC * dc, WaveTrack *t, wxRect rect, bool captured) const;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void DrawVelocitySlider(wxDC * dc, NoteTrack *t, wxRect rect, bool captured) const;
|
||||
#endif
|
||||
|
||||
// Draw the minimize button *and* the sync-lock track icon, if necessary.
|
||||
void DrawMinimize(wxDC * dc, const wxRect & rect, Track * t, bool down) const;
|
||||
@ -103,9 +103,13 @@ private:
|
||||
void GetTrackControlsRect(const wxRect & rect, wxRect &dest) const;
|
||||
void GetCloseBoxRect(const wxRect & rect, wxRect &dest) const;
|
||||
void GetTitleBarRect(const wxRect & rect, wxRect &dest) const;
|
||||
void GetMuteSoloRect(const wxRect & rect, wxRect &dest, bool solo, bool bHasSoloButton) const;
|
||||
void GetMuteSoloRect(const wxRect & rect, wxRect &dest, bool solo, bool bHasSoloButton,
|
||||
const Track *pTrack) const;
|
||||
void GetGainRect(const wxRect & rect, wxRect &dest) const;
|
||||
void GetPanRect(const wxRect & rect, wxRect &dest) const;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
void GetVelocityRect(const wxRect & rect, wxRect &dest) const;
|
||||
#endif
|
||||
void GetMinimizeRect(const wxRect & rect, wxRect &dest) const;
|
||||
void GetSyncLockIconRect(const wxRect & rect, wxRect &dest) const;
|
||||
|
||||
@ -114,7 +118,7 @@ public:
|
||||
LWSlider * PanSlider(WaveTrack *t, bool captured = false) const;
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
LWSlider *GainSlider(int index) const;
|
||||
LWSlider * VelocitySlider(NoteTrack *t, bool captured = false) const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
@ -124,6 +128,9 @@ private:
|
||||
wxFont mFont;
|
||||
std::unique_ptr<LWSlider>
|
||||
mGainCaptured, mPanCaptured, mGain, mPan;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
std::unique_ptr<LWSlider> mVelocityCaptured, mVelocity;
|
||||
#endif
|
||||
|
||||
friend class TrackPanel;
|
||||
};
|
||||
@ -415,6 +422,9 @@ protected:
|
||||
virtual void HandleMutingSoloing(wxMouseEvent & event, bool solo);
|
||||
virtual void HandleMinimizing(wxMouseEvent & event);
|
||||
virtual void HandleSliders(wxMouseEvent &event, bool pan);
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
virtual void HandleVelocitySlider(wxMouseEvent &event);
|
||||
#endif
|
||||
|
||||
|
||||
// These *Func methods are used in TrackPanel::HandleLabelClick to set up
|
||||
@ -434,6 +444,10 @@ protected:
|
||||
int x, int y);
|
||||
virtual bool PanFunc(Track * t, wxRect rect, wxMouseEvent &event,
|
||||
int x, int y);
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
virtual bool VelocityFunc(Track * t, wxRect rect, wxMouseEvent &event,
|
||||
int x, int y);
|
||||
#endif
|
||||
|
||||
|
||||
virtual void MakeParentRedrawScrollbars();
|
||||
@ -747,6 +761,9 @@ protected:
|
||||
IsStretching,
|
||||
#endif
|
||||
IsZooming,
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
IsVelocitySliding,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
@ -54,6 +54,7 @@ enum CommandFlag : unsigned long long
|
||||
PausedFlag = 0x200000000ULL, // jkc
|
||||
NotPausedFlag = 0x400000000ULL, // jkc
|
||||
HasWaveDataFlag = 0x800000000ULL, // jkc
|
||||
PlayableTracksExistFlag = 0x1000000000ULL,
|
||||
|
||||
NoFlagsSpecifed = ~0ULL
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user