mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-08 08:01:19 +02:00
Move AudacityProject::DoTrackMute and DoTrackSolo...
... also fixed the bug that muting and soloing from the mixer board did not update accessibility.
This commit is contained in:
parent
51c3541716
commit
50f8579475
@ -140,6 +140,11 @@ namespace TrackActions {
|
|||||||
};
|
};
|
||||||
/// Move a track up, down, to top or to bottom.
|
/// Move a track up, down, to top or to bottom.
|
||||||
void DoMoveTrack( AudacityProject &project, Track* target, MoveChoice choice );
|
void DoMoveTrack( AudacityProject &project, Track* target, MoveChoice choice );
|
||||||
|
// "exclusive" mute means mute the chosen track and unmute all others.
|
||||||
|
void DoTrackMute( AudacityProject &project, Track *pTrack, bool exclusive );
|
||||||
|
// Type of solo (standard or simple) follows the set preference, unless
|
||||||
|
// exclusive == true, which causes the opposite behavior.
|
||||||
|
void DoTrackSolo( AudacityProject &project, Track *pTrack, bool exclusive );
|
||||||
void DoRemoveTrack( AudacityProject &project, Track * toRemove );
|
void DoRemoveTrack( AudacityProject &project, Track * toRemove );
|
||||||
void DoRemoveTracks( AudacityProject & );
|
void DoRemoveTracks( AudacityProject & );
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#include "Audacity.h"
|
#include "Audacity.h"
|
||||||
|
#include "Menus.h"
|
||||||
#include "MixerBoard.h"
|
#include "MixerBoard.h"
|
||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
@ -744,7 +745,8 @@ void MixerTrackCluster::OnSlider_Pan(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
void MixerTrackCluster::OnButton_Mute(wxCommandEvent& WXUNUSED(event))
|
void MixerTrackCluster::OnButton_Mute(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
mProject->HandleTrackMute(mTrack.get(), mToggleButton_Mute->WasShiftDown());
|
TrackActions::DoTrackMute(
|
||||||
|
*mProject, mTrack.get(), mToggleButton_Mute->WasShiftDown());
|
||||||
mToggleButton_Mute->SetAlternateIdx(mTrack->GetSolo() ? 1 : 0);
|
mToggleButton_Mute->SetAlternateIdx(mTrack->GetSolo() ? 1 : 0);
|
||||||
|
|
||||||
// Update the TrackPanel correspondingly.
|
// Update the TrackPanel correspondingly.
|
||||||
@ -759,7 +761,8 @@ void MixerTrackCluster::OnButton_Mute(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
void MixerTrackCluster::OnButton_Solo(wxCommandEvent& WXUNUSED(event))
|
void MixerTrackCluster::OnButton_Solo(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
mProject->HandleTrackSolo(mTrack.get(), mToggleButton_Solo->WasShiftDown());
|
TrackActions::DoTrackSolo(
|
||||||
|
*mProject, mTrack.get(), mToggleButton_Solo->WasShiftDown());
|
||||||
bool bIsSolo = mTrack->GetSolo();
|
bool bIsSolo = mTrack->GetSolo();
|
||||||
mToggleButton_Mute->SetAlternateIdx(bIsSolo ? 1 : 0);
|
mToggleButton_Mute->SetAlternateIdx(bIsSolo ? 1 : 0);
|
||||||
|
|
||||||
|
107
src/Project.cpp
107
src/Project.cpp
@ -5312,113 +5312,6 @@ void AudacityProject::SetSyncLock(bool flag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudacityProject::DoTrackMute(Track *t, bool exclusive)
|
|
||||||
{
|
|
||||||
HandleTrackMute(t, exclusive);
|
|
||||||
|
|
||||||
mTrackPanel->UpdateAccessibility();
|
|
||||||
mTrackPanel->Refresh(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudacityProject::DoTrackSolo(Track *t, bool exclusive)
|
|
||||||
{
|
|
||||||
HandleTrackSolo(t, exclusive);
|
|
||||||
|
|
||||||
mTrackPanel->UpdateAccessibility();
|
|
||||||
mTrackPanel->Refresh(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudacityProject::HandleTrackMute(Track *t, const bool exclusive)
|
|
||||||
{
|
|
||||||
// Whatever t is, replace with lead channel
|
|
||||||
t = *GetTracks()->FindLeader(t);
|
|
||||||
|
|
||||||
// "exclusive" mute means mute the chosen track and unmute all others.
|
|
||||||
if (exclusive) {
|
|
||||||
for (auto leader : GetTracks()->Leaders<PlayableTrack>()) {
|
|
||||||
const auto group = TrackList::Channels(leader);
|
|
||||||
bool chosen = (t == leader);
|
|
||||||
for (auto channel : group)
|
|
||||||
channel->SetMute( chosen ),
|
|
||||||
channel->SetSolo( false );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Normal click toggles this track.
|
|
||||||
auto pt = dynamic_cast<PlayableTrack *>( t );
|
|
||||||
if (!pt)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool wasMute = pt->GetMute();
|
|
||||||
for (auto channel : TrackList::Channels(pt))
|
|
||||||
channel->SetMute( !wasMute );
|
|
||||||
|
|
||||||
if (IsSoloSimple() || IsSoloNone())
|
|
||||||
{
|
|
||||||
// We also set a solo indicator if we have just one track / stereo pair playing.
|
|
||||||
// in a group of more than one playable tracks.
|
|
||||||
// otherwise clear solo on everything.
|
|
||||||
|
|
||||||
auto range = GetTracks()->Leaders<PlayableTrack>();
|
|
||||||
auto nPlayableTracks = range.size();
|
|
||||||
auto nPlaying = (range - &PlayableTrack::GetMute).size();
|
|
||||||
|
|
||||||
for (auto track : GetTracks()->Any<PlayableTrack>())
|
|
||||||
// will set both of a stereo pair
|
|
||||||
track->SetSolo( (nPlaying==1) && (nPlayableTracks > 1 ) && !track->GetMute() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ModifyState(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type of solo (standard or simple) follows the set preference, unless
|
|
||||||
// alternate == true, which causes the opposite behavior.
|
|
||||||
void AudacityProject::HandleTrackSolo(Track *t, const bool alternate)
|
|
||||||
{
|
|
||||||
// Whatever t is, replace with lead channel
|
|
||||||
t = *GetTracks()->FindLeader(t);
|
|
||||||
|
|
||||||
const auto pt = dynamic_cast<PlayableTrack *>( t );
|
|
||||||
if (!pt)
|
|
||||||
return;
|
|
||||||
bool bWasSolo = pt->GetSolo();
|
|
||||||
|
|
||||||
bool bSoloMultiple = !IsSoloSimple() ^ alternate;
|
|
||||||
|
|
||||||
// Standard and Simple solo have opposite defaults:
|
|
||||||
// Standard - Behaves as individual buttons, shift=radio buttons
|
|
||||||
// Simple - Behaves as radio buttons, shift=individual
|
|
||||||
// In addition, Simple solo will mute/unmute tracks
|
|
||||||
// when in standard radio button mode.
|
|
||||||
if ( bSoloMultiple )
|
|
||||||
{
|
|
||||||
for (auto channel : TrackList::Channels(pt))
|
|
||||||
channel->SetSolo( !bWasSolo );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Normal click solo this track only, mute everything else.
|
|
||||||
// OR unmute and unsolo everything.
|
|
||||||
for (auto leader : GetTracks()->Leaders<PlayableTrack>()) {
|
|
||||||
const auto group = TrackList::Channels(leader);
|
|
||||||
bool chosen = (t == leader);
|
|
||||||
for (auto channel : group) {
|
|
||||||
if (chosen) {
|
|
||||||
channel->SetSolo( !bWasSolo );
|
|
||||||
if( IsSoloSimple() )
|
|
||||||
channel->SetMute( false );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
channel->SetSolo( false );
|
|
||||||
if( IsSoloSimple() )
|
|
||||||
channel->SetMute( !bWasSolo );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ModifyState(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keyboard capture
|
// Keyboard capture
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -425,16 +425,6 @@ public:
|
|||||||
bool IsSyncLocked();
|
bool IsSyncLocked();
|
||||||
void SetSyncLock(bool flag);
|
void SetSyncLock(bool flag);
|
||||||
|
|
||||||
void DoTrackMute(Track *pTrack, bool exclusive);
|
|
||||||
void DoTrackSolo(Track *pTrack, bool exclusive);
|
|
||||||
|
|
||||||
// "exclusive" mute means mute the chosen track and unmute all others.
|
|
||||||
void HandleTrackMute(Track *t, const bool exclusive);
|
|
||||||
|
|
||||||
// Type of solo (standard or simple) follows the set preference, unless
|
|
||||||
// alternate == true, which causes the opposite behavior.
|
|
||||||
void HandleTrackSolo(Track *t, const bool alternate);
|
|
||||||
|
|
||||||
// Snap To
|
// Snap To
|
||||||
|
|
||||||
void SetSnapTo(int snap);
|
void SetSnapTo(int snap);
|
||||||
|
@ -575,6 +575,107 @@ void DoRemoveTracks( AudacityProject &project )
|
|||||||
trackPanel->Refresh(false);
|
trackPanel->Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DoTrackMute(AudacityProject &project, Track *t, bool exclusive)
|
||||||
|
{
|
||||||
|
auto &tracks = *project.GetTracks();
|
||||||
|
auto &trackPanel = *project.GetTrackPanel();
|
||||||
|
|
||||||
|
// Whatever t is, replace with lead channel
|
||||||
|
t = *tracks.FindLeader(t);
|
||||||
|
|
||||||
|
// "exclusive" mute means mute the chosen track and unmute all others.
|
||||||
|
if (exclusive) {
|
||||||
|
for (auto leader : tracks.Leaders<PlayableTrack>()) {
|
||||||
|
const auto group = TrackList::Channels(leader);
|
||||||
|
bool chosen = (t == leader);
|
||||||
|
for (auto channel : group)
|
||||||
|
channel->SetMute( chosen ),
|
||||||
|
channel->SetSolo( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Normal click toggles this track.
|
||||||
|
auto pt = dynamic_cast<PlayableTrack *>( t );
|
||||||
|
if (!pt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool wasMute = pt->GetMute();
|
||||||
|
for (auto channel : TrackList::Channels(pt))
|
||||||
|
channel->SetMute( !wasMute );
|
||||||
|
|
||||||
|
if (project.IsSoloSimple() || project.IsSoloNone())
|
||||||
|
{
|
||||||
|
// We also set a solo indicator if we have just one track / stereo pair playing.
|
||||||
|
// in a group of more than one playable tracks.
|
||||||
|
// otherwise clear solo on everything.
|
||||||
|
|
||||||
|
auto range = tracks.Leaders<PlayableTrack>();
|
||||||
|
auto nPlayableTracks = range.size();
|
||||||
|
auto nPlaying = (range - &PlayableTrack::GetMute).size();
|
||||||
|
|
||||||
|
for (auto track : tracks.Any<PlayableTrack>())
|
||||||
|
// will set both of a stereo pair
|
||||||
|
track->SetSolo( (nPlaying==1) && (nPlayableTracks > 1 ) && !track->GetMute() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project.ModifyState(true);
|
||||||
|
|
||||||
|
trackPanel.UpdateAccessibility();
|
||||||
|
trackPanel.Refresh(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoTrackSolo(AudacityProject &project, Track *t, bool exclusive)
|
||||||
|
{
|
||||||
|
auto &tracks = *project.GetTracks();
|
||||||
|
auto &trackPanel = *project.GetTrackPanel();
|
||||||
|
|
||||||
|
// Whatever t is, replace with lead channel
|
||||||
|
t = *tracks.FindLeader(t);
|
||||||
|
|
||||||
|
const auto pt = dynamic_cast<PlayableTrack *>( t );
|
||||||
|
if (!pt)
|
||||||
|
return;
|
||||||
|
bool bWasSolo = pt->GetSolo();
|
||||||
|
|
||||||
|
bool bSoloMultiple = !project.IsSoloSimple() ^ exclusive;
|
||||||
|
|
||||||
|
// Standard and Simple solo have opposite defaults:
|
||||||
|
// Standard - Behaves as individual buttons, shift=radio buttons
|
||||||
|
// Simple - Behaves as radio buttons, shift=individual
|
||||||
|
// In addition, Simple solo will mute/unmute tracks
|
||||||
|
// when in standard radio button mode.
|
||||||
|
if ( bSoloMultiple )
|
||||||
|
{
|
||||||
|
for (auto channel : TrackList::Channels(pt))
|
||||||
|
channel->SetSolo( !bWasSolo );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Normal click solo this track only, mute everything else.
|
||||||
|
// OR unmute and unsolo everything.
|
||||||
|
for (auto leader : tracks.Leaders<PlayableTrack>()) {
|
||||||
|
const auto group = TrackList::Channels(leader);
|
||||||
|
bool chosen = (t == leader);
|
||||||
|
for (auto channel : group) {
|
||||||
|
if (chosen) {
|
||||||
|
channel->SetSolo( !bWasSolo );
|
||||||
|
if( project.IsSoloSimple() )
|
||||||
|
channel->SetMute( false );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
channel->SetSolo( false );
|
||||||
|
if( project.IsSoloSimple() )
|
||||||
|
channel->SetMute( !bWasSolo );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project.ModifyState(true);
|
||||||
|
|
||||||
|
trackPanel.UpdateAccessibility();
|
||||||
|
trackPanel.Refresh(false);
|
||||||
|
}
|
||||||
|
|
||||||
void DoRemoveTrack(AudacityProject &project, Track * toRemove)
|
void DoRemoveTrack(AudacityProject &project, Track * toRemove)
|
||||||
{
|
{
|
||||||
auto &tracks = *project.GetTracks();
|
auto &tracks = *project.GetTracks();
|
||||||
@ -1234,7 +1335,7 @@ void OnTrackMute(const CommandContext &context)
|
|||||||
|
|
||||||
const auto track = trackPanel->GetFocusedTrack();
|
const auto track = trackPanel->GetFocusedTrack();
|
||||||
if (track) track->TypeSwitch( [&](PlayableTrack *t) {
|
if (track) track->TypeSwitch( [&](PlayableTrack *t) {
|
||||||
project.DoTrackMute(t, false);
|
DoTrackMute(project, t, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1245,7 +1346,7 @@ void OnTrackSolo(const CommandContext &context)
|
|||||||
|
|
||||||
const auto track = trackPanel->GetFocusedTrack();
|
const auto track = trackPanel->GetFocusedTrack();
|
||||||
if (track) track->TypeSwitch( [&](PlayableTrack *t) {
|
if (track) track->TypeSwitch( [&](PlayableTrack *t) {
|
||||||
project.DoTrackSolo(t, false);
|
DoTrackSolo(project, t, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
|
|
||||||
#include "../../../commands/CommandManager.h"
|
#include "../../../commands/CommandManager.h"
|
||||||
#include "../../../HitTestResult.h"
|
#include "../../../HitTestResult.h"
|
||||||
|
#include "../../../Menus.h"
|
||||||
#include "../../../Project.h"
|
#include "../../../Project.h"
|
||||||
#include "../../../RefreshCode.h"
|
#include "../../../RefreshCode.h"
|
||||||
#include "../../../Track.h"
|
#include "../../../Track.h"
|
||||||
@ -33,7 +34,7 @@ UIHandle::Result MuteButtonHandle::CommitChanges
|
|||||||
{
|
{
|
||||||
auto pTrack = mpTrack.lock();
|
auto pTrack = mpTrack.lock();
|
||||||
if ( dynamic_cast< PlayableTrack* >( pTrack.get() ) )
|
if ( dynamic_cast< PlayableTrack* >( pTrack.get() ) )
|
||||||
pProject->DoTrackMute(pTrack.get(), event.ShiftDown());
|
TrackActions::DoTrackMute(*pProject, pTrack.get(), event.ShiftDown());
|
||||||
|
|
||||||
return RefreshCode::RefreshNone;
|
return RefreshCode::RefreshNone;
|
||||||
}
|
}
|
||||||
@ -89,7 +90,7 @@ UIHandle::Result SoloButtonHandle::CommitChanges
|
|||||||
{
|
{
|
||||||
auto pTrack = mpTrack.lock();
|
auto pTrack = mpTrack.lock();
|
||||||
if ( dynamic_cast< PlayableTrack* >( pTrack.get() ) )
|
if ( dynamic_cast< PlayableTrack* >( pTrack.get() ) )
|
||||||
pProject->DoTrackSolo(pTrack.get(), event.ShiftDown());
|
TrackActions::DoTrackSolo(*pProject, pTrack.get(), event.ShiftDown());
|
||||||
|
|
||||||
return RefreshCode::RefreshNone;
|
return RefreshCode::RefreshNone;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user