1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-12-16 09:31:14 +01:00

Automation: AudacityCommand

This is a squash of 50 commits.

This merges the capabilities of BatchCommands and Effects using a new
AudacityCommand class.  AudacityCommand provides one function to specify the
parameters, and then we leverage that one function in automation, whether by chains,
mod-script-pipe or (future) Nyquist.

- Now have AudacityCommand which is using the same mechanism as Effect
- Has configurable parameters
- Has data-entry GUI (built using shuttle GUI)
- Registers with PluginManager.
- Menu commands now provided in chains, and to python batch.
   - Tested with Zoom Toggle.

- ShuttleParams now can set, get, set defaults, validate and specify
the parameters.
- Bugfix: Don't overwrite values with defaults first time out.
- Add DefineParams function for all built-in effects.
- Extend CommandContext to carry output channels for results.

We abuse EffectsManager.  It handles both Effects and
AudacityCommands now.  In time an Effect should become a special case of
AudacityCommand and we'll split and rename the EffectManager class.

- Don't use 'default' as a parameter name.
- Massive renaming for CommandDefinitionInterface
- EffectIdentInterface becomes EffectDefinitionInterface
- EffectAutomationParameters becomes CommandAutomationParameters
- PluginType is now a bit field.

This way we can search for related types at the same time.

- Most old batch commands made into AudacityCommands.
The ones that weren't are for a reason.  They are used by mod-script-pipe
to carry commands and responses across from a non-GUI thread to the GUI
thread.

- Major tidy up of ScreenshotCommand
- Reworking of SelectCommand
- GetPreferenceCommand and SetPreferenceCommand
- GetTrackInfo and SetTrackInfo
- GetInfoCommand
- Help, Open, Save, Import and Export commands.
- Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo
  which are now better handled by other commands.

- JSONify "GetInfo: Commands" output, i.e. commas in the right places.

- General work on better Doxygen.
    - Lyrics -> LyricsPanel
    - Meter -> MeterPanel
- Updated Linux makefile.
- Scripting commands added into Extra menu.
- Distinct names for previously duplicated find-clipping parameters.
- Fixed longstanding error with erroneous status field number which
  previously caused an ASSERT in debug.
- Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
This commit is contained in:
James Crook
2018-01-14 18:51:41 +00:00
committed by Paul Licameli
parent b7b01d48e0
commit 1c988b4e3a
191 changed files with 4659 additions and 2768 deletions

View File

