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  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 175 of file Export.h.

Constructor & Destructor Documentation

◆ Exporter()

Exporter::Exporter ( AudacityProject project)

Definition at line 324 of file Export.cpp.

325: mProject{ &project }
326{
327 using namespace Registry;
329 PathStart,
330 { {wxT(""), wxT("PCM,MP3,OGG,FLAC,MP2,CommandLine,FFmpeg") } },
331 };
332
333 mMixerSpec = NULL;
334 mBook = NULL;
335
336 // build the list of export plugins.
337 for ( const auto &factory : sFactories() )
338 mPlugins.emplace_back( factory() );
339
340 struct MyVisitor final : Visitor {
341 MyVisitor()
342 {
343 // visit the registry to collect the plug-ins properly
344 // sorted
346 Registry::Visit( *this, &top, &sRegistry() );
347 }
348
349 void Visit( SingleItem &item, const Path &path ) override
350 {
351 mPlugins.emplace_back(
352 static_cast<ExporterItem&>( item ).mFactory() );
353 }
354
356 } visitor;
357
358 mPlugins.swap( visitor.mPlugins );
359
360 SetFileDialogTitle( XO("Export Audio") );
361}
wxT("CloseDown"))
std::vector< std::unique_ptr< ExportPlugin > > ExportPluginArray
Definition: Export.h:161
XO("Cut/Copy/Paste")
auto Visit(Visitor &&vis, Variant &&var)
Mimic some of std::visit, for the case of one visitor only.
Definition: MemoryX.h:611
void SetFileDialogTitle(const TranslatableString &DialogTitle)
Definition: Export.cpp:378
wxSimplebook * mBook
Definition: Export.h:263
std::unique_ptr< MixerSpec > mMixerSpec
Definition: Export.h:244
ExportPluginArray mPlugins
Definition: Export.h:246
AudacityProject * mProject
Definition: Export.h:243
Definition: Menus.h:35
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItem *pRegistry)
Definition: Registry.cpp:713
filesystem::path Path
ExportPluginFactories & sFactories()
Definition: Export.cpp:307
static Registry::GroupItem & sRegistry()
Definition: Export.cpp:290
static RegisteredToolbarFactory factory

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

Here is the call graph for this function:

◆ ~Exporter()

Exporter::~Exporter ( )
virtual

Definition at line 363 of file Export.cpp.

364{
365}

Member Function Documentation

◆ CheckFilename()

bool Exporter::CheckFilename ( )
private

Definition at line 769 of file Export.cpp.

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

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 818 of file Export.cpp.

819{
820 // Clean up ... should never happen
821 mMixerSpec.reset();
822
823 // Determine if exported file will be stereo or mono or multichannel,
824 // and if mixing will occur.
825
827 int exportedChannels = mPlugins[mFormat]->SetNumExportChannels();
828
829 if (downMix) {
830 if (mNumRight > 0 || mNumLeft > 0) {
831 mChannels = 2;
832 }
833 else {
834 mChannels = 1;
835 }
837 mPlugins[mFormat]->GetMaxChannels(mSubFormat));
838
839 auto numLeft = mNumLeft + mNumMono;
840 auto numRight = mNumRight + mNumMono;
841
842 if (numLeft > 1 || numRight > 1 || mNumLeft + mNumRight + mNumMono > mChannels) {
843 wxString exportFormat = mPlugins[mFormat]->GetFormat(mSubFormat);
844 if (exportFormat != wxT("CL") && exportFormat != wxT("FFMPEG") && exportedChannels == -1)
845 exportedChannels = mChannels;
846
847 if (prompt) {
848 auto pWindow = ProjectWindow::Find(mProject);
849 if (exportedChannels == 1) {
850 if (ShowWarningDialog(pWindow,
851 wxT("MixMono"),
852 XO("Your tracks will be mixed down and exported as one mono file."),
853 true) == wxID_CANCEL)
854 return false;
855 }
856 else if (exportedChannels == 2) {
857 if (ShowWarningDialog(pWindow,
858 wxT("MixStereo"),
859 XO("Your tracks will be mixed down and exported as one stereo file."),
860 true) == wxID_CANCEL)
861 return false;
862 }
863 else {
864 if (ShowWarningDialog(pWindow,
865 wxT("MixUnknownChannels"),
866 XO("Your tracks will be mixed down to one exported file according to the encoder settings."),
867 true) == wxID_CANCEL)
868 return false;
869 }
870 }
871 }
872 }
873 else
874 {
875 if (exportedChannels < 0)
876 exportedChannels = mPlugins[mFormat]->GetMaxChannels(mSubFormat);
877
880 exportedChannels,
881 NULL,
882 1,
883 XO("Advanced Mixing Options"));
884 if (prompt) {
885 if (md.ShowModal() != wxID_OK) {
886 return false;
887 }
888 }
889
890 mMixerSpec = std::make_unique<MixerSpec>(*(md.GetMixerSpec()));
891 mChannels = mMixerSpec->GetNumChannels();
892 }
893
894 return true;
895}
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:306
int mFormat
Definition: Export.h:254
unsigned mChannels
Definition: Export.h:260
bool mSelectedOnly
Definition: Export.h:261
unsigned mNumRight
Definition: Export.h:258
unsigned mNumLeft
Definition: Export.h:257
int mSubFormat
Definition: Export.h:255
unsigned mNumMono
Definition: Export.h:259
static EnumSetting< bool > ExportDownMixSetting
static ProjectWindow * Find(AudacityProject *pProject)
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:486

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 953 of file Export.cpp.

