Audacity 3.2.0
Classes | Public Types | Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
Exporter Class Referencefinal

#include <Export.h>

Inheritance diagram for Exporter:
[legend]
Collaboration diagram for Exporter:
[legend]

Classes

struct  ExporterItem
 
struct  RegisteredExportPlugin
 

Public Types

using ExportPluginFactory = std::function< std::unique_ptr< ExportPlugin >() >
 

Public Member Functions

 Exporter (AudacityProject &project)
 
virtual ~Exporter ()
 
void SetFileDialogTitle (const TranslatableString &DialogTitle)
 
void SetDefaultFormat (const FileExtension &Format)
 
bool Process (bool selectedOnly, double t0, double t1)
 
bool Process (unsigned numChannels, const FileExtension &type, const wxString &filename, bool selectedOnly, double t0, double t1)
 
bool Process (unsigned numChannels, const FileExtension &type, const wxString &filename, bool selectedOnly, double t0, double t1, std::unique_ptr< BasicUI::ProgressDialog > &progressDialog)
 
void DisplayOptions (int index)
 
int FindFormatIndex (int exportindex)
 
const ExportPluginArrayGetPlugins ()
 
bool ProcessFromTimerRecording (bool selectedOnly, double t0, double t1, wxFileName fnFile, int iFormat, int iSubFormat, int iFilterIndex)
 
bool SetAutoExportOptions ()
 
int GetAutoExportFormat ()
 
int GetAutoExportSubFormat ()
 
int GetAutoExportFilterIndex ()
 
wxFileName GetAutoExportFileName ()
 
void OnExtensionChanged (wxCommandEvent &evt)
 
void OnHelp (wxCommandEvent &evt)
 

Private Member Functions

bool ExamineTracks ()
 
bool GetFilename ()
 
bool CheckFilename ()
 
bool CheckMix (bool prompt=true)
 
bool ExportTracks (std::unique_ptr< BasicUI::ProgressDialog > &progressDialog)
 
void CreateUserPane (wxWindow *parent)
 
void OnFilterChanged (wxFileCtrlEvent &evt)
 

Static Private Member Functions

static void CreateUserPaneCallback (wxWindow *parent, wxUIntPtr userdata)
 

Private Attributes

FileExtension mFormatName
 
FileDialogWrappermDialog
 
TranslatableString mFileDialogTitle
 
AudacityProjectmProject
 
std::unique_ptr< MixerSpecmMixerSpec
 
ExportPluginArray mPlugins
 
wxFileName mFilename
 
wxFileName mActualName
 
double mT0
 
double mT1
 
int mFilterIndex
 
int mFormat
 
int mSubFormat
 
int mNumSelected
 
unsigned mNumLeft
 
unsigned mNumRight
 
unsigned mNumMono
 
unsigned mChannels
 
bool mSelectedOnly
 
wxSimplebook * mBook
 

Detailed Description

Definition at line 171 of file Export.h.

Member Typedef Documentation

◆ ExportPluginFactory

using Exporter::ExportPluginFactory = std::function< std::unique_ptr< ExportPlugin >() >

Definition at line 176 of file Export.h.

Constructor & Destructor Documentation

◆ Exporter()

Exporter::Exporter ( AudacityProject project)

Definition at line 321 of file Export.cpp.

322: mProject{ &project }
323{
324 using namespace Registry;
326 PathStart,
327 { {wxT(""), wxT("PCM,MP3,OGG,FLAC,MP2,CommandLine,FFmpeg") } },
328 };
329
330 mMixerSpec = NULL;
331 mBook = NULL;
332
333 // build the list of export plugins.
334 for ( const auto &factory : sFactories() )
335 mPlugins.emplace_back( factory() );
336
337 struct MyVisitor final : Visitor {
338 MyVisitor()
339 {
340 // visit the registry to collect the plug-ins properly
341 // sorted
342 GroupItem<> top{ PathStart };
343 Registry::Visit( *this, &top, &ExporterItem::Registry() );
344 }
345
346 void Visit( SingleItem &item, const Path &path ) override
347 {
348 mPlugins.emplace_back(
349 static_cast<ExporterItem&>( item ).mFactory() );
350 }
351
353 } visitor;
354
355 mPlugins.swap( visitor.mPlugins );
356
357 SetFileDialogTitle( XO("Export Audio") );
358}
wxT("CloseDown"))
std::vector< std::unique_ptr< ExportPlugin > > ExportPluginArray
Definition: Export.h:161
XO("Cut/Copy/Paste")
void SetFileDialogTitle(const TranslatableString &DialogTitle)
Definition: Export.cpp:375
wxSimplebook * mBook
Definition: Export.h:273
std::unique_ptr< MixerSpec > mMixerSpec
Definition: Export.h:254
ExportPluginArray mPlugins
Definition: Export.h:256
AudacityProject * mProject
Definition: Export.h:253
Definition: Menus.h:35
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItemBase *pRegistry)
Definition: Registry.cpp:737
ExportPluginFactories & sFactories()
Definition: Export.cpp:291
static RegisteredToolbarFactory factory
static Registry::GroupItemBase & Registry()
Definition: Export.cpp:298