@@ -11,7 +11,12 @@
\file PluginManager.cpp
\brief
*//*******************************************************************/
************************************************************************//**
\class PluginManager
\brief PluginManager maintains a list of all plug ins. That covers modules,
effects, generators, analysis-effects, commands. It also has functions
for shared and private configs - which need to move out.
*****************************************************************************/
#include <algorithm>
@@ -952,7 +957,8 @@ void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt))
mLongestPath + wxT("\n");
wxString msg;
msg.Printf(_("Enabling effects:\n\n%s"), last3);
msg.Printf(_("Enabling effects or commands:\n\n%s"), 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.
@@ -970,7 +976,7 @@ void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt))
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, wxString::Format(_("Enabling effect:\n\n%s"), last3));
auto status = progress.Update(++i, enableCount, wxString::Format(_("Enabling effect or command:\n\n%s"), last3));
if (status == ProgressResult::Cancelled)
{
break;
@@ -982,7 +988,7 @@ void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt))
for (size_t j = 0, cnt = item.plugs.size(); j < cnt; j++)
{
wxString errMsg;
if (mm.RegisterPlugin(item.plugs[j]->GetProviderID(), path,
if (mm.RegisterEffectPlugin(item.plugs[j]->GetProviderID(), path,
errMsg))
{
for (size_t j = 0, cnt = item.plugs.size(); j < cnt; j++)
@@ -1000,7 +1006,7 @@ void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt))
}
if (!errMsgs.empty())
AudacityMessageBox( wxString::Format(
_("Effect at %s failed to register:\n%s"),
_("Effect or Command at %s failed to register:\n%s"),
path, errMsgs
) );
}
@@ -1370,11 +1376,21 @@ void PluginDescriptor::SetImporterExtensions(const wxArrayString & extensions)
// ============================================================================
const PluginID &PluginManagerInterface::DefaultRegistrationCallback(
ModuleInterface *provider, EffectIdentInterface *pInterface )
ModuleInterface *provider, CommandDefinitionInterface *pInterface )
{
EffectDefinitionInterface * pEInterface = dynamic_cast<EffectDefinitionInterface*>(pInterface);
if( pEInterface )
return PluginManager::Get().RegisterPlugin(provider, pEInterface, PluginTypeEffect);
return PluginManager::Get().RegisterPlugin(provider, pInterface);
}
const PluginID &PluginManagerInterface::GenericRegistrationCallback(
ModuleInterface *provider, CommandDefinitionInterface *pInterface )
{
return PluginManager::Get().RegisterPlugin(provider, pInterface);
}
bool PluginManager::IsPluginRegistered(const wxString & path)
{
for (PluginMap::iterator iter = mPlugins.begin(); iter != mPlugins.end(); ++iter)
@@ -1398,9 +1414,28 @@ const PluginID & PluginManager::RegisterPlugin(ModuleInterface *module)
return plug.GetID();
}
const PluginID & PluginManager::RegisterPlugin(ModuleInterface *provider, EffectIdentInterface *effect)
const PluginID & PluginManager::RegisterPlugin(ModuleInterface *provider, CommandDefinitionInterface *command)
{
PluginDescriptor & plug = CreatePlugin(GetID(effect), effect, PluginTypeEffect);
PluginDescriptor & plug = CreatePlugin(GetID(command), command, (PluginType)PluginTypeGeneric);
plug.SetProviderID(PluginManager::GetID(provider));
//plug.SetEffectType(effect->GetType());
//plug.SetEffectFamily(effect->GetFamily());
//plug.SetEffectInteractive(effect->IsInteractive());
//plug.SetEffectDefault(effect->IsDefault());
//plug.SetEffectRealtime(effect->SupportsRealtime());
//plug.SetEffectAutomatable(effect->SupportsAutomation());
plug.SetEnabled(true);
plug.SetValid(true);
return plug.GetID();
}
const PluginID & PluginManager::RegisterPlugin(ModuleInterface *provider, EffectDefinitionInterface *effect, int type)
{
PluginDescriptor & plug = CreatePlugin(GetID(effect), effect, (PluginType)type);
plug.SetProviderID(PluginManager::GetID(provider));
@@ -1805,15 +1840,14 @@ bool PluginManager::DropFile(const wxString &fileName)
std::vector<PluginID> ids;
std::vector<wxString> names;
nPlugIns = module->DiscoverPluginsAtPath(dstPath, errMsg,
[&](ModuleInterface *provider, EffectIdentInterface *ident){
[&](ModuleInterface *provider, CommandDefinitionInterface *ident){
// Register as by default, but also collecting the PluginIDs
// and names
const auto &id =
PluginManagerInterface::DefaultRegistrationCallback(
const PluginID * id = &PluginManagerInterface::DefaultRegistrationCallback(
provider, ident);
ids.push_back(id);
ids.push_back(*id);
names.push_back( wxGetTranslation( ident->GetName() ) );
return id;
return *id;
});
if ( ! nPlugIns ) {
// Unlikely after the dry run succeeded
@@ -1877,6 +1911,7 @@ void PluginManager::Load()
// Now the rest
LoadGroup(&registry, PluginTypeEffect);
LoadGroup(&registry, PluginTypeGeneric );
LoadGroup(&registry, PluginTypeExporter);
LoadGroup(&registry, PluginTypeImporter);
@@ -2174,12 +2209,13 @@ void PluginManager::Save()
// Save the individual groups
SaveGroup(&registry, PluginTypeEffect);
SaveGroup(&registry, PluginTypeExporter);
SaveGroup(&registry, PluginTypeGeneric);
SaveGroup(&registry, PluginTypeImporter);
SaveGroup(&registry, PluginTypeStub);
// Not used by 2.1.1 or greater, but must save to allow users to switch between 2.1.0
// and 2.1.1+. This should be removed after a few releases past 2.1.0.
SaveGroup(&registry, PluginTypeNone);
//SaveGroup(&registry, PluginTypeNone);
// And now the providers
SaveGroup(&registry, PluginTypeModule);
@@ -2377,9 +2413,9 @@ bool PluginManager::ShowManager(wxWindow *parent, EffectType type)
// Here solely for the purpose of Nyquist Workbench until
// a better solution is devised.
const PluginID & PluginManager::RegisterPlugin(EffectIdentInterface *effect)
const PluginID & PluginManager::RegisterPlugin(EffectDefinitionInterface *effect, PluginType type)
{
PluginDescriptor & plug = CreatePlugin(GetID(effect), effect, PluginTypeEffect);
PluginDescriptor & plug = CreatePlugin(GetID(effect), effect, type);
plug.SetEffectType(effect->GetType());
plug.SetEffectFamilyId(effect->GetFamilyId());
@@ -2433,40 +2469,40 @@ const PluginDescriptor *PluginManager::GetPlugin(const PluginID & ID)
return &mPlugins[ID];
}
const PluginDescriptor *PluginManager::GetFirstPlugin(PluginType type)
const PluginDescriptor *PluginManager::GetFirstPlugin(int type)
{
for (mPluginsIter = mPlugins.begin(); mPluginsIter != mPlugins.end(); ++mPluginsIter)
{
PluginDescriptor & plug = mPluginsIter->second;
bool familyEnabled = true;
if (type == PluginTypeEffect)
PluginType plugType = plug.GetPluginType();
if( plug.IsValid() && plug.IsEnabled() && ((plugType & type) != 0))
{
// This preference may be written by EffectsPrefs
gPrefs->Read(plug.GetEffectFamilyId() + wxT("/Enable"), &familyEnabled, true);
}
if (plug.IsValid() && plug.IsEnabled() && plug.GetPluginType() == type && familyEnabled)
{
return &mPluginsIter->second;
bool familyEnabled = true;
if( (plugType & PluginTypeEffect) != 0)
// This preference may be written by EffectsPrefs
gPrefs->Read(plug.GetEffectFamilyId() + wxT("/Enable"), &familyEnabled, true);
if (familyEnabled)
return &mPluginsIter->second;
}
}
return NULL;
}
const PluginDescriptor *PluginManager::GetNextPlugin(PluginType type)
const PluginDescriptor *PluginManager::GetNextPlugin(int type)
{
while (++mPluginsIter != mPlugins.end())
{
PluginDescriptor & plug = mPluginsIter->second;
bool familyEnabled = true;
if (type == PluginTypeEffect)
PluginType plugType = plug.GetPluginType();
if( plug.IsValid() && plug.IsEnabled() && ((plugType & type) != 0))
{
// This preference may be written by EffectsPrefs
gPrefs->Read(plug.GetEffectFamilyId() + wxT("/Enable"), &familyEnabled, true);
}
if (plug.IsValid() && plug.IsEnabled() && plug.GetPluginType() == type && familyEnabled)
{
return &mPluginsIter->second;
bool familyEnabled = true;
if( (plugType & PluginTypeEffect) != 0)
// This preference may be written by EffectsPrefs
gPrefs->Read(plug.GetEffectFamilyId() + wxT("/Enable"), &familyEnabled, true);
if (familyEnabled)
return &mPluginsIter->second;
}
}
@@ -2596,7 +2632,17 @@ PluginID PluginManager::GetID(ModuleInterface *module)
module->GetPath());
}
PluginID PluginManager::GetID(EffectIdentInterface *effect)
PluginID PluginManager::GetID(CommandDefinitionInterface *command)
{
return wxString::Format(wxT("%s_%s_%s_%s_%s"),
GetPluginTypeString(PluginTypeGeneric),
wxEmptyString,
command->GetVendor(),
command->GetName(),
command->GetPath());
}
PluginID PluginManager::GetID(EffectDefinitionInterface *effect)
{
return wxString::Format(wxT("%s_%s_%s_%s_%s"),
GetPluginTypeString(PluginTypeEffect),
@@ -2624,6 +2670,7 @@ wxString PluginManager::GetPluginTypeString(PluginType type)
switch (type)
{
default:
case PluginTypeNone:
str = wxT("Placeholder");
break;
@@ -2633,6 +2680,9 @@ wxString PluginManager::GetPluginTypeString(PluginType type)
case PluginTypeEffect:
str = wxT("Effect");
break;
case PluginTypeGeneric:
str = wxT("Generic");
break;
case PluginTypeExporter:
str = wxT("Exporter");
break;