mirror of
https://github.com/cookiengineer/audacity
synced 2025-11-23 17:30:17 +01:00
Crude way to let modules depend on others: multiple load passes...
... Repeatedly pass through the list of modules that need to be opened, so long as the list is not empty and at least one module loaded in the last pass. This discovers dependencies of modules on other modules, avoiding the need to describe the dependencies and make one pass in some topologically sorted order. Which would be smarter, but would require much other work.
This commit is contained in:
@@ -85,8 +85,8 @@ wxWindow * MakeHijackPanel()
|
||||
static tpRegScriptServerFunc scriptFn;
|
||||
|
||||
Module::Module(const FilePath & name)
|
||||
: mName{ name }
|
||||
{
|
||||
mName = name;
|
||||
mLib = std::make_unique<wxDynamicLibrary>();
|
||||
mDispatch = NULL;
|
||||
}
|
||||
@@ -119,6 +119,9 @@ bool Module::Load(wxString &deferredErrorMessage)
|
||||
auto ShortName = wxFileName(mName).GetName();
|
||||
|
||||
if (!mLib->Load(mName, wxDL_NOW | wxDL_QUIET | wxDL_GLOBAL)) {
|
||||
// For this failure path, only, there is a possiblity of retrial
|
||||
// after some other dependency of this module is loaded. So the
|
||||
// error is not immediately reported.
|
||||
deferredErrorMessage = wxString(wxSysErrorMsg());
|
||||
return false;
|
||||
}
|
||||
@@ -265,7 +268,8 @@ void ModuleManager::FindModules(FilePaths &files)
|
||||
#endif
|
||||
}
|
||||
|
||||
void ModuleManager::TryLoadModules(const FilePaths &files)
|
||||
void ModuleManager::TryLoadModules(
|
||||
const FilePaths &files, FilePaths &decided, DelayedErrors &errors)
|
||||
{
|
||||
FilePaths checked;
|
||||
wxString saveOldCWD = ::wxGetCwd();
|
||||
@@ -284,6 +288,10 @@ void ModuleManager::TryLoadModules(const FilePaths &files)
|
||||
continue;
|
||||
checked.Add( ShortName );
|
||||
|
||||
// Skip if a previous pass through this function decided it already
|
||||
if( decided.Index( ShortName, false ) != wxNOT_FOUND )
|
||||
continue;
|
||||
|
||||
#ifdef EXPERIMENTAL_MODULE_PREFS
|
||||
int iModuleStatus = ModulePrefs::GetModuleStatus( file );
|
||||
if( iModuleStatus == kModuleDisabled )
|
||||
@@ -323,6 +331,7 @@ void ModuleManager::TryLoadModules(const FilePaths &files)
|
||||
}
|
||||
#endif
|
||||
if(action == 1){ // "No"
|
||||
decided.Add( ShortName );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -336,6 +345,7 @@ void ModuleManager::TryLoadModules(const FilePaths &files)
|
||||
auto umodule = std::make_unique<Module>(file);
|
||||
if (umodule->Load(Error)) // it will get rejected if there are version problems
|
||||
{
|
||||
decided.Add( ShortName );
|
||||
auto module = umodule.get();
|
||||
|
||||
{
|
||||
@@ -376,7 +386,11 @@ void ModuleManager::TryLoadModules(const FilePaths &files)
|
||||
}
|
||||
}
|
||||
else if (!Error.empty()) {
|
||||
umodule->ShowLoadFailureError(Error);
|
||||
// Module is not yet decided in this pass.
|
||||
// Maybe it depends on another which has not yet been loaded.
|
||||
// But don't take the kModuleAsk path again in a later pass.
|
||||
ModulePrefs::SetModuleStatus( file, kModuleEnabled );
|
||||
errors.emplace_back( std::move( umodule ), Error );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -387,7 +401,25 @@ void ModuleManager::Initialize()
|
||||
FilePaths files;
|
||||
FindModules(files);
|
||||
|
||||
TryLoadModules(files);
|
||||
FilePaths decided;
|
||||
DelayedErrors errors;
|
||||
size_t numDecided = 0;
|
||||
|
||||
// Multiple passes give modules multiple chances to load in case they
|
||||
// depend on some other module not yet loaded
|
||||
do {
|
||||
numDecided = decided.size();
|
||||
errors.clear();
|
||||
TryLoadModules(files, decided, errors);
|
||||
}
|
||||
while ( errors.size() && numDecided < decided.size() );
|
||||
|
||||
// Only now show accumulated errors of modules that failed to load
|
||||
for ( const auto &pair : errors ) {
|
||||
auto &pModule = pair.first;
|
||||
pModule->ShowLoadFailureError(pair.second);
|
||||
ModulePrefs::SetModuleStatus( pModule->GetName(), kModuleFailed );
|
||||
}
|
||||
|
||||
// After loading all the modules, we may have a registered scripting function.
|
||||
if(scriptFn)
|
||||
|
||||
@@ -47,9 +47,10 @@ public:
|
||||
bool HasDispatch() { return mDispatch != NULL; };
|
||||
int Dispatch(ModuleDispatchTypes type);
|
||||
void * GetSymbol(const wxString &name);
|
||||
const FilePath &GetName() const { return mName; }
|
||||
|
||||
private:
|
||||
FilePath mName;
|
||||
const FilePath mName;
|
||||
std::unique_ptr<wxDynamicLibrary> mLib;
|
||||
fnModuleDispatch mDispatch;
|
||||
};
|
||||
@@ -78,7 +79,10 @@ public:
|
||||
|
||||
private:
|
||||
static void FindModules(FilePaths &files);
|
||||
static void TryLoadModules(const FilePaths &files);
|
||||
using DelayedErrors =
|
||||
std::vector< std::pair< std::unique_ptr<Module>, wxString > >;
|
||||
static void TryLoadModules(
|
||||
const FilePaths &files, FilePaths &decided, DelayedErrors &errors);
|
||||
|
||||
public:
|
||||
void Initialize();
|
||||
|
||||
Reference in New Issue
Block a user