References cloud::factory, mBook, mMixerSpec, mPlugins, anonymous_namespace{Export.cpp}::PathStart, Exporter::ExporterItem::Registry(), SetFileDialogTitle(), anonymous_namespace{Export.cpp}::sFactories(), Registry::Visit(), wxT(), and XO().

Here is the call graph for this function:

◆ ~Exporter()

Exporter::~Exporter ( )
virtual

Definition at line 360 of file Export.cpp.

361{
362}

Member Function Documentation

◆ CheckFilename()

bool Exporter::CheckFilename ( )
private

Definition at line 766 of file Export.cpp.

767{
768 //
769 // To be even safer, return a temporary file name based
770 // on this one...
771 //
772
774
775 int suffix = 0;
776 while (mFilename.FileExists()) {
777 mFilename.SetName(mActualName.GetName() +
778 wxString::Format(wxT("%d"), suffix));
779 suffix++;
780 }
781
782 return true;
783}
wxFileName mActualName
Definition: Export.h:259
wxFileName mFilename
Definition: Export.h:258

References mActualName, mFilename, and wxT().

Referenced by Process(), and ProcessFromTimerRecording().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CheckMix()

bool Exporter::CheckMix ( bool  prompt = true)
private

Definition at line 815 of file Export.cpp.

816{
817 // Clean up ... should never happen
818 mMixerSpec.reset();
819
820 // Determine if exported file will be stereo or mono or multichannel,
821 // and if mixing will occur.
822
824 int exportedChannels = mPlugins[mFormat]->SetNumExportChannels();
825
826 if (downMix) {
827 if (mNumRight > 0 || mNumLeft > 0) {
828 mChannels = 2;
829 }
830 else {
831 mChannels = 1;
832 }
834 mPlugins[mFormat]->GetMaxChannels(mSubFormat));
835
836 auto numLeft = mNumLeft + mNumMono;
837 auto numRight = mNumRight + mNumMono;
838
839 if (numLeft > 1 || numRight > 1 || mNumLeft + mNumRight + mNumMono > mChannels) {
840 wxString exportFormat = mPlugins[mFormat]->GetFormat(mSubFormat);
841 if (exportFormat != wxT("CL") && exportFormat != wxT("FFMPEG") && exportedChannels == -1)
842 exportedChannels = mChannels;
843
844 if (prompt) {
845 auto pWindow = ProjectWindow::Find(mProject);
846 if (exportedChannels == 1) {
847 if (ShowWarningDialog(pWindow,
848 wxT("MixMono"),
849 XO("Your tracks will be mixed down and exported as one mono file."),
850 true) == wxID_CANCEL)
851 return false;
852 }
853 else if (exportedChannels == 2) {
854 if (ShowWarningDialog(pWindow,
855 wxT("MixStereo"),
856 XO("Your tracks will be mixed down and exported as one stereo file."),
857 true) == wxID_CANCEL)
858 return false;
859 }
860 else {
861 if (ShowWarningDialog(pWindow,
862 wxT("MixUnknownChannels"),
863 XO("Your tracks will be mixed down to one exported file according to the encoder settings."),
864 true) == wxID_CANCEL)
865 return false;
866 }
867 }
868 }
869 }
870 else
871 {
872 if (exportedChannels < 0)
873 exportedChannels = mPlugins[mFormat]->GetMaxChannels(mSubFormat);
874
877 exportedChannels,
878 NULL,
879 1,
880 XO("Advanced Mixing Options"));
881 if (prompt) {
882 if (md.ShowModal() != wxID_OK) {
883 return false;
884 }
885 }
886
887 mMixerSpec = std::make_unique<MixerSpec>(*(md.GetMixerSpec()));
888 mChannels = mMixerSpec->GetNumChannels();
889 }
890
891 return true;
892}
int min(int a, int b)
int ShowWarningDialog(wxWindow *parent, const wxString &internalDialogName, const TranslatableString &message, bool showCancelButton, const TranslatableString &footer)
Definition: Warning.cpp:90
Enum ReadEnum() const
Definition: Prefs.h:527
Dialog for advanced mixing.
Definition: Export.h:316
int mFormat
Definition: Export.h:264
unsigned mChannels
Definition: Export.h:270
bool mSelectedOnly
Definition: Export.h:271
unsigned mNumRight
Definition: Export.h:268
unsigned mNumLeft
Definition: Export.h:267
int mSubFormat
Definition: Export.h:265
unsigned mNumMono
Definition: Export.h:269
static EnumSetting< bool > ExportDownMixSetting
static ProjectWindow * Find(AudacityProject *pProject)
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:385

References ImportExportPrefs::ExportDownMixSetting, ProjectWindow::Find(), TrackList::Get(), ExportMixerDialog::GetMixerSpec(), mChannels, mFormat, min(), mMixerSpec, mNumLeft, mNumMono, mNumRight, mPlugins, mProject, mSelectedOnly, mSubFormat, EnumSetting< Enum >::ReadEnum(), ShowWarningDialog(), wxT(), and XO().

