diff --git a/src/export/Export.cpp b/src/export/Export.cpp index f4917432d..6e7880491 100644 --- a/src/export/Export.cpp +++ b/src/export/Export.cpp @@ -282,6 +282,24 @@ BEGIN_EVENT_TABLE(Exporter, wxEvtHandler) END_EVENT_TABLE() namespace { +const auto PathStart = wxT("Exporters"); + +static Registry::GroupItem &sRegistry() +{ + static Registry::TransparentGroupItem<> registry{ PathStart }; + return registry; +} + +struct ExporterItem final : Registry::SingleItem { + ExporterItem( + const Identifier &id, const Exporter::ExportPluginFactory &factory ) + : SingleItem{ id } + , mFactory{ factory } + {} + + Exporter::ExportPluginFactory mFactory; +}; + using ExportPluginFactories = std::vector< Exporter::ExportPluginFactory >; ExportPluginFactories &sFactories() { @@ -291,15 +309,24 @@ namespace { } Exporter::RegisteredExportPlugin::RegisteredExportPlugin( - const ExportPluginFactory &factory ) + const Identifier &id, + const ExportPluginFactory &factory, + const Registry::Placement &placement ) { if ( factory ) - sFactories().emplace_back( factory ); + Registry::RegisterItem( sRegistry(), placement, + std::make_unique< ExporterItem >( id, factory ) ); } Exporter::Exporter( AudacityProject &project ) : mProject{ &project } { + using namespace Registry; + static OrderingPreferenceInitializer init{ + PathStart, + { {wxT(""), wxT("PCM,MP3,OGG,FLAC,MP2,CommandLine,FFmpeg") } }, + }; + mMixerSpec = NULL; mBook = NULL; @@ -307,15 +334,25 @@ Exporter::Exporter( AudacityProject &project ) for ( const auto &factory : sFactories() ) mPlugins.emplace_back( factory() ); - // The factories were pushed on the array at static initialization time in an - // unspecified sequence. Sort according to the sequence numbers the plugins - // report to make the order determinate. - std::sort( mPlugins.begin(), mPlugins.end(), - []( const ExportPluginArray::value_type &a, - const ExportPluginArray::value_type &b ){ - return a->SequenceNumber() < b->SequenceNumber(); + struct MyVisitor final : Visitor { + MyVisitor() + { + // visit the registry to collect the plug-ins properly + // sorted + TransparentGroupItem<> top{ PathStart }; + Registry::Visit( *this, &top, &sRegistry() ); } - ); + + void Visit( SingleItem &item, const Path &path ) override + { + mPlugins.emplace_back( + static_cast( item ).mFactory() ); + } + + ExportPluginArray mPlugins; + } visitor; + + mPlugins.swap( visitor.mPlugins ); SetFileDialogTitle( XO("Export Audio") ); } diff --git a/src/export/Export.h b/src/export/Export.h index d886e7d96..dc0ff8d17 100644 --- a/src/export/Export.h +++ b/src/export/Export.h @@ -19,6 +19,8 @@ #include "../widgets/wxPanelWrapper.h" // to inherit #include "../FileNames.h" // for FileTypes +#include "../commands/CommandManager.h" // for Registry::Placement + class wxArrayString; class FileDialogWrapper; class wxFileCtrlEvent; @@ -132,8 +134,6 @@ public: const Tags *metadata = NULL, int subformat = 0) = 0; - virtual unsigned SequenceNumber() const = 0; - protected: std::unique_ptr CreateMixer(const TrackList &tracks, bool selectionOnly, @@ -174,7 +174,10 @@ public: // to have some fresh state variables each time export begins again // and to compute translated strings for the current locale struct RegisteredExportPlugin{ - RegisteredExportPlugin( const ExportPluginFactory& ); + RegisteredExportPlugin( + const Identifier &id, // an internal string naming the plug-in + const ExportPluginFactory&, + const Registry::Placement &placement = { wxEmptyString, {} } ); }; static bool DoEditMetadata(AudacityProject &project, diff --git a/src/export/ExportCL.cpp b/src/export/ExportCL.cpp index 49a9d6a4f..d29c3ff87 100644 --- a/src/export/ExportCL.cpp +++ b/src/export/ExportCL.cpp @@ -310,8 +310,6 @@ public: MixerSpec *mixerSpec = NULL, const Tags *metadata = NULL, int subformat = 0) override; - - virtual unsigned SequenceNumber() const override { return 60; } }; ExportCL::ExportCL() @@ -567,5 +565,6 @@ void ExportCL::OptionsCreate(ShuttleGui &S, int format) S.AddWindow( safenew ExportCLOptions{ S.GetParent(), format } ); } -static Exporter::RegisteredExportPlugin -sRegisteredPlugin{ []{ return std::make_unique< ExportCL >(); } }; +static Exporter::RegisteredExportPlugin sRegisteredPlugin{ "CommandLine", + []{ return std::make_unique< ExportCL >(); } +}; diff --git a/src/export/ExportFFmpeg.cpp b/src/export/ExportFFmpeg.cpp index 4376be31f..9de4a4169 100644 --- a/src/export/ExportFFmpeg.cpp +++ b/src/export/ExportFFmpeg.cpp @@ -152,8 +152,6 @@ public: const Tags *metadata = NULL, int subformat = 0) override; - virtual unsigned SequenceNumber() const override { return 70; } - private: AVOutputFormat * mEncFormatDesc{}; // describes our output file to libavformat @@ -1141,8 +1139,9 @@ void ExportFFmpeg::OptionsCreate(ShuttleGui &S, int format) ExportPlugin::OptionsCreate(S, format); } -static Exporter::RegisteredExportPlugin -sRegisteredPlugin{ []{ return std::make_unique< ExportFFmpeg >(); } }; +static Exporter::RegisteredExportPlugin sRegisteredPlugin{ "FFmpeg", + []{ return std::make_unique< ExportFFmpeg >(); } +}; #endif diff --git a/src/export/ExportFLAC.cpp b/src/export/ExportFLAC.cpp index d78ffb481..3c4e4741e 100644 --- a/src/export/ExportFLAC.cpp +++ b/src/export/ExportFLAC.cpp @@ -224,8 +224,6 @@ public: const Tags *metadata = NULL, int subformat = 0) override; - virtual unsigned SequenceNumber() const override { return 40; } - private: bool GetMetadata(AudacityProject *project, const Tags *tags); @@ -474,8 +472,9 @@ bool ExportFLAC::GetMetadata(AudacityProject *project, const Tags *tags) return true; } -static Exporter::RegisteredExportPlugin -sRegisteredPlugin{ []{ return std::make_unique< ExportFLAC >(); } }; +static Exporter::RegisteredExportPlugin sRegisteredPlugin{ "FLAC", + []{ return std::make_unique< ExportFLAC >(); } +}; #endif // USE_LIBFLAC diff --git a/src/export/ExportMP2.cpp b/src/export/ExportMP2.cpp index af9476e86..f3472d020 100644 --- a/src/export/ExportMP2.cpp +++ b/src/export/ExportMP2.cpp @@ -217,8 +217,6 @@ public: const Tags *metadata = NULL, int subformat = 0) override; - virtual unsigned SequenceNumber() const override { return 50; } - private: int AddTags(AudacityProject *project, ArrayOf &buffer, bool *endOfFile, const Tags *tags); @@ -498,8 +496,9 @@ void ExportMP2::AddFrame(struct id3_tag *tp, const wxString & n, const wxString } #endif -static Exporter::RegisteredExportPlugin -sRegisteredPlugin{ []{ return std::make_unique< ExportMP2 >(); } }; +static Exporter::RegisteredExportPlugin sRegisteredPlugin{ "MP2", + []{ return std::make_unique< ExportMP2 >(); } +}; #endif // #ifdef USE_LIBTWOLAME diff --git a/src/export/ExportMP3.cpp b/src/export/ExportMP3.cpp index 5e081e5f0..83a98ab47 100644 --- a/src/export/ExportMP3.cpp +++ b/src/export/ExportMP3.cpp @@ -1687,8 +1687,6 @@ public: const Tags *metadata = NULL, int subformat = 0) override; - virtual unsigned SequenceNumber() const override { return 20; } - private: int AskResample(int bitrate, int rate, int lowrate, int highrate); @@ -2199,8 +2197,9 @@ void ExportMP3::AddFrame(struct id3_tag *tp, const wxString & n, const wxString } #endif -static Exporter::RegisteredExportPlugin -sRegisteredPlugin{ []{ return std::make_unique< ExportMP3 >(); } }; +static Exporter::RegisteredExportPlugin sRegisteredPlugin{ "MP3", + []{ return std::make_unique< ExportMP3 >(); } +}; //---------------------------------------------------------------------------- // Return library version diff --git a/src/export/ExportOGG.cpp b/src/export/ExportOGG.cpp index 9d2f2450b..41b4a5c58 100644 --- a/src/export/ExportOGG.cpp +++ b/src/export/ExportOGG.cpp @@ -143,8 +143,6 @@ public: const Tags *metadata = NULL, int subformat = 0) override; - virtual unsigned SequenceNumber() const override { return 30; } - private: bool FillComment(AudacityProject *project, vorbis_comment *comment, const Tags *metadata); @@ -398,8 +396,9 @@ bool ExportOGG::FillComment(AudacityProject *project, vorbis_comment *comment, c return true; } -static Exporter::RegisteredExportPlugin -sRegisteredPlugin{ []{ return std::make_unique< ExportOGG >(); } }; +static Exporter::RegisteredExportPlugin sRegisteredPlugin{ "OGG", + []{ return std::make_unique< ExportOGG >(); } +}; #endif // USE_LIBVORBIS diff --git a/src/export/ExportPCM.cpp b/src/export/ExportPCM.cpp index 585d65fd5..8e78af1c5 100644 --- a/src/export/ExportPCM.cpp +++ b/src/export/ExportPCM.cpp @@ -342,8 +342,6 @@ public: FileExtension GetExtension(int index) override; bool CheckFileName(wxFileName &filename, int format) override; - virtual unsigned SequenceNumber() const override { return 10; } - private: void ReportTooBigError(wxWindow * pParent); ArrayOf AdjustString(const wxString & wxStr, int sf_format); @@ -971,5 +969,6 @@ bool ExportPCM::CheckFileName(wxFileName &filename, int format) return ExportPlugin::CheckFileName(filename, format); } -static Exporter::RegisteredExportPlugin -sRegisteredPlugin{ []{ return std::make_unique< ExportPCM >(); } }; +static Exporter::RegisteredExportPlugin sRegisteredPlugin{ "PCM", + []{ return std::make_unique< ExportPCM >(); } +};