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