954{
955 ShuttleGui S(parent, eIsCreating);
956
957 S.StartStatic(XO("Format Options"), 1);
958 {
959 S.StartHorizontalLay(wxEXPAND);
960 {
961 mBook = S.Position(wxEXPAND).StartSimplebook();
962 {
963 for (const auto &pPlugin : mPlugins)
964 {
965 for (int j = 0; j < pPlugin->GetFormatCount(); j++)
966 {
967 // Name of simple book page is not displayed
968 S.StartNotebookPage( {} );
969 {
970 pPlugin->OptionsCreate(S, j);
971 }
972 S.EndNotebookPage();
973 }
974 }
975 }
976 S.EndSimplebook();
977
978 auto b = safenew wxBitmapButton(S.GetParent(), wxID_HELP, theTheme.Bitmap( bmpHelpIcon ));
979 b->SetToolTip( XO("Help").Translation() );
980 b->SetLabel(XO("Help").Translation()); // for screen readers
981 S.Position(wxALIGN_BOTTOM | wxRIGHT | wxBOTTOM).AddWindow(b);
982 }
983 S.EndHorizontalLay();
984 }
985 S.EndStatic();
986
987 return;
988}
#define safenew
Definition: MemoryX.h:10
@ eIsCreating
Definition: ShuttleGui.h:39
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:628
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 944 of file Export.cpp.

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

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 788 of file Export.cpp.

789{
790 int c = 0;
791 int mf = -1, msf = -1;
792 int i = -1;
793 for (const auto &pPlugin : mPlugins)
794 {
795 ++i;
796 for (int j = 0; j < pPlugin->GetFormatCount(); j++)
797 {
798 if (index == c)
799 {
800 mf = i;
801 msf = j;
802 }
803 c++;
804 }
805 }
806 // This shouldn't happen...
807 if (index >= c) {
808 return;
809 }
810
811#if defined(__WXMSW__)
812 mPlugins[mf]->DisplayOptions( FindProjectFrame( mProject ), msf);
813#else
814 mPlugins[mf]->DisplayOptions(mDialog, msf);
815#endif
816}
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:241

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

Here is the call graph for this function:

◆ ExamineTracks()

bool Exporter::ExamineTracks ( )
private

Definition at line 496 of file Export.cpp.

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

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 897 of file Export.cpp.

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

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 384 of file Export.cpp.

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

References mPlugins.

◆ GetAutoExportFileName()

wxFileName Exporter::GetAutoExportFileName ( )

Definition at line 1084 of file Export.cpp.

1084 {
1085 return mFilename;
1086}

References mFilename.

◆ GetAutoExportFilterIndex()

int Exporter::GetAutoExportFilterIndex ( )

Definition at line 1080 of file Export.cpp.

1080 {
1081 return mFormat;
1082}

References mFormat.

◆ GetAutoExportFormat()

int Exporter::GetAutoExportFormat ( )

Definition at line 1072 of file Export.cpp.

1072 {
1073 return mFormat;
1074}

References mFormat.

◆ GetAutoExportSubFormat()

int Exporter::GetAutoExportSubFormat ( )

Definition at line 1076 of file Export.cpp.

1076 {
1077 return mSubFormat;
1078}

References mSubFormat.

◆ GetFilename()

bool Exporter::GetFilename ( )
private

Definition at line 591 of file Export.cpp.

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

399{
400 return mPlugins;
401}

References mPlugins.

◆ OnExtensionChanged()

void Exporter::OnExtensionChanged ( wxCommandEvent &  evt)

Definition at line 367 of file Export.cpp.

368{
369 mDialog->SetFileExtension(evt.GetString().BeforeFirst(' ').Lower());
370}
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 990 of file Export.cpp.

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

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

