1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-01 08:09:41 +02:00

EffectsPrefs discovers all registered effect families...

... instead of keeping an exhaustive list of them with hardcoded preference
paths.  And some duplication of string literals for those paths is eliminated.

One small piece of improvements of preference path handling.
This commit is contained in:
Paul Licameli 2019-11-26 12:02:03 -05:00
commit 5459a7bf27
20 changed files with 233 additions and 57 deletions

View File

@ -76,6 +76,11 @@ public:
// Called just prior to deletion to allow releasing any resources.
virtual void Terminate() = 0;
// A symbol identifying the family of plugin provided by this module;
// if it is not empty, then the family as a whole can be enabled or
// disabled by the user in Preferences
virtual EffectFamilySymbol GetOptionalFamilySymbol() = 0;
// "Paths" returned by FindPluginPaths() and passed back to
// DiscoverPluginsAtPath() have module-specific meaning.
// They are not necessarily file system paths to existent files that

View File

@ -439,7 +439,6 @@ private:
void OnDisable(wxCommandEvent & evt);
private:
ModuleInterface *mMod;
EffectType mType;
int mFilter;
@ -1397,6 +1396,36 @@ const PluginID &PluginManagerInterface::AudacityCommandRegistrationCallback(
return empty;
}
RegistryPath PluginManager::GetPluginEnabledSetting( const PluginID &ID )
{
auto pPlugin = GetPlugin( ID );
if ( pPlugin )
return GetPluginEnabledSetting( *pPlugin );
return {};
}
RegistryPath PluginManager::GetPluginEnabledSetting(
const PluginDescriptor &desc )
{
switch ( desc.GetPluginType() ) {
case PluginTypeModule: {
// Retrieve optional family symbol that was recorded in
// RegisterPlugin() for the module
auto family = desc.GetEffectFamily();
if ( family.empty() ) // as for built-in effect and command modules
return {};
else
return wxT('/') + family + wxT("/Enable");
}
case PluginTypeEffect:
// do NOT use GetEffectFamily() for this descriptor, but instead,
// delegate to the plugin descriptor of the provider, which may
// be different (may be empty)
return GetPluginEnabledSetting( desc.GetProviderID() );
default:
return {};
}
}
bool PluginManager::IsPluginRegistered(const PluginPath &path)
{
@ -1414,6 +1443,7 @@ bool PluginManager::IsPluginRegistered(const PluginPath &path)
const PluginID & PluginManager::RegisterPlugin(ModuleInterface *module)
{
PluginDescriptor & plug = CreatePlugin(GetID(module), module, PluginTypeModule);
plug.SetEffectFamily(module->GetOptionalFamilySymbol().Internal());
plug.SetEnabled(true);
plug.SetValid(true);
@ -2510,9 +2540,13 @@ const PluginDescriptor *PluginManager::GetFirstPlugin(int type)
if( plug.IsValid() && plug.IsEnabled() && ((plugType & type) != 0))
{
bool familyEnabled = true;
if( (plugType & PluginTypeEffect) != 0)
if( (plugType & PluginTypeEffect) != 0) {
// This preference may be written by EffectsPrefs
gPrefs->Read(plug.GetEffectFamily() + wxT("/Enable"), &familyEnabled, true);
auto setting = GetPluginEnabledSetting( plug );
familyEnabled = setting.empty()
? true
: gPrefs->Read( setting, true );
}
if (familyEnabled)
return &mPluginsIter->second;
}
@ -2530,9 +2564,13 @@ const PluginDescriptor *PluginManager::GetNextPlugin(int type)
if( plug.IsValid() && plug.IsEnabled() && ((plugType & type) != 0))
{
bool familyEnabled = true;
if( (plugType & PluginTypeEffect) != 0)
if( (plugType & PluginTypeEffect) != 0) {
// This preference may be written by EffectsPrefs
gPrefs->Read(plug.GetEffectFamily() + wxT("/Enable"), &familyEnabled, true);
auto setting = GetPluginEnabledSetting( plug );
familyEnabled = setting.empty()
? true
: gPrefs->Read( setting, true );
}
if (familyEnabled)
return &mPluginsIter->second;
}
@ -2549,7 +2587,10 @@ const PluginDescriptor *PluginManager::GetFirstPluginForEffectType(EffectType ty
bool familyEnabled;
// This preference may be written by EffectsPrefs
gPrefs->Read(plug.GetEffectFamily() + wxT("/Enable"), &familyEnabled, true);
auto setting = GetPluginEnabledSetting( plug );
familyEnabled = setting.empty()
? true
: gPrefs->Read( setting, true );
if (plug.IsValid() && plug.IsEnabled() && plug.GetEffectType() == type && familyEnabled)
{
return &plug;
@ -2566,7 +2607,10 @@ const PluginDescriptor *PluginManager::GetNextPluginForEffectType(EffectType typ
PluginDescriptor & plug = mPluginsIter->second;
bool familyEnabled;
// This preference may be written by EffectsPrefs
gPrefs->Read(plug.GetEffectFamily() + wxT("/Enable"), &familyEnabled, true);
auto setting = GetPluginEnabledSetting( plug );
familyEnabled = setting.empty()
? true
: gPrefs->Read( setting, true );
if (plug.IsValid() && plug.IsEnabled() && plug.GetEffectType() == type && familyEnabled)
{
return &plug;

View File

@ -173,6 +173,9 @@ class PluginManager final : public PluginManagerInterface
{
public:
RegistryPath GetPluginEnabledSetting( const PluginID &ID );
RegistryPath GetPluginEnabledSetting( const PluginDescriptor &desc );
// PluginManagerInterface implementation
bool IsPluginRegistered(const PluginPath &path) override;

View File

@ -224,6 +224,12 @@ void BuiltinCommandsModule::Terminate()
return;
}
EffectFamilySymbol BuiltinCommandsModule::GetOptionalFamilySymbol()
{
// Commands are not enabled and disabled in EffectsPrefs
return {};
}
const FileExtensions &BuiltinCommandsModule::GetFileExtensions()
{
static FileExtensions empty;

View File

@ -39,6 +39,7 @@ public:
bool Initialize() override;
void Terminate() override;
EffectFamilySymbol GetOptionalFamilySymbol() override;
const FileExtensions &GetFileExtensions() override;
FilePath InstallPath() override { return {}; }

View File

@ -290,6 +290,13 @@ void BuiltinEffectsModule::Terminate()
return;
}
EffectFamilySymbol BuiltinEffectsModule::GetOptionalFamilySymbol()
{
// Returns empty, because there should not be an option in Preferences to
// disable the built-in effects.
return {};
}
const FileExtensions &BuiltinEffectsModule::GetFileExtensions()
{
static FileExtensions empty;

View File

@ -38,6 +38,7 @@ public:
bool Initialize() override;
void Terminate() override;
EffectFamilySymbol GetOptionalFamilySymbol() override;
const FileExtensions &GetFileExtensions() override;
FilePath InstallPath() override { return {}; }

View File

@ -366,6 +366,15 @@ void VSTEffectsModule::Terminate()
return;
}
EffectFamilySymbol VSTEffectsModule::GetOptionalFamilySymbol()
{
#if USE_VST
return VSTPLUGINTYPE;
#else
return {};
#endif
}
const FileExtensions &VSTEffectsModule::GetFileExtensions()
{
static FileExtensions result{{ _T("vst") }};

View File

@ -417,6 +417,7 @@ public:
bool Initialize() override;
void Terminate() override;
EffectFamilySymbol GetOptionalFamilySymbol() override;
const FileExtensions &GetFileExtensions() override;
FilePath InstallPath() override;

View File

@ -153,6 +153,15 @@ void AudioUnitEffectsModule::Terminate()
return;
}
EffectFamilySymbol AudioUnitEffectsModule::GetOptionalFamilySymbol()
{
#if USE_AUDIO_UNITS
return AUDIOUNITEFFECTS_FAMILY;
#else
return {};
#endif
}
bool AudioUnitEffectsModule::AutoRegisterPlugins(PluginManagerInterface & pm)
{
// Nothing to be done here

View File

@ -241,6 +241,7 @@ public:
bool Initialize() override;
void Terminate() override;
EffectFamilySymbol GetOptionalFamilySymbol() override;
const FileExtensions &GetFileExtensions() override;
FilePath InstallPath() override { return {}; }

View File

@ -162,6 +162,15 @@ void LadspaEffectsModule::Terminate()
return;
}
EffectFamilySymbol LadspaEffectsModule::GetOptionalFamilySymbol()
{
#if USE_LADSPA
return LADSPAEFFECTS_FAMILY;
#else
return {};
#endif
}
const FileExtensions &LadspaEffectsModule::GetFileExtensions()
{
static FileExtensions result{{

View File

@ -222,6 +222,7 @@ public:
bool Initialize() override;
void Terminate() override;
EffectFamilySymbol GetOptionalFamilySymbol() override;
const FileExtensions &GetFileExtensions() override;
FilePath InstallPath() override;

View File

@ -207,6 +207,15 @@ void LV2EffectsModule::Terminate()
return;
}
EffectFamilySymbol LV2EffectsModule::GetOptionalFamilySymbol()
{
#if USE_LV2
return LV2EFFECTS_FAMILY;
#else
return {};
#endif
}
const FileExtensions &LV2EffectsModule::GetFileExtensions()
{
static FileExtensions empty;

View File

@ -85,6 +85,7 @@ public:
bool Initialize() override;
void Terminate() override;
EffectFamilySymbol GetOptionalFamilySymbol() override;
const FileExtensions &GetFileExtensions() override;
FilePath InstallPath() override { return {}; }

View File

@ -154,6 +154,15 @@ void NyquistEffectsModule::Terminate()
return;
}
EffectFamilySymbol NyquistEffectsModule::GetOptionalFamilySymbol()
{
#if USE_NYQUIST
return NYQUISTEFFECTS_FAMILY;
#else
return {};
#endif
}
const FileExtensions &NyquistEffectsModule::GetFileExtensions()
{
static FileExtensions result{{ _T("ny") }};

View File

@ -36,6 +36,8 @@ public:
bool Initialize() override;
void Terminate() override;
EffectFamilySymbol GetOptionalFamilySymbol() override;
const FileExtensions &GetFileExtensions() override;
FilePath InstallPath() override;

View File

@ -111,6 +111,15 @@ void VampEffectsModule::Terminate()
return;
}
EffectFamilySymbol VampEffectsModule::GetOptionalFamilySymbol()
{
#if USE_VAMP
return VAMPEFFECTS_FAMILY;
#else
return {};
#endif
}
const FileExtensions &VampEffectsModule::GetFileExtensions()
{
static FileExtensions empty;

View File

@ -44,6 +44,7 @@ public:
bool Initialize() override;
void Terminate() override;
EffectFamilySymbol GetOptionalFamilySymbol() override;
const FileExtensions &GetFileExtensions() override;
FilePath InstallPath() override { return {}; }

View File

@ -26,6 +26,7 @@
#include <wx/defs.h>
#include "../Languages.h"
#include "../PluginManager.h"
#include "../Prefs.h"
#include "../ShuttleGui.h"
@ -65,6 +66,95 @@ void EffectsPrefs::Populate()
// ----------------------- End of main section --------------
}
namespace {
// Rather than hard-code an exhaustive list of effect families in this file,
// pretend we don't know, but discover them instead by querying the module and
// effect managers.
// But then we would like to have prompts with accelerator characters that are
// distinct. We collect some prompts in the following map.
// It is not required that each module be found here, nor that each module
// mentioned here be found.
const std::map< wxString, wxString > SuggestedPrompts{
/* i18n-hint: Audio Unit is the name of an Apple audio software protocol */
{ wxT("AudioUnit"), XO("Audio Unit") },
/* i18n-hint: abbreviates "Linux Audio Developer's Simple Plugin API"
(Application programming interface)
*/
{ wxT("LADSPA"), XO("&LADSPA") },
/* i18n-hint: abbreviates
"Linux Audio Developer's Simple Plugin API (LADSPA) version 2" */
{ wxT("LV2"), XO("LV&2") },
/* i18n-hint: "Nyquist" is an embedded interpreted programming language in
Audacity, named in honor of the Swedish-American Harry Nyquist (or Nyqvist).
In the translations of this and other strings, you may transliterate the
name into another alphabet. */
{ wxT("Nyquist"), XO("N&yquist") },
/* i18n-hint: Vamp is the proper name of a software protocol for sound analysis.
It is not an abbreviation for anything. See http://vamp-plugins.org */
{ wxT("Vamp"), XO("&Vamp") },
/* i18n-hint: Abbreviates Virtual Studio Technology, an audio software protocol
developed by Steinberg GmbH */
{ wxT("VST"), XO("V&ST") },
};
// Collect needed prompts and settings paths, at most once, on demand
struct Entry {
wxString prompt; // untranslated
wxString setting;
};
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();
if ( internal.empty() )
continue;
wxString prompt;
auto iter = SuggestedPrompts.find( internal );
if ( iter == SuggestedPrompts.end() )
// For the built-in modules this Msgid includes " Effects",
// but those strings were never shown to the user,
// and the prompts in the table above do not include it.
// 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();
else
prompt = iter->second;
auto setting = pm.GetPluginEnabledSetting( *plug );
push_back( { prompt, setting } );
}
// Guarantee some determinate ordering
std::sort( begin(), end(),
[]( const Entry &a, const Entry &b ){
return a.setting < b.setting;
}
);
}
};
static ModuleData theData;
return theData;
}
}
void EffectsPrefs::PopulateOrExchange(ShuttleGui & S)
{
S.SetBorder(2);
@ -72,56 +162,14 @@ void EffectsPrefs::PopulateOrExchange(ShuttleGui & S)
S.StartStatic(_("Enable Effects"));
{
#if USE_AUDIO_UNITS
/* i18n-hint: Audio Unit is the name of an Apple audio software protocol */
S.TieCheckBox(_("Audio Unit"),
wxT("/AudioUnit/Enable"),
true);
#endif
// JKC: LADSPA, LV2, Nyquist, VST, VAMP should not be translated.
#if USE_LADSPA
/* i18n-hint: abbreviates "Linux Audio Developer's Simple Plugin API"
(Application programming interface)
*/
S.TieCheckBox(_("&LADSPA"),
wxT("/LADSPA/Enable"),
true);
#endif
#if USE_LV2
/* i18n-hint: abbreviates
"Linux Audio Developer's Simple Plugin API (LADSPA) version 2" */
S.TieCheckBox(_("LV&2"),
wxT("/LV2/Enable"),
true);
#endif
#if USE_NYQUIST
/* i18n-hint: "Nyquist" is an embedded interpreted programming language in
Audacity, named in honor of the Swedish-American Harry Nyquist (or Nyqvist).
In the translations of this and other strings, you may transliterate the
name into another alphabet. */
S.TieCheckBox(_("N&yquist"),
wxT("/Nyquist/Enable"),
true);
#endif
#if USE_VAMP
/* i18n-hint: Vamp is the proper name of a software protocol for sound analysis.
It is not an abbreviation for anything. See http://vamp-plugins.org */
S.TieCheckBox(_("&Vamp"),
wxT("/Vamp/Enable"),
true);
#endif
#if USE_VST
/* i18n-hint: Abbreviates Virtual Studio Technology, an audio software protocol
developed by Steinberg GmbH */
S.TieCheckBox(_("V&ST"),
wxT("/VST/Enable"),
true);
#endif
for ( const auto &entry : GetModuleData() )
{
S.TieCheckBox(
GetCustomTranslation( entry.prompt ),
entry.setting,
true
);
}
}
S.EndStatic();