Referenced by Process(), and ProcessFromTimerRecording().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CreateUserPane()

void Exporter::CreateUserPane ( wxWindow *  parent)
private

Definition at line 950 of file Export.cpp.

951{
952 ShuttleGui S(parent, eIsCreating);
953
954 S.StartStatic(XO("Format Options"), 1);
955 {
956 S.StartHorizontalLay(wxEXPAND);
957 {
958 mBook = S.Position(wxEXPAND).StartSimplebook();
959 {
960 for (const auto &pPlugin : mPlugins)
961 {
962 for (int j = 0; j < pPlugin->GetFormatCount(); j++)
963 {
964 // Name of simple book page is not displayed
965 S.StartNotebookPage( {} );
966 {
967 pPlugin->OptionsCreate(S, j);
968 }
969 S.EndNotebookPage();
970 }
971 }
972 }
973 S.EndSimplebook();
974
975 auto b = safenew wxBitmapButton(S.GetParent(), wxID_HELP, theTheme.Bitmap( bmpHelpIcon ));
976 b->SetToolTip( XO("Help").Translation() );
977 b->SetLabel(XO("Help").Translation()); // for screen readers
978 S.Position(wxALIGN_BOTTOM | wxRIGHT | wxBOTTOM).AddWindow(b);
979 }
980 S.EndHorizontalLay();
981 }
982 S.EndStatic();
983
984 return;
985}
#define safenew
Definition: MemoryX.h:10
@ eIsCreating
Definition: ShuttleGui.h:37
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:625
wxBitmap & Bitmap(int iIndex)

References ThemeBase::Bitmap(), eIsCreating, mBook, mPlugins, S, safenew, theTheme, and XO().

Referenced by CreateUserPaneCallback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CreateUserPaneCallback()

void Exporter::CreateUserPaneCallback ( wxWindow *  parent,
wxUIntPtr  userdata 
)
staticprivate

Definition at line 941 of file Export.cpp.

942{
943 Exporter *self = (Exporter *) userdata;
944 if (self)
945 {
946 self->CreateUserPane(parent);
947 }
948}
void CreateUserPane(wxWindow *parent)
Definition: Export.cpp:950

References CreateUserPane().

Referenced by GetFilename().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DisplayOptions()

void Exporter::DisplayOptions ( int  index)

Definition at line 785 of file Export.cpp.

786{
787 int c = 0;
788 int mf = -1, msf = -1;
789 int i = -1;
790 for (const auto &pPlugin : mPlugins)
791 {
792 ++i;
793 for (int j = 0; j < pPlugin->GetFormatCount(); j++)
794 {
795 if (index == c)
796 {
797 mf = i;
798 msf = j;
799 }
800 c++;
801 }
802 }
803 // This shouldn't happen...
804 if (index >= c) {
805 return;
806 }
807
808#if defined(__WXMSW__)
809 mPlugins[mf]->DisplayOptions( FindProjectFrame( mProject ), msf);
810#else
811 mPlugins[mf]->DisplayOptions(mDialog, msf);
812#endif
813}
wxFrame * FindProjectFrame(AudacityProject *project)
Get a pointer to the window associated with a project, or null if the given pointer is null,...
FileDialogWrapper * mDialog
Definition: Export.h:251

References FindProjectFrame(), mDialog, mPlugins, and mProject.

Here is the call graph for this function:

◆ ExamineTracks()

bool Exporter::ExamineTracks ( )
private

Definition at line 493 of file Export.cpp.

