Audacity 3.2.0
LabelMenus.cpp
Go to the documentation of this file.
1#include "AudioIO.h"
2#include "BasicUI.h"
3#include "../Clipboard.h"
4#include "../CommonCommandFlags.h"
5#include "LabelTrack.h"
6#include "Prefs.h"
7#include "Project.h"
8#include "ProjectAudioIO.h"
9#include "ProjectHistory.h"
10
11#include "../SelectUtilities.h"
12#include "SyncLock.h"
13#include "TrackFocus.h"
14#include "../TrackPanel.h"
15#include "ViewInfo.h"
16#include "Viewport.h"
17#include "WaveTrack.h"
18#include "TimeStretching.h"
19#include "CommandContext.h"
20#include "../tracks/labeltrack/ui/LabelTrackView.h"
22
23#include <cassert>
24
27
28// private helper classes and functions
29namespace {
30
33 [](const AudacityProject &project){
34 // At least one label track selected, having at least one label
35 // completely within the time selection.
36 const auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
37 const auto &test = [&]( const LabelTrack *pTrack ){
38 const auto &labels = pTrack->GetLabels();
39 return std::any_of( labels.begin(), labels.end(),
40 [&](const LabelStruct &label){
41 return
42 label.getT0() >= selectedRegion.t0()
43 &&
44 label.getT1() <= selectedRegion.t1()
45 ;
46 }
47 );
48 };
49 auto range = TrackList::Get(project).Selected<const LabelTrack>()
50 + test;
51 return !range.empty();
52 }
53}; return flag; }
54
55//Adds label and returns index of label in labeltrack.
58 bool preserveFocus = false)
59{
60 auto &tracks = TrackList::Get( project );
61 auto &trackFocus = TrackFocus::Get( project );
62 auto &trackPanel = TrackPanel::Get( project );
63
64 wxString title; // of label
65
66 bool useDialog;
67 gPrefs->Read(wxT("/GUI/DialogForNameNewLabel"), &useDialog, false);
68 if (useDialog) {
70 project, region, wxEmptyString, title) == wxID_CANCEL)
71 return -1; // index
72 }
73
74 // If the focused track is a label track, use that
75 const auto pFocusedTrack = trackFocus.Get();
76
77 // Look for a label track at or after the focused track
78 auto begin = tracks.begin();
79 auto iter = pFocusedTrack
80 ? tracks.Find(pFocusedTrack)
81 : begin;
82 auto lt = * iter.Filter<LabelTrack>();
83
84 // If none found, start a NEW label track and use it
85 if (!lt)
87
88// LLL: Commented as it seemed a little forceful to remove users
89// selection when adding the label. This does not happen if
90// you select several tracks and the last one of those is a
91// label track...typing a label will not clear the selections.
92//
93// SelectNone();
94 lt->SetSelected(true);
95
96 int index;
97 if (useDialog) {
98 index = lt->AddLabel(region, title);
99 }
100 else {
101 int focusTrackNumber = -1;
102 if (pFocusedTrack && preserveFocus) {
103 // Must remember the track to re-focus after finishing a label edit.
104 // do NOT identify it by a pointer, which might dangle! Identify
105 // by position.
106 focusTrackNumber = std::distance(begin, iter);
107 }
108 index =
109 LabelTrackView::Get( *lt ).AddLabel(region, title, focusTrackNumber);
110 }
111
113 .PushState(XO("Added label"), XO("Label"));
114
115 if (!useDialog) {
116 TrackFocus::Get(project).Set(lt);
118 }
119 trackPanel.SetFocus();
120
121 return index;
122}
123
124//get regions selected by selected labels
125//removes unnecessary regions, overlapping regions are merged
127 const TrackList &tracks, const SelectedRegion &selectedRegion,
128 Regions &regions )
129{
130 //determine labeled regions
131 for (auto lt : tracks.Selected< const LabelTrack >()) {
132 for (int i = 0; i < lt->GetNumLabels(); i++)
133 {
134 const LabelStruct *ls = lt->GetLabel(i);
135 if (ls->selectedRegion.t0() >= selectedRegion.t0() &&
136 ls->selectedRegion.t1() <= selectedRegion.t1())
137 regions.push_back(Region(ls->getT0(), ls->getT1()));
138 }
139 }
140
141 //anything to do ?
142 if( regions.size() == 0 )
143 return;
144
145 //sort and remove unnecessary regions
146 std::sort(regions.begin(), regions.end());
147 unsigned int selected = 1;
148 while( selected < regions.size() )
149 {
150 const Region &cur = regions.at( selected );
151 Region &last = regions.at( selected - 1 );
152 if( cur.start < last.end )
153 {
154 if( cur.end > last.end )
155 last.end = cur.end;
156 regions.erase( regions.begin() + selected );
157 }
158 else
159 ++selected;
160 }
161}
162
163
165{
166 const bool syncLocked = SyncLockState::Get(project).IsSyncLocked();
167 const bool playableTrackSelected = !tracks.Selected<const PlayableTrack>().empty();
168
169 return [syncLocked, playableTrackSelected](const auto pTrack) {
170 // All sync-locked tracks should be edited,
171 // if sync lock is enabled regardless of selection
172 if (syncLocked) {
173 return SyncLock::IsSyncLockSelected(*pTrack);
174 }
175
176 // Non-playable tracks should not be edited if sync-lock disabled
177 if (dynamic_cast<const PlayableTrack*>(pTrack) == nullptr) {
178 return false;
179 }
180
181 // If no playable tracks were selected,
182 // then all tracks should be edited
183 return playableTrackSelected ? pTrack->IsSelected() : true;
184 };
185}
186
187using EditFunction = std::function<void(Track& track, double, double)>;
189 std::function<void(Track& track, double, double, ProgressReporter)>;
190
191// Executes the edit function on all selected wave tracks with
192// regions specified by selected labels
193// If No tracks selected, function is applied on all tracks
194// If the function replaces the selection with audio of a different length,
195// bSyncLockedTracks should be set true to perform the same action on sync-lock
196// selected tracks.
197// If `progress` is non-null, `action` is passed a callable `ProgressReporter`.
200 const SelectedRegion& selectedRegion, EditFunctionWithProgress action,
201 ProgressReporter progress)
202{
203 Regions regions;
204
205 GetRegionsByLabel(tracks, selectedRegion, regions);
206 if (regions.empty())
207 return;
208
209 const auto tracksToEdit = tracks.Any<Track>() + GetTracksToEditByLabel(project, tracks);
210
212 tracksToEdit.begin(), tracksToEdit.end(),
213 [&](Track* aTrack, const ProgressReporter& child) {
214 // Apply action on tracks starting from labeled regions in the end.
215 // This is to correctly perform actions like 'Delete' which collapse
216 // the track area.
217 BasicUI::SplitProgress(
218 regions.rbegin(), regions.rend(),
219 [&](const Region& region, const ProgressReporter& grandChild) {
220 action(*aTrack, region.start, region.end, grandChild);
221 },
222 child);
223 },
224 progress);
225}
226
229 const SelectedRegion& selectedRegion, EditFunction action)
230{
232 project, tracks, selectedRegion,
233 [&](Track& track, double t0, double t1, ProgressReporter) {
234 action(track, t0, t1);
235 },
236 nullptr);
237}
238
240 std::function<Track::Holder(Track &, double, double)>;
241
242//Executes the edit function on all selected wave tracks with
243//regions specified by selected labels
244//If No tracks selected, function is applied on all tracks
245//Functions copy the edited regions to clipboard, possibly in multiple tracks
246//This probably should not be called if *action() changes the timeline, because
247// the copy needs to happen by track, and the timeline change by group.
249 TrackList &tracks, const SelectedRegion &selectedRegion,
250 EditDestFunction action)
251{
252 Regions regions;
253
254 GetRegionsByLabel(tracks, selectedRegion, regions);
255 if (regions.empty())
256 return;
257
258 const auto tracksToEdit = tracks.Any<Track>() + GetTracksToEditByLabel(project, tracks);
259
260 auto &clipboard = Clipboard::Get();
261 clipboard.Clear();
262
263 auto pNewClipboard = TrackList::Create(nullptr);
264 auto &newClipboard = *pNewClipboard;
265
266 //Apply action on wavetracks starting from
267 //labeled regions in the end. This is to correctly perform
268 //actions like 'Cut' which collapse the track area.
269
270 for (auto t : tracksToEdit) {
271 // These tracks accumulate the needed clips, right to left:
272 Track::Holder merged;
273 for (size_t i = regions.size(); i--;) {
274 const Region &region = regions.at(i);
275 if (auto dest = action(*t, region.start, region.end)) {
276 if (!merged)
277 merged = dest;
278 else {
279 // Paste to the beginning; unless this is the first region,
280 // offset the track to account for time between the regions
281 if (i + 1 < regions.size())
282 merged->ShiftBy(
283 regions.at(i + 1).start - region.end);
284
285 // If GetEditClipsCanMove is not set, we need to manually
286 // shift the merged track by the end time of the dest clip,
287 // to make room for pasting because Paste does not
288 // handle shifting in this case.
289 if (!GetEditClipsCanMove())
290 merged->ShiftBy(dest->GetEndTime());
291
292 // dest may have a placeholder clip at the end that is
293 // removed when pasting, which is okay because we proceed
294 // right to left. Any placeholder already in merged is kept.
295 // Only the rightmost placeholder is important in the final
296 // result.
297 merged->Paste(0.0, *dest);
298 }
299 }
300 else
301 // nothing copied but there is a 'region', so the 'region' must
302 // be a 'point label' so offset
303 if (i + 1 < regions.size() && merged)
304 merged->ShiftBy(regions.at(i + 1).start - region.end);
305 }
306 if (merged)
307 newClipboard.Add(merged);
308 }
309
310 // Survived possibility of exceptions. Commit changes to the clipboard now.
311 clipboard.Assign( std::move( newClipboard ),
312 regions.front().start, regions.back().end, project.shared_from_this() );
313}
314
315}
316
318namespace {
319
320// Menu handler functions
321
322void OnEditLabels(const CommandContext &context)
323{
324 auto &project = context.project;
326}
327
328void OnAddLabel(const CommandContext &context)
329{
330 auto &project = context.project;
331 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
332
333 DoAddLabel(project, selectedRegion);
334}
335
337{
338 auto &project = context.project;
340
341 auto gAudioIO = AudioIO::Get();
342 if (token > 0 &&
343 gAudioIO->IsStreamActive(token)) {
344 double indicator = gAudioIO->GetStreamTime();
345 DoAddLabel(project, SelectedRegion(indicator, indicator), true);
346 }
347}
348
349// Creates a NEW label in each selected label track with text from the system
350// clipboard
351void OnPasteNewLabel(const CommandContext &context)
352{
353 auto &project = context.project;
354 auto &tracks = TrackList::Get( project );
355 auto &trackPanel = TrackPanel::Get( project );
356 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
357
358 bool bPastedSomething = false;
359
360 {
361 auto trackRange = tracks.Selected<const LabelTrack>();
362 if (trackRange.empty())
363 {
364 // If there are no selected label tracks, try to choose the first label
365 // track after some other selected track
366 Track *t = *tracks.Selected().begin()
367 .Filter(&Track::Any)
368 .Filter<LabelTrack>();
369
370 // If no match found, add one
371 if (!t)
373
374 // Select this track so the loop picks it up
375 t->SetSelected(true);
376 }
377 }
378
379 LabelTrack *plt = NULL; // the previous track
380 for ( auto lt : tracks.Selected<LabelTrack>() )
381 {
382 // Unselect the last label, so we'll have just one active label when
383 // we're done
384 if (plt)
386
387 // Add a NEW label, paste into it
388 // Paul L: copy whatever defines the selected region, not just times
389 auto &view = LabelTrackView::Get( *lt );
390 view.AddLabel(selectedRegion);
391 if (view.PasteSelectedText( context.project, selectedRegion.t0(),
392 selectedRegion.t1() ))
393 bPastedSomething = true;
394
395 // Set previous track
396 plt = lt;
397 }
398
399 // plt should point to the last label track pasted to -- ensure it's visible
400 // and set focus
401 if (plt) {
402 TrackFocus::Get(project).Set(plt);
404 trackPanel.SetFocus();
405 }
406
407 if (bPastedSomething) {
409 XO("Pasted from the clipboard"), XO("Paste Text to New Label"));
410 }
411}
412
413void OnToggleTypeToCreateLabel(const CommandContext &WXUNUSED(context) )
414{
415 bool typeToCreateLabel;
416 gPrefs->Read(wxT("/GUI/TypeToCreateLabel"), &typeToCreateLabel, false);
417 gPrefs->Write(wxT("/GUI/TypeToCreateLabel"), !typeToCreateLabel);
418 gPrefs->Flush();
420}
421
422void OnCutLabels(const CommandContext &context)
423{
424 auto &project = context.project;
426 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
427
428 if (selectedRegion.isPoint())
429 return;
430
431 // Because of grouping the copy may need to operate on different tracks than
432 // the clear, so we do these actions separately.
433 auto copyfunc = [&](Track &track, double t0, double t1) {
434 Track::Holder result;
435 track.TypeSwitch( [&](WaveTrack &wt) { result = wt.Copy(t0, t1); } );
436 return result;
437 };
438 EditClipboardByLabel(project, tracks, selectedRegion, copyfunc);
439
440 bool enableCutlines = gPrefs->ReadBool(wxT( "/GUI/EnableCutLines"), false);
441 auto editfunc = [&](Track &track, double t0, double t1) {
442 track.TypeSwitch(
443 [&](WaveTrack &t) {
444 if (enableCutlines)
445 t.ClearAndAddCutLine(t0, t1);
446 else
447 t.Clear(t0, t1);
448 },
449 [&](Track &t) {
450 t.Clear(t0, t1);
451 }
452 );
453 };
454 EditByLabel(project, tracks, selectedRegion, editfunc);
455
456 selectedRegion.collapseToT0();
457
459 /* i18n-hint: (verb) past tense. Audacity has just cut the labeled audio
460 regions.*/
461 XO("Cut labeled audio regions to clipboard"),
462 /* i18n-hint: (verb)*/
463 XO("Cut Labeled Audio"));
464}
465
466void OnDeleteLabels(const CommandContext &context)
467{
468 auto &project = context.project;
470 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
471
472 if (selectedRegion.isPoint())
473 return;
474
475 auto editfunc = [&](Track &track, double t0, double t1) {
476 track.TypeSwitch( [&](Track &t) { t.Clear(t0, t1); } );
477 };
478 EditByLabel(project, tracks, selectedRegion, editfunc);
479
480 selectedRegion.collapseToT0();
481
483 /* i18n-hint: (verb) Audacity has just deleted the labeled audio regions*/
484 XO("Deleted labeled audio regions"),
485 /* i18n-hint: (verb)*/
486 XO("Delete Labeled Audio"));
487}
488
490{
491 auto &project = context.project;
493 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
494
495 if (selectedRegion.isPoint())
496 return;
497
498 auto copyfunc = [&](Track &track, double t0, double t1) {
499 Track::Holder result;
500 track.TypeSwitch(
501 [&](WaveTrack &wt) {
502 result = wt.SplitCut(t0, t1);
503 },
504 [&](Track &t) {
505 result = t.Copy(t0, t1);
506 t.Silence(t0, t1);
507 }
508 );
509 return result;
510 };
511 EditClipboardByLabel(project, tracks, selectedRegion, copyfunc);
512
514 XO("Cut labeled audio regions to clipboard and leave gap"),
515 XO("Cut labeled audio and leave gap"));
516}
517
519{
520 auto &project = context.project;
522 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
523
524 if (selectedRegion.isPoint())
525 return;
526
527 auto editfunc = [&](Track &track, double t0, double t1) {
528 track.TypeSwitch(
529 [&](WaveTrack &t) {
530 t.SplitDelete(t0, t1);
531 },
532 [&](Track &t) {
533 t.Silence(t0, t1);
534 }
535 );
536 };
537 EditByLabel(project, tracks, selectedRegion, editfunc);
538
540 /* i18n-hint: (verb) Audacity has just done a special kind of DELETE on
541 the labeled audio regions */
542 XO("Split Deleted labeled audio regions"),
543 /* i18n-hint: (verb) Do a special kind of DELETE on labeled audio
544 regions */
545 XO("Split Delete Labeled Audio"));
546}
547
548void OnSilenceLabels(const CommandContext &context)
549{
550 auto &project = context.project;
552 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
553
554 if (selectedRegion.isPoint())
555 return;
556
557 auto editfunc = [&](Track &track, double t0, double t1) {
558 // TODO use progress-bar utilities pending in
559 // https://github.com/audacity/audacity/pull/5043
560 track.TypeSwitch([&](WaveTrack& t) { t.Silence(t0, t1, {}); });
561 };
562 EditByLabel(project, tracks, selectedRegion, editfunc);
563
565 /* i18n-hint: (verb)*/
566 XO("Silenced labeled audio regions"),
567 /* i18n-hint: (verb)*/
568 XO("Silence Labeled Audio"));
569}
570
571void OnCopyLabels(const CommandContext &context)
572{
573 auto &project = context.project;
575 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
576
577 if (selectedRegion.isPoint())
578 return;
579
580 auto copyfunc = [&](Track &track, double t0, double t1) {
581 Track::Holder result;
582 track.TypeSwitch( [&](WaveTrack &wt) { result = wt.Copy(t0, t1); } );
583 return result;
584 };
585 EditClipboardByLabel(project, tracks, selectedRegion, copyfunc);
586
588 .PushState(XO("Copied labeled audio regions to clipboard"),
589 /* i18n-hint: (verb)*/
590 XO("Copy Labeled Audio"));
591}
592
593void OnSplitLabels(const CommandContext &context)
594{
595 auto &project = context.project;
597 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
598
599 if (selectedRegion.isPoint())
600 return;
601
602 auto editfunc = [&](Track &track, double t0, double t1) {
603 track.TypeSwitch( [&](WaveTrack &t) { t.Split(t0, t1); } );
604 };
605 EditByLabel(project, tracks, selectedRegion, editfunc);
606
608 /* i18n-hint: (verb) past tense. Audacity has just split the labeled
609 audio (a point or a region)*/
610 XO("Split labeled audio (points or regions)"),
611 /* i18n-hint: (verb)*/
612 XO("Split Labeled Audio"));
613}
614
615void OnJoinLabels(const CommandContext &context)
616{
617 auto &project = context.project;
619 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
620
621 if (selectedRegion.isPoint())
622 return;
623
624 auto editfunc = [&](Track& track, double t0, double t1, ProgressReporter reportProgress) {
625 track.TypeSwitch(
626 [&](WaveTrack& t) {
627 // Extend Join Region by one sample, to ensure
628 // that Split-Join operation on a given label is reversible and consistent
629 const auto sampleTime = 1.0 / t.GetRate();
630 t.Join(t0 - sampleTime, t1 + sampleTime, std::move(reportProgress));
631 });
632 };
634 [&](ProgressReporter progress) {
635 EditByLabel(project, tracks, selectedRegion, editfunc, progress);
636 });
637
639 /* i18n-hint: (verb) Audacity has just joined the labeled audio (points or
640 regions) */
641 XO("Joined labeled audio (points or regions)"),
642 /* i18n-hint: (verb) */
643 XO("Join Labeled Audio"));
644}
645
646void OnDisjoinLabels(const CommandContext &context)
647{
648 auto &project = context.project;
650 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
651
652 if (selectedRegion.isPoint())
653 return;
654
655 auto editfunc = [&](Track &track, double t0, double t1) {
656 track.TypeSwitch( [&](WaveTrack &t) {
657 wxBusyCursor busy;
658 t.Disjoin(t0, t1);
659 } );
660 };
661 EditByLabel(project, tracks, selectedRegion, editfunc);
662
664 /* i18n-hint: (verb) Audacity has just detached the labeled audio regions.
665 This message appears in history and tells you about something
666 Audacity has done.*/
667 XO("Detached labeled audio regions"),
668 /* i18n-hint: (verb)*/
669 XO("Detach Labeled Audio"));
670}
671
672void OnNewLabelTrack(const CommandContext &context)
673{
674 auto &project = context.project;
675 auto &tracks = TrackList::Get( project );
676
677 auto track = LabelTrack::Create(tracks);
678
680
681 track->SetSelected(true);
682
684 .PushState(XO("Created new label track"), XO("New Track"));
685
686 TrackFocus::Get(project).Set(track);
688}
689
690// Menu definitions
691
692using namespace MenuRegistry;
694{
695 using namespace MenuRegistry;
696
697 static const auto NotBusyLabelsAndWaveFlags =
700
701 // Returns TWO menus.
702
703 static auto menus = std::shared_ptr{
704 Items( wxT("LabelEditMenus"),
705
706 Menu( wxT("Labels"), XXO("&Labels"),
707 Section( "",
708 Command( wxT("EditLabels"), XXO("Label &Editor"), OnEditLabels,
710 ),
711
712 Section( "",
713 Command( wxT("AddLabel"), XXO("Add Label at &Selection"),
714 OnAddLabel, AlwaysEnabledFlag, wxT("Ctrl+B") ),
715 Command( wxT("AddLabelPlaying"),
716 XXO("Add Label at &Playback Position"),
718 #ifdef __WXMAC__
719 wxT("Ctrl+.")
720 #else
721 wxT("Ctrl+M")
722 #endif
723 ),
724 Command( wxT("PasteNewLabel"), XXO("Paste Te&xt to New Label"),
726 AudioIONotBusyFlag(), wxT("Ctrl+Alt+V") )
727 ),
728
729 Section( "",
730 Command( wxT("TypeToCreateLabel"),
731 XXO("&Typing Creates New Labels"),
733 Options{}.CheckTest(wxT("/GUI/TypeToCreateLabel"), false) )
734 )
735 ), // first menu
736
738
739 Menu( wxT("Labeled"), XXO("La&beled Audio"),
740 Section( "",
741 /* i18n-hint: (verb)*/
742 Command( wxT("CutLabels"), XXO("&Cut"), OnCutLabels,
745 Options{ wxT("Alt+X"), XO("Cut by label") } ),
746 Command( wxT("DeleteLabels"), XXO("&Delete"), OnDeleteLabels,
749 Options{ wxT("Alt+K"), XO("Delete by label") } )
750 ),
751
752 Section( "",
753 /* i18n-hint: (verb) A special way to cut out a piece of audio*/
754 Command( wxT("SplitCutLabels"), XXO("C&ut and leave gap"),
755 OnSplitCutLabels, NotBusyLabelsAndWaveFlags,
756 Options{ wxT("Alt+Shift+X"), XO("Cut by labels and leave gap") } ),
757 Command( wxT("SplitDeleteLabels"), XXO("De&lete and leave gap"),
758 OnSplitDeleteLabels, NotBusyLabelsAndWaveFlags,
759 Options{ wxT("Alt+Shift+K"), XO("Delete by labels and leave gap") } )
760 ),
761
762 Section( "",
763 Command( wxT("SilenceLabels"), XXO("Silence &Audio"),
764 OnSilenceLabels, NotBusyLabelsAndWaveFlags,
765 Options{ wxT("Alt+L"), XO("Label Silence") } ),
766 /* i18n-hint: (verb)*/
767 Command( wxT("CopyLabels"), XXO("Co&py"), OnCopyLabels,
768 NotBusyLabelsAndWaveFlags,
769 Options{ wxT("Alt+Shift+C"), XO("Label Copy") } )
770 ),
771
772 Section( "",
773 /* i18n-hint: (verb)*/
774 Command( wxT("SplitLabels"), XXO("Spli&t"), OnSplitLabels,
776 Options{ wxT("Alt+I"), XO("Label Split") } ),
777 /* i18n-hint: (verb)*/
778 Command( wxT("JoinLabels"), XXO("&Join"), OnJoinLabels,
779 NotBusyLabelsAndWaveFlags,
780 Options{ wxT("Alt+J"), XO("Label Join") } ),
781 Command( wxT("DisjoinLabels"), XXO("Detac&h at Silences"),
782 OnDisjoinLabels, NotBusyLabelsAndWaveFlags,
783 wxT("Alt+Shift+J") )
784 )
785 ) // second menu
786
787 ) }; // two menus
788 return menus;
789}
790
792 { wxT("Edit/Other"),
793 { OrderingHint::Before, wxT("EditMetaData") } }
794};
795
797 Command( wxT("NewLabelTrack"), XXO("&Label Track"),
799 wxT("Tracks/Add/Add")
800};
801
802}
wxT("CloseDown"))
Toolkit-neutral facade for basic user interface services.
AttachedItem sAttachment1
AttachedItem sAttachment2
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:34
const ReservedCommandFlag & AudioIOBusyFlag()
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & WaveTracksExistFlag()
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
WaveTrack::Region Region
Definition: LabelMenus.cpp:25
WaveTrack::Regions Regions
Definition: LabelMenus.cpp:26
static const auto title
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
TranslatableString label
Definition: TagsEditor.cpp:165
const auto tracks
const auto project
std::function< void(double)> ProgressReporter
Definition: Track.h:48
bool GetEditClipsCanMove()
Definition: WaveTrack.cpp:3408
static std::once_flag flag
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static AudioIO * Get()
Definition: AudioIO.cpp:126
static Clipboard & Get()
Definition: Clipboard.cpp:28
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
A LabelStruct holds information for ONE label in a LabelTrack.
Definition: LabelTrack.h:40
double getT1() const
Definition: LabelTrack.h:51
double getT0() const
Definition: LabelTrack.h:50
SelectedRegion selectedRegion
Definition: LabelTrack.h:80
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:98
static LabelTrack * Create(TrackList &trackList, const wxString &name)
Create a new LabelTrack with specified name and append it to the trackList.
Definition: LabelTrack.cpp:109
static LabelTrackView & Get(LabelTrack &)
static int DialogForLabelName(AudacityProject &project, const SelectedRegion &region, const wxString &initialValue, wxString &value)
int AddLabel(const SelectedRegion &region, const wxString &title={}, int restoreFocus=-1)
static void DoEditLabels(AudacityProject &project, LabelTrack *lt=nullptr, int index=-1)
AudioTrack subclass that can also be audibly replayed by the program.
Definition: PlayableTrack.h:40
int GetAudioIOToken() const
static ProjectAudioIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
Generates classes whose instances register items at construction.
Definition: Registry.h:388
Defines a selected portion of a project.
double t1() const
double t0() const
static bool IsSyncLockSelected(const Track &track)
Definition: SyncLock.cpp:80
bool IsSyncLocked() const
Definition: SyncLock.cpp:44
static SyncLockState & Get(AudacityProject &project)
Definition: SyncLock.cpp:27
static void ModifyAllProjectToolbarMenus()
Track * Get()
Definition: TrackFocus.cpp:156
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
virtual void SetSelected(bool s)
Definition: Track.cpp:83
R TypeSwitch(const Functions &...functions)
Definition: Track.h:381
virtual void Clear(double t0, double t1)=0
std::shared_ptr< Track > Holder
Definition: Track.h:202
bool Any() const
Definition: Track.cpp:255
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:850
static TrackListHolder Create(AudacityProject *pOwner)
Definition: Track.cpp:330
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:967
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:234
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:216
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
void ShowTrack(const Track &track)
Definition: Viewport.cpp:460
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
void SplitDelete(double t0, double t1)
Definition: WaveTrack.cpp:1526
std::vector< Region > Regions
Definition: WaveTrack.h:230
void Silence(double t0, double t1, ProgressReporter reportProgress) override
Definition: WaveTrack.cpp:2000
void Join(double t0, double t1, const ProgressReporter &reportProgress)
Definition: WaveTrack.cpp:2148
void ClearAndAddCutLine(double t0, double t1)
Definition: WaveTrack.cpp:1167
void Clear(double t0, double t1) override
Definition: WaveTrack.cpp:1161
void Split(double t0, double t1)
Definition: WaveTrack.cpp:3157
void Disjoin(double t0, double t1)
Definition: WaveTrack.cpp:2061
Holder SplitCut(double t0, double t1)
Definition: WaveTrack.cpp:966
double GetRate() const override
Definition: WaveTrack.cpp:821
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
Definition: WaveTrack.cpp:1097
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
bool ReadBool(const wxString &key, bool defaultValue) const
virtual bool Read(const wxString &key, bool *value) const =0
void SplitProgress(ItType first, ItType last, FnType action, ProgressReporter parent)
Helper for the update of a task's progress bar when this task is made of a range's subtasks.
Definition: BasicUI.h:339
constexpr auto Section
Definition: MenuRegistry.h:436
constexpr auto Items
Definition: MenuRegistry.h:427
constexpr auto Command
Definition: MenuRegistry.h:456
constexpr auto Menu
Items will appear in a main toolbar menu or in a sub-menu.
Definition: MenuRegistry.h:445
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
Definition: Registry.h:175
void SelectNone(AudacityProject &project)
WAVE_TRACK_API void WithClipRenderingProgress(std::function< void(const ProgressReporter &)> action, TranslatableString title=defaultStretchRenderingTitle)
void OnAddLabel(const CommandContext &context)
Definition: LabelMenus.cpp:328
void OnSplitDeleteLabels(const CommandContext &context)
Definition: LabelMenus.cpp:518
int DoAddLabel(AudacityProject &project, const SelectedRegion &region, bool preserveFocus=false)
Definition: LabelMenus.cpp:56
std::function< void(Track &track, double, double)> EditFunction
Definition: LabelMenus.cpp:187
void EditByLabel(AudacityProject &project, TrackList &tracks, const SelectedRegion &selectedRegion, EditFunction action)
Definition: LabelMenus.cpp:227
void OnSplitCutLabels(const CommandContext &context)
Definition: LabelMenus.cpp:489
void OnCopyLabels(const CommandContext &context)
Definition: LabelMenus.cpp:571
void OnSplitLabels(const CommandContext &context)
Definition: LabelMenus.cpp:593
void OnCutLabels(const CommandContext &context)
Definition: LabelMenus.cpp:422
auto GetTracksToEditByLabel(const AudacityProject &project, const TrackList &tracks)
Definition: LabelMenus.cpp:164
void GetRegionsByLabel(const TrackList &tracks, const SelectedRegion &selectedRegion, Regions &regions)
Definition: LabelMenus.cpp:126
void OnJoinLabels(const CommandContext &context)
Definition: LabelMenus.cpp:615
void OnPasteNewLabel(const CommandContext &context)
Definition: LabelMenus.cpp:351
void OnDeleteLabels(const CommandContext &context)
Definition: LabelMenus.cpp:466
void OnEditLabels(const CommandContext &context)
Definition: LabelMenus.cpp:322
const ReservedCommandFlag & LabelsSelectedFlag()
Definition: LabelMenus.cpp:32
std::function< void(Track &track, double, double, ProgressReporter)> EditFunctionWithProgress
Definition: LabelMenus.cpp:189
void OnSilenceLabels(const CommandContext &context)
Definition: LabelMenus.cpp:548
void OnDisjoinLabels(const CommandContext &context)
Definition: LabelMenus.cpp:646
void EditClipboardByLabel(AudacityProject &project, TrackList &tracks, const SelectedRegion &selectedRegion, EditDestFunction action)
Definition: LabelMenus.cpp:248
void OnAddLabelPlaying(const CommandContext &context)
Definition: LabelMenus.cpp:336
void OnToggleTypeToCreateLabel(const CommandContext &WXUNUSED(context))
Definition: LabelMenus.cpp:413
std::function< Track::Holder(Track &, double, double)> EditDestFunction
Definition: LabelMenus.cpp:240
void OnNewLabelTrack(const CommandContext &context)
Definition: LabelMenus.cpp:672
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
Options && CheckTest(const CheckFn &fn) &&
Definition: MenuRegistry.h:74
Structure to hold region of a wavetrack and a comparison function for sortability.
Definition: WaveTrack.h:217