28#include <wx/filename.h>
38#define initFnName "ExtensionModuleInit"
39#define versionFnName "GetVersionString"
42typedef wxChar * (*tVersionFn)();
47 mLib = std::make_unique<wxDynamicLibrary>();
59 if (
mLib !=
nullptr &&
mLib->IsLoaded())
72 auto ShortName = wxFileName(
mName).GetName();
74 XO(
"Unable to load the \"%s\" module.\n\nError: %s")
76 wxLogMessage(
wxT(
"Unable to load the module \"%s\". Error: %s"),
mName,
Error);
81 deferredErrorMessage.clear();
83 if (
mLib->IsLoaded()) {
92 auto ShortName = wxFileName(
mName).GetName();
94 if (!
mLib->Load(
mName, wxDL_NOW | wxDL_QUIET | wxDL_GLOBAL)) {
98 deferredErrorMessage = wxString(wxSysErrorMsg());
104 if (versionFn == NULL){
106 XO(
"The module \"%s\" does not provide a version string.\n\nIt will not be loaded.")
108 wxLogMessage(
wxT(
"The module \"%s\" does not provide a version string. It will not be loaded."),
mName);
113 wxString moduleVersion = versionFn();
114 if( moduleVersion != AUDACITY_VERSION_STRING) {
116 XO(
"The module \"%s\" is matched with Audacity version \"%s\".\n\nIt will not be loaded.")
117 .
Format(ShortName, moduleVersion));
118 wxLogMessage(
wxT(
"The module \"%s\" is matched with Audacity version \"%s\". It will not be loaded."),
mName, moduleVersion);
139 XO(
"The module \"%s\" failed to initialize.\n\nIt will not be loaded.")
141 wxLogMessage(
wxT(
"The module \"%s\" failed to initialize.\nIt will not be loaded."),
mName);
150 if (
mLib->IsLoaded()) {
160 if (
mLib->IsLoaded())
194 if(pluginProviderFactory)
195 list.push_back(std::move(pluginProviderFactory));
201 auto end = list.end(), iter = std::find(list.begin(),
end, pluginProviderFactory);
228 pathVar = wxGetenv(
wxT(
"AUDACITY_MODULES_PATH"));
229 if (!pathVar.empty())
232 for (
const auto &path : audacityPathList) {
233 wxString prefix = path + wxFILE_SEP_PATH;
241 #if defined(__WXMSW__)
252 wxString saveOldCWD = ::wxGetCwd();
253 auto cleanup =
finally([&]{ ::wxSetWorkingDirectory(saveOldCWD); });
254 for (
const auto &file : files) {
258 auto prefix = ::wxPathOnly(file);
259 ::wxSetWorkingDirectory(prefix);
263 wxString ShortName = wxFileName( file ).GetName();
264 if( checked.Index( ShortName,
false ) != wxNOT_FOUND )
266 checked.Add( ShortName );
269 if( decided.Index( ShortName,
false ) != wxNOT_FOUND )
290 auto msg =
XO(
"Module \"%s\" found.").Format( ShortName );
291 msg +=
XO(
"\n\nOnly use modules from trusted sources");
296 XO(
"Audacity Module Loader"),
299 XO(
"Try and load this module?"),
307 decided.Add( ShortName );
316 auto umodule = std::make_unique<Module>(file);
317 if (umodule->Load(
Error))
319 decided.Add( ShortName );
320 auto module = umodule.get();
322 if (!module->HasDispatch())
324 auto ShortName = wxFileName(file).GetName();
326 XO(
"The module \"%s\" does not provide any of the required functions.\n\nIt will not be loaded.")
328 wxLogMessage(
wxT(
"The module \"%s\" does not provide any of the required functions. It will not be loaded."), file);
339 else if (!
Error.empty()) {
344 errors.emplace_back( std::move( umodule ),
Error );
357 size_t numDecided = 0;
362 numDecided = decided.size();
366 while ( errors.size() && numDecided < decided.size() );
369 for (
const auto &pair : errors ) {
370 auto &pModule = pair.first;
371 pModule->ShowLoadFailureError(pair.second);
379 for (
const auto &module:
mModules) {
380 module->Dispatch(type);
417 mInstance = std::make_unique<ModuleManager>();
429 return wxString::Format(
wxT(
"%s_%s_%s_%s_%s"),
448 wxString pathVar = wxString::FromUTF8(getenv(
"AUDACITY_MODULES_PATH"));
450 if (!pathVar.empty())
459#if defined(__WXMSW__)
461#elif defined(__WXMAC__)
467 for (
const auto &path : provList )
478 auto pluginProvider = pluginProviderFactory();
480 if (pluginProvider && pluginProvider->Initialize()) {
483 auto id =
GetID(handle.get());
522 return iter->second->LoadPlugin(path);
530 return mProviders[providerId]->CheckPluginExist(path);
542 wxFileName lib(path);
543 if (lib.FileExists() || lib.DirExists())
Toolkit-neutral facade for basic user interface services.
wxString PluginPath
type alias for identifying a Plugin supplied by a module, each module defining its own interpretation...
#define ModuleDispatchName
void RegisterProviderFactory(PluginProviderFactory pluginProviderFactory)
static BasicUI::MessageBoxResult DoMessageBox(const TranslatableString &msg)
void UnregisterProviderFactory(PluginProviderFactory pluginProviderFactory)
std::vector< PluginProviderFactory > BuiltinProviderList
std::unique_ptr< PluginProvider >(*)() PluginProviderFactory
int(* fnModuleDispatch)(ModuleDispatchTypes type)
Generalized interface for discovery of plug-ins for one protocol.
std::vector< TranslatableString > TranslatableStrings
virtual PluginPath GetPath() const =0
virtual VendorSymbol GetVendor() const =0
virtual ComponentInterfaceSymbol GetSymbol() const =0
const wxString & Internal() const
void ShowLoadFailureError(const wxString &Error)
fnModuleDispatch mDispatch
std::unique_ptr< wxDynamicLibrary > mLib
Module(const FilePath &name)
void * GetSymbol(const wxString &name)
bool Load(wxString &deferredErrorMessage)
int Dispatch(ModuleDispatchTypes type)
std::vector< std::pair< std::unique_ptr< Module >, wxString > > DelayedErrors
static void FindModules(FilePaths &files)
static std::unique_ptr< ModuleManager > mInstance
PluginProviderHandlesMap mProviders
static ModuleManager & Get()
static wxString GetPluginTypeString()
void InitializeBuiltins()
std::unique_ptr< ComponentInterface > LoadPlugin(const PluginID &provider, const PluginPath &path)
int Dispatch(ModuleDispatchTypes type)
static PluginID GetID(const PluginProvider *provider)
PluginProvider * CreateProviderInstance(const PluginID &provider, const PluginPath &path)
bool IsProviderValid(const PluginID &provider, const PluginPath &path)
bool RegisterEffectPlugin(const PluginID &provider, const PluginPath &path, TranslatableString &errMsg)
bool CheckPluginExist(const PluginID &providerId, const PluginPath &path)
std::vector< std::unique_ptr< Module > > mModules
static void TryLoadModules(const FilePaths &files, FilePaths &decided, DelayedErrors &errors)
static const PluginID & DefaultRegistrationCallback(PluginProvider *provider, ComponentInterface *ident)
std::unique_ptr< PluginProvider > mPtr
~PluginProviderUniqueHandle()
Holds a msgid for the translation catalog; may also bind format arguments.
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
int ShowMultiDialog(const TranslatableString &message, const TranslatableString &title, const TranslatableStrings &buttons, const ManualPageID &helpPage, const TranslatableString &boxMsg, bool log)
Display a dialog with radio buttons.
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
FILES_API void AddUniquePathToPathList(const FilePath &path, FilePaths &pathList)
FILES_API void FindFilesInPathList(const wxString &pattern, const FilePaths &pathList, FilePaths &results, int flags=wxDIR_FILES)
FILES_API void AddMultiPathsToPathList(const wxString &multiPathString, FilePaths &pathList)
FILES_API FilePath ModulesDir()
FILES_API const FilePaths & AudacityPathList()
A list of directories that should be searched for Audacity files (plug-ins, help files,...
MODULE_MANAGER_API void SetModuleStatus(const FilePath &fname, int iStatus)
MODULE_MANAGER_API int GetModuleStatus(const FilePath &fname)
BuiltinProviderList & builtinProviderList()
const char * end(const char *str) noexcept
MessageBoxOptions && Caption(TranslatableString caption_) &&