494{
495 // Init
496 mNumSelected = 0;
497 mNumLeft = 0;
498 mNumRight = 0;
499 mNumMono = 0;
500
501 // First analyze the selected audio, perform sanity checks, and provide
502 // information as appropriate.
503
504 // Tally how many are right, left, mono, and make sure at
505 // least one track is selected (if selectedOnly==true)
506
507 double earliestBegin = mT1;
508 double latestEnd = mT0;
509
510 auto &tracks = TrackList::Get( *mProject );
511
512 bool anySolo = !(( tracks.Any<const WaveTrack>() + &WaveTrack::GetSolo ).empty());
513
514 for (auto tr :
515 tracks.Any< const WaveTrack >()
518 ) {
519 mNumSelected++;
520
521 if (tr->GetChannel() == Track::LeftChannel) {
522 mNumLeft++;
523 }
524 else if (tr->GetChannel() == Track::RightChannel) {
525 mNumRight++;
526 }
527 else if (tr->GetChannel() == Track::MonoChannel) {
528 // It's a mono channel, but it may be panned
529 float pan = tr->GetPan();
530
531 if (pan == -1.0)
532 mNumLeft++;
533 else if (pan == 1.0)
534 mNumRight++;
535 else if (pan == 0)
536 mNumMono++;
537 else {
538 // Panned partially off-center. Mix as stereo.
539 mNumLeft++;
540 mNumRight++;
541 }
542 }
543
544 if (tr->GetOffset() < earliestBegin) {
545 earliestBegin = tr->GetOffset();
546 }
547
548 if (tr->GetEndTime() > latestEnd) {
549 latestEnd = tr->GetEndTime();
550 }
551 }
552
553 if (mNumSelected == 0) {
554 TranslatableString message;
555 if(mSelectedOnly)
556 message = XO("All selected audio is muted.");
557 else
558 message = XO("All audio is muted.");
560 ":576",
561 message, AudacityExportCaptionStr(), false);
562 return false;
563 }
564
565 // The skipping of silent space could be cleverer and take
566 // into account clips.
567 // As implemented now, it can only skip initial silent space that
568 // has no clip before it, and terminal silent space that has no clip
569 // after it.
570 if (mT0 < earliestBegin){
571 // Bug 1904
572 // Previously we always skipped initial silent space.
573 // Now skipping it is an opt-in option.
574 bool skipSilenceAtBeginning;
575 gPrefs->Read(wxT("/AudioFiles/SkipSilenceAtBeginning"),
576 &skipSilenceAtBeginning, false);
577 if (skipSilenceAtBeginning)
578 mT0 = earliestBegin;
579 }
580
581 // We still skip silent space at the end
582 if (mT1 > latestEnd)
583 mT1 = latestEnd;
584
585 return true;
586}
void ShowExportErrorDialog(wxString ErrorCode, TranslatableString message, const TranslatableString &caption, bool allowReporting)
Definition: Export.cpp:1503
TranslatableString AudacityExportCaptionStr()
Definition: Export.cpp:1486
FileConfig * gPrefs
Definition: Prefs.cpp:70
double mT0
Definition: Export.h:261
double mT1
Definition: Export.h:262
int mNumSelected
Definition: Export.h:266
bool GetSolo() const
Definition: PlayableTrack.h:48
bool GetNotSolo() const
Definition: PlayableTrack.h:50
bool GetMute() const
Definition: PlayableTrack.h:47
bool IsSelected() const
Definition: Track.cpp:302
@ LeftChannel
Definition: Track.h:217
@ RightChannel
Definition: Track.h:218
@ MonoChannel
Definition: Track.h:219
bool Any() const
Definition: Track.cpp:299
Holds a msgid for the translation catalog; may also bind format arguments.
A Track that contains audio waveform data.
Definition: WaveTrack.h:51

References Track::Any(), AudacityExportCaptionStr(), TrackList::Get(), PlayableTrack::GetMute(), PlayableTrack::GetNotSolo(), PlayableTrack::GetSolo(), gPrefs, Track::IsSelected(), Track::LeftChannel, mNumLeft, mNumMono, mNumRight, mNumSelected, Track::MonoChannel, mProject, mSelectedOnly, mT0, mT1, Track::RightChannel, ShowExportErrorDialog(), wxT(), and XO().

Referenced by Process(), and ProcessFromTimerRecording().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ExportTracks()

bool Exporter::ExportTracks ( std::unique_ptr< BasicUI::ProgressDialog > &  progressDialog)
private

Definition at line 894 of file Export.cpp.

896{
897 // Keep original in case of failure
898 if (mActualName != mFilename) {
899 ::wxRenameFile(mActualName.GetFullPath(), mFilename.GetFullPath());
900 }
901
902 bool success = false;
903
904 auto cleanup = finally( [&] {
905 if (mActualName != mFilename) {
906 // Remove backup
907 if ( success )
908 ::wxRemoveFile(mFilename.GetFullPath());
909 else {
910 // Restore original, if needed
911 ::wxRemoveFile(mActualName.GetFullPath());
912 ::wxRenameFile(mFilename.GetFullPath(), mActualName.GetFullPath());
913 }
914 // Restore filename
916 }
917 else {
918 if ( ! success )
919 // Remove any new, and only partially written, file.
920 ::wxRemoveFile(mFilename.GetFullPath());
921 }
922 } );
923
924 auto result = mPlugins[mFormat]->Export(mProject,
925 progressDialog,
926 mChannels,
927 mActualName.GetFullPath(),
929 mT0,
930 mT1,
931 mMixerSpec.get(),
932 NULL,
933 mSubFormat);
934
935 success =
936 result == ProgressResult::Success || result == ProgressResult::Stopped;
937
938 return success;
939}

References mActualName, mChannels, mFilename, mFormat, mMixerSpec, mPlugins, mProject, mSelectedOnly, mSubFormat, mT0, mT1, and BasicUI::Success.

Referenced by Process(), and ProcessFromTimerRecording().

Here is the caller graph for this function:

◆ FindFormatIndex()

int Exporter::FindFormatIndex ( int  exportindex)

Definition at line 381 of file Export.cpp.

382{
383 int c = 0;
384 for (const auto &pPlugin : mPlugins)
385 {
386 for (int j = 0; j < pPlugin->GetFormatCount(); j++)
387 {
388 if (exportindex == c) return j;
389 c++;
390 }
391 }
392 return 0;
393}

References mPlugins.

◆ GetAutoExportFileName()

wxFileName Exporter::GetAutoExportFileName ( )

Definition at line 1081 of file Export.cpp.

1081 {
1082 return mFilename;
1083}

References mFilename.

