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