Audacity  3.0.3
Export.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Export.cpp
6 
7  Dominic Mazzoni
8 
9 *******************************************************************//****************************************************************//****************************************************************//****************************************************************//********************************************************************/
30 
31 
32 #include "Export.h"
33 
34 #include <wx/bmpbuttn.h>
35 #include <wx/dcclient.h>
36 #include <wx/file.h>
37 #include <wx/filectrl.h>
38 #include <wx/filename.h>
39 #include <wx/simplebook.h>
40 #include <wx/sizer.h>
41 #include <wx/slider.h>
42 #include <wx/statbox.h>
43 #include <wx/stattext.h>
44 #include <wx/string.h>
45 #include <wx/textctrl.h>
46 #include <wx/timer.h>
47 #include <wx/dcmemory.h>
48 #include <wx/window.h>
49 
50 #include "sndfile.h"
51 
53 
54 #include "AllThemeResources.h"
55 #include "BasicUI.h"
56 #include "Mix.h"
57 #include "Prefs.h"
58 #include "../prefs/ImportExportPrefs.h"
59 #include "Project.h"
60 #include "../ProjectHistory.h"
61 #include "../ProjectSettings.h"
62 #include "../ProjectWindow.h"
63 #include "../ProjectWindows.h"
64 #include "../ShuttleGui.h"
65 #include "../Tags.h"
66 #include "Theme.h"
67 #include "../WaveTrack.h"
68 #include "../widgets/AudacityMessageBox.h"
69 #include "../widgets/Warning.h"
70 #include "../widgets/HelpSystem.h"
71 #include "AColor.h"
72 #include "FileNames.h"
73 #include "widgets/HelpSystem.h"
74 #include "widgets/ProgressDialog.h"
75 #include "wxFileNameWrapper.h"
76 
77 //----------------------------------------------------------------------------
78 // ExportPlugin
79 //----------------------------------------------------------------------------
80 
82 {
83 }
84 
86 {
87 }
88 
89 bool ExportPlugin::CheckFileName(wxFileName & WXUNUSED(filename), int WXUNUSED(format))
90 {
91  return true;
92 }
93 
102 {
103  FormatInfo nf;
104  mFormatInfos.push_back(nf);
105  return mFormatInfos.size();
106 }
107 
109 {
110  return mFormatInfos.size();
111 }
112 
117 void ExportPlugin::SetFormat(const wxString & format, int index)
118 {
119  mFormatInfos[index].mFormat = format;
120 }
121 
122 void ExportPlugin::SetDescription(const TranslatableString & description, int index)
123 {
124  mFormatInfos[index].mDescription = description;
125 }
126 
127 void ExportPlugin::AddExtension(const FileExtension &extension, int index)
128 {
129  mFormatInfos[index].mExtensions.push_back(extension);
130 }
131 
132 void ExportPlugin::SetExtensions(FileExtensions extensions, int index)
133 {
134  mFormatInfos[index].mExtensions = std::move(extensions);
135 }
136 
138 {
139  mFormatInfos[index].mMask = std::move( mask );
140 }
141 
142 void ExportPlugin::SetMaxChannels(unsigned maxchannels, unsigned index)
143 {
144  mFormatInfos[index].mMaxChannels = maxchannels;
145 }
146 
147 void ExportPlugin::SetCanMetaData(bool canmetadata, int index)
148 {
149  mFormatInfos[index].mCanMetaData = canmetadata;
150 }
151 
152 wxString ExportPlugin::GetFormat(int index)
153 {
154  return mFormatInfos[index].mFormat;
155 }
156 
158 {
159  return mFormatInfos[index].mDescription;
160 }
161 
163 {
164  return mFormatInfos[index].mExtensions[0];
165 }
166 
168 {
169  return mFormatInfos[index].mExtensions;
170 }
171 
173 {
174  if (!mFormatInfos[index].mMask.empty())
175  return mFormatInfos[index].mMask;
176 
177  return { { GetDescription(index), GetExtensions(index) } };
178 }
179 
180 unsigned ExportPlugin::GetMaxChannels(int index)
181 {
182  return mFormatInfos[index].mMaxChannels;
183 }
184 
186 {
187  return mFormatInfos[index].mCanMetaData;
188 }
189 
190 bool ExportPlugin::IsExtension(const FileExtension & ext, int index)
191 {
192  bool isext = false;
193  for (int i = index; i < GetFormatCount(); i = GetFormatCount())
194  {
195  const auto &defext = GetExtension(i);
196  const auto &defexts = GetExtensions(i);
197  int indofext = defexts.Index(ext, false);
198  if (defext.empty() || (indofext != wxNOT_FOUND))
199  isext = true;
200  }
201  return isext;
202 }
203 
204 bool ExportPlugin::DisplayOptions(wxWindow * WXUNUSED(parent), int WXUNUSED(format))
205 {
206  return false;
207 }
208 
210 {
211  S.StartHorizontalLay(wxCENTER);
212  {
213  S.StartHorizontalLay(wxCENTER, 0);
214  {
215  S.Prop(1).AddTitle(XO("No format specific options"));
216  }
217  S.EndHorizontalLay();
218  }
219  S.EndHorizontalLay();
220 }
221 
222 //Create a mixer by computing the time warp factor
223 std::unique_ptr<Mixer> ExportPlugin::CreateMixer(const TrackList &tracks,
224  bool selectionOnly,
225  double startTime, double stopTime,
226  unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
227  double outRate, sampleFormat outFormat,
228  MixerSpec *mixerSpec)
229 {
230  WaveTrackConstArray inputTracks;
231 
232  bool anySolo = !(( tracks.Any<const WaveTrack>() + &WaveTrack::GetSolo ).empty());
233 
234  auto range = tracks.Any< const WaveTrack >()
235  + (selectionOnly ? &Track::IsSelected : &Track::Any )
236  - ( anySolo ? &WaveTrack::GetNotSolo : &WaveTrack::GetMute);
237  for (auto pTrack: range)
238  inputTracks.push_back(
239  pTrack->SharedPointer< const WaveTrack >() );
240  // MB: the stop time should not be warped, this was a bug.
241  return std::make_unique<Mixer>(inputTracks,
242  // Throw, to stop exporting, if read fails:
243  true,
244  Mixer::WarpOptions{tracks},
245  startTime, stopTime,
246  numOutChannels, outBufferSize, outInterleaved,
247  outRate, outFormat,
248  true, mixerSpec);
249 }
250 
251 void ExportPlugin::InitProgress(std::unique_ptr<ProgressDialog> &pDialog,
252  const TranslatableString &title, const TranslatableString &message)
253 {
254  if (!pDialog)
255  pDialog = std::make_unique<ProgressDialog>( title, message );
256  else {
257  pDialog->SetTitle( title );
258  pDialog->SetMessage( message );
259  pDialog->Reinit();
260  }
261 }
262 
263 void ExportPlugin::InitProgress(std::unique_ptr<ProgressDialog> &pDialog,
264  const wxFileNameWrapper &title, const TranslatableString &message)
265 {
266  return InitProgress(
267  pDialog, Verbatim( title.GetName() ), message );
268 }
269 
270 //----------------------------------------------------------------------------
271 // Export
272 //----------------------------------------------------------------------------
273 
274 
275 wxDEFINE_EVENT(AUDACITY_FILE_SUFFIX_EVENT, wxCommandEvent);
276 
277 BEGIN_EVENT_TABLE(Exporter, wxEvtHandler)
278  EVT_FILECTRL_FILTERCHANGED(wxID_ANY, Exporter::OnFilterChanged)
279  EVT_BUTTON(wxID_HELP, Exporter::OnHelp)
280  EVT_COMMAND(wxID_ANY, AUDACITY_FILE_SUFFIX_EVENT, Exporter::OnExtensionChanged)
282 
283 namespace {
284 const auto PathStart = wxT("Exporters");
285 
287 {
288  static Registry::TransparentGroupItem<> registry{ PathStart };
289  return registry;
290 }
291 
295  : SingleItem{ id }
296  , mFactory{ factory }
297  {}
298 
300 };
301 
302  using ExportPluginFactories = std::vector< Exporter::ExportPluginFactory >;
304  {
305  static ExportPluginFactories theList;
306  return theList;
307  }
308 }
309 
311  const Identifier &id,
313  const Registry::Placement &placement )
314 {
315  if ( factory )
316  Registry::RegisterItem( sRegistry(), placement,
317  std::make_unique< ExporterItem >( id, factory ) );
318 }
319 
321 : mProject{ &project }
322 {
323  using namespace Registry;
324  static OrderingPreferenceInitializer init{
325  PathStart,
326  { {wxT(""), wxT("PCM,MP3,OGG,FLAC,MP2,CommandLine,FFmpeg") } },
327  };
328 
329  mMixerSpec = NULL;
330  mBook = NULL;
331 
332  // build the list of export plugins.
333  for ( const auto &factory : sFactories() )
334  mPlugins.emplace_back( factory() );
335 
336  struct MyVisitor final : Visitor {
337  MyVisitor()
338  {
339  // visit the registry to collect the plug-ins properly
340  // sorted
342  Registry::Visit( *this, &top, &sRegistry() );
343  }
344 
345  void Visit( SingleItem &item, const Path &path ) override
346  {
347  mPlugins.emplace_back(
348  static_cast<ExporterItem&>( item ).mFactory() );
349  }
350 
351  ExportPluginArray mPlugins;
352  } visitor;
353 
354  mPlugins.swap( visitor.mPlugins );
355 
356  SetFileDialogTitle( XO("Export Audio") );
357 }
358 
360 {
361 }
362 
363 void Exporter::OnExtensionChanged(wxCommandEvent &evt)
364 {
365  mDialog->SetFileExtension(evt.GetString().BeforeFirst(' ').Lower());
366 }
367 
368 void Exporter::OnHelp(wxCommandEvent& WXUNUSED(evt))
369 {
370  wxWindow * pWin = FindProjectFrame( mProject );
371  HelpSystem::ShowHelp(pWin, L"File_Export_Dialog", true);
372 }
373 
375 {
376  // The default title is "Export File"
377  mFileDialogTitle = DialogTitle;
378 }
379 
380 int Exporter::FindFormatIndex(int exportindex)
381 {
382  int c = 0;
383  for (const auto &pPlugin : mPlugins)
384  {
385  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
386  {
387  if (exportindex == c) return j;
388  c++;
389  }
390  }
391  return 0;
392 }
393 
395 {
396  return mPlugins;
397 }
398 
400  const TranslatableString &title,
401  const TranslatableString &shortUndoDescription, bool force)
402 {
403  auto &settings = ProjectSettings::Get( project );
404  auto &tags = Tags::Get( project );
405 
406  // Back up my tags
407  // Tags (artist name, song properties, MP3 ID3 info, etc.)
408  // The structure may be shared with undo history entries
409  // To keep undo working correctly, always replace this with a NEW duplicate
410  // BEFORE doing any editing of it!
411  auto newTags = tags.Duplicate();
412 
413  if (newTags->ShowEditDialog(&GetProjectFrame( project ), title, force)) {
414  if (tags != *newTags) {
415  // Commit the change to project state only now.
416  Tags::Set( project, newTags );
417  ProjectHistory::Get( project ).PushState( title, shortUndoDescription);
418  }
419  bool bShowInFuture;
420  gPrefs->Read(wxT("/AudioFiles/ShowId3Dialog"), &bShowInFuture, true);
421  settings.SetShowId3Dialog( bShowInFuture );
422  return true;
423  }
424 
425  return false;
426 }
427 
428 bool Exporter::Process(bool selectedOnly, double t0, double t1)
429 {
430  // Save parms
431  mSelectedOnly = selectedOnly;
432  mT0 = t0;
433  mT1 = t1;
434 
435  // Gather track information
436  if (!ExamineTracks()) {
437  return false;
438  }
439 
440  // Ask user for file name
441  if (!GetFilename()) {
442  return false;
443  }
444 
445  // Check for down mixing
446  if (!CheckMix()) {
447  return false;
448  }
449 
450  // Let user edit MetaData
451  if (mPlugins[mFormat]->GetCanMetaData(mSubFormat)) {
452  if (!DoEditMetadata( *mProject,
453  XO("Edit Metadata Tags"), XO("Exported Tags"),
454  ProjectSettings::Get( *mProject ).GetShowId3Dialog())) {
455  return false;
456  }
457  }
458 
459  // Ensure filename doesn't interfere with project files.
460  if (!CheckFilename()) {
461  return false;
462  }
463 
464  // Export the tracks
465  bool success = ExportTracks();
466 
467  // Get rid of mixerspec
468  mMixerSpec.reset();
469 
470  if (success) {
471  if (mFormatName.empty()) {
472  gPrefs->Write(wxT("/Export/Format"), mPlugins[mFormat]->GetFormat(mSubFormat));
473  }
474 
475  FileNames::UpdateDefaultPath(FileNames::Operation::Export, mFilename.GetPath());
476  }
477 
478  return success;
479 }
480 
481 bool Exporter::Process(unsigned numChannels,
482  const FileExtension &type, const wxString & filename,
483  bool selectedOnly, double t0, double t1)
484 {
485  // Save parms
486  mChannels = numChannels;
487  mFilename = filename;
488  mSelectedOnly = selectedOnly;
489  mT0 = t0;
490  mT1 = t1;
492 
493  int i = -1;
494  for (const auto &pPlugin : mPlugins) {
495  ++i;
496  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
497  {
498  if (pPlugin->GetFormat(j).IsSameAs(type, false))
499  {
500  mFormat = i;
501  mSubFormat = j;
502  return CheckFilename() && ExportTracks();
503  }
504  }
505  }
506 
507  return false;
508 }
509 
511 {
512  // Init
513  mNumSelected = 0;
514  mNumLeft = 0;
515  mNumRight = 0;
516  mNumMono = 0;
517 
518  // First analyze the selected audio, perform sanity checks, and provide
519  // information as appropriate.
520 
521  // Tally how many are right, left, mono, and make sure at
522  // least one track is selected (if selectedOnly==true)
523 
524  double earliestBegin = mT1;
525  double latestEnd = mT0;
526 
527  auto &tracks = TrackList::Get( *mProject );
528 
529  bool anySolo = !(( tracks.Any<const WaveTrack>() + &WaveTrack::GetSolo ).empty());
530 
531  for (auto tr :
532  tracks.Any< const WaveTrack >()
534  - ( anySolo ? &WaveTrack::GetNotSolo : &WaveTrack::GetMute)
535  ) {
536  mNumSelected++;
537 
538  if (tr->GetChannel() == Track::LeftChannel) {
539  mNumLeft++;
540  }
541  else if (tr->GetChannel() == Track::RightChannel) {
542  mNumRight++;
543  }
544  else if (tr->GetChannel() == Track::MonoChannel) {
545  // It's a mono channel, but it may be panned
546  float pan = tr->GetPan();
547 
548  if (pan == -1.0)
549  mNumLeft++;
550  else if (pan == 1.0)
551  mNumRight++;
552  else if (pan == 0)
553  mNumMono++;
554  else {
555  // Panned partially off-center. Mix as stereo.
556  mNumLeft++;
557  mNumRight++;
558  }
559  }
560 
561  if (tr->GetOffset() < earliestBegin) {
562  earliestBegin = tr->GetOffset();
563  }
564 
565  if (tr->GetEndTime() > latestEnd) {
566  latestEnd = tr->GetEndTime();
567  }
568  }
569 
570  if (mNumSelected == 0) {
571  TranslatableString message;
572  if(mSelectedOnly)
573  message = XO("All selected audio is muted.");
574  else
575  message = XO("All audio is muted.");
577  ":576",
578  message);
579  return false;
580  }
581 
582  // The skipping of silent space could be cleverer and take
583  // into account clips.
584  // As implemented now, it can only skip initial silent space that
585  // has no clip before it, and terminal silent space that has no clip
586  // after it.
587  if (mT0 < earliestBegin){
588  // Bug 1904
589  // Previously we always skipped initial silent space.
590  // Now skipping it is an opt-in option.
591  bool skipSilenceAtBeginning;
592  gPrefs->Read(wxT("/AudioFiles/SkipSilenceAtBeginning"),
593  &skipSilenceAtBeginning, false);
594  if (skipSilenceAtBeginning)
595  mT0 = earliestBegin;
596  }
597 
598  // We still skip silent space at the end
599  if (mT1 > latestEnd)
600  mT1 = latestEnd;
601 
602  return true;
603 }
604 
606 {
607  mFormat = -1;
608 
609  FileNames::FileTypes fileTypes;
610  auto defaultFormat = mFormatName;
611  if( defaultFormat.empty() )
612  defaultFormat = gPrefs->Read(wxT("/Export/Format"),
613  wxT("WAV"));
614 
615  mFilterIndex = 0;
616 
617  {
618  int i = -1;
619  for (const auto &pPlugin : mPlugins) {
620  ++i;
621  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
622  {
623  auto mask = pPlugin->GetMask(j);
624  fileTypes.insert( fileTypes.end(), mask.begin(), mask.end() );
625  if (mPlugins[i]->GetFormat(j) == defaultFormat) {
626  mFormat = i;
627  mSubFormat = j;
628  }
629  if (mFormat == -1) mFilterIndex++;
630  }
631  }
632  }
633  if (mFormat == -1)
634  {
635  mFormat = 0;
636  mFilterIndex = 0;
637  mSubFormat = 0;
638  }
639  wxString defext = mPlugins[mFormat]->GetExtension(mSubFormat).Lower();
640 
641  //Bug 1304: Set a default path if none was given. For Export.
642  mFilename.SetPath(FileNames::FindDefaultPath(FileNames::Operation::Export));
643  mFilename.SetName(mProject->GetProjectName());
644  if (mFilename.GetName().empty())
645  mFilename.SetName(_("untitled"));
646  while (true) {
647  // Must reset each iteration
648  mBook = NULL;
649 
650  {
651  auto useFileName = mFilename;
652  if (!useFileName.HasExt())
653  useFileName.SetExt(defext);
656  mFilename.GetPath(),
657  useFileName.GetFullName(),
658  fileTypes,
659  wxFD_SAVE | wxRESIZE_BORDER);
660  mDialog = &fd;
661  mDialog->PushEventHandler(this);
662 
663  fd.SetUserPaneCreator(CreateUserPaneCallback, (wxUIntPtr) this);
665 
666  int result = fd.ShowModal();
667 
668  mDialog->PopEventHandler();
669 
670  if (result == wxID_CANCEL) {
671  return false;
672  }
673 
674  mFilename = fd.GetPath();
675  if (mFilename == wxT("")) {
676  return false;
677  }
678 
679  mFormat = fd.GetFilterIndex();
681  }
682 
683  {
684  int c = 0;
685  int i = -1;
686  for (const auto &pPlugin : mPlugins)
687  {
688  ++i;
689  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
690  {
691  if (mFilterIndex == c)
692  {
693  mFormat = i;
694  mSubFormat = j;
695  }
696  c++;
697  }
698  }
699  }
700 
701  const auto ext = mFilename.GetExt();
702  defext = mPlugins[mFormat]->GetExtension(mSubFormat).Lower();
703 
704  //
705  // Check the extension - add the default if it's not there,
706  // and warn user if it's abnormal.
707  //
708  if (ext.empty()) {
709  //
710  // Make sure the user doesn't accidentally save the file
711  // as an extension with no name, like just plain ".wav".
712  //
713  if (mFilename.GetName().Left(1) == wxT(".")) {
714  auto prompt =
715  XO("Are you sure you want to export the file as \"%s\"?\n")
716  .Format( mFilename.GetFullName() );
717 
718  int action = AudacityMessageBox(
719  prompt,
720  XO("Warning"),
721  wxYES_NO | wxICON_EXCLAMATION);
722  if (action != wxYES) {
723  continue;
724  }
725  }
726 
727  mFilename.SetExt(defext);
728  }
729 
730  if (!mPlugins[mFormat]->CheckFileName(mFilename, mSubFormat))
731  {
732  continue;
733  }
734  else if (!ext.empty() && !mPlugins[mFormat]->IsExtension(ext,mSubFormat) && ext.CmpNoCase(defext)) {
735  auto prompt = XO("You are about to export a %s file with the name \"%s\".\n\nNormally these files end in \".%s\", and some programs will not open files with nonstandard extensions.\n\nAre you sure you want to export the file under this name?")
736  .Format(mPlugins[mFormat]->GetFormat(mSubFormat),
737  mFilename.GetFullName(),
738  defext);
739 
740  int action = AudacityMessageBox(
741  prompt,
742  XO("Warning"),
743  wxYES_NO | wxICON_EXCLAMATION);
744  if (action != wxYES) {
745  continue;
746  }
747  }
748 
749  if (mFilename.GetFullPath().length() >= 256) {
751  XO( "Sorry, pathnames longer than 256 characters not supported.") );
752  continue;
753  }
754 
755 // For Mac, it's handled by the FileDialog
756 #if !defined(__WXMAC__)
757  if (mFilename.FileExists()) {
758  auto prompt = XO("A file named \"%s\" already exists. Replace?")
759  .Format( mFilename.GetFullPath() );
760 
761  int action = AudacityMessageBox(
762  prompt,
763  XO("Warning"),
764  wxYES_NO | wxICON_EXCLAMATION);
765  if (action != wxYES) {
766  continue;
767  }
768  }
769 #endif
770 
771  break;
772  }
773 
774  return true;
775 }
776 
777 //
778 // For safety, if the file already exists it stores the filename
779 // the user wants in actualName, and returns a temporary file name.
780 // The calling function should rename the file when it's successfully
781 // exported.
782 //
784 {
785  //
786  // To be even safer, return a temporary file name based
787  // on this one...
788  //
789 
791 
792  int suffix = 0;
793  while (mFilename.FileExists()) {
794  mFilename.SetName(mActualName.GetName() +
795  wxString::Format(wxT("%d"), suffix));
796  suffix++;
797  }
798 
799  return true;
800 }
801 
803 {
804  int c = 0;
805  int mf = -1, msf = -1;
806  int i = -1;
807  for (const auto &pPlugin : mPlugins)
808  {
809  ++i;
810  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
811  {
812  if (index == c)
813  {
814  mf = i;
815  msf = j;
816  }
817  c++;
818  }
819  }
820  // This shouldn't happen...
821  if (index >= c) {
822  return;
823  }
824 
825 #if defined(__WXMSW__)
826  mPlugins[mf]->DisplayOptions( FindProjectFrame( mProject ), msf);
827 #else
828  mPlugins[mf]->DisplayOptions(mDialog, msf);
829 #endif
830 }
831 
832 bool Exporter::CheckMix(bool prompt /*= true*/ )
833 {
834  // Clean up ... should never happen
835  mMixerSpec.reset();
836 
837  // Determine if exported file will be stereo or mono or multichannel,
838  // and if mixing will occur.
839 
841  int exportedChannels = mPlugins[mFormat]->SetNumExportChannels();
842 
843  if (downMix) {
844  if (mNumRight > 0 || mNumLeft > 0) {
845  mChannels = 2;
846  }
847  else {
848  mChannels = 1;
849  }
851  mPlugins[mFormat]->GetMaxChannels(mSubFormat));
852 
853  auto numLeft = mNumLeft + mNumMono;
854  auto numRight = mNumRight + mNumMono;
855 
856  if (numLeft > 1 || numRight > 1 || mNumLeft + mNumRight + mNumMono > mChannels) {
857  wxString exportFormat = mPlugins[mFormat]->GetFormat(mSubFormat);
858  if (exportFormat != wxT("CL") && exportFormat != wxT("FFMPEG") && exportedChannels == -1)
859  exportedChannels = mChannels;
860 
861  if (prompt) {
862  auto pWindow = ProjectWindow::Find(mProject);
863  if (exportedChannels == 1) {
864  if (ShowWarningDialog(pWindow,
865  wxT("MixMono"),
866  XO("Your tracks will be mixed down and exported as one mono file."),
867  true) == wxID_CANCEL)
868  return false;
869  }
870  else if (exportedChannels == 2) {
871  if (ShowWarningDialog(pWindow,
872  wxT("MixStereo"),
873  XO("Your tracks will be mixed down and exported as one stereo file."),
874  true) == wxID_CANCEL)
875  return false;
876  }
877  else {
878  if (ShowWarningDialog(pWindow,
879  wxT("MixUnknownChannels"),
880  XO("Your tracks will be mixed down to one exported file according to the encoder settings."),
881  true) == wxID_CANCEL)
882  return false;
883  }
884  }
885  }
886  }
887  else
888  {
889  if (exportedChannels < 0)
890  exportedChannels = mPlugins[mFormat]->GetMaxChannels(mSubFormat);
891 
894  exportedChannels,
895  NULL,
896  1,
897  XO("Advanced Mixing Options"));
898  if (prompt) {
899  if (md.ShowModal() != wxID_OK) {
900  return false;
901  }
902  }
903 
904  mMixerSpec = std::make_unique<MixerSpec>(*(md.GetMixerSpec()));
905  mChannels = mMixerSpec->GetNumChannels();
906  }
907 
908  return true;
909 }
910 
912 {
913  // Keep original in case of failure
914  if (mActualName != mFilename) {
915  ::wxRenameFile(mActualName.GetFullPath(), mFilename.GetFullPath());
916  }
917 
918  bool success = false;
919 
920  auto cleanup = finally( [&] {
921  if (mActualName != mFilename) {
922  // Remove backup
923  if ( success )
924  ::wxRemoveFile(mFilename.GetFullPath());
925  else {
926  // Restore original, if needed
927  ::wxRemoveFile(mActualName.GetFullPath());
928  ::wxRenameFile(mFilename.GetFullPath(), mActualName.GetFullPath());
929  }
930  // Restore filename
932  }
933  else {
934  if ( ! success )
935  // Remove any new, and only partially written, file.
936  ::wxRemoveFile(mFilename.GetFullPath());
937  }
938  } );
939 
940  std::unique_ptr<ProgressDialog> pDialog;
941  auto result = mPlugins[mFormat]->Export(mProject,
942  pDialog,
943  mChannels,
944  mActualName.GetFullPath(),
946  mT0,
947  mT1,
948  mMixerSpec.get(),
949  NULL,
950  mSubFormat);
951 
952  success =
953  result == ProgressResult::Success || result == ProgressResult::Stopped;
954 
955  return success;
956 }
957 
958 void Exporter::CreateUserPaneCallback(wxWindow *parent, wxUIntPtr userdata)
959 {
960  Exporter *self = (Exporter *) userdata;
961  if (self)
962  {
963  self->CreateUserPane(parent);
964  }
965 }
966 
967 void Exporter::CreateUserPane(wxWindow *parent)
968 {
969  ShuttleGui S(parent, eIsCreating);
970 
971  S.StartStatic(XO("Format Options"), 1);
972  {
973  S.StartHorizontalLay(wxEXPAND);
974  {
975  mBook = S.Position(wxEXPAND).StartSimplebook();
976  {
977  for (const auto &pPlugin : mPlugins)
978  {
979  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
980  {
981  // Name of simple book page is not displayed
982  S.StartNotebookPage( {} );
983  {
984  pPlugin->OptionsCreate(S, j);
985  }
986  S.EndNotebookPage();
987  }
988  }
989  }
990  S.EndSimplebook();
991 
992  auto b = safenew wxBitmapButton(S.GetParent(), wxID_HELP, theTheme.Bitmap( bmpHelpIcon ));
993  b->SetToolTip( XO("Help").Translation() );
994  b->SetLabel(XO("Help").Translation()); // for screen readers
995  S.Position(wxALIGN_BOTTOM | wxRIGHT | wxBOTTOM).AddWindow(b);
996  }
997  S.EndHorizontalLay();
998  }
999  S.EndStatic();
1000 
1001  return;
1002 }
1003 
1004 void Exporter::OnFilterChanged(wxFileCtrlEvent & evt)
1005 {
1006  int index = evt.GetFilterIndex();
1007 
1008  // On GTK, this event can fire before the userpane is created
1009  if (mBook == NULL || index < 0 || index >= (int) mBook->GetPageCount())
1010  {
1011  return;
1012  }
1013 
1014 #if defined(__WXGTK__)
1015  // On Windows and MacOS, changing the filter in the dialog
1016  // automatically changes the extension of the current file
1017  // name. GTK doesn't, so do it here.
1018  {
1019  FileNames::FileTypes fileTypes;
1020 
1021  int i = -1;
1022  for (const auto &pPlugin : mPlugins)
1023  {
1024  ++i;
1025  for (int j = 0; j < pPlugin->GetFormatCount(); j++)
1026  {
1027  auto mask = pPlugin->GetMask(j);
1028  fileTypes.insert( fileTypes.end(), mask.begin(), mask.end() );
1029  }
1030  }
1031 
1032  if (index < fileTypes.size())
1033  {
1034  mDialog->SetFileExtension(fileTypes[index].extensions[0].Lower());
1035  }
1036  }
1037 #endif
1038 
1039  mBook->ChangeSelection(index);
1040 }
1041 
1043  double t0,
1044  double t1,
1045  wxFileName fnFile,
1046  int iFormat,
1047  int iSubFormat,
1048  int iFilterIndex)
1049 {
1050  // Save parms
1051  mSelectedOnly = selectedOnly;
1052  mT0 = t0;
1053  mT1 = t1;
1054 
1055  // Auto Export Parameters
1056  mFilename = fnFile;
1057  mFormat = iFormat;
1058  mSubFormat = iSubFormat;
1059  mFilterIndex = iFilterIndex;
1060 
1061  // Gather track information
1062  if (!ExamineTracks()) {
1063  return false;
1064  }
1065 
1066  // Check for down mixing
1067  if (!CheckMix(false)) {
1068  return false;
1069  }
1070 
1071  // Ensure filename doesn't interfere with project files.
1072  if (!CheckFilename()) {
1073  return false;
1074  }
1075 
1076  // Export the tracks
1077  bool success = ExportTracks();
1078 
1079  // Get rid of mixerspec
1080  mMixerSpec.reset();
1081 
1082  return success;
1083 }
1084 
1086  return mFormat;
1087 }
1088 
1090  return mSubFormat;
1091 }
1092 
1094  return mFormat;
1095 }
1096 
1098  return mFilename;
1099 }
1100 
1102  mFormat = -1;
1103 
1104  if( GetFilename()==false )
1105  return false;
1106 
1107  // Let user edit MetaData
1108  if (mPlugins[mFormat]->GetCanMetaData(mSubFormat)) {
1109  if (!DoEditMetadata( *mProject,
1110  XO("Edit Metadata Tags"),
1111  XO("Exported Tags"),
1112  ProjectSettings::Get(*mProject).GetShowId3Dialog())) {
1113  return false;
1114  }
1115  }
1116 
1117  return true;
1118 }
1119 
1120 //----------------------------------------------------------------------------
1121 // ExportMixerPanel
1122 //----------------------------------------------------------------------------
1123 
1124 BEGIN_EVENT_TABLE(ExportMixerPanel, wxPanelWrapper)
1125  EVT_PAINT(ExportMixerPanel::OnPaint)
1126  EVT_MOUSE_EVENTS(ExportMixerPanel::OnMouseEvent)
1128 
1129 ExportMixerPanel::ExportMixerPanel( wxWindow *parent, wxWindowID id,
1130  MixerSpec *mixerSpec,
1131  wxArrayString trackNames,
1132  const wxPoint& pos, const wxSize& size):
1133  wxPanelWrapper(parent, id, pos, size)
1134  , mMixerSpec{mixerSpec}
1135  , mChannelRects{ mMixerSpec->GetMaxNumChannels() }
1136  , mTrackRects{ mMixerSpec->GetNumTracks() }
1137 {
1138  mBitmap = NULL;
1139  mWidth = 0;
1140  mHeight = 0;
1141  mSelectedTrack = mSelectedChannel = -1;
1142 
1143  mTrackNames = trackNames;
1144 }
1145 
1147 {
1148 }
1149 
1150 //set the font on memDC such that text can fit in specified width and height
1151 void ExportMixerPanel::SetFont(wxMemoryDC &memDC, const wxString &text, int width,
1152  int height )
1153 {
1154  int l = 0, u = 13, m, w, h;
1155  wxFont font = memDC.GetFont();
1156  while( l < u - 1 )
1157  {
1158  m = ( l + u ) / 2;
1159  font.SetPointSize( m );
1160  memDC.SetFont( font );
1161  memDC.GetTextExtent( text, &w, &h );
1162 
1163  if( w < width && h < height )
1164  l = m;
1165  else
1166  u = m;
1167  }
1168  font.SetPointSize( l );
1169  memDC.SetFont( font );
1170 }
1171 
1172 void ExportMixerPanel::OnPaint(wxPaintEvent & WXUNUSED(event))
1173 {
1174  wxPaintDC dc( this );
1175 
1176  int width, height;
1177  GetSize( &width, &height );
1178 
1179  if( !mBitmap || mWidth != width || mHeight != height )
1180  {
1181  mWidth = width;
1182  mHeight = height;
1183  mBitmap = std::make_unique<wxBitmap>( mWidth, mHeight,24 );
1184  }
1185 
1186  wxColour bkgnd = GetBackgroundColour();
1187  wxBrush bkgndBrush( bkgnd, wxBRUSHSTYLE_SOLID );
1188 
1189  wxMemoryDC memDC;
1190  memDC.SelectObject( *mBitmap );
1191 
1192  //draw background
1193  wxRect bkgndRect;
1194  bkgndRect.x = 0;
1195  bkgndRect.y = 0;
1196  bkgndRect.width = mWidth;
1197  bkgndRect.height = mHeight;
1198 
1199  memDC.SetBrush( *wxWHITE_BRUSH );
1200  memDC.SetPen( *wxBLACK_PEN );
1201  memDC.DrawRectangle( bkgndRect );
1202 
1203  //box dimensions
1204  mBoxWidth = mWidth / 6;
1205 
1206  mTrackHeight = ( mHeight * 3 ) / ( mMixerSpec->GetNumTracks() * 4 );
1207  if( mTrackHeight > 30 )
1208  mTrackHeight = 30;
1209 
1210  mChannelHeight = ( mHeight * 3 ) / ( mMixerSpec->GetNumChannels() * 4 );
1211  if( mChannelHeight > 30 )
1212  mChannelHeight = 30;
1213 
1214  static double PI = 2 * acos( 0.0 );
1215  double angle = atan( ( 3.0 * mHeight ) / mWidth );
1216  double radius = mHeight / ( 2.0 * sin( PI - 2.0 * angle ) );
1217  double totAngle = ( asin( mHeight / ( 2.0 * radius ) ) * 2.0 );
1218 
1219  //draw tracks
1220  memDC.SetBrush( AColor::envelopeBrush );
1221  angle = totAngle / ( mMixerSpec->GetNumTracks() + 1 );
1222 
1223  int max = 0, w, h;
1224  for( unsigned int i = 1; i < mMixerSpec->GetNumTracks(); i++ )
1225  if( mTrackNames[ i ].length() > mTrackNames[ max ].length() )
1226  max = i;
1227 
1228  SetFont( memDC, mTrackNames[ max ], mBoxWidth, mTrackHeight );
1229 
1230  for( unsigned int i = 0; i < mMixerSpec->GetNumTracks(); i++ )
1231  {
1232  mTrackRects[ i ].x = (int)( mBoxWidth * 2 + radius - radius *
1233  cos( totAngle / 2.0 - angle * ( i + 1 ) ) - mBoxWidth + 0.5 );
1234  mTrackRects[ i ].y = (int)( mHeight * 0.5 - radius *
1235  sin( totAngle * 0.5 - angle * ( i + 1.0 ) ) -
1236  0.5 * mTrackHeight + 0.5 );
1237 
1238  mTrackRects[ i ].width = mBoxWidth;
1239  mTrackRects[ i ].height = mTrackHeight;
1240 
1241  memDC.SetPen( mSelectedTrack == (int)i ? *wxRED_PEN : *wxBLACK_PEN );
1242  memDC.DrawRectangle( mTrackRects[ i ] );
1243 
1244  memDC.GetTextExtent( mTrackNames[ i ], &w, &h );
1245  memDC.DrawText( mTrackNames[ i ],
1246  mTrackRects[ i ].x + ( mBoxWidth - w ) / 2,
1247  mTrackRects[ i ].y + ( mTrackHeight - h ) / 2 );
1248  }
1249 
1250  //draw channels
1251  memDC.SetBrush( AColor::playRegionBrush[ 0 ] );
1252  angle = ( asin( mHeight / ( 2.0 * radius ) ) * 2.0 ) /
1253  ( mMixerSpec->GetNumChannels() + 1 );
1254 
1255  SetFont( memDC, wxT( "Channel: XX" ), mBoxWidth, mChannelHeight );
1256  memDC.GetTextExtent( wxT( "Channel: XX" ), &w, &h );
1257 
1258  for( unsigned int i = 0; i < mMixerSpec->GetNumChannels(); i++ )
1259  {
1260  mChannelRects[ i ].x = (int)( mBoxWidth * 4 - radius + radius *
1261  cos( totAngle * 0.5 - angle * ( i + 1 ) ) + 0.5 );
1262  mChannelRects[ i ].y = (int)( mHeight * 0.5 - radius *
1263  sin( totAngle * 0.5 - angle * ( i + 1 ) ) -
1264  0.5 * mChannelHeight + 0.5 );
1265 
1266  mChannelRects[ i ].width = mBoxWidth;
1267  mChannelRects[ i ].height = mChannelHeight;
1268 
1269  memDC.SetPen( mSelectedChannel == (int)i ? *wxRED_PEN : *wxBLACK_PEN );
1270  memDC.DrawRectangle( mChannelRects[ i ] );
1271 
1272  memDC.DrawText( wxString::Format( _( "Channel: %2d" ), i + 1 ),
1273  mChannelRects[ i ].x + ( mBoxWidth - w ) / 2,
1274  mChannelRects[ i ].y + ( mChannelHeight - h ) / 2 );
1275  }
1276 
1277  //draw links
1278  memDC.SetPen( wxPen( *wxBLACK, mHeight / 200 ) );
1279  for( unsigned int i = 0; i < mMixerSpec->GetNumTracks(); i++ )
1280  for( unsigned int j = 0; j < mMixerSpec->GetNumChannels(); j++ )
1281  if( mMixerSpec->mMap[ i ][ j ] )
1282  AColor::Line(memDC, mTrackRects[ i ].x + mBoxWidth,
1283  mTrackRects[ i ].y + mTrackHeight / 2, mChannelRects[ j ].x,
1284  mChannelRects[ j ].y + mChannelHeight / 2 );
1285 
1286  dc.Blit( 0, 0, mWidth, mHeight, &memDC, 0, 0, wxCOPY, FALSE );
1287 }
1288 
1289 double ExportMixerPanel::Distance( wxPoint &a, wxPoint &b )
1290 {
1291  return sqrt( pow( a.x - b.x, 2.0 ) + pow( a.y - b.y, 2.0 ) );
1292 }
1293 
1294 //checks if p is on the line connecting la, lb with tolerance
1295 bool ExportMixerPanel::IsOnLine( wxPoint p, wxPoint la, wxPoint lb )
1296 {
1297  return Distance( p, la ) + Distance( p, lb ) - Distance( la, lb ) < 0.1;
1298 }
1299 
1300 void ExportMixerPanel::OnMouseEvent(wxMouseEvent & event)
1301 {
1302  if( event.ButtonDown() )
1303  {
1304  bool reset = true;
1305  //check tracks
1306  for( unsigned int i = 0; i < mMixerSpec->GetNumTracks(); i++ )
1307  if( mTrackRects[ i ].Contains( event.m_x, event.m_y ) )
1308  {
1309  reset = false;
1310  if( mSelectedTrack == (int)i )
1311  mSelectedTrack = -1;
1312  else
1313  {
1314  mSelectedTrack = i;
1315  if( mSelectedChannel != -1 )
1318  }
1319  goto found;
1320  }
1321 
1322  //check channels
1323  for( unsigned int i = 0; i < mMixerSpec->GetNumChannels(); i++ )
1324  if( mChannelRects[ i ].Contains( event.m_x, event.m_y ) )
1325  {
1326  reset = false;
1327  if( mSelectedChannel == (int)i )
1328  mSelectedChannel = -1;
1329  else
1330  {
1331  mSelectedChannel = i;
1332  if( mSelectedTrack != -1 )
1335  }
1336  goto found;
1337  }
1338 
1339  //check links
1340  for( unsigned int i = 0; i < mMixerSpec->GetNumTracks(); i++ )
1341  for( unsigned int j = 0; j < mMixerSpec->GetNumChannels(); j++ )
1342  if( mMixerSpec->mMap[ i ][ j ] && IsOnLine( wxPoint( event.m_x,
1343  event.m_y ), wxPoint( mTrackRects[ i ].x + mBoxWidth,
1344  mTrackRects[ i ].y + mTrackHeight / 2 ),
1345  wxPoint( mChannelRects[ j ].x, mChannelRects[ j ].y +
1346  mChannelHeight / 2 ) ) )
1347  mMixerSpec->mMap[ i ][ j ] = false;
1348 
1349 found:
1350  if( reset )
1352  Refresh( false );
1353  }
1354 }
1355 
1356 //----------------------------------------------------------------------------
1357 // ExportMixerDialog
1358 //----------------------------------------------------------------------------
1359 
1360 enum
1361 {
1362  ID_MIXERPANEL = 10001,
1364 };
1365 
1366 BEGIN_EVENT_TABLE( ExportMixerDialog, wxDialogWrapper )
1368  EVT_BUTTON( wxID_CANCEL, ExportMixerDialog::OnCancel )
1370  EVT_SIZE( ExportMixerDialog::OnSize )
1373 
1374 ExportMixerDialog::ExportMixerDialog( const TrackList *tracks, bool selectedOnly,
1375  unsigned maxNumChannels, wxWindow *parent, wxWindowID id, const TranslatableString &title,
1376  const wxPoint &position, const wxSize& size, long style ) :
1377  wxDialogWrapper( parent, id, title, position, size, style | wxRESIZE_BORDER )
1378 {
1379  SetName();
1380 
1381  unsigned numTracks = 0;
1382 
1383  bool anySolo = !(( tracks->Any<const WaveTrack>() + &WaveTrack::GetSolo ).empty());
1384 
1385  for (auto t :
1386  tracks->Any< const WaveTrack >()
1387  + ( selectedOnly ? &Track::IsSelected : &Track::Any )
1388  - ( anySolo ? &WaveTrack::GetNotSolo : &WaveTrack::GetMute)
1389  ) {
1390  numTracks++;
1391  const wxString sTrackName = (t->GetName()).Left(20);
1392  if( t->GetChannel() == Track::LeftChannel )
1393  /* i18n-hint: track name and L abbreviating Left channel */
1394  mTrackNames.push_back( wxString::Format( _( "%s - L" ), sTrackName ) );
1395  else if( t->GetChannel() == Track::RightChannel )
1396  /* i18n-hint: track name and R abbreviating Right channel */
1397  mTrackNames.push_back( wxString::Format( _( "%s - R" ), sTrackName ) );
1398  else
1399  mTrackNames.push_back(sTrackName);
1400  }
1401 
1402  // JKC: This is an attempt to fix a 'watching brief' issue, where the slider is
1403  // sometimes not slidable. My suspicion is that a mixer may incorrectly
1404  // state the number of channels - so we assume there are always at least two.
1405  // The downside is that if someone is exporting to a mono device, the dialog
1406  // will allow them to output to two channels. Hmm. We may need to revisit this.
1407 
1408  if (maxNumChannels < 2 )
1409  // STF (April 2016): AMR (narrowband) and MP3 may export 1 channel.
1410  // maxNumChannels = 2;
1411  maxNumChannels = 1;
1412  if (maxNumChannels > 32)
1413  maxNumChannels = 32;
1414 
1415  mMixerSpec = std::make_unique<MixerSpec>(numTracks, maxNumChannels);
1416 
1417  auto label = XO("Output Channels: %2d")
1418  .Format( mMixerSpec->GetNumChannels() );
1419 
1420  ShuttleGui S{ this, eIsCreating };
1421  {
1422  S.SetBorder( 5 );
1423 
1424  auto mixerPanel = safenew ExportMixerPanel(
1425  S.GetParent(), ID_MIXERPANEL, mMixerSpec.get(),
1426  mTrackNames, wxDefaultPosition, wxSize(400, -1));
1427  S.Prop(1)
1428  .Name(XO("Mixer Panel"))
1429  .Position(wxEXPAND | wxALL)
1430  .AddWindow(mixerPanel);
1431 
1432  S.StartHorizontalLay(wxALIGN_CENTER | wxALL, 0);
1433  {
1434  mChannelsText = S.AddVariableText(
1435  label,
1436  false, wxALIGN_LEFT | wxALL );
1437 
1438  S
1440  .Name(label)
1441  .Size({300, -1})
1442  .Style(wxSL_HORIZONTAL)
1443  .Position(wxEXPAND | wxALL)
1444  .AddSlider( {},
1445  mMixerSpec->GetNumChannels(),
1446  mMixerSpec->GetMaxNumChannels(), 1 );
1447  }
1448  S.EndHorizontalLay();
1449 
1451  }
1452 
1453  SetAutoLayout(true);
1454  GetSizer()->Fit( this );
1455  GetSizer()->SetSizeHints( this );
1456 
1457  SetSizeHints( 640, 480, 20000, 20000 );
1458 
1459  SetSize( 640, 480 );
1460  Center();
1461 }
1462 
1464 {
1465 }
1466 
1467 void ExportMixerDialog::OnSize(wxSizeEvent &event)
1468 {
1469  ExportMixerPanel *pnl = ( ( ExportMixerPanel* ) FindWindow( ID_MIXERPANEL ) );
1470  pnl->Refresh( false );
1471  event.Skip();
1472 }
1473 
1474 void ExportMixerDialog::OnSlider( wxCommandEvent & WXUNUSED(event))
1475 {
1476  wxSlider *channels = ( wxSlider* )FindWindow( ID_SLIDER_CHANNEL );
1477  ExportMixerPanel *pnl = ( ( ExportMixerPanel* ) FindWindow( ID_MIXERPANEL ) );
1478  mMixerSpec->SetNumChannels( channels->GetValue() );
1479  pnl->Refresh( false );
1480  wxString label;
1481  label.Printf( _( "Output Channels: %2d" ), mMixerSpec->GetNumChannels() );
1482  mChannelsText->SetLabel( label );
1483  channels->SetName( label );
1484 }
1485 
1486 void ExportMixerDialog::OnOk(wxCommandEvent & WXUNUSED(event))
1487 {
1488  EndModal( wxID_OK );
1489 }
1490 
1491 void ExportMixerDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
1492 {
1493  EndModal( wxID_CANCEL );
1494 }
1495 
1496 void ExportMixerDialog::OnMixerPanelHelp(wxCommandEvent & WXUNUSED(event))
1497 {
1498  HelpSystem::ShowHelp(this, L"Advanced_Mixing_Options", true);
1499 }
1500 
1501 
1503 {
1504  return XO("Warning");
1505 }
1507 {
1508  return XO("Unable to export.\nError %s");
1509 }
1510 
1511 
1512 // This creates a generic export error dialog
1513 // Untranslated ErrorCodes like "MP3:1882" are used since we don't yet have
1514 // a good user facing error message. They allow us to
1515 // distinguish where the error occurred, and we can update the landing
1516 // page as we learn more about when (if ever) these errors actually happen.
1517 // The number happens to at one time have been a line number, but all
1518 // we need from them is that they be distinct.
1519 void ShowExportErrorDialog(wxString ErrorCode,
1520  TranslatableString message,
1521  const TranslatableString& caption)
1522 {
1523  using namespace BasicUI;
1524  ShowErrorDialog( {},
1525  caption,
1526  message.Format( ErrorCode ),
1527  "Error:_Unable_to_export", // URL.
1529 }
1530 
1532 {
1534  XO("Warning"),
1536  "Error:_Disk_full_or_not_writable"
1537  );
1538 }
1539 
1540 
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
Exporter::OnHelp
void OnHelp(wxCommandEvent &evt)
Definition: Export.cpp:368
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
Registry::TransparentGroupItem
Definition: Registry.h:210
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
Registry::RegisterItem
void RegisterItem(GroupItem &registry, const Placement &placement, BaseItemPtr pItem)
Definition: Registry.cpp:750
ShuttleGuiBase::EndSimplebook
void EndSimplebook()
Definition: ShuttleGui.cpp:1061
Registry::SingleItem
Definition: Registry.h:120
WaveTrackConstArray
std::vector< std::shared_ptr< const WaveTrack > > WaveTrackConstArray
Definition: AudioIO.h:49
ExportPlugin::GetMask
FileNames::FileTypes GetMask(int index)
Definition: Export.cpp:172
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:38
ExportMixerDialog::mChannelsText
wxStaticText * mChannelsText
Definition: Export.h:312
Registry
Definition: Menus.h:35
ExportMixerPanel::mTrackNames
wxArrayString mTrackNames
Definition: Export.h:285
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
anonymous_namespace{Export.cpp}::ExporterItem::ExporterItem
ExporterItem(const Identifier &id, const Exporter::ExportPluginFactory &factory)
Definition: Export.cpp:293
wxFileNameWrapper.h
Exporter::Process
bool Process(bool selectedOnly, double t0, double t1)
Definition: Export.cpp:428
BasicUI::ProgressResult::Success
@ Success
ExportMixerPanel::~ExportMixerPanel
virtual ~ExportMixerPanel()
Definition: Export.cpp:1146
PlayableTrack::GetSolo
bool GetSolo() const
Definition: Track.h:861
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
ExportMixerDialog::OnOk
void OnOk(wxCommandEvent &event)
Definition: Export.cpp:1486
wxFileNameWrapper
Definition: wxFileNameWrapper.h:21
FileNames::FindDefaultPath
FILES_API FilePath FindDefaultPath(Operation op)
HelpSystem.h
ShuttleGuiBase::AddTitle
void AddTitle(const TranslatableString &Prompt, int wrapWidth=0)
Centred text string.
Definition: ShuttleGui.cpp:281
Exporter::OnExtensionChanged
void OnExtensionChanged(wxCommandEvent &evt)
Definition: Export.cpp:363
Exporter::~Exporter
virtual ~Exporter()
Definition: Export.cpp:359
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
AllThemeResources.h
EVT_COMMAND
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Definition: LabelDialog.cpp:92
BasicUI::ShowErrorDialog
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
Definition: BasicUI.h:233
ExportPlugin::GetFormatCount
virtual int GetFormatCount()
Definition: Export.cpp:108
eHelpButton
@ eHelpButton
Definition: ShuttleGui.h:604
Exporter::SetFileDialogTitle
void SetFileDialogTitle(const TranslatableString &DialogTitle)
Definition: Export.cpp:374
anonymous_namespace{Export.cpp}::ExporterItem
Definition: Export.cpp:292
Project.h
Exporter::GetFilename
bool GetFilename()
Definition: Export.cpp:605
ExportPlugin::AddExtension
void AddExtension(const FileExtension &extension, int index)
Definition: Export.cpp:127
ShowExportErrorDialog
void ShowExportErrorDialog(wxString ErrorCode, TranslatableString message, const TranslatableString &caption)
Definition: Export.cpp:1519
wxPanelWrapper
Definition: wxPanelWrapper.h:41
Exporter::CreateUserPane
void CreateUserPane(wxWindow *parent)
Definition: Export.cpp:967
Exporter::Exporter
Exporter(AudacityProject &project)
Definition: Export.cpp:320
ShowWarningDialog
int ShowWarningDialog(wxWindow *parent, const wxString &internalDialogName, const TranslatableString &message, bool showCancelButton, const TranslatableString &footer)
Definition: Warning.cpp:92
ExportMixerPanel::mBoxWidth
int mBoxWidth
Definition: Export.h:286
Mixer::WarpOptions
Definition: Mix.h:81
FileNames::UpdateDefaultPath
FILES_API void UpdateDefaultPath(Operation op, const FilePath &path)
Mix.h
TrackList
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1280
Exporter::mChannels
unsigned mChannels
Definition: Export.h:253
ImportExportPrefs::ExportDownMixSetting
static EnumSetting< bool > ExportDownMixSetting
Definition: ImportExportPrefs.h:29
Exporter
Definition: Export.h:166
AColor::Line
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:109
Exporter::mActualName
wxFileName mActualName
Definition: Export.h:242
ExportMixerPanel::SetFont
void SetFont(wxMemoryDC &memDC, const wxString &text, int width, int height)
Definition: Export.cpp:1151
Exporter::SetAutoExportOptions
bool SetAutoExportOptions()
Definition: Export.cpp:1101
ExportMixerPanel::mBitmap
std::unique_ptr< wxBitmap > mBitmap
Definition: Export.h:277
ID_MIXERPANEL
@ ID_MIXERPANEL
Definition: Export.cpp:1362
ExportMixerDialog::OnCancel
void OnCancel(wxCommandEvent &event)
Definition: Export.cpp:1491
Exporter::CreateUserPaneCallback
static void CreateUserPaneCallback(wxWindow *parent, wxUIntPtr userdata)
Definition: Export.cpp:958
XO
#define XO(s)
Definition: Internat.h:31
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:44
ExportMixerPanel::mChannelRects
ArrayOf< wxRect > mChannelRects
Definition: Export.h:282
ExportMixerPanel::mTrackHeight
int mTrackHeight
Definition: Export.h:286
Exporter::GetAutoExportFormat
int GetAutoExportFormat()
Definition: Export.cpp:1085
ProgressDialog.h
ExportPlugin::ExportPlugin
ExportPlugin()
Definition: Export.cpp:81
Exporter::CheckFilename
bool CheckFilename()
Definition: Export.cpp:783
Track::Any
bool Any() const
Definition: Track.cpp:370
ExportMixerPanel::OnMouseEvent
void OnMouseEvent(wxMouseEvent &event)
Definition: Export.cpp:1300
ExportPlugin::GetCanMetaData
virtual bool GetCanMetaData(int index)
Definition: Export.cpp:185
ShuttleGuiBase::StartNotebookPage
wxNotebookPage * StartNotebookPage(const TranslatableString &Name)
Definition: ShuttleGui.cpp:1068
Exporter::mFormat
int mFormat
Definition: Export.h:247
PI
#define PI
Definition: Biquad.cpp:18
ExportPlugin::mFormatInfos
std::vector< FormatInfo > mFormatInfos
Definition: Export.h:152
anonymous_namespace{Export.cpp}::ExporterItem::mFactory
Exporter::ExportPluginFactory mFactory
Definition: Export.cpp:299
Exporter::mFilename
wxFileName mFilename
Definition: Export.h:241
ShuttleGuiBase::EndNotebookPage
void EndNotebookPage()
Definition: ShuttleGui.cpp:1091
BasicUI::ErrorDialogType::ModalErrorReport
@ ModalErrorReport
HelpSystem::ShowHelp
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:237
ExportMixerPanel::mMixerSpec
MixerSpec * mMixerSpec
Definition: Export.h:281
wxArrayStringEx
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Definition: wxArrayStringEx.h:18
Registry::Placement
Definition: Registry.h:219
Exporter::GetAutoExportFileName
wxFileName GetAutoExportFileName()
Definition: Export.cpp:1097
wxDEFINE_EVENT
wxDEFINE_EVENT(AUDACITY_FILE_SUFFIX_EVENT, wxCommandEvent)
Exporter::mSelectedOnly
bool mSelectedOnly
Definition: Export.h:254
ExportMixerPanel::Distance
double Distance(wxPoint &a, wxPoint &b)
Definition: Export.cpp:1289
ExportPlugin::GetFormat
virtual wxString GetFormat(int index)
Definition: Export.cpp:152
ExportPlugin::GetExtension
virtual FileExtension GetExtension(int index=0)
Return the (first) file name extension for the sub-format.
Definition: Export.cpp:162
Tags::Get
static Tags & Get(AudacityProject &project)
Definition: Tags.cpp:237
ExportPlugin::GetDescription
TranslatableString GetDescription(int index)
Definition: Export.cpp:157
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2274
ThemeBase::Bitmap
wxBitmap & Bitmap(int iIndex)
Definition: Theme.cpp:1209
ProgressDialog::SetMessage
void SetMessage(const TranslatableString &message)
Definition: ProgressDialog.cpp:1510
ExportMixerPanel::mChannelHeight
int mChannelHeight
Definition: Export.h:286
Identifier
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
AudacityExportMessageStr
TranslatableString AudacityExportMessageStr()
Definition: Export.cpp:1506
Exporter::mNumSelected
int mNumSelected
Definition: Export.h:249
FileExtension
wxString FileExtension
File extension, not including any leading dot.
Definition: Identifier.h:224
Registry::Visitor
Definition: Registry.h:242
ExportMixerDialog
Dialog for advanced mixing.
Definition: Export.h:299
ExportPluginArray
std::vector< std::unique_ptr< ExportPlugin > > ExportPluginArray
Definition: Export.h:155
Exporter::OnFilterChanged
void OnFilterChanged(wxFileCtrlEvent &evt)
Definition: Export.cpp:1004
ShowDiskFullExportErrorDialog
void ShowDiskFullExportErrorDialog(const wxFileNameWrapper &fileName)
Definition: Export.cpp:1531
eCancelButton
@ eCancelButton
Definition: ShuttleGui.h:601
Exporter::mSubFormat
int mSubFormat
Definition: Export.h:248
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1177
Exporter::mFormatName
FileExtension mFormatName
Definition: Export.h:233
ExportPlugin::SetExtensions
void SetExtensions(FileExtensions extensions, int index)
Definition: Export.cpp:132
factory
static RegisteredToolbarFactory factory
Definition: ControlToolBar.cpp:817
ExportPlugin::InitProgress
static void InitProgress(std::unique_ptr< ProgressDialog > &pDialog, const TranslatableString &title, const TranslatableString &message)
Definition: Export.cpp:251
Exporter::mMixerSpec
std::unique_ptr< MixerSpec > mMixerSpec
Definition: Export.h:237
anonymous_namespace{Export.cpp}::sRegistry
static Registry::GroupItem & sRegistry()
Definition: Export.cpp:286
ExportMixerPanel::mSelectedChannel
int mSelectedChannel
Definition: Export.h:284
MixerSpec::mMap
ArraysOf< bool > mMap
Definition: Mix.h:61
label
TranslatableString label
Definition: Tags.cpp:756
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1167
Exporter::GetPlugins
const ExportPluginArray & GetPlugins()
Definition: Export.cpp:394
ExportPlugin::SetFormat
void SetFormat(const wxString &format, int index)
Definition: Export.cpp:117
FileDialog::GetPath
virtual wxString GetPath() const
Definition: gtk/FileDialogPrivate.cpp:514
ProjectSettings::GetShowId3Dialog
bool GetShowId3Dialog() const
Definition: ProjectSettings.h:80
ShuttleGuiBase::StartSimplebook
wxSimplebook * StartSimplebook()
Definition: ShuttleGui.cpp:1047
ExportMixerPanel
Panel that displays mixing for advanced mixing option.
Definition: Export.h:265
ExportMixerPanel::mTrackRects
ArrayOf< wxRect > mTrackRects
Definition: Export.h:283
FileDialog::SetFilterIndex
virtual void SetFilterIndex(int filterIndex)
Definition: gtk/FileDialogPrivate.cpp:599
Exporter::mPlugins
ExportPluginArray mPlugins
Definition: Export.h:239
ExportPlugin::DisplayOptions
virtual bool DisplayOptions(wxWindow *parent, int format=0)
Definition: Export.cpp:204
Theme.h
Exporter::mDialog
FileDialogWrapper * mDialog
Definition: Export.h:234
anonymous_namespace{Export.cpp}::sFactories
ExportPluginFactories & sFactories()
Definition: Export.cpp:303
Exporter::mT1
double mT1
Definition: Export.h:245
MixerSpec::GetNumTracks
unsigned GetNumTracks()
Definition: Mix.h:71
ExportMixerDialog::OnSize
void OnSize(wxSizeEvent &event)
Definition: Export.cpp:1467
FileDialog.h
Track::RightChannel
@ RightChannel
Definition: Track.h:277
ExportPlugin::~ExportPlugin
virtual ~ExportPlugin()
Definition: Export.cpp:85
Track::IsSelected
bool IsSelected() const
Definition: Track.cpp:373
format
int format
Definition: ExportPCM.cpp:56
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:496
Export.h
ShuttleGuiBase::AddWindow
wxWindow * AddWindow(wxWindow *pWindow, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:299
ExportPlugin::SetDescription
void SetDescription(const TranslatableString &description, int index)
Definition: Export.cpp:122
AColor::playRegionBrush
static wxBrush playRegionBrush[1]
Definition: AColor.h:97
Exporter::GetAutoExportFilterIndex
int GetAutoExportFilterIndex()
Definition: Export.cpp:1093
Exporter::mT0
double mT0
Definition: Export.h:244
PlayableTrack::GetNotSolo
bool GetNotSolo() const
Definition: Track.h:863
ShuttleGui::Size
ShuttleGui & Size(wxSize size)
Definition: ShuttleGui.h:718
Exporter::DisplayOptions
void DisplayOptions(int index)
Definition: Export.cpp:802
Tags::Set
static Tags & Set(AudacityProject &project, const std::shared_ptr< Tags > &tags)
Definition: Tags.cpp:247
BasicUI::ErrorDialogOptions
Options for variations of error dialogs; the default is for modal dialogs.
Definition: BasicUI.h:49
AudacityExportCaptionStr
TranslatableString AudacityExportCaptionStr()
Definition: Export.cpp:1502
ShuttleGui::Prop
ShuttleGui & Prop(int iProp)
Definition: ShuttleGui.h:725
ShuttleGuiBase::AddSlider
wxSlider * AddSlider(const TranslatableString &Prompt, int pos, int Max, int Min=0)
Definition: ShuttleGui.cpp:589
theTheme
THEME_API Theme theTheme
Definition: Theme.cpp:79
FileDialogBase::SetUserPaneCreator
virtual void SetUserPaneCreator(UserPaneCreatorFunction creator, wxUIntPtr userdata)
Definition: FileDialog.cpp:30
ExportMixerDialog::GetMixerSpec
MixerSpec * GetMixerSpec()
Definition: Export.h:309
ExportPlugin::GetExtensions
virtual FileExtensions GetExtensions(int index=0)
Return all the file name extensions used for the sub-format.
Definition: Export.cpp:167
ID_SLIDER_CHANNEL
@ ID_SLIDER_CHANNEL
Definition: Export.cpp:1363
BasicUI.h
Toolkit-neutral facade for basic user interface services.
sampleFormat
sampleFormat
Definition: SampleFormat.h:29
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:893
ExportPlugin::SetMaxChannels
void SetMaxChannels(unsigned maxchannels, unsigned index)
Definition: Export.cpp:142
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
ExportMixerPanel::OnPaint
void OnPaint(wxPaintEvent &event)
Definition: Export.cpp:1172
ProjectHistory::PushState
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
Definition: ProjectHistory.cpp:90
ShuttleGui::Name
ShuttleGui & Name(const TranslatableString &name)
Definition: ShuttleGui.h:663
wxDialogWrapper
Definition: wxPanelWrapper.h:81
Exporter::ExportTracks
bool ExportTracks()
Definition: Export.cpp:911
ExportMixerPanel::mHeight
int mHeight
Definition: Export.h:280
ExportMixerPanel::mWidth
int mWidth
Definition: Export.h:279
BasicUI
Definition: Export.h:39
title
static const auto title
Definition: NoUpdatesAvailableDialog.cpp:22
ExportMixerDialog::~ExportMixerDialog
virtual ~ExportMixerDialog()
Definition: Export.cpp:1463
eOkButton
@ eOkButton
Definition: ShuttleGui.h:600
EnumSetting::ReadEnum
Enum ReadEnum() const
Definition: Prefs.h:373
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:506
ExportPlugin::GetMaxChannels
virtual unsigned GetMaxChannels(int index)
Definition: Export.cpp:180
ExportMixerDialog::OnSlider
void OnSlider(wxCommandEvent &event)
Definition: Export.cpp:1474
ShuttleGui::Position
ShuttleGui & Position(int flags)
Definition: ShuttleGui.h:712
Registry::Visit
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItem *pRegistry)
Definition: Registry.cpp:713
FileDialogWrapper
Definition: wxPanelWrapper.h:165
_
#define _(s)
Definition: Internat.h:75
Exporter::mFileDialogTitle
TranslatableString mFileDialogTitle
Definition: Export.h:235
Exporter::mBook
wxSimplebook * mBook
Definition: Export.h:256
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
ExportPlugin::SetMask
void SetMask(FileNames::FileTypes mask, int index)
Definition: Export.cpp:137
Exporter::FindFormatIndex
int FindFormatIndex(int exportindex)
Definition: Export.cpp:380
ExportPlugin::CreateMixer
std::unique_ptr< Mixer > CreateMixer(const TrackList &tracks, bool selectionOnly, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, MixerSpec *mixerSpec)
Definition: Export.cpp:223
FileNames.h
ExportPlugin::SetCanMetaData
void SetCanMetaData(bool canmetadata, int index)
Definition: Export.cpp:147
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
ExportPlugin::OptionsCreate
virtual void OptionsCreate(ShuttleGui &S, int format)=0
Definition: Export.cpp:209
ExportMixerPanel::mSelectedTrack
int mSelectedTrack
Definition: Export.h:284
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
Registry::GroupItem
Definition: Registry.h:126
ExportPlugin::AddFormat
int AddFormat()
Add a NEW entry to the list of formats this plug-in can export.
Definition: Export.cpp:101
wxDialogWrapper::SetTitle
void SetTitle(const TranslatableString &title)
Definition: wxPanelWrapper.cpp:66
FindProjectFrame
wxFrame * FindProjectFrame(AudacityProject *project)
Get a pointer to the window associated with a project, or null if the given pointer is null,...
Definition: ProjectWindows.cpp:88
ExportPlugin::IsExtension
virtual bool IsExtension(const FileExtension &ext, int index)
Definition: Export.cpp:190
FileException::WriteFailureMessage
static TranslatableString WriteFailureMessage(const wxFileName &fileName)
Definition: FileException.cpp:60
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2444
ExportMixerPanel::IsOnLine
bool IsOnLine(wxPoint p, wxPoint la, wxPoint lb)
Definition: Export.cpp:1295
Exporter::mFilterIndex
int mFilterIndex
Definition: Export.h:246
FileNames::FileTypes
std::vector< FileType > FileTypes
Definition: FileNames.h:76
ExportMixerDialog::OnMixerPanelHelp
void OnMixerPanelHelp(wxCommandEvent &event)
Definition: Export.cpp:1496
Exporter::mNumMono
unsigned mNumMono
Definition: Export.h:252
Prefs.h
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:489
anonymous_namespace{Export.cpp}::ExportPluginFactories
std::vector< Exporter::ExportPluginFactory > ExportPluginFactories
Definition: Export.cpp:302
TrackList::Any
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1371
ProgressDialog::Reinit
void Reinit()
Definition: ProgressDialog.cpp:1073
MixerSpec
Class used with Mixer.
Definition: Mix.h:55
TranslatableString::Format
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
Definition: TranslatableString.h:103
MixerSpec::GetNumChannels
unsigned GetNumChannels()
Definition: Mix.h:68
ShuttleGuiBase::AddVariableText
wxStaticText * AddVariableText(const TranslatableString &Str, bool bCenter=false, int PositionFlags=0, int wrapWidth=0)
Definition: ShuttleGui.cpp:463
FormatInfo
Definition: Export.h:43
FileDialog::SetFileExtension
virtual void SetFileExtension(const wxString &extension)
Definition: gtk/FileDialogPrivate.cpp:474
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:922
safenew
#define safenew
Definition: MemoryX.h:10
settings
static Settings & settings()
Definition: TrackInfo.cpp:86
Exporter::ExamineTracks
bool ExamineTracks()
Definition: Export.cpp:510
AColor.h
Exporter::GetAutoExportSubFormat
int GetAutoExportSubFormat()
Definition: Export.cpp:1089
AColor::envelopeBrush
static wxBrush envelopeBrush
Definition: AColor.h:106
Exporter::ProcessFromTimerRecording
bool ProcessFromTimerRecording(bool selectedOnly, double t0, double t1, wxFileName fnFile, int iFormat, int iSubFormat, int iFilterIndex)
Definition: Export.cpp:1042
FileDialog::ShowModal
virtual int ShowModal()
Definition: gtk/FileDialogPrivate.cpp:445
Track::LeftChannel
@ LeftChannel
Definition: Track.h:276
Exporter::DoEditMetadata
static bool DoEditMetadata(AudacityProject &project, const TranslatableString &title, const TranslatableString &shortUndoDescription, bool force)
Definition: Export.cpp:399
AudacityProject::GetProjectName
const wxString & GetProjectName() const
Definition: Project.cpp:92
END_EVENT_TABLE
END_EVENT_TABLE()
Exporter::ExportPluginFactory
std::function< std::unique_ptr< ExportPlugin >() > ExportPluginFactory
Definition: Export.h:170
FileDialog::GetFilterIndex
virtual int GetFilterIndex() const
Definition: gtk/FileDialogPrivate.cpp:604
Exporter::CheckMix
bool CheckMix(bool prompt=true)
Definition: Export.cpp:832
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
Exporter::mNumRight
unsigned mNumRight
Definition: Export.h:251
Exporter::RegisteredExportPlugin::RegisteredExportPlugin
RegisteredExportPlugin(const Identifier &id, const ExportPluginFactory &, const Registry::Placement &placement={ wxEmptyString, {} })
Definition: Export.cpp:310
Journal::WindowPaths::Path
Identifier Path
Definition: JournalWindowPaths.h:24
anonymous_namespace{Export.cpp}::PathStart
const auto PathStart
Definition: Export.cpp:284
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
Registry::OrderingPreferenceInitializer
Definition: Registry.h:273
ExportPlugin::CheckFileName
virtual bool CheckFileName(wxFileName &filename, int format=0)
Definition: Export.cpp:89
Exporter::mNumLeft
unsigned mNumLeft
Definition: Export.h:250
ExportMixerDialog::mMixerSpec
std::unique_ptr< MixerSpec > mMixerSpec
Definition: Export.h:313
Exporter::mProject
AudacityProject * mProject
Definition: Export.h:236