◆ GetAutoExportFilterIndex()

int Exporter::GetAutoExportFilterIndex ( )

Definition at line 1077 of file Export.cpp.

1077 {
1078 return mFormat;
1079}

References mFormat.

◆ GetAutoExportFormat()

int Exporter::GetAutoExportFormat ( )

Definition at line 1069 of file Export.cpp.

1069 {
1070 return mFormat;
1071}

References mFormat.

◆ GetAutoExportSubFormat()

int Exporter::GetAutoExportSubFormat ( )

Definition at line 1073 of file Export.cpp.

1073 {
1074 return mSubFormat;
1075}

References mSubFormat.

◆ GetFilename()

bool Exporter::GetFilename ( )
private

Definition at line 588 of file Export.cpp.

589{
590 mFormat = -1;
591
592 FileNames::FileTypes fileTypes;
593 auto defaultFormat = mFormatName;
594 if( defaultFormat.empty() )
595 defaultFormat = gPrefs->Read(wxT("/Export/Format"),
596 wxT("WAV"));
597
598 mFilterIndex = 0;
599
600 {
601 int i = -1;
602 for (const auto &pPlugin : mPlugins) {
603 ++i;
604 for (int j = 0; j < pPlugin->GetFormatCount(); j++)
605 {
606 auto mask = pPlugin->GetMask(j);
607 fileTypes.insert( fileTypes.end(), mask.begin(), mask.end() );
608 if (mPlugins[i]->GetFormat(j) == defaultFormat) {
609 mFormat = i;
610 mSubFormat = j;
611 }
612 if (mFormat == -1) mFilterIndex++;
613 }
614 }
615 }
616 if (mFormat == -1)
617 {
618 mFormat = 0;
619 mFilterIndex = 0;
620 mSubFormat = 0;
621 }
622 wxString defext = mPlugins[mFormat]->GetExtension(mSubFormat).Lower();
623
624 //Bug 1304: Set a default path if none was given. For Export.
625 mFilename.SetPath(FileNames::FindDefaultPath(FileNames::Operation::Export));
627 if (mFilename.GetName().empty())
628 mFilename.SetName(_("untitled"));
629 while (true) {
630 // Must reset each iteration
631 mBook = NULL;
632
633 {
634 auto useFileName = mFilename;
635 if (!useFileName.HasExt())
636 useFileName.SetExt(defext);
639 mFilename.GetPath(),
640 useFileName.GetFullName(),
641 fileTypes,
642 wxFD_SAVE | wxRESIZE_BORDER);
643 mDialog = &fd;
644 mDialog->PushEventHandler(this);
645
646 fd.SetUserPaneCreator(CreateUserPaneCallback, (wxUIntPtr) this);
647 fd.SetFilterIndex(mFilterIndex);
648
649 int result = fd.ShowModal();
650
651 mDialog->PopEventHandler();
652
653 if (result == wxID_CANCEL) {
654 return false;
655 }
656
657 mFilename = fd.GetPath();
658 if (mFilename == wxT("")) {
659 return false;
660 }
661
662 mFormat = fd.GetFilterIndex();
663 mFilterIndex = fd.GetFilterIndex();
664 }
665
666 {
667 int c = 0;
668 int i = -1;
669 for (const auto &pPlugin : mPlugins)
670 {
671 ++i;
672 for (int j = 0; j < pPlugin->GetFormatCount(); j++)
673 {
674 if (mFilterIndex == c)
675 {
676 mFormat = i;
677 mSubFormat = j;
678 }
679 c++;
680 }
681 }
682 }
683
684 const auto ext = mFilename.GetExt();
685 defext = mPlugins[mFormat]->GetExtension(mSubFormat).Lower();
686
687 //
688 // Check the extension - add the default if it's not there,
689 // and warn user if it's abnormal.
690 //
691 if (ext.empty()) {
692 //
693 // Make sure the user doesn't accidentally save the file
694 // as an extension with no name, like just plain ".wav".
695 //
696 if (mFilename.GetName().Left(1) == wxT(".")) {
697 auto prompt =
698 XO("Are you sure you want to export the file as \"%s\"?\n")
699 .Format( mFilename.GetFullName() );
700
701 int action = AudacityMessageBox(
702 prompt,
703 XO("Warning"),
704 wxYES_NO | wxICON_EXCLAMATION);
705 if (action != wxYES) {
706 continue;
707 }
708 }
709
710 mFilename.SetExt(defext);
711 }
712
713 if (!mPlugins[mFormat]->CheckFileName(mFilename, mSubFormat))
714 {
715 continue;
716 }
717 else if (!ext.empty() && !mPlugins[mFormat]->IsExtension(ext,mSubFormat) && ext.CmpNoCase(defext)) {
718 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?")
719 .Format(mPlugins[mFormat]->GetFormat(mSubFormat),
720 mFilename.GetFullName(),
721 defext);
722
723 int action = AudacityMessageBox(
724 prompt,
725 XO("Warning"),
726 wxYES_NO | wxICON_EXCLAMATION);
727 if (action != wxYES) {
728 continue;
729 }
730 }
731
732 if (mFilename.GetFullPath().length() >= 256) {
734 XO( "Sorry, pathnames longer than 256 characters not supported.") );
735 continue;
736 }
737
738// For Mac, it's handled by the FileDialog
739#if !defined(__WXMAC__)
740 if (mFilename.FileExists()) {
741 auto prompt = XO("A file named \"%s\" already exists. Replace?")
742 .Format( mFilename.GetFullPath() );
743
744 int action = AudacityMessageBox(
745 prompt,
746 XO("Warning"),
747 wxYES_NO | wxICON_EXCLAMATION);
748 if (action != wxYES) {
749 continue;
750 }
751 }
752#endif
753
754 break;
755 }
756
757 return true;
758}
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
#define _(s)
Definition: Internat.h:73
const wxString & GetProjectName() const
Definition: Project.cpp:100
FileExtension mFormatName
Definition: Export.h:250
static void CreateUserPaneCallback(wxWindow *parent, wxUIntPtr userdata)
Definition: Export.cpp:941
int mFilterIndex
Definition: Export.h:263
TranslatableString mFileDialogTitle
Definition: Export.h:252
virtual void SetUserPaneCreator(UserPaneCreatorFunction creator, wxUIntPtr userdata)
Definition: FileDialog.cpp:30
std::vector< FileType > FileTypes
Definition: FileNames.h:75
FILES_API FilePath FindDefaultPath(Operation op)

