Merge pull request #1057 from Paul-Licameli/Cleanup-Plugin-and-Module-Managers
Cleanup plugin and module managers
This commit is contained in:
commit
3ebd8d4014
|
@ -43,6 +43,7 @@
|
|||
#define __AUDACITY_MODULEINTERFACE_H__
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "Identifier.h"
|
||||
#include "audacity/ComponentInterface.h"
|
||||
#include "audacity/PluginInterface.h"
|
||||
|
@ -129,10 +130,8 @@ public:
|
|||
virtual bool IsPluginValid(const PluginPath & path, bool bFast) = 0;
|
||||
|
||||
// When appropriate, CreateInstance() will be called to instantiate the plugin.
|
||||
virtual ComponentInterface *CreateInstance(const PluginPath & path) = 0;
|
||||
|
||||
// When appropriate, DeleteInstance() will be called to delete the plugin.
|
||||
virtual void DeleteInstance(ComponentInterface *instance) = 0;
|
||||
virtual std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginPath & path) = 0;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -1327,9 +1327,11 @@ void NyqBench::OnLargeIcons(wxCommandEvent & e)
|
|||
|
||||
void NyqBench::OnGo(wxCommandEvent & e)
|
||||
{
|
||||
// No need to delete...EffectManager will do it
|
||||
mEffect = new NyquistEffect(wxT("Nyquist Effect Workbench"));
|
||||
const PluginID & ID = EffectManager::Get().RegisterEffect(mEffect);
|
||||
auto pEffect =
|
||||
std::make_unique<NyquistEffect>(L"Nyquist Effect Workbench");
|
||||
mEffect = pEffect.get();
|
||||
const PluginID & ID =
|
||||
EffectManager::Get().RegisterEffect(std::move(pEffect));
|
||||
|
||||
mEffect->SetCommand(mScript->GetValue());
|
||||
mEffect->RedirectOutput();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -202,6 +202,8 @@ list( APPEND SOURCES
|
|||
PlaybackSchedule.h
|
||||
PluginManager.cpp
|
||||
PluginManager.h
|
||||
PluginRegistrationDialog.cpp
|
||||
PluginRegistrationDialog.h
|
||||
Prefs.cpp
|
||||
Prefs.h
|
||||
Printing.cpp
|
||||
|
|
|
@ -22,7 +22,6 @@ class wxCommandEvent;
|
|||
class AudacityProject;
|
||||
class CommandContext;
|
||||
class CommandManager;
|
||||
class PluginDescriptor;
|
||||
class Track;
|
||||
class TrackList;
|
||||
class ViewInfo;
|
||||
|
|
|
@ -31,7 +31,6 @@ i.e. an alternative to the usual interface, for Audacity.
|
|||
|
||||
#include "FileNames.h"
|
||||
#include "MemoryX.h"
|
||||
#include "PluginManager.h"
|
||||
|
||||
#include "audacity/PluginInterface.h"
|
||||
|
||||
|
@ -403,6 +402,21 @@ ModuleManager & ModuleManager::Get()
|
|||
return *mInstance;
|
||||
}
|
||||
|
||||
wxString ModuleManager::GetPluginTypeString()
|
||||
{
|
||||
return L"Module";
|
||||
}
|
||||
|
||||
PluginID ModuleManager::GetID(ModuleInterface *module)
|
||||
{
|
||||
return wxString::Format(wxT("%s_%s_%s_%s_%s"),
|
||||
GetPluginTypeString(),
|
||||
wxEmptyString,
|
||||
module->GetVendor().Internal(),
|
||||
module->GetSymbol().Internal(),
|
||||
module->GetPath());
|
||||
}
|
||||
|
||||
bool ModuleManager::DiscoverProviders()
|
||||
{
|
||||
InitializeBuiltins();
|
||||
|
@ -433,20 +447,8 @@ bool ModuleManager::DiscoverProviders()
|
|||
FileNames::FindFilesInPathList(wxT("*.so"), pathList, provList);
|
||||
#endif
|
||||
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
|
||||
for (int i = 0, cnt = provList.size(); i < cnt; i++)
|
||||
{
|
||||
ModuleInterface *module = LoadModule(provList[i]);
|
||||
if (module)
|
||||
{
|
||||
// Register the provider
|
||||
pm.RegisterPlugin(module);
|
||||
|
||||
// Now, allow the module to auto-register children
|
||||
module->AutoRegisterPlugins(pm);
|
||||
}
|
||||
}
|
||||
for ( const auto &path : provList )
|
||||
LoadModule(path);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -454,8 +456,6 @@ bool ModuleManager::DiscoverProviders()
|
|||
|
||||
void ModuleManager::InitializeBuiltins()
|
||||
{
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
|
||||
for (auto moduleMain : builtinModuleList())
|
||||
{
|
||||
ModuleInterfaceHandle module {
|
||||
|
@ -466,13 +466,10 @@ void ModuleManager::InitializeBuiltins()
|
|||
{
|
||||
// Register the provider
|
||||
ModuleInterface *pInterface = module.get();
|
||||
const PluginID & id = pm.RegisterPlugin(pInterface);
|
||||
auto id = GetID(pInterface);
|
||||
|
||||
// Need to remember it
|
||||
mDynModules[id] = std::move(module);
|
||||
|
||||
// Allow the module to auto-register children
|
||||
pInterface->AutoRegisterPlugins(pm);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -490,22 +487,6 @@ void ModuleInterfaceDeleter::operator() (ModuleInterface *pInterface) const
|
|||
}
|
||||
}
|
||||
|
||||
PluginPaths ModuleManager::FindPluginsForProvider(const PluginID & providerID,
|
||||
const PluginPath & path)
|
||||
{
|
||||
// Instantiate if it hasn't already been done
|
||||
if (mDynModules.find(providerID) == mDynModules.end())
|
||||
{
|
||||
// If it couldn't be created, just give up and return an empty list
|
||||
if (!CreateProviderInstance(providerID, path))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return mDynModules[providerID]->FindPluginPaths(PluginManager::Get());
|
||||
}
|
||||
|
||||
bool ModuleManager::RegisterEffectPlugin(const PluginID & providerID, const PluginPath & path, TranslatableString &errMsg)
|
||||
{
|
||||
errMsg = {};
|
||||
|
@ -530,26 +511,14 @@ ModuleInterface *ModuleManager::CreateProviderInstance(const PluginID & provider
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
ComponentInterface *ModuleManager::CreateInstance(const PluginID & providerID,
|
||||
const PluginPath & path)
|
||||
std::unique_ptr<ComponentInterface> ModuleManager::CreateInstance(
|
||||
const PluginID & providerID, const PluginPath & path)
|
||||
{
|
||||
if (mDynModules.find(providerID) == mDynModules.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mDynModules[providerID]->CreateInstance(path);
|
||||
}
|
||||
|
||||
void ModuleManager::DeleteInstance(const PluginID & providerID,
|
||||
ComponentInterface *instance)
|
||||
{
|
||||
if (mDynModules.find(providerID) == mDynModules.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mDynModules[providerID]->DeleteInstance(instance);
|
||||
if (auto iter = mDynModules.find(providerID);
|
||||
iter == mDynModules.end())
|
||||
return nullptr;
|
||||
else
|
||||
return iter->second->CreateInstance(path);
|
||||
}
|
||||
|
||||
bool ModuleManager::IsProviderValid(const PluginID & WXUNUSED(providerID),
|
||||
|
@ -581,4 +550,3 @@ bool ModuleManager::IsPluginValid(const PluginID & providerID,
|
|||
|
||||
return mDynModules[providerID]->IsPluginValid(path, bFast);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
#ifndef __AUDACITY_MODULEMANAGER_H__
|
||||
#define __AUDACITY_MODULEMANAGER_H__
|
||||
|
||||
#include <memory>
|
||||
#include "MemoryX.h"
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
|
@ -77,6 +78,12 @@ public:
|
|||
|
||||
static ModuleManager & Get();
|
||||
|
||||
// This string persists in configuration files
|
||||
// So config compatibility will break if it is changed across Audacity versions
|
||||
static wxString GetPluginTypeString();
|
||||
|
||||
static PluginID GetID(ModuleInterface *module);
|
||||
|
||||
private:
|
||||
static void FindModules(FilePaths &files);
|
||||
using DelayedErrors =
|
||||
|
@ -92,13 +99,17 @@ public:
|
|||
// Can be called before Initialize()
|
||||
bool DiscoverProviders();
|
||||
|
||||
PluginPaths FindPluginsForProvider(const PluginID & provider, const PluginPath & path);
|
||||
// Supports range-for iteration
|
||||
auto Providers() const
|
||||
{ return make_iterator_range(mDynModules.cbegin(), mDynModules.cend()); }
|
||||
|
||||
bool RegisterEffectPlugin(const PluginID & provider, const PluginPath & path,
|
||||
TranslatableString &errMsg);
|
||||
|
||||
ModuleInterface *CreateProviderInstance(const PluginID & provider, const PluginPath & path);
|
||||
ComponentInterface *CreateInstance(const PluginID & provider, const PluginPath & path);
|
||||
void DeleteInstance(const PluginID & provider, ComponentInterface *instance);
|
||||
ModuleInterface *CreateProviderInstance(
|
||||
const PluginID & provider, const PluginPath & path);
|
||||
std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginID & provider, const PluginPath & path);
|
||||
|
||||
bool IsProviderValid(const PluginID & provider, const PluginPath & path);
|
||||
bool IsPluginValid(const PluginID & provider, const PluginPath & path, bool bFast);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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,
|
||||
|
@ -46,14 +45,12 @@ class AUDACITY_DLL_API PluginDescriptor
|
|||
{
|
||||
public:
|
||||
PluginDescriptor();
|
||||
PluginDescriptor &operator =(PluginDescriptor &&);
|
||||
virtual ~PluginDescriptor();
|
||||
|
||||
bool IsInstantiated() const;
|
||||
ComponentInterface *GetInstance();
|
||||
void SetInstance(ComponentInterface *instance);
|
||||
|
||||
PluginType GetPluginType() const;
|
||||
void SetPluginType(PluginType type);
|
||||
|
||||
// All plugins
|
||||
|
||||
|
@ -71,17 +68,6 @@ public:
|
|||
bool IsEnabled() const;
|
||||
bool IsValid() const;
|
||||
|
||||
// These should be passed an untranslated value
|
||||
void SetID(const PluginID & ID);
|
||||
void SetProviderID(const PluginID & providerID);
|
||||
void SetPath(const PluginPath & path);
|
||||
void SetSymbol(const ComponentInterfaceSymbol & symbol);
|
||||
|
||||
// These should be passed an untranslated value wrapped in XO() so
|
||||
// the value will still be extracted for translation
|
||||
void SetVersion(const wxString & version);
|
||||
void SetVendor(const wxString & vendor);
|
||||
|
||||
void SetEnabled(bool enable);
|
||||
void SetValid(bool valid);
|
||||
|
||||
|
@ -100,6 +86,31 @@ public:
|
|||
bool IsEffectRealtime() const;
|
||||
bool IsEffectAutomatable() const;
|
||||
|
||||
// Importer plugins only
|
||||
|
||||
const wxString & GetImporterIdentifier() const;
|
||||
const TranslatableString & GetImporterFilterDescription() const;
|
||||
const FileExtensions & GetImporterExtensions() const;
|
||||
|
||||
private:
|
||||
friend class PluginManager;
|
||||
|
||||
ComponentInterface *GetInstance();
|
||||
void SetInstance(std::unique_ptr<ComponentInterface> instance);
|
||||
|
||||
void SetPluginType(PluginType type);
|
||||
|
||||
// These should be passed an untranslated value
|
||||
void SetID(const PluginID & ID);
|
||||
void SetProviderID(const PluginID & providerID);
|
||||
void SetPath(const PluginPath & path);
|
||||
void SetSymbol(const ComponentInterfaceSymbol & symbol);
|
||||
|
||||
// These should be passed an untranslated value wrapped in XO() so
|
||||
// the value will still be extracted for translation
|
||||
void SetVersion(const wxString & version);
|
||||
void SetVendor(const wxString & vendor);
|
||||
|
||||
// "family" should be an untranslated string wrapped in wxT()
|
||||
void SetEffectFamily(const wxString & family);
|
||||
void SetEffectType(EffectType type);
|
||||
|
@ -109,25 +120,16 @@ public:
|
|||
void SetEffectRealtime(bool realtime);
|
||||
void SetEffectAutomatable(bool automatable);
|
||||
|
||||
// Importer plugins only
|
||||
|
||||
const wxString & GetImporterIdentifier() const;
|
||||
const TranslatableString & GetImporterFilterDescription() const;
|
||||
const FileExtensions & GetImporterExtensions() const;
|
||||
|
||||
void SetImporterIdentifier(const wxString & identifier);
|
||||
void SetImporterFilterDescription(const TranslatableString & filterDesc);
|
||||
void SetImporterExtensions(FileExtensions extensions);
|
||||
|
||||
private:
|
||||
|
||||
void DeleteInstance();
|
||||
|
||||
// Common
|
||||
|
||||
// Among other purposes, PluginDescriptor acts as the resource handle,
|
||||
// or smart pointer, to a resource created in a plugin library, and is responsible
|
||||
// for a cleanup of this pointer.
|
||||
std::unique_ptr<ComponentInterface> muInstance; // may be null for a module
|
||||
ComponentInterface *mInstance;
|
||||
|
||||
PluginType mPluginType;
|
||||
|
@ -173,8 +175,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
|
||||
|
||||
|
@ -236,7 +238,6 @@ public:
|
|||
|
||||
static PluginManager & Get();
|
||||
|
||||
static PluginID GetID(ModuleInterface *module);
|
||||
static PluginID GetID(ComponentInterface *command);
|
||||
static PluginID GetID(EffectDefinitionInterface *effect);
|
||||
static PluginID GetID(ImporterInterface *importer);
|
||||
|
@ -246,13 +247,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);
|
||||
|
@ -262,19 +292,22 @@ public:
|
|||
|
||||
void CheckForUpdates(bool bFast = false);
|
||||
|
||||
bool ShowManager(wxWindow *parent, EffectType type = EffectTypeNone);
|
||||
|
||||
const PluginID & RegisterPlugin(EffectDefinitionInterface *effect, PluginType type );
|
||||
//! Used only by Nyquist Workbench module
|
||||
const PluginID & RegisterPlugin(
|
||||
std::unique_ptr<EffectDefinitionInterface> effect, PluginType type );
|
||||
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);
|
||||
|
@ -321,9 +354,6 @@ private:
|
|||
int mCurrentIndex;
|
||||
|
||||
PluginMap mPlugins;
|
||||
PluginMap::iterator mPluginsIter;
|
||||
|
||||
friend class PluginRegistrationDialog;
|
||||
};
|
||||
|
||||
// Defining these special names in the low-level PluginManager.h
|
||||
|
|
|
@ -0,0 +1,970 @@
|
|||
/*!*********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
@file PluginRegistrationDialog.cpp
|
||||
|
||||
Paul Licameli split from PluginManager.cpp
|
||||
|
||||
**********************************************************************/
|
||||
#include "PluginRegistrationDialog.h"
|
||||
|
||||
#include "audacity/EffectInterface.h"
|
||||
#include "ModuleManager.h"
|
||||
#include "PluginManager.h"
|
||||
#include "ShuttleGui.h"
|
||||
#include "widgets/AudacityMessageBox.h"
|
||||
#include "widgets/ProgressDialog.h"
|
||||
|
||||
#include <wx/setup.h> // for wxUSE_* macros
|
||||
#include <wx/defs.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/dynlib.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/listctrl.h>
|
||||
#include <wx/radiobut.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
// ============================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
// ============================================================================
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
#include "widgets/WindowAccessible.h"
|
||||
|
||||
class CheckListAx final : public WindowAccessible
|
||||
{
|
||||
public:
|
||||
CheckListAx(wxListCtrl * window);
|
||||
|
||||
virtual ~ CheckListAx();
|
||||
|
||||
// Retrieves the address of an IDispatch interface for the specified child.
|
||||
// All objects must support this property.
|
||||
wxAccStatus GetChild( int childId, wxAccessible **child ) override;
|
||||
|
||||
// Gets the number of children.
|
||||
wxAccStatus GetChildCount( int *childCount ) override;
|
||||
|
||||
// Gets the default action for this object (0) or > 0 (the action for a child).
|
||||
// Return wxACC_OK even if there is no action. actionName is the action, or the empty
|
||||
// string if there is no action.
|
||||
// The retrieved string describes the action that is performed on an object,
|
||||
// not what the object does as a result. For example, a toolbar button that prints
|
||||
// a document has a default action of "Press" rather than "Prints the current document."
|
||||
wxAccStatus GetDefaultAction( int childId, wxString *actionName ) override;
|
||||
|
||||
// Returns the description for this object or a child.
|
||||
wxAccStatus GetDescription( int childId, wxString *description ) override;
|
||||
|
||||
// Gets the window with the keyboard focus.
|
||||
// If childId is 0 and child is NULL, no object in
|
||||
// this subhierarchy has the focus.
|
||||
// If this object has the focus, child should be 'this'.
|
||||
wxAccStatus GetFocus( int *childId, wxAccessible **child ) override;
|
||||
|
||||
// Returns help text for this object or a child, similar to tooltip text.
|
||||
wxAccStatus GetHelpText( int childId, wxString *helpText ) override;
|
||||
|
||||
// Returns the keyboard shortcut for this object or child.
|
||||
// Return e.g. ALT+K
|
||||
wxAccStatus GetKeyboardShortcut( int childId, wxString *shortcut ) override;
|
||||
|
||||
// Returns the rectangle for this object (id = 0) or a child element (id > 0).
|
||||
// rect is in screen coordinates.
|
||||
wxAccStatus GetLocation( wxRect& rect, int elementId ) override;
|
||||
|
||||
// Gets the name of the specified object.
|
||||
wxAccStatus GetName( int childId, wxString *name ) override;
|
||||
|
||||
// Returns a role constant.
|
||||
wxAccStatus GetRole( int childId, wxAccRole *role ) override;
|
||||
|
||||
// Gets a variant representing the selected children
|
||||
// of this object.
|
||||
// Acceptable values:
|
||||
// - a null variant (IsNull() returns TRUE)
|
||||
// - a list variant (GetType() == wxT("list"))
|
||||
// - an integer representing the selected child element,
|
||||
// or 0 if this object is selected (GetType() == wxT("long"))
|
||||
// - a "void*" pointer to a wxAccessible child object
|
||||
wxAccStatus GetSelections( wxVariant *selections ) override;
|
||||
|
||||
// Returns a state constant.
|
||||
wxAccStatus GetState( int childId, long* state ) override;
|
||||
|
||||
// Returns a localized string representing the value for the object
|
||||
// or child.
|
||||
wxAccStatus GetValue( int childId, wxString *strValue ) override;
|
||||
|
||||
void SetSelected( int item, bool focused = true );
|
||||
|
||||
private:
|
||||
wxListCtrl *mParent;
|
||||
int mLastId;
|
||||
};
|
||||
|
||||
CheckListAx::CheckListAx( wxListCtrl * window )
|
||||
: WindowAccessible( window )
|
||||
{
|
||||
mParent = window;
|
||||
mLastId = -1;
|
||||
}
|
||||
|
||||
CheckListAx::~CheckListAx()
|
||||
{
|
||||
}
|
||||
|
||||
void CheckListAx::SetSelected( int item, bool focused )
|
||||
{
|
||||
if (mLastId != -1)
|
||||
{
|
||||
NotifyEvent( wxACC_EVENT_OBJECT_SELECTIONREMOVE,
|
||||
mParent,
|
||||
wxOBJID_CLIENT,
|
||||
mLastId );
|
||||
mLastId = -1;
|
||||
}
|
||||
|
||||
if (item != -1)
|
||||
{
|
||||
if (focused)
|
||||
{
|
||||
NotifyEvent( wxACC_EVENT_OBJECT_FOCUS,
|
||||
mParent,
|
||||
wxOBJID_CLIENT,
|
||||
item + 1 );
|
||||
}
|
||||
|
||||
NotifyEvent( wxACC_EVENT_OBJECT_SELECTION,
|
||||
mParent,
|
||||
wxOBJID_CLIENT,
|
||||
item + 1 );
|
||||
|
||||
mLastId = item + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieves the address of an IDispatch interface for the specified child.
|
||||
// All objects must support this property.
|
||||
wxAccStatus CheckListAx::GetChild( int childId, wxAccessible** child )
|
||||
{
|
||||
if( childId == wxACC_SELF )
|
||||
{
|
||||
*child = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
*child = NULL;
|
||||
}
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Gets the number of children.
|
||||
wxAccStatus CheckListAx::GetChildCount( int *childCount )
|
||||
{
|
||||
*childCount = mParent->GetItemCount();
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Gets the default action for this object (0) or > 0 (the action for a child).
|
||||
// Return wxACC_OK even if there is no action. actionName is the action, or the empty
|
||||
// string if there is no action.
|
||||
// The retrieved string describes the action that is performed on an object,
|
||||
// not what the object does as a result. For example, a toolbar button that prints
|
||||
// a document has a default action of "Press" rather than "Prints the current document."
|
||||
wxAccStatus CheckListAx::GetDefaultAction( int WXUNUSED(childId), wxString *actionName )
|
||||
{
|
||||
actionName->clear();
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Returns the description for this object or a child.
|
||||
wxAccStatus CheckListAx::GetDescription( int WXUNUSED(childId), wxString *description )
|
||||
{
|
||||
description->clear();
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Gets the window with the keyboard focus.
|
||||
// If childId is 0 and child is NULL, no object in
|
||||
// this subhierarchy has the focus.
|
||||
// If this object has the focus, child should be 'this'.
|
||||
wxAccStatus CheckListAx::GetFocus( int *childId, wxAccessible **child )
|
||||
{
|
||||
*childId = 0;
|
||||
*child = this;
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Returns help text for this object or a child, similar to tooltip text.
|
||||
wxAccStatus CheckListAx::GetHelpText( int WXUNUSED(childId), wxString *helpText )
|
||||
{
|
||||
helpText->clear();
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Returns the keyboard shortcut for this object or child.
|
||||
// Return e.g. ALT+K
|
||||
wxAccStatus CheckListAx::GetKeyboardShortcut( int WXUNUSED(childId), wxString *shortcut )
|
||||
{
|
||||
shortcut->clear();
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Returns the rectangle for this object (id = 0) or a child element (id > 0).
|
||||
// rect is in screen coordinates.
|
||||
wxAccStatus CheckListAx::GetLocation( wxRect& rect, int elementId )
|
||||
{
|
||||
if( elementId == wxACC_SELF )
|
||||
{
|
||||
rect = mParent->GetRect();
|
||||
rect.SetPosition( mParent->GetParent()->ClientToScreen( rect.GetPosition() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( elementId <= mParent->GetItemCount() )
|
||||
{
|
||||
mParent->GetItemRect( elementId - 1, rect, wxLIST_RECT_LABEL );
|
||||
rect.SetPosition( mParent->ClientToScreen( rect.GetPosition() ) );
|
||||
}
|
||||
}
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Gets the name of the specified object.
|
||||
wxAccStatus CheckListAx::GetName( int WXUNUSED(childId), wxString *name )
|
||||
{
|
||||
*name = mParent->GetName();
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Returns a role constant.
|
||||
wxAccStatus CheckListAx::GetRole( int childId, wxAccRole *role )
|
||||
{
|
||||
if( childId == wxACC_SELF )
|
||||
{
|
||||
*role = wxROLE_SYSTEM_LIST;
|
||||
}
|
||||
else
|
||||
{
|
||||
*role = wxROLE_SYSTEM_LISTITEM;
|
||||
}
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Gets a variant representing the selected children
|
||||
// of this object.
|
||||
// Acceptable values:
|
||||
// - a null variant (IsNull() returns TRUE)
|
||||
// - a list variant (GetType() == wxT("list"))
|
||||
// - an integer representing the selected child element,
|
||||
// or 0 if this object is selected (GetType() == wxT("long"))
|
||||
// - a "void*" pointer to a wxAccessible child object
|
||||
wxAccStatus CheckListAx::GetSelections( wxVariant * WXUNUSED(selections) )
|
||||
{
|
||||
return wxACC_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Returns a state constant.
|
||||
wxAccStatus CheckListAx::GetState( int childId, long *pState )
|
||||
{
|
||||
int flag = wxACC_STATE_SYSTEM_FOCUSABLE;
|
||||
|
||||
if( childId == wxACC_SELF )
|
||||
{
|
||||
flag |= wxACC_STATE_SYSTEM_FOCUSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxListItem item;
|
||||
|
||||
item.SetId( childId - 1 );
|
||||
item.SetState( wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED );
|
||||
item.SetMask( wxLIST_MASK_STATE );
|
||||
|
||||
if( mParent->GetItem( item ) )
|
||||
{
|
||||
flag |= wxACC_STATE_SYSTEM_SELECTABLE;
|
||||
|
||||
long state = item.GetState();
|
||||
|
||||
if( state & wxLIST_STATE_FOCUSED )
|
||||
{
|
||||
flag |= wxACC_STATE_SYSTEM_FOCUSED;
|
||||
}
|
||||
|
||||
if( state & wxLIST_STATE_SELECTED )
|
||||
{
|
||||
flag |= wxACC_STATE_SYSTEM_SELECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*pState = flag;
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
// Returns a localized string representing the value for the object
|
||||
// or child.
|
||||
wxAccStatus CheckListAx::GetValue( int childId, wxString *strValue )
|
||||
{
|
||||
if( childId == 0 )
|
||||
{
|
||||
return wxACC_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
*strValue = mParent->GetItemText( childId - 1 );
|
||||
}
|
||||
|
||||
return wxACC_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
enum
|
||||
{
|
||||
STATE_Enabled,
|
||||
STATE_Disabled,
|
||||
STATE_New,
|
||||
|
||||
STATE_COUNT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ID_ShowAll = 10000,
|
||||
ID_ShowEnabled,
|
||||
ID_ShowDisabled,
|
||||
ID_ShowNew,
|
||||
ID_List,
|
||||
ID_ClearAll,
|
||||
ID_SelectAll,
|
||||
ID_Enable,
|
||||
ID_Disable,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
COL_Name,
|
||||
COL_State,
|
||||
COL_Path,
|
||||
|
||||
COL_COUNT
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(PluginRegistrationDialog, wxDialogWrapper)
|
||||
EVT_LIST_COL_CLICK(ID_List, PluginRegistrationDialog::OnSort)
|
||||
EVT_BUTTON(wxID_OK, PluginRegistrationDialog::OnOK)
|
||||
EVT_BUTTON(wxID_CANCEL, PluginRegistrationDialog::OnCancel)
|
||||
EVT_BUTTON(ID_ClearAll, PluginRegistrationDialog::OnClearAll)
|
||||
EVT_BUTTON(ID_SelectAll, PluginRegistrationDialog::OnSelectAll)
|
||||
EVT_BUTTON(ID_Enable, PluginRegistrationDialog::OnEnable)
|
||||
EVT_BUTTON(ID_Disable, PluginRegistrationDialog::OnDisable)
|
||||
EVT_RADIOBUTTON(ID_ShowAll, PluginRegistrationDialog::OnChangedVisibility)
|
||||
EVT_RADIOBUTTON(ID_ShowEnabled, PluginRegistrationDialog::OnChangedVisibility)
|
||||
EVT_RADIOBUTTON(ID_ShowDisabled, PluginRegistrationDialog::OnChangedVisibility)
|
||||
EVT_RADIOBUTTON(ID_ShowNew, PluginRegistrationDialog::OnChangedVisibility)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
PluginRegistrationDialog::PluginRegistrationDialog(wxWindow *parent, EffectType type)
|
||||
: wxDialogWrapper(parent,
|
||||
wxID_ANY,
|
||||
XO("Manage Plug-ins"),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
{
|
||||
mType = type;
|
||||
mEffects = NULL;
|
||||
SetName();
|
||||
|
||||
mStates.resize(STATE_COUNT);
|
||||
mStates[STATE_Enabled] = _("Enabled");
|
||||
mStates[STATE_Disabled] = _("Disabled");
|
||||
mStates[STATE_New] = _("New");
|
||||
|
||||
mSortColumn = COL_Name;
|
||||
mSortDirection = 1;
|
||||
|
||||
Populate();
|
||||
|
||||
DoSort( mSortColumn );
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::Populate()
|
||||
{
|
||||
//------------------------- Main section --------------------
|
||||
ShuttleGui S(this, eIsCreating);
|
||||
PopulateOrExchange(S);
|
||||
// ----------------------- End of main section --------------
|
||||
}
|
||||
|
||||
/// Defines the dialog and does data exchange with it.
|
||||
void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
|
||||
{
|
||||
S.StartVerticalLay(true);
|
||||
{
|
||||
/*i18n-hint: The dialog shows a list of plugins with check-boxes
|
||||
beside each one.*/
|
||||
// S.StartStatic(XO("Effects"), true);
|
||||
S.StartVerticalLay();
|
||||
{
|
||||
S.StartHorizontalLay(wxEXPAND, 0);
|
||||
{
|
||||
S.StartHorizontalLay(wxALIGN_LEFT, 0);
|
||||
{
|
||||
S.AddPrompt(XXO("Select effects, click the Enable or Disable button, then click OK."));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(wxCENTER, 1);
|
||||
{
|
||||
S.AddSpace(1);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(wxALIGN_NOT | wxALIGN_LEFT, 0);
|
||||
{
|
||||
wxRadioButton *rb;
|
||||
|
||||
/* i18n-hint: This is before radio buttons selecting which effects to show */
|
||||
S.AddPrompt(XXO("Show:"));
|
||||
rb = S.Id(ID_ShowAll)
|
||||
/* i18n-hint: Radio button to show all effects */
|
||||
.Name(XO("Show all"))
|
||||
/* i18n-hint: Radio button to show all effects */
|
||||
.AddRadioButton(XXO("&All"));
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
// so that name can be set on a standard control
|
||||
rb->SetAccessible(safenew WindowAccessible(rb));
|
||||
#endif
|
||||
|
||||
rb = S.Id(ID_ShowDisabled)
|
||||
/* i18n-hint: Radio button to show just the currently disabled effects */
|
||||
.Name(XO("Show disabled"))
|
||||
/* i18n-hint: Radio button to show just the currently disabled effects */
|
||||
.AddRadioButtonToGroup(XXO("D&isabled"));
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
// so that name can be set on a standard control
|
||||
rb->SetAccessible(safenew WindowAccessible(rb));
|
||||
#endif
|
||||
|
||||
rb = S.Id(ID_ShowEnabled)
|
||||
/* i18n-hint: Radio button to show just the currently enabled effects */
|
||||
.Name(XO("Show enabled"))
|
||||
/* i18n-hint: Radio button to show just the currently enabled effects */
|
||||
.AddRadioButtonToGroup(XXO("E&nabled"));
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
// so that name can be set on a standard control
|
||||
rb->SetAccessible(safenew WindowAccessible(rb));
|
||||
#endif
|
||||
|
||||
rb = S.Id(ID_ShowNew)
|
||||
/* i18n-hint: Radio button to show just the newly discovered effects */
|
||||
.Name(XO("Show new"))
|
||||
/* i18n-hint: Radio button to show just the newly discovered effects */
|
||||
.AddRadioButtonToGroup(XXO("Ne&w"));
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
// so that name can be set on a standard control
|
||||
rb->SetAccessible(safenew WindowAccessible(rb));
|
||||
#endif
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
mEffects = S.Id(ID_List)
|
||||
.Style(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES )
|
||||
.ConnectRoot(wxEVT_KEY_DOWN,
|
||||
&PluginRegistrationDialog::OnListChar)
|
||||
.AddListControlReportMode({ XO("Name"), XO("State"), XO("Path") });
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
mEffects->SetAccessible(mAx = safenew CheckListAx(mEffects));
|
||||
#endif
|
||||
|
||||
S.StartHorizontalLay(wxALIGN_LEFT | wxEXPAND, 0);
|
||||
{
|
||||
S.Id(ID_SelectAll).AddButton(XXO("&Select All"));
|
||||
S.Id(ID_ClearAll).AddButton(XXO("C&lear All"));
|
||||
|
||||
S.StartHorizontalLay(wxALIGN_CENTER);
|
||||
{
|
||||
S.AddSpace(1);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.Id(ID_Enable).AddButton(XXO("&Enable"));
|
||||
S.Id(ID_Disable).AddButton(XXO("&Disable"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
// S.EndStatic();
|
||||
S.EndVerticalLay();
|
||||
|
||||
S.AddStandardButtons(eOkButton | eCancelButton);
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
|
||||
std::vector<int> colWidths;
|
||||
for (int i = 0, cnt = mEffects->GetColumnCount(); i < cnt; i++)
|
||||
{
|
||||
colWidths.push_back(0);
|
||||
}
|
||||
|
||||
for (int i = 0, cnt = mStates.size(); i < cnt; i++)
|
||||
{
|
||||
int x;
|
||||
mEffects->GetTextExtent(mStates[i], &x, NULL);
|
||||
colWidths[COL_State] = wxMax(colWidths[COL_State], x + 4); // 2 pixel margin on each side
|
||||
}
|
||||
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
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
|
||||
item.plugs.push_back(&plug);
|
||||
item.path = path;
|
||||
item.state = plug.IsEnabled() ? STATE_Enabled : STATE_Disabled;
|
||||
item.valid = plug.IsValid();
|
||||
|
||||
if (plugType == PluginTypeEffect)
|
||||
{
|
||||
item.name = plug.GetSymbol().Translation();
|
||||
}
|
||||
// This is not right and will not work when other plugin types are added.
|
||||
// But it's presumed that the plugin manager dialog will be fully developed
|
||||
// by then.
|
||||
else if (plugType == PluginTypeStub)
|
||||
{
|
||||
wxFileName fname { path };
|
||||
item.name = fname.GetName().Trim(false).Trim(true);
|
||||
if (!item.valid)
|
||||
{
|
||||
item.state = STATE_New;
|
||||
}
|
||||
}
|
||||
|
||||
int x;
|
||||
mEffects->GetTextExtent(item.name, &x, NULL);
|
||||
colWidths[COL_Name] = wxMax(colWidths[COL_Name], x);
|
||||
|
||||
mEffects->GetTextExtent(item.path, &x, NULL);
|
||||
if (x > colWidths[COL_Path])
|
||||
{
|
||||
mLongestPath = item.path;
|
||||
}
|
||||
colWidths[COL_Path] = wxMax(colWidths[COL_Path], x);
|
||||
}
|
||||
|
||||
wxRect r = wxGetClientDisplayRect();
|
||||
|
||||
int maxW = 0;
|
||||
for (int i = 0, cnt = mEffects->GetColumnCount(); i < cnt; i++)
|
||||
{
|
||||
int w = colWidths[i] + /* fudge */ 10;
|
||||
mEffects->SetColumnWidth(i, w);
|
||||
maxW += w;
|
||||
}
|
||||
|
||||
// Keep dialog from getting too wide
|
||||
int w = r.GetWidth() - (GetClientSize().GetWidth() - mEffects->GetSize().GetWidth());
|
||||
mEffects->SetMinSize({ std::min(maxW, w), 200 });
|
||||
mEffects->SetMaxSize({ w, -1 });
|
||||
|
||||
RegenerateEffectsList(ID_ShowAll);
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
wxSize sz = GetSize();
|
||||
sz.SetWidth(wxMin(sz.GetWidth(), r.GetWidth()));
|
||||
sz.SetHeight(wxMin(sz.GetHeight(), r.GetHeight()));
|
||||
SetMinSize(sz);
|
||||
|
||||
// Parent window is usually not there yet, so centre on screen rather than on parent.
|
||||
CenterOnScreen();
|
||||
|
||||
if (mEffects->GetItemCount() > 0)
|
||||
{
|
||||
// Make sure first item is selected/focused.
|
||||
mEffects->SetFocus();
|
||||
mEffects->SetItemState(0, wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED, wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED);
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
mAx->SetSelected(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::RegenerateEffectsList(int filter)
|
||||
{
|
||||
mFilter = filter;
|
||||
|
||||
mEffects->DeleteAllItems();
|
||||
|
||||
int i = 0;
|
||||
for (ItemDataMap::iterator iter = mItems.begin(); iter != mItems.end(); ++iter)
|
||||
{
|
||||
ItemData & item = iter->second;
|
||||
bool add = false;
|
||||
|
||||
switch (mFilter)
|
||||
{
|
||||
case ID_ShowAll:
|
||||
add = true;
|
||||
break;
|
||||
case ID_ShowNew:
|
||||
if (item.state == STATE_New)
|
||||
{
|
||||
add = true;
|
||||
}
|
||||
break;
|
||||
case ID_ShowEnabled:
|
||||
if (item.state == STATE_Enabled)
|
||||
{
|
||||
add = true;
|
||||
}
|
||||
break;
|
||||
case ID_ShowDisabled:
|
||||
if (item.state == STATE_Disabled)
|
||||
{
|
||||
add = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (add)
|
||||
{
|
||||
mEffects->InsertItem(i, item.name);
|
||||
mEffects->SetItem(i, COL_State, mStates[item.state]);
|
||||
mEffects->SetItem(i, COL_Path, item.path);
|
||||
mEffects->SetItemPtrData(i, (wxUIntPtr) &item);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
mEffects->SortItems(SortCompare, (wxUIntPtr) this);
|
||||
|
||||
if (mEffects->GetItemCount() > 0)
|
||||
{
|
||||
// Make sure first item is selected/focused.
|
||||
// mEffects->SetFocus();
|
||||
mEffects->SetItemState(0, wxLIST_STATE_FOCUSED|wxLIST_STATE_SELECTED, wxLIST_STATE_FOCUSED|wxLIST_STATE_SELECTED);
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
mAx->SetSelected(0, false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::SetState(int i, bool toggle, bool state)
|
||||
{
|
||||
wxListItem li;
|
||||
|
||||
li.m_mask = wxLIST_MASK_DATA;
|
||||
li.m_itemId = i;
|
||||
|
||||
mEffects->GetItem(li);
|
||||
|
||||
ItemData *item = (ItemData *) li.m_data;
|
||||
|
||||
// If changing the state of a "New" (stub) entry, then we mark it as valid
|
||||
// since it will either be registered if "Enabled" or ignored if "Disabled".
|
||||
if (item->state == STATE_New)
|
||||
{
|
||||
item->valid = true;
|
||||
}
|
||||
|
||||
if (toggle)
|
||||
{
|
||||
item->state = item->state == STATE_Enabled ? STATE_Disabled : STATE_Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->state = state;
|
||||
}
|
||||
|
||||
if (mFilter == ID_ShowNew && item->state != STATE_New)
|
||||
{
|
||||
mEffects->DeleteItem(i);
|
||||
}
|
||||
else if (mFilter == ID_ShowDisabled && item->state != STATE_Disabled)
|
||||
{
|
||||
mEffects->DeleteItem(i);
|
||||
}
|
||||
else if (mFilter == ID_ShowEnabled && item->state != STATE_Enabled)
|
||||
{
|
||||
mEffects->DeleteItem(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
mEffects->SetItem(i, COL_State, mStates[item->state]);
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
mAx->SetSelected(i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int wxCALLBACK PluginRegistrationDialog::SortCompare(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData)
|
||||
{
|
||||
PluginRegistrationDialog *dlg = (PluginRegistrationDialog *) sortData;
|
||||
ItemData *i1 = (ItemData *) item1;
|
||||
ItemData *i2 = (ItemData *) item2;
|
||||
|
||||
return dlg->SortCompare(i1, i2);
|
||||
}
|
||||
|
||||
int PluginRegistrationDialog::SortCompare(ItemData *item1, ItemData *item2)
|
||||
{
|
||||
// This function is a three-valued comparator
|
||||
|
||||
wxString *str1;
|
||||
wxString *str2;
|
||||
|
||||
switch (mSortColumn)
|
||||
{
|
||||
case COL_Name:
|
||||
str1 = &item1->name;
|
||||
str2 = &item2->name;
|
||||
break;
|
||||
case COL_State:
|
||||
str1 = &mStates[item1->state];
|
||||
str2 = &mStates[item2->state];
|
||||
break;
|
||||
case COL_Path:
|
||||
str1 = &item1->path;
|
||||
str2 = &item2->path;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return str2->CmpNoCase(*str1) * mSortDirection;
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::OnChangedVisibility(wxCommandEvent & evt)
|
||||
{
|
||||
// Go and show the relevant items.
|
||||
RegenerateEffectsList(evt.GetId());
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::OnSort(wxListEvent & evt)
|
||||
{
|
||||
int col = evt.GetColumn();
|
||||
DoSort( col );
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::DoSort( int col )
|
||||
{
|
||||
if (col != mSortColumn)
|
||||
{
|
||||
mSortDirection = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mSortDirection *= -1;
|
||||
}
|
||||
|
||||
mSortColumn = col;
|
||||
mEffects->SortItems(SortCompare, (wxUIntPtr) this);
|
||||
|
||||
// Without a refresh, wxMac doesn't redisplay the list properly after a sort
|
||||
mEffects->Refresh();
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::OnListChar(wxKeyEvent & evt)
|
||||
{
|
||||
switch (evt.GetKeyCode())
|
||||
{
|
||||
case WXK_SPACE:
|
||||
{
|
||||
int item = mEffects->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED);
|
||||
if (item != wxNOT_FOUND)
|
||||
{
|
||||
SetState(item, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WXK_RETURN:
|
||||
// Don't know why wxListCtrls prevent default dialog action,
|
||||
// but they do, so handle it.
|
||||
EmulateButtonClickIfPresent(GetAffirmativeId());
|
||||
break;
|
||||
|
||||
default:
|
||||
evt.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::OnSelectAll(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
for (int i = 0, cnt = mEffects->GetItemCount(); i < cnt; i++)
|
||||
{
|
||||
mEffects->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::OnClearAll(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
for (int i = 0, cnt = mEffects->GetItemCount(); i < cnt; i++)
|
||||
{
|
||||
mEffects->SetItemState(i, 0, wxLIST_STATE_SELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::OnEnable(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
std::vector<long> items;
|
||||
|
||||
{
|
||||
long i = mEffects->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
||||
while (i != wxNOT_FOUND)
|
||||
{
|
||||
items.insert(items.begin(), i);
|
||||
i = mEffects->GetNextItem(i, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0, cnt = items.size(); i < cnt; i++)
|
||||
{
|
||||
SetState(items[i], false, STATE_Enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::OnDisable(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
std::vector<long> items;
|
||||
|
||||
{
|
||||
long i = mEffects->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
||||
while (i != wxNOT_FOUND)
|
||||
{
|
||||
items.insert(items.begin(), i);
|
||||
i = mEffects->GetNextItem(i, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0, cnt = items.size(); i < cnt; i++)
|
||||
{
|
||||
SetState(items[i], false, STATE_Disabled);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
ModuleManager & mm = ModuleManager::Get();
|
||||
|
||||
int enableCount = 0;
|
||||
for (ItemDataMap::iterator iter = mItems.begin(); iter != mItems.end(); ++iter)
|
||||
{
|
||||
ItemData & item = iter->second;
|
||||
wxString path = item.path;
|
||||
|
||||
if (item.state == STATE_Enabled && item.plugs[0]->GetPluginType() == PluginTypeStub)
|
||||
{
|
||||
enableCount++;
|
||||
}
|
||||
}
|
||||
|
||||
wxString last3 = mLongestPath + wxT("\n") +
|
||||
mLongestPath + wxT("\n") +
|
||||
mLongestPath + wxT("\n");
|
||||
|
||||
auto msg = XO("Enabling effects or commands:\n\n%s").Format( last3 );
|
||||
|
||||
// Make sure the progress dialog is deleted before we call EndModal() or
|
||||
// we will leave the project window in an unusable state on OSX.
|
||||
// See bug #1192.
|
||||
{
|
||||
ProgressDialog progress{
|
||||
Verbatim( GetTitle() ), msg, pdlgHideStopButton };
|
||||
progress.CenterOnParent();
|
||||
|
||||
int i = 0;
|
||||
for (ItemDataMap::iterator iter = mItems.begin(); iter != mItems.end(); ++iter)
|
||||
{
|
||||
ItemData & item = iter->second;
|
||||
wxString path = item.path;
|
||||
|
||||
if (item.state == STATE_Enabled && item.plugs[0]->GetPluginType() == PluginTypeStub)
|
||||
{
|
||||
last3 = last3.AfterFirst(wxT('\n')) + item.path + wxT("\n");
|
||||
auto status = progress.Update(++i, enableCount,
|
||||
XO("Enabling effect or command:\n\n%s").Format( last3 ));
|
||||
if (status == ProgressResult::Cancelled)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
TranslatableString errMsgs;
|
||||
|
||||
// Try to register the plugin via each provider until one succeeds
|
||||
for (size_t j = 0, cntj = item.plugs.size(); j < cntj; j++)
|
||||
{
|
||||
TranslatableString errMsg;
|
||||
if (mm.RegisterEffectPlugin(item.plugs[j]->GetProviderID(), path,
|
||||
errMsg))
|
||||
{
|
||||
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 = {};
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!errMsgs.empty())
|
||||
errMsgs.Join( errMsg, '\n' );
|
||||
else
|
||||
errMsgs = errMsg;
|
||||
}
|
||||
}
|
||||
if (!errMsgs.empty())
|
||||
AudacityMessageBox(
|
||||
XO("Effect or Command at %s failed to register:\n%s")
|
||||
.Format( path, errMsgs ) );
|
||||
}
|
||||
else if (item.state == STATE_New) {
|
||||
for (auto plug : item.plugs)
|
||||
plug->SetValid(false);
|
||||
}
|
||||
else if (item.state != STATE_New) {
|
||||
for (auto plug : item.plugs) {
|
||||
plug->SetEnabled(item.state == STATE_Enabled);
|
||||
plug->SetValid(item.valid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pm.Save();
|
||||
}
|
||||
|
||||
EndModal(wxID_OK);
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::OnCancel(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
EndModal(wxID_CANCEL);
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
PluginRegistrationDialog.h
|
||||
|
||||
Paul Licameli split from PluginManager.cpp
|
||||
|
||||
**********************************************************************/
|
||||
#ifndef __AUDACITY_PLUGIN_REGISTRATION_DIALOG__
|
||||
#define __AUDACITY_PLUGIN_REGISTRATION_DIALOG__
|
||||
|
||||
#include "widgets/wxPanelWrapper.h" // to inherit
|
||||
#include <vector>
|
||||
#include <unordered_map> // member
|
||||
|
||||
class CheckListAx;
|
||||
enum EffectType : int;
|
||||
class PluginDescriptor;
|
||||
class ShuttleGui;
|
||||
class wxListEvent;
|
||||
class wxListCtrl;
|
||||
|
||||
class PluginRegistrationDialog final : public wxDialogWrapper
|
||||
{
|
||||
public:
|
||||
// constructors and destructors
|
||||
PluginRegistrationDialog(wxWindow *parent, EffectType type);
|
||||
|
||||
private:
|
||||
struct ItemData
|
||||
{
|
||||
std::vector<PluginDescriptor*> plugs;
|
||||
wxString name;
|
||||
PluginPath path;
|
||||
int state;
|
||||
bool valid;
|
||||
int nameWidth;
|
||||
int pathWidth;
|
||||
int stateWidth;
|
||||
};
|
||||
|
||||
using ItemDataMap = std::unordered_map<PluginPath, ItemData>;
|
||||
|
||||
void Populate();
|
||||
void PopulateOrExchange(ShuttleGui & S);
|
||||
void RegenerateEffectsList(int iShowWhat);
|
||||
void SetState(int i, bool toggle, bool state = true);
|
||||
|
||||
static int wxCALLBACK SortCompare(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData);
|
||||
int SortCompare(ItemData *item1, ItemData *item2);
|
||||
|
||||
void OnChangedVisibility(wxCommandEvent & evt);
|
||||
void OnSort(wxListEvent & evt);
|
||||
void DoSort( int col );
|
||||
void OnListChar(wxKeyEvent & evt);
|
||||
void OnOK(wxCommandEvent & evt);
|
||||
void OnCancel(wxCommandEvent & evt);
|
||||
void OnSelectAll(wxCommandEvent & evt);
|
||||
void OnClearAll(wxCommandEvent & evt);
|
||||
void OnEnable(wxCommandEvent & evt);
|
||||
void OnDisable(wxCommandEvent & evt);
|
||||
|
||||
private:
|
||||
EffectType mType;
|
||||
int mFilter;
|
||||
|
||||
wxArrayString mStates;
|
||||
ItemDataMap mItems;
|
||||
|
||||
int mSortColumn;
|
||||
int mSortDirection;
|
||||
|
||||
PluginPath mLongestPath;
|
||||
|
||||
wxListCtrl *mEffects;
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
CheckListAx *mAx;
|
||||
#endif
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -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();
|
||||
|
|
|
@ -194,19 +194,11 @@ bool BuiltinCommandsModule::IsPluginValid(const PluginPath & path, bool bFast)
|
|||
return mCommands.find( path ) != mCommands.end();
|
||||
}
|
||||
|
||||
ComponentInterface *BuiltinCommandsModule::CreateInstance(const PluginPath & path)
|
||||
std::unique_ptr<ComponentInterface>
|
||||
BuiltinCommandsModule::CreateInstance(const PluginPath & path)
|
||||
{
|
||||
// Acquires a resource for the application.
|
||||
// Safety of this depends on complementary calls to DeleteInstance on the module manager side.
|
||||
return Instantiate(path).release();
|
||||
}
|
||||
|
||||
void BuiltinCommandsModule::DeleteInstance(ComponentInterface *instance)
|
||||
{
|
||||
// Releases the resource.
|
||||
std::unique_ptr < AudacityCommand > {
|
||||
dynamic_cast<AudacityCommand *>(instance)
|
||||
};
|
||||
return Instantiate(path);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
@ -69,8 +69,8 @@ public:
|
|||
|
||||
bool IsPluginValid(const PluginPath & path, bool bFast) override;
|
||||
|
||||
ComponentInterface *CreateInstance(const PluginPath & path) override;
|
||||
void DeleteInstance(ComponentInterface *instance) override;
|
||||
std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginPath & path) override;
|
||||
|
||||
private:
|
||||
// BuiltinEffectModule implementation
|
||||
|
|
|
@ -56,12 +56,12 @@ EffectManager::~EffectManager()
|
|||
|
||||
// Here solely for the purpose of Nyquist Workbench until
|
||||
// a better solution is devised.
|
||||
const PluginID & EffectManager::RegisterEffect(Effect *f)
|
||||
const PluginID & EffectManager::RegisterEffect(std::unique_ptr<Effect> uEffect)
|
||||
{
|
||||
const PluginID & ID = PluginManager::Get().RegisterPlugin(f, PluginTypeEffect);
|
||||
|
||||
mEffects[ID] = f;
|
||||
|
||||
auto pEffect = uEffect.get();
|
||||
const PluginID & ID =
|
||||
PluginManager::Get().RegisterPlugin(std::move(uEffect), PluginTypeEffect);
|
||||
mEffects[ID] = pEffect;
|
||||
return ID;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
for (auto &plug
|
||||
: pm.PluginsOfType(PluginTypeEffect | PluginTypeAudacityCommand)) {
|
||||
auto &ID = plug.GetID();
|
||||
if (GetCommandIdentifier(ID) == strTarget)
|
||||
return ID;
|
||||
}
|
||||
plug = pm.GetNextPlugin(PluginTypeEffect | PluginTypeAudacityCommand);
|
||||
}
|
||||
return empty;;
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,10 +75,10 @@ public:
|
|||
EffectManager();
|
||||
virtual ~EffectManager();
|
||||
|
||||
/** (Un)Register an effect so it can be executed. */
|
||||
// Here solely for the purpose of Nyquist Workbench until
|
||||
// a better solution is devised.
|
||||
const PluginID & RegisterEffect(Effect *f);
|
||||
//! Here solely for the purpose of Nyquist Workbench until a better solution is devised.
|
||||
/** Register an effect so it can be executed. */
|
||||
const PluginID & RegisterEffect(std::unique_ptr<Effect> uEffect);
|
||||
//! Used only by Nyquist Workbench module
|
||||
void UnregisterEffect(const PluginID & ID);
|
||||
|
||||
TranslatableString GetEffectFamilyName(const PluginID & ID);
|
||||
|
|
|
@ -191,19 +191,11 @@ bool BuiltinEffectsModule::IsPluginValid(const PluginPath & path, bool bFast)
|
|||
return mEffects.find( path ) != mEffects.end();
|
||||
}
|
||||
|
||||
ComponentInterface *BuiltinEffectsModule::CreateInstance(const PluginPath & path)
|
||||
std::unique_ptr<ComponentInterface>
|
||||
BuiltinEffectsModule::CreateInstance(const PluginPath & path)
|
||||
{
|
||||
// Acquires a resource for the application.
|
||||
// Safety of this depends on complementary calls to DeleteInstance on the module manager side.
|
||||
return Instantiate(path).release();
|
||||
}
|
||||
|
||||
void BuiltinEffectsModule::DeleteInstance(ComponentInterface *instance)
|
||||
{
|
||||
// Releases the resource.
|
||||
std::unique_ptr < Effect > {
|
||||
dynamic_cast<Effect *>(instance)
|
||||
};
|
||||
return Instantiate(path);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
@ -69,8 +69,8 @@ public:
|
|||
|
||||
bool IsPluginValid(const PluginPath & path, bool bFast) override;
|
||||
|
||||
ComponentInterface *CreateInstance(const PluginPath & path) override;
|
||||
void DeleteInstance(ComponentInterface *instance) override;
|
||||
std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginPath & path) override;
|
||||
|
||||
private:
|
||||
// BuiltinEffectModule implementation
|
||||
|
|
|
@ -684,19 +684,12 @@ bool VSTEffectsModule::IsPluginValid(const PluginPath & path, bool bFast)
|
|||
return wxFileName::FileExists(realPath) || wxFileName::DirExists(realPath);
|
||||
}
|
||||
|
||||
ComponentInterface *VSTEffectsModule::CreateInstance(const PluginPath & path)
|
||||
std::unique_ptr<ComponentInterface>
|
||||
VSTEffectsModule::CreateInstance(const PluginPath & path)
|
||||
{
|
||||
// Acquires a resource for the application.
|
||||
// For us, the ID is simply the path to the effect
|
||||
// Safety of this depends on complementary calls to DeleteInstance on the module manager side.
|
||||
return safenew VSTEffect(path);
|
||||
}
|
||||
|
||||
void VSTEffectsModule::DeleteInstance(ComponentInterface *instance)
|
||||
{
|
||||
std::unique_ptr < VSTEffect > {
|
||||
dynamic_cast<VSTEffect *>(instance)
|
||||
};
|
||||
return std::make_unique<VSTEffect>(path);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
@ -432,8 +432,8 @@ public:
|
|||
|
||||
bool IsPluginValid(const PluginPath & path, bool bFast) override;
|
||||
|
||||
ComponentInterface *CreateInstance(const PluginPath & path) override;
|
||||
void DeleteInstance(ComponentInterface *instance) override;
|
||||
std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginPath & path) override;
|
||||
|
||||
// VSTEffectModule implementation
|
||||
|
||||
|
|
|
@ -377,25 +377,13 @@ bool AudioUnitEffectsModule::IsPluginValid(const PluginPath & path, bool bFast)
|
|||
return FindAudioUnit(path, name) != NULL;
|
||||
}
|
||||
|
||||
ComponentInterface *AudioUnitEffectsModule::CreateInstance(const PluginPath & path)
|
||||
std::unique_ptr<ComponentInterface>
|
||||
AudioUnitEffectsModule::CreateInstance(const PluginPath & path)
|
||||
{
|
||||
// Acquires a resource for the application.
|
||||
wxString name;
|
||||
AudioComponent component = FindAudioUnit(path, name);
|
||||
if (component == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Safety of this depends on complementary calls to DeleteInstance on the module manager side.
|
||||
return safenew AudioUnitEffect(path, name, component);
|
||||
}
|
||||
|
||||
void AudioUnitEffectsModule::DeleteInstance(ComponentInterface *instance)
|
||||
{
|
||||
std::unique_ptr < AudioUnitEffect > {
|
||||
dynamic_cast<AudioUnitEffect *>(instance)
|
||||
};
|
||||
if (wxString name; auto component = FindAudioUnit(path, name))
|
||||
return std::make_unique<AudioUnitEffect>(path, name, component);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
@ -261,8 +261,8 @@ public:
|
|||
|
||||
bool IsPluginValid(const PluginPath & path, bool bFast) override;
|
||||
|
||||
ComponentInterface *CreateInstance(const PluginPath & path) override;
|
||||
void DeleteInstance(ComponentInterface *instance) override;
|
||||
std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginPath & path) override;
|
||||
|
||||
// AudioUnitEffectModule implementation
|
||||
|
||||
|
|
|
@ -330,7 +330,8 @@ bool LadspaEffectsModule::IsPluginValid(const PluginPath & path, bool bFast)
|
|||
return wxFileName::FileExists(realPath);
|
||||
}
|
||||
|
||||
ComponentInterface *LadspaEffectsModule::CreateInstance(const PluginPath & path)
|
||||
std::unique_ptr<ComponentInterface>
|
||||
LadspaEffectsModule::CreateInstance(const PluginPath & path)
|
||||
{
|
||||
// Acquires a resource for the application.
|
||||
// For us, the path is two words.
|
||||
|
@ -339,16 +340,7 @@ ComponentInterface *LadspaEffectsModule::CreateInstance(const PluginPath & path)
|
|||
long index;
|
||||
wxString realPath = path.BeforeFirst(wxT(';'));
|
||||
path.AfterFirst(wxT(';')).ToLong(&index);
|
||||
|
||||
// Safety of this depends on complementary calls to DeleteInstance on the module manager side.
|
||||
return safenew LadspaEffect(realPath, (int)index);
|
||||
}
|
||||
|
||||
void LadspaEffectsModule::DeleteInstance(ComponentInterface *instance)
|
||||
{
|
||||
std::unique_ptr < LadspaEffect > {
|
||||
dynamic_cast<LadspaEffect *>(instance)
|
||||
};
|
||||
return std::make_unique<LadspaEffect>(realPath, (int)index);
|
||||
}
|
||||
|
||||
FilePaths LadspaEffectsModule::GetSearchPaths()
|
||||
|
|
|
@ -237,8 +237,8 @@ public:
|
|||
|
||||
bool IsPluginValid(const PluginPath & path, bool bFast) override;
|
||||
|
||||
ComponentInterface *CreateInstance(const PluginPath & path) override;
|
||||
void DeleteInstance(ComponentInterface *instance) override;
|
||||
std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginPath & path) override;
|
||||
|
||||
// LadspaEffectModule implementation
|
||||
|
||||
|
|
|
@ -302,24 +302,13 @@ bool LV2EffectsModule::IsPluginValid(const PluginPath & path, bool bFast)
|
|||
return GetPlugin(path) != NULL;
|
||||
}
|
||||
|
||||
ComponentInterface *LV2EffectsModule::CreateInstance(const PluginPath & path)
|
||||
std::unique_ptr<ComponentInterface>
|
||||
LV2EffectsModule::CreateInstance(const PluginPath & path)
|
||||
{
|
||||
// Acquires a resource for the application.
|
||||
const LilvPlugin *plug = GetPlugin(path);
|
||||
if (!plug)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Safety of this depends on complementary calls to DeleteInstance on the module manager side.
|
||||
return safenew LV2Effect(plug);
|
||||
}
|
||||
|
||||
void LV2EffectsModule::DeleteInstance(ComponentInterface *instance)
|
||||
{
|
||||
std::unique_ptr < LV2Effect > {
|
||||
dynamic_cast<LV2Effect *>(instance)
|
||||
};
|
||||
if (auto plug = GetPlugin(path))
|
||||
return std::make_unique<LV2Effect>(plug);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
@ -192,8 +192,8 @@ public:
|
|||
|
||||
bool IsPluginValid(const PluginPath & path, bool bFast) override;
|
||||
|
||||
ComponentInterface *CreateInstance(const PluginPath & path) override;
|
||||
void DeleteInstance(ComponentInterface *instance) override;
|
||||
std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginPath & path) override;
|
||||
|
||||
// LV2EffectModule implementation
|
||||
|
||||
|
|
|
@ -264,24 +264,14 @@ bool NyquistEffectsModule::IsPluginValid(const PluginPath & path, bool bFast)
|
|||
return wxFileName::FileExists(path);
|
||||
}
|
||||
|
||||
ComponentInterface *NyquistEffectsModule::CreateInstance(const PluginPath & path)
|
||||
std::unique_ptr<ComponentInterface>
|
||||
NyquistEffectsModule::CreateInstance(const PluginPath & path)
|
||||
{
|
||||
// Acquires a resource for the application.
|
||||
auto effect = std::make_unique<NyquistEffect>(path);
|
||||
if (effect->IsOk())
|
||||
{
|
||||
// Safety of this depends on complementary calls to DeleteInstance on the module manager side.
|
||||
return effect.release();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void NyquistEffectsModule::DeleteInstance(ComponentInterface *instance)
|
||||
{
|
||||
std::unique_ptr < NyquistEffect > {
|
||||
dynamic_cast<NyquistEffect *>(instance)
|
||||
};
|
||||
return effect;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
|
|
@ -51,6 +51,6 @@ public:
|
|||
|
||||
bool IsPluginValid(const PluginPath & path, bool bFast) override;
|
||||
|
||||
ComponentInterface *CreateInstance(const PluginPath & path) override;
|
||||
void DeleteInstance(ComponentInterface *instance) override;
|
||||
std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginPath & path) override;
|
||||
};
|
||||
|
|
|
@ -236,27 +236,16 @@ bool VampEffectsModule::IsPluginValid(const PluginPath & path, bool bFast)
|
|||
return bool(vp);
|
||||
}
|
||||
|
||||
ComponentInterface *VampEffectsModule::CreateInstance(const PluginPath & path)
|
||||
std::unique_ptr<ComponentInterface>
|
||||
VampEffectsModule::CreateInstance(const PluginPath & path)
|
||||
{
|
||||
// Acquires a resource for the application.
|
||||
int output;
|
||||
bool hasParameters;
|
||||
|
||||
auto vp = FindPlugin(path, output, hasParameters);
|
||||
if (vp)
|
||||
{
|
||||
// Safety of this depends on complementary calls to DeleteInstance on the module manager side.
|
||||
return safenew VampEffect(std::move(vp), path, output, hasParameters);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void VampEffectsModule::DeleteInstance(ComponentInterface *instance)
|
||||
{
|
||||
std::unique_ptr < VampEffect > {
|
||||
dynamic_cast<VampEffect *>(instance)
|
||||
};
|
||||
if (auto vp = FindPlugin(path, output, hasParameters))
|
||||
return std::make_unique<VampEffect>(std::move(vp), path, output, hasParameters);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// VampEffectsModule implementation
|
||||
|
|
|
@ -58,8 +58,8 @@ public:
|
|||
|
||||
bool IsPluginValid(const PluginPath & path, bool bFast) override;
|
||||
|
||||
ComponentInterface *CreateInstance(const PluginPath & path) override;
|
||||
void DeleteInstance(ComponentInterface *instance) override;
|
||||
std::unique_ptr<ComponentInterface>
|
||||
CreateInstance(const PluginPath & path) override;
|
||||
|
||||
private:
|
||||
// VampEffectModule implementation
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../CommonCommandFlags.h"
|
||||
#include "../Menus.h"
|
||||
#include "../PluginManager.h"
|
||||
#include "../PluginRegistrationDialog.h"
|
||||
#include "../Prefs.h"
|
||||
#include "../Project.h"
|
||||
#include "../ProjectSettings.h"
|
||||
|
@ -36,10 +37,20 @@ AudacityProject::AttachedWindows::RegisteredFactory sMacrosWindowKey{
|
|||
}
|
||||
};
|
||||
|
||||
bool ShowManager(
|
||||
PluginManager &pm, wxWindow *parent, EffectType type)
|
||||
{
|
||||
pm.CheckForUpdates();
|
||||
|
||||
PluginRegistrationDialog dlg(parent, type);
|
||||
return dlg.ShowModal() == wxID_OK;
|
||||
}
|
||||
|
||||
void DoManagePluginsMenu(AudacityProject &project, EffectType type)
|
||||
{
|
||||
auto &window = GetProjectFrame( project );
|
||||
if (PluginManager::Get().ShowManager(&window, type))
|
||||
auto &pm = PluginManager::Get();
|
||||
if (ShowManager(pm, &window, type))
|
||||
MenuCreator::RebuildAllMenuBars();
|
||||
}
|
||||
|
||||
|
@ -302,9 +313,8 @@ MenuTable::BaseItemPtrs PopulateEffectsMenu(
|
|||
std::vector<const PluginDescriptor*> 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 +332,6 @@ MenuTable::BaseItemPtrs PopulateEffectsMenu(
|
|||
defplugs.push_back(plug);
|
||||
else
|
||||
optplugs.push_back(plug);
|
||||
plug = pm.GetNextPluginForEffectType(type);
|
||||
}
|
||||
|
||||
wxString groupby = EffectsGroupBy.Read();
|
||||
|
|
|
@ -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 } );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue