diff --git a/src/BatchCommands.cpp b/src/BatchCommands.cpp index 60dc787e1..141f84c75 100644 --- a/src/BatchCommands.cpp +++ b/src/BatchCommands.cpp @@ -308,17 +308,15 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project ) PluginManager & pm = PluginManager::Get(); EffectManager & em = EffectManager::Get(); { - const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeEffect|PluginTypeAudacityCommand); - while (plug) - { - auto command = em.GetCommandIdentifier(plug->GetID()); + for (auto &plug + : pm.PluginsOfType(PluginTypeEffect|PluginTypeAudacityCommand)) { + auto command = em.GetCommandIdentifier(plug.GetID()); if (!command.empty()) commands.push_back( { - { command, plug->GetSymbol().Msgid() }, - plug->GetPluginType() == PluginTypeEffect ? + { command, plug.GetSymbol().Msgid() }, + plug.GetPluginType() == PluginTypeEffect ? XO("Effect") : XO("Menu Command (With Parameters)") } ); - plug = pm.GetNextPlugin(PluginTypeEffect|PluginTypeAudacityCommand); } } @@ -608,19 +606,12 @@ bool MacroCommands::HandleTextualCommand( CommandManager &commandManager, // Not one of the singleton commands. // We could/should try all the list-style commands. // instead we only try the effects. - PluginManager & pm = PluginManager::Get(); EffectManager & em = EffectManager::Get(); - const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeEffect); - while (plug) - { - if (em.GetCommandIdentifier(plug->GetID()) == Str) - { + for (auto &plug : PluginManager::Get().PluginsOfType(PluginTypeEffect)) + if (em.GetCommandIdentifier(plug.GetID()) == Str) return EffectUI::DoEffect( - plug->GetID(), context, + plug.GetID(), context, EffectManager::kConfigured); - } - plug = pm.GetNextPlugin(PluginTypeEffect); - } return false; } diff --git a/src/PluginManager.cpp b/src/PluginManager.cpp index 42c613bca..d4600e322 100644 --- a/src/PluginManager.cpp +++ b/src/PluginManager.cpp @@ -627,15 +627,10 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S) } PluginManager & pm = PluginManager::Get(); - for (PluginMap::iterator iter = pm.mPlugins.begin(); iter != pm.mPlugins.end(); ++iter) - { - PluginDescriptor & plug = iter->second; - + for (auto &plug : pm.AllPlugins()) { PluginType plugType = plug.GetPluginType(); if (plugType != PluginTypeEffect && plugType != PluginTypeStub) - { continue; - } const auto &path = plug.GetPath(); ItemData & item = mItems[path]; // will create NEW entry @@ -1025,10 +1020,9 @@ void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt)) if (mm.RegisterEffectPlugin(item.plugs[j]->GetProviderID(), path, errMsg)) { - for (size_t k = 0, cntk = item.plugs.size(); k < cntk; k++) - { - pm.mPlugins.erase(item.plugs[k]->GetProviderID() + wxT("_") + path); - } + for (auto plug : item.plugs) + pm.UnregisterPlugin( + plug->GetProviderID() + wxT("_") + path); // Bug 1893. We've found a provider that works. // Error messages from any that failed are no longer useful. errMsgs = {}; @@ -1047,19 +1041,14 @@ void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt)) XO("Effect or Command at %s failed to register:\n%s") .Format( path, errMsgs ) ); } - else if (item.state == STATE_New) - { - for (size_t j = 0, cnt = item.plugs.size(); j < cnt; j++) - { - item.plugs[j]->SetValid(false); - } + else if (item.state == STATE_New) { + for (auto plug : item.plugs) + plug->SetValid(false); } - else if (item.state != STATE_New) - { - for (size_t j = 0, cnt = item.plugs.size(); j < cnt; j++) - { - item.plugs[j]->SetEnabled(item.state == STATE_Enabled); - item.plugs[j]->SetValid(item.valid); + else if (item.state != STATE_New) { + for (auto plug : item.plugs) { + plug->SetEnabled(item.state == STATE_Enabled); + plug->SetValid(item.valid); } } } @@ -1388,7 +1377,7 @@ const PluginID &PluginManagerInterface::AudacityCommandRegistrationCallback( return empty; } -RegistryPath PluginManager::GetPluginEnabledSetting( const PluginID &ID ) +RegistryPath PluginManager::GetPluginEnabledSetting( const PluginID &ID ) const { auto pPlugin = GetPlugin( ID ); if ( pPlugin ) @@ -1397,7 +1386,7 @@ RegistryPath PluginManager::GetPluginEnabledSetting( const PluginID &ID ) } RegistryPath PluginManager::GetPluginEnabledSetting( - const PluginDescriptor &desc ) + const PluginDescriptor &desc ) const { switch ( desc.GetPluginType() ) { case PluginTypeModule: { @@ -1802,12 +1791,9 @@ bool PluginManager::DropFile(const wxString &fileName) auto &mm = ModuleManager::Get(); const wxFileName src{ fileName }; - for (const PluginDescriptor *plug = GetFirstPlugin(PluginTypeModule); - plug; - plug = GetNextPlugin(PluginTypeModule)) - { + for (auto &plug : PluginsOfType(PluginTypeModule)) { auto module = static_cast - (mm.CreateProviderInstance(plug->GetID(), plug->GetPath())); + (mm.CreateProviderInstance(plug.GetID(), plug.GetPath())); if (! module) continue; @@ -2483,8 +2469,6 @@ const PluginID & PluginManager::RegisterPlugin( return plug.GetID(); } -// Here solely for the purpose of Nyquist Workbench until -// a better solution is devised. void PluginManager::UnregisterPlugin(const PluginID & ID) { mPlugins.erase(ID); @@ -2496,7 +2480,7 @@ int PluginManager::GetPluginCount(PluginType type) return pair.second.GetPluginType() == type; }); } -const PluginDescriptor *PluginManager::GetPlugin(const PluginID & ID) +const PluginDescriptor *PluginManager::GetPlugin(const PluginID & ID) const { if (auto iter = mPlugins.find(ID); iter == mPlugins.end()) return nullptr; @@ -2504,93 +2488,57 @@ const PluginDescriptor *PluginManager::GetPlugin(const PluginID & ID) return &iter->second; } -const PluginDescriptor *PluginManager::GetFirstPlugin(int type) +void PluginManager::Iterator::Advance(bool incrementing) { - for (mPluginsIter = mPlugins.begin(); mPluginsIter != mPlugins.end(); ++mPluginsIter) - { - PluginDescriptor & plug = mPluginsIter->second; - PluginType plugType = plug.GetPluginType(); - if( plug.IsValid() && plug.IsEnabled() && ((plugType & type) != 0)) - { - bool familyEnabled = true; - if( (plugType & PluginTypeEffect) != 0) { + const auto end = mPm.mPlugins.end(); + if (incrementing && mIterator != end) + ++mIterator; + bool all = mPluginType == PluginTypeNone && mEffectType == EffectTypeNone; + for (; mIterator != end; ++mIterator) { + auto &plug = mIterator->second; + if (!all && !(plug.IsValid() && plug.IsEnabled())) + continue; + auto plugType = plug.GetPluginType(); + if ((mPluginType == PluginTypeNone || (plugType & mPluginType)) && + (mEffectType == EffectTypeNone || plug.GetEffectType() == mEffectType)) { + if (!all && (plugType & PluginTypeEffect)) { // This preference may be written by EffectsPrefs - auto setting = GetPluginEnabledSetting( plug ); - familyEnabled = setting.empty() - ? true - : gPrefs->Read( setting, true ); + auto setting = mPm.GetPluginEnabledSetting( plug ); + if (!(setting.empty() || gPrefs->Read( setting, true ))) + continue; } - if (familyEnabled) - return &mPluginsIter->second; + // Pause iteration at this match + break; } } - - return NULL; } -const PluginDescriptor *PluginManager::GetNextPlugin(int type) -{ - while (++mPluginsIter != mPlugins.end()) - { - PluginDescriptor & plug = mPluginsIter->second; - PluginType plugType = plug.GetPluginType(); - if( plug.IsValid() && plug.IsEnabled() && ((plugType & type) != 0)) - { - bool familyEnabled = true; - if( (plugType & PluginTypeEffect) != 0) { - // This preference may be written by EffectsPrefs - auto setting = GetPluginEnabledSetting( plug ); - familyEnabled = setting.empty() - ? true - : gPrefs->Read( setting, true ); - } - if (familyEnabled) - return &mPluginsIter->second; - } - } - - return NULL; +PluginManager::Iterator::Iterator(PluginManager &manager) +: mPm{ manager } +, mIterator{ manager.mPlugins.begin() } +{ } -const PluginDescriptor *PluginManager::GetFirstPluginForEffectType(EffectType type) +PluginManager::Iterator::Iterator(PluginManager &manager, int type) +: mPm{ manager } +, mIterator{ manager.mPlugins.begin() } +, mPluginType{ type } { - for (mPluginsIter = mPlugins.begin(); mPluginsIter != mPlugins.end(); ++mPluginsIter) - { - PluginDescriptor & plug = mPluginsIter->second; - - bool familyEnabled; - // This preference may be written by EffectsPrefs - auto setting = GetPluginEnabledSetting( plug ); - familyEnabled = setting.empty() - ? true - : gPrefs->Read( setting, true ); - if (plug.IsValid() && plug.IsEnabled() && plug.GetEffectType() == type && familyEnabled) - { - return &plug; - } - } - - return NULL; + Advance(false); } -const PluginDescriptor *PluginManager::GetNextPluginForEffectType(EffectType type) +PluginManager::Iterator::Iterator(PluginManager &manager, EffectType type) +: mPm{ manager } +, mIterator{ manager.mPlugins.begin() } +, mEffectType{ type } { - while (++mPluginsIter != mPlugins.end()) - { - PluginDescriptor & plug = mPluginsIter->second; - bool familyEnabled; - // This preference may be written by EffectsPrefs - auto setting = GetPluginEnabledSetting( plug ); - familyEnabled = setting.empty() - ? true - : gPrefs->Read( setting, true ); - if (plug.IsValid() && plug.IsEnabled() && plug.GetEffectType() == type && familyEnabled) - { - return &plug; - } - } + Advance(false); +} - return NULL; +auto PluginManager::Iterator::operator ++() -> Iterator & +{ + Advance(true); + return *this; } bool PluginManager::IsPluginEnabled(const PluginID & ID) diff --git a/src/PluginManager.h b/src/PluginManager.h index 817fa3412..81a27e388 100644 --- a/src/PluginManager.h +++ b/src/PluginManager.h @@ -30,8 +30,7 @@ class FileConfig; // /////////////////////////////////////////////////////////////////////////////// -typedef enum -{ +typedef enum : unsigned { PluginTypeNone = 0, // 2.1.0 placeholder entries...not used by 2.1.1 or greater PluginTypeStub =1, // Used for plugins that have not yet been registered PluginTypeEffect =1<<1, @@ -173,8 +172,8 @@ class AUDACITY_DLL_API PluginManager final : public PluginManagerInterface { public: - RegistryPath GetPluginEnabledSetting( const PluginID &ID ); - RegistryPath GetPluginEnabledSetting( const PluginDescriptor &desc ); + RegistryPath GetPluginEnabledSetting( const PluginID &ID ) const; + RegistryPath GetPluginEnabledSetting( const PluginDescriptor &desc ) const; // PluginManagerInterface implementation @@ -246,13 +245,42 @@ public: static wxString GetPluginTypeString(PluginType type); int GetPluginCount(PluginType type); - const PluginDescriptor *GetPlugin(const PluginID & ID); + const PluginDescriptor *GetPlugin(const PluginID & ID) const; - const PluginDescriptor *GetFirstPlugin(int type); // possible or of several PlugInTypes. - const PluginDescriptor *GetNextPlugin( int type); + //! @name iteration over plugins of certain types, supporting range-for syntax + //! @{ + class Iterator { + public: + //! Iterates all, even disabled + explicit Iterator(PluginManager &manager); + //! Iterates only enabled and matching plugins, with family enabled too if an effect + Iterator(PluginManager &manager, + int pluginType //!< bitwise or of values in PluginType + ); + //! Iterates only enabled and matching effects, with family enabled too + Iterator(PluginManager &manager, EffectType type); + bool operator != (int) const { + return mIterator != mPm.mPlugins.end(); + } + Iterator &operator ++ (); + auto &operator *() const { return mIterator->second; } + private: + void Advance(bool incrementing); + const PluginManager &mPm; + PluginMap::iterator mIterator; + EffectType mEffectType{ EffectTypeNone }; + int mPluginType{ PluginTypeNone }; + }; + struct Range { + Iterator first; + Iterator begin() const { return first; } + int end() const { return 0; } + }; - const PluginDescriptor *GetFirstPluginForEffectType(EffectType type); - const PluginDescriptor *GetNextPluginForEffectType(EffectType type); + Range AllPlugins() { return { Iterator{ *this } }; } + Range PluginsOfType(int type) { return { Iterator{ *this, type } }; } + Range EffectsOfType(EffectType type) { return { Iterator{ *this, type } }; } + //! @} bool IsPluginEnabled(const PluginID & ID); void EnablePlugin(const PluginID & ID, bool enable); @@ -267,17 +295,19 @@ public: //! Used only by Nyquist Workbench module const PluginID & RegisterPlugin( std::unique_ptr effect, PluginType type ); - //! Used only by Nyquist Workbench module void UnregisterPlugin(const PluginID & ID); + //! Load from preferences + void Load(); + //! Save to preferences + void Save(); + private: // private! Use Get() PluginManager(); ~PluginManager(); - void Load(); void LoadGroup(FileConfig *pRegistry, PluginType type); - void Save(); void SaveGroup(FileConfig *pRegistry, PluginType type); PluginDescriptor & CreatePlugin(const PluginID & id, ComponentInterface *ident, PluginType type); @@ -324,9 +354,6 @@ private: int mCurrentIndex; PluginMap mPlugins; - PluginMap::iterator mPluginsIter; - - friend class PluginRegistrationDialog; }; // Defining these special names in the low-level PluginManager.h diff --git a/src/commands/GetInfoCommand.cpp b/src/commands/GetInfoCommand.cpp index a99137dd9..289e12042 100644 --- a/src/commands/GetInfoCommand.cpp +++ b/src/commands/GetInfoCommand.cpp @@ -416,14 +416,12 @@ bool GetInfoCommand::SendCommands(const CommandContext &context, int flags ) PluginManager & pm = PluginManager::Get(); EffectManager & em = EffectManager::Get(); { - const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeEffect | PluginTypeAudacityCommand); - while (plug) - { - auto command = em.GetCommandIdentifier(plug->GetID()); + for (auto &plug + : pm.PluginsOfType(PluginTypeEffect | PluginTypeAudacityCommand)) { + auto command = em.GetCommandIdentifier(plug.GetID()); if (!command.empty()){ - em.GetCommandDefinition( plug->GetID(), context, flags ); + em.GetCommandDefinition( plug.GetID(), context, flags ); } - plug = pm.GetNextPlugin(PluginTypeEffect | PluginTypeAudacityCommand ); } } context.EndArray(); diff --git a/src/effects/EffectManager.cpp b/src/effects/EffectManager.cpp index 1063429ec..1e2956013 100644 --- a/src/effects/EffectManager.cpp +++ b/src/effects/EffectManager.cpp @@ -826,15 +826,12 @@ const PluginID & EffectManager::GetEffectByIdentifier(const CommandID & strTarge PluginManager & pm = PluginManager::Get(); // Effects OR Generic commands... - const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeEffect | PluginTypeAudacityCommand); - while (plug) - { - if (GetCommandIdentifier(plug->GetID()) == strTarget) - { - return plug->GetID(); - } - plug = pm.GetNextPlugin(PluginTypeEffect | PluginTypeAudacityCommand); + for (auto &plug + : pm.PluginsOfType(PluginTypeEffect | PluginTypeAudacityCommand)) { + auto &ID = plug.GetID(); + if (GetCommandIdentifier(ID) == strTarget) + return ID; } - return empty;; + return empty; } diff --git a/src/menus/PluginMenus.cpp b/src/menus/PluginMenus.cpp index 8eaeba3da..aa8821fad 100644 --- a/src/menus/PluginMenus.cpp +++ b/src/menus/PluginMenus.cpp @@ -302,9 +302,8 @@ MenuTable::BaseItemPtrs PopulateEffectsMenu( std::vector optplugs; EffectManager & em = EffectManager::Get(); - const PluginDescriptor *plug = pm.GetFirstPluginForEffectType(type); - while (plug) - { + for (auto &plugin : pm.EffectsOfType(type)) { + auto plug = &plugin; if( plug->IsInstantiated() && em.IsHidden(plug->GetID()) ) continue; if ( !plug->IsEnabled() ){ @@ -322,7 +321,6 @@ MenuTable::BaseItemPtrs PopulateEffectsMenu( defplugs.push_back(plug); else optplugs.push_back(plug); - plug = pm.GetNextPluginForEffectType(type); } wxString groupby = EffectsGroupBy.Read(); diff --git a/src/prefs/EffectsPrefs.cpp b/src/prefs/EffectsPrefs.cpp index d01dd2df2..2bc0f47c6 100644 --- a/src/prefs/EffectsPrefs.cpp +++ b/src/prefs/EffectsPrefs.cpp @@ -137,10 +137,8 @@ static const std::vector< Entry > &GetModuleData() struct ModuleData : public std::vector< Entry > { ModuleData() { auto &pm = PluginManager::Get(); - for (auto plug = pm.GetFirstPlugin(PluginTypeModule); - plug; - plug = pm.GetNextPlugin(PluginTypeModule)) { - auto internal = plug->GetEffectFamily(); + for (auto &plug : pm.PluginsOfType(PluginTypeModule)) { + auto internal = plug.GetEffectFamily(); if ( internal.empty() ) continue; @@ -153,11 +151,11 @@ static const std::vector< Entry > &GetModuleData() // If there should be new modules, it is not important for them // to follow the " Effects" convention, but instead they can // have shorter msgids. - prompt = plug->GetSymbol().Msgid(); + prompt = plug.GetSymbol().Msgid(); else prompt = iter->second; - auto setting = pm.GetPluginEnabledSetting( *plug ); + auto setting = pm.GetPluginEnabledSetting( plug ); push_back( { prompt, setting } ); }