1#include "../AdornedRulerPanel.h"
4#include "../CommonCommandFlags.h"
8#include "../ProjectAudioManager.h"
12#include "../ProjectWindows.h"
13#include "../SelectUtilities.h"
15#include "../TrackPanel.h"
19#include "../LabelTrack.h"
22#include "../toolbars/ControlToolBar.h"
23#include "../tracks/ui/SelectHandle.h"
24#include "../tracks/labeltrack/ui/LabelTrackView.h"
25#include "../tracks/playabletrack/wavetrack/ui/WaveChannelView.h"
32 return size_t(std::max(1.0, projectRate / 100));
42 Floats dist{ windowSize,
true };
46 const auto nChannels = one->NChannels();
47 auto oneWindowSize = size_t(std::max(1.0, one->GetRate() / 100));
48 Floats buffer1{ oneWindowSize };
49 Floats buffer2{ oneWindowSize };
50 float *
const buffers[]{ buffer1.get(), buffer2.get() };
51 auto s = one->TimeToLongSamples(t0);
55 one->GetFloats(0, nChannels, buffers,
61 const auto oneDist = buffers[
iChannel];
63 for (
size_t i = 0; i < oneWindowSize; ++i) {
64 float fDist = fabs(oneDist[i]);
65 if (prev * oneDist[i] > 0)
76 for (
size_t i = 0; i < windowSize; i++) {
78 if (windowSize != oneWindowSize)
79 j = i * (oneWindowSize - 1) / (windowSize - 1);
83 dist[i] += oneDist[j];
87 0.1 * (abs(
int(i) -
int(windowSize / 2))) /
float(windowSize / 2);
96 for (
size_t i = 0; i < windowSize; ++i) {
104 if ((nTracks == 1) && (
min > (0.2 * nTracks)))
107 if ((nTracks > 1) && (
min > (0.6 * nTracks)))
110 return t0 + (argmin - (int)windowSize / 2) / rate;
119 auto evt = context.
pEvt;
120 bool bKeyUp = (evt) && evt->GetEventType() == wxEVT_KEY_UP;
149 wxLongLong mLastSelectionAdjustment { ::wxGetUTCTimeMillis() };
150 double mSeekShort{ 0.0 };
151 double mSeekLong{ 0.0 };
157#ifdef EXPERIMENTAL_IMPROVED_SEEKING
158 if (gAudioIO->GetLastPlaybackTime() < lastSelectionAdjustment) {
165 lastSelectionAdjustment = ::wxGetUTCTimeMillis();
167 gAudioIO->SeekStream(seekStep);
181 auto result = projectSnap.SingleStep(t, minPix >= 0).time;
184 std::abs(viewInfo.TimeToPosition(result) - viewInfo.TimeToPosition(t)) >=
189 result = viewInfo.OffsetTimeByPixels(t, minPix);
190 return projectSnap.SnapTime(result).time;
203 return viewInfo.OffsetTimeByPixels(t, (
int)offset);
220 auto snapMode =
settings.GetSnapMode();
224 if (viewInfo.selectedRegion.isPoint())
227 project, viewInfo.selectedRegion.t0(), seekStep, timeUnit, snapMode);
229 newT = std::max(0.0, newT);
231 viewInfo.selectedRegion.setT0(
234 viewInfo.selectedRegion.collapseToT0();
237 trackPanel.DrawOverlays(
false);
238 ruler.DrawOverlays(
false);
243 constexpr auto maySwapBoundaries =
false;
247 viewInfo.selectedRegion.setT0(
248 settings.SnapTime(viewInfo.selectedRegion.t0()).time,
250 viewInfo.selectedRegion.collapseToT0();
255 viewInfo.selectedRegion.setT1(
256 settings.SnapTime(viewInfo.selectedRegion.t1()).time,
258 viewInfo.selectedRegion.collapseToT1();
260 trackPanel.Refresh(
false);
264 viewport.ScrollIntoView(viewInfo.selectedRegion.t1());
283 auto snapMode =
settings.GetSnapMode();
284 const double t0 = viewInfo.selectedRegion.t0();
285 const double t1 = viewInfo.selectedRegion.t1();
286 const double end = std::max(
287 tracks.GetEndTime(), viewInfo.GetScreenEndTime());
294 bMoveT0 ? t0 : t1, seekStep, timeUnit, snapMode);
296 newT = std::max( 0.0, newT );
300 newT = bMoveT0 ?
std::min( t1, newT ) : std::max( t0, newT );
304 viewInfo.selectedRegion.setT0( newT );
306 viewInfo.selectedRegion.setT1( newT );
309 viewport.ScrollIntoView(newT);
336 const wxLongLong curtime = ::wxGetUTCTimeMillis();
337 enum { MIN_INTERVAL = 50 };
344 enum { LARGER_MULTIPLIER = 4 };
345 const double seekStep = (fast ? LARGER_MULTIPLIER : 1.0) * direction;
353 wxLongLong &lastSelectionAdjustment)
360 lastSelectionAdjustment = ::wxGetUTCTimeMillis();
378 wxLongLong curtime = ::wxGetUTCTimeMillis();
386 bool bMoveT0 = (step < 0 );
390 double indicator = gAudioIO->GetStreamTime();
392 viewInfo.selectedRegion.setT0(indicator,
false);
394 viewInfo.selectedRegion.setT1(indicator);
400 const double t0 = viewInfo.selectedRegion.t0();
401 const double t1 = viewInfo.selectedRegion.t1();
402 const double end = std::max(
403 tracks.GetEndTime(), viewInfo.GetScreenEndTime());
405 double newT = viewInfo.OffsetTimeByPixels( bMoveT0 ? t0 : t1, pixels);
407 newT = std::max( 0.0, newT );
415 viewInfo.selectedRegion.setT0( newT );
417 viewInfo.selectedRegion.setT1( newT );
420 viewport.ScrollIntoView(newT);
445 if (view.SelectAllText(context.
project)) {
446 trackPanel.Refresh(
false);
455 if (view.SelectAllText(context.
project)) {
456 trackPanel.Refresh(
false);
485 bool selected =
false;
488 t->SetSelected(
true);
499 true,
true,
XO(
"Set Left Selection Boundary"));
505 false,
true,
XO(
"Set Right Selection Boundary"));
514 double kWayOverToRight = std::numeric_limits<double>::max();
516 auto range =
tracks.Selected();
523 (kWayOverToRight * (1 - std::numeric_limits<double>::epsilon()) ))
526 selectedRegion.setT0(minOffset);
536 double kWayOverToLeft = std::numeric_limits<double>::lowest();
538 auto range =
tracks.Selected();
545 (kWayOverToLeft * (1 - std::numeric_limits<double>::epsilon()) ))
548 selectedRegion.setT1(maxEndOffset);
558 auto range =
tracks.Selected();
562 if( maxEndOffset < minOffset)
565 viewInfo.selectedRegion.setTimes(minOffset, maxEndOffset);
591 viewport.ScrollIntoView(selectedRegion.t0());
608 double cursorPositionCurrent = isAudioActive
609 ? gAudioIO->GetStreamTime()
610 : selectedRegion.t0();
611 selectedRegion.setTimes(
627 isAudioActive ? gAudioIO->GetStreamTime() : selectedRegion.t0();
643 const auto searchWindowDuration =
GetWindowSize(projectRate) / projectRate;
644 const auto wouldSearchStretchedClip =
645 [searchWindowDuration](
const WaveTrack& track,
double t) {
647 t - searchWindowDuration / 2, t + searchWindowDuration / 2);
649 clips.begin(), clips.end(),
650 [](
const std::shared_ptr<const WaveClip>& clip) {
651 return !clip->StretchRatioEquals(1);
656 selected.begin(), selected.end(), [&](
const WaveTrack* track) {
657 return wouldSearchStretchedClip(*track, selectedRegion.t0()) ||
658 wouldSearchStretchedClip(*track, selectedRegion.t1());
663 XO(
"Zero-crossing search regions intersect stretched clip(s)."),
669 if (selectedRegion.isPoint())
670 selectedRegion.setTimes(t0, t0);
675 selectedRegion.setTimes(t0, t1);
703 viewport.ScrollToStart(
true);
711 viewport.ScrollToEnd(
true);
762 selectedRegion.collapseToT0();
764 viewport.ScrollIntoView(selectedRegion.t0());
773 selectedRegion.collapseToT1();
775 viewport.ScrollIntoView(selectedRegion.t1());
785 double kWayOverToRight = std::numeric_limits<double>::max();
788 if (trackRange.empty())
796 (kWayOverToRight * (1 - std::numeric_limits<double>::epsilon()) ))
799 selectedRegion.setTimes(minOffset, minOffset);
801 viewport.ScrollIntoView(selectedRegion.t0());
811 double kWayOverToLeft = std::numeric_limits<double>::lowest();
814 if (trackRange.empty())
822 (kWayOverToLeft * (1 - std::numeric_limits<double>::epsilon()) ))
825 selectedRegion.setTimes(maxEndOffset, maxEndOffset);
827 viewport.ScrollIntoView(selectedRegion.t1());
836 controlToolBar.OnRewind(evt);
846 controlToolBar.OnFF(evt);
941 return std::make_unique< SelectActions::Handler >(); } };
949#define FN(X) (& SelectActions::Handler :: X)
955 static auto menu = std::shared_ptr{
971 FN(OnSelectAllTracks),
973 wxT(
"Ctrl+Shift+K") ),
974 Command(
wxT(
"SelSyncLockTracks"),
XXO(
"In All &Sync-Locked Tracks"),
975 FN(OnSelectSyncLockSel),
977 Options{
wxT(
"Ctrl+Shift+Y"),
XO(
"Select Sync-Locked") } )
984 Command(
wxT(
"SetLeftSelection"),
XXO(
"&Left at Playback Position"),
986 Options{
wxT(
"["),
XO(
"Set Selection Left at Play Position") } ),
987 Command(
wxT(
"SetRightSelection"),
XXO(
"&Right at Playback Position"),
989 Options{
wxT(
"]"),
XO(
"Set Selection Right at Play Position") } ),
990 Command(
wxT(
"SelTrackStartToCursor"),
XXO(
"Track &Start to Cursor"),
992 Options{
wxT(
"Shift+J"),
XO(
"Select Track Start to Cursor") } ),
993 Command(
wxT(
"SelCursorToTrackEnd"),
XXO(
"Cursor to Track &End"),
995 Options{
wxT(
"Shift+K"),
XO(
"Select Cursor to Track End") } ),
996 Command(
wxT(
"SelTrackStartToEnd"),
XXO(
"Track Start to En&d"),
1007 Command(
wxT(
"SelSave"),
XXO(
"S&tore Selection"),
FN(OnSelectionSave),
1021 XXO(
"Cursor to Stored &Cursor Position"),
1025 Command(
wxT(
"StoreCursorPosition"),
XXO(
"Store Cursor Pos&ition"),
1026 FN(OnCursorPositionStore),
1045 static auto menu = std::shared_ptr{
1052 Command(
wxT(
"SnapToPrior"),
XXO(
"Snap-To &Prior"),
FN(OnSnapToPrior),
1054 Command(
wxT(
"SelStart"),
XXO(
"Selection to &Start"),
FN(OnSelToStart),
1059 FN(OnSelExtendLeft),
1061 Options{
wxT(
"Shift+Left") }.WantKeyUp().AllowDup() ),
1062 Command(
wxT(
"SelExtRight"),
XXO(
"Selection Extend &Right"),
1063 FN(OnSelExtendRight),
1065 Options{
wxT(
"Shift+Right") }.WantKeyUp().AllowDup() ),
1066 Command(
wxT(
"SelSetExtLeft"),
XXO(
"Set (or Extend) Le&ft Selection"),
1067 FN(OnSelSetExtendLeft),
1069 Command(
wxT(
"SelSetExtRight"),
XXO(
"Set (or Extend) Rig&ht Selection"),
1070 FN(OnSelSetExtendRight),
1072 Command(
wxT(
"SelCntrLeft"),
XXO(
"Selection Contract L&eft"),
1073 FN(OnSelContractLeft),
1075 Options{
wxT(
"Ctrl+Shift+Right") }.WantKeyUp() ),
1076 Command(
wxT(
"SelCntrRight"),
XXO(
"Selection Contract R&ight"),
1077 FN(OnSelContractRight),
1079 Options{
wxT(
"Ctrl+Shift+Left") }.WantKeyUp() )
1085 wxT(
"Optional/Extra/Part1")
1099 static auto menu = std::shared_ptr{
1103 FN(OnCursorSelStart),
1112 FN(OnCursorTrackStart),
1116 FN(OnCursorTrackEnd),
1123 Options{
wxT(
"Home"),
XO(
"Cursor to Project Start") } ),
1132 wxT(
"Transport/Basic")
1137 static auto menu = std::shared_ptr{
1142 Options{
wxT(
"Left") }.WantKeyUp().AllowDup() ),
1145 Options{
wxT(
"Right") }.WantKeyUp().AllowDup() ),
1146 Command(
wxT(
"CursorShortJumpLeft"),
XXO(
"Cursor Sh&ort Jump Left"),
1147 FN(OnCursorShortJumpLeft),
1149 Command(
wxT(
"CursorShortJumpRight"),
XXO(
"Cursor Shor&t Jump Right"),
1150 FN(OnCursorShortJumpRight),
1152 Command(
wxT(
"CursorLongJumpLeft"),
XXO(
"Cursor Long J&ump Left"),
1153 FN(OnCursorLongJumpLeft),
1155 Command(
wxT(
"CursorLongJumpRight"),
XXO(
"Cursor Long Ju&mp Right"),
1156 FN(OnCursorLongJumpRight),
1163 wxT(
"Optional/Extra/Part2")
1168 static auto menu = std::shared_ptr{
1171 Command(
wxT(
"SeekLeftShort"),
XXO(
"Short Seek &Left During Playback"),
1175 XXO(
"Short Seek &Right During Playback"),
FN(OnSeekRightShort),
1178 Command(
wxT(
"SeekLeftLong"),
XXO(
"Long Seek Le&ft During Playback"),
1181 Command(
wxT(
"SeekRightLong"),
XXO(
"Long Seek Rig&ht During Playback"),
1189 wxT(
"Optional/Extra/Part1")
Toolkit-neutral facade for basic user interface services.
AttachedItem sAttachment1
AttachedItem sAttachment2
constexpr CommandFlag AlwaysEnabledFlag
wxEvtHandler CommandHandlerObject
const ReservedCommandFlag & AudioIOBusyFlag()
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & IsSyncLockedFlag()
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & EditableTracksSelectedFlag()
const ReservedCommandFlag & TracksExistFlag()
const ReservedCommandFlag & WaveTracksExistFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
const ReservedCommandFlag & TrackPanelHasFocus()
XXO("&Cut/Copy/Paste Toolbar")
audacity::BasicSettings * gPrefs
const ReservedCommandFlag & CanStopAudioStreamFlag()
an object holding per-project preferred sample rate
static Settings & settings()
static AdornedRulerPanel & Get(AudacityProject &project)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
double GetStartTime() const
Get the minimum of Start() values of intervals, or 0 when none.
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
A LabelTrack is a Track that holds labels (LabelStruct).
static LabelTrackView & Get(LabelTrack &)
A listener notified of changes in preferences.
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
Holds project sample rate.
static ProjectRate & Get(AudacityProject &project)
void SetSnapMode(SnapMode mode)
static ProjectSnap & Get(AudacityProject &project)
Generates classes whose instances register items at construction.
Defines a selected portion of a project.
static bool IsSyncLockSelected(const Track *pTrack)
virtual bool SupportsBasicEditing() const
Whether this track type implements cut-copy-paste; by default, true.
static TrackList & Get(AudacityProject &project)
static TrackPanel & Get(AudacityProject &project)
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
static Viewport & Get(AudacityProject &project)
static WaveChannelView & Get(WaveChannel &channel)
A Track that contains audio waveform data.
WaveClipConstHolders GetClipsIntersecting(double t0, double t1) const
virtual bool Read(const wxString &key, bool *value) const =0
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
void SelectNone(AudacityProject &project)
void DoSelectAll(AudacityProject &project)
void OnSetRegion(AudacityProject &project, bool left, bool selection, const TranslatableString &dialogTitle)
Adjust left or right of selection or play region.
void DoSelectTimeAndTracks(AudacityProject &project, bool bAllTime, bool bAllTracks)
double GetRate(const Track &track)
MessageBoxOptions && Caption(TranslatableString caption_) &&
A convenient default parameter for class template Site.
void OnSetLeftSelection(const CommandContext &context)
double mCursorPositionStored
void OnCursorLeft(const CommandContext &context)
void OnSnapToOff(const CommandContext &context)
void OnCursorRight(const CommandContext &context)
void OnSelExtendRight(const CommandContext &context)
void OnSelectionSave(const CommandContext &context)
void OnSkipEnd(const CommandContext &context)
void OnSelContractRight(const CommandContext &context)
void OnSelContractLeft(const CommandContext &context)
void OnSelectAll(const CommandContext &context)
SelectedRegion mRegionSave
void OnCursorLongJumpRight(const CommandContext &context)
void UpdatePrefs() override
void OnSeekRightShort(const CommandContext &context)
Handler & operator=(const Handler &)=delete
Handler(const Handler &)=delete
void OnSnapToNearest(const CommandContext &context)
void OnSelToStart(const CommandContext &context)
void OnCursorLongJumpLeft(const CommandContext &context)
void OnSeekLeftShort(const CommandContext &context)
void OnSelectAllTime(const CommandContext &context)
void OnSnapToPrior(const CommandContext &context)
void OnSelectTrackStartToEnd(const CommandContext &context)
void OnCursorTrackEnd(const CommandContext &context)
void OnZeroCrossing(const CommandContext &context)
void OnCursorShortJumpRight(const CommandContext &context)
void OnCursorShortJumpLeft(const CommandContext &context)
void OnCursorTrackStart(const CommandContext &context)
void OnSelectNone(const CommandContext &context)
void OnSelSetExtendLeft(const CommandContext &context)
void OnSelectCursorEnd(const CommandContext &context)
void OnSelectSyncLockSel(const CommandContext &context)
void OnSelectCursorStoredCursor(const CommandContext &context)
void OnSelToEnd(const CommandContext &context)
void OnSelSetExtendRight(const CommandContext &context)
void OnCursorSelStart(const CommandContext &context)
void OnSkipStart(const CommandContext &context)
void OnSelectStartCursor(const CommandContext &context)
void OnSelectionRestore(const CommandContext &context)
void OnSeekRightLong(const CommandContext &context)
void OnSelExtendLeft(const CommandContext &context)
void OnSelectAllTracks(const CommandContext &context)
void OnSetRightSelection(const CommandContext &context)
void OnSeekLeftLong(const CommandContext &context)
void OnCursorPositionStore(const CommandContext &context)
bool mCursorPositionHasBeenStored
void OnCursorSelEnd(const CommandContext &context)