1#include "../AdornedRulerPanel.h"
4#include "../CommonCommandFlags.h"
8#include "../ProjectAudioManager.h"
12#include "../ProjectWindows.h"
13#include "../SelectUtilities.h"
15#include "../TrackPanel.h"
23#include "../toolbars/ControlToolBar.h"
24#include "../tracks/ui/SelectHandle.h"
25#include "../tracks/labeltrack/ui/LabelTrackView.h"
26#include "../tracks/playabletrack/wavetrack/ui/WaveChannelView.h"
33 return size_t(std::max(1.0, projectRate / 100));
43 Floats dist{ windowSize,
true };
47 const auto nChannels = one->NChannels();
48 auto oneWindowSize = size_t(std::max(1.0, one->GetRate() / 100));
49 Floats buffer1{ oneWindowSize };
50 Floats buffer2{ oneWindowSize };
51 float *
const buffers[]{ buffer1.get(), buffer2.get() };
52 auto s = one->TimeToLongSamples(t0);
56 one->GetFloats(0, nChannels, buffers,
62 const auto oneDist = buffers[
iChannel];
64 for (
size_t i = 0; i < oneWindowSize; ++i) {
65 float fDist = fabs(oneDist[i]);
66 if (prev * oneDist[i] > 0)
77 for (
size_t i = 0; i < windowSize; i++) {
79 if (windowSize != oneWindowSize)
80 j = i * (oneWindowSize - 1) / (windowSize - 1);
84 dist[i] += oneDist[j];
88 0.1 * (abs(
int(i) -
int(windowSize / 2))) /
float(windowSize / 2);
97 for (
size_t i = 0; i < windowSize; ++i) {
105 if ((nTracks == 1) && (
min > (0.2 * nTracks)))
108 if ((nTracks > 1) && (
min > (0.6 * nTracks)))
111 return t0 + (argmin - (int)windowSize / 2) / rate;
120 auto evt = context.
pEvt;
121 bool bKeyUp = (evt) && evt->GetEventType() == wxEVT_KEY_UP;
150 wxLongLong mLastSelectionAdjustment { ::wxGetUTCTimeMillis() };
151 double mSeekShort{ 0.0 };
152 double mSeekLong{ 0.0 };
158#ifdef EXPERIMENTAL_IMPROVED_SEEKING
159 if (gAudioIO->GetLastPlaybackTime() < lastSelectionAdjustment) {
166 lastSelectionAdjustment = ::wxGetUTCTimeMillis();
168 gAudioIO->SeekStream(seekStep);
182 auto result = projectSnap.SingleStep(t, minPix >= 0).time;
185 std::abs(viewInfo.TimeToPosition(result) - viewInfo.TimeToPosition(t)) >=
190 result = viewInfo.OffsetTimeByPixels(t, minPix);
191 return projectSnap.SnapTime(result).time;
204 return viewInfo.OffsetTimeByPixels(t, (
int)offset);
221 auto snapMode =
settings.GetSnapMode();
225 if (viewInfo.selectedRegion.isPoint())
228 project, viewInfo.selectedRegion.t0(), seekStep, timeUnit, snapMode);
230 newT = std::max(0.0, newT);
232 viewInfo.selectedRegion.setT0(
235 viewInfo.selectedRegion.collapseToT0();
238 trackPanel.DrawOverlays(
false);
239 ruler.DrawOverlays(
false);
244 constexpr auto maySwapBoundaries =
false;
248 viewInfo.selectedRegion.setT0(
249 settings.SnapTime(viewInfo.selectedRegion.t0()).time,
251 viewInfo.selectedRegion.collapseToT0();
256 viewInfo.selectedRegion.setT1(
257 settings.SnapTime(viewInfo.selectedRegion.t1()).time,
259 viewInfo.selectedRegion.collapseToT1();
261 trackPanel.Refresh(
false);
265 viewport.ScrollIntoView(viewInfo.selectedRegion.t1());
284 auto snapMode =
settings.GetSnapMode();
285 const double t0 = viewInfo.selectedRegion.t0();
286 const double t1 = viewInfo.selectedRegion.t1();
287 const double end = std::max(
288 tracks.GetEndTime(), viewInfo.GetScreenEndTime());
295 bMoveT0 ? t0 : t1, seekStep, timeUnit, snapMode);
297 newT = std::max( 0.0, newT );
301 newT = bMoveT0 ?
std::min( t1, newT ) : std::max( t0, newT );
305 viewInfo.selectedRegion.setT0( newT );
307 viewInfo.selectedRegion.setT1( newT );
310 viewport.ScrollIntoView(newT);
337 const wxLongLong curtime = ::wxGetUTCTimeMillis();
338 enum { MIN_INTERVAL = 50 };
345 enum { LARGER_MULTIPLIER = 4 };
346 const double seekStep = (fast ? LARGER_MULTIPLIER : 1.0) * direction;
354 wxLongLong &lastSelectionAdjustment)
361 lastSelectionAdjustment = ::wxGetUTCTimeMillis();
379 wxLongLong curtime = ::wxGetUTCTimeMillis();
387 bool bMoveT0 = (step < 0 );
391 double indicator = gAudioIO->GetStreamTime();
393 viewInfo.selectedRegion.setT0(indicator,
false);
395 viewInfo.selectedRegion.setT1(indicator);
401 const double t0 = viewInfo.selectedRegion.t0();
402 const double t1 = viewInfo.selectedRegion.t1();
403 const double end = std::max(
404 tracks.GetEndTime(), viewInfo.GetScreenEndTime());
406 double newT = viewInfo.OffsetTimeByPixels( bMoveT0 ? t0 : t1, pixels);
408 newT = std::max( 0.0, newT );
416 viewInfo.selectedRegion.setT0( newT );
418 viewInfo.selectedRegion.setT1( newT );
421 viewport.ScrollIntoView(newT);
446 if (view.SelectAllText(context.
project)) {
447 trackPanel.Refresh(
false);
456 if (view.SelectAllText(context.
project)) {
457 trackPanel.Refresh(
false);
486 bool selected =
false;
489 t->SetSelected(
true);
500 true,
true,
XO(
"Set Left Selection Boundary"));
506 false,
true,
XO(
"Set Right Selection Boundary"));
515 double kWayOverToRight = std::numeric_limits<double>::max();
517 auto range =
tracks.Selected();
524 (kWayOverToRight * (1 - std::numeric_limits<double>::epsilon()) ))
527 selectedRegion.setT0(minOffset);
537 double kWayOverToLeft = std::numeric_limits<double>::lowest();
539 auto range =
tracks.Selected();
546 (kWayOverToLeft * (1 - std::numeric_limits<double>::epsilon()) ))
549 selectedRegion.setT1(maxEndOffset);
559 auto range =
tracks.Selected();
563 if( maxEndOffset < minOffset)
566 viewInfo.selectedRegion.setTimes(minOffset, maxEndOffset);
592 viewport.ScrollIntoView(selectedRegion.t0());
609 double cursorPositionCurrent = isAudioActive
610 ? gAudioIO->GetStreamTime()
611 : selectedRegion.t0();
612 selectedRegion.setTimes(
628 isAudioActive ? gAudioIO->GetStreamTime() : selectedRegion.t0();
644 const auto searchWindowDuration =
GetWindowSize(projectRate) / projectRate;
645 const auto wouldSearchClipWithPitchOrSpeed =
646 [searchWindowDuration](
const WaveTrack& track,
double t) {
648 t - searchWindowDuration / 2, t + searchWindowDuration / 2);
650 clips.begin(), clips.end(),
651 [](
const auto& clip) { return clip->HasPitchOrSpeed(); });
655 selected.begin(), selected.end(), [&](
const WaveTrack* track) {
656 return wouldSearchClipWithPitchOrSpeed(
657 *track, selectedRegion.t0()) ||
658 wouldSearchClipWithPitchOrSpeed(
659 *track, selectedRegion.t1());
664 XO(
"Zero-crossing search regions intersect stretched clip(s)."),
670 if (selectedRegion.isPoint())
671 selectedRegion.setTimes(t0, t0);
676 selectedRegion.setTimes(t0, t1);
704 viewport.ScrollToStart(
true);
712 viewport.ScrollToEnd(
true);
763 selectedRegion.collapseToT0();
765 viewport.ScrollIntoView(selectedRegion.t0());
774 selectedRegion.collapseToT1();
776 viewport.ScrollIntoView(selectedRegion.t1());
786 double kWayOverToRight = std::numeric_limits<double>::max();
789 if (trackRange.empty())
797 (kWayOverToRight * (1 - std::numeric_limits<double>::epsilon()) ))
800 selectedRegion.setTimes(minOffset, minOffset);
802 viewport.ScrollIntoView(selectedRegion.t0());
812 double kWayOverToLeft = std::numeric_limits<double>::lowest();
815 if (trackRange.empty())
823 (kWayOverToLeft * (1 - std::numeric_limits<double>::epsilon()) ))
826 selectedRegion.setTimes(maxEndOffset, maxEndOffset);
828 viewport.ScrollIntoView(selectedRegion.t1());
837 controlToolBar.OnRewind(evt);
847 controlToolBar.OnFF(evt);
942 return std::make_unique< SelectActions::Handler >(); } };
950#define FN(X) (& SelectActions::Handler :: X)
956 static auto menu = std::shared_ptr{
972 FN(OnSelectAllTracks),
974 wxT(
"Ctrl+Shift+K") ),
975 Command(
wxT(
"SelSyncLockTracks"),
XXO(
"In All &Sync-Locked Tracks"),
976 FN(OnSelectSyncLockSel),
978 Options{
wxT(
"Ctrl+Shift+Y"),
XO(
"Select Sync-Locked") } )
985 Command(
wxT(
"SetLeftSelection"),
XXO(
"&Left at Playback Position"),
987 Options{
wxT(
"["),
XO(
"Set Selection Left at Play Position") } ),
988 Command(
wxT(
"SetRightSelection"),
XXO(
"&Right at Playback Position"),
990 Options{
wxT(
"]"),
XO(
"Set Selection Right at Play Position") } ),
991 Command(
wxT(
"SelTrackStartToCursor"),
XXO(
"Track &Start to Cursor"),
993 Options{
wxT(
"Shift+J"),
XO(
"Select Track Start to Cursor") } ),
994 Command(
wxT(
"SelCursorToTrackEnd"),
XXO(
"Cursor to Track &End"),
996 Options{
wxT(
"Shift+K"),
XO(
"Select Cursor to Track End") } ),
997 Command(
wxT(
"SelTrackStartToEnd"),
XXO(
"Track Start to En&d"),
1008 Command(
wxT(
"SelSave"),
XXO(
"S&tore Selection"),
FN(OnSelectionSave),
1022 XXO(
"Cursor to Stored &Cursor Position"),
1026 Command(
wxT(
"StoreCursorPosition"),
XXO(
"Store Cursor Pos&ition"),
1027 FN(OnCursorPositionStore),
1046 static auto menu = std::shared_ptr{
1053 Command(
wxT(
"SnapToPrior"),
XXO(
"Snap-To &Prior"),
FN(OnSnapToPrior),
1055 Command(
wxT(
"SelStart"),
XXO(
"Selection to &Start"),
FN(OnSelToStart),
1060 FN(OnSelExtendLeft),
1062 Options{
wxT(
"Shift+Left") }.WantKeyUp().AllowDup() ),
1063 Command(
wxT(
"SelExtRight"),
XXO(
"Selection Extend &Right"),
1064 FN(OnSelExtendRight),
1066 Options{
wxT(
"Shift+Right") }.WantKeyUp().AllowDup() ),
1067 Command(
wxT(
"SelSetExtLeft"),
XXO(
"Set (or Extend) Le&ft Selection"),
1068 FN(OnSelSetExtendLeft),
1070 Command(
wxT(
"SelSetExtRight"),
XXO(
"Set (or Extend) Rig&ht Selection"),
1071 FN(OnSelSetExtendRight),
1073 Command(
wxT(
"SelCntrLeft"),
XXO(
"Selection Contract L&eft"),
1074 FN(OnSelContractLeft),
1076 Options{
wxT(
"Ctrl+Shift+Right") }.WantKeyUp() ),
1077 Command(
wxT(
"SelCntrRight"),
XXO(
"Selection Contract R&ight"),
1078 FN(OnSelContractRight),
1080 Options{
wxT(
"Ctrl+Shift+Left") }.WantKeyUp() )
1086 wxT(
"Optional/Extra/Part1")
1100 static auto menu = std::shared_ptr{
1104 FN(OnCursorSelStart),
1113 FN(OnCursorTrackStart),
1117 FN(OnCursorTrackEnd),
1124 Options{
wxT(
"Home"),
XO(
"Cursor to Project Start") } ),
1133 wxT(
"Transport/Basic")
1138 static auto menu = std::shared_ptr{
1143 Options{
wxT(
"Left") }.WantKeyUp().AllowDup() ),
1146 Options{
wxT(
"Right") }.WantKeyUp().AllowDup() ),
1147 Command(
wxT(
"CursorShortJumpLeft"),
XXO(
"Cursor Sh&ort Jump Left"),
1148 FN(OnCursorShortJumpLeft),
1150 Command(
wxT(
"CursorShortJumpRight"),
XXO(
"Cursor Shor&t Jump Right"),
1151 FN(OnCursorShortJumpRight),
1153 Command(
wxT(
"CursorLongJumpLeft"),
XXO(
"Cursor Long J&ump Left"),
1154 FN(OnCursorLongJumpLeft),
1156 Command(
wxT(
"CursorLongJumpRight"),
XXO(
"Cursor Long Ju&mp Right"),
1157 FN(OnCursorLongJumpRight),
1164 wxT(
"Optional/Extra/Part2")
1169 static auto menu = std::shared_ptr{
1172 Command(
wxT(
"SeekLeftShort"),
XXO(
"Short Seek &Left During Playback"),
1176 XXO(
"Short Seek &Right During Playback"),
FN(OnSeekRightShort),
1179 Command(
wxT(
"SeekLeftLong"),
XXO(
"Long Seek Le&ft During Playback"),
1182 Command(
wxT(
"SeekRightLong"),
XXO(
"Long Seek Rig&ht During Playback"),
1190 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 IsSyncLockSelectedP(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 & GetFirst(WaveTrack &wt)
Get the view of the first channel.
A Track that contains audio waveform data.
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.
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)
WAVE_TRACK_API WaveTrack::IntervalConstHolders GetClipsIntersecting(const WaveTrack &track, double t0, double t1)
double GetRate(const Track &track)
const char * end(const char *str) noexcept
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)