Here is the call graph for this function:

◆ OnHelp()

void Exporter::OnHelp ( wxCommandEvent &  evt)

Definition at line 372 of file Export.cpp.

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

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 403 of file Export.cpp.

404{
405 // Save parms
406 mSelectedOnly = selectedOnly;
407 mT0 = t0;
408 mT1 = t1;
409
410 // Gather track information
411 if (!ExamineTracks()) {
412 return false;
413 }
414
415 // Ask user for file name
416 if (!GetFilename()) {
417 return false;
418 }
419
420 // Check for down mixing
421 if (!CheckMix()) {
422 return false;
423 }
424
425 // Let user edit MetaData
426 if (mPlugins[mFormat]->GetCanMetaData(mSubFormat)) {
428 XO("Edit Metadata Tags"), XO("Exported Tags"),
429 ProjectSettings::Get( *mProject ).GetShowId3Dialog())) {
430 return false;
431 }
432 }
433
434 // Ensure filename doesn't interfere with project files.
435 if (!CheckFilename()) {
436 return false;
437 }
438
439 // Export the tracks
440 std::unique_ptr<BasicUI::ProgressDialog> pDialog;
441 bool success = ExportTracks(pDialog);
442
443 // Get rid of mixerspec
444 mMixerSpec.reset();
445
446 if (success) {
447 if (mFormatName.empty()) {
448 gPrefs->Write(wxT("/Export/Format"), mPlugins[mFormat]->GetFormat(mSubFormat));
449 }
450
451 FileNames::UpdateDefaultPath(FileNames::Operation::Export, mFilename.GetPath());
452 }
453
454 return success;
455}
bool ExamineTracks()
Definition: Export.cpp:496
bool ExportTracks(std::unique_ptr< BasicUI::ProgressDialog > &progressDialog)
Definition: Export.cpp:897
bool CheckMix(bool prompt=true)
Definition: Export.cpp:818
bool GetFilename()
Definition: Export.cpp:591
bool CheckFilename()
Definition: Export.cpp:769
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 457 of file Export.cpp.

460{
461 std::unique_ptr<BasicUI::ProgressDialog> pDialog;
462 return Process(numChannels, type, filename, selectedOnly, t0, t1, pDialog);
463}
bool Process(bool selectedOnly, double t0, double t1)
Definition: Export.cpp:403

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 465 of file Export.cpp.

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

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 1028 of file Export.cpp.

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

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 1088 of file Export.cpp.

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

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 194 of file Export.h.

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

◆ SetFileDialogTitle()

void Exporter::SetFileDialogTitle ( const TranslatableString DialogTitle)

Definition at line 378 of file Export.cpp.

379{
380 // The default title is "Export File"
381 mFileDialogTitle = DialogTitle;
382}

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 249 of file Export.h.

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

◆ mBook

wxSimplebook* Exporter::mBook
private

Definition at line 263 of file Export.h.

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

◆ mChannels

unsigned Exporter::mChannels
private

Definition at line 260 of file Export.h.

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

◆ mDialog

FileDialogWrapper* Exporter::mDialog
private

Definition at line 241 of file Export.h.

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

◆ mFileDialogTitle

TranslatableString Exporter::mFileDialogTitle
private

Definition at line 242 of file Export.h.

Referenced by GetFilename(), and SetFileDialogTitle().

◆ mFilename

wxFileName Exporter::mFilename
private

◆ mFilterIndex

int Exporter::mFilterIndex
private

Definition at line 253 of file Export.h.

Referenced by GetFilename(), and ProcessFromTimerRecording().

◆ mFormat

int Exporter::mFormat
private

◆ mFormatName

FileExtension Exporter::mFormatName
private

Definition at line 240 of file Export.h.

Referenced by GetFilename(), and Process().

◆ mMixerSpec

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

Definition at line 244 of file Export.h.

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

◆ mNumLeft

unsigned Exporter::mNumLeft
private

Definition at line 257 of file Export.h.

Referenced by CheckMix(), and ExamineTracks().

◆ mNumMono

unsigned Exporter::mNumMono
private

Definition at line 259 of file Export.h.

Referenced by CheckMix(), and ExamineTracks().

◆ mNumRight

unsigned Exporter::mNumRight
private

Definition at line 258 of file Export.h.

Referenced by CheckMix(), and ExamineTracks().

◆ mNumSelected

int Exporter::mNumSelected
private

Definition at line 256 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 261 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 251 of file Export.h.

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

◆ mT1

double Exporter::mT1
private

Definition at line 252 of file Export.h.

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


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