Audacity  3.0.3
ExportMultiple.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  ExportMultiple.cpp
6 
7  Dominic Mazzoni
8 
9 *******************************************************************//********************************************************************/
17 
18 
19 #include "ExportMultiple.h"
20 
21 #include <wx/defs.h>
22 #include <wx/button.h>
23 #include <wx/checkbox.h>
24 #include <wx/choice.h>
25 #include <wx/dialog.h>
26 #include <wx/dirdlg.h>
27 #include <wx/event.h>
28 #include <wx/listbase.h>
29 #include <wx/filefn.h>
30 #include <wx/filename.h>
31 #include <wx/intl.h>
32 #include <wx/log.h>
33 #include <wx/radiobut.h>
34 #include <wx/simplebook.h>
35 #include <wx/sizer.h>
36 #include <wx/statbox.h>
37 #include <wx/stattext.h>
38 #include <wx/textctrl.h>
39 #include <wx/textdlg.h>
40 
41 #include "../FileNames.h"
42 #include "../LabelTrack.h"
43 #include "../Project.h"
44 #include "../ProjectSettings.h"
45 #include "../ProjectWindow.h"
46 #include "Prefs.h"
47 #include "../SelectionState.h"
48 #include "../ShuttleGui.h"
49 #include "../Tags.h"
50 #include "../WaveTrack.h"
51 #include "../widgets/HelpSystem.h"
52 #include "../widgets/AudacityMessageBox.h"
53 #include "../widgets/AudacityTextEntryDialog.h"
54 #include "../widgets/ProgressDialog.h"
55 
56 
57 namespace {
63  class ExportKit
64  {
65  public:
68  double t0;
69  double t1;
70  unsigned channels;
71  }; // end of ExportKit declaration
72  /* we are going to want an set of these kits, and don't know how many until
73  * runtime. I would dearly like to use a std::vector, but it seems that
74  * this isn't done anywhere else in Audacity, presumably for a reason?, so
75  * I'm stuck with wxArrays, which are much harder, as well as non-standard.
76  */
77 }
78 
79 /* define our dynamic array of export settings */
80 
81 enum {
82  FormatID = 10001,
96 };
97 
98 //
99 // ExportMultipleDialog methods
100 //
101 
102 BEGIN_EVENT_TABLE(ExportMultipleDialog, wxDialogWrapper)
104 // EVT_BUTTON(OptionsID, ExportMultipleDialog::OnOptions)
110  EVT_RADIOBUTTON(LabelID, ExportMultipleDialog::OnLabel)
111  EVT_RADIOBUTTON(TrackID, ExportMultipleDialog::OnTrack)
113  EVT_RADIOBUTTON(ByNameID, ExportMultipleDialog::OnByName)
119 
120 BEGIN_EVENT_TABLE(SuccessDialog, wxDialogWrapper)
121  EVT_LIST_KEY_DOWN(wxID_ANY, SuccessDialog::OnKeyDown)
122  EVT_LIST_ITEM_ACTIVATED(wxID_ANY, SuccessDialog::OnItemActivated) // happens when <enter> is pressed with list item having focus
124 
125 BEGIN_EVENT_TABLE(MouseEvtHandler, wxEvtHandler)
126  EVT_LEFT_DCLICK(MouseEvtHandler::OnMouse)
128 
130 : wxDialogWrapper( &GetProjectFrame( *project ),
131  wxID_ANY, XO("Export Multiple") )
132 , mExporter{ *project }
133 , mSelectionState{ SelectionState::Get( *project ) }
134 {
135  SetName();
136 
137  mProject = project;
138  mTracks = &TrackList::Get( *project );
139  // Construct an array of non-owning pointers
140  for (const auto &plugin : mExporter.GetPlugins())
141  mPlugins.push_back(plugin.get());
142 
143  this->CountTracksAndLabels();
144 
145  mBook = NULL;
146 
148 
149  // Creating some of the widgets cause events to fire
150  // and we don't want that until after we're completely
151  // created. (Observed on Windows)
152  mInitialized = false;
153  PopulateOrExchange(S);
154  mInitialized = true;
155 
156  Layout();
157  Fit();
158  SetMinSize(GetSize());
159  Center();
160 
161  EnableControls();
162 }
163 
165 {
166 }
167 
169 {
170  bool anySolo = !(( mTracks->Any<const WaveTrack>() + &WaveTrack::GetSolo ).empty());
171 
173  (mTracks->Leaders< const WaveTrack >() -
174  (anySolo ? &WaveTrack::GetNotSolo : &WaveTrack::GetMute)).size();
175 
176  // only the first label track
177  mLabels = *mTracks->Any< const LabelTrack >().begin();
179 }
180 
182 {
183  // Cannot export if all audio tracks are muted.
184  if (mNumWaveTracks == 0)
185  {
187  XO("All audio is muted."),
188  XO("Cannot Export Multiple"),
189  wxOK | wxCENTRE,
190  this);
191  return wxID_CANCEL;
192  }
193 
194  if ((mNumWaveTracks < 1) && (mNumLabels < 1))
195  {
197  XO(
198 "You have no unmuted Audio Tracks and no applicable \
199 \nlabels, so you cannot export to separate audio files."),
200  XO("Cannot Export Multiple"),
201  wxOK | wxCENTRE,
202  this);
203  return wxID_CANCEL;
204  }
205 
206  bool bHasLabels = (mNumLabels > 0);
207  bool bHasTracks = (mNumWaveTracks > 0);
208 
209  mLabel->Enable(bHasLabels && bHasTracks);
210  mTrack->Enable(bHasTracks);
211 
212  // If you have 2 or more tracks, then it is export by tracks.
213  // If you have no labels, then it is export by tracks.
214  // Otherwise it is export by labels, by default.
215  bool bPreferByLabels = bHasLabels && (mNumWaveTracks < 2);
216  mLabel->SetValue(bPreferByLabels);
217  mTrack->SetValue(!bPreferByLabels);
218 
219  EnableControls();
220 
221  return wxDialogWrapper::ShowModal();
222 }
223 
225 {
226  wxString name = mProject->GetProjectName();
227  wxString defaultFormat = gPrefs->Read(wxT("/Export/Format"), wxT("WAV"));
228 
229  TranslatableStrings visibleFormats;
230  wxArrayStringEx formats;
231  mPluginIndex = -1;
232  mFilterIndex = 0;
233 
234  {
235  int i = -1;
236  for (const auto &pPlugin : mPlugins)
237  {
238  ++i;
239  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
240  {
241  auto format = mPlugins[i]->GetDescription(j);
242  visibleFormats.push_back( format );
243  // use MSGID of description as a value too, written into config file
244  // This is questionable. A change in the msgid can make the
245  // preference stored in old config files inapplicable
246  formats.push_back( format.MSGID().GET() );
247  if (mPlugins[i]->GetFormat(j) == defaultFormat) {
248  mPluginIndex = i;
249  mSubFormatIndex = j;
250  }
251  if (mPluginIndex == -1) mFilterIndex++;
252  }
253  }
254  }
255 
256 
257  // Bug 1304: Set the default file path. It's used if none stored in config.
258  auto DefaultPath = FileNames::FindDefaultPath(FileNames::Operation::Export);
259 
260  if (mPluginIndex == -1)
261  {
262  mPluginIndex = 0;
263  mFilterIndex = 0;
264  mSubFormatIndex = 0;
265  }
266 
267  S.SetBorder(5);
268  S.StartHorizontalLay(wxEXPAND, true);
269  {
270  S.SetBorder(5);
271  S.StartStatic(XO("Export files to:"), true);
272  {
273  S.StartMultiColumn(4, true);
274  {
275  mDir = S.Id(DirID)
276  .AddTextBox(XXO("Folder:"),
277  DefaultPath,
278  64);
279  S.Id(ChooseID).AddButton(XXO("Choose..."));
280  S.Id(CreateID).AddButton(XXO("Create"));
281 
282  mFormat = S.Id(FormatID)
283  .TieChoice( XXO("Format:"),
284  {
285  wxT("/Export/MultipleFormat"),
286  {
287  ByColumns,
288  visibleFormats,
289  formats
290  },
292  }
293  );
294  S.AddVariableText( {}, false);
295  S.AddVariableText( {}, false);
296 
297  S.AddPrompt(XXO("Options:"));
298 
299  mBook = S.Id(OptionsID)
300  .Style(wxBORDER_STATIC)
301  .StartSimplebook();
302  if (S.GetMode() == eIsCreating)
303  {
304  for (const auto &pPlugin : mPlugins)
305  {
306  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
307  {
308  // Name of simple book page is not displayed
309  S.StartNotebookPage( {} );
310  pPlugin->OptionsCreate(S, j);
311  S.EndNotebookPage();
312  }
313  }
314  mBook->ChangeSelection(mFormat->GetSelection());
315  }
316  S.EndSimplebook();
317  S.AddVariableText( {}, false);
318  S.AddVariableText( {}, false);
319  }
320  S.EndMultiColumn();
321  }
322  S.EndStatic();
323  }
324  S.EndHorizontalLay();
325 
326  S.StartHorizontalLay(wxEXPAND, false);
327  {
328  S.SetBorder(5);
329  S.StartStatic(XO("Split files based on:"), 1);
330  {
331  // Row 1
332  S.SetBorder(1);
333 
334  // Bug 2692: Place button group in panel so tabbing will work and,
335  // on the Mac, VoiceOver will announce as radio buttons.
336  S.StartPanel();
337  {
338  mTrack = S.Id(TrackID)
339  .AddRadioButton(XXO("Tracks"));
340 
341  // Row 2
342  S.SetBorder(1);
343  mLabel = S.Id(LabelID)
344  .AddRadioButtonToGroup(XXO("Labels"));
345  }
346  S.EndPanel();
347 
348  S.SetBorder(3);
349  S.StartMultiColumn(2, wxEXPAND);
350  S.SetStretchyCol(1);
351  {
352  // Row 3 (indented)
353  S.AddVariableText(Verbatim(" "), false);
354  mFirst = S.Id(FirstID)
355  .AddCheckBox(XXO("Include audio before first label"), false);
356 
357  // Row 4
358  S.AddVariableText( {}, false);
359  S.StartMultiColumn(2, wxEXPAND);
360  S.SetStretchyCol(1);
361  {
363  S.AddVariableText(XO("First file name:"), false);
365  .Prop(1)
366  .Name(XO("First file name"))
367  .TieTextBox( {},
368  name,
369  30);
370  }
371  S.EndMultiColumn();
372  }
373  S.EndMultiColumn();
374 
375  S.SetBorder(3);
376  }
377  S.EndStatic();
378 
379  S.SetBorder(5);
380  S.StartStatic(XO("Name files:"), 1);
381  {
382  S.SetBorder(2);
383 
384  // Bug 2692: Place button group in panel so tabbing will work and,
385  // on the Mac, VoiceOver will announce as radio buttons.
386  S.StartPanel();
387  {
389  wxT("/Export/TrackNameWithOrWithoutNumbers"),
390  {
391  { wxT("labelTrack"), XXO("Using Label/Track Name") },
392  { wxT("numberBefore"), XXO("Numbering before Label/Track Name") },
393  { wxT("numberAfter"), XXO("Numbering after File name prefix") },
394  },
395  0 // labelTrack
396  });
397  {
399 
401 
403  }
405  }
406  S.EndPanel();
407 
408  S.StartMultiColumn(3, wxEXPAND);
409  S.SetStretchyCol(2);
410  {
411  // Row 3 (indented)
412  S.AddVariableText(Verbatim(" "), false);
413  mPrefixLabel = S.AddVariableText(XO("File name prefix:"), false);
414  mPrefix = S.Id(PrefixID)
415  .Name(XO("File name prefix"))
416  .TieTextBox( {},
417  name,
418  30);
419  }
420  S.EndMultiColumn();
421  }
422  S.EndStatic();
423  }
424  S.EndHorizontalLay();
425 
426  S.SetBorder(5);
427  S.StartHorizontalLay(wxEXPAND, false);
428  {
429  mOverwrite = S.Id(OverwriteID).TieCheckBox(XXO("Overwrite existing files"),
430  {wxT("/Export/OverwriteExisting"),
431  false});
432  }
433  S.EndHorizontalLay();
434 
436  mExport = (wxButton *)wxWindow::FindWindowById(wxID_OK, this);
437  mExport->SetLabel(_("Export"));
438 
439 }
440 
442 {
443  bool enable;
444 
445  if (!mInitialized) {
446  return;
447  }
448 
449  mFirst->Enable(mLabel->GetValue());
450 
451  enable = mLabel->GetValue() &&
452  (mByName->GetValue() || mByNumberAndName->GetValue()) &&
453  mFirst->GetValue();
454  mFirstFileLabel->Enable(enable);
455  mFirstFileName->Enable(enable);
456 
457  enable = mByNumber->GetValue();
458  mPrefixLabel->Enable(enable);
459  mPrefix->Enable(enable);
460 
461  bool ok = true;
462 
463  if (mLabel->GetValue() && mFirst->GetValue() &&
464  mFirstFileName->GetValue().empty() &&
465  mPrefix->GetValue().empty())
466  ok = false;
467 
468  if (mByNumber->GetValue() &&
469  mPrefix->GetValue().empty())
470  ok = false;
471 
472  mExport->Enable(ok);
473 }
474 
475 void ExportMultipleDialog::OnFormat(wxCommandEvent& WXUNUSED(event))
476 {
477  mBook->ChangeSelection(mFormat->GetSelection());
478 
479  EnableControls();
480 }
481 
482 void ExportMultipleDialog::OnOptions(wxCommandEvent& WXUNUSED(event))
483 {
484  const int sel = mFormat->GetSelection();
485  if (sel != wxNOT_FOUND)
486  {
487  size_t c = 0;
488  int i = -1;
489  for (const auto &pPlugin : mPlugins)
490  {
491  ++i;
492  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
493  {
494  if ((size_t)sel == c)
495  {
496  mPluginIndex = i;
497  mSubFormatIndex = j;
498  }
499  c++;
500  }
501  }
502  }
503  mPlugins[mPluginIndex]->DisplayOptions(this,mSubFormatIndex);
504 }
505 
506 void ExportMultipleDialog::OnCreate(wxCommandEvent& WXUNUSED(event))
507 {
508  wxFileName fn;
509 
510  fn.AssignDir(mDir->GetValue());
511 
512  bool ok = fn.Mkdir(0777, wxPATH_MKDIR_FULL);
513 
514  if (!ok) {
515  // Mkdir will produce an error dialog
516  return;
517  }
518 
520  XO("\"%s\" successfully created.").Format( fn.GetPath() ),
521  XO("Export Multiple"),
522  wxOK | wxCENTRE,
523  this);
524 }
525 
526 void ExportMultipleDialog::OnChoose(wxCommandEvent& WXUNUSED(event))
527 {
528  wxDirDialogWrapper dlog(this,
529  XO("Choose a location to save the exported files"),
530  mDir->GetValue());
531  dlog.ShowModal();
532  if (!dlog.GetPath().empty())
533  mDir->SetValue(dlog.GetPath());
534 }
535 
536 void ExportMultipleDialog::OnLabel(wxCommandEvent& WXUNUSED(event))
537 {
538  EnableControls();
539 }
540 
541 void ExportMultipleDialog::OnFirst(wxCommandEvent& WXUNUSED(event))
542 {
543  EnableControls();
544 }
545 
546 void ExportMultipleDialog::OnFirstFileName(wxCommandEvent& WXUNUSED(event))
547 {
548  EnableControls();
549 }
550 
551 void ExportMultipleDialog::OnTrack(wxCommandEvent& WXUNUSED(event))
552 {
553  EnableControls();
554 }
555 
556 void ExportMultipleDialog::OnByName(wxCommandEvent& WXUNUSED(event))
557 {
558  EnableControls();
559 }
560 
561 void ExportMultipleDialog::OnByNumber(wxCommandEvent& WXUNUSED(event))
562 {
563  EnableControls();
564 }
565 
566 void ExportMultipleDialog::OnPrefix(wxCommandEvent& WXUNUSED(event))
567 {
568  EnableControls();
569 }
570 
571 void ExportMultipleDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
572 {
573  EndModal(0);
574 }
575 
576 void ExportMultipleDialog::OnHelp(wxCommandEvent& WXUNUSED(event))
577 {
578  HelpSystem::ShowHelp(this, L"Export_Multiple", true);
579 }
580 
581 void ExportMultipleDialog::OnExport(wxCommandEvent& WXUNUSED(event))
582 {
583  ShuttleGui S(this, eIsSavingToPrefs);
585 
586  gPrefs->Flush();
587 
588  FileNames::UpdateDefaultPath(FileNames::Operation::Export, mDir->GetValue());
589 
590  // Make sure the output directory is in good shape
591  if (!DirOk()) {
592  return;
593  }
594 
595  mFilterIndex = mFormat->GetSelection();
596  if (mFilterIndex != wxNOT_FOUND)
597  {
598  size_t c = 0;
599  int i = -1;
600  for (const auto &pPlugin : mPlugins)
601  {
602  ++i;
603  for (int j = 0; j < pPlugin->GetFormatCount(); j++, c++)
604  {
605  if ((size_t)mFilterIndex == c)
606  { // this is the selected format. Store the plug-in and sub-format
607  // needed to achieve it.
608  mPluginIndex = i;
609  mSubFormatIndex = j;
610  mBook->GetPage(mFilterIndex)->TransferDataFromWindow();
611  }
612  }
613  }
614  }
615 
616 // bool overwrite = mOverwrite->GetValue();
617  ProgressResult ok = ProgressResult::Failed;
618  mExported.clear();
619 
620  // Give 'em the result
621  auto cleanup = finally( [&]
622  {
623  auto msg = (ok == ProgressResult::Success
624  ? XO("Successfully exported the following %lld file(s).")
625  : ok == ProgressResult::Failed
626  ? XO("Something went wrong after exporting the following %lld file(s).")
628  ? XO("Export canceled after exporting the following %lld file(s).")
629  : ok == ProgressResult::Stopped
630  ? XO("Export stopped after exporting the following %lld file(s).")
631  : XO("Something went really wrong after exporting the following %lld file(s).")
632  ).Format((long long) mExported.size());
633 
634  wxString FileList;
635  for (size_t i = 0; i < mExported.size(); i++) {
636  FileList += mExported[i];
637  FileList += '\n';
638  }
639 
640  // TODO: give some warning dialog first, when only some files exported
641  // successfully.
642 
643  GuardedCall( [&] {
644  // This results dialog is a child of this dialog.
646  XO("Export Multiple"),
647  msg,
648  FileList,
649  450,400);
650  } );
651  } );
652 
653  if (mLabel->GetValue()) {
654  ok = ExportMultipleByLabel(mByName->GetValue() || mByNumberAndName->GetValue(),
655  mPrefix->GetValue(),
656  mByNumberAndName->GetValue());
657  }
658  else {
659  ok = ExportMultipleByTrack(mByName->GetValue() || mByNumberAndName->GetValue(),
660  mPrefix->GetValue(),
661  mByNumberAndName->GetValue());
662  }
663 
664  if (ok == ProgressResult::Success || ok == ProgressResult::Stopped) {
665  EndModal(1);
666  }
667 }
668 
670 {
671  wxFileName fn;
672 
673  fn.AssignDir(mDir->GetValue());
674 
675  if (fn.DirExists()) {
676  return true;
677  }
678 
679  auto prompt = XO("\"%s\" doesn't exist.\n\nWould you like to create it?")
680  .Format( fn.GetFullPath() );
681 
682  int action = AudacityMessageBox(
683  prompt,
684  XO("Warning"),
685  wxYES_NO | wxICON_EXCLAMATION);
686  if (action != wxYES) {
687  return false;
688  }
689 
690  return fn.Mkdir(0777, wxPATH_MKDIR_FULL);
691 }
692 
693 static unsigned GetNumExportChannels( const TrackList &tracks )
694 {
695  /* counters for tracks panned different places */
696  int numLeft = 0;
697  int numRight = 0;
698  //int numMono = 0;
699  /* track iteration kit */
700 
701  bool anySolo = !(( tracks.Any<const WaveTrack>() + &WaveTrack::GetSolo ).empty());
702 
703  // Want only unmuted wave tracks.
704  for (auto tr :
705  tracks.Any< const WaveTrack >() -
707  ) {
708  // Found a left channel
709  if (tr->GetChannel() == Track::LeftChannel) {
710  numLeft++;
711  }
712 
713  // Found a right channel
714  else if (tr->GetChannel() == Track::RightChannel) {
715  numRight++;
716  }
717 
718  // Found a mono channel, but it may be panned
719  else if (tr->GetChannel() == Track::MonoChannel) {
720  float pan = tr->GetPan();
721 
722  // Figure out what kind of channel it should be
723  if (pan == -1.0) { // panned hard left
724  numLeft++;
725  }
726  else if (pan == 1.0) { // panned hard right
727  numRight++;
728  }
729  else if (pan == 0) { // panned dead center
730  // numMono++;
731  }
732  else { // panned somewhere else
733  numLeft++;
734  numRight++;
735  }
736  }
737  }
738 
739  // if there is stereo content, report 2, else report 1
740  if (numRight > 0 || numLeft > 0) {
741  return 2;
742  }
743 
744  return 1;
745 }
746 
747 // TODO: JKC July2016: Merge labels/tracks duplicated export code.
748 // TODO: JKC Apr2019: Doubly so merge these! Too much duplication.
750  const wxString &prefix, bool addNumber)
751 {
752  wxASSERT(mProject);
753  int numFiles = mNumLabels;
754  int l = 0; // counter for files done
755  std::vector<ExportKit> exportSettings; // dynamic array for settings.
756  exportSettings.reserve(numFiles); // Allocate some guessed space to use.
757 
758  // Account for exporting before first label
759  if( mFirst->GetValue() ) {
760  l--;
761  numFiles++;
762  }
763 
764  // Figure out how many channels we should export.
765  auto channels = GetNumExportChannels( *mTracks );
766 
767  FilePaths otherNames; // keep track of file names we will use, so we
768  // don't duplicate them
769  ExportKit setting; // the current batch of settings
770  setting.destfile.SetPath(mDir->GetValue());
771  setting.destfile.SetExt(mPlugins[mPluginIndex]->GetExtension(mSubFormatIndex));
772  wxLogDebug(wxT("Plug-in index = %d, Sub-format = %d"), mPluginIndex, mSubFormatIndex);
773  wxLogDebug(wxT("File extension is %s"), setting.destfile.GetExt());
774  wxString name; // used to hold file name whilst we mess with it
775  wxString title; // un-messed-with title of file for tagging with
776 
777  const LabelStruct *info = NULL;
778  /* Examine all labels a first time, sort out all data but don't do any
779  * exporting yet (so this run is quick but interactive) */
780  while( l < mNumLabels ) {
781 
782  // Get file name and starting time
783  if( l < 0 ) {
784  // create wxFileName for output file
785  name = (mFirstFileName->GetValue());
786  setting.t0 = 0.0;
787  } else {
788  info = mLabels->GetLabel(l);
789  name = (info->title);
790  setting.t0 = info->selectedRegion.t0();
791  }
792 
793  // Figure out the ending time
794  if( info && !info->selectedRegion.isPoint() ) {
795  setting.t1 = info->selectedRegion.t1();
796  } else if( l < mNumLabels-1 ) {
797  // Use start of next label as end
798  const LabelStruct *info1 = mLabels->GetLabel(l+1);
799  setting.t1 = info1->selectedRegion.t0();
800  } else {
801  setting.t1 = mTracks->GetEndTime();
802  }
803 
804  if( name.empty() )
805  name = _("untitled");
806 
807  // store title of label to use in tags
808  title = name;
809 
810  // Numbering files...
811  if( !byName ) {
812  name.Printf(wxT("%s-%02d"), prefix, l+1);
813  } else if( addNumber ) {
814  // Following discussion with GA, always have 2 digits
815  // for easy file-name sorting (on Windows)
816  name.Prepend(wxString::Format(wxT("%02d-"), l+1));
817  }
818 
819  // store sanitised and user checked name in object
820  setting.destfile.SetName(MakeFileName(name));
821  if( setting.destfile.GetName().empty() )
822  { // user cancelled dialogue, or deleted everything in field.
823  // or maybe the label was empty??
824  // So we ignore this one and keep going.
825  }
826  else
827  {
828  // FIXME: TRAP_ERR User could have given an illegal filename prefix.
829  // in that case we should tell them, not fail silently.
830  wxASSERT(setting.destfile.IsOk()); // burp if file name is broke
831 
832  // Make sure the (final) file name is unique within the set of exports
833  FileNames::MakeNameUnique(otherNames, setting.destfile);
834 
835  /* do the metadata for this file */
836  // copy project metadata to start with
837  setting.filetags = Tags::Get( *mProject );
838  setting.filetags.LoadDefaults();
839  if (exportSettings.size()) {
840  setting.filetags = exportSettings.back().filetags;
841  }
842  // over-ride with values
843  setting.filetags.SetTag(TAG_TITLE, title);
844  setting.filetags.SetTag(TAG_TRACK, l+1);
845  // let the user have a crack at editing it, exit if cancelled
847  bool bShowTagsDialog = settings.GetShowId3Dialog();
848 
849  bShowTagsDialog = bShowTagsDialog && mPlugins[mPluginIndex]->GetCanMetaData(mSubFormatIndex);
850 
851  if( bShowTagsDialog ){
852  bool bCancelled = !setting.filetags.ShowEditDialog(
854  XO("Edit Metadata Tags"), bShowTagsDialog);
855  gPrefs->Read(wxT("/AudioFiles/ShowId3Dialog"), &bShowTagsDialog, true);
856  settings.SetShowId3Dialog( bShowTagsDialog );
857  if( bCancelled )
859  }
860  }
861 
862  /* add the settings to the array of settings to be used for export */
863  exportSettings.push_back(setting);
864 
865  l++; // next label, count up one
866  }
867 
868  auto ok = ProgressResult::Success; // did it work?
869  int count = 0; // count the number of successful runs
870  ExportKit activeSetting; // pointer to the settings in use for this export
871  /* Go round again and do the exporting (so this run is slow but
872  * non-interactive) */
873  std::unique_ptr<ProgressDialog> pDialog;
874  for (count = 0; count < numFiles; count++) {
875  /* get the settings to use for the export from the array */
876  activeSetting = exportSettings[count];
877  // Bug 1440 fix.
878  if( activeSetting.destfile.GetName().empty() )
879  continue;
880 
881  // Export it
882  ok = DoExport(pDialog, channels, activeSetting.destfile, false,
883  activeSetting.t0, activeSetting.t1, activeSetting.filetags);
884  if (ok == ProgressResult::Stopped) {
885  AudacityMessageDialog dlgMessage(
886  nullptr,
887  XO("Continue to export remaining files?"),
888  XO("Export"),
889  wxYES_NO | wxNO_DEFAULT | wxICON_WARNING);
890  if (dlgMessage.ShowModal() != wxID_YES ) {
891  // User decided not to continue - bail out!
892  break;
893  }
894  }
895  else if (ok != ProgressResult::Success) {
896  break;
897  }
898  }
899 
900  return ok;
901 }
902 
904  const wxString &prefix, bool addNumber)
905 {
906  wxASSERT(mProject);
907  int l = 0; // track counter
908  auto ok = ProgressResult::Success;
909  FilePaths otherNames;
910  std::vector<ExportKit> exportSettings; // dynamic array we will use to store the
911  // settings needed to do the exports with in
912  exportSettings.reserve(mNumWaveTracks); // Allocate some guessed space to use.
913  ExportKit setting; // the current batch of settings
914  setting.destfile.SetPath(mDir->GetValue());
915  setting.destfile.SetExt(mPlugins[mPluginIndex]->GetExtension(mSubFormatIndex));
916 
917  wxString name; // used to hold file name whilst we mess with it
918  wxString title; // un-messed-with title of file for tagging with
919 
920  /* Remember which tracks were selected, and set them to deselected */
922  for (auto tr : mTracks->Selected<WaveTrack>())
923  tr->SetSelected(false);
924 
925  bool anySolo = !(( mTracks->Any<const WaveTrack>() + &WaveTrack::GetSolo ).empty());
926 
927  bool skipSilenceAtBeginning;
928  gPrefs->Read(wxT("/AudioFiles/SkipSilenceAtBeginning"), &skipSilenceAtBeginning, false);
929 
930  /* Examine all tracks in turn, collecting export information */
931  for (auto tr : mTracks->Leaders<WaveTrack>() -
932  (anySolo ? &WaveTrack::GetNotSolo : &WaveTrack::GetMute)) {
933 
934  // Get the times for the track
935  auto channels = TrackList::Channels(tr);
936  setting.t0 = skipSilenceAtBeginning ? channels.min(&Track::GetStartTime) : 0;
937  setting.t1 = channels.max( &Track::GetEndTime );
938 
939  // number of export channels?
940  setting.channels = channels.size();
941  if (setting.channels == 1 &&
942  !(tr->GetChannel() == WaveTrack::MonoChannel &&
943  tr->GetPan() == 0.0))
944  setting.channels = 2;
945 
946  // Get name and title
947  title = tr->GetName();
948  if( title.empty() )
949  title = _("untitled");
950 
951  if (byName) {
952  name = title;
953  if (addNumber) {
954  name.Prepend(
955  wxString::Format(wxT("%02d-"), l+1));
956  }
957  }
958  else {
959  name = (wxString::Format(wxT("%s-%02d"), prefix, l+1));
960  }
961 
962  // store sanitised and user checked name in object
963  setting.destfile.SetName(MakeFileName(name));
964 
965  if (setting.destfile.GetName().empty())
966  { // user cancelled dialogue, or deleted everything in field.
967  // So we ignore this one and keep going.
968  }
969  else
970  {
971 
972  // FIXME: TRAP_ERR User could have given an illegal track name.
973  // in that case we should tell them, not fail silently.
974  wxASSERT(setting.destfile.IsOk()); // burp if file name is broke
975 
976  // Make sure the (final) file name is unique within the set of exports
977  FileNames::MakeNameUnique(otherNames, setting.destfile);
978 
979  /* do the metadata for this file */
980  // copy project metadata to start with
981  setting.filetags = Tags::Get( *mProject );
982  setting.filetags.LoadDefaults();
983  if (exportSettings.size()) {
984  setting.filetags = exportSettings.back().filetags;
985  }
986  // over-ride with values
987  setting.filetags.SetTag(TAG_TITLE, title);
988  setting.filetags.SetTag(TAG_TRACK, l+1);
989  // let the user have a crack at editing it, exit if cancelled
991  bool bShowTagsDialog = settings.GetShowId3Dialog();
992 
993  bShowTagsDialog = bShowTagsDialog && mPlugins[mPluginIndex]->GetCanMetaData(mSubFormatIndex);
994 
995  if( bShowTagsDialog ){
996  bool bCancelled = !setting.filetags.ShowEditDialog(
998  XO("Edit Metadata Tags"), bShowTagsDialog);
999  gPrefs->Read(wxT("/AudioFiles/ShowId3Dialog"), &bShowTagsDialog, true);
1000  settings.SetShowId3Dialog( bShowTagsDialog );
1001  if( bCancelled )
1003  }
1004  }
1005  /* add the settings to the array of settings to be used for export */
1006  exportSettings.push_back(setting);
1007 
1008  l++; // next track, count up one
1009  }
1010  // end of user-interactive data gathering loop, start of export processing
1011  // loop
1012  int count = 0; // count the number of successful runs
1013  ExportKit activeSetting; // pointer to the settings in use for this export
1014  std::unique_ptr<ProgressDialog> pDialog;
1015 
1016  for (auto tr : mTracks->Leaders<WaveTrack>() -
1017  (anySolo ? &WaveTrack::GetNotSolo : &WaveTrack::GetMute)) {
1018 
1019  wxLogDebug( "Get setting %i", count );
1020  /* get the settings to use for the export from the array */
1021  activeSetting = exportSettings[count];
1022  if( activeSetting.destfile.GetName().empty() ){
1023  count++;
1024  continue;
1025  }
1026 
1027  /* Select the track */
1029  const auto range = TrackList::Channels(tr);
1030  for (auto channel : range)
1031  channel->SetSelected(true);
1032 
1033  // Export the data. "channels" are per track.
1034  ok = DoExport(pDialog,
1035  activeSetting.channels, activeSetting.destfile, true,
1036  activeSetting.t0, activeSetting.t1, activeSetting.filetags);
1037  if (ok == ProgressResult::Stopped) {
1038  AudacityMessageDialog dlgMessage(
1039  nullptr,
1040  XO("Continue to export remaining files?"),
1041  XO("Export"),
1042  wxYES_NO | wxNO_DEFAULT | wxICON_WARNING);
1043  if (dlgMessage.ShowModal() != wxID_YES ) {
1044  // User decided not to continue - bail out!
1045  break;
1046  }
1047  }
1048  else if (ok != ProgressResult::Success) {
1049  break;
1050  }
1051  // increment export counter
1052  count++;
1053 
1054  }
1055 
1056  return ok ;
1057 }
1058 
1059 ProgressResult ExportMultipleDialog::DoExport(std::unique_ptr<ProgressDialog> &pDialog,
1060  unsigned channels,
1061  const wxFileName &inName,
1062  bool selectedOnly,
1063  double t0,
1064  double t1,
1065  const Tags &tags)
1066 {
1067  wxFileName name;
1068 
1069  wxLogDebug(wxT("Doing multiple Export: File name \"%s\""), (inName.GetFullName()));
1070  wxLogDebug(wxT("Channels: %i, Start: %lf, End: %lf "), channels, t0, t1);
1071  if (selectedOnly)
1072  wxLogDebug(wxT("Selected Region Only"));
1073  else
1074  wxLogDebug(wxT("Whole Project"));
1075 
1076  wxFileName backup;
1077  if (mOverwrite->GetValue()) {
1078  name = inName;
1079  backup.Assign(name);
1080 
1081  int suffix = 0;
1082  do {
1083  backup.SetName(name.GetName() +
1084  wxString::Format(wxT("%d"), suffix));
1085  ++suffix;
1086  }
1087  while (backup.FileExists());
1088  ::wxRenameFile(inName.GetFullPath(), backup.GetFullPath());
1089  }
1090  else {
1091  name = inName;
1092  int i = 2;
1093  wxString base(name.GetName());
1094  while (name.FileExists()) {
1095  name.SetName(wxString::Format(wxT("%s-%d"), base, i++));
1096  }
1097  }
1098 
1100  const wxString fullPath{name.GetFullPath()};
1101 
1102  auto cleanup = finally( [&] {
1103  bool ok =
1104  success == ProgressResult::Stopped ||
1105  success == ProgressResult::Success;
1106  if (backup.IsOk()) {
1107  if ( ok )
1108  // Remove backup
1109  ::wxRemoveFile(backup.GetFullPath());
1110  else {
1111  // Restore original
1112  ::wxRemoveFile(fullPath);
1113  ::wxRenameFile(backup.GetFullPath(), fullPath);
1114  }
1115  }
1116  else {
1117  if ( ! ok )
1118  // Remove any new, and only partially written, file.
1119  ::wxRemoveFile(fullPath);
1120  }
1121  } );
1122 
1123  // Call the format export routine
1124  success = mPlugins[mPluginIndex]->Export(mProject,
1125  pDialog,
1126  channels,
1127  fullPath,
1128  selectedOnly,
1129  t0,
1130  t1,
1131  NULL,
1132  &tags,
1133  mSubFormatIndex);
1134 
1135  if (success == ProgressResult::Success || success == ProgressResult::Stopped) {
1136  mExported.push_back(fullPath);
1137  }
1138 
1139  Refresh();
1140  Update();
1141 
1142  return success;
1143 }
1144 
1145 wxString ExportMultipleDialog::MakeFileName(const wxString &input)
1146 {
1147  wxString newname = input; // name we are generating
1148 
1149  // strip out anything that isn't allowed in file names on this platform
1150  auto changed = Internat::SanitiseFilename(newname, wxT("_"));
1151 
1152  if(changed)
1153  { // need to get user to fix file name
1154  // build the dialog
1155  TranslatableString msg;
1156  wxString excluded = ::wxJoin( Internat::GetExcludedCharacters(), wxT(' '), wxT('\0') );
1157  // TODO: For Russian language we should have separate cases for 2 and more than 2 letters.
1158  if( excluded.length() > 1 ){
1159  msg = XO(
1160 // i18n-hint: The second %s gives some letters that can't be used.
1161 "Label or track \"%s\" is not a legal file name.\nYou cannot use any of these characters:\n\n%s\n\nSuggested replacement:")
1162  .Format( input, excluded );
1163  } else {
1164  msg = XO(
1165 // i18n-hint: The second %s gives a letter that can't be used.
1166 "Label or track \"%s\" is not a legal file name. You cannot use \"%s\".\n\nSuggested replacement:")
1167  .Format( input, excluded );
1168  }
1169 
1170  AudacityTextEntryDialog dlg( this, msg, XO("Save As..."), newname );
1171 
1172 
1173  // And tell the validator about excluded chars
1174  dlg.SetTextValidator( wxFILTER_EXCLUDE_CHAR_LIST );
1175  wxTextValidator *tv = dlg.GetTextValidator();
1176  tv->SetExcludes(Internat::GetExcludedCharacters());
1177 
1178  // Show the dialog and bail if the user cancels
1179  if( dlg.ShowModal() == wxID_CANCEL )
1180  {
1181  return wxEmptyString;
1182  }
1183  // Extract the name from the dialog
1184  newname = dlg.GetValue();
1185  } // phew - end of file name sanitisation procedure
1186  return newname;
1187 }
1188 
1189 void SuccessDialog::OnKeyDown(wxListEvent& event)
1190 {
1191  if (event.GetKeyCode() == WXK_RETURN)
1192  EndModal(1);
1193  else
1194  event.Skip(); // allow standard behaviour
1195 }
1196 
1197 void SuccessDialog::OnItemActivated(wxListEvent& WXUNUSED(event))
1198 {
1199  EndModal(1);
1200 }
1201 
1202 void MouseEvtHandler::OnMouse(wxMouseEvent& event)
1203 {
1204  event.Skip(false);
1205 }
ExportMultipleDialog::mPrefixLabel
wxStaticText * mPrefixLabel
Definition: ExportMultiple.h:154
ExportMultipleDialog::mProject
AudacityProject * mProject
Definition: ExportMultiple.h:110
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
ShuttleGuiBase::StartRadioButtonGroup
void StartRadioButtonGroup(const ChoiceSetting &Setting)
Call this before any TieRadioButton calls.
Definition: ShuttleGui.cpp:1595
ExportMultipleDialog::mLabel
wxRadioButton * mLabel
Definition: ExportMultiple.h:139
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
ShuttleGuiBase::EndSimplebook
void EndSimplebook()
Definition: ShuttleGui.cpp:1061
TrackID
@ TrackID
Definition: ExportMultiple.cpp:90
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:38
ExportMultipleDialog::OnLabel
void OnLabel(wxCommandEvent &event)
Definition: ExportMultiple.cpp:536
TranslatableString::empty
bool empty() const
Definition: TranslatableString.h:72
ShuttleGuiBase::EndRadioButtonGroup
void EndRadioButtonGroup()
Definition: ShuttleGui.cpp:1612
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
GuardedCall
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), std::function< void(AudacityException *)> delayedHandler=DefaultDelayedHandlerAction{})
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
Definition: AudacityException.h:202
ExportMultipleDialog::mExported
FilePaths mExported
Definition: ExportMultiple.h:128
ShuttleGuiBase::AddCheckBox
wxCheckBox * AddCheckBox(const TranslatableString &Prompt, bool Selected)
Definition: ShuttleGui.cpp:309
ExportMultipleDialog::OnFirstFileName
void OnFirstFileName(wxCommandEvent &event)
Definition: ExportMultiple.cpp:546
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption=XO("Message"), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: AudacityMessageBox.h:20
BasicUI::ProgressResult::Success
@ Success
Track::RightChannel
static const auto RightChannel
Definition: Track.h:267
PlayableTrack::GetSolo
bool GetSolo() const
Definition: Track.h:845
ExportMultipleDialog::mTrack
wxRadioButton * mTrack
Definition: ExportMultiple.h:147
ExportMultipleDialog::mFirstFileLabel
wxStaticText * mFirstFileLabel
Definition: ExportMultiple.h:143
PlayableTrack::GetMute
bool GetMute() const
Definition: Track.h:844
fn
static const auto fn
Definition: WaveformView.cpp:1114
wxFileNameWrapper
Definition: wxFileNameWrapper.h:21
ExportMultipleDialog::EnableControls
void EnableControls()
Definition: ExportMultiple.cpp:441
MouseEvtHandler::OnMouse
void OnMouse(wxMouseEvent &event)
Definition: ExportMultiple.cpp:1202
LabelStruct::title
wxString title
Definition: LabelTrack.h:71
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
HelpSystem::ShowInfoDialog
static void ShowInfoDialog(wxWindow *parent, const TranslatableString &dlogTitle, const TranslatableString &shortMsg, const wxString &message, const int xSize, const int ySize)
Displays cuttable information in a text ctrl, with an OK button.
Definition: HelpSystem.cpp:90
Track::GetEndTime
virtual double GetEndTime() const =0
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: TranslatableString.h:295
SelectedRegion::t1
double t1() const
Definition: SelectedRegion.h:95
ExportMultipleDialog::MakeFileName
wxString MakeFileName(const wxString &input)
Takes an arbitrary text string and converts it to a form that can be used as a file name,...
Definition: ExportMultiple.cpp:1145
eHelpButton
@ eHelpButton
Definition: ShuttleGui.h:604
ExportMultipleDialog::~ExportMultipleDialog
virtual ~ExportMultipleDialog()
Definition: ExportMultiple.cpp:164
SelectedRegion::isPoint
bool isPoint() const
Definition: SelectedRegion.h:97
FileNames::UpdateDefaultPath
AUDACITY_DLL_API void UpdateDefaultPath(Operation op, const FilePath &path)
ExportMultipleDialog::mFirst
wxCheckBox * mFirst
Definition: ExportMultiple.h:142
ExportMultipleDialog::CountTracksAndLabels
void CountTracksAndLabels()
Definition: ExportMultiple.cpp:168
Tags
ID3 Tags (for MP3)
Definition: Tags.h:74
CreateID
@ CreateID
Definition: ExportMultiple.cpp:85
ExportMultipleDialog::ShowModal
int ShowModal()
Definition: ExportMultiple.cpp:181
ExportMultipleDialog::mDir
wxTextCtrl * mDir
Definition: ExportMultiple.h:134
ShuttleGuiBase::TieCheckBox
wxCheckBox * TieCheckBox(const TranslatableString &Prompt, bool &Var)
Definition: ShuttleGui.cpp:1629
AudacityTextEntryDialog
Wrap wxTextEntryDialog so that caption IS translatable.
Definition: AudacityTextEntryDialog.h:23
ExportMultipleDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: ExportMultiple.cpp:224
TrackList::Channels
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1468
Format
Abstract base class used in importing a file.
TAG_TRACK
#define TAG_TRACK
Definition: Tags.h:63
TrackList
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1264
ShuttleGuiBase::AddRadioButtonToGroup
wxRadioButton * AddRadioButtonToGroup(const TranslatableString &Prompt, int selector=1, int initValue=0)
Definition: ShuttleGui.cpp:574
BasicUI::ProgressResult
ProgressResult
Definition: BasicUI.h:145
SelectionStateChanger
Definition: SelectionState.h:56
ExportMultipleDialog::mPlugins
std::vector< ExportPlugin * > mPlugins
Definition: ExportMultiple.h:108
wxDirDialogWrapper
Definition: wxPanelWrapper.h:126
ExportMultipleDialog::OnChoose
void OnChoose(wxCommandEvent &event)
Definition: ExportMultiple.cpp:526
ExportMultipleDialog::DoExport
ProgressResult DoExport(std::unique_ptr< ProgressDialog > &pDialog, unsigned channels, const wxFileName &name, bool selectedOnly, double t0, double t1, const Tags &tags)
Definition: ExportMultiple.cpp:1059
ExportMultipleDialog::mTracks
TrackList * mTracks
Definition: ExportMultiple.h:111
RefreshCode::Cancelled
@ Cancelled
Definition: RefreshCode.h:23
XO
#define XO(s)
Definition: Internat.h:31
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:40
LabelTrack
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:88
ShuttleGuiBase::EndMultiColumn
void EndMultiColumn()
Definition: ShuttleGui.cpp:1238
ByNameID
@ ByNameID
Definition: ExportMultiple.cpp:92
ShuttleGuiBase::StartNotebookPage
wxNotebookPage * StartNotebookPage(const TranslatableString &Name)
Definition: ShuttleGui.cpp:1068
ExportMultipleDialog::mPluginIndex
int mPluginIndex
Definition: ExportMultiple.h:121
ShuttleGuiBase::EndNotebookPage
void EndNotebookPage()
Definition: ShuttleGui.cpp:1091
ShuttleGuiBase::StartPanel
wxPanel * StartPanel(int iStyle=0)
Definition: ShuttleGui.cpp:990
LabelStruct
A LabelStruct holds information for ONE label in a LabelTrack.
Definition: LabelTrack.h:30
HelpSystem::ShowHelp
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:237
wxArrayStringEx
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Definition: wxArrayStringEx.h:18
ShuttleGuiBase::EndPanel
void EndPanel()
Definition: ShuttleGui.cpp:1018
AudacityMessageDialog
Wrap wxMessageDialog so that caption IS translatable.
Definition: wxPanelWrapper.h:215
ExportMultipleDialog::OnCreate
void OnCreate(wxCommandEvent &event)
Definition: ExportMultiple.cpp:506
anonymous_namespace{ExportMultiple.cpp}::ExportKit
A private class used to store the information needed to do an export.
Definition: ExportMultiple.cpp:64
Tags::Get
static Tags & Get(AudacityProject &project)
Definition: Tags.cpp:237
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2274
Export
Main class to control the export function.
ExportMultipleDialog::DirOk
bool DirOk()
Definition: ExportMultiple.cpp:669
ExportMultipleDialog::mFilterIndex
int mFilterIndex
Definition: ExportMultiple.h:117
anonymous_namespace{ExportMultiple.cpp}::ExportKit::t1
double t1
Definition: ExportMultiple.cpp:69
TrackList::GetEndTime
double GetEndTime() const
Definition: Track.cpp:1026
ExportMultipleDialog::mSelectionState
SelectionState & mSelectionState
Definition: ExportMultiple.h:164
ShuttleGui::Style
ShuttleGui & Style(long iStyle)
Definition: ShuttleGui.h:727
ExportMultipleDialog::mSubFormatIndex
int mSubFormatIndex
Definition: ExportMultiple.h:123
Track::GetStartTime
virtual double GetStartTime() const =0
anonymous_namespace{ExportMultiple.cpp}::ExportKit::channels
unsigned channels
Definition: ExportMultiple.cpp:70
ExportMultipleDialog::mFirstFileName
wxTextCtrl * mFirstFileName
Definition: ExportMultiple.h:144
XXO
#define XXO(s)
Definition: Internat.h:44
eCancelButton
@ eCancelButton
Definition: ShuttleGui.h:601
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1177
ExportMultipleDialog::mNumLabels
int mNumLabels
Definition: ExportMultiple.h:114
OptionsID
@ OptionsID
Definition: ExportMultiple.cpp:83
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1167
LabelStruct::selectedRegion
SelectedRegion selectedRegion
Definition: LabelTrack.h:70
OverwriteID
@ OverwriteID
Definition: ExportMultiple.cpp:95
ShuttleGuiBase::AddTextBox
wxTextCtrl * AddTextBox(const TranslatableString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:638
ShuttleGuiBase::StartMultiColumn
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:1229
ByNameAndNumberID
@ ByNameAndNumberID
Definition: ExportMultiple.cpp:91
ShuttleGuiBase::StartSimplebook
wxSimplebook * StartSimplebook()
Definition: ShuttleGui.cpp:1047
ExportMultipleDialog::ExportMultipleByTrack
ProgressResult ExportMultipleByTrack(bool byName, const wxString &prefix, bool addNumber)
Export each track in the project to a separate file.
Definition: ExportMultiple.cpp:903
GetProjectFrame
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
Definition: Project.cpp:188
PrefixID
@ PrefixID
Definition: ExportMultiple.cpp:94
ByNumberID
@ ByNumberID
Definition: ExportMultiple.cpp:93
Track::MonoChannel
static const auto MonoChannel
Definition: Track.h:268
ExportMultipleDialog::mPrefix
wxTextCtrl * mPrefix
Definition: ExportMultiple.h:155
name
const TranslatableString name
Definition: Distortion.cpp:98
format
int format
Definition: ExportPCM.cpp:56
ExportMultipleDialog::mByName
wxRadioButton * mByName
Definition: ExportMultiple.h:151
ExportMultipleDialog::mInitialized
bool mInitialized
Definition: ExportMultiple.h:125
Track::LeftChannel
static const auto LeftChannel
Definition: Track.h:266
ExportMultipleDialog::ExportMultipleByLabel
ProgressResult ExportMultipleByLabel(bool byName, const wxString &prefix, bool addNumber)
Export multiple labeled regions of the project to separate files.
Definition: ExportMultiple.cpp:749
ExportMultipleDialog::OnByName
void OnByName(wxCommandEvent &event)
Definition: ExportMultiple.cpp:556
ShuttleGuiBase::AddRadioButton
wxRadioButton * AddRadioButton(const TranslatableString &Prompt, int selector=0, int initValue=0)
Definition: ShuttleGui.cpp:568
ExportMultipleDialog::mBook
wxSimplebook * mBook
Definition: ExportMultiple.h:162
PlayableTrack::GetNotSolo
bool GetNotSolo() const
Definition: Track.h:847
anonymous_namespace{ExportMultiple.cpp}::ExportKit::t0
double t0
Definition: ExportMultiple.cpp:68
MouseEvtHandler
Definition: ExportMultiple.h:183
ExportMultipleDialog::OnCancel
void OnCancel(wxCommandEvent &event)
Definition: ExportMultiple.cpp:571
title
static const auto title
Definition: UpdateNoticeDialog.cpp:23
ShuttleGui::Prop
ShuttleGui & Prop(int iProp)
Definition: ShuttleGui.h:725
DirID
@ DirID
Definition: ExportMultiple.cpp:84
FileNames::MakeNameUnique
AUDACITY_DLL_API void MakeNameUnique(FilePaths &otherNames, wxFileName &newName)
ShuttleGuiBase::AddButton
wxButton * AddButton(const TranslatableString &Text, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:360
anonymous_namespace{ExportMultiple.cpp}::ExportKit::filetags
Tags filetags
Definition: ExportMultiple.cpp:66
anonymous_namespace{ExportMultiple.cpp}::ExportKit::destfile
wxFileNameWrapper destfile
Definition: ExportMultiple.cpp:67
SelectionState::Get
static SelectionState & Get(AudacityProject &project)
Definition: SelectionState.cpp:20
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:893
eIsSavingToPrefs
@ eIsSavingToPrefs
Definition: ShuttleGui.h:48
ExportMultipleDialog::mByNumberAndName
wxRadioButton * mByNumberAndName
Definition: ExportMultiple.h:150
ExportMultipleDialog::mFormat
wxChoice * mFormat
Definition: ExportMultiple.h:130
ExportMultipleDialog
Presents a dialog box allowing the user to export multiple files either by exporting each track as a ...
Definition: ExportMultiple.h:33
ShuttleGui::Name
ShuttleGui & Name(const TranslatableString &name)
Definition: ShuttleGui.h:663
SuccessDialog::OnKeyDown
void OnKeyDown(wxListEvent &event)
Definition: ExportMultiple.cpp:1189
wxDialogWrapper
Definition: wxPanelWrapper.h:81
SelectedRegion::t0
double t0() const
Definition: SelectedRegion.h:94
LabelTrack::GetNumLabels
int GetNumLabels() const
Definition: LabelTrack.cpp:921
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
eOkButton
@ eOkButton
Definition: ShuttleGui.h:600
SuccessDialog
Definition: ExportMultiple.h:171
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:495
TrackList::Leaders
auto Leaders() -> TrackIterRange< TrackType >
Definition: Track.h:1389
ExportMultipleDialog::mOverwrite
wxCheckBox * mOverwrite
Definition: ExportMultiple.h:157
ExportMultipleDialog::OnFirst
void OnFirst(wxCommandEvent &event)
Definition: ExportMultiple.cpp:541
_
#define _(s)
Definition: Internat.h:75
FirstFileNameID
@ FirstFileNameID
Definition: ExportMultiple.cpp:89
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:113
Internat::GetExcludedCharacters
static const wxArrayString & GetExcludedCharacters()
Definition: Internat.h:149
ExportMultiple.h
ExportMultipleDialog::mExport
wxButton * mExport
Definition: ExportMultiple.h:160
ExportMultipleDialog::OnExport
void OnExport(wxCommandEvent &event)
Definition: ExportMultiple.cpp:581
ProjectWindow::Find
static ProjectWindow * Find(AudacityProject *pProject)
Definition: ProjectWindow.cpp:543
ExportMultipleDialog::OnFormat
void OnFormat(wxCommandEvent &event)
Definition: ExportMultiple.cpp:475
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
ChooseID
@ ChooseID
Definition: ExportMultiple.cpp:86
ExportMultipleDialog::OnPrefix
void OnPrefix(wxCommandEvent &event)
Definition: ExportMultiple.cpp:566
EVT_LIST_ITEM_ACTIVATED
EVT_LIST_ITEM_ACTIVATED(wxID_ANY, SuccessDialog::OnItemActivated) ExportMultipleDialog
Definition: ExportMultiple.cpp:122
LabelTrack::GetLabel
const LabelStruct * GetLabel(int index) const
Definition: LabelTrack.cpp:926
ExportMultipleDialog::OnHelp
void OnHelp(wxCommandEvent &event)
Definition: ExportMultiple.cpp:576
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2432
ShuttleGui::GetMode
teShuttleMode GetMode()
Definition: ShuttleGui.h:752
ShuttleGuiBase::TieRadioButton
wxRadioButton * TieRadioButton()
This function must be within a StartRadioButtonGroup - EndRadioButtonGroup pair.
Definition: ShuttleGui.cpp:1536
Prefs.h
ShuttleGuiBase::AddPrompt
void AddPrompt(const TranslatableString &Prompt, int wrapWidth=0)
Right aligned text string.
Definition: ShuttleGui.cpp:238
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:489
ByColumns
ByColumns_t ByColumns
Definition: Prefs.cpp:414
TrackList::Any
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1355
FileNames::FindDefaultPath
AUDACITY_DLL_API FilePath FindDefaultPath(Operation op)
eIsCreatingFromPrefs
@ eIsCreatingFromPrefs
Definition: ShuttleGui.h:47
ShuttleGuiBase::AddVariableText
wxStaticText * AddVariableText(const TranslatableString &Str, bool bCenter=false, int PositionFlags=0, int wrapWidth=0)
Definition: ShuttleGui.cpp:463
SuccessDialog::OnItemActivated
void OnItemActivated(wxListEvent &event)
Definition: ExportMultiple.cpp:1197
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:922
ExportMultipleDialog::OnOptions
void OnOptions(wxCommandEvent &event)
Definition: ExportMultiple.cpp:482
settings
static Settings & settings()
Definition: TrackInfo.cpp:86
ExportMultipleDialog::mNumWaveTracks
int mNumWaveTracks
Definition: ExportMultiple.h:115
ExportMultipleDialog::OnTrack
void OnTrack(wxCommandEvent &event)
Definition: ExportMultiple.cpp:551
LabelID
@ LabelID
Definition: ExportMultiple.cpp:87
ShuttleGuiBase::SetStretchyCol
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:202
FirstID
@ FirstID
Definition: ExportMultiple.cpp:88
ExportMultipleDialog::OnByNumber
void OnByNumber(wxCommandEvent &event)
Definition: ExportMultiple.cpp:561
TrackList::Selected
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1372
AudacityProject::GetProjectName
const wxString & GetProjectName() const
Definition: Project.cpp:165
END_EVENT_TABLE
END_EVENT_TABLE()
ShuttleGuiBase::TieChoice
wxChoice * TieChoice(const TranslatableString &Prompt, TranslatableString &Selected, const TranslatableStrings &choices)
Definition: ShuttleGui.cpp:1727
Internat::SanitiseFilename
static bool SanitiseFilename(wxString &name, const wxString &sub)
Check a proposed file name string for illegal characters and remove them return true iff name is "vis...
Definition: Internat.cpp:239
TAG_TITLE
#define TAG_TITLE
Definition: Tags.h:60
ExportMultipleDialog::mLabels
const LabelTrack * mLabels
Definition: ExportMultiple.h:113
FormatID
@ FormatID
Definition: ExportMultiple.cpp:82
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
ExportMultipleDialog::mByNumber
wxRadioButton * mByNumber
Definition: ExportMultiple.h:152
GetNumExportChannels
static unsigned GetNumExportChannels(const TrackList &tracks)
Definition: ExportMultiple.cpp:693