References _, AudacityMessageBox(), CreateUserPaneCallback(), ProjectWindow::Find(), FileNames::FindDefaultPath(), FileDialog::GetFilterIndex(), FileDialog::GetPath(), AudacityProject::GetProjectName(), gPrefs, mBook, mDialog, mFileDialogTitle, mFilename, mFilterIndex, mFormat, mFormatName, mPlugins, mProject, mSubFormat, FileDialog::SetFilterIndex(), FileDialogBase::SetUserPaneCreator(), FileDialog::ShowModal(), wxT(), and XO().

Referenced by Process(), and SetAutoExportOptions().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetPlugins()

const ExportPluginArray & Exporter::GetPlugins ( )

Definition at line 395 of file Export.cpp.

396{
397 return mPlugins;
398}

References mPlugins.

◆ OnExtensionChanged()

void Exporter::OnExtensionChanged ( wxCommandEvent &  evt)

Definition at line 364 of file Export.cpp.

365{
366 mDialog->SetFileExtension(evt.GetString().BeforeFirst(' ').Lower());
367}
virtual void SetFileExtension(const wxString &extension)

References mDialog, and FileDialog::SetFileExtension().

Here is the call graph for this function:

◆ OnFilterChanged()

void Exporter::OnFilterChanged ( wxFileCtrlEvent &  evt)
private

Definition at line 987 of file Export.cpp.

988{
989 int index = evt.GetFilterIndex();
990
991 // On GTK, this event can fire before the userpane is created
992 if (mBook == NULL || index < 0 || index >= (int) mBook->GetPageCount())
993 {
994 return;
995 }
996
997#if defined(__WXGTK__)
998 // On Windows and MacOS, changing the filter in the dialog
999 // automatically changes the extension of the current file
1000 // name. GTK doesn't, so do it here.
1001 {
1002 FileNames::FileTypes fileTypes;
1003
1004 int i = -1;
1005 for (const auto &pPlugin : mPlugins)
1006 {
1007 ++i;
1008 for (int j = 0; j < pPlugin->GetFormatCount(); j++)
1009 {
1010 auto mask = pPlugin->GetMask(j);
1011 fileTypes.insert( fileTypes.end(), mask.begin(), mask.end() );
1012 }
1013 }
1014
1015 if (index < fileTypes.size())
1016 {
1017 mDialog->SetFileExtension(fileTypes[index].extensions[0].Lower());
1018 }
1019 }
1020#endif
1021
1022 mBook->ChangeSelection(index);
1023}

References mBook, mDialog, mPlugins, and FileDialog::SetFileExtension().

Here is the call graph for this function:

◆ OnHelp()

void Exporter::OnHelp ( wxCommandEvent &  evt)

Definition at line 369 of file Export.cpp.

370{
371 wxWindow * pWin = FindProjectFrame( mProject );
372 HelpSystem::ShowHelp(pWin, L"File_Export_Dialog", true);
373}
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:233

References FindProjectFrame(), mProject, and HelpSystem::ShowHelp().

Here is the call graph for this function:

◆ Process() [1/3]

bool Exporter::Process ( bool  selectedOnly,
double  t0,
double  t1 
)

Definition at line 400 of file Export.cpp.

