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