1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-08 16:39:59 +02:00

Implement drag-and-drop of Nyquist, LADSPA, VST plug-ins...

... I'm not sure how to make it work for AudioUnits, LV2, or Vamp, for which
the API for identifying a plug-in doesn't map straightforwardly to a file name.
This commit is contained in:
Paul Licameli 2017-12-28 19:15:26 -05:00
parent 8cfb8d2400
commit 2c2db0fe09
4 changed files with 122 additions and 0 deletions

View File

@ -224,6 +224,10 @@
// scrolling past zero is enabled. Perhaps that lessens confusion.
#define EXPERIMENTAL_TWO_TONE_TIME_RULER
// Paul Licameli (PRL) 28 Dec 2017
// Easy drag-and-drop to add Nyquist, LADSPA, and VST plug-ins
#define EXPERIMENTAL_DRAG_DROP_PLUG_INS
#ifndef IN_RC
// Define to include crash reporting
#include <wx/defs.h>

View File

@ -1747,6 +1747,111 @@ void PluginManager::Terminate()
}
}
bool PluginManager::DropFile(const wxString &fileName)
{
auto &mm = ModuleManager::Get();
for (const PluginDescriptor *plug = GetFirstPlugin(PluginTypeModule);
plug;
plug = GetNextPlugin(PluginTypeModule))
{
auto module = static_cast<ModuleInterface *>
(mm.CreateProviderInstance(plug->GetID(), plug->GetPath()));
const auto &ff = module->InstallPath();
if (!ff.empty() && module->PathsAreFiles()) {
wxString errMsg;
// Do dry-run test of the file format
unsigned nPlugIns = module->DiscoverPluginsAtPath(fileName, errMsg,
[](ModuleInterface *, EffectIdentInterface *){});
if (nPlugIns) {
// File contents are good for this module, so check no others.
// All branches of this block return true, even in case of
// failure for other reasons, to signal that other drag-and-drop
// actions should not be tried.
// Find path to copy it
const wxFileName src{ fileName };
wxFileName dst;
dst.AssignDir( ff );
dst.SetFullName( src.GetFullName() );
if ( dst.Exists() ) {
// Query whether to overwrite
bool overwrite = (wxYES == ::wxMessageBox(
wxString::Format(_("Overwrite the plug-in file %s ?"),
dst.GetFullPath() ),
_("Plug-in already exists"),
wxYES_NO
) );
if ( !overwrite )
return true;
}
// Move the file or subtree
bool copied = false;
auto dstPath = dst.GetFullPath();
if ( src.FileExists() )
// A simple one-file plug-in
copied = FileNames::CopyFile(
src.GetFullPath(), dstPath, true );
else {
// A sub-folder
// such as for some VST packages
// Recursive copy needed -- to do
return true;
}
if (!copied) {
::wxMessageBox(
_("Plug-in file is in use. Failed to overwrite"));
return true;
}
// Register for real
std::vector<PluginID> ids;
std::vector<wxString> names;
nPlugIns = module->DiscoverPluginsAtPath(dstPath, errMsg,
[&](ModuleInterface *provider, EffectIdentInterface *ident){
// Register as by default, but also collecting the PluginIDs
// and names
ids.push_back(
PluginManagerInterface::DefaultRegistrationCallback(
provider, ident) );
names.push_back( wxGetTranslation( ident->GetName() ) );
});
if ( ! nPlugIns ) {
// Unlikely after the dry run succeeded
::wxMessageBox( wxString::Format(
_("Failed to register:\n%s"), errMsg ) );
return true;
}
// Ask whether to enable the plug-ins
if (auto nIds = ids.size()) {
auto format = wxPLURAL(
_("Enable this plug-in?"),
_("Enable these plug-ins?"),
nIds
);
format += wxT("\n");
for (const auto &name : names)
format += name + wxT("\n");
bool enable = (wxYES == ::wxMessageBox(
wxString::Format( format, nIds ),
_("Enable new plug-ins"),
wxYES_NO
) );
for (const auto &id : ids)
mPlugins[id].SetEnabled(enable);
}
return true;
}
}
}
return false;
}
void PluginManager::Load()
{
// Create/Open the registry

View File

@ -228,6 +228,8 @@ public:
void Initialize();
void Terminate();
bool DropFile(const wxString &fileName);
static PluginManager & Get();
static PluginID GetID(ModuleInterface *module);

View File

@ -461,6 +461,17 @@ public:
} );
for (const auto &name : sortednames) {
#ifdef EXPERIMENTAL_DRAG_DROP_PLUG_INS
// Is it a plug-in?
if (PluginManager::Get().DropFile(name)) {
mProject->RebuildAllMenuBars();
continue;
}
// No, so import.
#endif
if (Importer::IsMidi(name))
AudacityProject::DoImportMIDI(mProject, name);
else