401{
402 // Save parms
403 mSelectedOnly = selectedOnly;
404 mT0 = t0;
405 mT1 = t1;
406
407 // Gather track information
408 if (!ExamineTracks()) {
409 return false;
410 }
411
412 // Ask user for file name
413 if (!GetFilename()) {
414 return false;
415 }
416
417 // Check for down mixing
418 if (!CheckMix()) {
419 return false;
420 }
421
422 // Let user edit MetaData
423 if (mPlugins[mFormat]->GetCanMetaData(mSubFormat)) {
425 XO("Edit Metadata Tags"), XO("Exported Tags"),
426 ProjectSettings::Get( *mProject ).GetShowId3Dialog())) {
427 return false;
428 }
429 }
430
431 // Ensure filename doesn't interfere with project files.
432 if (!CheckFilename()) {
433 return false;
434 }
435
436 // Export the tracks
437 std::unique_ptr<BasicUI::ProgressDialog> pDialog;
438 bool success = ExportTracks(pDialog);
439
440 // Get rid of mixerspec
441 mMixerSpec.reset();
442
443 if (success) {
444 if (mFormatName.empty()) {
445 gPrefs->Write(wxT("/Export/Format"), mPlugins[mFormat]->GetFormat(mSubFormat));
446 }
447
448 FileNames::UpdateDefaultPath(FileNames::Operation::Export, mFilename.GetPath());
449 }
450
451 return success;
452}
bool ExamineTracks()
Definition: Export.cpp:493
bool ExportTracks(std::unique_ptr< BasicUI::ProgressDialog > &progressDialog)
Definition: Export.cpp:894
bool CheckMix(bool prompt=true)
Definition: Export.cpp:815
bool GetFilename()
Definition: Export.cpp:588
bool CheckFilename()
Definition: Export.cpp:766
static ProjectSettings & Get(AudacityProject &project)
bool GetShowId3Dialog() const
static AUDACITY_DLL_API bool DoEditMetadata(AudacityProject &project, const TranslatableString &title, const TranslatableString &shortUndoDescription, bool force)
Definition: TagsEditor.cpp:952
FILES_API void UpdateDefaultPath(Operation op, const FilePath &path)

References CheckFilename(), CheckMix(), TagsEditorDialog::DoEditMetadata(), ExamineTracks(), ExportTracks(), ProjectSettings::Get(), GetFilename(), ProjectSettings::GetShowId3Dialog(), gPrefs, mFilename, mFormat, mFormatName, mMixerSpec, mPlugins, mProject, mSelectedOnly, mSubFormat, mT0, mT1, FileNames::UpdateDefaultPath(), wxT(), and XO().

Referenced by Process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Process() [2/3]

bool Exporter::Process ( unsigned  numChannels,
const FileExtension type,
const wxString &  filename,
bool  selectedOnly,
double  t0,
double  t1 
)

Definition at line 454 of file Export.cpp.

457{
458 std::unique_ptr<BasicUI::ProgressDialog> pDialog;
459 return Process(numChannels, type, filename, selectedOnly, t0, t1, pDialog);
460}
bool Process(bool selectedOnly, double t0, double t1)
Definition: Export.cpp:400

References Process().

Here is the call graph for this function:

◆ Process() [3/3]

bool Exporter::Process ( unsigned  numChannels,
const FileExtension type,
const wxString &  filename,
bool  selectedOnly,
double  t0,
double  t1,
std::unique_ptr< BasicUI::ProgressDialog > &  progressDialog 
)

Definition at line 462 of file Export.cpp.

466{
467 // Save parms
468 mChannels = numChannels;
469 mFilename = filename;
470 mSelectedOnly = selectedOnly;
471 mT0 = t0;
472 mT1 = t1;
474
475 int i = -1;
476 for (const auto& pPlugin : mPlugins)
477 {
478 ++i;
479 for (int j = 0; j < pPlugin->GetFormatCount(); j++)
480 {
481 if (pPlugin->GetFormat(j).IsSameAs(type, false))
482 {
483 mFormat = i;
484 mSubFormat = j;
485 return CheckFilename() && ExportTracks(progressDialog);
486 }
487 }
488 }
489
490 return false;
491}

References CheckFilename(), ExportTracks(), mActualName, mChannels, mFilename, mFormat, mPlugins, mSelectedOnly, mSubFormat, mT0, and mT1.

Here is the call graph for this function:

◆ ProcessFromTimerRecording()

bool Exporter::ProcessFromTimerRecording ( bool  selectedOnly,
double  t0,
double  t1,
wxFileName  fnFile,
int  iFormat,
int  iSubFormat,
int  iFilterIndex 
)

Definition at line 1025 of file Export.cpp.

1032{
1033 // Save parms
1034 mSelectedOnly = selectedOnly;
1035 mT0 = t0;
1036 mT1 = t1;
1037
1038 // Auto Export Parameters
1039 mFilename = fnFile;
1040 mFormat = iFormat;
1041 mSubFormat = iSubFormat;
1042 mFilterIndex = iFilterIndex;
1043
1044 // Gather track information
1045 if (!ExamineTracks()) {
1046 return false;
1047 }
1048
1049 // Check for down mixing
1050 if (!CheckMix(false)) {
1051 return false;
1052 }
1053
1054 // Ensure filename doesn't interfere with project files.
1055 if (!CheckFilename()) {
1056 return false;
1057 }
1058
1059 // Export the tracks
1060 std::unique_ptr<BasicUI::ProgressDialog> pDialog;
1061 bool success = ExportTracks(pDialog);
1062
1063 // Get rid of mixerspec
1064 mMixerSpec.reset();
1065
1066 return success;
1067}

