Another round of effects bashing.
I've added some of the new plugin stuff to LV2, Nyquist, and Vamp so that they play better in the new system. They no longer get bunched in with the Audacity effects when sorting or grouping the menus. They have not been fully converted but they should be good for 2.1.0. Nyquist plugins now include ";author" and ";copyright" statements. Added the 4 new Nyquist plugins to the Windows build. Audiounits are still coming...had to push them to the back burner to get this other stuff out of the way. Scanning for new plugins has been improved so that newly discovered ones will be shown to the user when Audacity starts. Effects menu sorting has been fixed and improved. Disabling effect types in Preferences works again and you no longer have to restart Audacity for them the change to work. Effect usage in chains works again. Plugin registration dialog code simplified a bit. Group names in the pluginregistry are now base64 encoded. I never really thought about it, but wxFileConfig group names are case insensitive and since I was using the group name as the plugin ID, I ran into a conflict on Linux where there were two plugins with the same name, just different case. (And they were different plugins.) Hoping all of this will change when/if the config file gets converted to XML. (wx3 if finally including XML support) A fair amount of cleanup of this new code has been done and will continue as more stuff is converted.
This commit is contained in:
parent
393109afa3
commit
41083f74cc
|
@ -172,6 +172,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -89,6 +89,10 @@ public:
|
|||
virtual bool RegisterPlugin(PluginManagerInterface & pluginManager,
|
||||
const wxString & path) = 0;
|
||||
|
||||
// For modules providing an interface to other dynamically loaded plugins,
|
||||
// the module returns true if the plugin is still valid, otherwise false.
|
||||
virtual bool IsPluginValid(const PluginID & ID, const wxString & path) = 0;
|
||||
|
||||
// When appropriate, CreateInstance() will be called to instantiate the plugin.
|
||||
virtual IdentInterface *CreateInstance(const PluginID & ID, const wxString & path) = 0;
|
||||
|
||||
|
|
|
@ -122,9 +122,69 @@ typedef enum
|
|||
ChannelNameBottomFrontRight,
|
||||
} ChannelName;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Convenience macro to suppress unused parameter warnings
|
||||
// ----------------------------------------------------------------------------
|
||||
#define AUNUSED(p)
|
||||
// LLL FIXME: Until a complete API is devised, we have to use
|
||||
// AUDACITY_DLL_API when defining API classes. This
|
||||
// it ugly, but a part of the game. Remove it when
|
||||
// the API is complete.
|
||||
|
||||
#if !defined(AUDACITY_DLL_API)
|
||||
// This was copied from "Audacity.h" so these headers wouldn't have
|
||||
// to include it.
|
||||
|
||||
/* Magic for dynamic library import and export. This is unfortunately
|
||||
* compiler-specific because there isn't a standard way to do it. Currently it
|
||||
* works with the Visual Studio compiler for windows, and for GCC 4+. Anything
|
||||
* else gets all symbols made public, which gets messy */
|
||||
/* The Visual Studio implementation */
|
||||
#ifdef _MSC_VER
|
||||
#ifndef AUDACITY_DLL_API
|
||||
#ifdef BUILDING_AUDACITY
|
||||
#define AUDACITY_DLL_API _declspec(dllexport)
|
||||
#else
|
||||
#ifdef _DLL
|
||||
#define AUDACITY_DLL_API _declspec(dllimport)
|
||||
#else
|
||||
#define AUDACITY_DLL_API
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif //_MSC_VER
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include "configunix.h"
|
||||
#endif
|
||||
|
||||
/* The GCC-elf implementation */
|
||||
#ifdef HAVE_VISIBILITY // this is provided by the configure script, is only
|
||||
// enabled for suitable GCC versions
|
||||
/* The incantation is a bit weird here because it uses ELF symbol stuff. If we
|
||||
* make a symbol "default" it makes it visible (for import or export). Making it
|
||||
* "hidden" means it is invisible outside the shared object. */
|
||||
#ifndef AUDACITY_DLL_API
|
||||
#ifdef BUILDING_AUDACITY
|
||||
#define AUDACITY_DLL_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#define AUDACITY_DLL_API __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The GCC-win32 implementation */
|
||||
// bizzarely, GCC-for-win32 supports Visual Studio style symbol visibility, so
|
||||
// we use that if building on Cygwin
|
||||
#if defined __CYGWIN__ && defined __GNUC__
|
||||
#ifndef AUDACITY_DLL_API
|
||||
#ifdef BUILDING_AUDACITY
|
||||
#define AUDACITY_DLL_API _declspec(dllexport)
|
||||
#else
|
||||
#ifdef _DLL
|
||||
#define AUDACITY_DLL_API _declspec(dllimport)
|
||||
#else
|
||||
#define AUDACITY_DLL_API
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // __AUDACITY_TYPES_H__
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;name "Silence Finder..."
|
||||
;action "Finding silence..."
|
||||
;info "Adds point labels in areas of silence according to the specified\nlevel and duration of silence. If too many silences are detected,\nincrease the silence level and duration; if too few are detected,\nreduce the level and duration."
|
||||
;author "Alex S. Brown"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; by Alex S. Brown, PMP (http://www.alexsbrown.com)
|
||||
;; Released under terms of the GNU General Public License version 2:
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
;name "Sound Finder..."
|
||||
;action "Finding sound..."
|
||||
;info "Adds region labels for areas of sound according to the specified level\nand duration of surrounding silence. If too many labels are produced,\nincrease the silence level and duration; if too few are produced,\nreduce the level and duration."
|
||||
|
||||
;author "Jeremy R. Brown"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; by Jeremy R. Brown (http://www.jeremy-brown.com/)
|
||||
;; based on the Silence Finder script by Alex S. Brown (http://www.alexsbrown.com)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
;type process
|
||||
;name "Spectral edit multi tool"
|
||||
;action "Calculating..."
|
||||
;author "Paul Licameli"
|
||||
;copyright "Unknown"
|
||||
|
||||
(defun wet (sig)
|
||||
(cond
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
;type process
|
||||
;name "Spectral edit parametric EQ..."
|
||||
;action "Calculating..."
|
||||
;author "Paul Licameli"
|
||||
;copyright "Unknown"
|
||||
|
||||
;control control-gain "Gain (dB)" real "" 0 -24 24
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
;type process
|
||||
;name "Spectral edit shelves..."
|
||||
;action "Calculating..."
|
||||
;author "Paul Licameli"
|
||||
;copyright "Unknown"
|
||||
|
||||
;control control-gain "Gain (dB)" real "" 0 -24 24
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#MixerPlugin"
|
||||
;name "Studio Fade Out"
|
||||
;action "Applying Fade..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; StudioFadeOut.ny by Steve Daulton December 2012.
|
||||
;; Released under terms of the GNU General Public License version 2:
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#MixerPlugin"
|
||||
;name "Adjustable Fade..."
|
||||
;action "Applying Fade..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; adjustable-fade.ny by Steve Daulton Dec 2012
|
||||
;; Released under terms of the GNU General Public License version 2:
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
;categories "http://audacityteam.org/namespace#OnsetDetector"
|
||||
;name "Beat Finder..."
|
||||
;action "Finding beats..."
|
||||
;author "Audacity"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; Released under terms of the GNU General Public License version 2:
|
||||
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;name "Click Track..."
|
||||
;action "Generating Click Track..."
|
||||
;info "For help, select one of two help screens in 'Action choice' below."
|
||||
;author "Dominic Mazzoni"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; by Dominic Mazzoni, modified by David R. Sky and Steve Daulton.
|
||||
;; Released under terms of the GNU General Public License version 2:
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;categories "http://audacityteam.org/namespace#NoiseRemoval"
|
||||
;name "Clip Fix..."
|
||||
;action "Reconstructing clips..."
|
||||
;author "Benjamin Schwartz"
|
||||
;copyright "Licensing confirmed under terms of the GNU General Public License version 2"
|
||||
|
||||
;; clipfix.ny by Benjamin Schwartz.
|
||||
;; Licensing confirmed under terms of the GNU General Public License version 2:
|
||||
|
|
|
@ -4,4 +4,7 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#MixerPlugin"
|
||||
;name "Cross Fade In"
|
||||
;action "Cross-Fading In..."
|
||||
;author "Audacity"
|
||||
;copyright "Unknown"
|
||||
|
||||
(mult s (control-srate-abs *sound-srate* (s-sqrt (pwlv 0 1 1))))
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#MixerPlugin"
|
||||
;name "Cross Fade Out"
|
||||
;action "Cross-Fading Out..."
|
||||
;author "Audacity"
|
||||
;copyright "Unknown"
|
||||
|
||||
(mult s (snd-exp
|
||||
(snd-scale 0.5 (snd-log
|
||||
(sum 1 (snd-scale -1 (ramp)))))))
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#DelayPlugin"
|
||||
;name "Delay..."
|
||||
;action "Applying Delay Effect..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; by Steve Daulton, July 2012.
|
||||
;; based on 'Delay' by David R. Sky
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
;type analyze
|
||||
;name "Regular Interval Labels..."
|
||||
;action "Adding equally-spaced labels to the label track..."
|
||||
;author "David R. Sky"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; by David R. Sky (http://www.garyallendj.com/davidsky/), June-October 2007.
|
||||
;; Code for label placement based on silencemarker.ny by Alex S.Brown.
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#HighpassPlugin"
|
||||
;name "High Pass Filter..."
|
||||
;action "Performing High Pass Filter..."
|
||||
;author "Dominic Mazzoni"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; highpass.ny by Dominic Mazzoni
|
||||
;; Modified by David R. Sky
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#LowpassPlugin"
|
||||
;name "Low Pass Filter..."
|
||||
;action "Performing Low Pass Filter..."
|
||||
;author "Dominic Mazzoni"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; lowpass.ny by Dominic Mazzoni
|
||||
;; Modified by David R. Sky
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core/#FilterPlugin"
|
||||
;name "Notch Filter..."
|
||||
;action "Performing Notch Filter..."
|
||||
;author "Steve Daulton and Bill Wharrie"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;control freq "Frequency" real "Hz" 60 0 10000
|
||||
;control q "Q (higher value reduces width)" real "" 1 0.1 20
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
;name "Pluck..."
|
||||
;action "Generating pluck sound..."
|
||||
;info "MIDI values for C notes: 36, 48, 60 [middle C], 72, 84, 96."
|
||||
;author "David R.Sky"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; Released under terms of the GNU General Public License version 2:
|
||||
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html .
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#GeneratorPlugin"
|
||||
;name "Risset Drum..."
|
||||
;action "Generating Risset Drum..."
|
||||
;author "Steven Jones"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; rissetdrum.ny by Steven Jones, after Jean Claude Risset.
|
||||
;; Updated by Steve Daulton July 2012.
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
;name "Sample Data Export..."
|
||||
;action "Analyzing..."
|
||||
;categories "http://lv2plug.in/ns/lv2core#AnalyserPlugin"
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; sample-data-export.ny by Steve Daulton June 2012.
|
||||
;; Updated July 16 2012.
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#ModulatorPlugin"
|
||||
;name "Tremolo..."
|
||||
;action "Applying Tremolo..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; tremolo.ny by Steve Daulton (www.easyspacepro.com) July 2012.
|
||||
;; Based on Tremolo by Dominic Mazzoni and David R. Sky."
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
;name "Vocal Remover..."
|
||||
;action "Removing center-panned audio..."
|
||||
;info "For reducing center-panned vocals"
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; This version of vocalremover.ny by Steve Daulton June 2013.
|
||||
;;
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
;categories "http://lv2plug.in/ns/lv2core#SpectralPlugin"
|
||||
;name "Vocoder..."
|
||||
;action "Processing Vocoder..."
|
||||
;author "Edgar-RFT"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; vocoder.ny by Edgar-RFT
|
||||
;; a bit of code added by David R. Sky
|
||||
|
|
|
@ -17,7 +17,7 @@ It handles initialization and termination by subclassing wxApp.
|
|||
|
||||
#if 0
|
||||
// This may be used to debug memory leaks.
|
||||
// See: Visual Leak Dectector @ http://dmoulding.googlepages.com/vld
|
||||
// See: Visual Leak Dectector @ http://vld.codeplex.com/
|
||||
#include <vld.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -177,6 +177,7 @@ void BatchCommandDialog::OnEditParams(wxCommandEvent & WXUNUSED(event))
|
|||
{
|
||||
wxString command = mCommand->GetValue();
|
||||
wxString params = mParameters->GetValue();
|
||||
|
||||
if (BatchCommands::SetCurrentParametersFor( command, params ))
|
||||
{
|
||||
if( BatchCommands::PromptForParamsFor( command, this ))
|
||||
|
|
|
@ -288,12 +288,14 @@ wxArrayString BatchCommands::GetAllCommands()
|
|||
command = em.GetEffectIdentifier(plug->GetID());
|
||||
if (!command.IsEmpty())
|
||||
{
|
||||
commands.Add( command);
|
||||
commands.Add(command);
|
||||
}
|
||||
}
|
||||
plug = pm.GetNextPlugin(PluginTypeEffect);
|
||||
}
|
||||
|
||||
commands.Sort();
|
||||
|
||||
/* This is for later in development: include the menu commands.
|
||||
CommandManager * mManager = project->GetCommandManager();
|
||||
wxArrayString mNames;
|
||||
|
|
238
src/Menus.cpp
238
src/Menus.cpp
|
@ -264,7 +264,36 @@ static int SortEffectsByPublisherAndName(const PluginDescriptor **a, const Plugi
|
|||
return akey.CmpNoCase(bkey);
|
||||
}
|
||||
|
||||
static int SortEffectsByFamily(const PluginDescriptor **a, const PluginDescriptor **b)
|
||||
static int SortEffectsByTypeAndName(const PluginDescriptor **a, const PluginDescriptor **b)
|
||||
{
|
||||
wxString akey = (*a)->GetEffectFamily();
|
||||
wxString bkey = (*b)->GetEffectFamily();
|
||||
|
||||
if (akey.IsEmpty())
|
||||
{
|
||||
akey = _("Uncategorized");
|
||||
}
|
||||
if (bkey.IsEmpty())
|
||||
{
|
||||
bkey = _("Uncategorized");
|
||||
}
|
||||
|
||||
if ((*a)->IsEffectDefault())
|
||||
{
|
||||
akey = wxEmptyString;
|
||||
}
|
||||
if ((*b)->IsEffectDefault())
|
||||
{
|
||||
bkey = wxEmptyString;
|
||||
}
|
||||
|
||||
akey += (*a)->GetName();
|
||||
bkey += (*b)->GetName();
|
||||
|
||||
return akey.CmpNoCase(bkey);
|
||||
}
|
||||
|
||||
static int SortEffectsByType(const PluginDescriptor **a, const PluginDescriptor **b)
|
||||
{
|
||||
wxString akey = (*a)->GetEffectFamily();
|
||||
wxString bkey = (*b)->GetEffectFamily();
|
||||
|
@ -1284,27 +1313,32 @@ void AudacityProject::PopulateEffectsMenu(CommandManager* c,
|
|||
plug = pm.GetNextPluginForEffectType(type);
|
||||
}
|
||||
|
||||
wxString groupby = gPrefs->Read(wxT("/Effects/GroupBy"), wxT("default"));
|
||||
wxString groupby = gPrefs->Read(wxT("/Effects/GroupBy"), wxT("name"));
|
||||
|
||||
if (groupby == wxT("name"))
|
||||
if (groupby == wxT("sortby:name"))
|
||||
{
|
||||
defplugs.Sort(SortEffectsByName);
|
||||
optplugs.Sort(SortEffectsByName);
|
||||
}
|
||||
else if (groupby == wxT("publisher"))
|
||||
else if (groupby == wxT("sortby:publisher:name"))
|
||||
{
|
||||
defplugs.Sort(SortEffectsByName);
|
||||
optplugs.Sort(SortEffectsByPublisherAndName);
|
||||
}
|
||||
else if (groupby == wxT("sortby:type:name"))
|
||||
{
|
||||
defplugs.Sort(SortEffectsByName);
|
||||
optplugs.Sort(SortEffectsByTypeAndName);
|
||||
}
|
||||
else if (groupby == wxT("groupby:publisher"))
|
||||
{
|
||||
defplugs.Sort(SortEffectsByPublisher);
|
||||
optplugs.Sort(SortEffectsByPublisher);
|
||||
}
|
||||
else if (groupby == wxT("publisher:name"))
|
||||
else if (groupby == wxT("groupby:type"))
|
||||
{
|
||||
defplugs.Sort(SortEffectsByPublisherAndName);
|
||||
optplugs.Sort(SortEffectsByPublisherAndName);
|
||||
}
|
||||
else if (groupby == wxT("family"))
|
||||
{
|
||||
defplugs.Sort(SortEffectsByFamily);
|
||||
optplugs.Sort(SortEffectsByFamily);
|
||||
defplugs.Sort(SortEffectsByType);
|
||||
optplugs.Sort(SortEffectsByType);
|
||||
}
|
||||
else // name
|
||||
{
|
||||
|
@ -1341,26 +1375,26 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||
wxString groupBy = gPrefs->Read(wxT("/Effects/GroupBy"), wxT("name"));
|
||||
|
||||
bool grouped = false;
|
||||
if (groupBy == wxT("publisher") || groupBy == wxT("family"))
|
||||
if (groupBy.StartsWith(wxT("groupby")))
|
||||
{
|
||||
grouped = true;
|
||||
}
|
||||
|
||||
wxString last;
|
||||
wxArrayString groupNames;
|
||||
PluginIDList groupPlugs;
|
||||
wxArrayInt groupFlags;
|
||||
if (grouped)
|
||||
{
|
||||
wxString last;
|
||||
wxString current;
|
||||
|
||||
for (size_t i = 0; i < pluginCnt; i++)
|
||||
{
|
||||
const PluginDescriptor *plug = plugs[i];
|
||||
|
||||
#if defined(EXPERIMENTAL_REALTIME_EFFECTS)
|
||||
int flags = plug->IsEffectRealtime() ? realflags : batchflags;
|
||||
#else
|
||||
int flags = batchflags;
|
||||
#endif
|
||||
|
||||
wxString name = plug->GetName();
|
||||
|
||||
// This goes away once everything has been converted to new format
|
||||
wxString stripped;
|
||||
if (name.EndsWith(wxT("..."), &stripped))
|
||||
{
|
||||
|
@ -1372,24 +1406,7 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||
name += wxT("...");
|
||||
}
|
||||
|
||||
wxString current;
|
||||
if (groupBy == wxT("publisher:name"))
|
||||
{
|
||||
current = plug->GetVendor();
|
||||
if (plug->IsEffectDefault())
|
||||
{
|
||||
current = wxEmptyString;
|
||||
}
|
||||
|
||||
if (!current.IsEmpty())
|
||||
{
|
||||
current += wxT(": ");
|
||||
}
|
||||
|
||||
current += name;
|
||||
name = current;
|
||||
}
|
||||
else if (groupBy == wxT("publisher"))
|
||||
if (groupBy == wxT("groupby:publisher"))
|
||||
{
|
||||
current = plug->GetVendor();
|
||||
if (current.IsEmpty())
|
||||
|
@ -1397,7 +1414,7 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||
current = _("Unknown");
|
||||
}
|
||||
}
|
||||
else if (groupBy == wxT("family"))
|
||||
else if (groupBy == wxT("groupby:type"))
|
||||
{
|
||||
current = plug->GetEffectFamily();
|
||||
if (current.IsEmpty())
|
||||
|
@ -1405,34 +1422,109 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||
current = _("Unknown");
|
||||
}
|
||||
}
|
||||
else if (groupBy == wxT("name"))
|
||||
{
|
||||
current = plug->GetName();
|
||||
name = current;
|
||||
}
|
||||
else // default to "name"
|
||||
{
|
||||
current = plug->GetName();
|
||||
name = current;
|
||||
}
|
||||
|
||||
if (current != last || i + 1 == pluginCnt)
|
||||
if (current != last)
|
||||
{
|
||||
if (i + 1 == pluginCnt)
|
||||
{
|
||||
groupNames.Add(name);
|
||||
groupPlugs.Add(plug->GetID());
|
||||
}
|
||||
|
||||
int groupCnt = (int) groupPlugs.GetCount();
|
||||
|
||||
if (grouped && groupCnt > 0 && i > 0)
|
||||
if (!last.IsEmpty())
|
||||
{
|
||||
c->BeginSubMenu(last);
|
||||
}
|
||||
|
||||
if (grouped || i + 1 == pluginCnt)
|
||||
AddEffectMenuItemGroup(c, groupNames, groupPlugs, groupFlags);
|
||||
|
||||
if (!last.IsEmpty())
|
||||
{
|
||||
c->EndSubMenu();
|
||||
}
|
||||
|
||||
groupNames.Clear();
|
||||
groupPlugs.Clear();
|
||||
groupFlags.Clear();
|
||||
last = current;
|
||||
}
|
||||
|
||||
groupNames.Add(name);
|
||||
groupPlugs.Add(plug->GetID());
|
||||
groupFlags.Add(plug->IsEffectRealtime() ? realflags : batchflags);
|
||||
}
|
||||
|
||||
if (groupNames.GetCount() > 0)
|
||||
{
|
||||
c->BeginSubMenu(current);
|
||||
|
||||
AddEffectMenuItemGroup(c, groupNames, groupPlugs, groupFlags);
|
||||
|
||||
c->EndSubMenu();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < pluginCnt; i++)
|
||||
{
|
||||
const PluginDescriptor *plug = plugs[i];
|
||||
|
||||
wxString name = plug->GetName();
|
||||
|
||||
// This goes away once everything has been converted to new format
|
||||
wxString stripped;
|
||||
if (name.EndsWith(wxT("..."), &stripped))
|
||||
{
|
||||
name = stripped;
|
||||
}
|
||||
|
||||
if (plug->IsEffectInteractive())
|
||||
{
|
||||
name += wxT("...");
|
||||
}
|
||||
|
||||
wxString group = wxEmptyString;
|
||||
if (groupBy == wxT("sortby:publisher:name"))
|
||||
{
|
||||
group = plug->GetVendor();
|
||||
}
|
||||
else if (groupBy == wxT("sortby:type:name"))
|
||||
{
|
||||
group = plug->GetEffectFamily();
|
||||
}
|
||||
|
||||
if (plug->IsEffectDefault())
|
||||
{
|
||||
group = wxEmptyString;
|
||||
}
|
||||
|
||||
if (!group.IsEmpty())
|
||||
{
|
||||
group += wxT(": ");
|
||||
}
|
||||
|
||||
groupNames.Add(group + name);
|
||||
groupPlugs.Add(plug->GetID());
|
||||
groupFlags.Add(plug->IsEffectRealtime() ? realflags : batchflags);
|
||||
}
|
||||
if (groupNames.GetCount() > 0)
|
||||
{
|
||||
AddEffectMenuItemGroup(c, groupNames, groupPlugs, groupFlags);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void AudacityProject::AddEffectMenuItemGroup(CommandManager *c,
|
||||
const wxArrayString & names,
|
||||
const PluginIDList & plugs,
|
||||
const wxArrayInt & flags)
|
||||
{
|
||||
int groupCnt = (int) names.GetCount();
|
||||
int perGroup;
|
||||
|
||||
#if defined(__WXGTK__)
|
||||
gPrefs->Read(wxT("/Effects/MaxPerGroup"), &perGroup, 15);
|
||||
#else
|
||||
gPrefs->Read(wxT("/Effects/MaxPerGroup"), &perGroup, 0);
|
||||
#endif
|
||||
|
||||
int max = perGroup;
|
||||
int items = perGroup;
|
||||
|
||||
|
@ -1455,11 +1547,11 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||
end));
|
||||
}
|
||||
|
||||
c->AddItem(groupNames[j],
|
||||
groupNames[j],
|
||||
FNS(OnEffect, groupPlugs[j]),
|
||||
flags,
|
||||
flags);
|
||||
c->AddItem(names[j],
|
||||
names[j],
|
||||
FNS(OnEffect, plugs[j]),
|
||||
flags[j],
|
||||
flags[j]);
|
||||
|
||||
if (max > 0)
|
||||
{
|
||||
|
@ -1471,22 +1563,6 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (grouped && groupCnt > 0 && i > 0)
|
||||
{
|
||||
c->EndSubMenu();
|
||||
|
||||
groupNames.Clear();
|
||||
groupPlugs.Clear();
|
||||
}
|
||||
|
||||
last = current;
|
||||
}
|
||||
|
||||
groupNames.Add(name);
|
||||
groupPlugs.Add(plug->GetID());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ void AddEffectsToMenu(CommandManager* c, const EffectSet& effects);
|
|||
|
||||
void PopulateEffectsMenu(CommandManager *c, EffectType type, int batchflags, int realflags);
|
||||
void AddEffectMenuItems(CommandManager *c, EffectPlugs & plugs, int batchflags, int realflags);
|
||||
void AddEffectMenuItemGroup(CommandManager *c, const wxArrayString & names, const PluginIDList & plugs, const wxArrayInt & flags);
|
||||
void CreateRecentFilesMenu(CommandManager *c);
|
||||
void ModifyUndoMenuItems();
|
||||
void ModifyToolbarMenus();
|
||||
|
|
|
@ -18,6 +18,7 @@ i.e. an alternative to the usual interface, for Audacity.
|
|||
|
||||
*//*******************************************************************/
|
||||
|
||||
#include <wx/dynarray.h>
|
||||
#include <wx/dynlib.h>
|
||||
#include <wx/list.h>
|
||||
#include <wx/log.h>
|
||||
|
@ -44,6 +45,8 @@ i.e. an alternative to the usual interface, for Audacity.
|
|||
#include "ModuleManager.h"
|
||||
#include "widgets/MultiDialog.h"
|
||||
|
||||
#include <wx/arrimpl.cpp>
|
||||
|
||||
#define initFnName "ExtensionModuleInit"
|
||||
#define versionFnName "GetVersionString"
|
||||
#define scriptFnName "RegScriptServerFunc"
|
||||
|
@ -182,9 +185,12 @@ static wxArrayPtrVoid *pBuiltinModuleList = NULL;
|
|||
void RegisterBuiltinModule(ModuleMain moduleMain)
|
||||
{
|
||||
if (pBuiltinModuleList == NULL)
|
||||
{
|
||||
pBuiltinModuleList = new wxArrayPtrVoid;
|
||||
}
|
||||
|
||||
pBuiltinModuleList->Add((void *)moduleMain);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -205,14 +211,17 @@ ModuleManager::~ModuleManager()
|
|||
}
|
||||
mModules.Clear();
|
||||
|
||||
for (ModuleMap::iterator iter = mDynModules.begin(); iter != mDynModules.end(); iter++)
|
||||
ModuleMap::iterator iter = mDynModules.begin();
|
||||
while (iter != mDynModules.end())
|
||||
{
|
||||
ModuleInterface *mod = iter->second;
|
||||
delete mod;
|
||||
UnloadModule(iter->second);
|
||||
iter = mDynModules.begin();
|
||||
}
|
||||
mDynModules.clear();
|
||||
if( pBuiltinModuleList != NULL )
|
||||
|
||||
if (pBuiltinModuleList != NULL)
|
||||
{
|
||||
delete pBuiltinModuleList;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -352,38 +361,10 @@ ModuleManager & ModuleManager::Get()
|
|||
return mInstance;
|
||||
}
|
||||
|
||||
void ModuleManager::InitializeBuiltins()
|
||||
{
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
|
||||
if (pBuiltinModuleList==NULL)
|
||||
return;
|
||||
|
||||
for (size_t i = 0, cnt = pBuiltinModuleList->GetCount(); i < cnt; i++)
|
||||
{
|
||||
ModuleMain audacityMain = (ModuleMain) (*pBuiltinModuleList)[i];
|
||||
ModuleInterface *module = audacityMain(this, NULL);
|
||||
|
||||
mDynModules[module->GetID()] = module;
|
||||
|
||||
module->Initialize();
|
||||
|
||||
// First, we need to remember it
|
||||
pm.RegisterModulePlugin(module);
|
||||
|
||||
// Now, allow the module to auto-register children
|
||||
module->AutoRegisterPlugins(pm);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void ModuleManager::EarlyInit()
|
||||
bool ModuleManager::DiscoverProviders()
|
||||
{
|
||||
InitializeBuiltins();
|
||||
}
|
||||
|
||||
bool ModuleManager::DiscoverProviders(wxArrayString & providers)
|
||||
{
|
||||
wxArrayString provList;
|
||||
wxArrayString pathList;
|
||||
|
||||
|
@ -407,31 +388,43 @@ bool ModuleManager::DiscoverProviders(wxArrayString & providers)
|
|||
wxGetApp().FindFilesInPathList(wxT("*.so"), pathList, provList);
|
||||
#endif
|
||||
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
|
||||
for (int i = 0, cnt = provList.GetCount(); i < cnt; i++)
|
||||
{
|
||||
providers.push_back(provList[i]);
|
||||
ModuleInterface *module = LoadModule(provList[i]);
|
||||
if (module)
|
||||
{
|
||||
// First, we need to remember it
|
||||
pm.RegisterModulePlugin(module);
|
||||
|
||||
// Now, allow the module to auto-register children
|
||||
module->AutoRegisterPlugins(pm);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ModuleManager::DiscoverProvider(const wxString & path)
|
||||
void ModuleManager::InitializeBuiltins()
|
||||
{
|
||||
ModuleInterface *module = LoadModule(path);
|
||||
if (module)
|
||||
{
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
|
||||
for (size_t i = 0, cnt = pBuiltinModuleList->GetCount(); i < cnt; i++)
|
||||
{
|
||||
ModuleInterface *module = ((ModuleMain) (*pBuiltinModuleList)[i])(this, NULL);
|
||||
|
||||
if (module->Initialize())
|
||||
{
|
||||
mDynModules[module->GetID()] = module;
|
||||
|
||||
// First, we need to remember it
|
||||
pm.RegisterModulePlugin(module);
|
||||
|
||||
// Now, allow the module to auto-register children
|
||||
module->AutoRegisterPlugins(pm);
|
||||
|
||||
// UnloadModule(module);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ModuleInterface *ModuleManager::LoadModule(const wxString & path)
|
||||
|
@ -489,19 +482,6 @@ void ModuleManager::UnloadModule(ModuleInterface *module)
|
|||
}
|
||||
}
|
||||
|
||||
void ModuleManager::InitializePlugins()
|
||||
{
|
||||
InitializeBuiltins();
|
||||
|
||||
// Look for dynamic modules here
|
||||
|
||||
for (ModuleMap::iterator iter = mDynModules.begin(); iter != mDynModules.end(); iter++)
|
||||
{
|
||||
ModuleInterface *mod = iter->second;
|
||||
mod->Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void ModuleManager::RegisterModule(ModuleInterface *module)
|
||||
{
|
||||
wxString id = module->GetID();
|
||||
|
@ -573,15 +553,10 @@ bool ModuleManager::RegisterPlugin(const PluginID & providerID, const wxString &
|
|||
return mDynModules[providerID]->RegisterPlugin(PluginManager::Get(), path);
|
||||
}
|
||||
|
||||
bool ModuleManager::IsProviderBuiltin(const PluginID & providerID)
|
||||
{
|
||||
return mModuleMains.find(providerID) != mModuleMains.end();
|
||||
}
|
||||
|
||||
IdentInterface *ModuleManager::CreateProviderInstance(const PluginID & providerID,
|
||||
const wxString & path)
|
||||
{
|
||||
if (path.empty() && mDynModules.find(providerID) != mDynModules.end())
|
||||
if (path.IsEmpty() && mDynModules.find(providerID) != mDynModules.end())
|
||||
{
|
||||
return mDynModules[providerID];
|
||||
}
|
||||
|
@ -611,3 +586,34 @@ void ModuleManager::DeleteInstance(const PluginID & providerID,
|
|||
|
||||
mDynModules[providerID]->DeleteInstance(instance);
|
||||
}
|
||||
|
||||
bool ModuleManager::IsProviderValid(const PluginID & providerID,
|
||||
const wxString & path)
|
||||
{
|
||||
// Builtin modules do not have a path
|
||||
if (path.IsEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
wxFileName lib(path);
|
||||
if (lib.FileExists() || lib.DirExists())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModuleManager::IsPluginValid(const PluginID & providerID,
|
||||
const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
if (mDynModules.find(providerID) == mDynModules.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return mDynModules[providerID]->IsPluginValid(ID, path);
|
||||
}
|
||||
|
||||
|
|
|
@ -86,22 +86,20 @@ public:
|
|||
void Initialize(CommandHandler & cmdHandler);
|
||||
int Dispatch(ModuleDispatchTypes type);
|
||||
|
||||
void EarlyInit();
|
||||
|
||||
// PluginManager use
|
||||
bool DiscoverProviders(wxArrayString & providers);
|
||||
bool DiscoverProvider(const wxString & path);
|
||||
bool DiscoverProviders();
|
||||
|
||||
void FindAllPlugins(PluginIDList & providers, wxArrayString & paths);
|
||||
wxArrayString FindPluginsForProvider(const PluginID & provider, const wxString & path);
|
||||
bool RegisterPlugin(const PluginID & provider, const wxString & path);
|
||||
|
||||
void InitializePlugins();
|
||||
bool IsProviderBuiltin(const PluginID & provider);
|
||||
IdentInterface *CreateProviderInstance(const PluginID & ID, const wxString & path);
|
||||
IdentInterface *CreateInstance(const PluginID & provider, const PluginID & ID, const wxString & path);
|
||||
void DeleteInstance(const PluginID & provider, IdentInterface *instance);
|
||||
|
||||
bool IsProviderValid(const PluginID & provider, const wxString & path);
|
||||
bool IsPluginValid(const PluginID & provider, const PluginID & ID, const wxString & path);
|
||||
|
||||
private:
|
||||
void InitializeBuiltins();
|
||||
ModuleInterface *LoadModule(const wxString & path);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <wx/dir.h>
|
||||
#include <wx/dynarray.h>
|
||||
#include <wx/dynlib.h>
|
||||
#include <wx/hashmap.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/imaglist.h>
|
||||
|
@ -48,6 +49,8 @@
|
|||
|
||||
#include <wx/arrimpl.cpp>
|
||||
|
||||
WX_DECLARE_STRING_HASH_MAP(wxString, ProviderMap);
|
||||
|
||||
// ============================================================================
|
||||
//
|
||||
//
|
||||
|
@ -373,11 +376,19 @@ wxAccStatus CheckListAx::GetValue( int childId, wxString *strValue )
|
|||
#define EffectClearAllID 7002
|
||||
#define EffectSelectAllID 7003
|
||||
|
||||
int wxCALLBACK SortCompare(long item1, long item2, long WXUNUSED(sortData))
|
||||
{
|
||||
wxString *str1 = (wxString *) item1;
|
||||
wxString *str2 = (wxString *) item2;
|
||||
|
||||
return str2->Cmp(*str1);
|
||||
}
|
||||
|
||||
class PluginRegistrationDialog : public wxDialog
|
||||
{
|
||||
public:
|
||||
// constructors and destructors
|
||||
PluginRegistrationDialog();
|
||||
PluginRegistrationDialog(ProviderMap & map);
|
||||
virtual ~PluginRegistrationDialog();
|
||||
|
||||
private:
|
||||
|
@ -405,10 +416,12 @@ private:
|
|||
wxListCtrl *mEffects;
|
||||
PluginIDList mProvs;
|
||||
wxArrayString mPaths;
|
||||
std::vector<int> miState;
|
||||
wxArrayInt miState;
|
||||
|
||||
bool mCancelClicked;
|
||||
|
||||
ProviderMap & mMap;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
@ -419,12 +432,13 @@ BEGIN_EVENT_TABLE(PluginRegistrationDialog, wxDialog)
|
|||
EVT_BUTTON(EffectSelectAllID, PluginRegistrationDialog::OnSelectAll)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
PluginRegistrationDialog::PluginRegistrationDialog()
|
||||
PluginRegistrationDialog::PluginRegistrationDialog(ProviderMap & map)
|
||||
: wxDialog(wxGetApp().GetTopWindow(),
|
||||
wxID_ANY,
|
||||
_("Register Effects"),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||
mMap(map)
|
||||
{
|
||||
mEffects = NULL;
|
||||
SetLabel(_("Register Effects")); // Provide visual label
|
||||
|
@ -443,6 +457,15 @@ PluginRegistrationDialog::~PluginRegistrationDialog()
|
|||
wxKeyEventHandler(PluginRegistrationDialog::OnListChar),
|
||||
NULL,
|
||||
this);
|
||||
|
||||
for (int i = 0, cnt = mEffects->GetItemCount(); i < cnt; i++)
|
||||
{
|
||||
wxString *str = (wxString *) mEffects->GetItemData(i);
|
||||
if (str)
|
||||
{
|
||||
delete str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PluginRegistrationDialog::Populate()
|
||||
|
@ -453,8 +476,6 @@ void PluginRegistrationDialog::Populate()
|
|||
// ----------------------- End of main section --------------
|
||||
}
|
||||
|
||||
WX_DECLARE_STRING_HASH_MAP(wxString, ProviderMap);
|
||||
|
||||
/// Defines the dialog and does data exchange with it.
|
||||
void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
|
||||
{
|
||||
|
@ -521,44 +542,6 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
|
|||
}
|
||||
S.EndVerticalLay();
|
||||
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
ModuleManager & mm = ModuleManager::Get();
|
||||
|
||||
// Capture all of the module IDs and paths so the iterate stays valid
|
||||
ProviderMap provs;
|
||||
wxArrayString keys;
|
||||
wxArrayString paths;
|
||||
wxString padding = wxT("0000000000");
|
||||
const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeModule);
|
||||
while (plug)
|
||||
{
|
||||
wxString key = wxString::Format(wxT("%d"), (int) provs.size());
|
||||
key.insert(0, padding.substr(0, padding.length() - key.length()));
|
||||
provs[key] = plug->GetID();
|
||||
keys.push_back(key);
|
||||
paths.push_back(plug->GetPath());
|
||||
|
||||
plug = pm.GetNextPlugin(PluginTypeModule);
|
||||
}
|
||||
|
||||
wxArrayString sortable;
|
||||
for (size_t i = 0, icnt = paths.size(); i < icnt; i++)
|
||||
{
|
||||
wxString key = keys[i];
|
||||
PluginID provID = provs[key];
|
||||
wxString provPath = paths[i];
|
||||
|
||||
wxArrayString newPaths = mm.FindPluginsForProvider(provID, provPath);
|
||||
|
||||
for (size_t j = 0, jcnt = newPaths.size(); j < jcnt; j++)
|
||||
{
|
||||
sortable.push_back(key + wxT(" ") + newPaths[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// With the index
|
||||
sortable.Sort();
|
||||
|
||||
// The dc is used to compute the text width in pixels.
|
||||
// FIXME: That works fine for PC, but apparently comes out too small for wxMAC.
|
||||
// iLen is minimum width in pixels shown for the file names. 200 is reasonable.
|
||||
|
@ -566,20 +549,18 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
|
|||
int iPathLen = 0;
|
||||
int x, y;
|
||||
wxRect iconrect;
|
||||
for (int i = 0, cnt = sortable.size(); i < cnt; i++)
|
||||
int i = 0;
|
||||
for (ProviderMap::iterator iter = mMap.begin(); iter != mMap.end(); iter++, i++)
|
||||
{
|
||||
miState.push_back( SHOW_CHECKED );
|
||||
miState.Add( SHOW_CHECKED );
|
||||
|
||||
wxString item = sortable[i];
|
||||
int split = item.find(wxT(" "));
|
||||
mProvs.push_back(provs[item.substr(0, split)]);
|
||||
mPaths.push_back(item.substr(split + 1, wxString::npos));
|
||||
|
||||
wxFileName fn(mPaths.back());
|
||||
wxString name(fn.GetName());
|
||||
wxString path(fn.GetFullPath());
|
||||
wxFileName fname = iter->first;
|
||||
wxString name = fname.GetName();
|
||||
wxString path = fname.GetFullPath();
|
||||
wxString *key = new wxString(iter->second + name);
|
||||
|
||||
mEffects->InsertItem(i, name, SHOW_CHECKED);
|
||||
mEffects->SetItemPtrData(i, (wxUIntPtr) key);
|
||||
mEffects->SetItem(i, COL_PATH, path);
|
||||
|
||||
// Only need to get the icon width once
|
||||
|
@ -606,6 +587,8 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
|
|||
iPathLen = wxMax(iPathLen, x + iconrect.width + (iconrect.x * 2));
|
||||
}
|
||||
|
||||
mEffects->SortItems(SortCompare, 0);
|
||||
|
||||
mEffects->SetColumnWidth(COL_NAME, iNameLen + /* fudge */ 5);
|
||||
mEffects->SetColumnWidth(COL_PATH, iPathLen + /* fudge */ 5);
|
||||
|
||||
|
@ -713,18 +696,50 @@ void PluginRegistrationDialog::OnClearAll(wxCommandEvent & WXUNUSED(evt))
|
|||
void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
mCancelClicked = false;
|
||||
FindWindowById(EffectListID)->Disable();
|
||||
FindWindowById(wxID_OK)->Disable();
|
||||
FindWindowById(EffectListID)->Disable();
|
||||
FindWindowById(EffectClearAllID)->Disable();
|
||||
FindWindowById(EffectSelectAllID)->Disable();
|
||||
|
||||
for (size_t i = 0, cnt = mPaths.size(); i < cnt && !mCancelClicked; i++)
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
ModuleManager & mm = ModuleManager::Get();
|
||||
|
||||
wxListItem li;
|
||||
li.Clear();
|
||||
for (int i = 0, cnt = mEffects->GetItemCount(); i < cnt && !mCancelClicked; i++)
|
||||
{
|
||||
mEffects->EnsureVisible(i);
|
||||
li.SetId(i);
|
||||
li.SetColumn(COL_PATH);
|
||||
li.SetMask(wxLIST_MASK_TEXT);
|
||||
mEffects->GetItem(li);
|
||||
wxString path = li.GetText();
|
||||
|
||||
// Create a placeholder descriptor to show we've seen this plugin before and not
|
||||
// to show it as new the next time Audacity starts.
|
||||
//
|
||||
// If the user chooses not to enable it or the scan of the plugin fails, the dummy
|
||||
// entry will remain in the plugin list as disabled.
|
||||
//
|
||||
// However, if the scan of the of the plugin succeeds, then this dummy entry will be
|
||||
// replaced during registration.
|
||||
PluginDescriptor & plug = pm.mPlugins[path];
|
||||
|
||||
plug.SetID(path);
|
||||
plug.SetPath(path);
|
||||
plug.SetEnabled(false);
|
||||
|
||||
if (miState[i] == SHOW_CHECKED)
|
||||
{
|
||||
li.SetId(i);
|
||||
li.SetColumn(COL_PATH);
|
||||
li.SetMask(wxLIST_MASK_TEXT);
|
||||
mEffects->GetItem(li);
|
||||
wxString path = li.GetText();
|
||||
|
||||
mEffects->SetItemImage(i, SHOW_ARROW);
|
||||
ModuleManager::Get().RegisterPlugin(mProvs[i], wxString(mPaths[i]));
|
||||
mm.RegisterPlugin(mMap[path], path);
|
||||
mEffects->SetItemImage(i, SHOW_CHECKED);
|
||||
}
|
||||
wxYield();
|
||||
|
@ -841,11 +856,6 @@ const PluginID & PluginDescriptor::GetProviderID() const
|
|||
return mProviderID;
|
||||
}
|
||||
|
||||
const wxString & PluginDescriptor::GetDateTime() const
|
||||
{
|
||||
return mDateTime;
|
||||
}
|
||||
|
||||
bool PluginDescriptor::IsEnabled() const
|
||||
{
|
||||
return mEnabled;
|
||||
|
@ -902,11 +912,6 @@ void PluginDescriptor::SetProviderID(const PluginID & providerID)
|
|||
mProviderID = providerID;
|
||||
}
|
||||
|
||||
void PluginDescriptor::SetDateTime(const wxString & dateTime)
|
||||
{
|
||||
mDateTime = dateTime;
|
||||
}
|
||||
|
||||
void PluginDescriptor::SetEnabled(bool enable)
|
||||
{
|
||||
mEnabled = enable;
|
||||
|
@ -1054,7 +1059,9 @@ void PluginDescriptor::SetImporterExtensions(const wxArrayString & extensions)
|
|||
|
||||
void PluginManager::RegisterModulePlugin(IdentInterface *module)
|
||||
{
|
||||
CreatePlugin(module, PluginTypeModule);
|
||||
PluginDescriptor & plug = CreatePlugin(module, PluginTypeModule);
|
||||
|
||||
plug.SetEnabled(true);
|
||||
}
|
||||
|
||||
void PluginManager::RegisterEffectPlugin(IdentInterface *provider, EffectIdentInterface *effect)
|
||||
|
@ -1332,26 +1339,14 @@ PluginManager & PluginManager::Get()
|
|||
|
||||
void PluginManager::Initialize()
|
||||
{
|
||||
// Always load the config first
|
||||
bool loaded = Load();
|
||||
|
||||
ModuleManager::Get().EarlyInit();
|
||||
// Then look for providers (they may autoregister plugins)
|
||||
ModuleManager::Get().DiscoverProviders();
|
||||
|
||||
CheckForUpdates();
|
||||
|
||||
bool doRescan;
|
||||
gPrefs->Read(wxT("/Plugins/Rescan"), &doRescan, true);
|
||||
|
||||
if (!loaded || doRescan)
|
||||
{
|
||||
gPrefs->Write(wxT("/Plugins/Rescan"), false);
|
||||
PluginRegistrationDialog dlg;
|
||||
dlg.ShowModal();
|
||||
|
||||
if (mConfig)
|
||||
{
|
||||
mConfig->Flush();
|
||||
}
|
||||
}
|
||||
// And finally check for updates
|
||||
CheckForUpdates(!loaded);
|
||||
}
|
||||
|
||||
void PluginManager::Terminate()
|
||||
|
@ -1416,6 +1411,8 @@ bool PluginManager::Load()
|
|||
LoadGroup(wxT("exporters"), PluginTypeExporter);
|
||||
LoadGroup(wxT("importers"), PluginTypeImporter);
|
||||
|
||||
LoadGroup(wxT("placeholders"), PluginTypeNone);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1494,16 +1491,6 @@ void PluginManager::LoadGroup(const wxChar * group, PluginType type)
|
|||
}
|
||||
plug.SetDescription(wxString(strVal));
|
||||
|
||||
// Get the last update time and bypass group if not found
|
||||
if (!plug.GetPath().IsEmpty())
|
||||
{
|
||||
if (!mConfig->Read(KEY_LASTUPDATED, &strVal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
plug.SetDateTime(wxString(strVal));
|
||||
}
|
||||
|
||||
// Is it enabled...default to no if not found
|
||||
mConfig->Read(KEY_ENABLED, &boolVal, false);
|
||||
plug.SetEnabled(boolVal);
|
||||
|
@ -1511,9 +1498,13 @@ void PluginManager::LoadGroup(const wxChar * group, PluginType type)
|
|||
switch (type)
|
||||
{
|
||||
case PluginTypeModule:
|
||||
{
|
||||
// Nothing to do here yet
|
||||
}
|
||||
break;
|
||||
|
||||
case PluginTypeEffect:
|
||||
{
|
||||
// Get the effect type and bypass group if not found
|
||||
if (!mConfig->Read(KEY_EFFECTTYPE, &strVal))
|
||||
{
|
||||
|
@ -1571,7 +1562,7 @@ void PluginManager::LoadGroup(const wxChar * group, PluginType type)
|
|||
continue;
|
||||
}
|
||||
plug.SetEffectAutomatable(boolVal);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case PluginTypeImporter:
|
||||
|
@ -1605,9 +1596,17 @@ void PluginManager::LoadGroup(const wxChar * group, PluginType type)
|
|||
}
|
||||
break;
|
||||
|
||||
case PluginTypeNone:
|
||||
{
|
||||
// Used for placeholder groups
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Everything checked out...accept the plugin
|
||||
mPlugins[groupName] = plug;
|
||||
|
@ -1624,12 +1623,13 @@ void PluginManager::Save()
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: This is a bit drastic...only save groups when new plugins are registerd
|
||||
// TODO: This is a bit drastic...only save groups when new plugins are registered
|
||||
|
||||
// Save the individual groups
|
||||
SaveGroup(wxT("effects"), PluginTypeEffect);
|
||||
SaveGroup(wxT("exporters"), PluginTypeExporter);
|
||||
SaveGroup(wxT("importers"), PluginTypeImporter);
|
||||
SaveGroup(wxT("placeholders"), PluginTypeNone);
|
||||
|
||||
// And now the providers
|
||||
SaveGroup(wxT("modules"), PluginTypeModule);
|
||||
|
@ -1656,7 +1656,6 @@ void PluginManager::SaveGroup(const wxChar *group, PluginType type)
|
|||
mConfig->Write(KEY_VENDOR, plug.GetVendor());
|
||||
mConfig->Write(KEY_DESCRIPTION, plug.GetDescription());
|
||||
mConfig->Write(KEY_PROVIDERID, plug.GetProviderID());
|
||||
mConfig->Write(KEY_LASTUPDATED, plug.GetDateTime());
|
||||
mConfig->Write(KEY_ENABLED, plug.IsEnabled());
|
||||
|
||||
switch (type)
|
||||
|
@ -1712,118 +1711,93 @@ void PluginManager::SaveGroup(const wxChar *group, PluginType type)
|
|||
return;
|
||||
}
|
||||
|
||||
void PluginManager::CheckForUpdates()
|
||||
void PluginManager::CheckForUpdates(bool forceRescan)
|
||||
{
|
||||
// Always check for and remove missing plugins
|
||||
RemoveMissing();
|
||||
|
||||
// Get ModuleManager reference
|
||||
ModuleManager & mm = ModuleManager::Get();
|
||||
|
||||
wxArrayString providers;
|
||||
wxArrayString paths;
|
||||
|
||||
// Always check for new or updated modules
|
||||
if (mm.DiscoverProviders(paths))
|
||||
{
|
||||
paths = IsNewOrUpdated(paths);
|
||||
for (size_t i = 0, cnt = paths.size(); i < cnt; i++)
|
||||
{
|
||||
mm.DiscoverProvider(paths[i]);
|
||||
}
|
||||
}
|
||||
bool doRescan;
|
||||
gPrefs->Read(wxT("/Plugins/Rescan"), &doRescan, true);
|
||||
|
||||
bool doCheck;
|
||||
gPrefs->Read(wxT("/Plugins/CheckForUpdates"), &doCheck, true);
|
||||
if (doCheck && paths.size() > 0)
|
||||
{
|
||||
PluginRegistrationDialog dlg;
|
||||
dlg.ShowModal();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
ProviderMap map;
|
||||
|
||||
void PluginManager::RemoveMissing()
|
||||
{
|
||||
// Check for plugins that no longer exist
|
||||
// Always check for and disable missing plugins
|
||||
//
|
||||
// Since the user's saved presets are in the registery, never delete them. That is
|
||||
// a job for the plugin manager UI (once it is written)
|
||||
// Check for plugins that are no longer valid
|
||||
PluginMap::iterator iter = mPlugins.begin();
|
||||
while (iter != mPlugins.end())
|
||||
{
|
||||
PluginDescriptor & plug = iter->second;
|
||||
const PluginID & plugID = plug.GetID();
|
||||
const wxString & plugPath = plug.GetPath();
|
||||
|
||||
if (!plug.GetPath().IsEmpty())
|
||||
if (plug.GetPluginType() == PluginTypeModule)
|
||||
{
|
||||
wxFileName plugPath = plug.GetPath();
|
||||
|
||||
if (!(plugPath.FileExists() || plugPath.DirExists()))
|
||||
if (!mm.IsProviderValid(plugID, plugPath))
|
||||
{
|
||||
mPlugins.erase(iter++);
|
||||
continue;
|
||||
plug.SetEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only collect plugin paths if we're doing a full scan or checking for updates
|
||||
if (doRescan || doCheck)
|
||||
{
|
||||
wxArrayString paths = mm.FindPluginsForProvider(plugID, plugPath);
|
||||
for (size_t i = 0, cnt = paths.GetCount(); i < cnt; i++)
|
||||
{
|
||||
map[paths[i]] = plugID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mm.IsPluginValid(plug.GetProviderID(), plugID, plugPath))
|
||||
{
|
||||
plug.SetEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
++iter;
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
wxArrayString PluginManager::IsNewOrUpdated(const wxArrayString & paths)
|
||||
{
|
||||
wxArrayString plugsToAddOrUpdate;
|
||||
|
||||
// Create a map of plugins indexed by their path
|
||||
std::map<wxString, PluginDescriptor *> pathPlugs;
|
||||
// If we're only checking for new plugins, then remove all of the known ones
|
||||
if (doCheck && !doRescan)
|
||||
{
|
||||
for (PluginMap::iterator iter = mPlugins.begin(); iter != mPlugins.end(); iter++)
|
||||
{
|
||||
PluginDescriptor & plug = iter->second;
|
||||
pathPlugs[plug.GetPath()] = &plug;
|
||||
const wxString & plugPath = plug.GetPath();
|
||||
|
||||
ProviderMap::iterator mapiter = map.find(plugPath);
|
||||
if (map.find(plugPath) != map.end())
|
||||
{
|
||||
map.erase(mapiter);
|
||||
}
|
||||
|
||||
// Now check for new or updated paths
|
||||
for (size_t i = 0, cnt = paths.size(); i < cnt; i++)
|
||||
{
|
||||
wxFileName scanPath = paths[i];
|
||||
wxString scanFull = scanPath.GetFullPath();
|
||||
|
||||
if (pathPlugs.find(scanFull) != pathPlugs.end())
|
||||
{
|
||||
if (GetDateTime(scanFull) <= pathPlugs[scanFull]->GetDateTime())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
plugsToAddOrUpdate.push_back(scanFull);
|
||||
}
|
||||
|
||||
return plugsToAddOrUpdate;
|
||||
}
|
||||
|
||||
bool PluginManager::HasType(PluginType type)
|
||||
{
|
||||
for (PluginMap::iterator iter = mPlugins.begin(); iter != mPlugins.end(); iter++)
|
||||
// Allow the user to choose which ones to enable
|
||||
if (map.size() != 0)
|
||||
{
|
||||
if (iter->second.GetPluginType() == type)
|
||||
PluginRegistrationDialog dlg(map);
|
||||
if (dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
return true;
|
||||
gPrefs->Write(wxT("/Plugins/Rescan"), false);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
if (mConfig)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
|
||||
void PluginManager::PurgeType(PluginType type)
|
||||
{
|
||||
#if 0
|
||||
for (PluginMap::iterator iter = mPlugins.begin(); iter != mPlugins.end(); iter++)
|
||||
{
|
||||
if (iter->second.GetPluginType() == type)
|
||||
{
|
||||
mPlugins.erase(iter->first);
|
||||
mConfig->DeleteGroup(CACHEROOT + iter->second.GetID()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
int PluginManager::GetPluginCount(PluginType type)
|
||||
|
@ -1855,7 +1829,13 @@ const PluginDescriptor *PluginManager::GetFirstPlugin(PluginType type)
|
|||
{
|
||||
for (mPluginsIter = mPlugins.begin(); mPluginsIter != mPlugins.end(); mPluginsIter++)
|
||||
{
|
||||
if (mPluginsIter->second.GetPluginType() == type)
|
||||
PluginDescriptor & plug = mPluginsIter->second;
|
||||
bool familyEnabled = true;
|
||||
if (type == PluginTypeEffect)
|
||||
{
|
||||
gPrefs->Read(plug.GetEffectFamily() + wxT("/Enable"), &familyEnabled, true);
|
||||
}
|
||||
if (plug.IsEnabled() && plug.GetPluginType() == type && familyEnabled)
|
||||
{
|
||||
return &mPluginsIter->second;
|
||||
}
|
||||
|
@ -1868,33 +1848,13 @@ const PluginDescriptor *PluginManager::GetNextPlugin(PluginType type)
|
|||
{
|
||||
while (++mPluginsIter != mPlugins.end())
|
||||
{
|
||||
if (mPluginsIter->second.GetPluginType() == type)
|
||||
PluginDescriptor & plug = mPluginsIter->second;
|
||||
bool familyEnabled = true;
|
||||
if (type == PluginTypeEffect)
|
||||
{
|
||||
return &mPluginsIter->second;
|
||||
gPrefs->Read(plug.GetEffectFamily() + wxT("/Enable"), &familyEnabled, true);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const PluginDescriptor *PluginManager::GetFirstPluginForProvider(const PluginID & ID)
|
||||
{
|
||||
for (mPluginsIter = mPlugins.begin(); mPluginsIter != mPlugins.end(); mPluginsIter++)
|
||||
{
|
||||
if (mPluginsIter->second.GetProviderID() == ID)
|
||||
{
|
||||
return &mPluginsIter->second;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const PluginDescriptor *PluginManager::GetNextPluginForProvider(const PluginID & ID)
|
||||
{
|
||||
while (++mPluginsIter != mPlugins.end())
|
||||
{
|
||||
if (mPluginsIter->second.GetProviderID() == ID)
|
||||
if (plug.IsEnabled() && plug.GetPluginType() == type && familyEnabled)
|
||||
{
|
||||
return &mPluginsIter->second;
|
||||
}
|
||||
|
@ -1908,7 +1868,9 @@ const PluginDescriptor *PluginManager::GetFirstPluginForEffectType(EffectType ty
|
|||
for (mPluginsIter = mPlugins.begin(); mPluginsIter != mPlugins.end(); mPluginsIter++)
|
||||
{
|
||||
PluginDescriptor & plug = mPluginsIter->second;
|
||||
if (plug.IsEnabled() && plug.GetEffectType() == type)
|
||||
bool familyEnabled;
|
||||
gPrefs->Read(plug.GetEffectFamily() + wxT("/Enable"), &familyEnabled, true);
|
||||
if (plug.IsEnabled() && plug.GetEffectType() == type && familyEnabled)
|
||||
{
|
||||
return &plug;
|
||||
}
|
||||
|
@ -1922,7 +1884,9 @@ const PluginDescriptor *PluginManager::GetNextPluginForEffectType(EffectType typ
|
|||
while (++mPluginsIter != mPlugins.end())
|
||||
{
|
||||
PluginDescriptor & plug = mPluginsIter->second;
|
||||
if (plug.IsEnabled() && plug.GetEffectType() == type)
|
||||
bool familyEnabled;
|
||||
gPrefs->Read(plug.GetEffectFamily() + wxT("/Enable"), &familyEnabled, true);
|
||||
if (plug.IsEnabled() && plug.GetEffectType() == type && familyEnabled)
|
||||
{
|
||||
return &plug;
|
||||
}
|
||||
|
@ -1931,33 +1895,6 @@ const PluginDescriptor *PluginManager::GetNextPluginForEffectType(EffectType typ
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const PluginDescriptor *PluginManager::GetFirstPluginForEffectFamily(const wxString & family)
|
||||
{
|
||||
for (mPluginsIter = mPlugins.begin(); mPluginsIter != mPlugins.end(); mPluginsIter++)
|
||||
{
|
||||
if (mPluginsIter->second.GetEffectFamily() == family)
|
||||
{
|
||||
return &mPluginsIter->second;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const PluginDescriptor *PluginManager::GetNextPluginForEffectFamily(const wxString & family)
|
||||
{
|
||||
while (++mPluginsIter != mPlugins.end())
|
||||
{
|
||||
if (mPluginsIter->second.GetEffectFamily() == family)
|
||||
{
|
||||
return &mPluginsIter->second;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool PluginManager::IsRegistered(const PluginID & ID)
|
||||
{
|
||||
if (mPlugins.find(ID) == mPlugins.end())
|
||||
|
@ -2053,7 +1990,8 @@ void PluginManager::SetInstance(const PluginID & ID, IdentInterface *instance)
|
|||
|
||||
PluginDescriptor & PluginManager::CreatePlugin(IdentInterface *ident, PluginType type)
|
||||
{
|
||||
PluginDescriptor plug;
|
||||
// This will either create a new entry or replace an existing entry
|
||||
PluginDescriptor & plug = mPlugins[ident->GetID()];
|
||||
|
||||
plug.SetPluginType(type);
|
||||
|
||||
|
@ -2063,24 +2001,8 @@ PluginDescriptor & PluginManager::CreatePlugin(IdentInterface *ident, PluginType
|
|||
plug.SetVendor(ident->GetVendor());
|
||||
plug.SetVersion(ident->GetVersion());
|
||||
plug.SetDescription(ident->GetDescription());
|
||||
plug.SetEnabled(false);
|
||||
plug.SetDateTime(GetDateTime(ident->GetPath()));
|
||||
|
||||
// This will either create a new entry or replace an existing entry
|
||||
mPlugins[plug.GetID()] = plug;
|
||||
return mPlugins[plug.GetID()];
|
||||
}
|
||||
|
||||
wxString PluginManager::GetDateTime(const wxString & path)
|
||||
{
|
||||
wxFileName fn(path);
|
||||
if (fn.FileExists())
|
||||
{
|
||||
wxDateTime mod = fn.GetModificationTime();
|
||||
return wxString(mod.FormatISODate() + wxT(' ') + mod.FormatISOTime());
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
return plug;
|
||||
}
|
||||
|
||||
bool PluginManager::GetSubgroups(const wxString & group, wxArrayString & subgroups)
|
||||
|
@ -2358,24 +2280,149 @@ wxString PluginManager::PrivateKey(const PluginID & ID, const wxString & group,
|
|||
}
|
||||
|
||||
// Sanitize the ID...not the best solution, but will suffice until this
|
||||
// is converted to XML
|
||||
// is converted to XML. We use base64 encoding to preserve case.
|
||||
wxString PluginManager::ConvertID(const PluginID & ID)
|
||||
{
|
||||
wxString id = ID;
|
||||
size_t cnt = 0;
|
||||
|
||||
cnt += id.Replace(wxT("\x01"), wxT(":"));
|
||||
cnt += id.Replace(wxT("\x02"), wxT("/"));
|
||||
cnt += id.Replace(wxT("\x03"), wxT("\\"));
|
||||
|
||||
if (cnt > 0)
|
||||
if (ID.StartsWith(wxT("base64:")))
|
||||
{
|
||||
wxString id = ID.Mid(7);
|
||||
char *buf = new char[id.Length() / 4 * 3];
|
||||
id = wxString::FromUTF8(buf, b64decode(id, buf));
|
||||
delete [] buf;
|
||||
return id;
|
||||
}
|
||||
|
||||
id.Replace(wxT(":"), wxT("\x01"));
|
||||
id.Replace(wxT("/"), wxT("\x02"));
|
||||
id.Replace(wxT("\\"), wxT("\x03"));
|
||||
|
||||
return id;
|
||||
const wxCharBuffer & buf = ID.ToUTF8();
|
||||
return wxT("base64:") + b64encode(buf, strlen(buf));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Base64 en/decoding
|
||||
//
|
||||
// Original routines marked as public domain and found at:
|
||||
//
|
||||
// http://en.wikibooks.org/wiki/Algorithm_implementation/Miscellaneous/Base64
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Lookup table for encoding
|
||||
const static wxChar cset[] = wxT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
|
||||
const static char padc = wxT('=');
|
||||
|
||||
wxString PluginManager::b64encode(const void *in, int len)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) in;
|
||||
wxString out;
|
||||
|
||||
unsigned long temp;
|
||||
for (int i = 0; i < len / 3; i++)
|
||||
{
|
||||
temp = (*p++) << 16; //Convert to big endian
|
||||
temp += (*p++) << 8;
|
||||
temp += (*p++);
|
||||
out += cset[(temp & 0x00FC0000) >> 18];
|
||||
out += cset[(temp & 0x0003F000) >> 12];
|
||||
out += cset[(temp & 0x00000FC0) >> 6];
|
||||
out += cset[(temp & 0x0000003F)];
|
||||
}
|
||||
|
||||
switch (len % 3)
|
||||
{
|
||||
case 1:
|
||||
temp = (*p++) << 16; //Convert to big endian
|
||||
out += cset[(temp & 0x00FC0000) >> 18];
|
||||
out += cset[(temp & 0x0003F000) >> 12];
|
||||
out += padc;
|
||||
out += padc;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
temp = (*p++) << 16; //Convert to big endian
|
||||
temp += (*p++) << 8;
|
||||
out += cset[(temp & 0x00FC0000) >> 18];
|
||||
out += cset[(temp & 0x0003F000) >> 12];
|
||||
out += cset[(temp & 0x00000FC0) >> 6];
|
||||
out += padc;
|
||||
break;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int PluginManager::b64decode(wxString in, void *out)
|
||||
{
|
||||
int len = in.length();
|
||||
unsigned char *p = (unsigned char *) out;
|
||||
|
||||
if (len % 4) //Sanity check
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int padding = 0;
|
||||
if (len)
|
||||
{
|
||||
if (in[len - 1] == padc)
|
||||
{
|
||||
padding++;
|
||||
}
|
||||
|
||||
if (in[len - 2] == padc)
|
||||
{
|
||||
padding++;
|
||||
}
|
||||
}
|
||||
|
||||
//const char *a = in.mb_str();
|
||||
//Setup a vector to hold the result
|
||||
unsigned long temp = 0; //Holds decoded quanta
|
||||
int i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
for (int quantumPosition = 0; quantumPosition < 4; quantumPosition++)
|
||||
{
|
||||
unsigned char c = in[i];
|
||||
temp <<= 6;
|
||||
|
||||
if (c >= 0x41 && c <= 0x5A)
|
||||
{
|
||||
temp |= c - 0x41;
|
||||
}
|
||||
else if (c >= 0x61 && c <= 0x7A)
|
||||
{
|
||||
temp |= c - 0x47;
|
||||
}
|
||||
else if (c >= 0x30 && c <= 0x39)
|
||||
{
|
||||
temp |= c + 0x04;
|
||||
}
|
||||
else if (c == 0x2B)
|
||||
{
|
||||
temp |= 0x3E;
|
||||
}
|
||||
else if (c == 0x2F)
|
||||
{
|
||||
temp |= 0x3F;
|
||||
}
|
||||
else if (c == padc)
|
||||
{
|
||||
switch (len - i)
|
||||
{
|
||||
case 1: //One pad character
|
||||
*p++ = (temp >> 16) & 0x000000FF;
|
||||
*p++ = (temp >> 8) & 0x000000FF;
|
||||
return p - (unsigned char *) out;
|
||||
case 2: //Two pad characters
|
||||
*p++ = (temp >> 10) & 0x000000FF;
|
||||
return p - (unsigned char *) out;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*p++ = (temp >> 16) & 0x000000FF;
|
||||
*p++ = (temp >> 8) & 0x000000FF;
|
||||
*p++ = temp & 0x000000FF;
|
||||
}
|
||||
|
||||
return p - (unsigned char *) out;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PluginManager
|
||||
// PluginDescriptor
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -53,6 +53,7 @@ public:
|
|||
void SetPluginType(PluginType type);
|
||||
|
||||
// All plugins
|
||||
|
||||
const wxString & GetID() const;
|
||||
const wxString & GetPath() const;
|
||||
const wxString & GetName() const;
|
||||
|
@ -60,7 +61,6 @@ public:
|
|||
const wxString & GetVendor() const;
|
||||
const wxString & GetDescription() const;
|
||||
const wxString & GetProviderID() const;
|
||||
const wxString & GetDateTime() const;
|
||||
bool IsEnabled() const;
|
||||
|
||||
void SetID(const PluginID & ID);
|
||||
|
@ -70,7 +70,6 @@ public:
|
|||
void SetVendor(const wxString & vendor);
|
||||
void SetDescription(const wxString & description);
|
||||
void SetProviderID(const PluginID & providerID);
|
||||
void SetDateTime(const wxString & dateTime);
|
||||
void SetEnabled(bool enable);
|
||||
|
||||
wxString GetMenuName() const;
|
||||
|
@ -118,7 +117,6 @@ private:
|
|||
wxString mVendor;
|
||||
wxString mDescription;
|
||||
wxString mProviderID;
|
||||
wxString mDateTime;
|
||||
bool mEnabled;
|
||||
|
||||
// Effects
|
||||
|
@ -138,10 +136,21 @@ private:
|
|||
wxArrayString mImporterExtensions;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PluginManager
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WX_DECLARE_STRING_HASH_MAP(wxArrayString, ArrayStringMap);
|
||||
|
||||
//WX_DECLARE_STRING_HASH_MAP(PluginDescriptor, PluginMap);
|
||||
typedef std::map<PluginID, PluginDescriptor> PluginMap;
|
||||
|
||||
typedef wxArrayString PluginIDList;
|
||||
|
||||
class PluginRegistrationDialog;
|
||||
|
||||
class PluginManager : public PluginManagerInterface
|
||||
{
|
||||
public:
|
||||
|
@ -213,15 +222,9 @@ public:
|
|||
const PluginDescriptor *GetFirstPlugin(PluginType type);
|
||||
const PluginDescriptor *GetNextPlugin(PluginType type);
|
||||
|
||||
const PluginDescriptor *GetFirstPluginForProvider(const PluginID & ID);
|
||||
const PluginDescriptor *GetNextPluginForProvider(const PluginID & ID);
|
||||
|
||||
const PluginDescriptor *GetFirstPluginForEffectType(EffectType type);
|
||||
const PluginDescriptor *GetNextPluginForEffectType(EffectType type);
|
||||
|
||||
const PluginDescriptor *GetFirstPluginForEffectFamily(const PluginID & ID);
|
||||
const PluginDescriptor *GetNextPluginForEffectFamily(const PluginID & ID);
|
||||
|
||||
bool IsRegistered(const PluginID & ID);
|
||||
void RegisterPlugin(const wxString & type, const wxString & path);
|
||||
|
||||
|
@ -235,19 +238,17 @@ public:
|
|||
//
|
||||
const PluginID & RegisterLegacyEffectPlugin(EffectIdentInterface *effect);
|
||||
|
||||
void CheckForUpdates();
|
||||
|
||||
private:
|
||||
bool Load();
|
||||
void LoadGroup(const wxChar *group, PluginType type);
|
||||
void Save();
|
||||
void SaveGroup(const wxChar *group, PluginType type);
|
||||
|
||||
void RemoveMissing();
|
||||
void CheckForUpdates(bool forceRescan);
|
||||
void DisableMissing();
|
||||
wxArrayString IsNewOrUpdated(const wxArrayString & paths);
|
||||
|
||||
PluginDescriptor & CreatePlugin(IdentInterface *ident, PluginType type);
|
||||
wxString GetDateTime(const wxString & path);
|
||||
|
||||
bool GetSubgroups(const wxString & group, wxArrayString & subgroups);
|
||||
|
||||
|
@ -269,7 +270,12 @@ private:
|
|||
wxString SharedKey(const PluginID & ID, const wxString & group, const wxString & key);
|
||||
wxString PrivateGroup(const PluginID & ID, const wxString & group);
|
||||
wxString PrivateKey(const PluginID & ID, const wxString & group, const wxString & key);
|
||||
|
||||
// The PluginID must be kept unique. Since the wxFileConfig class does not preserve
|
||||
// case, we use base64 encoding.
|
||||
wxString ConvertID(const PluginID & ID);
|
||||
wxString b64encode(const void *in, int len);
|
||||
int b64decode(wxString in, void *out);
|
||||
|
||||
private:
|
||||
static PluginManager mInstance;
|
||||
|
@ -283,6 +289,8 @@ private:
|
|||
|
||||
PluginMap mPlugins;
|
||||
PluginMap::iterator mPluginsIter;
|
||||
|
||||
friend class PluginRegistrationDialog;
|
||||
};
|
||||
|
||||
#endif /* __AUDACITY_PLUGINMANAGER_H__ */
|
||||
|
|
|
@ -168,7 +168,7 @@ wxString Effect::GetName()
|
|||
return mClient->GetName();
|
||||
}
|
||||
|
||||
return GetEffectName();
|
||||
return GetEffectIdentifier();
|
||||
}
|
||||
|
||||
wxString Effect::GetVendor()
|
||||
|
@ -509,6 +509,10 @@ bool Effect::Startup(EffectClientInterface *client)
|
|||
case EffectTypeAnalyze:
|
||||
flags |= INSERT_EFFECT;
|
||||
break;
|
||||
|
||||
case EffectTypeNone:
|
||||
// Nothing to set
|
||||
break;
|
||||
}
|
||||
|
||||
SetEffectFlags(flags);
|
||||
|
@ -708,13 +712,17 @@ bool Effect::PromptUser(wxWindow *parent, bool forceModal)
|
|||
|
||||
// Really need to clean this up...should get easier when
|
||||
// all effects get converted.
|
||||
if (!res || SupportsRealtime())
|
||||
if (!res || (SupportsRealtime() && !forceModal))
|
||||
{
|
||||
// Return false to force DoEffect() to skip processing since
|
||||
// this UI has either been shown modeless or there was an error.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PromptUser();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2096,7 +2104,14 @@ void EffectUIHost::OnCancel(wxCommandEvent & WXUNUSED(evt))
|
|||
{
|
||||
if (IsModal())
|
||||
{
|
||||
SetReturnCode(false);
|
||||
|
||||
Close();
|
||||
|
||||
#if !defined(__WXGTK__)
|
||||
EndModal(false);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -224,6 +224,20 @@ EffectManager::~EffectManager()
|
|||
}
|
||||
}
|
||||
|
||||
void EffectManager::RegisterEffect(IdentInterface *p, Effect *f, int NewFlags)
|
||||
{
|
||||
f->SetEffectID(mNumEffects++);
|
||||
|
||||
if( NewFlags != 0)
|
||||
{
|
||||
f->SetEffectFlags( NewFlags );
|
||||
}
|
||||
|
||||
PluginManager::Get().RegisterEffectPlugin(p, f);
|
||||
|
||||
mEffects[f->GetID()] = f;
|
||||
}
|
||||
|
||||
void EffectManager::RegisterEffect(Effect *f, int NewFlags)
|
||||
{
|
||||
f->SetEffectID(mNumEffects++);
|
||||
|
@ -679,9 +693,10 @@ Effect *EffectManager::GetEffect(const PluginID & ID)
|
|||
|
||||
const PluginID & EffectManager::GetEffectByIdentifier(const wxString & strTarget)
|
||||
{
|
||||
static PluginID empty;
|
||||
if (strTarget == wxEmptyString) // set GetEffectIdentifier to wxT("") to not show an effect in Batch mode
|
||||
{
|
||||
return PluginID(wxEmptyString);
|
||||
return empty;
|
||||
}
|
||||
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
|
@ -695,7 +710,7 @@ const PluginID & EffectManager::GetEffectByIdentifier(const wxString & strTarget
|
|||
plug = pm.GetNextPlugin(PluginTypeEffect);
|
||||
}
|
||||
|
||||
return PluginID(wxEmptyString);
|
||||
return empty;;
|
||||
}
|
||||
|
||||
#ifdef EFFECT_CATEGORIES
|
||||
|
|
|
@ -67,6 +67,7 @@ class AUDACITY_DLL_API EffectManager
|
|||
|
||||
/** Register an effect so it will appear in the menu. */
|
||||
void RegisterEffect(Effect *f, int AdditionalFlags=0);
|
||||
void RegisterEffect(IdentInterface *p, Effect *f, int AdditionalFlags=0);
|
||||
|
||||
/** Unregister all effects. */
|
||||
void UnregisterEffects();
|
||||
|
|
|
@ -265,7 +265,7 @@ void EffectRack::OnClose(wxCloseEvent & evt)
|
|||
evt.Veto();
|
||||
}
|
||||
|
||||
void EffectRack::OnTimer(wxTimerEvent & AUNUSED(evt))
|
||||
void EffectRack::OnTimer(wxTimerEvent & WXUNUSED(evt))
|
||||
{
|
||||
int latency = EffectManager::Get().GetRealtimeLatency();
|
||||
if (latency != mLastLatency)
|
||||
|
@ -276,7 +276,7 @@ void EffectRack::OnTimer(wxTimerEvent & AUNUSED(evt))
|
|||
}
|
||||
}
|
||||
|
||||
void EffectRack::OnApply(wxCommandEvent & AUNUSED(evt))
|
||||
void EffectRack::OnApply(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
AudacityProject *project = GetActiveProject();
|
||||
|
||||
|
|
|
@ -57,18 +57,10 @@
|
|||
#include "ChangeTempo.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_NYQUIST
|
||||
#include "nyquist/LoadNyquist.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_AUDIO_UNITS
|
||||
#include "audiounits/LoadAudioUnits.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_LV2
|
||||
#include "lv2/LoadLV2.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_VAMP
|
||||
#include "vamp/LoadVamp.h"
|
||||
#endif
|
||||
|
@ -279,42 +271,15 @@ void LoadEffects()
|
|||
// Analyze menu
|
||||
em.RegisterEffect(new EffectFindClipping());
|
||||
|
||||
#ifdef USE_NYQUIST
|
||||
if (gPrefs->Read(wxT("/Nyquist/Enable"), true)) {
|
||||
LoadNyquistPlugins();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_LV2
|
||||
if (gPrefs->Read(wxT("/LV2/Enable"), true)) {
|
||||
LoadLV2Plugins();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_AUDIO_UNITS
|
||||
if (gPrefs->Read(wxT("/AudioUnits/Enable"), true)) {
|
||||
LoadAudioUnits();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_VAMP
|
||||
if (gPrefs->Read(wxT("/VAMP/Enable"), true)) {
|
||||
LoadVampPlugins();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void UnloadEffects()
|
||||
{
|
||||
EffectManager::Get().UnregisterEffects();
|
||||
|
||||
#ifdef USE_LV2
|
||||
UnloadLV2Plugins();
|
||||
#endif
|
||||
|
||||
#ifdef USE_VAMP
|
||||
UnloadVampPlugins();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -551,6 +551,12 @@ bool VSTEffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxStrin
|
|||
return valid;
|
||||
}
|
||||
|
||||
bool VSTEffectsModule::IsPluginValid(const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
return wxFileName::FileExists(path);
|
||||
}
|
||||
|
||||
IdentInterface *VSTEffectsModule::CreateInstance(const PluginID & WXUNUSED(ID),
|
||||
const wxString & path)
|
||||
{
|
||||
|
|
|
@ -397,6 +397,8 @@ public:
|
|||
virtual wxArrayString FindPlugins(PluginManagerInterface & pm);
|
||||
virtual bool RegisterPlugin(PluginManagerInterface & pm, const wxString & path);
|
||||
|
||||
virtual bool IsPluginValid(const PluginID & ID, const wxString & path);
|
||||
|
||||
virtual IdentInterface *CreateInstance(const PluginID & ID, const wxString & path);
|
||||
virtual void DeleteInstance(IdentInterface *instance);
|
||||
|
||||
|
|
|
@ -346,6 +346,12 @@ bool LadspaEffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxSt
|
|||
return index > 0;
|
||||
}
|
||||
|
||||
bool LadspaEffectsModule::IsPluginValid(const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
return wxFileName::FileExists(path);
|
||||
}
|
||||
|
||||
IdentInterface *LadspaEffectsModule::CreateInstance(const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
|
@ -1222,7 +1228,6 @@ bool LadspaEffect::PopulateUI(wxWindow *parent)
|
|||
gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
|
||||
|
||||
wxString fieldText;
|
||||
LADSPA_PortRangeHint hint = mData->PortRangeHints[p];
|
||||
|
||||
mFields[p] = new wxTextCtrl(mParent, wxID_ANY,
|
||||
fieldText,
|
||||
|
@ -1558,24 +1563,6 @@ void LadspaEffect::RefreshControls(bool outputOnly)
|
|||
continue;
|
||||
}
|
||||
|
||||
wxString bound;
|
||||
double lower = -FLT_MAX;
|
||||
double upper = FLT_MAX;
|
||||
bool haslo = false;
|
||||
bool hashi = false;
|
||||
|
||||
if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor))
|
||||
{
|
||||
lower = hint.LowerBound;
|
||||
haslo = true;
|
||||
}
|
||||
|
||||
if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor))
|
||||
{
|
||||
upper = hint.UpperBound;
|
||||
hashi = true;
|
||||
}
|
||||
|
||||
if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor) || forceint)
|
||||
{
|
||||
fieldText.Printf(wxT("%d"), (int)(mInputControls[p] + 0.5));
|
||||
|
|
|
@ -244,6 +244,8 @@ public:
|
|||
virtual wxArrayString FindPlugins(PluginManagerInterface & pm);
|
||||
virtual bool RegisterPlugin(PluginManagerInterface & pm, const wxString & path);
|
||||
|
||||
virtual bool IsPluginValid(const PluginID & ID, const wxString & path);
|
||||
|
||||
virtual IdentInterface *CreateInstance(const PluginID & ID, const wxString & path);
|
||||
virtual void DeleteInstance(IdentInterface *instance);
|
||||
|
||||
|
|
|
@ -53,6 +53,12 @@
|
|||
|
||||
#include <wx/arrimpl.cpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LV2Effect
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WX_DEFINE_OBJARRAY(LV2PortArray);
|
||||
|
||||
LV2Effect::LV2Effect(const LilvPlugin *data,
|
||||
|
@ -292,6 +298,92 @@ LV2Effect::~LV2Effect()
|
|||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// IdentInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
wxString LV2Effect::GetID()
|
||||
{
|
||||
return GetString(lilv_plugin_get_uri(mData));
|
||||
}
|
||||
|
||||
wxString LV2Effect::GetPath()
|
||||
{
|
||||
return GetString(lilv_plugin_get_bundle_uri(mData));
|
||||
}
|
||||
|
||||
wxString LV2Effect::GetName()
|
||||
{
|
||||
return pluginName;
|
||||
}
|
||||
|
||||
wxString LV2Effect::GetVendor()
|
||||
{
|
||||
wxString vendor = GetString(lilv_plugin_get_author_name(mData), true);
|
||||
|
||||
if (vendor.IsEmpty())
|
||||
{
|
||||
vendor = wxT("N/A");
|
||||
}
|
||||
|
||||
return vendor;
|
||||
}
|
||||
|
||||
wxString LV2Effect::GetVersion()
|
||||
{
|
||||
return wxT("N/A");
|
||||
}
|
||||
|
||||
wxString LV2Effect::GetDescription()
|
||||
{
|
||||
return wxT("N/A");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// EffectIdentInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
EffectType LV2Effect::GetType()
|
||||
{
|
||||
// For now, relegate to Effect()
|
||||
return Effect::GetType();
|
||||
}
|
||||
|
||||
wxString LV2Effect::GetFamily()
|
||||
{
|
||||
return LV2EFFECTS_FAMILY;
|
||||
}
|
||||
|
||||
bool LV2Effect::IsInteractive()
|
||||
{
|
||||
// For now, relegate to Effect()
|
||||
return Effect::IsInteractive();
|
||||
}
|
||||
|
||||
bool LV2Effect::IsDefault()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LV2Effect::IsLegacy()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LV2Effect::SupportsRealtime()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LV2Effect::SupportsAutomation()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Effect Implementation
|
||||
// ============================================================================
|
||||
|
||||
wxString LV2Effect::GetEffectName()
|
||||
{
|
||||
if (mControlInputs.GetCount() > 0)
|
||||
|
@ -714,6 +806,9 @@ void LV2Effect::End()
|
|||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// LV2Effect Implementation
|
||||
// ============================================================================
|
||||
|
||||
bool LV2Effect::IsValid()
|
||||
{
|
||||
|
@ -1246,9 +1341,11 @@ LV2EffectDialog::LV2EffectDialog(LV2Effect *effect,
|
|||
|
||||
LV2EffectDialog::~LV2EffectDialog()
|
||||
{
|
||||
delete [] mToggles;
|
||||
delete [] mSliders;
|
||||
delete [] mFields;
|
||||
delete [] mLabels;
|
||||
delete [] mEnums;
|
||||
}
|
||||
|
||||
void LV2EffectDialog::OnCheckBox(wxCommandEvent &event)
|
||||
|
|
|
@ -24,6 +24,8 @@ class wxCheckBox;
|
|||
#include "../Effect.h"
|
||||
#include "LV2PortGroup.h"
|
||||
|
||||
#define LV2EFFECTS_VERSION wxT("1.0.0.0");
|
||||
#define LV2EFFECTS_FAMILY L"LV2"
|
||||
|
||||
/** A structure that contains information about a single LV2 plugin port. */
|
||||
struct LV2Port
|
||||
|
@ -66,6 +68,27 @@ public:
|
|||
const std::set<wxString> & categories = std::set<wxString>());
|
||||
virtual ~LV2Effect();
|
||||
|
||||
// IdentInterface implementation
|
||||
|
||||
virtual PluginID GetID();
|
||||
virtual wxString GetPath();
|
||||
virtual wxString GetName();
|
||||
virtual wxString GetVendor();
|
||||
virtual wxString GetVersion();
|
||||
virtual wxString GetDescription();
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
virtual EffectType GetType();
|
||||
virtual wxString GetFamily();
|
||||
virtual bool IsInteractive();
|
||||
virtual bool IsDefault();
|
||||
virtual bool IsLegacy();
|
||||
virtual bool SupportsRealtime();
|
||||
virtual bool SupportsAutomation();
|
||||
|
||||
// Effect implementation
|
||||
|
||||
/** Get the name of the effect. */
|
||||
virtual wxString GetEffectName();
|
||||
|
||||
|
|
|
@ -41,6 +41,32 @@ Functions that find and load all LV2 plugins on the system.
|
|||
|
||||
#include "LoadLV2.h"
|
||||
|
||||
// ============================================================================
|
||||
// Module registration entry point
|
||||
//
|
||||
// This is the symbol that Audacity looks for when the module is built as a
|
||||
// dynamic library.
|
||||
//
|
||||
// When the module is builtin to Audacity, we use the same function, but it is
|
||||
// declared static so as not to clash with other builtin modules.
|
||||
// ============================================================================
|
||||
DECLARE_MODULE_ENTRY(AudacityModule)
|
||||
{
|
||||
// Create and register the importer
|
||||
return new LV2EffectsModule(moduleManager, path);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Register this as a builtin module
|
||||
// ============================================================================
|
||||
DECLARE_BUILTIN_MODULE(LV2sEffectBuiltin);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LV2EffectsModule
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LilvWorld *gWorld = NULL;
|
||||
|
||||
// This is the URI Map Feature object. It is required for loading synth
|
||||
|
@ -96,24 +122,67 @@ LilvNode *gName;
|
|||
LilvNode *gPortGroup;
|
||||
LilvNode *gSubGroupOf;
|
||||
|
||||
void LoadLV2Plugins()
|
||||
LV2EffectsModule::LV2EffectsModule(ModuleManagerInterface *moduleManager,
|
||||
const wxString *path)
|
||||
{
|
||||
|
||||
EffectManager& em = EffectManager::Get();
|
||||
|
||||
// If gWorld isn't 0 we have already initialised Lilv - unload all plugins
|
||||
// and initialise again.
|
||||
if (gWorld)
|
||||
mModMan = moduleManager;
|
||||
if (path)
|
||||
{
|
||||
UnloadLV2Plugins();
|
||||
mPath = *path;
|
||||
}
|
||||
}
|
||||
|
||||
LV2EffectsModule::~LV2EffectsModule()
|
||||
{
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// IdentInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
wxString LV2EffectsModule::GetID()
|
||||
{
|
||||
// Can be anything, but this is a v4 UUID
|
||||
return wxT("5d03b6ad-ca64-41b2-a3f2-785ff5b279d9");
|
||||
}
|
||||
|
||||
wxString LV2EffectsModule::GetPath()
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
wxString LV2EffectsModule::GetName()
|
||||
{
|
||||
return _("LV2 Effects Module");
|
||||
}
|
||||
|
||||
wxString LV2EffectsModule::GetVendor()
|
||||
{
|
||||
return _("The Audacity Team");
|
||||
}
|
||||
|
||||
wxString LV2EffectsModule::GetVersion()
|
||||
{
|
||||
// This "may" be different if this were to be maintained as a separate DLL
|
||||
return LV2EFFECTS_VERSION;
|
||||
}
|
||||
|
||||
wxString LV2EffectsModule::GetDescription()
|
||||
{
|
||||
return _("Provides LV2 Effects support to Audacity");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ModuleInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
bool LV2EffectsModule::Initialize()
|
||||
{
|
||||
// Try to initialise Lilv, or return.
|
||||
gWorld = lilv_world_new();
|
||||
if (!gWorld)
|
||||
{
|
||||
wxLogMessage(wxT("Could not initialise lilv!"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
gAudioPortClass = lilv_new_uri(gWorld, LV2_CORE__AudioPort);
|
||||
|
@ -133,49 +202,10 @@ void LoadLV2Plugins()
|
|||
|
||||
lilv_world_load_all(gWorld);
|
||||
|
||||
#ifdef EFFECT_CATEGORIES
|
||||
|
||||
// Add all LV2 categories and their relationships
|
||||
LilvPluginClasses classes = Lilv_world_get_plugin_classes(gWorld);
|
||||
for (unsigned index = 0; index < Lilv_plugin_classes_size(classes);++index){
|
||||
LilvPluginClass c = Lilv_plugin_classes_get_at(classes, index);
|
||||
em.AddCategory(wxString::FromUTF8(lilv_node_as_uri(Lilv_plugin_class_get_uri(c))),
|
||||
wxString::FromUTF8(lilv_node_as_string(Lilv_plugin_class_get_label(c))));
|
||||
}
|
||||
for (unsigned index = 0; index < Lilv_plugin_classes_size(classes);++index){
|
||||
LilvPluginClass c = Lilv_plugin_classes_get_at(classes, index);
|
||||
LilvPluginClasses ch = Lilv_plugin_class_get_children(c);
|
||||
EffectCategory* pCat = em.LookupCategory(wxString::FromUTF8(lilv_node_as_uri(Lilv_plugin_class_get_uri(c))));
|
||||
for (unsigned j = 0; j < Lilv_plugin_classes_size(ch); ++j) {
|
||||
EffectCategory* chCat = em.LookupCategory(wxString::FromUTF8(lilv_node_as_uri(Lilv_plugin_class_get_uri(Lilv_plugin_classes_get_at(ch, j)))));
|
||||
if (chCat && pCat) {
|
||||
em.AddCategoryParent(chCat, pCat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Retrieve data about all plugins
|
||||
const LilvPlugins *plugs = lilv_world_get_all_plugins(gWorld);
|
||||
|
||||
// Iterate over all plugins and register them with the EffectManager
|
||||
LILV_FOREACH(plugins, i, plugs)
|
||||
{
|
||||
const LilvPlugin *plug = lilv_plugins_get(plugs, i);
|
||||
std::set<wxString> cats;
|
||||
cats.insert(wxString::FromUTF8(lilv_node_as_uri(lilv_plugin_class_get_uri(lilv_plugin_get_class(plug)))));
|
||||
LV2Effect *effect = new LV2Effect(plug, cats);
|
||||
if (effect->IsValid())
|
||||
em.RegisterEffect(effect);
|
||||
else
|
||||
delete effect;
|
||||
//std::cerr<<"Loaded LV2 \""<<lilv_node_as_string(Lilv_plugin_get_name(plug))<<"\""<<std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UnloadLV2Plugins()
|
||||
void LV2EffectsModule::Terminate()
|
||||
{
|
||||
lilv_node_free(gAudioPortClass);
|
||||
gAudioPortClass = NULL;
|
||||
|
@ -221,6 +251,97 @@ void UnloadLV2Plugins()
|
|||
|
||||
lilv_world_free(gWorld);
|
||||
gWorld = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool LV2EffectsModule::AutoRegisterPlugins(PluginManagerInterface & pm)
|
||||
{
|
||||
EffectManager& em = EffectManager::Get();
|
||||
|
||||
#ifdef EFFECT_CATEGORIES
|
||||
|
||||
// Add all LV2 categories and their relationships
|
||||
LilvPluginClasses classes = Lilv_world_get_plugin_classes(gWorld);
|
||||
for (unsigned index = 0; index < Lilv_plugin_classes_size(classes);++index){
|
||||
LilvPluginClass c = Lilv_plugin_classes_get_at(classes, index);
|
||||
em.AddCategory(wxString::FromUTF8(lilv_node_as_uri(Lilv_plugin_class_get_uri(c))),
|
||||
wxString::FromUTF8(lilv_node_as_string(Lilv_plugin_class_get_label(c))));
|
||||
}
|
||||
for (unsigned index = 0; index < Lilv_plugin_classes_size(classes);++index){
|
||||
LilvPluginClass c = Lilv_plugin_classes_get_at(classes, index);
|
||||
LilvPluginClasses ch = Lilv_plugin_class_get_children(c);
|
||||
EffectCategory* pCat = em.LookupCategory(wxString::FromUTF8(lilv_node_as_uri(Lilv_plugin_class_get_uri(c))));
|
||||
for (unsigned j = 0; j < Lilv_plugin_classes_size(ch); ++j) {
|
||||
EffectCategory* chCat = em.LookupCategory(wxString::FromUTF8(lilv_node_as_uri(Lilv_plugin_class_get_uri(Lilv_plugin_classes_get_at(ch, j)))));
|
||||
if (chCat && pCat) {
|
||||
em.AddCategoryParent(chCat, pCat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Retrieve data about all plugins
|
||||
const LilvPlugins *plugs = lilv_world_get_all_plugins(gWorld);
|
||||
|
||||
// Iterate over all plugins and register them with the EffectManager
|
||||
LILV_FOREACH(plugins, i, plugs)
|
||||
{
|
||||
const LilvPlugin *plug = lilv_plugins_get(plugs, i);
|
||||
std::set<wxString> cats;
|
||||
cats.insert(wxString::FromUTF8(lilv_node_as_uri(lilv_plugin_class_get_uri(lilv_plugin_get_class(plug)))));
|
||||
LV2Effect *effect = new LV2Effect(plug, cats);
|
||||
if (effect->IsValid())
|
||||
{
|
||||
em.RegisterEffect(this, effect);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete effect;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wxArrayString LV2EffectsModule::FindPlugins(PluginManagerInterface & pm)
|
||||
{
|
||||
// Nothing to do here yet
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LV2EffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxString & path)
|
||||
{
|
||||
// Nothing to do here yet
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LV2EffectsModule::IsPluginValid(const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
LilvNode *uri = lilv_new_uri(gWorld, path.ToUTF8());
|
||||
const LilvPlugin *plugin = lilv_plugins_get_by_uri(lilv_world_get_all_plugins(gWorld), uri);
|
||||
lilv_node_free(uri);
|
||||
|
||||
return plugin != NULL;
|
||||
}
|
||||
|
||||
IdentInterface *LV2EffectsModule::CreateInstance(const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
// Nothing to do here yet since we are autoregistering (and creating legacy
|
||||
// effects anyway).
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void LV2EffectsModule::DeleteInstance(IdentInterface *instance)
|
||||
{
|
||||
// Nothing to do here yet
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// LV2EffectsModule implementation
|
||||
// ============================================================================
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,52 @@
|
|||
|
||||
#include <lilv/lilv.h>
|
||||
|
||||
#include "audacity/ModuleInterface.h"
|
||||
#include "audacity/EffectInterface.h"
|
||||
#include "audacity/PluginInterface.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LV2EffectsModule
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LV2EffectsModule : public ModuleInterface
|
||||
{
|
||||
public:
|
||||
LV2EffectsModule(ModuleManagerInterface *moduleManager, const wxString *path);
|
||||
virtual ~LV2EffectsModule();
|
||||
|
||||
// IdentInterface implementatino
|
||||
|
||||
virtual wxString GetID();
|
||||
virtual wxString GetPath();
|
||||
virtual wxString GetName();
|
||||
virtual wxString GetVendor();
|
||||
virtual wxString GetVersion();
|
||||
virtual wxString GetDescription();
|
||||
|
||||
// ModuleInterface implementation
|
||||
|
||||
virtual bool Initialize();
|
||||
virtual void Terminate();
|
||||
|
||||
virtual bool AutoRegisterPlugins(PluginManagerInterface & pm);
|
||||
virtual wxArrayString FindPlugins(PluginManagerInterface & pm);
|
||||
virtual bool RegisterPlugin(PluginManagerInterface & pm, const wxString & path);
|
||||
|
||||
virtual bool IsPluginValid(const PluginID & ID, const wxString & path);
|
||||
|
||||
virtual IdentInterface *CreateInstance(const PluginID & ID, const wxString & path);
|
||||
virtual void DeleteInstance(IdentInterface *instance);
|
||||
|
||||
// LV2EffectModule implementation
|
||||
|
||||
private:
|
||||
ModuleManagerInterface *mModMan;
|
||||
wxString mPath;
|
||||
};
|
||||
|
||||
extern LilvWorld *gWorld;
|
||||
|
||||
// This is the LV2 Feature array. It is passed to every LV2 plugin on
|
||||
|
|
|
@ -8,43 +8,174 @@
|
|||
|
||||
**********************************************************************/
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include <wx/filefn.h>
|
||||
#include <wx/list.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include "../../Audacity.h"
|
||||
#include "../../AudacityApp.h"
|
||||
#include "../EffectManager.h"
|
||||
#include "Nyquist.h"
|
||||
#include "LoadNyquist.h"
|
||||
|
||||
void LoadNyquistEffect(wxString fname)
|
||||
// ============================================================================
|
||||
// Module registration entry point
|
||||
//
|
||||
// This is the symbol that Audacity looks for when the module is built as a
|
||||
// dynamic library.
|
||||
//
|
||||
// When the module is builtin to Audacity, we use the same function, but it is
|
||||
// declared static so as not to clash with other builtin modules.
|
||||
// ============================================================================
|
||||
DECLARE_MODULE_ENTRY(AudacityModule)
|
||||
{
|
||||
EffectNyquist *effect = new EffectNyquist(fname);
|
||||
if (effect->LoadedNyFile())
|
||||
EffectManager::Get().RegisterEffect(effect);
|
||||
else
|
||||
delete effect;
|
||||
// Create and register the importer
|
||||
return new NyquistEffectsModule(moduleManager, path);
|
||||
}
|
||||
|
||||
void LoadNyquistPlugins()
|
||||
// ============================================================================
|
||||
// Register this as a builtin module
|
||||
// ============================================================================
|
||||
DECLARE_BUILTIN_MODULE(NyquistsEffectBuiltin);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// NyquistEffectsModule
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NyquistEffectsModule::NyquistEffectsModule(ModuleManagerInterface *moduleManager,
|
||||
const wxString *path)
|
||||
{
|
||||
mModMan = moduleManager;
|
||||
if (path)
|
||||
{
|
||||
mPath = *path;
|
||||
}
|
||||
}
|
||||
|
||||
NyquistEffectsModule::~NyquistEffectsModule()
|
||||
{
|
||||
mPath.Clear();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// IdentInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
wxString NyquistEffectsModule::GetID()
|
||||
{
|
||||
// Can be anything, but this is a v4 UUID
|
||||
return wxT("42a58b1e-cc24-4b55-861a-4b2008a7cf7b");
|
||||
}
|
||||
|
||||
wxString NyquistEffectsModule::GetPath()
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
wxString NyquistEffectsModule::GetName()
|
||||
{
|
||||
return _("Nyquist Effects Module");
|
||||
}
|
||||
|
||||
wxString NyquistEffectsModule::GetVendor()
|
||||
{
|
||||
return _("The Audacity Team");
|
||||
}
|
||||
|
||||
wxString NyquistEffectsModule::GetVersion()
|
||||
{
|
||||
// This "may" be different if this were to be maintained as a separate DLL
|
||||
return NYQUISTEFFECTS_VERSION;
|
||||
}
|
||||
|
||||
wxString NyquistEffectsModule::GetDescription()
|
||||
{
|
||||
return _("Provides Nyquist Effects support to Audacity");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ModuleInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
bool NyquistEffectsModule::Initialize()
|
||||
{
|
||||
// Nothing to do here
|
||||
return true;
|
||||
}
|
||||
|
||||
void NyquistEffectsModule::Terminate()
|
||||
{
|
||||
// Nothing to do here
|
||||
return;
|
||||
}
|
||||
|
||||
bool NyquistEffectsModule::AutoRegisterPlugins(PluginManagerInterface & pm)
|
||||
{
|
||||
// For Nyquist, we autoregister plugins at this time using the legacy
|
||||
// interface. This will change eventually.
|
||||
|
||||
wxArrayString pathList = EffectNyquist::GetNyquistSearchPath();
|
||||
wxArrayString files;
|
||||
unsigned int i;
|
||||
|
||||
// Create one "interactive Nyquist"
|
||||
// Create one "interactive Nyquist" effect
|
||||
EffectNyquist *effect = new EffectNyquist(wxT(""));
|
||||
EffectManager::Get().RegisterEffect(effect);
|
||||
EffectManager::Get().RegisterEffect(this, effect);
|
||||
|
||||
// Load .ny plug-ins
|
||||
wxGetApp().FindFilesInPathList(wxT("*.ny"), pathList, files);
|
||||
pm.FindFilesInPathList(wxT("*.ny"), pathList, files);
|
||||
#ifdef __WXGTK__
|
||||
wxGetApp().FindFilesInPathList(wxT("*.NY"), pathList, files); // Ed's fix for bug 179
|
||||
pm.FindFilesInPathList(wxT("*.NY"), pathList, files); // Ed's fix for bug 179
|
||||
#endif
|
||||
|
||||
for(i=0; i<files.GetCount(); i++)
|
||||
LoadNyquistEffect(files[i]);
|
||||
for (size_t i = 0; i < files.GetCount(); i++)
|
||||
{
|
||||
EffectNyquist *effect = new EffectNyquist(files[i]);
|
||||
if (effect->LoadedNyFile())
|
||||
{
|
||||
EffectManager::Get().RegisterEffect(this, effect);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete effect;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wxArrayString NyquistEffectsModule::FindPlugins(PluginManagerInterface & pm)
|
||||
{
|
||||
// Nothing to do here yet
|
||||
return wxArrayString();
|
||||
}
|
||||
|
||||
bool NyquistEffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxString & path)
|
||||
{
|
||||
// Nothing to do here yet
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NyquistEffectsModule::IsPluginValid(const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
if (ID == wxT("nyquist prompt"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return wxFileName::FileExists(path);
|
||||
}
|
||||
|
||||
IdentInterface *NyquistEffectsModule::CreateInstance(const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
// Nothing to do here yet since we are autoregistering (and creating legacy
|
||||
// effects anyway).
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void NyquistEffectsModule::DeleteInstance(IdentInterface *instance)
|
||||
{
|
||||
// Nothing to do here yet
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// NyquistEffectsModule implementation
|
||||
// ============================================================================
|
||||
|
||||
|
|
|
@ -8,5 +8,48 @@
|
|||
|
||||
**********************************************************************/
|
||||
|
||||
void LoadNyquistPlugins();
|
||||
#include "audacity/ModuleInterface.h"
|
||||
#include "audacity/EffectInterface.h"
|
||||
#include "audacity/PluginInterface.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// NyquistEffectsModule
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class NyquistEffectsModule : public ModuleInterface
|
||||
{
|
||||
public:
|
||||
NyquistEffectsModule(ModuleManagerInterface *moduleManager, const wxString *path);
|
||||
virtual ~NyquistEffectsModule();
|
||||
|
||||
// IdentInterface implementatino
|
||||
|
||||
virtual wxString GetID();
|
||||
virtual wxString GetPath();
|
||||
virtual wxString GetName();
|
||||
virtual wxString GetVendor();
|
||||
virtual wxString GetVersion();
|
||||
virtual wxString GetDescription();
|
||||
|
||||
// ModuleInterface implementation
|
||||
|
||||
virtual bool Initialize();
|
||||
virtual void Terminate();
|
||||
|
||||
virtual bool AutoRegisterPlugins(PluginManagerInterface & pm);
|
||||
virtual wxArrayString FindPlugins(PluginManagerInterface & pm);
|
||||
virtual bool RegisterPlugin(PluginManagerInterface & pm, const wxString & path);
|
||||
|
||||
virtual bool IsPluginValid(const PluginID & ID, const wxString & path);
|
||||
|
||||
virtual IdentInterface *CreateInstance(const PluginID & ID, const wxString & path);
|
||||
virtual void DeleteInstance(IdentInterface *instance);
|
||||
|
||||
// NyquistEffectModule implementation
|
||||
|
||||
private:
|
||||
ModuleManagerInterface *mModMan;
|
||||
wxString mPath;
|
||||
};
|
||||
|
|
|
@ -74,6 +74,15 @@ effects from this one class.
|
|||
#include <float.h>
|
||||
|
||||
#include <wx/arrimpl.cpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// NyquistEffect
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define UNINITIALIZED_CONTROL ((double)99999999.99)
|
||||
|
||||
WX_DEFINE_OBJARRAY(NyqControlArray);
|
||||
|
||||
EffectNyquist::EffectNyquist(wxString fName)
|
||||
|
@ -88,6 +97,8 @@ EffectNyquist::EffectNyquist(wxString fName)
|
|||
mDebug = false;
|
||||
mIsSal = false;
|
||||
mOK = false;
|
||||
mAuthor = wxT("N/A");
|
||||
mCopyright = wxT("N/A");
|
||||
|
||||
mVersion = 4;
|
||||
|
||||
|
@ -120,331 +131,103 @@ EffectNyquist::EffectNyquist(wxString fName)
|
|||
|
||||
EffectNyquist::~EffectNyquist()
|
||||
{
|
||||
nyx_set_xlisp_path(NULL);
|
||||
}
|
||||
|
||||
wxString EffectNyquist::NyquistToWxString(const char *nyqString)
|
||||
// ============================================================================
|
||||
// IdentInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
wxString EffectNyquist::GetID()
|
||||
{
|
||||
wxString str(nyqString, wxConvUTF8);
|
||||
if (nyqString != NULL && nyqString[0] && str.IsEmpty()) {
|
||||
// invalid UTF-8 string, convert as Latin-1
|
||||
str = _("[Warning: Nyquist returned invalid UTF-8 string, converted here as Latin-1]");
|
||||
str += LAT1CTOWX(nyqString);
|
||||
}
|
||||
return str;
|
||||
return GetPath();
|
||||
}
|
||||
|
||||
|
||||
void EffectNyquist::Break()
|
||||
wxString EffectNyquist::GetPath()
|
||||
{
|
||||
mBreak = true;
|
||||
}
|
||||
|
||||
void EffectNyquist::Continue()
|
||||
{
|
||||
mCont = true;
|
||||
}
|
||||
|
||||
void EffectNyquist::Stop()
|
||||
{
|
||||
mStop = true;
|
||||
}
|
||||
|
||||
#define UNINITIALIZED_CONTROL ((double)99999999.99)
|
||||
|
||||
wxString EffectNyquist::UnQuote(wxString s)
|
||||
{
|
||||
wxString out;
|
||||
int len = s.Length();
|
||||
|
||||
if (len >= 2 && s[0] == wxT('\"') && s[len - 1] == wxT('\"')) {
|
||||
return s.Mid(1, len - 2);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
double EffectNyquist::GetCtrlValue(wxString s)
|
||||
{
|
||||
if (s == wxT("rate")) {
|
||||
TrackListOfKindIterator iter(Track::Wave, mTracks);
|
||||
return ((WaveTrack *)iter.First())->GetRate();
|
||||
}
|
||||
|
||||
return Internat::CompatibleToDouble(s);
|
||||
}
|
||||
|
||||
void EffectNyquist::Parse(wxString line)
|
||||
{
|
||||
wxArrayString tokens;
|
||||
|
||||
int i;
|
||||
int len = line.Length();
|
||||
bool sl = false;
|
||||
bool q = false;
|
||||
wxString tok = wxT("");
|
||||
|
||||
for (i = 1; i < len; i++) {
|
||||
wxChar c = line[i];
|
||||
|
||||
if (c == wxT('\\')) {
|
||||
sl = true;
|
||||
}
|
||||
else if (c == wxT('"')) {
|
||||
q = !q;
|
||||
}
|
||||
else {
|
||||
if ((!q && !sl && c == wxT(' ')) || c == wxT('\t')) {
|
||||
tokens.Add(tok);
|
||||
tok = wxT("");
|
||||
}
|
||||
else if (sl && c == wxT('n')) {
|
||||
tok += wxT('\n');
|
||||
}
|
||||
else {
|
||||
tok += c;
|
||||
}
|
||||
|
||||
sl = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (tok != wxT("")) {
|
||||
tokens.Add(tok);
|
||||
}
|
||||
|
||||
len = tokens.GetCount();
|
||||
if (len < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len == 2 && tokens[0] == wxT("nyquist") && tokens[1] == wxT("plug-in")) {
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("type")) {
|
||||
if (tokens[1] == wxT("process")) {
|
||||
SetEffectFlags(PROCESS_EFFECT | PLUGIN_EFFECT);
|
||||
}
|
||||
else if (tokens[1] == wxT("generate")) {
|
||||
SetEffectFlags(INSERT_EFFECT | PLUGIN_EFFECT);
|
||||
}
|
||||
else if (tokens[1] == wxT("analyze")) {
|
||||
SetEffectFlags(ANALYZE_EFFECT | PLUGIN_EFFECT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len == 2 && tokens[0] == wxT("codetype")) {
|
||||
if (tokens[1] == wxT("lisp")) {
|
||||
mIsSal = false;
|
||||
}
|
||||
else if (tokens[1] == wxT("sal")) {
|
||||
mIsSal = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("debugflags")) {
|
||||
for (int i = 1; i < len; i++) {
|
||||
// Note: "trace" and "notrace" are overridden by "Debug" and "OK"
|
||||
// buttons if the plug-in generates a dialog box by using controls
|
||||
if (tokens[i] == wxT("trace")) {
|
||||
mDebug = true;
|
||||
}
|
||||
else if (tokens[i] == wxT("notrace")) {
|
||||
mDebug = false;
|
||||
}
|
||||
else if (tokens[i] == wxT("compiler")) {
|
||||
mCompiler = true;
|
||||
}
|
||||
else if (tokens[i] == wxT("nocompiler")) {
|
||||
mCompiler = false;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We support versions 1, 2 and 3
|
||||
// (Version 2 added support for string parameters.)
|
||||
// (Version 3 added support for choice parameters.)
|
||||
// (Version 4 added support for project/track/selection information.)
|
||||
if (len >= 2 && tokens[0] == wxT("version")) {
|
||||
long v;
|
||||
tokens[1].ToLong(&v);
|
||||
if (v < 1 && v > 4) {
|
||||
// This is an unsupported plug-in version
|
||||
mOK = false;
|
||||
return;
|
||||
}
|
||||
mVersion = (int) v;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("name")) {
|
||||
mName = UnQuote(tokens[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("action")) {
|
||||
mAction = UnQuote(tokens[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("info")) {
|
||||
mInfo = UnQuote(tokens[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("preview")) {
|
||||
if (tokens[1] == wxT("enabled") || tokens[1] == wxT("true")) {
|
||||
mEnablePreview = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 6 && tokens[0] == wxT("control")) {
|
||||
NyqControl ctrl;
|
||||
|
||||
ctrl.var = tokens[1];
|
||||
ctrl.name = tokens[2];
|
||||
ctrl.label = tokens[4];
|
||||
ctrl.valStr = tokens[5];
|
||||
|
||||
if (tokens[3] == wxT("string")) {
|
||||
ctrl.type = NYQ_CTRL_STRING;
|
||||
}
|
||||
else if (tokens[ 3 ] == wxT("choice")) {
|
||||
ctrl.type = NYQ_CTRL_CHOICE;
|
||||
}
|
||||
else {
|
||||
if (len < 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((tokens[3] == wxT("real")) ||
|
||||
(tokens[3] == wxT("float"))) // undocumented, but useful, alternative
|
||||
ctrl.type = NYQ_CTRL_REAL;
|
||||
else if (tokens[3] == wxT("int"))
|
||||
ctrl.type = NYQ_CTRL_INT;
|
||||
else
|
||||
if (mFileName.GetFullPath().IsEmpty())
|
||||
{
|
||||
wxString str;
|
||||
str.Printf(_("Bad Nyquist 'control' type specification: '%s' in plugin file '%s'.\nControl not created."),
|
||||
tokens[3].c_str(), mFileName.GetFullPath().c_str());
|
||||
|
||||
// Too disturbing to show alert before Audacity frame is up.
|
||||
// wxMessageBox(str, wxT("Nyquist Warning"), wxOK | wxICON_EXCLAMATION);
|
||||
|
||||
// Note that the AudacityApp's mLogger has not yet been created,
|
||||
// so this brings up an alert box, but after the Audacity frame is up.
|
||||
wxLogWarning(str);
|
||||
return;
|
||||
return wxT("nyquist prompt");
|
||||
}
|
||||
|
||||
ctrl.lowStr = tokens[6];
|
||||
ctrl.highStr = tokens[7];
|
||||
}
|
||||
return mFileName.GetFullPath();
|
||||
}
|
||||
|
||||
ctrl.val = UNINITIALIZED_CONTROL;
|
||||
wxString EffectNyquist::GetName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
if( mPresetNames.Index( ctrl.var ) == wxNOT_FOUND )
|
||||
wxString EffectNyquist::GetVendor()
|
||||
{
|
||||
if (GetID() == wxT("nyquist prompt"))
|
||||
{
|
||||
mControls.Add(ctrl);
|
||||
}
|
||||
return wxT("Audacity");
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("categories")) {
|
||||
for (size_t i = 1; i < tokens.GetCount(); ++i) {
|
||||
mCategories.Add(tokens[i]);
|
||||
}
|
||||
}
|
||||
return mAuthor;
|
||||
}
|
||||
|
||||
void EffectNyquist::ParseFile()
|
||||
wxString EffectNyquist::GetVersion()
|
||||
{
|
||||
wxTextFile f(mFileName.GetFullPath());
|
||||
if (!f.Open())
|
||||
return;
|
||||
|
||||
mCmd = wxT("");
|
||||
SetEffectFlags(PROCESS_EFFECT | PLUGIN_EFFECT);
|
||||
mOK = false;
|
||||
mEnablePreview = false;
|
||||
mIsSal = false;
|
||||
mControls.Clear();
|
||||
mDebug = false;
|
||||
|
||||
int i;
|
||||
int len = f.GetLineCount();
|
||||
wxString line;
|
||||
for (i = 0; i < len; i++) {
|
||||
line = f[i];
|
||||
if (line.Length() > 1 && line[0] == wxT(';')) {
|
||||
Parse(line);
|
||||
}
|
||||
// preserve comments so that SAL effects compile with proper line numbers
|
||||
mCmd += line + wxT("\n");
|
||||
}
|
||||
return wxT("N/A");
|
||||
}
|
||||
|
||||
void EffectNyquist::SetCommand(wxString cmd)
|
||||
wxString EffectNyquist::GetDescription()
|
||||
{
|
||||
mExternal = true;
|
||||
mInteractive = false;
|
||||
mCmd = wxT("");
|
||||
SetEffectFlags(INSERT_EFFECT | HIDDEN_EFFECT);
|
||||
mOK = false;
|
||||
mIsSal = false;
|
||||
mControls.Clear();
|
||||
|
||||
wxStringTokenizer lines(cmd, wxT("\n"));
|
||||
while (lines.HasMoreTokens()) {
|
||||
wxString line = lines.GetNextToken();
|
||||
|
||||
if (line.Length() > 1 && line[0] == wxT(';')) {
|
||||
Parse(line);
|
||||
}
|
||||
else {
|
||||
mCmd += line + wxT("\n");
|
||||
}
|
||||
}
|
||||
return mCopyright;
|
||||
}
|
||||
|
||||
bool EffectNyquist::SetXlispPath()
|
||||
// ============================================================================
|
||||
// EffectIdentInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
EffectType EffectNyquist::GetType()
|
||||
{
|
||||
wxString fname;
|
||||
|
||||
fname = mXlispPath + wxFILE_SEP_PATH + wxT("nyinit.lsp");
|
||||
if (!(::wxFileExists(fname))) {
|
||||
mXlispPath = wxT("");
|
||||
}
|
||||
|
||||
if (mXlispPath == wxT("")) {
|
||||
wxArrayString audacityPathList = wxGetApp().audacityPathList;
|
||||
wxArrayString pathList;
|
||||
wxArrayString files;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < audacityPathList.GetCount(); i++) {
|
||||
wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("nyquist"),
|
||||
pathList);
|
||||
}
|
||||
|
||||
wxGetApp().FindFilesInPathList(wxT("nyquist.lsp"), pathList, files);
|
||||
|
||||
if (files.GetCount() > 0) {
|
||||
mXlispPath = ::wxPathOnly(files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* set_xlisp_path doesn't handle fn_Str() in Unicode build. May or may not actually work. */
|
||||
nyx_set_xlisp_path(mXlispPath.mb_str());
|
||||
|
||||
fname = mXlispPath + wxFILE_SEP_PATH + wxT("nyinit.lsp");
|
||||
return ::wxFileExists(fname);
|
||||
// For now, relegate to Effect()
|
||||
return Effect::GetType();
|
||||
}
|
||||
|
||||
wxString EffectNyquist::GetFamily()
|
||||
{
|
||||
return NYQUISTEFFECTS_FAMILY;
|
||||
}
|
||||
|
||||
bool EffectNyquist::IsInteractive()
|
||||
{
|
||||
// For now, relegate to Effect()
|
||||
return Effect::IsInteractive();
|
||||
}
|
||||
|
||||
bool EffectNyquist::IsDefault()
|
||||
{
|
||||
if (GetID() == wxT("nyquist prompt"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EffectNyquist::IsLegacy()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EffectNyquist::SupportsRealtime()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EffectNyquist::SupportsAutomation()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Effect Implementation
|
||||
// ============================================================================
|
||||
|
||||
bool EffectNyquist::SupportsChains()
|
||||
{
|
||||
return (GetEffectFlags() & PROCESS_EFFECT) != 0;
|
||||
|
@ -1270,6 +1053,341 @@ bool EffectNyquist::ProcessOne()
|
|||
return true;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// EffectNyquist Implementation
|
||||
// ============================================================================
|
||||
|
||||
wxString EffectNyquist::NyquistToWxString(const char *nyqString)
|
||||
{
|
||||
wxString str(nyqString, wxConvUTF8);
|
||||
if (nyqString != NULL && nyqString[0] && str.IsEmpty()) {
|
||||
// invalid UTF-8 string, convert as Latin-1
|
||||
str = _("[Warning: Nyquist returned invalid UTF-8 string, converted here as Latin-1]");
|
||||
str += LAT1CTOWX(nyqString);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
void EffectNyquist::Break()
|
||||
{
|
||||
mBreak = true;
|
||||
}
|
||||
|
||||
void EffectNyquist::Continue()
|
||||
{
|
||||
mCont = true;
|
||||
}
|
||||
|
||||
void EffectNyquist::Stop()
|
||||
{
|
||||
mStop = true;
|
||||
}
|
||||
|
||||
wxString EffectNyquist::UnQuote(wxString s)
|
||||
{
|
||||
wxString out;
|
||||
int len = s.Length();
|
||||
|
||||
if (len >= 2 && s[0] == wxT('\"') && s[len - 1] == wxT('\"')) {
|
||||
return s.Mid(1, len - 2);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
double EffectNyquist::GetCtrlValue(wxString s)
|
||||
{
|
||||
if (s == wxT("rate")) {
|
||||
TrackListOfKindIterator iter(Track::Wave, mTracks);
|
||||
return ((WaveTrack *)iter.First())->GetRate();
|
||||
}
|
||||
|
||||
return Internat::CompatibleToDouble(s);
|
||||
}
|
||||
|
||||
void EffectNyquist::Parse(wxString line)
|
||||
{
|
||||
wxArrayString tokens;
|
||||
|
||||
int i;
|
||||
int len = line.Length();
|
||||
bool sl = false;
|
||||
bool q = false;
|
||||
wxString tok = wxT("");
|
||||
|
||||
for (i = 1; i < len; i++) {
|
||||
wxChar c = line[i];
|
||||
|
||||
if (c == wxT('\\')) {
|
||||
sl = true;
|
||||
}
|
||||
else if (c == wxT('"')) {
|
||||
q = !q;
|
||||
}
|
||||
else {
|
||||
if ((!q && !sl && c == wxT(' ')) || c == wxT('\t')) {
|
||||
tokens.Add(tok);
|
||||
tok = wxT("");
|
||||
}
|
||||
else if (sl && c == wxT('n')) {
|
||||
tok += wxT('\n');
|
||||
}
|
||||
else {
|
||||
tok += c;
|
||||
}
|
||||
|
||||
sl = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (tok != wxT("")) {
|
||||
tokens.Add(tok);
|
||||
}
|
||||
|
||||
len = tokens.GetCount();
|
||||
if (len < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len == 2 && tokens[0] == wxT("nyquist") && tokens[1] == wxT("plug-in")) {
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("type")) {
|
||||
if (tokens[1] == wxT("process")) {
|
||||
SetEffectFlags(PROCESS_EFFECT | PLUGIN_EFFECT);
|
||||
}
|
||||
else if (tokens[1] == wxT("generate")) {
|
||||
SetEffectFlags(INSERT_EFFECT | PLUGIN_EFFECT);
|
||||
}
|
||||
else if (tokens[1] == wxT("analyze")) {
|
||||
SetEffectFlags(ANALYZE_EFFECT | PLUGIN_EFFECT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len == 2 && tokens[0] == wxT("codetype")) {
|
||||
if (tokens[1] == wxT("lisp")) {
|
||||
mIsSal = false;
|
||||
}
|
||||
else if (tokens[1] == wxT("sal")) {
|
||||
mIsSal = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("debugflags")) {
|
||||
for (int i = 1; i < len; i++) {
|
||||
// Note: "trace" and "notrace" are overridden by "Debug" and "OK"
|
||||
// buttons if the plug-in generates a dialog box by using controls
|
||||
if (tokens[i] == wxT("trace")) {
|
||||
mDebug = true;
|
||||
}
|
||||
else if (tokens[i] == wxT("notrace")) {
|
||||
mDebug = false;
|
||||
}
|
||||
else if (tokens[i] == wxT("compiler")) {
|
||||
mCompiler = true;
|
||||
}
|
||||
else if (tokens[i] == wxT("nocompiler")) {
|
||||
mCompiler = false;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We support versions 1, 2 and 3
|
||||
// (Version 2 added support for string parameters.)
|
||||
// (Version 3 added support for choice parameters.)
|
||||
// (Version 4 added support for project/track/selection information.)
|
||||
if (len >= 2 && tokens[0] == wxT("version")) {
|
||||
long v;
|
||||
tokens[1].ToLong(&v);
|
||||
if (v < 1 && v > 4) {
|
||||
// This is an unsupported plug-in version
|
||||
mOK = false;
|
||||
return;
|
||||
}
|
||||
mVersion = (int) v;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("name")) {
|
||||
mName = UnQuote(tokens[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("action")) {
|
||||
mAction = UnQuote(tokens[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("info")) {
|
||||
mInfo = UnQuote(tokens[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("preview")) {
|
||||
if (tokens[1] == wxT("enabled") || tokens[1] == wxT("true")) {
|
||||
mEnablePreview = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("author")) {
|
||||
mAuthor = UnQuote(tokens[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("copyright")) {
|
||||
mCopyright = UnQuote(tokens[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= 6 && tokens[0] == wxT("control")) {
|
||||
NyqControl ctrl;
|
||||
|
||||
ctrl.var = tokens[1];
|
||||
ctrl.name = tokens[2];
|
||||
ctrl.label = tokens[4];
|
||||
ctrl.valStr = tokens[5];
|
||||
|
||||
if (tokens[3] == wxT("string")) {
|
||||
ctrl.type = NYQ_CTRL_STRING;
|
||||
}
|
||||
else if (tokens[ 3 ] == wxT("choice")) {
|
||||
ctrl.type = NYQ_CTRL_CHOICE;
|
||||
}
|
||||
else {
|
||||
if (len < 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((tokens[3] == wxT("real")) ||
|
||||
(tokens[3] == wxT("float"))) // undocumented, but useful, alternative
|
||||
ctrl.type = NYQ_CTRL_REAL;
|
||||
else if (tokens[3] == wxT("int"))
|
||||
ctrl.type = NYQ_CTRL_INT;
|
||||
else
|
||||
{
|
||||
wxString str;
|
||||
str.Printf(_("Bad Nyquist 'control' type specification: '%s' in plugin file '%s'.\nControl not created."),
|
||||
tokens[3].c_str(), mFileName.GetFullPath().c_str());
|
||||
|
||||
// Too disturbing to show alert before Audacity frame is up.
|
||||
// wxMessageBox(str, wxT("Nyquist Warning"), wxOK | wxICON_EXCLAMATION);
|
||||
|
||||
// Note that the AudacityApp's mLogger has not yet been created,
|
||||
// so this brings up an alert box, but after the Audacity frame is up.
|
||||
wxLogWarning(str);
|
||||
return;
|
||||
}
|
||||
|
||||
ctrl.lowStr = tokens[6];
|
||||
ctrl.highStr = tokens[7];
|
||||
}
|
||||
|
||||
ctrl.val = UNINITIALIZED_CONTROL;
|
||||
|
||||
if( mPresetNames.Index( ctrl.var ) == wxNOT_FOUND )
|
||||
{
|
||||
mControls.Add(ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("categories")) {
|
||||
for (size_t i = 1; i < tokens.GetCount(); ++i) {
|
||||
mCategories.Add(tokens[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectNyquist::ParseFile()
|
||||
{
|
||||
wxTextFile f(mFileName.GetFullPath());
|
||||
if (!f.Open())
|
||||
return;
|
||||
|
||||
mCmd = wxT("");
|
||||
SetEffectFlags(PROCESS_EFFECT | PLUGIN_EFFECT);
|
||||
mOK = false;
|
||||
mEnablePreview = false;
|
||||
mIsSal = false;
|
||||
mControls.Clear();
|
||||
mDebug = false;
|
||||
|
||||
int i;
|
||||
int len = f.GetLineCount();
|
||||
wxString line;
|
||||
for (i = 0; i < len; i++) {
|
||||
line = f[i];
|
||||
if (line.Length() > 1 && line[0] == wxT(';')) {
|
||||
Parse(line);
|
||||
}
|
||||
// preserve comments so that SAL effects compile with proper line numbers
|
||||
mCmd += line + wxT("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EffectNyquist::SetCommand(wxString cmd)
|
||||
{
|
||||
mExternal = true;
|
||||
mInteractive = false;
|
||||
mCmd = wxT("");
|
||||
SetEffectFlags(INSERT_EFFECT | HIDDEN_EFFECT);
|
||||
mOK = false;
|
||||
mIsSal = false;
|
||||
mControls.Clear();
|
||||
|
||||
wxStringTokenizer lines(cmd, wxT("\n"));
|
||||
while (lines.HasMoreTokens()) {
|
||||
wxString line = lines.GetNextToken();
|
||||
|
||||
if (line.Length() > 1 && line[0] == wxT(';')) {
|
||||
Parse(line);
|
||||
}
|
||||
else {
|
||||
mCmd += line + wxT("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectNyquist::SetXlispPath()
|
||||
{
|
||||
wxString fname;
|
||||
|
||||
fname = mXlispPath + wxFILE_SEP_PATH + wxT("nyinit.lsp");
|
||||
if (!(::wxFileExists(fname))) {
|
||||
mXlispPath = wxT("");
|
||||
}
|
||||
|
||||
if (mXlispPath == wxT("")) {
|
||||
wxArrayString audacityPathList = wxGetApp().audacityPathList;
|
||||
wxArrayString pathList;
|
||||
wxArrayString files;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < audacityPathList.GetCount(); i++) {
|
||||
wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("nyquist"),
|
||||
pathList);
|
||||
}
|
||||
|
||||
wxGetApp().FindFilesInPathList(wxT("nyquist.lsp"), pathList, files);
|
||||
|
||||
if (files.GetCount() > 0) {
|
||||
mXlispPath = ::wxPathOnly(files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* set_xlisp_path doesn't handle fn_Str() in Unicode build. May or may not actually work. */
|
||||
nyx_set_xlisp_path(mXlispPath.mb_str());
|
||||
|
||||
fname = mXlispPath + wxFILE_SEP_PATH + wxT("nyinit.lsp");
|
||||
return ::wxFileExists(fname);
|
||||
}
|
||||
|
||||
int EffectNyquist::StaticGetCallback(float *buffer, int channel,
|
||||
long start, long len, long totlen,
|
||||
void *userdata)
|
||||
|
@ -1427,7 +1545,11 @@ wxArrayString EffectNyquist::GetNyquistSearchPath()
|
|||
return pathList;
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// NyquistDialog
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define ID_NYQ_SLIDER 2000
|
||||
#define ID_NYQ_TEXT 3000
|
||||
|
@ -1584,6 +1706,10 @@ NyquistDialog::NyquistDialog(wxWindow * parent, wxWindowID id,
|
|||
mainSizer->SetSizeHints(this);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// NyquistDialog implementation
|
||||
// ============================================================================
|
||||
|
||||
void NyquistDialog::OnSlider(wxCommandEvent & /* event */)
|
||||
{
|
||||
if (mInHandler) {
|
||||
|
@ -1715,7 +1841,12 @@ void NyquistDialog::OnPreview(wxCommandEvent & /* event */)
|
|||
mEffect->Preview();
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// NyquistInputDialog
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define ID_VERSION 1001
|
||||
|
||||
BEGIN_EVENT_TABLE(NyquistInputDialog, wxDialog)
|
||||
|
@ -1770,6 +1901,10 @@ NyquistInputDialog::NyquistInputDialog(wxWindow * parent, wxWindowID id,
|
|||
mCommandText->SetFocus();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// NyquistInputDialog implementation
|
||||
// ============================================================================
|
||||
|
||||
wxString NyquistInputDialog::GetCommand()
|
||||
{
|
||||
return mCommandText->GetValue();
|
||||
|
@ -1805,7 +1940,11 @@ void NyquistInputDialog::OnPreview(wxCommandEvent & /* event */)
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// NyquistOutputDialog
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE(NyquistOutputDialog, wxDialog)
|
||||
|
@ -1849,6 +1988,10 @@ NyquistOutputDialog::NyquistOutputDialog(wxWindow * parent, wxWindowID id,
|
|||
mainSizer->SetSizeHints(this);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// NyquistOutputDialog implementation
|
||||
// ============================================================================
|
||||
|
||||
void NyquistOutputDialog::OnOk(wxCommandEvent & /* event */)
|
||||
{
|
||||
EndModal(wxID_OK);
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#define NYQUISTEFFECTS_VERSION wxT("1.0.0.0");
|
||||
#define NYQUISTEFFECTS_FAMILY L"Nyquist"
|
||||
|
||||
class NyqControl
|
||||
{
|
||||
public:
|
||||
|
@ -60,18 +63,26 @@ class AUDACITY_DLL_API EffectNyquist:public Effect
|
|||
EffectNyquist(wxString fName);
|
||||
virtual ~EffectNyquist();
|
||||
|
||||
bool SetXlispPath();
|
||||
// IdentInterface implementation
|
||||
|
||||
bool LoadedNyFile() {
|
||||
return mOK;
|
||||
}
|
||||
virtual PluginID GetID();
|
||||
virtual wxString GetPath();
|
||||
virtual wxString GetName();
|
||||
virtual wxString GetVendor();
|
||||
virtual wxString GetVersion();
|
||||
virtual wxString GetDescription();
|
||||
|
||||
void Continue();
|
||||
void Break();
|
||||
void Stop();
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
void SetCommand(wxString cmd);
|
||||
wxString GetOutput();
|
||||
virtual EffectType GetType();
|
||||
virtual wxString GetFamily();
|
||||
virtual bool IsInteractive();
|
||||
virtual bool IsDefault();
|
||||
virtual bool IsLegacy();
|
||||
virtual bool SupportsRealtime();
|
||||
virtual bool SupportsAutomation();
|
||||
|
||||
// Effect implementation
|
||||
|
||||
/** Get the name of the effect (taken from the script that is loaded). Note
|
||||
* that this name is currently not translated because the translations system
|
||||
|
@ -121,6 +132,22 @@ class AUDACITY_DLL_API EffectNyquist:public Effect
|
|||
virtual bool SupportsChains();
|
||||
virtual bool TransferParameters( Shuttle & shuttle );
|
||||
|
||||
// EffectNyquist implementation
|
||||
|
||||
bool SetXlispPath();
|
||||
|
||||
bool LoadedNyFile() {
|
||||
return mOK;
|
||||
}
|
||||
|
||||
void Continue();
|
||||
void Break();
|
||||
void Stop();
|
||||
|
||||
void SetCommand(wxString cmd);
|
||||
wxString GetOutput();
|
||||
|
||||
|
||||
static wxArrayString GetNyquistSearchPath();
|
||||
|
||||
private:
|
||||
|
@ -175,6 +202,8 @@ class AUDACITY_DLL_API EffectNyquist:public Effect
|
|||
wxString mName; ///< Name of the Effect
|
||||
wxString mAction;
|
||||
wxString mInfo;
|
||||
wxString mAuthor;
|
||||
wxString mCopyright;
|
||||
bool mEnablePreview;
|
||||
bool mDebug;
|
||||
std::string mDebugOutput;
|
||||
|
|
|
@ -19,60 +19,100 @@
|
|||
using namespace Vamp;
|
||||
using namespace Vamp::HostExt;
|
||||
|
||||
#ifdef EFFECT_CATEGORIES
|
||||
|
||||
static std::map<wxString, wxString> gCategoryMap;
|
||||
|
||||
#define VAMP(S) wxT("http://audacityteam.org/namespace#VampCategories") wxT(S)
|
||||
#define ATEAM(S) wxT("http://audacityteam.org/namespace#") wxT(S)
|
||||
|
||||
/** Initialise the data structure that maps locally generated URI strings to
|
||||
internal ones. */
|
||||
static void InitCategoryMap()
|
||||
// ============================================================================
|
||||
// Module registration entry point
|
||||
//
|
||||
// This is the symbol that Audacity looks for when the module is built as a
|
||||
// dynamic library.
|
||||
//
|
||||
// When the module is builtin to Audacity, we use the same function, but it is
|
||||
// declared static so as not to clash with other builtin modules.
|
||||
// ============================================================================
|
||||
DECLARE_MODULE_ENTRY(AudacityModule)
|
||||
{
|
||||
gCategoryMap[VAMP("/Time")] = ATEAM("TimeAnalyser");
|
||||
gCategoryMap[VAMP("/Time/Onsets")] = ATEAM("OnsetDetector");
|
||||
// Create and register the importer
|
||||
return new VampEffectsModule(moduleManager, path);
|
||||
}
|
||||
|
||||
/** Map the generated VAMP category URI to the internal ones. */
|
||||
static wxString MapCategoryUri(const wxString& uri)
|
||||
{
|
||||
std::map<wxString, wxString>::const_iterator iter;
|
||||
iter = gCategoryMap.find(uri);
|
||||
if (iter != gCategoryMap.end())
|
||||
return iter->second;
|
||||
return uri;
|
||||
}
|
||||
// ============================================================================
|
||||
// Register this as a builtin module
|
||||
// ============================================================================
|
||||
DECLARE_BUILTIN_MODULE(VampsEffectBuiltin);
|
||||
|
||||
/** Generate category URIs for all levels in a VAMP category hierarchy,
|
||||
add them to the EffectManager and return the most detailed one. */
|
||||
static wxString VampHierarchyToUri(const PluginLoader::PluginCategoryHierarchy& h)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// VampEffectsModule
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VampEffectsModule::VampEffectsModule(ModuleManagerInterface *moduleManager,
|
||||
const wxString *path)
|
||||
{
|
||||
// Else, generate URIs and add them to the EffectManager
|
||||
EffectManager& em = EffectManager::Get();
|
||||
wxString vampCategory =
|
||||
wxString::FromAscii("http://audacityteam.org/namespace#VampCategories");
|
||||
EffectCategory* parent =
|
||||
em.LookupCategory(wxT("http://lv2plug.in/ns/lv2core#AnalyserPlugin"));
|
||||
if (parent) {
|
||||
for (size_t c = 0; c < h.size(); ++c) {
|
||||
vampCategory += wxT("/");
|
||||
wxString catName = wxString::FromAscii(h[c].c_str());
|
||||
vampCategory += catName;
|
||||
EffectCategory* ec = em.AddCategory(MapCategoryUri(vampCategory),
|
||||
catName);
|
||||
em.AddCategoryParent(ec, parent);
|
||||
parent = ec;
|
||||
mModMan = moduleManager;
|
||||
if (path)
|
||||
{
|
||||
mPath = *path;
|
||||
}
|
||||
}
|
||||
return MapCategoryUri(vampCategory);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void LoadVampPlugins()
|
||||
VampEffectsModule::~VampEffectsModule()
|
||||
{
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// IdentInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
wxString VampEffectsModule::GetID()
|
||||
{
|
||||
// Can be anything, but this is a v4 UUID
|
||||
return wxT("33a86140-7310-4bdf-ad8e-a4af29079f61");
|
||||
}
|
||||
|
||||
wxString VampEffectsModule::GetPath()
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
wxString VampEffectsModule::GetName()
|
||||
{
|
||||
return _("Vamp Effects Module");
|
||||
}
|
||||
|
||||
wxString VampEffectsModule::GetVendor()
|
||||
{
|
||||
return _("The Audacity Team");
|
||||
}
|
||||
|
||||
wxString VampEffectsModule::GetVersion()
|
||||
{
|
||||
// This "may" be different if this were to be maintained as a separate DLL
|
||||
return VAMPEFFECTS_VERSION;
|
||||
}
|
||||
|
||||
wxString VampEffectsModule::GetDescription()
|
||||
{
|
||||
return _("Provides Vamp Effects support to Audacity");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ModuleInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
bool VampEffectsModule::Initialize()
|
||||
{
|
||||
// Nothing to do here
|
||||
return true;
|
||||
}
|
||||
|
||||
void VampEffectsModule::Terminate()
|
||||
{
|
||||
// Nothing to do here
|
||||
return;
|
||||
}
|
||||
|
||||
bool VampEffectsModule::AutoRegisterPlugins(PluginManagerInterface & pm)
|
||||
{
|
||||
#ifdef EFFECT_CATEGORIES
|
||||
InitCategoryMap();
|
||||
#endif
|
||||
|
@ -155,13 +195,115 @@ void LoadVampPlugins()
|
|||
#else
|
||||
VampEffect *effect = new VampEffect(*i, n, hasParameters, name);
|
||||
#endif
|
||||
em.RegisterEffect(effect);
|
||||
em.RegisterEffect(this, effect);
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
delete vp;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wxArrayString VampEffectsModule::FindPlugins(PluginManagerInterface & pm)
|
||||
{
|
||||
// Nothing to do here yet
|
||||
return wxArrayString();
|
||||
}
|
||||
|
||||
bool VampEffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxString & path)
|
||||
{
|
||||
// Nothing to do here yet
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VampEffectsModule::IsPluginValid(const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
Vamp::HostExt::PluginLoader *loader = Vamp::HostExt::PluginLoader::getInstance();
|
||||
Vamp::Plugin *plug = loader->loadPlugin(ID.ToUTF8().data(), 48000); // rate doesn't matter here
|
||||
|
||||
if (plug)
|
||||
{
|
||||
delete plug;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
IdentInterface *VampEffectsModule::CreateInstance(const PluginID & ID,
|
||||
const wxString & path)
|
||||
{
|
||||
// Nothing to do here yet since we are autoregistering (and creating legacy
|
||||
// effects anyway).
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void VampEffectsModule::DeleteInstance(IdentInterface *instance)
|
||||
{
|
||||
// Nothing to do here yet
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// VampEffectsModule implementation
|
||||
// ============================================================================
|
||||
|
||||
#ifdef EFFECT_CATEGORIES
|
||||
|
||||
static std::map<wxString, wxString> gCategoryMap;
|
||||
|
||||
#define VAMP(S) wxT("http://audacityteam.org/namespace#VampCategories") wxT(S)
|
||||
#define ATEAM(S) wxT("http://audacityteam.org/namespace#") wxT(S)
|
||||
|
||||
/** Initialise the data structure that maps locally generated URI strings to
|
||||
internal ones. */
|
||||
static void InitCategoryMap()
|
||||
{
|
||||
gCategoryMap[VAMP("/Time")] = ATEAM("TimeAnalyser");
|
||||
gCategoryMap[VAMP("/Time/Onsets")] = ATEAM("OnsetDetector");
|
||||
}
|
||||
|
||||
/** Map the generated VAMP category URI to the internal ones. */
|
||||
static wxString MapCategoryUri(const wxString& uri)
|
||||
{
|
||||
std::map<wxString, wxString>::const_iterator iter;
|
||||
iter = gCategoryMap.find(uri);
|
||||
if (iter != gCategoryMap.end())
|
||||
return iter->second;
|
||||
return uri;
|
||||
}
|
||||
|
||||
/** Generate category URIs for all levels in a VAMP category hierarchy,
|
||||
add them to the EffectManager and return the most detailed one. */
|
||||
static wxString VampHierarchyToUri(const PluginLoader::PluginCategoryHierarchy& h)
|
||||
{
|
||||
// Else, generate URIs and add them to the EffectManager
|
||||
EffectManager& em = EffectManager::Get();
|
||||
wxString vampCategory =
|
||||
wxString::FromAscii("http://audacityteam.org/namespace#VampCategories");
|
||||
EffectCategory* parent =
|
||||
em.LookupCategory(wxT("http://lv2plug.in/ns/lv2core#AnalyserPlugin"));
|
||||
if (parent) {
|
||||
for (size_t c = 0; c < h.size(); ++c) {
|
||||
vampCategory += wxT("/");
|
||||
wxString catName = wxString::FromAscii(h[c].c_str());
|
||||
vampCategory += catName;
|
||||
EffectCategory* ec = em.AddCategory(MapCategoryUri(vampCategory),
|
||||
catName);
|
||||
em.AddCategoryParent(ec, parent);
|
||||
parent = ec;
|
||||
}
|
||||
}
|
||||
return MapCategoryUri(vampCategory);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void LoadVampPlugins()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UnloadVampPlugins()
|
||||
|
|
|
@ -8,5 +8,48 @@
|
|||
|
||||
**********************************************************************/
|
||||
|
||||
void LoadVampPlugins();
|
||||
void UnloadVampPlugins();
|
||||
#include "audacity/ModuleInterface.h"
|
||||
#include "audacity/EffectInterface.h"
|
||||
#include "audacity/PluginInterface.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// VampEffectsModule
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class VampEffectsModule : public ModuleInterface
|
||||
{
|
||||
public:
|
||||
VampEffectsModule(ModuleManagerInterface *moduleManager, const wxString *path);
|
||||
virtual ~VampEffectsModule();
|
||||
|
||||
// IdentInterface implementatino
|
||||
|
||||
virtual wxString GetID();
|
||||
virtual wxString GetPath();
|
||||
virtual wxString GetName();
|
||||
virtual wxString GetVendor();
|
||||
virtual wxString GetVersion();
|
||||
virtual wxString GetDescription();
|
||||
|
||||
// ModuleInterface implementation
|
||||
|
||||
virtual bool Initialize();
|
||||
virtual void Terminate();
|
||||
|
||||
virtual bool AutoRegisterPlugins(PluginManagerInterface & pm);
|
||||
virtual wxArrayString FindPlugins(PluginManagerInterface & pm);
|
||||
virtual bool RegisterPlugin(PluginManagerInterface & pm, const wxString & path);
|
||||
|
||||
virtual bool IsPluginValid(const PluginID & ID, const wxString & path);
|
||||
|
||||
virtual IdentInterface *CreateInstance(const PluginID & ID, const wxString & path);
|
||||
virtual void DeleteInstance(IdentInterface *instance);
|
||||
|
||||
// VampEffectModule implementation
|
||||
|
||||
private:
|
||||
ModuleManagerInterface *mModMan;
|
||||
wxString mPath;
|
||||
};
|
||||
|
|
|
@ -33,6 +33,12 @@
|
|||
#include <wx/scrolwin.h>
|
||||
#include <wx/version.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// VampEffect
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VampEffect::VampEffect(Vamp::HostExt::PluginLoader::PluginKey key,
|
||||
int output,
|
||||
bool hasParameters,
|
||||
|
@ -46,6 +52,9 @@ VampEffect::VampEffect(Vamp::HostExt::PluginLoader::PluginKey key,
|
|||
mCategory(category),
|
||||
mPlugin(NULL)
|
||||
{
|
||||
Vamp::HostExt::PluginLoader *loader = Vamp::HostExt::PluginLoader::getInstance();
|
||||
mPlugin = loader->loadPlugin(mKey, 48000); // rate doesn't matter here
|
||||
|
||||
SetEffectFlags(PLUGIN_EFFECT | ANALYZE_EFFECT);
|
||||
}
|
||||
|
||||
|
@ -55,6 +64,82 @@ VampEffect::~VampEffect()
|
|||
mPlugin = NULL;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// IdentInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
wxString VampEffect::GetID()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
wxString VampEffect::GetPath()
|
||||
{
|
||||
Vamp::HostExt::PluginLoader *loader = Vamp::HostExt::PluginLoader::getInstance();
|
||||
return LAT1CTOWX(loader->getLibraryPathForPlugin(mKey).c_str());
|
||||
}
|
||||
|
||||
wxString VampEffect::GetName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
wxString VampEffect::GetVendor()
|
||||
{
|
||||
return LAT1CTOWX(mPlugin->getMaker().c_str());
|
||||
}
|
||||
|
||||
wxString VampEffect::GetVersion()
|
||||
{
|
||||
return wxString::Format(wxT("%d"), mPlugin->getPluginVersion());
|
||||
}
|
||||
|
||||
wxString VampEffect::GetDescription()
|
||||
{
|
||||
return LAT1CTOWX(mPlugin->getCopyright().c_str());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// EffectIdentInterface implementation
|
||||
// ============================================================================
|
||||
|
||||
EffectType VampEffect::GetType()
|
||||
{
|
||||
// For now, relegate to Effect()
|
||||
return Effect::GetType();
|
||||
}
|
||||
|
||||
wxString VampEffect::GetFamily()
|
||||
{
|
||||
return VAMPEFFECTS_FAMILY;
|
||||
}
|
||||
|
||||
bool VampEffect::IsInteractive()
|
||||
{
|
||||
// For now, relegate to Effect()
|
||||
return Effect::IsInteractive();
|
||||
}
|
||||
|
||||
bool VampEffect::IsDefault()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VampEffect::IsLegacy()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VampEffect::SupportsRealtime()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VampEffect::SupportsAutomation()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
wxString VampEffect::GetEffectName()
|
||||
{
|
||||
if (mHasParameters) {
|
||||
|
|
|
@ -24,7 +24,8 @@ class wxComboBox;
|
|||
|
||||
#include <vamp-hostsdk/PluginLoader.h>
|
||||
|
||||
void LoadVampPlugins();
|
||||
#define VAMPEFFECTS_VERSION wxT("1.0.0.0");
|
||||
#define VAMPEFFECTS_FAMILY L"Vamp"
|
||||
|
||||
class VampEffect : public Effect {
|
||||
|
||||
|
@ -37,6 +38,27 @@ class VampEffect : public Effect {
|
|||
wxString category = wxString());
|
||||
virtual ~VampEffect();
|
||||
|
||||
// IdentInterface implementation
|
||||
|
||||
virtual PluginID GetID();
|
||||
virtual wxString GetPath();
|
||||
virtual wxString GetName();
|
||||
virtual wxString GetVendor();
|
||||
virtual wxString GetVersion();
|
||||
virtual wxString GetDescription();
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
virtual EffectType GetType();
|
||||
virtual wxString GetFamily();
|
||||
virtual bool IsInteractive();
|
||||
virtual bool IsDefault();
|
||||
virtual bool IsLegacy();
|
||||
virtual bool SupportsRealtime();
|
||||
virtual bool SupportsAutomation();
|
||||
|
||||
// Effect implementation
|
||||
|
||||
virtual wxString GetEffectName();
|
||||
|
||||
virtual std::set<wxString> GetEffectCategories();
|
||||
|
|
|
@ -92,8 +92,6 @@ void EffectsPrefs::PopulateOrExchange(ShuttleGui & S)
|
|||
wxT("/VST/Enable"),
|
||||
true);
|
||||
#endif
|
||||
|
||||
S.AddFixedText(_("Restart Audacity to apply changes."));
|
||||
}
|
||||
S.EndStatic();
|
||||
|
||||
|
@ -106,13 +104,15 @@ void EffectsPrefs::PopulateOrExchange(ShuttleGui & S)
|
|||
|
||||
visualgroups.Add(_("Sorted by Effect Name"));
|
||||
visualgroups.Add(_("Sorted by Publisher and Effect Name"));
|
||||
visualgroups.Add(_("Sorted by Type and Effect Name"));
|
||||
visualgroups.Add(_("Grouped by Publisher"));
|
||||
visualgroups.Add(_("Grouped by Type (Ladspa, VST, etc.)"));
|
||||
visualgroups.Add(_("Grouped by Type"));
|
||||
|
||||
prefsgroups.Add(wxT("name"));
|
||||
prefsgroups.Add(wxT("publisher:name"));
|
||||
prefsgroups.Add(wxT("publisher"));
|
||||
prefsgroups.Add(wxT("family"));
|
||||
prefsgroups.Add(wxT("sortby:name"));
|
||||
prefsgroups.Add(wxT("sortby:publisher:name"));
|
||||
prefsgroups.Add(wxT("sortby:type:name"));
|
||||
prefsgroups.Add(wxT("groupby:publisher"));
|
||||
prefsgroups.Add(wxT("groupby:type"));
|
||||
|
||||
wxChoice *c = S.TieChoice(_("Effects in menus are:"),
|
||||
wxT("/Effects/GroupBy"),
|
||||
|
@ -158,43 +158,10 @@ void EffectsPrefs::PopulateOrExchange(ShuttleGui & S)
|
|||
#endif
|
||||
}
|
||||
|
||||
void EffectsPrefs::SetState(const wxString & family, const wxString & key)
|
||||
{
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
bool state = gPrefs->Read(wxT("/Nyquist/Enable"), true);
|
||||
|
||||
const PluginDescriptor *plug = pm.GetFirstPluginForEffectFamily(family);
|
||||
while (plug)
|
||||
{
|
||||
pm.EnablePlugin(plug->GetID(), state);
|
||||
plug = pm.GetNextPluginForEffectFamily(family);
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectsPrefs::Apply()
|
||||
{
|
||||
ShuttleGui S(this, eIsSavingToPrefs);
|
||||
PopulateOrExchange(S);
|
||||
|
||||
#ifdef USE_NYQUIST
|
||||
SetState(wxT("Nyquist"), wxT("/Nyquist/Enable"));
|
||||
#endif
|
||||
|
||||
#ifdef USE_LADSPA
|
||||
SetState(wxT("Ladspa"), wxT("/Ladspa/Enable"));
|
||||
#endif
|
||||
|
||||
#ifdef USE_LV2
|
||||
SetState(wxT("LV2"), wxT("/LV2/Enable"));
|
||||
#endif
|
||||
|
||||
#ifdef USE_AUDIO_UNITS
|
||||
SetState(wxT("AudioUnit"), wxT("/AudioUnits/Enable"));
|
||||
#endif
|
||||
|
||||
#ifdef USE_VAMP
|
||||
SetState(wxT("VAMP"), wxT("/VAMP/Enable"));
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ class EffectsPrefs:public PrefsPanel
|
|||
private:
|
||||
void Populate();
|
||||
void PopulateOrExchange(ShuttleGui & S);
|
||||
void SetState(const wxString & family, const wxString & key);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -784,6 +784,7 @@
|
|||
<copy Include="..\..\..\plug-ins\clipfix.ny" />
|
||||
<copy Include="..\..\..\plug-ins\crossfadein.ny" />
|
||||
<copy Include="..\..\..\plug-ins\crossfadeout.ny" />
|
||||
<copy Include="..\..\..\plug-ins\crossfadetracks.ny" />
|
||||
<copy Include="..\..\..\plug-ins\delay.ny" />
|
||||
<copy Include="..\..\..\plug-ins\equalabel.ny" />
|
||||
<copy Include="..\..\..\plug-ins\highpass.ny" />
|
||||
|
@ -794,6 +795,9 @@
|
|||
<copy Include="..\..\..\plug-ins\sample-data-export.ny" />
|
||||
<copy Include="..\..\..\plug-ins\SilenceMarker.ny" />
|
||||
<copy Include="..\..\..\plug-ins\SoundFinder.ny" />
|
||||
<copy Include="..\..\..\plug-ins\SpectralEditMulti.ny" />
|
||||
<copy Include="..\..\..\plug-ins\SpectralEditParametricEQ.ny" />
|
||||
<copy Include="..\..\..\plug-ins\SpectralEditShelves.ny" />
|
||||
<copy Include="..\..\..\plug-ins\StudioFadeOut.ny" />
|
||||
<copy Include="..\..\..\plug-ins\tremolo.ny" />
|
||||
<copy Include="..\..\..\plug-ins\vocalremover.ny" />
|
||||
|
|
|
@ -1852,5 +1852,17 @@
|
|||
<copy Include="..\..\..\plug-ins\vocoder.ny">
|
||||
<Filter>plug-ins</Filter>
|
||||
</copy>
|
||||
<copy Include="..\..\..\plug-ins\crossfadetracks.ny">
|
||||
<Filter>plug-ins</Filter>
|
||||
</copy>
|
||||
<copy Include="..\..\..\plug-ins\SpectralEditMulti.ny">
|
||||
<Filter>plug-ins</Filter>
|
||||
</copy>
|
||||
<copy Include="..\..\..\plug-ins\SpectralEditParametricEQ.ny">
|
||||
<Filter>plug-ins</Filter>
|
||||
</copy>
|
||||
<copy Include="..\..\..\plug-ins\SpectralEditShelves.ny">
|
||||
<Filter>plug-ins</Filter>
|
||||
</copy>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue