mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-03 09:09:47 +02:00
Merge branch 'master' into scrubbing
This commit is contained in:
commit
7e2380d496
@ -69,6 +69,8 @@ from there. Audacity will look for a file called "Pause.png".
|
|||||||
DEFINE_IMAGE( bmpAppendRecordDisabled, wxImage( 16, 16 ), wxT("AppendRecordDisabled"));
|
DEFINE_IMAGE( bmpAppendRecordDisabled, wxImage( 16, 16 ), wxT("AppendRecordDisabled"));
|
||||||
DEFINE_IMAGE( bmpScrubDisabled, wxImage( 16, 16 ), wxT("ScrubDisabled"));
|
DEFINE_IMAGE( bmpScrubDisabled, wxImage( 16, 16 ), wxT("ScrubDisabled"));
|
||||||
DEFINE_IMAGE( bmpScrub, wxImage( 16, 16 ), wxT("Scrub"));
|
DEFINE_IMAGE( bmpScrub, wxImage( 16, 16 ), wxT("Scrub"));
|
||||||
|
DEFINE_IMAGE( bmpSeekDisabled, wxImage( 24, 16 ), wxT("SeekDisabled"));
|
||||||
|
DEFINE_IMAGE( bmpSeek, wxImage( 24, 16 ), wxT("Seek"));
|
||||||
|
|
||||||
SET_THEME_FLAGS( resFlagNewLine );
|
SET_THEME_FLAGS( resFlagNewLine );
|
||||||
DEFINE_IMAGE( bmpUpButtonLarge, wxImage( 48, 48 ), wxT("UpButtonLarge"));
|
DEFINE_IMAGE( bmpUpButtonLarge, wxImage( 48, 48 ), wxT("UpButtonLarge"));
|
||||||
@ -123,6 +125,9 @@ from there. Audacity will look for a file called "Pause.png".
|
|||||||
DEFINE_IMAGE( bmpMic, wxImage( 25, 25 ), wxT("Mic"));
|
DEFINE_IMAGE( bmpMic, wxImage( 25, 25 ), wxT("Mic"));
|
||||||
DEFINE_IMAGE( bmpSpeaker, wxImage( 25, 25 ), wxT("Speaker"));
|
DEFINE_IMAGE( bmpSpeaker, wxImage( 25, 25 ), wxT("Speaker"));
|
||||||
|
|
||||||
|
DEFINE_IMAGE( bmpPinnedPlayRecordHead, wxImage( 27, 27 ), wxT("PinnedPlayRecordHead"));
|
||||||
|
DEFINE_IMAGE( bmpUnpinnedPlayRecordHead, wxImage( 27, 27 ), wxT("UnpinnedPlayRecordHead"));
|
||||||
|
|
||||||
SET_THEME_FLAGS( resFlagPaired );
|
SET_THEME_FLAGS( resFlagPaired );
|
||||||
DEFINE_IMAGE( bmpZoomFit, wxImage( 27, 27 ), wxT("ZoomFit"));
|
DEFINE_IMAGE( bmpZoomFit, wxImage( 27, 27 ), wxT("ZoomFit"));
|
||||||
DEFINE_IMAGE( bmpZoomFitDisabled, wxImage( 27, 27 ), wxT("ZoomFitDisabled"));
|
DEFINE_IMAGE( bmpZoomFitDisabled, wxImage( 27, 27 ), wxT("ZoomFitDisabled"));
|
||||||
|
@ -69,6 +69,7 @@ simplifies construction of menu items.
|
|||||||
#include "export/Export.h"
|
#include "export/Export.h"
|
||||||
#include "export/ExportMultiple.h"
|
#include "export/ExportMultiple.h"
|
||||||
#include "prefs/PrefsDialog.h"
|
#include "prefs/PrefsDialog.h"
|
||||||
|
#include "prefs/PlaybackPrefs.h"
|
||||||
#include "ShuttleGui.h"
|
#include "ShuttleGui.h"
|
||||||
#include "HistoryWindow.h"
|
#include "HistoryWindow.h"
|
||||||
#include "LyricsWindow.h"
|
#include "LyricsWindow.h"
|
||||||
@ -772,6 +773,11 @@ void AudacityProject::CreateMenusAndCommands()
|
|||||||
|
|
||||||
c->AddSeparator();
|
c->AddSeparator();
|
||||||
|
|
||||||
|
c->AddCheck(wxT("PinnedHead"), _("Pinned Recording/Playback Head"),
|
||||||
|
FN(OnTogglePinnedHead), 0,
|
||||||
|
// Switching of scrolling on and off is permitted even during transport
|
||||||
|
AlwaysEnabledFlag, AlwaysEnabledFlag);
|
||||||
|
|
||||||
c->AddCheck(wxT("Duplex"), _("&Overdub (on/off)"), FN(OnTogglePlayRecording), 0);
|
c->AddCheck(wxT("Duplex"), _("&Overdub (on/off)"), FN(OnTogglePlayRecording), 0);
|
||||||
c->AddCheck(wxT("SWPlaythrough"), _("So&ftware Playthrough (on/off)"), FN(OnToggleSWPlaythrough), 0);
|
c->AddCheck(wxT("SWPlaythrough"), _("So&ftware Playthrough (on/off)"), FN(OnToggleSWPlaythrough), 0);
|
||||||
|
|
||||||
@ -1840,6 +1846,10 @@ void AudacityProject::ModifyToolbarMenus()
|
|||||||
gPrefs->Read(wxT("/AudioIO/AutomatedInputLevelAdjustment"),&active, false);
|
gPrefs->Read(wxT("/AudioIO/AutomatedInputLevelAdjustment"),&active, false);
|
||||||
mCommandManager.Check(wxT("AutomatedInputLevelAdjustmentOnOff"), active);
|
mCommandManager.Check(wxT("AutomatedInputLevelAdjustmentOnOff"), active);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
active = PlaybackPrefs::GetPinnedHeadPreference();
|
||||||
|
mCommandManager.Check(wxT("PinnedHead"), active);
|
||||||
|
|
||||||
gPrefs->Read(wxT("/AudioIO/Duplex"),&active, true);
|
gPrefs->Read(wxT("/AudioIO/Duplex"),&active, true);
|
||||||
mCommandManager.Check(wxT("Duplex"), active);
|
mCommandManager.Check(wxT("Duplex"), active);
|
||||||
gPrefs->Read(wxT("/AudioIO/SWPlaythrough"),&active, false);
|
gPrefs->Read(wxT("/AudioIO/SWPlaythrough"),&active, false);
|
||||||
@ -2360,6 +2370,27 @@ void AudacityProject::OnToggleSoundActivated()
|
|||||||
ModifyAllProjectToolbarMenus();
|
ModifyAllProjectToolbarMenus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudacityProject::OnTogglePinnedHead()
|
||||||
|
{
|
||||||
|
bool value = !PlaybackPrefs::GetPinnedHeadPreference();
|
||||||
|
PlaybackPrefs::SetPinnedHeadPreference(value, true);
|
||||||
|
ModifyAllProjectToolbarMenus();
|
||||||
|
|
||||||
|
// Change what happens in case transport is in progress right now
|
||||||
|
auto ctb = GetActiveProject()->GetControlToolBar();
|
||||||
|
if (ctb)
|
||||||
|
ctb->StartScrollingIfPreferred();
|
||||||
|
|
||||||
|
auto ruler = GetRulerPanel();
|
||||||
|
if (ruler)
|
||||||
|
// Update button image
|
||||||
|
ruler->UpdateButtonStates();
|
||||||
|
|
||||||
|
auto &scrubber = GetScrubber();
|
||||||
|
if (scrubber.HasStartedScrubbing())
|
||||||
|
scrubber.SetScrollScrubbing(value);
|
||||||
|
}
|
||||||
|
|
||||||
void AudacityProject::OnTogglePlayRecording()
|
void AudacityProject::OnTogglePlayRecording()
|
||||||
{
|
{
|
||||||
bool Duplex;
|
bool Duplex;
|
||||||
|
@ -313,6 +313,7 @@ void OnResetToolBars();
|
|||||||
|
|
||||||
void OnSoundActivated();
|
void OnSoundActivated();
|
||||||
void OnToggleSoundActivated();
|
void OnToggleSoundActivated();
|
||||||
|
void OnTogglePinnedHead();
|
||||||
void OnTogglePlayRecording();
|
void OnTogglePlayRecording();
|
||||||
void OnToggleSWPlaythrough();
|
void OnToggleSWPlaythrough();
|
||||||
#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
|
#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
|
||||||
|
@ -890,7 +890,7 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
|
|||||||
mRuler = safenew AdornedRulerPanel( this,
|
mRuler = safenew AdornedRulerPanel( this,
|
||||||
wxID_ANY,
|
wxID_ANY,
|
||||||
wxDefaultPosition,
|
wxDefaultPosition,
|
||||||
wxSize( -1, AdornedRulerPanel::GetRulerHeight() ),
|
wxSize( -1, AdornedRulerPanel::GetRulerHeight(false) ),
|
||||||
&mViewInfo );
|
&mViewInfo );
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -65,6 +65,7 @@ and use it for toolbar and window layouts too.
|
|||||||
#include "Project.h"
|
#include "Project.h"
|
||||||
#include "toolbars/ToolBar.h"
|
#include "toolbars/ToolBar.h"
|
||||||
#include "toolbars/ToolManager.h"
|
#include "toolbars/ToolManager.h"
|
||||||
|
#include "widgets/Ruler.h"
|
||||||
#include "ImageManipulation.h"
|
#include "ImageManipulation.h"
|
||||||
#include "Theme.h"
|
#include "Theme.h"
|
||||||
#include "Experimental.h"
|
#include "Experimental.h"
|
||||||
@ -230,6 +231,7 @@ void Theme::ApplyUpdatedImages()
|
|||||||
if( pToolBar )
|
if( pToolBar )
|
||||||
pToolBar->ReCreateButtons();
|
pToolBar->ReCreateButtons();
|
||||||
}
|
}
|
||||||
|
p->GetRulerPanel()->ReCreateButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Theme::RegisterImages()
|
void Theme::RegisterImages()
|
||||||
@ -958,27 +960,41 @@ void ThemeBase::SaveComponents()
|
|||||||
if( (mBitmapFlags[i] & resFlagInternal)==0)
|
if( (mBitmapFlags[i] & resFlagInternal)==0)
|
||||||
{
|
{
|
||||||
FileName = FileNames::ThemeComponent( mBitmapNames[i] );
|
FileName = FileNames::ThemeComponent( mBitmapNames[i] );
|
||||||
if( !wxFileExists( FileName ))
|
if( wxFileExists( FileName ))
|
||||||
{
|
{
|
||||||
if( !mImages[i].SaveFile( FileName, wxBITMAP_TYPE_PNG ))
|
++n;
|
||||||
{
|
break;
|
||||||
wxMessageBox(
|
|
||||||
wxString::Format(
|
|
||||||
_("Audacity could not save file:\n %s"),
|
|
||||||
FileName.c_str() ));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( n==0 )
|
|
||||||
|
if (n > 0)
|
||||||
{
|
{
|
||||||
wxMessageBox(
|
auto result =
|
||||||
wxString::Format(
|
wxMessageBox(
|
||||||
_("All required files in:\n %s\nwere already present."),
|
wxString::Format(
|
||||||
FileNames::ThemeComponentsDir().c_str() ));
|
_("Some required files in:\n %s\nwere already present. Overwrite?"),
|
||||||
return;
|
FileNames::ThemeComponentsDir().c_str()),
|
||||||
|
wxMessageBoxCaptionStr,
|
||||||
|
wxYES_NO | wxNO_DEFAULT);
|
||||||
|
if(result == wxNO)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<(int)mImages.GetCount();i++)
|
||||||
|
{
|
||||||
|
if( (mBitmapFlags[i] & resFlagInternal)==0)
|
||||||
|
{
|
||||||
|
FileName = FileNames::ThemeComponent( mBitmapNames[i] );
|
||||||
|
if( !mImages[i].SaveFile( FileName, wxBITMAP_TYPE_PNG ))
|
||||||
|
{
|
||||||
|
wxMessageBox(
|
||||||
|
wxString::Format(
|
||||||
|
_("Audacity could not save file:\n %s"),
|
||||||
|
FileName.c_str() ));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wxMessageBox(
|
wxMessageBox(
|
||||||
wxString::Format(
|
wxString::Format(
|
||||||
|
8521
src/ThemeAsCeeCode.h
8521
src/ThemeAsCeeCode.h
File diff suppressed because it is too large
Load Diff
@ -19,13 +19,25 @@
|
|||||||
*//********************************************************************/
|
*//********************************************************************/
|
||||||
|
|
||||||
#include "../Audacity.h"
|
#include "../Audacity.h"
|
||||||
|
#include "PlaybackPrefs.h"
|
||||||
|
|
||||||
#include <wx/defs.h>
|
#include <wx/defs.h>
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
|
|
||||||
#include "../ShuttleGui.h"
|
#include "../ShuttleGui.h"
|
||||||
|
#include "../Prefs.h"
|
||||||
|
|
||||||
#include "PlaybackPrefs.h"
|
namespace {
|
||||||
|
const wxChar *PinnedHeadPreferenceKey()
|
||||||
|
{
|
||||||
|
return wxT("/AudioIO/PinnedHead");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PinnedHeadPreferenceDefault()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PlaybackPrefs::PlaybackPrefs(wxWindow * parent)
|
PlaybackPrefs::PlaybackPrefs(wxWindow * parent)
|
||||||
: PrefsPanel(parent, _("Playback"))
|
: PrefsPanel(parent, _("Playback"))
|
||||||
@ -113,6 +125,11 @@ void PlaybackPrefs::PopulateOrExchange(ShuttleGui & S)
|
|||||||
S.EndThreeColumn();
|
S.EndThreeColumn();
|
||||||
}
|
}
|
||||||
S.EndStatic();
|
S.EndStatic();
|
||||||
|
|
||||||
|
// This affects recording too, though it is in playback preferences.
|
||||||
|
S.TieCheckBox(_("Pinned playback/recording head"),
|
||||||
|
PinnedHeadPreferenceKey(),
|
||||||
|
PinnedHeadPreferenceDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlaybackPrefs::Apply()
|
bool PlaybackPrefs::Apply()
|
||||||
@ -123,8 +140,21 @@ bool PlaybackPrefs::Apply()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlaybackPrefs::GetPinnedHeadPreference()
|
||||||
|
{
|
||||||
|
return gPrefs->ReadBool(PinnedHeadPreferenceKey(), PinnedHeadPreferenceDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaybackPrefs::SetPinnedHeadPreference(bool value, bool flush)
|
||||||
|
{
|
||||||
|
gPrefs->Write(PinnedHeadPreferenceKey(), value);
|
||||||
|
if(flush)
|
||||||
|
gPrefs->Flush();
|
||||||
|
}
|
||||||
|
|
||||||
PrefsPanel *PlaybackPrefsFactory::Create(wxWindow *parent)
|
PrefsPanel *PlaybackPrefsFactory::Create(wxWindow *parent)
|
||||||
{
|
{
|
||||||
wxASSERT(parent); // to justify safenew
|
wxASSERT(parent); // to justify safenew
|
||||||
return safenew PlaybackPrefs(parent);
|
return safenew PlaybackPrefs(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,9 @@ class PlaybackPrefs final : public PrefsPanel
|
|||||||
virtual ~PlaybackPrefs();
|
virtual ~PlaybackPrefs();
|
||||||
bool Apply() override;
|
bool Apply() override;
|
||||||
|
|
||||||
|
static bool GetPinnedHeadPreference();
|
||||||
|
static void SetPinnedHeadPreference(bool value, bool flush = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Populate();
|
void Populate();
|
||||||
void PopulateOrExchange(ShuttleGui & S);
|
void PopulateOrExchange(ShuttleGui & S);
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
#include "../widgets/Meter.h"
|
#include "../widgets/Meter.h"
|
||||||
|
|
||||||
#include "../tracks/ui/Scrubbing.h"
|
#include "../tracks/ui/Scrubbing.h"
|
||||||
|
#include "../prefs/PlaybackPrefs.h"
|
||||||
|
|
||||||
IMPLEMENT_CLASS(ControlToolBar, ToolBar);
|
IMPLEMENT_CLASS(ControlToolBar, ToolBar);
|
||||||
|
|
||||||
@ -129,7 +130,7 @@ AButton *ControlToolBar::MakeButton(teBmps eEnabledUp, teBmps eEnabledDown, teBm
|
|||||||
bool processdownevents,
|
bool processdownevents,
|
||||||
const wxChar *label)
|
const wxChar *label)
|
||||||
{
|
{
|
||||||
AButton *r = ToolBar::MakeButton(
|
AButton *r = ToolBar::MakeButton(this,
|
||||||
bmpRecoloredUpLarge, bmpRecoloredDownLarge, bmpRecoloredHiliteLarge,
|
bmpRecoloredUpLarge, bmpRecoloredDownLarge, bmpRecoloredHiliteLarge,
|
||||||
eEnabledUp, eEnabledDown, eDisabled,
|
eEnabledUp, eEnabledDown, eDisabled,
|
||||||
wxWindowID(id),
|
wxWindowID(id),
|
||||||
@ -167,6 +168,8 @@ void ControlToolBar::Populate()
|
|||||||
bmpCutPreview, bmpCutPreview, bmpCutPreviewDisabled);
|
bmpCutPreview, bmpCutPreview, bmpCutPreviewDisabled);
|
||||||
MakeAlternateImages(*mPlay, 3,
|
MakeAlternateImages(*mPlay, 3,
|
||||||
bmpScrub, bmpScrub, bmpScrubDisabled);
|
bmpScrub, bmpScrub, bmpScrubDisabled);
|
||||||
|
MakeAlternateImages(*mPlay, 4,
|
||||||
|
bmpSeek, bmpSeek, bmpSeekDisabled);
|
||||||
mPlay->FollowModifierKeys();
|
mPlay->FollowModifierKeys();
|
||||||
|
|
||||||
mStop = MakeButton( bmpStop, bmpStop, bmpStopDisabled ,
|
mStop = MakeButton( bmpStop, bmpStop, bmpStopDisabled ,
|
||||||
@ -635,15 +638,16 @@ int ControlToolBar::PlayPlayRegion(const SelectedRegion &selectedRegion,
|
|||||||
NoteTrackArray(),
|
NoteTrackArray(),
|
||||||
#endif
|
#endif
|
||||||
tcp0, tcp1, myOptions);
|
tcp0, tcp1, myOptions);
|
||||||
} else
|
}
|
||||||
{
|
else {
|
||||||
// Cannot create cut preview tracks, clean up and exit
|
// Cannot create cut preview tracks, clean up and exit
|
||||||
SetPlay(false);
|
SetPlay(false);
|
||||||
SetStop(false);
|
SetStop(false);
|
||||||
SetRecord(false);
|
SetRecord(false);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Lifted the following into AudacityProject::GetDefaultPlayOptions()
|
// Lifted the following into AudacityProject::GetDefaultPlayOptions()
|
||||||
/*
|
/*
|
||||||
if (!timetrack) {
|
if (!timetrack) {
|
||||||
@ -682,6 +686,8 @@ int ControlToolBar::PlayPlayRegion(const SelectedRegion &selectedRegion,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StartScrollingIfPreferred();
|
||||||
|
|
||||||
// Let other UI update appearance
|
// Let other UI update appearance
|
||||||
if (p)
|
if (p)
|
||||||
p->GetRulerPanel()->HideQuickPlayIndicator();
|
p->GetRulerPanel()->HideQuickPlayIndicator();
|
||||||
@ -745,25 +751,17 @@ void ControlToolBar::OnKeyEvent(wxKeyEvent & event)
|
|||||||
|
|
||||||
void ControlToolBar::OnPlay(wxCommandEvent & WXUNUSED(evt))
|
void ControlToolBar::OnPlay(wxCommandEvent & WXUNUSED(evt))
|
||||||
{
|
{
|
||||||
auto doubleClicked = mPlay->IsDoubleClicked();
|
|
||||||
mPlay->ClearDoubleClicked();
|
|
||||||
|
|
||||||
auto p = GetActiveProject();
|
auto p = GetActiveProject();
|
||||||
|
|
||||||
if (doubleClicked)
|
if (!CanStopAudioStream())
|
||||||
p->GetPlaybackScroller().Activate
|
return;
|
||||||
(AudacityProject::PlaybackScroller::Mode::Centered);
|
|
||||||
else {
|
|
||||||
if (!CanStopAudioStream())
|
|
||||||
return;
|
|
||||||
|
|
||||||
StopPlaying();
|
StopPlaying();
|
||||||
|
|
||||||
if (p) p->TP_DisplaySelection();
|
if (p) p->TP_DisplaySelection();
|
||||||
|
|
||||||
PlayDefault();
|
PlayDefault();
|
||||||
UpdateStatusBar(p);
|
UpdateStatusBar(p);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlToolBar::OnStop(wxCommandEvent & WXUNUSED(evt))
|
void ControlToolBar::OnStop(wxCommandEvent & WXUNUSED(evt))
|
||||||
@ -792,11 +790,11 @@ void ControlToolBar::PlayDefault()
|
|||||||
|
|
||||||
void ControlToolBar::StopPlaying(bool stopStream /* = true*/)
|
void ControlToolBar::StopPlaying(bool stopStream /* = true*/)
|
||||||
{
|
{
|
||||||
|
StopScrolling();
|
||||||
|
|
||||||
AudacityProject *project = GetActiveProject();
|
AudacityProject *project = GetActiveProject();
|
||||||
|
|
||||||
if(project) {
|
if(project) {
|
||||||
project->GetPlaybackScroller().Activate
|
|
||||||
(AudacityProject::PlaybackScroller::Mode::Off);
|
|
||||||
// Let scrubbing code do some appearance change
|
// Let scrubbing code do some appearance change
|
||||||
project->GetScrubber().StopScrubbing();
|
project->GetScrubber().StopScrubbing();
|
||||||
}
|
}
|
||||||
@ -853,29 +851,6 @@ void ControlToolBar::Pause()
|
|||||||
|
|
||||||
void ControlToolBar::OnRecord(wxCommandEvent &evt)
|
void ControlToolBar::OnRecord(wxCommandEvent &evt)
|
||||||
{
|
{
|
||||||
auto doubleClicked = mRecord->IsDoubleClicked();
|
|
||||||
mRecord->ClearDoubleClicked();
|
|
||||||
|
|
||||||
if (doubleClicked) {
|
|
||||||
// Display a fixed recording head while scrolling the waves continuously.
|
|
||||||
// If you overdub, you may want to anticipate some context in existing tracks,
|
|
||||||
// so center the head. If not, put it rightmost to display as much wave as we can.
|
|
||||||
const auto project = GetActiveProject();
|
|
||||||
bool duplex;
|
|
||||||
gPrefs->Read(wxT("/AudioIO/Duplex"), &duplex, true);
|
|
||||||
|
|
||||||
if (duplex) {
|
|
||||||
// See if there is really anything being overdubbed
|
|
||||||
if (gAudioIO->GetNumPlaybackChannels() == 0)
|
|
||||||
// No.
|
|
||||||
duplex = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
using Mode = AudacityProject::PlaybackScroller::Mode;
|
|
||||||
project->GetPlaybackScroller().Activate(duplex ? Mode::Centered : Mode::Right);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gAudioIO->IsBusy()) {
|
if (gAudioIO->IsBusy()) {
|
||||||
if (!CanStopAudioStream() || 0 == gAudioIO->GetNumCaptureChannels())
|
if (!CanStopAudioStream() || 0 == gAudioIO->GetNumCaptureChannels())
|
||||||
mRecord->PopUp();
|
mRecord->PopUp();
|
||||||
@ -1092,6 +1067,8 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
|
|||||||
if (success) {
|
if (success) {
|
||||||
p->SetAudioIOToken(token);
|
p->SetAudioIOToken(token);
|
||||||
mBusyProject = p;
|
mBusyProject = p;
|
||||||
|
|
||||||
|
StartScrollingIfPreferred();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (shifted) {
|
if (shifted) {
|
||||||
@ -1278,3 +1255,60 @@ void ControlToolBar::UpdateStatusBar(AudacityProject *pProject)
|
|||||||
{
|
{
|
||||||
pProject->GetStatusBar()->SetStatusText(StateForStatusBar(), stateStatusBarField);
|
pProject->GetStatusBar()->SetStatusText(StateForStatusBar(), stateStatusBarField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ControlToolBar::StartScrollingIfPreferred()
|
||||||
|
{
|
||||||
|
if (PlaybackPrefs::GetPinnedHeadPreference())
|
||||||
|
StartScrolling();
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
else if (::GetActiveProject()->GetScrubber().HasStartedScrubbing()) {
|
||||||
|
// PRL: cause many "unnecessary" refreshes. For reasons I don't understand,
|
||||||
|
// doing this causes wheel rotation events (mapped from the double finger vertical
|
||||||
|
// swipe) to be delivered more uniformly to the application, so that speed control
|
||||||
|
// works better.
|
||||||
|
::GetActiveProject()->GetPlaybackScroller().Activate
|
||||||
|
(AudacityProject::PlaybackScroller::Mode::Refresh);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
StopScrolling();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlToolBar::StartScrolling()
|
||||||
|
{
|
||||||
|
using Mode = AudacityProject::PlaybackScroller::Mode;
|
||||||
|
const auto project = GetActiveProject();
|
||||||
|
if (project) {
|
||||||
|
auto mode = Mode::Centered;
|
||||||
|
|
||||||
|
if (gAudioIO->GetNumCaptureChannels() > 0) {
|
||||||
|
// recording
|
||||||
|
|
||||||
|
// Display a fixed recording head while scrolling the waves continuously.
|
||||||
|
// If you overdub, you may want to anticipate some context in existing tracks,
|
||||||
|
// so center the head. If not, put it rightmost to display as much wave as we can.
|
||||||
|
bool duplex;
|
||||||
|
gPrefs->Read(wxT("/AudioIO/Duplex"), &duplex, true);
|
||||||
|
|
||||||
|
if (duplex) {
|
||||||
|
// See if there is really anything being overdubbed
|
||||||
|
if (gAudioIO->GetNumPlaybackChannels() == 0)
|
||||||
|
// No.
|
||||||
|
duplex = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!duplex)
|
||||||
|
mode = Mode::Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
project->GetPlaybackScroller().Activate(mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlToolBar::StopScrolling()
|
||||||
|
{
|
||||||
|
const auto project = GetActiveProject();
|
||||||
|
if(project)
|
||||||
|
project->GetPlaybackScroller().Activate
|
||||||
|
(AudacityProject::PlaybackScroller::Mode::Off);
|
||||||
|
}
|
||||||
|
@ -62,7 +62,7 @@ class ControlToolBar final : public ToolBar {
|
|||||||
|
|
||||||
// Choice among the appearances of the play button:
|
// Choice among the appearances of the play button:
|
||||||
enum class PlayAppearance {
|
enum class PlayAppearance {
|
||||||
Straight, Looped, CutPreview, Scrub
|
Straight, Looped, CutPreview, Scrub, Seek
|
||||||
};
|
};
|
||||||
|
|
||||||
//These allow buttons to be controlled externally:
|
//These allow buttons to be controlled externally:
|
||||||
@ -106,6 +106,11 @@ class ControlToolBar final : public ToolBar {
|
|||||||
int WidthForStatusBar(wxStatusBar* const);
|
int WidthForStatusBar(wxStatusBar* const);
|
||||||
void UpdateStatusBar(AudacityProject *pProject);
|
void UpdateStatusBar(AudacityProject *pProject);
|
||||||
|
|
||||||
|
// Starting and stopping of scrolling display
|
||||||
|
void StartScrollingIfPreferred();
|
||||||
|
void StartScrolling();
|
||||||
|
void StopScrolling();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
AButton *MakeButton(teBmps eEnabledUp, teBmps eEnabledDown, teBmps eDisabled,
|
AButton *MakeButton(teBmps eEnabledUp, teBmps eEnabledDown, teBmps eDisabled,
|
||||||
|
@ -105,7 +105,7 @@ AButton *EditToolBar::AddButton(
|
|||||||
{
|
{
|
||||||
AButton *&r = mButtons[id];
|
AButton *&r = mButtons[id];
|
||||||
|
|
||||||
r = ToolBar::MakeButton(
|
r = ToolBar::MakeButton(this,
|
||||||
bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredHiliteSmall,
|
bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredHiliteSmall,
|
||||||
eEnabledUp, eEnabledDown, eDisabled,
|
eEnabledUp, eEnabledDown, eDisabled,
|
||||||
wxWindowID(id),
|
wxWindowID(id),
|
||||||
|
@ -700,6 +700,7 @@ void ToolBar::MakeButtonBackgroundsSmall()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a button and its four different state bitmaps
|
/// Makes a button and its four different state bitmaps
|
||||||
|
/// @param parent Parent window for the button.
|
||||||
/// @param eUp Background for when button is Up.
|
/// @param eUp Background for when button is Up.
|
||||||
/// @param eDown Background for when button is Down.
|
/// @param eDown Background for when button is Down.
|
||||||
/// @param eHilite Background for when button is Hilit.
|
/// @param eHilite Background for when button is Hilit.
|
||||||
@ -710,7 +711,8 @@ void ToolBar::MakeButtonBackgroundsSmall()
|
|||||||
/// @param placement Placement position
|
/// @param placement Placement position
|
||||||
/// @param processdownevents true iff button handles down events.
|
/// @param processdownevents true iff button handles down events.
|
||||||
/// @param size Size of the background.
|
/// @param size Size of the background.
|
||||||
AButton * ToolBar::MakeButton(teBmps eUp,
|
AButton * ToolBar::MakeButton(wxWindow *parent,
|
||||||
|
teBmps eUp,
|
||||||
teBmps eDown,
|
teBmps eDown,
|
||||||
teBmps eHilite,
|
teBmps eHilite,
|
||||||
teBmps eStandardUp,
|
teBmps eStandardUp,
|
||||||
@ -731,7 +733,7 @@ AButton * ToolBar::MakeButton(teBmps eUp,
|
|||||||
wxImagePtr disable2 (OverlayImage(eUp, eDisabled, xoff, yoff));
|
wxImagePtr disable2 (OverlayImage(eUp, eDisabled, xoff, yoff));
|
||||||
|
|
||||||
AButton * button =
|
AButton * button =
|
||||||
new AButton(this, id, placement, size, *up2, *hilite2, *down2,
|
new AButton(parent, id, placement, size, *up2, *hilite2, *down2,
|
||||||
*disable2, processdownevents);
|
*disable2, processdownevents);
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
|
@ -121,9 +121,11 @@ class ToolBar /* not final */ : public wxPanel
|
|||||||
virtual int GetInitialWidth() { return -1; }
|
virtual int GetInitialWidth() { return -1; }
|
||||||
virtual int GetMinToolbarWidth() { return GetInitialWidth(); }
|
virtual int GetMinToolbarWidth() { return GetInitialWidth(); }
|
||||||
virtual wxSize GetDockedSize() { return GetMinSize(); }
|
virtual wxSize GetDockedSize() { return GetMinSize(); }
|
||||||
protected:
|
|
||||||
|
|
||||||
AButton *MakeButton(teBmps eUp,
|
public:
|
||||||
|
static
|
||||||
|
AButton *MakeButton(wxWindow *parent,
|
||||||
|
teBmps eUp,
|
||||||
teBmps eDown,
|
teBmps eDown,
|
||||||
teBmps eHilite,
|
teBmps eHilite,
|
||||||
teBmps eStandardUp,
|
teBmps eStandardUp,
|
||||||
@ -144,6 +146,7 @@ class ToolBar /* not final */ : public wxPanel
|
|||||||
teBmps eDisabled,
|
teBmps eDisabled,
|
||||||
wxSize size);
|
wxSize size);
|
||||||
|
|
||||||
|
protected:
|
||||||
void SetButton(bool down, AButton *button);
|
void SetButton(bool down, AButton *button);
|
||||||
|
|
||||||
void MakeMacRecoloredImage(teBmps eBmpOut, teBmps eBmpIn);
|
void MakeMacRecoloredImage(teBmps eBmpOut, teBmps eBmpIn);
|
||||||
|
@ -156,7 +156,7 @@ void ToolsToolBar::UpdatePrefs()
|
|||||||
AButton * ToolsToolBar::MakeTool( teBmps eTool,
|
AButton * ToolsToolBar::MakeTool( teBmps eTool,
|
||||||
int id, const wxChar *label)
|
int id, const wxChar *label)
|
||||||
{
|
{
|
||||||
AButton *button = ToolBar::MakeButton(
|
AButton *button = ToolBar::MakeButton(this,
|
||||||
bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredHiliteSmall,
|
bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredHiliteSmall,
|
||||||
eTool, eTool, eTool,
|
eTool, eTool, eTool,
|
||||||
wxWindowID(id),
|
wxWindowID(id),
|
||||||
|
@ -147,7 +147,7 @@ AButton *TranscriptionToolBar::AddButton(
|
|||||||
{
|
{
|
||||||
AButton *&r = mButtons[id];
|
AButton *&r = mButtons[id];
|
||||||
|
|
||||||
r = ToolBar::MakeButton(
|
r = ToolBar::MakeButton(this,
|
||||||
bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredHiliteSmall,
|
bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredHiliteSmall,
|
||||||
eFore, eFore, eDisabled,
|
eFore, eFore, eDisabled,
|
||||||
wxWindowID(id),
|
wxWindowID(id),
|
||||||
@ -476,23 +476,11 @@ void TranscriptionToolBar::OnPlaySpeed(wxCommandEvent & WXUNUSED(event))
|
|||||||
{
|
{
|
||||||
auto button = mButtons[TTB_PlaySpeed];
|
auto button = mButtons[TTB_PlaySpeed];
|
||||||
|
|
||||||
auto doubleClicked = button->IsDoubleClicked();
|
// Let control have precedence over shift
|
||||||
button->ClearDoubleClicked();
|
const bool cutPreview = mButtons[TTB_PlaySpeed]->WasControlDown();
|
||||||
|
const bool looped = !cutPreview &&
|
||||||
if (doubleClicked) {
|
button->WasShiftDown();
|
||||||
GetActiveProject()->GetPlaybackScroller().Activate
|
PlayAtSpeed(looped, cutPreview);
|
||||||
(AudacityProject::PlaybackScroller::Mode::Centered);
|
|
||||||
|
|
||||||
// Pop up the button
|
|
||||||
SetButton(false, button);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Let control have precedence over shift
|
|
||||||
const bool cutPreview = mButtons[TTB_PlaySpeed]->WasControlDown();
|
|
||||||
const bool looped = !cutPreview &&
|
|
||||||
button->WasShiftDown();
|
|
||||||
PlayAtSpeed(looped, cutPreview);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranscriptionToolBar::OnSpeedSlider(wxCommandEvent& WXUNUSED(event))
|
void TranscriptionToolBar::OnSpeedSlider(wxCommandEvent& WXUNUSED(event))
|
||||||
|
@ -99,7 +99,7 @@ void PlayIndicatorOverlayBase::Draw(OverlayPanel &panel, wxDC &dc)
|
|||||||
else if(auto ruler = dynamic_cast<AdornedRulerPanel*>(&panel)) {
|
else if(auto ruler = dynamic_cast<AdornedRulerPanel*>(&panel)) {
|
||||||
wxASSERT(!mIsMaster);
|
wxASSERT(!mIsMaster);
|
||||||
|
|
||||||
ruler->DoDrawIndicator(&dc, mLastIndicatorX, !rec, IndicatorMediumWidth, false);
|
ruler->DoDrawIndicator(&dc, mLastIndicatorX, !rec, IndicatorMediumWidth, false, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wxASSERT(false);
|
wxASSERT(false);
|
||||||
|
@ -19,6 +19,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include "../../TrackPanelCell.h"
|
#include "../../TrackPanelCell.h"
|
||||||
#include "../../TrackPanelCellIterator.h"
|
#include "../../TrackPanelCellIterator.h"
|
||||||
#include "../../commands/CommandFunctors.h"
|
#include "../../commands/CommandFunctors.h"
|
||||||
|
#include "../../prefs/PlaybackPrefs.h"
|
||||||
#include "../../toolbars/ControlToolBar.h"
|
#include "../../toolbars/ControlToolBar.h"
|
||||||
|
|
||||||
#undef USE_TRANSCRIPTION_TOOLBAR
|
#undef USE_TRANSCRIPTION_TOOLBAR
|
||||||
@ -32,9 +33,6 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
|
|
||||||
#include <wx/dc.h>
|
#include <wx/dc.h>
|
||||||
|
|
||||||
// Conditional compilation switch for making scrub menu items checkable
|
|
||||||
#define CHECKABLE_SCRUB_MENU_ITEMS
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// PRL:
|
// PRL:
|
||||||
// Mouse must move at least this far to distinguish ctrl-drag to scrub
|
// Mouse must move at least this far to distinguish ctrl-drag to scrub
|
||||||
@ -219,37 +217,33 @@ namespace {
|
|||||||
wxString label;
|
wxString label;
|
||||||
wxString status;
|
wxString status;
|
||||||
void (Scrubber::*memFn)(wxCommandEvent&);
|
void (Scrubber::*memFn)(wxCommandEvent&);
|
||||||
bool scroll;
|
|
||||||
bool seek;
|
bool seek;
|
||||||
|
bool (Scrubber::*StatusTest)() const;
|
||||||
|
|
||||||
const wxString &GetStatus() const { return status; }
|
const wxString &GetStatus() const { return status; }
|
||||||
} menuItems[] = {
|
} menuItems[] = {
|
||||||
/* i18n-hint: These commands assist the user in finding a sound by ear. ...
|
/* i18n-hint: These commands assist the user in finding a sound by ear. ...
|
||||||
"Scrubbing" is variable-speed playback, ...
|
"Scrubbing" is variable-speed playback, ...
|
||||||
"Seeking" is normal speed playback but with skips, ...
|
"Seeking" is normal speed playback but with skips, ...
|
||||||
"Scrolling" keeps the playback position at a fixed place on screen while the waveform moves
|
|
||||||
*/
|
*/
|
||||||
{ wxT("Scrub"), XO("&Scrub"), XO("Scrubbing"),
|
{ wxT("Scrub"), XO("&Scrub"), XO("Scrubbing"),
|
||||||
&Scrubber::OnScrub, false, false },
|
&Scrubber::OnScrub, false, &Scrubber::Scrubs },
|
||||||
|
|
||||||
{ wxT("ScrollScrub"), XO("Sc&rolling Scrub"), XO("Scrolling Scrub"),
|
|
||||||
&Scrubber::OnScrollScrub, true, false },
|
|
||||||
|
|
||||||
{ wxT("Seek"), XO("See&k"), XO("Seeking"),
|
{ wxT("Seek"), XO("See&k"), XO("Seeking"),
|
||||||
&Scrubber::OnSeek, false, true },
|
&Scrubber::OnSeek, true, &Scrubber::Seeks },
|
||||||
|
|
||||||
{ wxT("ScrollSeek"), XO("Scro&lling Seek"), XO("Scrolling Seek"),
|
{ wxT("StartScrubSeek"), XO("Star&t"), XO(""),
|
||||||
&Scrubber::OnScrollSeek, true, true }
|
&Scrubber::OnStart, true, nullptr },
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { nMenuItems = sizeof(menuItems) / sizeof(*menuItems) };
|
enum { nMenuItems = sizeof(menuItems) / sizeof(*menuItems), StartMenuItem = 2 };
|
||||||
|
|
||||||
inline const MenuItem &FindMenuItem(bool scroll, bool seek)
|
// This never finds the last item:
|
||||||
|
inline const MenuItem &FindMenuItem(bool seek)
|
||||||
{
|
{
|
||||||
return *std::find_if(menuItems, menuItems + nMenuItems,
|
return *std::find_if(menuItems, menuItems + nMenuItems,
|
||||||
[=](const MenuItem &item) {
|
[=](const MenuItem &item) {
|
||||||
return scroll == item.scroll &&
|
return seek == item.seek;
|
||||||
seek == item.seek;
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -258,16 +252,13 @@ namespace {
|
|||||||
|
|
||||||
void Scrubber::MarkScrubStart(
|
void Scrubber::MarkScrubStart(
|
||||||
// Assume xx is relative to the left edge of TrackPanel!
|
// Assume xx is relative to the left edge of TrackPanel!
|
||||||
wxCoord xx, bool smoothScrolling, bool alwaysSeeking
|
wxCoord xx, bool smoothScrolling
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UncheckAllMenuItems();
|
|
||||||
|
|
||||||
// Don't actually start scrubbing, but collect some information
|
// Don't actually start scrubbing, but collect some information
|
||||||
// needed for the decision to start scrubbing later when handling
|
// needed for the decision to start scrubbing later when handling
|
||||||
// drag events.
|
// drag events.
|
||||||
mSmoothScrollingScrub = smoothScrolling;
|
mSmoothScrollingScrub = smoothScrolling;
|
||||||
mAlwaysSeeking = alwaysSeeking;
|
|
||||||
|
|
||||||
ControlToolBar * const ctb = mProject->GetControlToolBar();
|
ControlToolBar * const ctb = mProject->GetControlToolBar();
|
||||||
|
|
||||||
@ -278,14 +269,14 @@ void Scrubber::MarkScrubStart(
|
|||||||
// scrubber state
|
// scrubber state
|
||||||
mProject->SetAudioIOToken(0);
|
mProject->SetAudioIOToken(0);
|
||||||
|
|
||||||
ctb->SetPlay(true, ControlToolBar::PlayAppearance::Scrub);
|
ctb->SetPlay(true, mSeeking
|
||||||
|
? ControlToolBar::PlayAppearance::Seek
|
||||||
|
: ControlToolBar::PlayAppearance::Scrub);
|
||||||
|
|
||||||
ctb->UpdateStatusBar(mProject);
|
ctb->UpdateStatusBar(mProject);
|
||||||
|
|
||||||
mScrubStartPosition = xx;
|
mScrubStartPosition = xx;
|
||||||
mOptions.startClockTimeMillis = ::wxGetLocalTimeMillis();
|
mOptions.startClockTimeMillis = ::wxGetLocalTimeMillis();
|
||||||
|
|
||||||
CheckMenuItem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
|
#ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
|
||||||
@ -358,10 +349,11 @@ bool Scrubber::MaybeStartScrubbing(wxCoord xx)
|
|||||||
mOptions.maxSample =
|
mOptions.maxSample =
|
||||||
lrint(std::max(0.0, mProject->GetTracks()->GetEndTime()) * options.rate);
|
lrint(std::max(0.0, mProject->GetTracks()->GetEndTime()) * options.rate);
|
||||||
mOptions.minStutter =
|
mOptions.minStutter =
|
||||||
lrint(std::max(0.0, MinStutter) * options.rate);
|
mDragging ? 0.0 : lrint(std::max(0.0, MinStutter) * options.rate);
|
||||||
|
|
||||||
ControlToolBar::PlayAppearance appearance =
|
ControlToolBar::PlayAppearance appearance = mSeeking
|
||||||
ControlToolBar::PlayAppearance::Scrub;
|
? ControlToolBar::PlayAppearance::Seek
|
||||||
|
: ControlToolBar::PlayAppearance::Scrub;
|
||||||
const bool cutPreview = false;
|
const bool cutPreview = false;
|
||||||
const bool backwards = time1 < time0;
|
const bool backwards = time1 < time0;
|
||||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||||
@ -382,7 +374,6 @@ bool Scrubber::MaybeStartScrubbing(wxCoord xx)
|
|||||||
mOptions.startClockTimeMillis = ::wxGetLocalTimeMillis();
|
mOptions.startClockTimeMillis = ::wxGetLocalTimeMillis();
|
||||||
|
|
||||||
if (IsScrubbing()) {
|
if (IsScrubbing()) {
|
||||||
ActivateScroller();
|
|
||||||
mPaused = false;
|
mPaused = false;
|
||||||
mLastScrubPosition = xx;
|
mLastScrubPosition = xx;
|
||||||
|
|
||||||
@ -475,12 +466,12 @@ void Scrubber::ContinueScrubbingUI()
|
|||||||
|
|
||||||
{
|
{
|
||||||
// Show the correct status for seeking.
|
// Show the correct status for seeking.
|
||||||
bool backup = mAlwaysSeeking;
|
bool backup = mSeeking;
|
||||||
mAlwaysSeeking = seek;
|
mSeeking = seek;
|
||||||
const auto ctb = mProject->GetControlToolBar();
|
const auto ctb = mProject->GetControlToolBar();
|
||||||
if (ctb)
|
if (ctb)
|
||||||
ctb->UpdateStatusBar(mProject);
|
ctb->UpdateStatusBar(mProject);
|
||||||
mAlwaysSeeking = backup;
|
mSeeking = backup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seek)
|
if (seek)
|
||||||
@ -505,11 +496,7 @@ void Scrubber::StopScrubbing()
|
|||||||
|
|
||||||
mPoller->Stop();
|
mPoller->Stop();
|
||||||
|
|
||||||
UncheckAllMenuItems();
|
|
||||||
|
|
||||||
mScrubStartPosition = -1;
|
mScrubStartPosition = -1;
|
||||||
mProject->GetPlaybackScroller().Activate
|
|
||||||
(AudacityProject::PlaybackScroller::Mode::Off);
|
|
||||||
mDragging = false;
|
mDragging = false;
|
||||||
|
|
||||||
if (!IsScrubbing())
|
if (!IsScrubbing())
|
||||||
@ -779,31 +766,13 @@ Scrubber &ScrubbingOverlay::GetScrubber()
|
|||||||
|
|
||||||
bool Scrubber::PollIsSeeking()
|
bool Scrubber::PollIsSeeking()
|
||||||
{
|
{
|
||||||
return mDragging || (mAlwaysSeeking || ::wxGetMouseState().LeftIsDown());
|
return mDragging || (mSeeking || ::wxGetMouseState().LeftIsDown());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scrubber::ActivateScroller()
|
void Scrubber::DoScrub()
|
||||||
{
|
|
||||||
using Mode = AudacityProject::PlaybackScroller::Mode;
|
|
||||||
mProject->GetPlaybackScroller().Activate(mSmoothScrollingScrub
|
|
||||||
? Mode::Centered
|
|
||||||
:
|
|
||||||
#ifdef __WXMAC__
|
|
||||||
// PRL: cause many "unnecessary" refreshes. For reasons I don't understand,
|
|
||||||
// doing this causes wheel rotation events (mapped from the double finger vertical
|
|
||||||
// swipe) to be delivered more uniformly to the application, so that spped control
|
|
||||||
// works better.
|
|
||||||
Mode::Refresh
|
|
||||||
#else
|
|
||||||
Mode::Off
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scrubber::DoScrub(bool scroll, bool seek)
|
|
||||||
{
|
{
|
||||||
const bool wasScrubbing = IsScrubbing();
|
const bool wasScrubbing = IsScrubbing();
|
||||||
const bool match = (scroll == mSmoothScrollingScrub && seek == mAlwaysSeeking);
|
const bool scroll = PlaybackPrefs::GetPinnedHeadPreference();
|
||||||
if (!wasScrubbing) {
|
if (!wasScrubbing) {
|
||||||
auto tp = mProject->GetTrackPanel();
|
auto tp = mProject->GetTrackPanel();
|
||||||
wxCoord xx = tp->ScreenToClient(::wxGetMouseState().GetPosition()).x;
|
wxCoord xx = tp->ScreenToClient(::wxGetMouseState().GetPosition()).x;
|
||||||
@ -814,67 +783,65 @@ void Scrubber::DoScrub(bool scroll, bool seek)
|
|||||||
const auto offset = tp->GetLeftOffset();
|
const auto offset = tp->GetLeftOffset();
|
||||||
xx = (std::max(offset, std::min(offset + width - 1, xx)));
|
xx = (std::max(offset, std::min(offset + width - 1, xx)));
|
||||||
|
|
||||||
MarkScrubStart(xx, scroll, seek);
|
MarkScrubStart(xx, scroll);
|
||||||
}
|
}
|
||||||
else if(!match) {
|
}
|
||||||
mSmoothScrollingScrub = scroll;
|
|
||||||
ActivateScroller();
|
|
||||||
mAlwaysSeeking = seek;
|
|
||||||
UncheckAllMenuItems();
|
|
||||||
CheckMenuItem();
|
|
||||||
|
|
||||||
|
void Scrubber::OnScrubOrSeek(bool &toToggle, bool &other)
|
||||||
|
{
|
||||||
|
toToggle = !toToggle;
|
||||||
|
if (toToggle)
|
||||||
|
other = false;
|
||||||
|
|
||||||
|
if (HasStartedScrubbing()) {
|
||||||
// Show the correct status.
|
// Show the correct status.
|
||||||
const auto ctb = mProject->GetControlToolBar();
|
const auto ctb = mProject->GetControlToolBar();
|
||||||
ctb->UpdateStatusBar(mProject);
|
ctb->UpdateStatusBar(mProject);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// This will call back to Scrubber::StopScrubbing
|
auto ruler = mProject->GetRulerPanel();
|
||||||
const auto ctb = mProject->GetControlToolBar();
|
if (ruler)
|
||||||
ctb->StopPlaying();
|
// Update button images
|
||||||
}
|
ruler->UpdateButtonStates();
|
||||||
|
|
||||||
|
CheckMenuItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scrubber::OnScrub(wxCommandEvent&)
|
void Scrubber::OnScrub(wxCommandEvent&)
|
||||||
{
|
{
|
||||||
DoScrub(false, false);
|
OnScrubOrSeek(mScrubbing, mSeeking);
|
||||||
}
|
|
||||||
|
|
||||||
void Scrubber::OnScrollScrub(wxCommandEvent&)
|
|
||||||
{
|
|
||||||
DoScrub(true, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scrubber::OnSeek(wxCommandEvent&)
|
void Scrubber::OnSeek(wxCommandEvent&)
|
||||||
{
|
{
|
||||||
DoScrub(false, true);
|
OnScrubOrSeek(mSeeking, mScrubbing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scrubber::OnScrollSeek(wxCommandEvent&)
|
void Scrubber::OnStart(wxCommandEvent&)
|
||||||
{
|
{
|
||||||
DoScrub(true, true);
|
DoScrub();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum { CMD_ID = 8000 };
|
enum { CMD_ID = 8000 };
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(Scrubber, wxEvtHandler)
|
BEGIN_EVENT_TABLE(Scrubber, wxEvtHandler)
|
||||||
EVT_MENU(CMD_ID, Scrubber::OnScrub)
|
EVT_MENU(CMD_ID, Scrubber::OnScrub)
|
||||||
EVT_MENU(CMD_ID + 1, Scrubber::OnScrollScrub)
|
EVT_MENU(CMD_ID + 1, Scrubber::OnSeek)
|
||||||
EVT_MENU(CMD_ID + 2, Scrubber::OnSeek)
|
EVT_MENU(CMD_ID + 2, Scrubber::OnStart)
|
||||||
EVT_MENU(CMD_ID + 3, Scrubber::OnScrollSeek)
|
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(Scrubber::Forwarder, wxEvtHandler)
|
BEGIN_EVENT_TABLE(Scrubber::Forwarder, wxEvtHandler)
|
||||||
EVT_MOUSE_EVENTS(Scrubber::Forwarder::OnMouse)
|
EVT_MOUSE_EVENTS(Scrubber::Forwarder::OnMouse)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
static_assert(nMenuItems == 4, "wrong number of items");
|
static_assert(nMenuItems == 3, "wrong number of items");
|
||||||
|
|
||||||
const wxString &Scrubber::GetUntranslatedStateString() const
|
const wxString &Scrubber::GetUntranslatedStateString() const
|
||||||
{
|
{
|
||||||
static wxString empty;
|
static wxString empty;
|
||||||
|
|
||||||
if (HasStartedScrubbing()) {
|
if (HasStartedScrubbing()) {
|
||||||
auto &item = FindMenuItem(mSmoothScrollingScrub, mAlwaysSeeking);
|
auto &item = FindMenuItem(mSeeking);
|
||||||
return item.status;
|
return item.status;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -885,15 +852,19 @@ std::vector<wxString> Scrubber::GetAllUntranslatedStatusStrings()
|
|||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
vector<wxString> results;
|
vector<wxString> results;
|
||||||
transform(menuItems, menuItems + nMenuItems, back_inserter(results),
|
for (const auto &item : menuItems) {
|
||||||
mem_fun_ref(&MenuItem::GetStatus));
|
const auto &status = item.GetStatus();
|
||||||
|
if (!status.empty())
|
||||||
|
results.push_back(status);
|
||||||
|
}
|
||||||
return move(results);
|
return move(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scrubber::CanScrub() const
|
bool Scrubber::CanScrub() const
|
||||||
{
|
{
|
||||||
|
// Return the enabled state for the menu item that really launches the scrub or seek.
|
||||||
auto cm = mProject->GetCommandManager();
|
auto cm = mProject->GetCommandManager();
|
||||||
return cm->GetEnabled(menuItems[0].name);
|
return cm->GetEnabled(menuItems[StartMenuItem].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scrubber::AddMenuItems()
|
void Scrubber::AddMenuItems()
|
||||||
@ -904,15 +875,14 @@ void Scrubber::AddMenuItems()
|
|||||||
|
|
||||||
cm->BeginSubMenu(_("Scru&bbing"));
|
cm->BeginSubMenu(_("Scru&bbing"));
|
||||||
for (const auto &item : menuItems) {
|
for (const auto &item : menuItems) {
|
||||||
#ifdef CHECKABLE_SCRUB_MENU_ITEMS
|
if (!item.GetStatus().empty())
|
||||||
cm->AddCheck(item.name, wxGetTranslation(item.label),
|
cm->AddCheck(item.name, wxGetTranslation(item.label),
|
||||||
FNT(Scrubber, this, item.memFn),
|
FNT(Scrubber, this, item.memFn),
|
||||||
false, flags, mask);
|
false, flags, mask);
|
||||||
#else
|
else
|
||||||
cm->AddItem(item.name, wxGetTranslation(item.label),
|
cm->AddItem(item.name, wxGetTranslation(item.label),
|
||||||
FNT(Scrubber, this, item.memFn),
|
FNT(Scrubber, this, item.memFn),
|
||||||
flags, mask);
|
flags, mask);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
cm->EndSubMenu();
|
cm->EndSubMenu();
|
||||||
CheckMenuItem();
|
CheckMenuItem();
|
||||||
@ -922,42 +892,22 @@ void Scrubber::PopulateMenu(wxMenu &menu)
|
|||||||
{
|
{
|
||||||
int id = CMD_ID;
|
int id = CMD_ID;
|
||||||
auto cm = mProject->GetCommandManager();
|
auto cm = mProject->GetCommandManager();
|
||||||
const MenuItem *checkedItem =
|
const MenuItem *checkedItem = &FindMenuItem(mSeeking);
|
||||||
HasStartedScrubbing()
|
|
||||||
? &FindMenuItem(mSmoothScrollingScrub, mAlwaysSeeking)
|
|
||||||
: nullptr;
|
|
||||||
for (const auto &item : menuItems) {
|
for (const auto &item : menuItems) {
|
||||||
if (cm->GetEnabled(item.name)) {
|
if (cm->GetEnabled(item.name)) {
|
||||||
#ifdef CHECKABLE_SCRUB_MENU_ITEMS
|
|
||||||
menu.AppendCheckItem(id, item.label);
|
menu.AppendCheckItem(id, item.label);
|
||||||
if(&item == checkedItem)
|
if(&item == checkedItem)
|
||||||
menu.FindItem(id)->Check();
|
menu.FindItem(id)->Check();
|
||||||
#else
|
|
||||||
menu.Append(id, item.label);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
++id;
|
++id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scrubber::UncheckAllMenuItems()
|
|
||||||
{
|
|
||||||
#ifdef CHECKABLE_SCRUB_MENU_ITEMS
|
|
||||||
auto cm = mProject->GetCommandManager();
|
|
||||||
for (const auto &item : menuItems)
|
|
||||||
cm->Check(item.name, false);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scrubber::CheckMenuItem()
|
void Scrubber::CheckMenuItem()
|
||||||
{
|
{
|
||||||
#ifdef CHECKABLE_SCRUB_MENU_ITEMS
|
auto cm = mProject->GetCommandManager();
|
||||||
if(HasStartedScrubbing()) {
|
cm->Check(menuItems[0].name, mScrubbing);
|
||||||
auto cm = mProject->GetCommandManager();
|
cm->Check(menuItems[1].name, mSeeking);
|
||||||
auto item = FindMenuItem(mSmoothScrollingScrub, mAlwaysSeeking);
|
|
||||||
cm->Check(item.name, true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,7 +24,11 @@ class AudacityProject;
|
|||||||
// Conditionally compile either a separate thead, or else use a timer in the main
|
// Conditionally compile either a separate thead, or else use a timer in the main
|
||||||
// thread, to poll the mouse and update scrubbing speed and direction. The advantage of
|
// thread, to poll the mouse and update scrubbing speed and direction. The advantage of
|
||||||
// a thread may be immunity to choppy scrubbing in case redrawing takes too much time.
|
// a thread may be immunity to choppy scrubbing in case redrawing takes too much time.
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
// Unfortunately some things the thread needs to do are not thread safe
|
||||||
|
#else
|
||||||
#define USE_SCRUB_THREAD
|
#define USE_SCRUB_THREAD
|
||||||
|
#endif
|
||||||
|
|
||||||
// For putting an increment of work in the scrubbing queue
|
// For putting an increment of work in the scrubbing queue
|
||||||
struct ScrubbingOptions {
|
struct ScrubbingOptions {
|
||||||
@ -67,11 +71,7 @@ public:
|
|||||||
~Scrubber();
|
~Scrubber();
|
||||||
|
|
||||||
// Assume xx is relative to the left edge of TrackPanel!
|
// Assume xx is relative to the left edge of TrackPanel!
|
||||||
void MarkScrubStart(
|
void MarkScrubStart(wxCoord xx, bool smoothScrolling);
|
||||||
wxCoord xx, bool smoothScrolling,
|
|
||||||
bool alwaysSeeking // if false, can switch seeking or scrubbing
|
|
||||||
// by mouse button state
|
|
||||||
);
|
|
||||||
|
|
||||||
// Returns true iff the event should be considered consumed by this:
|
// Returns true iff the event should be considered consumed by this:
|
||||||
// Assume xx is relative to the left edge of TrackPanel!
|
// Assume xx is relative to the left edge of TrackPanel!
|
||||||
@ -94,9 +94,14 @@ public:
|
|||||||
|
|
||||||
bool IsScrollScrubbing() const // If true, implies HasStartedScrubbing()
|
bool IsScrollScrubbing() const // If true, implies HasStartedScrubbing()
|
||||||
{ return mSmoothScrollingScrub; }
|
{ return mSmoothScrollingScrub; }
|
||||||
|
void SetScrollScrubbing(bool value)
|
||||||
|
{ mSmoothScrollingScrub = value; }
|
||||||
|
|
||||||
bool IsAlwaysSeeking() const
|
bool Seeks() const
|
||||||
{ return mAlwaysSeeking; }
|
{ return mSeeking; }
|
||||||
|
|
||||||
|
bool Scrubs() const
|
||||||
|
{ return mScrubbing; }
|
||||||
|
|
||||||
bool ShouldDrawScrubSpeed();
|
bool ShouldDrawScrubSpeed();
|
||||||
double FindScrubSpeed(bool seeking, double time) const;
|
double FindScrubSpeed(bool seeking, double time) const;
|
||||||
@ -114,12 +119,13 @@ public:
|
|||||||
// For popup
|
// For popup
|
||||||
void PopulateMenu(wxMenu &menu);
|
void PopulateMenu(wxMenu &menu);
|
||||||
|
|
||||||
|
void OnScrubOrSeek(bool &toToggle, bool &other);
|
||||||
void OnScrub(wxCommandEvent&);
|
void OnScrub(wxCommandEvent&);
|
||||||
void OnScrollScrub(wxCommandEvent&);
|
|
||||||
void OnSeek(wxCommandEvent&);
|
void OnSeek(wxCommandEvent&);
|
||||||
void OnScrollSeek(wxCommandEvent&);
|
void OnStart(wxCommandEvent&);
|
||||||
|
|
||||||
// A string to put in the leftmost part of the status bar.
|
// A string to put in the leftmost part of the status bar
|
||||||
|
// when scrub or seek is in progress, or else empty.
|
||||||
const wxString &GetUntranslatedStateString() const;
|
const wxString &GetUntranslatedStateString() const;
|
||||||
|
|
||||||
// All possible status strings.
|
// All possible status strings.
|
||||||
@ -129,10 +135,8 @@ public:
|
|||||||
bool IsPaused() const;
|
bool IsPaused() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ActivateScroller();
|
void DoScrub();
|
||||||
void DoScrub(bool scroll, bool seek);
|
|
||||||
void OnActivateOrDeactivateApp(wxActivateEvent & event);
|
void OnActivateOrDeactivateApp(wxActivateEvent & event);
|
||||||
void UncheckAllMenuItems();
|
|
||||||
void CheckMenuItem();
|
void CheckMenuItem();
|
||||||
|
|
||||||
// I need this because I can't push the scrubber as an event handler
|
// I need this because I can't push the scrubber as an event handler
|
||||||
@ -155,7 +159,12 @@ private:
|
|||||||
wxCoord mLastScrubPosition {};
|
wxCoord mLastScrubPosition {};
|
||||||
bool mScrubSeekPress;
|
bool mScrubSeekPress;
|
||||||
bool mSmoothScrollingScrub;
|
bool mSmoothScrollingScrub;
|
||||||
bool mAlwaysSeeking {};
|
|
||||||
|
// These hold the three-way choice among click-to-scrub, click-to-seek, or disabled.
|
||||||
|
// Not both true.
|
||||||
|
bool mScrubbing {};
|
||||||
|
bool mSeeking {};
|
||||||
|
|
||||||
bool mDragging {};
|
bool mDragging {};
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
#ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL
|
||||||
|
@ -392,18 +392,6 @@ void AButton::OnMouseEvent(wxMouseEvent & event)
|
|||||||
(event.m_x >= 0 && event.m_y >= 0 &&
|
(event.m_x >= 0 && event.m_y >= 0 &&
|
||||||
event.m_x < clientSize.x && event.m_y < clientSize.y);
|
event.m_x < clientSize.x && event.m_y < clientSize.y);
|
||||||
|
|
||||||
if (!mButtonIsDown)
|
|
||||||
{
|
|
||||||
// Note that CMD (or CTRL) takes precedence over Shift if both are down
|
|
||||||
// see also AButton::Listener::OnKeyUp()
|
|
||||||
if (event.CmdDown() && HasAlternateImages(2))
|
|
||||||
mAlternateIdx = 2;
|
|
||||||
else if (event.ShiftDown() && HasAlternateImages(1))
|
|
||||||
mAlternateIdx = 1;
|
|
||||||
else
|
|
||||||
mAlternateIdx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mEnabled && event.IsButton()) {
|
if (mEnabled && event.IsButton()) {
|
||||||
if (event.ButtonIsDown(wxMOUSE_BTN_ANY)) {
|
if (event.ButtonIsDown(wxMOUSE_BTN_ANY)) {
|
||||||
mIsClicking = true;
|
mIsClicking = true;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -298,7 +298,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static int GetRulerHeight();
|
int GetRulerHeight() { return GetRulerHeight(mShowScrubbing); }
|
||||||
static int GetRulerHeight(bool showScrubBar);
|
static int GetRulerHeight(bool showScrubBar);
|
||||||
wxRect GetInnerRect() const { return mInner; }
|
wxRect GetInnerRect() const { return mInner; }
|
||||||
|
|
||||||
@ -315,39 +315,14 @@ public:
|
|||||||
void InvalidateRuler();
|
void InvalidateRuler();
|
||||||
|
|
||||||
void UpdatePrefs();
|
void UpdatePrefs();
|
||||||
|
void ReCreateButtons();
|
||||||
|
|
||||||
enum class StatusChoice {
|
enum class StatusChoice {
|
||||||
FirstButton = 0,
|
EnteringQP,
|
||||||
QuickPlayButton = FirstButton,
|
|
||||||
ScrubBarButton,
|
|
||||||
|
|
||||||
NumButtons,
|
|
||||||
LastButton = NumButtons - 1,
|
|
||||||
NoButton = -1,
|
|
||||||
|
|
||||||
EnteringQP = NumButtons,
|
|
||||||
EnteringScrubZone,
|
EnteringScrubZone,
|
||||||
Leaving,
|
Leaving,
|
||||||
NoChange
|
NoChange
|
||||||
};
|
};
|
||||||
enum class PointerState {
|
|
||||||
Out = 0, In, InArrow
|
|
||||||
};
|
|
||||||
struct CaptureState {
|
|
||||||
CaptureState() {}
|
|
||||||
CaptureState(StatusChoice s, PointerState p) : button(s), state(p) {}
|
|
||||||
StatusChoice button { StatusChoice::NoButton };
|
|
||||||
PointerState state { PointerState::Out };
|
|
||||||
};
|
|
||||||
|
|
||||||
friend inline StatusChoice &operator++ (StatusChoice &choice) {
|
|
||||||
choice = static_cast<StatusChoice>(1 + static_cast<int>(choice));
|
|
||||||
return choice;
|
|
||||||
}
|
|
||||||
friend inline StatusChoice &operator-- (StatusChoice &choice) {
|
|
||||||
choice = static_cast<StatusChoice>(-1 + static_cast<int>(choice));
|
|
||||||
return choice;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegenerateTooltips(StatusChoice choice);
|
void RegenerateTooltips(StatusChoice choice);
|
||||||
|
|
||||||
@ -361,21 +336,11 @@ private:
|
|||||||
void OnSize(wxSizeEvent &evt);
|
void OnSize(wxSizeEvent &evt);
|
||||||
void UpdateRects();
|
void UpdateRects();
|
||||||
void OnMouseEvents(wxMouseEvent &evt);
|
void OnMouseEvents(wxMouseEvent &evt);
|
||||||
void HandleQPDoubleClick(wxMouseEvent &event, wxCoord mousePosX);
|
|
||||||
void HandleQPClick(wxMouseEvent &event, wxCoord mousePosX);
|
void HandleQPClick(wxMouseEvent &event, wxCoord mousePosX);
|
||||||
void HandleQPDrag(wxMouseEvent &event, wxCoord mousePosX);
|
void HandleQPDrag(wxMouseEvent &event, wxCoord mousePosX);
|
||||||
void HandleQPRelease(wxMouseEvent &event);
|
void HandleQPRelease(wxMouseEvent &event);
|
||||||
void StartQPPlay(bool looped, bool cutPreview);
|
void StartQPPlay(bool looped, bool cutPreview);
|
||||||
|
|
||||||
static inline bool IsButton(StatusChoice choice)
|
|
||||||
{
|
|
||||||
auto integer = static_cast<int>(choice);
|
|
||||||
return integer >= 0 &&
|
|
||||||
integer < static_cast<int>(StatusChoice::NumButtons);
|
|
||||||
}
|
|
||||||
static inline bool IsButton(int choice)
|
|
||||||
{ return IsButton(static_cast<StatusChoice>(choice)); }
|
|
||||||
|
|
||||||
void UpdateStatusBarAndTooltips(StatusChoice choice);
|
void UpdateStatusBarAndTooltips(StatusChoice choice);
|
||||||
|
|
||||||
void OnCaptureLost(wxMouseCaptureLostEvent &evt);
|
void OnCaptureLost(wxMouseCaptureLostEvent &evt);
|
||||||
@ -384,40 +349,18 @@ private:
|
|||||||
void DoDrawEdge(wxDC *dc);
|
void DoDrawEdge(wxDC *dc);
|
||||||
void DoDrawMarks(wxDC * dc, bool /*text */ );
|
void DoDrawMarks(wxDC * dc, bool /*text */ );
|
||||||
void DoDrawSelection(wxDC * dc);
|
void DoDrawSelection(wxDC * dc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void DoDrawIndicator(wxDC * dc, wxCoord xx, bool playing, int width, bool scrub);
|
void DoDrawIndicator(wxDC * dc, wxCoord xx, bool playing, int width, bool scrub, bool seek);
|
||||||
|
void UpdateButtonStates();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QuickPlayIndicatorOverlay *GetOverlay();
|
QuickPlayIndicatorOverlay *GetOverlay();
|
||||||
void ShowOrHideQuickPlayIndicator(bool show);
|
void ShowOrHideQuickPlayIndicator(bool show);
|
||||||
void DoDrawPlayRegion(wxDC * dc);
|
void DoDrawPlayRegion(wxDC * dc);
|
||||||
|
|
||||||
wxRect GetButtonAreaRect(bool includeBorder = false) const;
|
enum class MenuChoice { QuickPlay, Scrub };
|
||||||
|
void ShowContextMenu( MenuChoice choice, const wxPoint *pPosition);
|
||||||
struct ButtonStrings {
|
|
||||||
wxString label, enable, disable;
|
|
||||||
};
|
|
||||||
static const ButtonStrings PushbuttonLabels[];
|
|
||||||
static const ButtonStrings *GetPushButtonStrings(StatusChoice choice)
|
|
||||||
{
|
|
||||||
if(IsButton(choice))
|
|
||||||
return &PushbuttonLabels[static_cast<size_t>(choice)];
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxRect GetButtonRect( StatusChoice button ) const;
|
|
||||||
PointerState InButtonRect( StatusChoice button, wxMouseEvent *pEvent ) const;
|
|
||||||
CaptureState FindButton( wxMouseEvent &mouseEvent ) const;
|
|
||||||
bool GetButtonState( StatusChoice button ) const;
|
|
||||||
void ToggleButtonState( StatusChoice button );
|
|
||||||
void ShowButtonMenu( StatusChoice button, const wxPoint *pPosition);
|
|
||||||
void DoDrawPushbutton
|
|
||||||
(wxDC *dc, StatusChoice button, bool buttonState, bool arrowState) const;
|
|
||||||
void DoDrawPushbuttons(wxDC *dc) const;
|
|
||||||
void HandlePushbuttonClick(wxMouseEvent &evt);
|
|
||||||
void HandlePushbuttonEvent(wxMouseEvent &evt);
|
|
||||||
|
|
||||||
wxFont &GetButtonFont() const;
|
|
||||||
|
|
||||||
double Pos2Time(int p, bool ignoreFisheye = false);
|
double Pos2Time(int p, bool ignoreFisheye = false);
|
||||||
int Time2Pos(double t, bool ignoreFisheye = false);
|
int Time2Pos(double t, bool ignoreFisheye = false);
|
||||||
@ -470,20 +413,18 @@ private:
|
|||||||
void OnAutoScroll(wxCommandEvent &evt);
|
void OnAutoScroll(wxCommandEvent &evt);
|
||||||
void OnLockPlayRegion(wxCommandEvent &evt);
|
void OnLockPlayRegion(wxCommandEvent &evt);
|
||||||
|
|
||||||
void OnToggleScrubbing(wxCommandEvent&);
|
void OnToggleScrubbing(/*wxCommandEvent&*/);
|
||||||
|
void OnScrub(wxCommandEvent&);
|
||||||
|
void OnSeek(wxCommandEvent&);
|
||||||
|
|
||||||
void OnCaptureKey(wxCommandEvent &event);
|
|
||||||
void OnKeyDown(wxKeyEvent &event);
|
|
||||||
void OnSetFocus(wxFocusEvent &);
|
|
||||||
void OnKillFocus(wxFocusEvent &);
|
|
||||||
void OnContextMenu(wxContextMenuEvent & WXUNUSED(event));
|
void OnContextMenu(wxContextMenuEvent & WXUNUSED(event));
|
||||||
|
|
||||||
|
void OnTogglePinnedState(wxCommandEvent & event);
|
||||||
|
|
||||||
bool mPlayRegionDragsSelection;
|
bool mPlayRegionDragsSelection;
|
||||||
bool mTimelineToolTip;
|
bool mTimelineToolTip;
|
||||||
bool mQuickPlayEnabled;
|
bool mQuickPlayEnabled;
|
||||||
|
|
||||||
CaptureState mCaptureState {};
|
|
||||||
|
|
||||||
enum MouseEventState {
|
enum MouseEventState {
|
||||||
mesNone,
|
mesNone,
|
||||||
mesDraggingPlayRegionStart,
|
mesDraggingPlayRegionStart,
|
||||||
@ -501,53 +442,14 @@ private:
|
|||||||
|
|
||||||
StatusChoice mPrevZone { StatusChoice::NoChange };
|
StatusChoice mPrevZone { StatusChoice::NoChange };
|
||||||
|
|
||||||
struct TabState {
|
|
||||||
StatusChoice mButton { StatusChoice::FirstButton };
|
|
||||||
bool mMenu { false };
|
|
||||||
|
|
||||||
TabState() {}
|
|
||||||
TabState(StatusChoice button, bool menu)
|
|
||||||
: mButton{ button }, mMenu{ menu } {}
|
|
||||||
|
|
||||||
bool operator == (const TabState &rhs) const
|
|
||||||
{ return mButton == rhs.mButton && mMenu == rhs.mMenu; }
|
|
||||||
bool operator != (const TabState &rhs) const { return !(*this == rhs); }
|
|
||||||
|
|
||||||
TabState &operator ++ () {
|
|
||||||
if (!mMenu)
|
|
||||||
mMenu = true;
|
|
||||||
else {
|
|
||||||
mMenu = false;
|
|
||||||
if (!IsButton (++mButton))
|
|
||||||
mButton = StatusChoice::FirstButton;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
TabState &operator -- () {
|
|
||||||
if (mMenu)
|
|
||||||
mMenu = false;
|
|
||||||
else {
|
|
||||||
mMenu = true;
|
|
||||||
if (!IsButton (--mButton))
|
|
||||||
mButton = StatusChoice::LastButton;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
TabState mTabState;
|
|
||||||
|
|
||||||
bool mShowScrubbing { true };
|
bool mShowScrubbing { true };
|
||||||
|
|
||||||
mutable int mButtonFontSize { -1 };
|
|
||||||
mutable wxFont mButtonFont;
|
|
||||||
|
|
||||||
bool mDoubleClick {};
|
|
||||||
bool mShowingMenu {};
|
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
|
|
||||||
friend QuickPlayRulerOverlay;
|
friend QuickPlayRulerOverlay;
|
||||||
|
|
||||||
|
wxWindow *mButtons[3];
|
||||||
|
bool mNeedButtonUpdate { true };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //define __AUDACITY_RULER__
|
#endif //define __AUDACITY_RULER__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user