References CheckFilename(), CheckMix(), ExamineTracks(), ExportTracks(), mFilename, mFilterIndex, mFormat, mMixerSpec, mSelectedOnly, mSubFormat, mT0, and mT1.

Here is the call graph for this function:

◆ SetAutoExportOptions()

bool Exporter::SetAutoExportOptions ( )

Definition at line 1085 of file Export.cpp.

1085 {
1086 mFormat = -1;
1087
1088 if( GetFilename()==false )
1089 return false;
1090
1091 // Let user edit MetaData
1092 if (mPlugins[mFormat]->GetCanMetaData(mSubFormat)) {
1094 XO("Edit Metadata Tags"),
1095 XO("Exported Tags"),
1096 ProjectSettings::Get(*mProject).GetShowId3Dialog())) {
1097 return false;
1098 }
1099 }
1100
1101 return true;
1102}

References TagsEditorDialog::DoEditMetadata(), ProjectSettings::Get(), GetFilename(), ProjectSettings::GetShowId3Dialog(), mFormat, mPlugins, mProject, mSubFormat, and XO().

Here is the call graph for this function:

◆ SetDefaultFormat()

void Exporter::SetDefaultFormat ( const FileExtension Format)
inline

Definition at line 197 of file Export.h.

197{ mFormatName = Format;};
Abstract base class used in importing a file.

◆ SetFileDialogTitle()

void Exporter::SetFileDialogTitle ( const TranslatableString DialogTitle)

Definition at line 375 of file Export.cpp.

376{
377 // The default title is "Export File"
378 mFileDialogTitle = DialogTitle;
379}

References mFileDialogTitle.

Referenced by Exporter(), and anonymous_namespace{FileMenus.cpp}::OnExportSelection().

Here is the caller graph for this function:

Member Data Documentation

◆ mActualName

wxFileName Exporter::mActualName
private

Definition at line 259 of file Export.h.

Referenced by CheckFilename(), ExportTracks(), and Process().

◆ mBook

wxSimplebook* Exporter::mBook
private

Definition at line 273 of file Export.h.

Referenced by CreateUserPane(), Exporter(), GetFilename(), and OnFilterChanged().

◆ mChannels

unsigned Exporter::mChannels
private

Definition at line 270 of file Export.h.

Referenced by CheckMix(), ExportTracks(), and Process().

◆ mDialog

FileDialogWrapper* Exporter::mDialog
private

Definition at line 251 of file Export.h.

Referenced by DisplayOptions(), GetFilename(), OnExtensionChanged(), and OnFilterChanged().

◆ mFileDialogTitle

TranslatableString Exporter::mFileDialogTitle
private

Definition at line 252 of file Export.h.

Referenced by GetFilename(), and SetFileDialogTitle().

◆ mFilename

wxFileName Exporter::mFilename
private

◆ mFilterIndex

int Exporter::mFilterIndex
private

Definition at line 263 of file Export.h.

Referenced by GetFilename(), and ProcessFromTimerRecording().

◆ mFormat

int Exporter::mFormat
private

◆ mFormatName

FileExtension Exporter::mFormatName
private

Definition at line 250 of file Export.h.

Referenced by GetFilename(), and Process().

◆ mMixerSpec

std::unique_ptr<MixerSpec> Exporter::mMixerSpec
private

Definition at line 254 of file Export.h.

Referenced by CheckMix(), Exporter(), ExportTracks(), Process(), and ProcessFromTimerRecording().

◆ mNumLeft

unsigned Exporter::mNumLeft
private

Definition at line 267 of file Export.h.

Referenced by CheckMix(), and ExamineTracks().

◆ mNumMono

unsigned Exporter::mNumMono
private

Definition at line 269 of file Export.h.

Referenced by CheckMix(), and ExamineTracks().

◆ mNumRight

unsigned Exporter::mNumRight
private

Definition at line 268 of file Export.h.

Referenced by CheckMix(), and ExamineTracks().

◆ mNumSelected

int Exporter::mNumSelected
private

Definition at line 266 of file Export.h.

Referenced by ExamineTracks().

◆ mPlugins

ExportPluginArray Exporter::mPlugins
private

◆ mProject

AudacityProject* Exporter::mProject
private

◆ mSelectedOnly

bool Exporter::mSelectedOnly
private

Definition at line 271 of file Export.h.

Referenced by CheckMix(), ExamineTracks(), ExportTracks(), Process(), and ProcessFromTimerRecording().

◆ mSubFormat

int Exporter::mSubFormat
private

◆ mT0

double Exporter::mT0
private

Definition at line 261 of file Export.h.

Referenced by ExamineTracks(), ExportTracks(), Process(), and ProcessFromTimerRecording().

◆ mT1

double Exporter::mT1
private

Definition at line 262 of file Export.h.

Referenced by ExamineTracks(), ExportTracks(), Process(), and ProcessFromTimerRecording().


The documentation for this class was generated from the following files: