One more round of effects changes.

The big thing is the common efffects UI.  Right now Ladspa and VST
have been converted to use it and Audiounits will be next.  It makes
everything nice and consistent while reducing the clutter in the
dialog.

Other goodies are:

Ladspa effects now show output controls when supplied by the effect
Ladspa effects now work fine as Analyze type effects
Ladspa now has user presets
VST effects dialog is now less cluttered...leaving more room for the effect
Ladspa and VST effects now share a common UI
Ladspa and VST effects are now usable in chains
Ladspa and VST effects now handle user presets the same way
Currently active effects settings automatically saved and reloaded
Can now do numeric range checking on input fields.

And, as always, plenty of critter squashing.
This commit is contained in:
lllucius 2014-11-14 03:03:17 +00:00
parent 34b9133031
commit ad92e8c4bf
33 changed files with 5381 additions and 4164 deletions

View File

@ -8,6 +8,14 @@ dist_doc_DATA = LICENSE.txt README.txt
dist_pkgdata_DATA = presets/EQDefaultCurves.xml
nobase_dist_pkgdata_DATA = \
include/audacity/ConfigInterface.h \
include/audacity/EffectAutomationParameters.h \
include/audacity/EffectInterface.h \
include/audacity/IdentInterface.h \
include/audacity/ImporterInterface.h \
include/audacity/ModuleInterface.h \
include/audacity/PluginInterface.h \
include/audacity/Types.h \
nyquist/bug.lsp \
nyquist/dspprims.lsp \
nyquist/envelopes.lsp \

View File

@ -488,6 +488,14 @@ bin_SCRIPTS = audacity$(EXEEXT)
dist_doc_DATA = LICENSE.txt README.txt
dist_pkgdata_DATA = presets/EQDefaultCurves.xml
nobase_dist_pkgdata_DATA = \
include/audacity/ConfigInterface.h \
include/audacity/EffectAutomationParameters.h \
include/audacity/EffectInterface.h \
include/audacity/IdentInterface.h \
include/audacity/ImporterInterface.h \
include/audacity/ModuleInterface.h \
include/audacity/PluginInterface.h \
include/audacity/Types.h \
nyquist/bug.lsp \
nyquist/dspprims.lsp \
nyquist/envelopes.lsp \

View File

@ -49,6 +49,8 @@ class AUDACITY_DLL_API ConfigClientInterface
public:
virtual ~ConfigClientInterface() {};
virtual bool GetSharedConfigSubgroups(const wxString & group, wxArrayString & subgroups) = 0;
virtual bool GetSharedConfig(const wxString & group, const wxString & key, wxString & value, const wxString & defval) = 0;
virtual bool GetSharedConfig(const wxString & group, const wxString & key, int & value, int defval) = 0;
virtual bool GetSharedConfig(const wxString & group, const wxString & key, bool & value, bool defval) = 0;
@ -63,6 +65,11 @@ public:
virtual bool SetSharedConfig(const wxString & group, const wxString & key, const double & value) = 0;
virtual bool SetSharedConfig(const wxString & group, const wxString & key, const sampleCount & value) = 0;
virtual bool RemoveSharedConfigSubgroup(const wxString & group) = 0;
virtual bool RemoveSharedConfig(const wxString & group, const wxString & key) = 0;
virtual bool GetPrivateConfigSubgroups(const wxString & group, wxArrayString & subgroups) = 0;
virtual bool GetPrivateConfig(const wxString & group, const wxString & key, wxString & value, const wxString & defval) = 0;
virtual bool GetPrivateConfig(const wxString & group, const wxString & key, int & value, int defval) = 0;
virtual bool GetPrivateConfig(const wxString & group, const wxString & key, bool & value, bool defval) = 0;
@ -76,6 +83,9 @@ public:
virtual bool SetPrivateConfig(const wxString & group, const wxString & key, const float & value) = 0;
virtual bool SetPrivateConfig(const wxString & group, const wxString & key, const double & value) = 0;
virtual bool SetPrivateConfig(const wxString & group, const wxString & key, const sampleCount & value) = 0;
virtual bool RemovePrivateConfigSubgroup(const wxString & group) = 0;
virtual bool RemovePrivateConfig(const wxString & group, const wxString & key) = 0;
};
class ConfigHostInterface

View File

@ -0,0 +1,178 @@
/**********************************************************************
Audacity: A Digital Audio Editor
EffectAutomationParameters.h
Leland Lucius
Copyright (c) 2014, Audacity Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
**********************************************************************/
#ifndef __AUDACITY_EFFECTAUTOMATIONPARAMETERS_H__
#define __AUDACITY_EFFECTAUTOMATIONPARAMETERS_H__
#include <wx/cmdline.h>
#include <wx/fileconf.h>
class EffectAutomationParameters : public wxFileConfig
{
public:
EffectAutomationParameters()
: wxFileConfig(wxEmptyString,
wxEmptyString,
wxEmptyString,
wxEmptyString,
0)
{
}
virtual ~EffectAutomationParameters()
{
}
virtual bool DoReadString(const wxString & key, wxString *pStr) const
{
return wxFileConfig::DoReadString(NormalizeName(key), pStr);
}
virtual bool DoReadLong(const wxString & key, long *pl) const
{
return wxFileConfig::DoReadLong(NormalizeName(key), pl);
}
virtual bool DoWriteString(const wxString & key, const wxString & szValue)
{
return wxFileConfig::DoWriteString(NormalizeName(key), szValue);
}
virtual bool DoWriteLong(const wxString & key, long lValue)
{
return wxFileConfig::DoWriteLong(NormalizeName(key), lValue);
}
bool ReadEnum(const wxString & key, int *pi, const wxArrayString & choices) const
{
wxString s;
if (wxFileConfig::Read(key, &s))
{
int i = choices.Index(s);
if (i != wxNOT_FOUND)
{
*pi = i;
return true;
}
}
return false;
}
bool ReadEnum(const wxString & key, int *pi, int defVal, const wxArrayString & choices) const
{
if (!ReadEnum(key, pi, choices))
{
*pi = defVal;
}
return true;
}
bool WriteEnum(const wxString & key, int value, const wxArrayString & choices)
{
if (value < 0 || value >= (int) choices.GetCount())
{
return false;
}
return wxFileConfig::Write(key, choices[value]);
}
wxString NormalizeName(const wxString & name) const
{
wxString cleaned = name;
cleaned.Trim(true).Trim(false);
cleaned.Replace(wxT(" "), wxT("_"));
cleaned.Replace(wxT("/"), wxT("_"));
cleaned.Replace(wxT("\\"), wxT("_"));
cleaned.Replace(wxT(":"), wxT("_"));
return cleaned;
}
bool GetParameters(wxString & parms)
{
wxFileConfig::SetPath(wxT("/"));
wxString str;
wxString key;
long ndx = 0;
bool res = wxFileConfig::GetFirstEntry(key, ndx);
while (res)
{
wxString val;
if (!wxFileConfig::Read(key, &val))
{
return false;
}
str += key + wxT("=\"") + val + wxT("\" ");
res = wxFileConfig::GetNextEntry(key, ndx);
}
str.Trim();
parms = str;
return true;
}
bool SetParameters(const wxString & parms)
{
wxFileConfig::SetPath(wxT("/"));
wxArrayString parsed = wxCmdLineParser::ConvertStringToArgs(parms);
for (size_t i = 0, cnt = parsed.GetCount(); i < cnt; i++)
{
wxString key = parsed[i].BeforeFirst(wxT('=')).Trim(false).Trim(true);
wxString val = parsed[i].AfterFirst(wxT('=')).Trim(false).Trim(true);
if (!wxFileConfig::Write(key, val))
{
return false;
}
}
}
};
#endif

View File

@ -42,11 +42,12 @@
#ifndef __AUDACITY_EFFECTINTERFACE_H__
#define __AUDACITY_EFFECTINTERFACE_H__
#include <vector>
#include "audacity/Types.h"
#include "audacity/IdentInterface.h"
#include "audacity/ConfigInterface.h"
#include "audacity/EffectAutomationParameters.h"
#include <wx/dialog.h>
typedef enum EffectType
{
@ -65,7 +66,7 @@ public:
virtual wxString GetFamily() = 0;
// These should move to the "EffectClientInterface" class once all
// effects have bee converted.
// effects have been converted.
virtual bool IsInteractive() = 0;
// I don't really like this, but couldn't think of a better way to force the
@ -76,13 +77,18 @@ public:
// interface.
virtual bool IsLegacy() = 0;
// Whether the effect supports realtime processing (while audio is playing).
virtual bool IsRealtimeCapable() = 0;
// Whether the effect supports realtime previewing (while audio is playing).
virtual bool SupportsRealtime() = 0;
// Can the effect be used without the UI.
virtual bool SupportsAutomation() = 0;
};
class AUDACITY_DLL_API EffectHostInterface :
public EffectIdentInterface,
public ConfigClientInterface
class EffectUIHostInterface;
class EffectUIClientInterface;
class AUDACITY_DLL_API EffectHostInterface : public EffectIdentInterface,
public ConfigClientInterface
{
public:
virtual ~EffectHostInterface() {};
@ -92,19 +98,22 @@ public:
virtual bool Apply() = 0;
virtual void Preview() = 0;
};
typedef float * pfloat;
typedef std::vector<pfloat> pvec;
//
virtual wxDialog *CreateUI(wxWindow *parent, EffectUIClientInterface *client) = 0;
// Preset handling
virtual wxString GetUserPresetsGroup(const wxString & name) = 0;
virtual wxString GetCurrentSettingsGroup() = 0;
virtual wxString GetFactoryDefaultsGroup() = 0;
};
class EffectClientInterface : public EffectIdentInterface
{
public:
virtual ~EffectClientInterface() {};
virtual void SetHost(EffectHostInterface *host) = 0;
virtual bool Startup() = 0;
virtual bool Shutdown() = 0;
virtual bool SetHost(EffectHostInterface *host) = 0;
virtual int GetAudioInCount() = 0;
virtual int GetAudioOutCount() = 0;
@ -130,7 +139,43 @@ public:
virtual bool RealtimeResume() = 0;
virtual sampleCount RealtimeProcess(int group, float **inbuf, float **outbuf, sampleCount size) = 0;
virtual bool ShowInterface(void *parent) = 0;
virtual bool ShowInterface(wxWindow *parent, bool forceModal = false) = 0;
virtual bool GetAutomationParameters(EffectAutomationParameters & parms) = 0;
virtual bool SetAutomationParameters(EffectAutomationParameters & parms) = 0;
};
class EffectUIHostInterface
{
public:
virtual ~EffectUIHostInterface() {};
// virtual wxScrolledWindow *GetScrollableClientArea();
// virtual wxScrolledWindow *GetStaticClientArea();
};
class EffectUIClientInterface
{
public:
virtual ~EffectUIClientInterface() {};
virtual void SetUIHost(EffectUIHostInterface *host) = 0;
virtual bool PopulateUI(wxWindow *parent) = 0;
virtual bool ValidateUI() = 0;
virtual bool HideUI() = 0;
virtual bool CloseUI() = 0;
virtual void LoadUserPreset(const wxString & name) = 0;
virtual void SaveUserPreset(const wxString & name) = 0;
virtual void LoadFactoryPreset(int id) = 0;
virtual void LoadFactoryDefaults() = 0;
virtual wxArrayString GetFactoryPresets() = 0;
virtual void ExportPresets() = 0;
virtual void ImportPresets() = 0;
virtual void ShowOptions() = 0;
};
class EffectManagerInterface

View File

@ -89,8 +89,11 @@ public:
virtual bool RegisterPlugin(PluginManagerInterface & pluginManager,
const wxString & path) = 0;
// When appropriate, CreateInstance() will be called to instantiate the plugins.
virtual void *CreateInstance(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;
// When appropriate, DeleteInstance() will be called to delete the plugin.
virtual void DeleteInstance(IdentInterface *instance) = 0;
};
// ============================================================================

View File

@ -48,8 +48,6 @@
#include "audacity/IdentInterface.h"
#include "audacity/ImporterInterface.h"
class AUDACITY_DLL_API IdentInterface;
class AUDACITY_DLL_API EffectIdentInterface;
class PluginManagerInterface
{
public:
@ -64,6 +62,8 @@ public:
wxArrayString & files,
bool directories = false) = 0;
virtual bool GetSharedConfigSubgroups(const PluginID & ID, const wxString & group, wxArrayString & subgroups) = 0;
virtual bool GetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, wxString & value, const wxString & defval = wxString()) = 0;
virtual bool GetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, int & value, int defval = 0) = 0;
virtual bool GetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, bool & value, bool defval = false) = 0;
@ -78,6 +78,11 @@ public:
virtual bool SetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, const double & value) = 0;
virtual bool SetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, const sampleCount & value) = 0;
virtual bool RemoveSharedConfigSubgroup(const PluginID & ID, const wxString & group) = 0;
virtual bool RemoveSharedConfig(const PluginID & ID, const wxString & group, const wxString & key) = 0;
virtual bool GetPrivateConfigSubgroups(const PluginID & ID, const wxString & group, wxArrayString & subgroups) = 0;
virtual bool GetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, wxString & value, const wxString & defval = wxString()) = 0;
virtual bool GetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, int & value, int defval = 0) = 0;
virtual bool GetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, bool & value, bool defval = false) = 0;
@ -91,6 +96,9 @@ public:
virtual bool SetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, const float & value) = 0;
virtual bool SetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, const double & value) = 0;
virtual bool SetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, const sampleCount & value) = 0;
virtual bool RemovePrivateConfigSubgroup(const PluginID & ID, const wxString & group) = 0;
virtual bool RemovePrivateConfig(const PluginID & ID, const wxString & group, const wxString & key) = 0;
};
#endif // __AUDACITY_PLUGININTERFACE_H__

View File

@ -35,29 +35,29 @@ INSTALL_DATA = ${INSTALL} -m 644
# We use $(mkdir_p).
# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as
# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions,
# ${SHELL} /home/yam/a/audacity/autotools/install-sh does not start with $(SHELL), so we add it.
# In automake >= 1.10, /usr/bin/mkdir -p is derived from ${MKDIR_P}, which is defined
# ${SHELL} /Users/yam/a/audacity/autotools/install-sh does not start with $(SHELL), so we add it.
# In automake >= 1.10, $(top_builddir)/autotools/install-sh -c -d is derived from ${MKDIR_P}, which is defined
# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake
# versions, $(mkinstalldirs) and $(install_sh) are unused.
mkinstalldirs = $(SHELL) ${SHELL} /home/yam/a/audacity/autotools/install-sh -d
install_sh = $(SHELL) ${SHELL} /home/yam/a/audacity/autotools/install-sh
MKDIR_P = /usr/bin/mkdir -p
mkdir_p = /usr/bin/mkdir -p
mkinstalldirs = $(SHELL) ${SHELL} /Users/yam/a/audacity/autotools/install-sh -d
install_sh = $(SHELL) ${SHELL} /Users/yam/a/audacity/autotools/install-sh
MKDIR_P = ../autotools/install-sh -c -d
mkdir_p = $(top_builddir)/autotools/install-sh -c -d
GMSGFMT_ = /usr/bin/msgfmt
GMSGFMT_no = /usr/bin/msgfmt
GMSGFMT_yes = /usr/bin/msgfmt
GMSGFMT_ = /opt/local/bin/msgfmt
GMSGFMT_no = /opt/local/bin/msgfmt
GMSGFMT_yes = /opt/local/bin/msgfmt
GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT))
MSGFMT_ = /usr/bin/msgfmt
MSGFMT_no = /usr/bin/msgfmt
MSGFMT_yes = /usr/bin/msgfmt
MSGFMT_ = /opt/local/bin/msgfmt
MSGFMT_no = /opt/local/bin/msgfmt
MSGFMT_yes = /opt/local/bin/msgfmt
MSGFMT = $(MSGFMT_$(USE_MSGCTXT))
XGETTEXT_ = /usr/bin/xgettext
XGETTEXT_no = /usr/bin/xgettext
XGETTEXT_yes = /usr/bin/xgettext
XGETTEXT_ = /opt/local/bin/xgettext
XGETTEXT_no = /opt/local/bin/xgettext
XGETTEXT_yes = /opt/local/bin/xgettext
XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
MSGMERGE = msgmerge
MSGMERGE_UPDATE = /usr/bin/msgmerge --update
MSGMERGE_UPDATE = /opt/local/bin/msgmerge --update
MSGINIT = msginit
MSGCONV = msgconv
MSGFILTER = msgfilter
@ -98,7 +98,7 @@ CATALOGS = @CATALOGS@
mv t-$@ $@
all: check-macro-version all-yes
all: check-macro-version all-no
all-yes: stamp-po
all-no:
@ -211,7 +211,7 @@ $(POFILES): $(srcdir)/$(DOMAIN).pot
install: install-exec install-data
install-exec:
install-data: install-data-yes
install-data: install-data-no
if test "$(PACKAGE)" = "gettext-tools"; then \
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
for file in $(DISTFILES.common) Makevars.template; do \
@ -269,7 +269,7 @@ install-strip: install
installdirs: installdirs-exec installdirs-data
installdirs-exec:
installdirs-data: installdirs-data-yes
installdirs-data: installdirs-data-no
if test "$(PACKAGE)" = "gettext-tools"; then \
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
else \
@ -313,7 +313,7 @@ installcheck:
uninstall: uninstall-exec uninstall-data
uninstall-exec:
uninstall-data: uninstall-data-yes
uninstall-data: uninstall-data-no
if test "$(PACKAGE)" = "gettext-tools"; then \
for file in $(DISTFILES.common) Makevars.template; do \
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \

View File

@ -4001,6 +4001,7 @@
28FE4A060ABF4E960056F5C4 /* mmx_optimized.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = mmx_optimized.cpp; sourceTree = "<group>"; tabWidth = 3; };
28FE4A070ABF4E960056F5C4 /* sse_optimized.cpp */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = sse_optimized.cpp; sourceTree = "<group>"; tabWidth = 3; };
28FE4A390ABF58360056F5C4 /* soundtouch_config.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = soundtouch_config.h; path = "../lib-src/soundtouch/include/soundtouch_config.h"; sourceTree = SOURCE_ROOT; tabWidth = 3; };
28FEC1B21A12B6FB00FACE48 /* EffectAutomationParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EffectAutomationParameters.h; path = ../include/audacity/EffectAutomationParameters.h; sourceTree = SOURCE_ROOT; };
82FF184D13CF01A600C1B664 /* dBTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dBTable.cpp; path = sbsms/src/dBTable.cpp; sourceTree = "<group>"; };
82FF184E13CF01A600C1B664 /* dBTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dBTable.h; path = sbsms/src/dBTable.h; sourceTree = "<group>"; };
82FF184F13CF01A600C1B664 /* slide.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = slide.cpp; path = sbsms/src/slide.cpp; sourceTree = "<group>"; };
@ -5588,6 +5589,7 @@
280A8B3D19F440010091DE70 /* audacity */ = {
isa = PBXGroup;
children = (
28FEC1B21A12B6FB00FACE48 /* EffectAutomationParameters.h */,
280A8B3E19F440160091DE70 /* ConfigInterface.h */,
280A8B3F19F440160091DE70 /* EffectInterface.h */,
280A8B4019F440160091DE70 /* IdentInterface.h */,

View File

@ -645,7 +645,7 @@ IMPLEMENT_APP(AudacityApp)
#ifdef __WXMAC__
// This should be removed when Lame and FFmpeg support is converted
// from loadable libraries to commands.mLogger
// from loadable libraries to commands.
//
// The purpose of this is to give the user more control over where libraries
// such as Lame and FFmpeg get loaded from.
@ -1008,7 +1008,6 @@ int AudacityApp::FilterEvent(wxEvent & event)
return -1;
}
#endif
#include "effects/VST/VSTEffect.h"
// The `main program' equivalent, creating the windows and returning the
// main frame

View File

@ -283,10 +283,13 @@ wxArrayString BatchCommands::GetAllCommands()
const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeEffect);
while (plug)
{
command = em.GetEffectIdentifier(plug->GetID());
if (!command.IsEmpty())
if (plug->IsEffectAutomatable())
{
commands.Add( command);
command = em.GetEffectIdentifier(plug->GetID());
if (!command.IsEmpty())
{
commands.Add( command);
}
}
plug = pm.GetNextPlugin(PluginTypeEffect);
}

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.13.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -1384,8 +1384,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
configwin.h: stamp-h1
@test -f $@ || rm -f stamp-h1
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
@if test ! -f $@; then rm -f stamp-h1; else :; fi
@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
stamp-h1: $(srcdir)/configtemplate.h $(top_builddir)/config.status
@rm -f stamp-h1
@ -1396,8 +1396,8 @@ $(srcdir)/configtemplate.h: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
touch $@
configunix.h: stamp-h2
@test -f $@ || rm -f stamp-h2
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h2
@if test ! -f $@; then rm -f stamp-h2; else :; fi
@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h2; else :; fi
stamp-h2: $(srcdir)/configtemplate.h $(top_builddir)/config.status
@rm -f stamp-h2

View File

@ -216,26 +216,6 @@ void AudacityProjectCommandFunctor::operator()(int index, const wxEvent * evt)
// Effects menu arrays
//
WX_DEFINE_ARRAY_PTR(const PluginDescriptor *, EffectPlugs);
static int SortPlugsByDefault(const PluginDescriptor **a, const PluginDescriptor **b)
{
wxString akey = (*a)->GetVendor();
wxString bkey = (*b)->GetVendor();
if ((*a)->IsEffectDefault())
{
akey = wxEmptyString;
}
if ((*b)->IsEffectDefault())
{
bkey = wxEmptyString;
}
akey += (*a)->GetName();
bkey += (*b)->GetName();
return akey.CmpNoCase(bkey);
}
static int SortPlugsByName(const PluginDescriptor **a, const PluginDescriptor **b)
{
wxString akey = (*a)->GetName();
@ -264,6 +244,26 @@ static int SortPlugsByPublisher(const PluginDescriptor **a, const PluginDescript
return akey.CmpNoCase(bkey);
}
static int SortPlugsByPublisherAndName(const PluginDescriptor **a, const PluginDescriptor **b)
{
wxString akey = (*a)->GetVendor();
wxString bkey = (*b)->GetVendor();
if ((*a)->IsEffectDefault())
{
akey = wxEmptyString;
}
if ((*b)->IsEffectDefault())
{
bkey = wxEmptyString;
}
akey += (*a)->GetName();
bkey += (*b)->GetName();
return akey.CmpNoCase(bkey);
}
static int SortPlugsByFamily(const PluginDescriptor **a, const PluginDescriptor **b)
{
wxString akey = (*a)->GetEffectFamily();
@ -291,8 +291,6 @@ static int SortPlugsByFamily(const PluginDescriptor **a, const PluginDescriptor
void AudacityProject::CreateMenusAndCommands()
{
CommandManager *c = &mCommandManager;
EffectManager& em = EffectManager::Get();
EffectArray *effects;
wxArrayString names;
wxArrayInt indices;
@ -934,8 +932,6 @@ void AudacityProject::CreateMenusAndCommands()
// the plugin manager...sorry! :-(
wxArrayString defaults;
PluginManager & pm = PluginManager::Get();
const PluginDescriptor *plug;
//////////////////////////////////////////////////////////////////////////
// Generate Menu
@ -1005,8 +1001,6 @@ void AudacityProject::CreateMenusAndCommands()
c->AddSeparator();
int additionalEffects = ADVANCED_EFFECT;
// this is really ugly but we need to keep all the old code to get any
// effects at all in the menu when EFFECT_CATEGORIES is undefined
@ -1290,14 +1284,19 @@ void AudacityProject::PopulateEffectsMenu(CommandManager* c,
if (groupby == wxT("default"))
{
defplugs.Sort(SortPlugsByDefault);
optplugs.Sort(SortPlugsByDefault);
defplugs.Sort(SortPlugsByName);
optplugs.Sort(SortPlugsByName);
}
else if (groupby == wxT("publisher"))
{
defplugs.Sort(SortPlugsByPublisher);
optplugs.Sort(SortPlugsByPublisher);
}
else if (groupby == wxT("publisher:name"))
{
defplugs.Sort(SortPlugsByPublisherAndName);
optplugs.Sort(SortPlugsByPublisherAndName);
}
else if (groupby == wxT("family"))
{
defplugs.Sort(SortPlugsByFamily);
@ -1351,11 +1350,7 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
const PluginDescriptor *plug = plugs[i];
#if defined(EXPERIMENTAL_REALTIME_EFFECTS)
if (plug->GetName() == wxT("Cross Fade In"))
{
int f = 1;
}
int flags = plug->IsEffectRealtimeCapable() ? realflags : batchflags;
int flags = plug->IsEffectRealtime() ? realflags : batchflags;
#else
int flags = batchflags;
#endif
@ -1420,7 +1415,7 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
groupPlugs.Add(plug->GetID());
}
size_t groupCnt = groupPlugs.GetCount();
int groupCnt = (int) groupPlugs.GetCount();
if (grouped && groupCnt > 0 && i > 0)
{
@ -1437,7 +1432,7 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
max = 0;
}
for (size_t j = 0; j < groupCnt; j++)
for (int j = 0; j < groupCnt; j++)
{
if (max > 0 && items == max)
{
@ -1447,8 +1442,8 @@ void AudacityProject::AddEffectMenuItems(CommandManager *c,
end = groupCnt;
}
c->BeginSubMenu(wxString::Format(_("Plug-ins %d to %d"),
(int) j + 1,
(int) end));
j + 1,
end));
}
c->AddItem(groupNames[j],
@ -3042,6 +3037,10 @@ void AudacityProject::OnEffect(const PluginID & pluginID)
case EffectTypeAnalyze:
type = ANALYZE_EFFECT;
break;
case EffectTypeNone:
type = 0;
break;
}
type |= plug->IsEffectDefault() ? BUILTIN_EFFECT : PLUGIN_EFFECT;
@ -3069,6 +3068,10 @@ void AudacityProject::OnEffect(const PluginID & pluginID, bool configured)
case EffectTypeAnalyze:
type = ANALYZE_EFFECT;
break;
case EffectTypeNone:
type = 0;
break;
}
type |= plug->IsEffectDefault() ? BUILTIN_EFFECT : PLUGIN_EFFECT;

View File

@ -578,8 +578,8 @@ bool ModuleManager::IsProviderBuiltin(const PluginID & providerID)
return mModuleMains.find(providerID) != mModuleMains.end();
}
void *ModuleManager::CreateProviderInstance(const PluginID & providerID,
const wxString & path)
IdentInterface *ModuleManager::CreateProviderInstance(const PluginID & providerID,
const wxString & path)
{
if (path.empty() && mDynModules.find(providerID) != mDynModules.end())
{
@ -589,9 +589,9 @@ void *ModuleManager::CreateProviderInstance(const PluginID & providerID,
return LoadModule(path);
}
void *ModuleManager::CreateInstance(const PluginID & providerID,
const PluginID & ID,
const wxString & path)
IdentInterface *ModuleManager::CreateInstance(const PluginID & providerID,
const PluginID & ID,
const wxString & path)
{
if (mDynModules.find(providerID) == mDynModules.end())
{
@ -600,3 +600,14 @@ void *ModuleManager::CreateInstance(const PluginID & providerID,
return mDynModules[providerID]->CreateInstance(ID, path);
}
void ModuleManager::DeleteInstance(const PluginID & providerID,
IdentInterface *instance)
{
if (mDynModules.find(providerID) == mDynModules.end())
{
return;
}
mDynModules[providerID]->DeleteInstance(instance);
}

View File

@ -98,8 +98,9 @@ public:
void InitializePlugins();
bool IsProviderBuiltin(const PluginID & provider);
void *CreateProviderInstance(const PluginID & ID, const wxString & path);
void *CreateInstance(const PluginID & provider, const PluginID & ID, const wxString & path);
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);
private:
void InitializeBuiltins();

View File

@ -528,7 +528,7 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
ProviderMap provs;
wxArrayString keys;
wxArrayString paths;
wxString padding = L"0000000000";
wxString padding = wxT("0000000000");
const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeModule);
while (plug)
{
@ -552,7 +552,7 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
for (size_t j = 0, jcnt = newPaths.size(); j < jcnt; j++)
{
sortable.push_back(key + L" " + newPaths[j]);
sortable.push_back(key + wxT(" ") + newPaths[j]);
}
}
@ -571,7 +571,7 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
miState.push_back( SHOW_CHECKED );
wxString item = sortable[i];
int split = item.find(L" ");
int split = item.find(wxT(" "));
mProvs.push_back(provs[item.substr(0, split)]);
mPaths.push_back(item.substr(split + 1, wxString::npos));
@ -758,23 +758,26 @@ PluginDescriptor::PluginDescriptor()
mEffectInteractive = false;
mEffectDefault = false;
mEffectLegacy = false;
mEffectRealtime = false;
mEffectAutomatable = false;
}
PluginDescriptor::~PluginDescriptor()
{
if (mInstance)
{
switch (mPluginType)
{
case PluginTypeEffect:
EffectHostInterface *e = reinterpret_cast<EffectHostInterface *>(mInstance);
delete e;
break;
}
ModuleManager::Get().DeleteInstance(GetProviderID(), mInstance);
}
return;
}
void *PluginDescriptor::GetInstance()
bool PluginDescriptor::IsInstantiated()
{
return mInstance != NULL;
}
IdentInterface *PluginDescriptor::GetInstance()
{
if (!mInstance)
{
@ -791,7 +794,7 @@ void *PluginDescriptor::GetInstance()
return mInstance;
}
void PluginDescriptor::SetInstance(void *instance)
void PluginDescriptor::SetInstance(IdentInterface *instance)
{
mInstance = instance;
@ -936,9 +939,14 @@ bool PluginDescriptor::IsEffectLegacy() const
return mEffectLegacy;
}
bool PluginDescriptor::IsEffectRealtimeCapable() const
bool PluginDescriptor::IsEffectRealtime() const
{
return mEffectRealtimeCapable;
return mEffectRealtime;
}
bool PluginDescriptor::IsEffectAutomatable() const
{
return mEffectAutomatable;
}
void PluginDescriptor::SetEffectFamily(const wxString & family)
@ -966,9 +974,14 @@ void PluginDescriptor::SetEffectLegacy(bool legacy)
mEffectLegacy = legacy;
}
void PluginDescriptor::SetEffectRealtimeCapable(bool realtime)
void PluginDescriptor::SetEffectRealtime(bool realtime)
{
mEffectRealtimeCapable = realtime;
mEffectRealtime = realtime;
}
void PluginDescriptor::SetEffectAutomatable(bool automatable)
{
mEffectAutomatable = automatable;
}
// Importer
@ -1024,7 +1037,8 @@ void PluginDescriptor::SetImporterExtensions(const wxArrayString & extensions)
#define KEY_EFFECTFAMILY wxT("EffectFamily")
#define KEY_EFFECTDEFAULT wxT("EffectDefault")
#define KEY_EFFECTINTERACTIVE wxT("EffectInteractive")
#define KEY_EFFECTREALTIMECAPABLE wxT("EffectRealtimeCapable")
#define KEY_EFFECTREALTIME wxT("EffectRealtime")
#define KEY_EFFECTAUTOMATABLE wxT("EffectAutomatable")
#define KEY_EFFECTTYPE_ANALYZE wxT("Analyze")
#define KEY_EFFECTTYPE_GENERATE wxT("Generate")
#define KEY_EFFECTTYPE_PROCESS wxT("Process")
@ -1053,7 +1067,8 @@ void PluginManager::RegisterEffectPlugin(IdentInterface *provider, EffectIdentIn
plug.SetEffectFamily(effect->GetFamily());
plug.SetEffectInteractive(effect->IsInteractive());
plug.SetEffectDefault(effect->IsDefault());
plug.SetEffectRealtimeCapable(effect->IsRealtimeCapable());
plug.SetEffectRealtime(effect->SupportsRealtime());
plug.SetEffectAutomatable(effect->SupportsAutomation());
plug.SetEnabled(true);
}
@ -1078,7 +1093,7 @@ void PluginManager::FindFilesInPathList(const wxString & pattern,
wxLogNull nolog;
// Why bother...
if (pattern.empty())
if (pattern.IsEmpty())
{
return;
}
@ -1117,13 +1132,17 @@ void PluginManager::FindFilesInPathList(const wxString & pattern,
for (size_t i = 0, cnt = paths.GetCount(); i < cnt; i++)
{
f = paths[i] + wxFILE_SEP_PATH + pattern;
wxString a = f.GetFullPath();
wxDir::GetAllFiles(f.GetPath(), &files, f.GetFullName(), directories ? wxDIR_DEFAULT : wxDIR_FILES);
}
return;
}
bool PluginManager::GetSharedConfigSubgroups(const PluginID & ID, const wxString & group, wxArrayString & subgroups)
{
return GetSubgroups(SharedGroup(ID, group), subgroups);
}
bool PluginManager::GetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, wxString & value, const wxString & defval)
{
return GetConfig(SharedKey(ID, group, key), value, defval);
@ -1184,6 +1203,21 @@ bool PluginManager::SetSharedConfig(const PluginID & ID, const wxString & group,
return SetConfig(SharedKey(ID, group, key), value);
}
bool PluginManager::RemoveSharedConfigSubgroup(const PluginID & ID, const wxString & group)
{
return mConfig->DeleteGroup(SharedGroup(ID, group));
}
bool PluginManager::RemoveSharedConfig(const PluginID & ID, const wxString & group, const wxString & key)
{
return mConfig->DeleteEntry(SharedKey(ID, group, key));
}
bool PluginManager::GetPrivateConfigSubgroups(const PluginID & ID, const wxString & group, wxArrayString & subgroups)
{
return GetSubgroups(PrivateGroup(ID, group), subgroups);
}
bool PluginManager::GetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, wxString & value, const wxString & defval)
{
return GetConfig(PrivateKey(ID, group, key), value, defval);
@ -1244,6 +1278,16 @@ bool PluginManager::SetPrivateConfig(const PluginID & ID, const wxString & group
return SetConfig(PrivateKey(ID, group, key), value);
}
bool PluginManager::RemovePrivateConfigSubgroup(const PluginID & ID, const wxString & group)
{
return mConfig->DeleteGroup(PrivateGroup(ID, group));
}
bool PluginManager::RemovePrivateConfig(const PluginID & ID, const wxString & group, const wxString & key)
{
return mConfig->DeleteEntry(PrivateKey(ID, group, key));
}
// ============================================================================
//
// PluginManager
@ -1302,6 +1346,11 @@ void PluginManager::Initialize()
gPrefs->Write(wxT("/Plugins/Rescan"), false);
PluginRegistrationDialog dlg;
dlg.ShowModal();
if (mConfig)
{
mConfig->Flush();
}
}
}
@ -1446,7 +1495,7 @@ 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().empty())
if (!plug.GetPath().IsEmpty())
{
if (!mConfig->Read(KEY_LASTUPDATED, &strVal))
{
@ -1509,12 +1558,19 @@ void PluginManager::LoadGroup(const wxChar * group, PluginType type)
}
plug.SetEffectInteractive(boolVal);
// Is it an realtime capable effect and bypass group if not found
if (!mConfig->Read(KEY_EFFECTREALTIMECAPABLE, &boolVal))
// Is it a realtime capable effect and bypass group if not found
if (!mConfig->Read(KEY_EFFECTREALTIME, &boolVal))
{
continue;
}
plug.SetEffectRealtimeCapable(boolVal);
plug.SetEffectRealtime(boolVal);
// Does the effect support automation...bypass group if not found
if (!mConfig->Read(KEY_EFFECTAUTOMATABLE, &boolVal))
{
continue;
}
plug.SetEffectAutomatable(boolVal);
break;
@ -1628,7 +1684,8 @@ void PluginManager::SaveGroup(const wxChar *group, PluginType type)
mConfig->Write(KEY_EFFECTFAMILY, plug.GetEffectFamily());
mConfig->Write(KEY_EFFECTDEFAULT, plug.IsEffectDefault());
mConfig->Write(KEY_EFFECTINTERACTIVE, plug.IsEffectInteractive());
mConfig->Write(KEY_EFFECTREALTIMECAPABLE, plug.IsEffectRealtimeCapable());
mConfig->Write(KEY_EFFECTREALTIME, plug.IsEffectRealtime());
mConfig->Write(KEY_EFFECTAUTOMATABLE, plug.IsEffectAutomatable());
}
break;
@ -1695,7 +1752,7 @@ void PluginManager::RemoveMissing()
{
PluginDescriptor & plug = iter->second;
if (!plug.GetPath().empty())
if (!plug.GetPath().IsEmpty())
{
wxFileName plugPath = plug.GetPath();
@ -1919,7 +1976,8 @@ const PluginID & PluginManager::RegisterLegacyEffectPlugin(EffectIdentInterface
plug.SetEffectFamily(effect->GetFamily());
plug.SetEffectInteractive(effect->IsInteractive());
plug.SetEffectDefault(effect->IsDefault());
plug.SetEffectRealtimeCapable(effect->IsRealtimeCapable());
plug.SetEffectRealtime(effect->SupportsRealtime());
plug.SetEffectAutomatable(effect->SupportsAutomation());
plug.SetInstance(effect);
plug.SetEffectLegacy(true);
@ -1959,7 +2017,7 @@ const wxString & PluginManager::GetName(const PluginID & ID)
return mPlugins[ID].GetName();
}
void *PluginManager::GetInstance(const PluginID & ID)
IdentInterface *PluginManager::GetInstance(const PluginID & ID)
{
if (mPlugins.find(ID) == mPlugins.end())
{
@ -1983,7 +2041,7 @@ void *PluginManager::GetInstance(const PluginID & ID)
}
// TODO: This goes away when all effects have been converted
void PluginManager::SetInstance(const PluginID & ID, void *instance)
void PluginManager::SetInstance(const PluginID & ID, IdentInterface *instance)
{
if (mPlugins.find(ID) == mPlugins.end())
{
@ -2022,14 +2080,51 @@ wxString PluginManager::GetDateTime(const wxString & path)
return wxString(mod.FormatISODate() + wxT(' ') + mod.FormatISOTime());
}
return L"";
return wxEmptyString;
}
bool PluginManager::GetSubgroups(const wxString & group, wxArrayString & subgroups)
{
bool result = false;
if (mConfig && !group.IsEmpty())
{
wxString name = wxEmptyString;
long index = 0;
wxString path = mConfig->GetPath();
mConfig->SetPath(group);
if (mConfig->GetFirstGroup(name, index))
{
do
{
subgroups.Add(name);
} while (mConfig->GetNextGroup(name, index));
}
mConfig->SetPath(path);
}
return result;
}
bool PluginManager::GetConfig(const wxString & key, int & value, int defval)
{
bool result = false;
if (mConfig && !key.IsEmpty())
{
result = mConfig->Read(key, &value, defval);
}
return result;
}
bool PluginManager::GetConfig(const wxString & key, wxString & value, const wxString & defval)
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
wxString wxval = wxEmptyString;
@ -2041,23 +2136,11 @@ bool PluginManager::GetConfig(const wxString & key, wxString & value, const wxSt
return result;
}
bool PluginManager::GetConfig(const wxString & key, int & value, int defval)
{
bool result = false;
if (mConfig && !key.empty())
{
result = mConfig->Read(key, &value, defval);
}
return result;
}
bool PluginManager::GetConfig(const wxString & key, bool & value, bool defval)
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
result = mConfig->Read(key, &value, defval);
}
@ -2069,7 +2152,7 @@ bool PluginManager::GetConfig(const wxString & key, float & value, float defval)
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
double dval = 0.0;
@ -2085,7 +2168,7 @@ bool PluginManager::GetConfig(const wxString & key, double & value, double defva
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
result = mConfig->Read(key, &value, defval);
}
@ -2097,7 +2180,7 @@ bool PluginManager::GetConfig(const wxString & key, sampleCount & value, sampleC
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
wxString wxval = wxEmptyString;
wxString wxdef;
@ -2115,7 +2198,7 @@ bool PluginManager::SetConfig(const wxString & key, const wxString & value)
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
wxString wxval = value.c_str();
result = mConfig->Write(key, wxval);
@ -2132,7 +2215,7 @@ bool PluginManager::SetConfig(const wxString & key, const int & value)
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
result = mConfig->Write(key, value);
if (result)
@ -2148,7 +2231,7 @@ bool PluginManager::SetConfig(const wxString & key, const bool & value)
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
result = mConfig->Write(key, value);
if (result)
@ -2164,7 +2247,7 @@ bool PluginManager::SetConfig(const wxString & key, const float & value)
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
result = mConfig->Write(key, value);
if (result)
@ -2180,7 +2263,7 @@ bool PluginManager::SetConfig(const wxString & key, const double & value)
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
result = mConfig->Write(key, value);
if (result)
@ -2196,7 +2279,7 @@ bool PluginManager::SetConfig(const wxString & key, const sampleCount & value)
{
bool result = false;
if (mConfig && !key.empty())
if (mConfig && !key.IsEmpty())
{
result = mConfig->Write(key, wxString::Format(wxT("%d"), (int) value));
if (result)
@ -2208,33 +2291,44 @@ bool PluginManager::SetConfig(const wxString & key, const sampleCount & value)
return result;
}
wxString PluginManager::SharedKey(const PluginID & ID, const wxString & group, const wxString & key)
wxString PluginManager::SharedGroup(const PluginID & ID, const wxString & group)
{
if (mPlugins.find(ID) == mPlugins.end())
{
L"";
return wxEmptyString;
}
wxString path = CACHEROOT +
ConvertID(mPlugins[ID].GetProviderID()) +
wxCONFIG_PATH_SEPARATOR +
wxT("private") +
wxT("shared") +
wxCONFIG_PATH_SEPARATOR;
wxFileName f(group);
if (!f.GetName().IsEmpty())
{
path += f.GetName() + wxCONFIG_PATH_SEPARATOR;
path += f.GetFullPath(wxPATH_UNIX) + wxCONFIG_PATH_SEPARATOR;
}
return path;
}
wxString PluginManager::SharedKey(const PluginID & ID, const wxString & group, const wxString & key)
{
wxString path = SharedGroup(ID, group);
if (path.IsEmpty())
{
return path;
}
return path + key;
}
wxString PluginManager::PrivateKey(const PluginID & ID, const wxString & group, const wxString & key)
wxString PluginManager::PrivateGroup(const PluginID & ID, const wxString & group)
{
if (mPlugins.find(ID) == mPlugins.end())
{
L"";
return wxEmptyString;
}
wxString path = CACHEROOT +
@ -2246,7 +2340,18 @@ wxString PluginManager::PrivateKey(const PluginID & ID, const wxString & group,
wxFileName f(group);
if (!f.GetName().IsEmpty())
{
path += f.GetName() + wxCONFIG_PATH_SEPARATOR;
path += f.GetFullPath(wxPATH_UNIX) + wxCONFIG_PATH_SEPARATOR;
}
return path;
}
wxString PluginManager::PrivateKey(const PluginID & ID, const wxString & group, const wxString & key)
{
wxString path = PrivateGroup(ID, group);
if (path.IsEmpty())
{
return path;
}
return path + key;

View File

@ -45,8 +45,9 @@ public:
PluginDescriptor();
virtual ~PluginDescriptor();
void *GetInstance();
void SetInstance(void *instance);
bool IsInstantiated();
IdentInterface *GetInstance();
void SetInstance(IdentInterface *instance);
PluginType GetPluginType() const;
void SetPluginType(PluginType type);
@ -81,14 +82,16 @@ public:
bool IsEffectDefault() const;
bool IsEffectInteractive() const;
bool IsEffectLegacy() const;
bool IsEffectRealtimeCapable() const;
bool IsEffectRealtime() const;
bool IsEffectAutomatable() const;
void SetEffectType(EffectType type);
void SetEffectFamily(const wxString & family);
void SetEffectDefault(bool dflt);
void SetEffectInteractive(bool interactive);
void SetEffectLegacy(bool legacy);
void SetEffectRealtimeCapable(bool realtime);
void SetEffectRealtime(bool realtime);
void SetEffectAutomatable(bool automatable);
// Importer plugins only
@ -104,7 +107,7 @@ private:
// Common
void *mInstance;
IdentInterface *mInstance;
PluginType mPluginType;
@ -125,9 +128,11 @@ private:
bool mEffectInteractive;
bool mEffectDefault;
bool mEffectLegacy;
bool mEffectRealtimeCapable;
bool mEffectRealtime;
bool mEffectAutomatable;
// Importers
wxString mImporterIdentifier;
wxString mImporterFilterDesc;
wxArrayString mImporterExtensions;
@ -154,6 +159,8 @@ public:
wxArrayString & files,
bool directories = false);
virtual bool GetSharedConfigSubgroups(const PluginID & ID, const wxString & group, wxArrayString & subgroups);
virtual bool GetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, wxString & value, const wxString & defval = _T(""));
virtual bool GetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, int & value, int defval = 0);
virtual bool GetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, bool & value, bool defval = false);
@ -168,6 +175,11 @@ public:
virtual bool SetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, const double & value);
virtual bool SetSharedConfig(const PluginID & ID, const wxString & group, const wxString & key, const sampleCount & value);
virtual bool RemoveSharedConfigSubgroup(const PluginID & ID, const wxString & group);
virtual bool RemoveSharedConfig(const PluginID & ID, const wxString & group, const wxString & key);
virtual bool GetPrivateConfigSubgroups(const PluginID & ID, const wxString & group, wxArrayString & subgroups);
virtual bool GetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, wxString & value, const wxString & defval = _T(""));
virtual bool GetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, int & value, int defval = 0);
virtual bool GetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, bool & value, bool defval = false);
@ -182,6 +194,9 @@ public:
virtual bool SetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, const double & value);
virtual bool SetPrivateConfig(const PluginID & ID, const wxString & group, const wxString & key, const sampleCount & value);
virtual bool RemovePrivateConfigSubgroup(const PluginID & ID, const wxString & group);
virtual bool RemovePrivateConfig(const PluginID & ID, const wxString & group, const wxString & key);
// PluginManager implementation
void Initialize();
@ -214,8 +229,8 @@ public:
void EnablePlugin(const PluginID & ID, bool enable);
const wxString & GetName(const PluginID & ID);
void *GetInstance(const PluginID & ID);
void SetInstance(const PluginID & ID, void *instance); // TODO: Remove after conversion
IdentInterface *GetInstance(const PluginID & ID);
void SetInstance(const PluginID & ID, IdentInterface *instance); // TODO: Remove after conversion
//
const PluginID & RegisterLegacyEffectPlugin(EffectIdentInterface *effect);
@ -234,6 +249,8 @@ private:
PluginDescriptor & CreatePlugin(IdentInterface *ident, PluginType type);
wxString GetDateTime(const wxString & path);
bool GetSubgroups(const wxString & group, wxArrayString & subgroups);
bool GetConfig(const wxString & key, wxString & value, const wxString & defval = L"");
bool GetConfig(const wxString & key, int & value, int defval = 0);
bool GetConfig(const wxString & key, bool & value, bool defval = false);
@ -248,7 +265,9 @@ private:
bool SetConfig(const wxString & key, const double & value);
bool SetConfig(const wxString & key, const sampleCount & value);
wxString SharedGroup(const PluginID & ID, const wxString & group);
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);
wxString ConvertID(const PluginID & ID);

View File

@ -2191,9 +2191,9 @@ wxSizer *CreateStdButtonSizer(wxWindow *parent, long buttons, wxButton *extra)
bs->Add( 20, 0 );
}
if( buttons & eDefaultsButton )
if( buttons & eSettingsButton )
{
bs->Add(new wxButton( parent, eDefaultsID, _("&Defaults") ), 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin );
bs->Add(new wxButton( parent, eSettingsID, _("&Settings") ), 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin );
bs->Add( 20, 0 );
}

View File

@ -334,7 +334,7 @@ enum
eHelpButton = 0x0010,
ePreviewButton = 0x0020,
eDebugButton = 0x0040,
eDefaultsButton= 0x0080,
eSettingsButton= 0x0080,
ePreviewDryButton = 0x0100,
eApplyButton = 0x0200,
};
@ -343,7 +343,7 @@ enum
{
ePreviewID = wxID_LOWEST - 1,
eDebugID = wxID_LOWEST - 2,
eDefaultsID = wxID_LOWEST - 3,
eSettingsID = wxID_LOWEST - 3,
ePreviewDryID = wxID_LOWEST - 4
};

View File

@ -129,7 +129,7 @@ is time to refresh some aspect of the screen.
+----------------------------------------------------+
|+------------+ +-----------------------------------+|
|| | | (L) GuiWaveTrack ||
|| TrackInfo | +-----------------------------------+|
|| TrackInfo | +-----------------------------------+|
|| | +-----------------------------------+|
|| | | (R) GuiWaveTrack ||
|+------------+ +-----------------------------------+|
@ -137,7 +137,7 @@ is time to refresh some aspect of the screen.
+----------------------------------------------------+
|+------------+ +-----------------------------------+|
|| | | (L) GuiWaveTrack ||
|| TrackInfo | +-----------------------------------+|
|| TrackInfo | +-----------------------------------+|
|| | +-----------------------------------+|
|| | | (R) GuiWaveTrack ||
|+------------+ +-----------------------------------+|

View File

@ -68,6 +68,8 @@ wxString Effect::StripAmpersand(const wxString& str)
// Legacy (or full blown effect)
Effect::Effect()
{
mParent = NULL;
mClient = NULL;
mWarper = NULL;
@ -99,11 +101,6 @@ Effect::Effect()
Effect::~Effect()
{
if (mClient)
{
mClient->Shutdown();
}
if (mWarper != NULL)
{
delete mWarper;
@ -214,6 +211,16 @@ wxString Effect::GetFamily()
return _("Audacity");
}
bool Effect::IsInteractive()
{
if (mClient)
{
return mClient->IsInteractive();
}
return GetEffectName().EndsWith(wxT("..."));
}
bool Effect::IsDefault()
{
if (mClient)
@ -234,14 +241,14 @@ bool Effect::IsLegacy()
return true;
}
bool Effect::IsInteractive()
bool Effect::SupportsAutomation()
{
if (mClient)
{
return mClient->IsInteractive();
return mClient->SupportsAutomation();
}
return GetEffectName().EndsWith(wxT("..."));
return SupportsChains();
}
// EffectHostInterface implementation
@ -283,8 +290,48 @@ void Effect::Preview()
Preview(false);
}
wxDialog *Effect::CreateUI(wxWindow *parent, EffectUIClientInterface *client)
{
EffectUIHost *dlg = new EffectUIHost(parent, this, client);
if (dlg->Initialize())
{
return dlg;
}
delete dlg;
return NULL;
}
wxString Effect::GetUserPresetsGroup(const wxString & name)
{
wxString group = wxT("UserPresets");
if (!name.IsEmpty())
{
group += wxCONFIG_PATH_SEPARATOR + name;
}
return group;
}
wxString Effect::GetCurrentSettingsGroup()
{
return wxT("CurrentSettings");
}
wxString Effect::GetFactoryDefaultsGroup()
{
return wxT("FactoryDefaults");
}
// ConfigClientInterface implementation
bool Effect::GetSharedConfigSubgroups(const wxString & group, wxArrayString & subgroups)
{
return PluginManager::Get().GetSharedConfigSubgroups(GetID(), group, subgroups);
}
bool Effect::GetSharedConfig(const wxString & group, const wxString & key, wxString & value, const wxString & defval)
{
return PluginManager::Get().GetSharedConfig(GetID(), group, key, value, defval);
@ -345,6 +392,21 @@ bool Effect::SetSharedConfig(const wxString & group, const wxString & key, const
return PluginManager::Get().SetSharedConfig(GetID(), group, key, value);
}
bool Effect::RemoveSharedConfigSubgroup(const wxString & group)
{
return PluginManager::Get().RemoveSharedConfigSubgroup(GetID(), group);
}
bool Effect::RemoveSharedConfig(const wxString & group, const wxString & key)
{
return PluginManager::Get().RemoveSharedConfig(GetID(), group, key);
}
bool Effect::GetPrivateConfigSubgroups(const wxString & group, wxArrayString & subgroups)
{
return PluginManager::Get().GetPrivateConfigSubgroups(GetID(), group, subgroups);
}
bool Effect::GetPrivateConfig(const wxString & group, const wxString & key, wxString & value, const wxString & defval)
{
return PluginManager::Get().GetPrivateConfig(GetID(), group, key, value, defval);
@ -405,6 +467,16 @@ bool Effect::SetPrivateConfig(const wxString & group, const wxString & key, cons
return PluginManager::Get().SetPrivateConfig(GetID(), group, key, value);
}
bool Effect::RemovePrivateConfigSubgroup(const wxString & group)
{
return PluginManager::Get().RemovePrivateConfigSubgroup(GetID(), group);
}
bool Effect::RemovePrivateConfig(const wxString & group, const wxString & key)
{
return PluginManager::Get().RemovePrivateConfig(GetID(), group, key);
}
// Effect implementation
bool Effect::Startup(EffectClientInterface *client)
@ -412,14 +484,11 @@ bool Effect::Startup(EffectClientInterface *client)
// Let destructor know we need to be shutdown
mClient = client;
// Need to set host now so client startup can use our services
mClient->SetHost(this);
// Bail if the client startup fails
if (!mClient->Startup())
// Set host so client startup can use our services
if (!mClient->SetHost(this))
{
// Bail if the client startup fails
mClient = NULL;
return false;
}
@ -447,6 +516,46 @@ bool Effect::Startup(EffectClientInterface *client)
return true;
}
bool Effect::GetAutomationParameters(wxString & parms)
{
if (mClient)
{
EffectAutomationParameters eap;
if (!mClient->GetAutomationParameters(eap))
{
return false;
}
return eap.GetParameters(parms);
}
ShuttleCli shuttle;
shuttle.mbStoreInClient = false;
if (!TransferParameters(shuttle))
{
return false;
}
parms = shuttle.mParams;
return true;
}
bool Effect::SetAutomationParameters(const wxString & parms)
{
if (mClient)
{
EffectAutomationParameters eap;
eap.SetParameters(parms);
return mClient->SetAutomationParameters(eap);
}
ShuttleCli shuttle;
shuttle.mParams = parms;
shuttle.mbStoreInClient = true;
return TransferParameters(shuttle);
}
// All legacy effects should have this overridden
wxString Effect::GetEffectName()
{
@ -591,19 +700,20 @@ bool Effect::PromptUser()
return PromptUser(mParent);
}
bool Effect::PromptUser(wxWindow *parent)
bool Effect::PromptUser(wxWindow *parent, bool forceModal)
{
if (mClient)
{
#if defined(EXPERIMENTAL_REALTIME_EFFECTS)
if (IsRealtimeCapable())
bool res = mClient->ShowInterface(parent, forceModal);
// Really need to clean this up...should get easier when
// all effects get converted.
if (!res || SupportsRealtime())
{
mClient->ShowInterface(parent);
// Return false to force DoEffect() to skip processing since
// this UI has either been shown modeless or there was an error.
return false;
}
#endif
return mClient->ShowInterface(parent);
}
return true;
@ -853,6 +963,7 @@ bool Effect::ProcessTrack(int count,
WaveTrack *genRight = NULL;
sampleCount genLength = 0;
bool isGenerator = mClient->GetType() == EffectTypeGenerate;
bool isProcessor = mClient->GetType() == EffectTypeProcess;
if (isGenerator)
{
genLength = left->GetRate() * mDuration;
@ -980,7 +1091,7 @@ bool Effect::ProcessTrack(int count,
}
// Get the current number of delayed samples and accumulate
if (!isGenerator)
if (isProcessor)
{
sampleCount delay = mClient->GetLatency();
curDelay += delay;
@ -999,7 +1110,7 @@ bool Effect::ProcessTrack(int count,
else if (curDelay > 0)
{
curBlockSize -= curDelay;
for (int i = 0; i < mNumChannels; i++)
for (int i = 0; i < wxMin(mNumAudioOut, mNumChannels); i++)
{
memmove(mOutBufPos[i], mOutBufPos[i] + curDelay, SAMPLE_SIZE(floatSample) * curBlockSize);
}
@ -1014,7 +1125,7 @@ bool Effect::ProcessTrack(int count,
if (outputBufferCnt < mBufferSize)
{
// Bump to next output buffer position
for (int i = 0; i < mNumChannels; i++)
for (int i = 0; i < wxMin(mNumAudioOut, mNumChannels); i++)
{
mOutBufPos[i] += curBlockSize;
}
@ -1022,7 +1133,7 @@ bool Effect::ProcessTrack(int count,
// Output buffers have filled
else
{
if (!isGenerator)
if (isProcessor)
{
// Write them out
left->Set((samplePtr) mOutBuffer[0], floatSample, outLeftPos, outputBufferCnt);
@ -1031,7 +1142,7 @@ bool Effect::ProcessTrack(int count,
right->Set((samplePtr) mOutBuffer[1], floatSample, outRightPos, outputBufferCnt);
}
}
else
else if (isGenerator)
{
genLeft->Append((samplePtr) mOutBuffer[0], floatSample, outputBufferCnt);
if (genRight)
@ -1041,7 +1152,7 @@ bool Effect::ProcessTrack(int count,
}
// Reset the output buffer positions
for (int i = 0; i < mNumChannels; i++)
for (int i = 0; i < wxMin(mNumAudioOut, mNumChannels); i++)
{
mOutBufPos[i] = mOutBuffer[i];
}
@ -1080,7 +1191,7 @@ bool Effect::ProcessTrack(int count,
// Put any remaining output
if (outputBufferCnt)
{
if (!isGenerator)
if (isProcessor)
{
left->Set((samplePtr) mOutBuffer[0], floatSample, outLeftPos, outputBufferCnt);
if (right)
@ -1088,7 +1199,7 @@ bool Effect::ProcessTrack(int count,
right->Set((samplePtr) mOutBuffer[1], floatSample, outRightPos, outputBufferCnt);
}
}
else
else if (isGenerator)
{
genLeft->Append((samplePtr) mOutBuffer[0], floatSample, outputBufferCnt);
if (genRight)
@ -1385,12 +1496,12 @@ wxString Effect::GetPreviewName()
return _("Pre&view");
}
bool Effect::IsRealtimeCapable()
bool Effect::SupportsRealtime()
{
#if defined(EXPERIMENTAL_REALTIME_EFFECTS)
if (mClient)
{
return mClient->IsRealtimeCapable();
return mClient->SupportsRealtime();
}
#endif
@ -1793,3 +1904,357 @@ void EffectDialog::OnPreview(wxCommandEvent & WXUNUSED(event))
{
return;
}
enum
{
kSaveAsID = 30001,
kImportID = 30002,
kExportID = 30003,
kDefaultsID = 30004,
kOptionsID = 30005,
kDeleteAllID = 30006,
kUserPresetsID = 31000,
kDeletePresetID = 32000,
kFactoryPresetsID = 33000,
};
BEGIN_EVENT_TABLE(EffectUIHost, wxDialog)
// EVT_WINDOW_DESTROY(EffectUIHost::OnDestroy)
EVT_CLOSE(EffectUIHost::OnClose)
EVT_BUTTON(wxID_OK, EffectUIHost::OnOk)
EVT_BUTTON(wxID_CANCEL, EffectUIHost::OnCancel)
EVT_BUTTON(ePreviewID, EffectUIHost::OnPreview)
EVT_BUTTON(eSettingsID, EffectUIHost::OnSettings)
EVT_MENU(kSaveAsID, EffectUIHost::OnSaveAs)
EVT_MENU(kImportID, EffectUIHost::OnImport)
EVT_MENU(kExportID, EffectUIHost::OnExport)
EVT_MENU(kOptionsID, EffectUIHost::OnOptions)
EVT_MENU(kDefaultsID, EffectUIHost::OnDefaults)
EVT_MENU(kDeleteAllID, EffectUIHost::OnDeleteAllPresets)
EVT_MENU_RANGE(kUserPresetsID, kUserPresetsID + 999, EffectUIHost::OnUserPreset)
EVT_MENU_RANGE(kDeletePresetID, kDeletePresetID + 999, EffectUIHost::OnDeletePreset)
EVT_MENU_RANGE(kFactoryPresetsID, kFactoryPresetsID + 999, EffectUIHost::OnFactoryPreset)
END_EVENT_TABLE()
EffectUIHost::EffectUIHost(wxWindow *parent,
EffectHostInterface *host,
EffectUIClientInterface *client)
: wxDialog(parent, wxID_ANY, host->GetName())
{
SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
mParent = parent;
mHost = host;
mClient = client;
mClient->SetUIHost(this);
}
EffectUIHost::~EffectUIHost()
{
if (mClient)
{
mClient->CloseUI();
mClient = NULL;
}
}
bool EffectUIHost::Initialize()
{
wxBoxSizer *vs = new wxBoxSizer(wxVERTICAL);
wxScrolledWindow *w = new wxScrolledWindow(this,
wxID_ANY,
wxDefaultPosition,
wxDefaultSize,
wxVSCROLL | wxTAB_TRAVERSAL);
// Try to give the window a sensible default/minimum size
w->SetMinSize(wxSize(wxMax(600, mParent->GetSize().GetWidth() * 2/3),
mParent->GetSize().GetHeight() / 2));
w->SetScrollRate(0, 20);
wxSizer *s = CreateStdButtonSizer(this, eSettingsButton | eOkButton | eCancelButton);
vs->Add(w, 1, wxEXPAND);
vs->Add(s, 0, wxEXPAND | wxALIGN_CENTER_VERTICAL);
SetSizer(vs);
if (!mClient->PopulateUI(w))
{
return false;
}
Layout();
Fit();
Center();
LoadUserPresets();
mClient->LoadUserPreset(mHost->GetCurrentSettingsGroup());
return true;
}
void EffectUIHost::OnDestroy(wxWindowDestroyEvent & WXUNUSED(evt))
{
mClient->CloseUI();
}
void EffectUIHost::OnClose(wxCloseEvent & WXUNUSED(evt))
{
mClient->CloseUI();
mClient = NULL;
Destroy();
}
void EffectUIHost::OnOk(wxCommandEvent & WXUNUSED(evt))
{
if (!mClient->ValidateUI())
{
return;
}
mClient->SaveUserPreset(mHost->GetCurrentSettingsGroup());
if (IsModal())
{
SetReturnCode(true);
Close();
#if !defined(__WXGTK__)
EndModal(true);
#endif
return;
}
mHost->Apply();
if (!mClient->HideUI())
{
return;
}
Close();
return;
}
void EffectUIHost::OnCancel(wxCommandEvent & WXUNUSED(evt))
{
if (IsModal())
{
EndModal(false);
return;
}
Close();
return;
}
void EffectUIHost::OnPreview(wxCommandEvent & WXUNUSED(evt))
{
mHost->Preview();
}
void EffectUIHost::OnSettings(wxCommandEvent & evt)
{
wxButton *b = (wxButton *)evt.GetEventObject();
wxMenu *menu = new wxMenu();
wxMenu *sub;
LoadUserPresets();
sub = new wxMenu();
for (size_t i = 0, cnt = mUserPresets.GetCount(); i < cnt; i++)
{
sub->Append(kUserPresetsID + i, mUserPresets[i]);
}
menu->Append(0, _("User Presets"), sub);
wxArrayString factory = mClient->GetFactoryPresets();
sub = new wxMenu();
sub->Append(kDefaultsID, _("Defaults"));
if (factory.GetCount() > 0)
{
sub->AppendSeparator();
for (size_t i = 0, cnt = factory.GetCount(); i < cnt; i++)
{
wxString label = factory[i];
if (label.IsEmpty())
{
label = _("None");
}
sub->Append(kFactoryPresetsID + i, label);
}
}
menu->Append(0, _("Factory Presets"), sub);
sub = new wxMenu();
for (size_t i = 0, cnt = mUserPresets.GetCount(); i < cnt; i++)
{
sub->Append(kDeletePresetID + i, mUserPresets[i]);
}
menu->Append(0, _("Delete Preset"), sub);
menu->AppendSeparator();
menu->Append(kSaveAsID, _("Save As..."));
menu->AppendSeparator();
menu->Append(kImportID, _("Import..."));
menu->Append(kExportID, _("Export..."));
menu->AppendSeparator();
menu->Append(kOptionsID, _("Options..."));
menu->AppendSeparator();
sub = new wxMenu();
sub->Append(0, wxString::Format(_("Type: %s"), mHost->GetFamily().c_str()));
sub->Append(0, wxString::Format(_("Name: %s"), mHost->GetName().c_str()));
sub->Append(0, wxString::Format(_("Version: %s"), mHost->GetVersion().c_str()));
sub->Append(0, wxString::Format(_("Vendor: %s"), mHost->GetVendor().c_str()));
sub->Append(0, wxString::Format(_("Description: %s"), mHost->GetDescription().c_str()));
// sub->Append(0, wxString::Format(_("Audio In: %d"), mHost->GetAudioInCount()));
// sub->Append(0, wxString::Format(_("Audio Out: %d"), mHost->GetAudioOutCount()));
menu->Append(0, _("About"), sub);
wxRect r = b->GetRect();
PopupMenu(menu, wxPoint(r.GetLeft(), r.GetBottom()));
delete menu;
}
void EffectUIHost::OnSaveAs(wxCommandEvent & WXUNUSED(evt))
{
wxTextCtrl *text;
wxString name;
wxDialog dlg(this, wxID_ANY, wxString(_("Save Preset")));
ShuttleGui S(&dlg, eIsCreating);
S.StartPanel();
{
S.StartVerticalLay(0);
{
S.StartHorizontalLay(wxALIGN_LEFT, 0);
{
text = S.AddTextBox(_("Preset name:"), name, 30);
}
S.EndHorizontalLay();
S.AddStandardButtons();
}
S.EndVerticalLay();
}
S.EndPanel();
dlg.SetSize(dlg.GetSizer()->GetMinSize());
dlg.Center();
while (true)
{
int rc = dlg.ShowModal();
if (rc != wxID_OK)
{
break;
}
name = text->GetValue();
if (mUserPresets.Index(name) == wxNOT_FOUND)
{
mClient->SaveUserPreset(mHost->GetUserPresetsGroup(name));
LoadUserPresets();
break;
}
wxMessageBox(_("Preset already exists"),
_("Save Preset"),
wxICON_EXCLAMATION);
}
return;
}
void EffectUIHost::OnImport(wxCommandEvent & WXUNUSED(evt))
{
mClient->ImportPresets();
LoadUserPresets();
return;
}
void EffectUIHost::OnExport(wxCommandEvent & WXUNUSED(evt))
{
mClient->ExportPresets();
return;
}
void EffectUIHost::OnDefaults(wxCommandEvent & WXUNUSED(evt))
{
mClient->LoadFactoryDefaults();
return;
}
void EffectUIHost::OnOptions(wxCommandEvent & WXUNUSED(evt))
{
mClient->ShowOptions();
return;
}
void EffectUIHost::OnUserPreset(wxCommandEvent & evt)
{
int preset = evt.GetId() - kUserPresetsID;
mClient->LoadUserPreset(mHost->GetUserPresetsGroup(mUserPresets[preset]));
return;
}
void EffectUIHost::OnFactoryPreset(wxCommandEvent & evt)
{
mClient->LoadFactoryPreset(evt.GetId() - kFactoryPresetsID);
return;
}
void EffectUIHost::OnDeletePreset(wxCommandEvent & evt)
{
mHost->RemovePrivateConfigSubgroup(mHost->GetUserPresetsGroup(mUserPresets[evt.GetId() - kDeletePresetID]));
LoadUserPresets();
return;
}
void EffectUIHost::OnDeleteAllPresets(wxCommandEvent & WXUNUSED(evt))
{
int res = wxMessageBox(_("This will delete all of your user presets. Are you sure?"),
_("Delete All Presets"),
wxICON_QUESTION | wxYES_NO);
if (res == wxID_YES)
{
mHost->RemovePrivateConfigSubgroup(mHost->GetUserPresetsGroup(wxEmptyString));
mUserPresets.Clear();
}
return;
}
void EffectUIHost::LoadUserPresets()
{
mUserPresets.Clear();
mHost->GetPrivateConfigSubgroups(mHost->GetUserPresetsGroup(wxEmptyString), mUserPresets);
mUserPresets.Sort();
return;
}

View File

@ -92,7 +92,8 @@ class AUDACITY_DLL_API Effect : public EffectHostInterface
virtual bool IsInteractive();
virtual bool IsDefault();
virtual bool IsLegacy();
virtual bool IsRealtimeCapable();
virtual bool SupportsRealtime();
virtual bool SupportsAutomation();
// EffectHostInterface implementation
@ -102,8 +103,16 @@ class AUDACITY_DLL_API Effect : public EffectHostInterface
virtual bool Apply();
virtual void Preview();
virtual wxDialog *CreateUI(wxWindow *parent, EffectUIClientInterface *client);
virtual wxString GetUserPresetsGroup(const wxString & name);
virtual wxString GetCurrentSettingsGroup();
virtual wxString GetFactoryDefaultsGroup();
// ConfigClientInterface implementation
virtual bool GetSharedConfigSubgroups(const wxString & group, wxArrayString & subgroups);
virtual bool GetSharedConfig(const wxString & group, const wxString & key, wxString & value, const wxString & defval = wxEmptyString);
virtual bool GetSharedConfig(const wxString & group, const wxString & key, int & value, int defval = 0);
virtual bool GetSharedConfig(const wxString & group, const wxString & key, bool & value, bool defval = false);
@ -118,6 +127,11 @@ class AUDACITY_DLL_API Effect : public EffectHostInterface
virtual bool SetSharedConfig(const wxString & group, const wxString & key, const double & value);
virtual bool SetSharedConfig(const wxString & group, const wxString & key, const sampleCount & value);
virtual bool RemoveSharedConfigSubgroup(const wxString & group);
virtual bool RemoveSharedConfig(const wxString & group, const wxString & key);
virtual bool GetPrivateConfigSubgroups(const wxString & group, wxArrayString & subgroups);
virtual bool GetPrivateConfig(const wxString & group, const wxString & key, wxString & value, const wxString & defval = wxEmptyString);
virtual bool GetPrivateConfig(const wxString & group, const wxString & key, int & value, int defval = 0);
virtual bool GetPrivateConfig(const wxString & group, const wxString & key, bool & value, bool defval = false);
@ -132,8 +146,14 @@ class AUDACITY_DLL_API Effect : public EffectHostInterface
virtual bool SetPrivateConfig(const wxString & group, const wxString & key, const double & value);
virtual bool SetPrivateConfig(const wxString & group, const wxString & key, const sampleCount & value);
virtual bool RemovePrivateConfigSubgroup(const wxString & group);
virtual bool RemovePrivateConfig(const wxString & group, const wxString & key);
// Effect implementation
virtual bool Startup(EffectClientInterface *client);
virtual bool GetAutomationParameters(wxString & parms);
virtual bool SetAutomationParameters(const wxString & parms);
// Each subclass of Effect should override this method.
// This name will go in the menu bar;
@ -274,7 +294,7 @@ class AUDACITY_DLL_API Effect : public EffectHostInterface
// repeats an effect) but if it is called, it will be called
// after Init.
virtual bool PromptUser();
virtual bool PromptUser(wxWindow *parent);
virtual bool PromptUser(wxWindow *parent, bool forceModal = false);
// Check whether effect should be skipped
// Typically this is only useful in automation, for example
@ -451,6 +471,48 @@ private:
int mAdditionalButtons;
};
//
class EffectUIHost : public wxDialog,
public EffectUIHostInterface
{
public:
// constructors and destructors
EffectUIHost(wxWindow *parent,
EffectHostInterface *host,
EffectUIClientInterface *client);
virtual ~EffectUIHost();
bool Initialize();
private:
void OnDestroy(wxWindowDestroyEvent & evt);
void OnClose(wxCloseEvent & evt);
void OnOk(wxCommandEvent & evt);
void OnCancel(wxCommandEvent & evt);
void OnPreview(wxCommandEvent & evt);
void OnSettings(wxCommandEvent & evt);
void OnSaveAs(wxCommandEvent & evt);
void OnImport(wxCommandEvent & evt);
void OnExport(wxCommandEvent & evt);
void OnOptions(wxCommandEvent & evt);
void OnUserPreset(wxCommandEvent & evt);
void OnDeletePreset(wxCommandEvent & evt);
void OnFactoryPreset(wxCommandEvent & evt);
void OnDefaults(wxCommandEvent & evt);
void OnDeleteAllPresets(wxCommandEvent & evt);
void LoadUserPresets();
private:
wxWindow *mParent;
EffectHostInterface *mHost;
EffectUIClientInterface *mClient;
wxArrayString mUserPresets;
DECLARE_EVENT_TABLE();
};
// Utility functions
float TrapFloat(float x, float min, float max);

View File

@ -215,6 +215,13 @@ EffectManager::~EffectManager()
// wxWidgets has already destroyed the rack since it was derived from wxFrame. So
// no need to delete it here.
#endif
EffectMap::iterator iter = mEffects.begin();
while (iter != mEffects.end())
{
delete iter->second;
iter++;
}
}
void EffectManager::RegisterEffect(Effect *f, int NewFlags)
@ -227,7 +234,7 @@ void EffectManager::RegisterEffect(Effect *f, int NewFlags)
}
// This will go away after all effects have been converted
mEffectPlugins.Add(PluginManager::Get().RegisterLegacyEffectPlugin(f));
mEffects[PluginManager::Get().RegisterLegacyEffectPlugin(f)] = f;
#ifdef EFFECT_CATEGORIES
// Add the effect in the right categories
@ -275,7 +282,7 @@ bool EffectManager::DoEffect(const PluginID & ID,
}
#if defined(EXPERIMENTAL_REALTIME_EFFECTS) && defined(EXPERIMENTAL_EFFECTS_RACK)
if (effect->IsRealtimeCapable())
if (effect->SupportsRealtime())
{
GetRack()->Add(effect);
}
@ -333,16 +340,28 @@ wxString EffectManager::GetEffectDescription(const PluginID & ID)
return wxEmptyString;
}
bool EffectManager::SupportsAutomation(const PluginID & ID)
{
const PluginDescriptor *plug = PluginManager::Get().GetPlugin(ID);
if (plug)
{
return plug->IsEffectAutomatable();
}
return false;
}
wxString EffectManager::GetEffectParameters(const PluginID & ID)
{
Effect *effect = GetEffect(ID);
if (effect)
{
ShuttleCli shuttle;
shuttle.mbStoreInClient = false;
effect->TransferParameters(shuttle);
return shuttle.mParams;
wxString parms;
effect->GetAutomationParameters(parms);
return parms;
}
return wxEmptyString;
@ -354,10 +373,7 @@ bool EffectManager::SetEffectParameters(const PluginID & ID, const wxString & pa
if (effect)
{
ShuttleCli shuttle;
shuttle.mParams = params;
shuttle.mbStoreInClient=true;
return effect->TransferParameters(shuttle);
return effect->SetAutomationParameters(params);
}
return false;
@ -370,7 +386,7 @@ bool EffectManager::PromptUser(const PluginID & ID, wxWindow *parent)
if (effect)
{
result = effect->PromptUser(parent);
result = effect->PromptUser(parent, true);
}
return result;
@ -634,18 +650,17 @@ Effect *EffectManager::GetEffect(const PluginID & ID)
Effect *effect;
// TODO: This is temporary and should be redone when all effects are converted
if (mEffectPlugins.Index(wxString(ID)) == wxNOT_FOUND)
if (mEffects.find(ID) == mEffects.end())
{
effect = new Effect();
if (effect)
{
// This will instantiate the effect client if it hasn't already been done
EffectClientInterface *client = static_cast<EffectClientInterface *>(PluginManager::Get().GetInstance(ID));
EffectClientInterface *client = dynamic_cast<EffectClientInterface *>(PluginManager::Get().GetInstance(ID));
if (client && effect->Startup(client))
{
effect->SetEffectID(mNumEffects++);
PluginManager::Get().SetInstance(ID, effect);
mEffectPlugins.Add(ID);
mEffects[ID] = effect;
return effect;
}
@ -659,14 +674,14 @@ Effect *EffectManager::GetEffect(const PluginID & ID)
return NULL;
}
return static_cast<Effect *>(PluginManager::Get().GetInstance(ID));
return mEffects[ID];
}
const PluginID & EffectManager::GetEffectByIdentifier(const wxString & strTarget)
{
if (strTarget == wxEmptyString) // set GetEffectIdentifier to wxT("") to not show an effect in Batch mode
{
return PluginID(wxString(wxEmptyString));
return PluginID(wxEmptyString);
}
PluginManager & pm = PluginManager::Get();
@ -680,7 +695,7 @@ const PluginID & EffectManager::GetEffectByIdentifier(const wxString & strTarget
plug = pm.GetNextPlugin(PluginTypeEffect);
}
return PluginID(wxString(wxEmptyString));
return PluginID(wxEmptyString);
}
#ifdef EFFECT_CATEGORIES

View File

@ -34,6 +34,7 @@ effects.
#endif
WX_DEFINE_USER_EXPORTED_ARRAY(Effect *, EffectArray, class AUDACITY_DLL_API);
WX_DECLARE_STRING_HASH_MAP_WITH_DECL(Effect *, EffectMap, class AUDACITY_DLL_API);
#if defined(EXPERIMENTAL_EFFECTS_RACK)
class EffectRack;
@ -88,6 +89,7 @@ class AUDACITY_DLL_API EffectManager
wxString GetEffectDescription(const PluginID & ID);
/** Support for batch commands */
bool SupportsAutomation(const PluginID & ID);
wxString GetEffectParameters(const PluginID & ID);
bool SetEffectParameters(const PluginID & ID, const wxString & params);
bool PromptUser(const PluginID & ID, wxWindow *parent);
@ -148,7 +150,7 @@ class AUDACITY_DLL_API EffectManager
#endif
private:
wxArrayString mEffectPlugins;
EffectMap mEffects;
int mNumEffects;

File diff suppressed because it is too large Load Diff

View File

@ -10,11 +10,13 @@
#if USE_VST
#include <wx/wx.h>
#include "audacity/EffectInterface.h"
#include "audacity/ModuleInterface.h"
#include "audacity/PluginInterface.h"
#include <wx/wx.h>
#include "../../widgets/NumericTextCtrl.h"
#include "aeffectx.h"
@ -48,15 +50,30 @@ class VSTEffectTimer;
class VSTEffectDialog;
class VSTEffect;
///////////////////////////////////////////////////////////////////////////////
//
// VSTEffect
//
///////////////////////////////////////////////////////////////////////////////
WX_DEFINE_ARRAY_PTR(VSTEffect *, VSTEffectArray);
class VSTEffect : public EffectClientInterface
DECLARE_LOCAL_EVENT_TYPE(EVT_SIZEWINDOW, -1);
DECLARE_LOCAL_EVENT_TYPE(EVT_UPDATEDISPLAY, -1);
class VSTEffectEventHelper;
class VSTEffect : public EffectClientInterface,
public EffectUIClientInterface,
public XMLTagHandler
{
public:
VSTEffect(const wxString & path, VSTEffect *master = NULL);
virtual ~VSTEffect();
// IdentInterface implementation
virtual PluginID GetID();
virtual wxString GetPath();
virtual wxString GetName();
@ -65,17 +82,18 @@ class VSTEffect : public EffectClientInterface
virtual wxString GetDescription();
// EffectIdentInterface implementation
virtual EffectType GetType();
virtual wxString GetFamily();
virtual bool IsInteractive();
virtual bool IsDefault();
virtual bool IsLegacy();
virtual bool IsRealtimeCapable();
virtual bool SupportsRealtime();
virtual bool SupportsAutomation();
// EffectClientInterface implementation
virtual void SetHost(EffectHostInterface *host);
virtual bool Startup();
virtual bool Shutdown();
virtual bool SetHost(EffectHostInterface *host);
virtual int GetAudioInCount();
virtual int GetAudioOutCount();
@ -104,7 +122,30 @@ class VSTEffect : public EffectClientInterface
float **outbuf,
sampleCount numSamples);
virtual bool ShowInterface(void *parent);
virtual bool ShowInterface(wxWindow *parent, bool forceModal = false);
virtual bool GetAutomationParameters(EffectAutomationParameters & parms);
virtual bool SetAutomationParameters(EffectAutomationParameters & parms);
// EffectUIClientInterface implementation
virtual void SetUIHost(EffectUIHostInterface *host);
virtual bool PopulateUI(wxWindow *parent);
virtual bool ValidateUI();
virtual bool HideUI();
virtual bool CloseUI();
virtual void LoadUserPreset(const wxString & name);
virtual void SaveUserPreset(const wxString & name);
virtual void LoadFactoryPreset(int id);
virtual void LoadFactoryDefaults();
virtual wxArrayString GetFactoryPresets();
virtual void ExportPresets();
virtual void ImportPresets();
virtual void ShowOptions();
// VSTEffect implementation
@ -135,6 +176,52 @@ private:
int GetChannelCount();
void SetChannelCount(int numChannels);
// UI
void OnSlider(wxCommandEvent & evt);
void ConnectFocus(wxControl *c);
void DisconnectFocus(wxControl *c);
void ControlSetFocus(wxFocusEvent & evt);
void OnSizeWindow(wxCommandEvent & evt);
void OnUpdateDisplay(wxCommandEvent & evt);
void RemoveHandler();
void OnProgram(wxCommandEvent & evt);
void OnProgramText(wxCommandEvent & evt);
void OnLoad(wxCommandEvent & evt);
void OnSave(wxCommandEvent & evt);
void OnSettings(wxCommandEvent & evt);
void OnApply(wxCommandEvent & evt);
void OnOk(wxCommandEvent & evt);
void OnCancel(wxCommandEvent & evt);
void OnPreview(wxCommandEvent & evt);
void OnDefaults(wxCommandEvent & evt);
void OnClose(wxCloseEvent & evt);
void BuildPlain();
void BuildFancy();
wxSizer *BuildProgramBar();
void RefreshParameters(int skip = -1);
// Program/Bank loading/saving
bool LoadFXB(const wxFileName & fn);
bool LoadFXP(const wxFileName & fn);
bool LoadXML(const wxFileName & fn);
bool LoadFXProgram(unsigned char **bptr, ssize_t & len, int index, bool dryrun);
void SaveFXB(const wxFileName & fn);
void SaveFXP(const wxFileName & fn);
void SaveXML(const wxFileName & fn);
void SaveFXProgram(wxMemoryBuffer & buf, int index);
virtual bool HandleXMLTag(const wxChar *tag, const wxChar **attrs);
virtual void HandleXMLEndTag(const wxChar *tag);
virtual void HandleXMLContent(const wxString & content);
virtual XMLTagHandler *HandleXMLChild(const wxChar *tag);
// Utility methods
VstTimeInfo *GetTimeInfo();
@ -148,7 +235,6 @@ private:
void Automate(int index, float value);
void PowerOn();
void PowerOff();
void InterfaceClosed();
int GetString(wxString & outstr, int opcode, int index = 0);
wxString GetString(int opcode, int index = 0);
@ -170,6 +256,7 @@ private:
int mAudioOuts;
int mMidiIns;
int mMidiOuts;
bool mAutomatable;
float mSampleRate;
sampleCount mUserBlockSize;
wxString mName;
@ -187,8 +274,6 @@ private:
void *mModule;
AEffect *mAEffect;
VSTEffectDialog *mDlg;
VstTimeInfo mTimeInfo;
bool mUseBufferDelay;
@ -215,11 +300,82 @@ private:
float **mMasterOut;
int mMasterOutLen;
friend class VSTEffectDialog;
// UI
wxDialog *mDialog;
wxWindow *mParent;
EffectUIHostInterface *mUIHost;
VSTEffectEventHelper *mEventHelper;
wxSizerItem *mContainer;
bool mGui;
NumericTextCtrl *mDuration;
wxStaticText **mNames;
wxSlider **mSliders;
wxStaticText **mDisplays;
wxStaticText **mLabels;
bool mInChunk;
wxString mChunk;
#if defined(__WXMAC__)
static pascal OSStatus OverlayEventHandler(EventHandlerCallRef handler, EventRef event, void *data);
OSStatus OnOverlayEvent(EventHandlerCallRef handler, EventRef event);
static pascal OSStatus WindowEventHandler(EventHandlerCallRef handler, EventRef event, void *data);
OSStatus OnWindowEvent(EventHandlerCallRef handler, EventRef event);
WindowRef mOverlayRef;
EventHandlerUPP mOverlayEventHandlerUPP;
EventHandlerRef mOverlayEventHandlerRef;
WindowRef mWindowRef;
WindowRef mPreviousRef;
EventHandlerUPP mWindowEventHandlerUPP;
EventHandlerRef mWindowEventHandlerRef;
#elif defined(__WXMSW__)
HANDLE mHwnd;
#else
Display *mXdisp;
Window mXwin;
#endif
friend class VSTEffectEventHelper;
friend class VSTEffectsModule;
};
void RegisterVSTEffects();
///////////////////////////////////////////////////////////////////////////////
//
// VSTEffectEventHelper
//
///////////////////////////////////////////////////////////////////////////////
class VSTEffectEventHelper : public wxEvtHandler
{
public:
VSTEffectEventHelper(VSTEffect *effect);
virtual ~VSTEffectEventHelper();
// VSTEffectEventHelper implementation
void OnSlider(wxCommandEvent & evt);
void ControlSetFocus(wxFocusEvent & evt);
void OnSizeWindow(wxCommandEvent & evt);
private:
VSTEffect *mEffect;
DECLARE_EVENT_TABLE();
};
///////////////////////////////////////////////////////////////////////////////
//
// VSTEffectsModule
//
///////////////////////////////////////////////////////////////////////////////
class VSTEffectsModule : public ModuleInterface
{
@ -245,7 +401,8 @@ public:
virtual wxArrayString FindPlugins(PluginManagerInterface & pm);
virtual bool RegisterPlugin(PluginManagerInterface & pm, const wxString & path);
virtual void *CreateInstance(const PluginID & ID, const wxString & path);
virtual IdentInterface *CreateInstance(const PluginID & ID, const wxString & path);
virtual void DeleteInstance(IdentInterface *instance);
// VSTEffectModule implementation

File diff suppressed because it is too large Load Diff

View File

@ -26,17 +26,25 @@ class wxCheckBox;
#define LADSPAEFFECTS_VERSION wxT("1.0.0.0");
#define LADSPAEFFECTS_FAMILY L"Ladspa"
///////////////////////////////////////////////////////////////////////////////
//
// LadspaEffect
//
///////////////////////////////////////////////////////////////////////////////
WX_DEFINE_ARRAY_PTR(LADSPA_Handle, LadspaSlaveArray);
class LadspaEffectDialog;
class LadspaEffectEventHelper;
class LadspaEffect : public EffectClientInterface
class LadspaEffect : public EffectClientInterface,
public EffectUIClientInterface
{
public:
LadspaEffect(const wxString & path, int index);
virtual ~LadspaEffect();
// IdentInterface implementation
virtual PluginID GetID();
virtual wxString GetPath();
virtual wxString GetName();
@ -45,17 +53,18 @@ public:
virtual wxString GetDescription();
// EffectIdentInterface implementation
virtual EffectType GetType();
virtual wxString GetFamily();
virtual bool IsInteractive();
virtual bool IsDefault();
virtual bool IsLegacy();
virtual bool IsRealtimeCapable();
virtual bool SupportsRealtime();
virtual bool SupportsAutomation();
// EffectClientInterface implementation
virtual void SetHost(EffectHostInterface *host);
virtual bool Startup();
virtual bool Shutdown();
virtual bool SetHost(EffectHostInterface *host);
virtual int GetAudioInCount();
virtual int GetAudioOutCount();
@ -84,10 +93,34 @@ public:
float **outbuf,
sampleCount numSamples);
virtual bool ShowInterface(void *parent);
virtual bool ShowInterface(wxWindow *parent, bool forceModal = false);
virtual bool GetAutomationParameters(EffectAutomationParameters & parms);
virtual bool SetAutomationParameters(EffectAutomationParameters & parms);
// EffectUIClientInterface implementation
virtual void SetUIHost(EffectUIHostInterface *host);
virtual bool PopulateUI(wxWindow *parent);
virtual bool ValidateUI();
virtual bool HideUI();
virtual bool CloseUI();
virtual void LoadUserPreset(const wxString & name);
virtual void SaveUserPreset(const wxString & name);
virtual void LoadFactoryPreset(int id);
virtual void LoadFactoryDefaults();
virtual wxArrayString GetFactoryPresets();
virtual void ExportPresets();
virtual void ImportPresets();
virtual void ShowOptions();
// LadspaEffect implementation
private:
// LadspaEffect implementation
bool Load();
void Unload();
@ -97,6 +130,14 @@ private:
LADSPA_Handle InitInstance(float sampleRate);
void FreeInstance(LADSPA_Handle handle);
void OnCheckBox(wxCommandEvent & evt);
void OnSlider(wxCommandEvent & evt);
void OnTextCtrl(wxCommandEvent & evt);
void RefreshControls(bool outputOnly = false);
void ConnectFocus(wxControl *c);
void DisconnectFocus(wxControl *c);
void ControlSetFocus(wxFocusEvent & evt);
private:
wxString mPath;
@ -126,6 +167,7 @@ private:
int mNumInputControls;
float *mInputControls;
int mNumOutputControls;
float *mOutputControls;
int mLatencyPort;
@ -135,12 +177,52 @@ private:
LadspaSlaveArray mSlaves;
wxArrayInt mSlaveChannels;
LadspaEffectDialog *mDlg;
EffectUIHostInterface *mUIHost;
LadspaEffectEventHelper *mEventHelper;
friend class LadspaEffectDialog;
NumericTextCtrl *mDuration;
wxDialog *mDialog;
wxWindow *mParent;
wxSlider **mSliders;
wxTextCtrl **mFields;
wxStaticText **mLabels;
wxCheckBox **mToggles;
friend class LadspaEffectEventHelper;
friend class LadspaEffectsModule;
};
///////////////////////////////////////////////////////////////////////////////
//
// LadspaEffectEventHelper
//
///////////////////////////////////////////////////////////////////////////////
class LadspaEffectEventHelper : public wxEvtHandler
{
public:
LadspaEffectEventHelper(LadspaEffect *effect);
virtual ~LadspaEffectEventHelper();
// LadspaEffectEventHelper implementatino
void OnCheckBox(wxCommandEvent & evt);
void OnSlider(wxCommandEvent & evt);
void OnTextCtrl(wxCommandEvent & evt);
void ControlSetFocus(wxFocusEvent & evt);
private:
LadspaEffect *mEffect;
DECLARE_EVENT_TABLE();
};
///////////////////////////////////////////////////////////////////////////////
//
// LadspaEffectsModule
//
///////////////////////////////////////////////////////////////////////////////
class LadspaEffectsModule : public ModuleInterface
{
public:
@ -165,7 +247,8 @@ public:
virtual wxArrayString FindPlugins(PluginManagerInterface & pm);
virtual bool RegisterPlugin(PluginManagerInterface & pm, const wxString & path);
virtual void *CreateInstance(const PluginID & ID, const wxString & path);
virtual IdentInterface *CreateInstance(const PluginID & ID, const wxString & path);
virtual void DeleteInstance(IdentInterface *instance);
// LadspaEffectModule implementation
@ -176,53 +259,3 @@ private:
wxString mPath;
};
class LadspaEffectDialog : public wxDialog
{
DECLARE_DYNAMIC_CLASS(LadspaEffectDialog)
public:
LadspaEffectDialog(LadspaEffect *effect,
wxWindow * parent,
const LADSPA_Descriptor *data,
float *inputControls,
sampleCount sampleRate,
double length);
~LadspaEffectDialog();
double GetLength();
DECLARE_EVENT_TABLE()
private:
void OnCheckBox(wxCommandEvent & evt);
void OnSlider(wxCommandEvent & evt);
void OnTextCtrl(wxCommandEvent & evt);
void OnApply(wxCommandEvent & evt);
void OnOK(wxCommandEvent & evt);
void OnCancel(wxCommandEvent & evt);
void OnPreview(wxCommandEvent & evt);
void OnDefaults(wxCommandEvent & evt);
void HandleText();
void RefreshParaemters();
void ConnectFocus(wxControl *c);
void DisconnectFocus(wxControl *c);
void ControlSetFocus(wxFocusEvent & evt);
private:
bool inSlider;
bool inText;
int mSampleRate;
const LADSPA_Descriptor *mData;
wxSlider **mSliders;
wxTextCtrl **mFields;
wxStaticText **mLabels;
wxCheckBox **mToggles;
unsigned long *mPorts;
unsigned long mNumParams;
float *mInputControls;
LadspaEffect *mEffect;
NumericTextCtrl *mSeconds;
};

View File

@ -104,14 +104,14 @@ void EffectsPrefs::PopulateOrExchange(ShuttleGui & S)
wxArrayString visualgroups;
wxArrayString prefsgroups;
visualgroups.Add(_("Publisher: Effect Name"));
visualgroups.Add(_("Name"));
visualgroups.Add(_("Effect Name"));
visualgroups.Add(_("Publisher"));
visualgroups.Add(_("Publisher: Effect Name"));
visualgroups.Add(_("Type (Internal, Ladspa, VST, etc.)"));
prefsgroups.Add(wxT("default"));
prefsgroups.Add(wxT("name"));
prefsgroups.Add(wxT("publisher"));
prefsgroups.Add(wxT("publisher:name"));
prefsgroups.Add(wxT("family"));
S.TieChoice(_("Group effects in menus by:"),

View File

@ -29,8 +29,8 @@
#if wxUSE_VALIDATORS && wxUSE_TEXTCTRL
#ifndef WX_PRECOMP
#include "wx/msgdlg.h"
#include "wx/textctrl.h"
#include "wx/combobox.h"
#endif
#include "valnum.h"
@ -39,7 +39,7 @@
// ============================================================================
// wxNumValidatorBase implementation
// ============================================================================
BEGIN_EVENT_TABLE(wxNumValidatorBase, wxValidator)
EVT_CHAR(wxNumValidatorBase::OnChar)
EVT_KILL_FOCUS(wxNumValidatorBase::OnKillFocus)
@ -74,6 +74,26 @@ wxTextEntry *wxNumValidatorBase::GetTextEntry() const
return NULL;
}
bool wxNumValidatorBase::Validate(wxWindow *parent)
{
// If window is disabled, simply return
if ( !m_validatorWindow->IsEnabled() )
return true;
wxString errmsg;
bool res = DoValidateNumber(&errmsg);
if ( !res )
{
wxMessageBox(errmsg, _("Validation error"),
wxOK | wxICON_ERROR, parent);
m_validatorWindow->SetFocus();
return false;
}
return true;
}
void
wxNumValidatorBase::GetCurrentValueAndInsertionPoint(wxString& val,
int& pos) const
@ -145,7 +165,9 @@ void wxNumValidatorBase::OnChar(wxKeyEvent& event)
return;
}
#endif // wxUSE_UNICODE/!wxUSE_UNICODE
// Space is an allowed thousands separator. But we don't allow user to type
// it. We will add it at formatting time in OnKillFocus().
if ( c < WXK_SPACE || c == WXK_DELETE )
{
// Allow ASCII control characters and Delete.
@ -188,6 +210,8 @@ void wxNumValidatorBase::OnKillFocus(wxFocusEvent& event)
text->MarkDirty();
event.Skip();
// Validate(text);
}
// ============================================================================
@ -223,26 +247,65 @@ wxIntegerValidatorBase::IsCharOk(const wxString& val, int pos, wxChar ch) const
return m_min < 0 && IsMinusOk(val, pos);
}
// We only accept digits here (remember that '-' is taken care of by the
// base class already).
// A separator is accepted if the locale allow it, the other chars must be digits
if ( ch < '0' || ch > '9' )
return false;
{
wxChar thousands;
if ( wxNumberFormatter::GetThousandsSeparatorIfUsed(&thousands) )
{
if (ch != thousands)
return false;
}
else
{
return false;
}
}
// And the value after insertion needs to be in the defined range.
LongestValueType value;
if ( !FromString(GetValueAfterInsertingChar(val, pos, ch), &value) )
return false;
wxString smin = ToString(m_min);
wxString smax = ToString(m_max);
if ( pos < (int) smin.Length() )
return true;
if ( pos < (int) smax.Length() - 1 )
return true;
return IsInRange(value);
return true;
}
bool wxIntegerValidatorBase::DoValidateNumber(wxString * errMsg) const
{
wxTextEntry * const control = GetTextEntry();
if ( !control )
return false;
wxString s(control->GetValue());
wxChar thousandsSep;
if ( wxNumberFormatter::GetThousandsSeparatorIfUsed(&thousandsSep) )
s.Replace(wxString(thousandsSep), wxString());
if ( s.empty() )
{
// Is blank, but allowed. Stop here
if ( HasFlag(wxNUM_VAL_ZERO_AS_BLANK) )
{
return true;
}
// We can't do any check with an empty string
else
{
*errMsg = _("Empty value");
return false;
}
}
// Can it be converted to a value?
LongestValueType value;
bool res = FromString(s, &value);
if ( !res )
*errMsg = _("Malformed number");
else
{
res = IsInRange(value);
if ( !res )
*errMsg = _("Not in range");
}
return res;
}
// ============================================================================
// wxFloatingPointValidatorBase implementation
// ============================================================================
@ -264,10 +327,27 @@ wxFloatingPointValidatorBase::IsCharOk(const wxString& val,
int pos,
wxChar ch) const
{
// We may accept minus sign if we can represent negative numbers at all.
if ( ch == '-' )
return m_min < 0 && IsMinusOk(val, pos);
{
// We may accept minus sign if we can represent negative numbers at all.
if ( pos == 0 )
return m_min < 0 && IsMinusOk(val, pos);
// or for the exponent definition
else if ( val[pos-1] != 'e' && val[pos-1] != 'E' )
return false;
return true;
}
else if ( ch == '+' )
{
if ( pos == 0 )
return m_max >= 0;
else if ( val[pos-1] != 'e' && val[pos-1] != 'E' )
return false;
return true;
}
const wxChar separator = wxNumberFormatter::GetDecimalSeparator();
if ( ch == separator )
{
@ -277,8 +357,8 @@ wxFloatingPointValidatorBase::IsCharOk(const wxString& val,
return false;
}
// Prepending a separator before the minus sign isn't allowed.
if ( pos == 0 && !val.empty() && val[0] == '-' )
// Prepending a separator before the sign isn't allowed.
if ( pos == 0 && !val.empty() && ( val[0] == '-' || val[0] == '+' ) )
return false;
// Otherwise always accept it, adding a decimal separator doesn't
@ -289,24 +369,83 @@ wxFloatingPointValidatorBase::IsCharOk(const wxString& val,
return true;
}
// Must be a digit then.
if ( ch < '0' || ch > '9' )
return false;
// Must be a digit, an exponent or a thousands separator.
if( ( ch < '0' || ch > '9' ) && ch != 'E' && ch != 'e' )
{
wxChar thousands;
if ( wxNumberFormatter::GetThousandsSeparatorIfUsed(&thousands) )
{
if (ch != thousands)
return false;
}
else
{
return false;
}
}
// Check the number of decimal digits in the final string
wxString str(val);
str.insert(pos, ch);
return ValidatePrecision(str);
}
// Check whether the value we'd obtain if we accepted this key is correct.
const wxString newval(GetValueAfterInsertingChar(val, pos, ch));
LongestValueType value;
if ( !FromString(newval, &value) )
return false;
// Also check that it doesn't have too many decimal digits.
const size_t posSep = newval.find(separator);
if ( posSep != wxString::npos && newval.length() - posSep - 1 > m_precision )
return false;
// Finally check whether it is in the range.
return IsInRange(value);
}
bool wxFloatingPointValidatorBase::DoValidateNumber(wxString * errMsg) const
{
wxTextEntry * const control = GetTextEntry();
if ( !control )
return false;
wxString s(control->GetValue());
wxChar thousandsSep;
if ( wxNumberFormatter::GetThousandsSeparatorIfUsed(&thousandsSep) )
s.Replace(wxString(thousandsSep), wxString());
if ( s.empty() )
{
if ( HasFlag(wxNUM_VAL_ZERO_AS_BLANK) )
return true; //Is blank, but allowed. Stop here
else
{
*errMsg = _("Empty value");
return false; //We can't do any checks with an empty string
}
}
LongestValueType value;
bool res = FromString(s, &value); // Can it be converted to a value?
if ( !res )
*errMsg = _("Value overflow");
else
{
res = ValidatePrecision(s);
if ( !res )
*errMsg = _("Too meany decimal digits");
else
{
res = IsInRange(value);
if ( !res )
*errMsg = _("Not in range");
}
}
return res;
}
bool wxFloatingPointValidatorBase::ValidatePrecision(const wxString& s) const
{
size_t posSep = s.find(wxNumberFormatter::GetDecimalSeparator());
if ( posSep == wxString::npos )
posSep = s.length();
// If user typed exponent 'e' the number of decimal digits is not
// important at all. But we must know that 'e' position.
size_t posExp = s.Lower().Find(_("e"));
if ( posExp == wxString::npos )
posExp = s.length();
// Return true if number has no more decimal digits than allowed
return ( (int)(posExp - posSep) - 1 <= (int)m_precision );
}
#endif // wxUSE_VALIDATORS && wxUSE_TEXTCTRL

View File

@ -43,10 +43,9 @@ public:
// Change the validator style. Usually it's specified during construction.
void SetStyle(int style) { m_style = style; }
// Override base class method to not do anything but always return success:
// we don't need this as we do our validation on the fly here.
virtual bool Validate(wxWindow * WXUNUSED(parent)) { return true; }
// Called when the value in the window must be validated.
// This function can pop up an error message.
virtual bool Validate(wxWindow * parent);
protected:
wxNumValidatorBase(int style)
@ -98,12 +97,16 @@ private:
// NormalizeString the contents of the string if it's a valid number, return
// empty string otherwise.
virtual wxString NormalizeString(const wxString& s) const = 0;
// Do all checks to ensure this is a valid value.
// Returns 'true' if the control has valid value.
// Otherwise the cause is indicated in 'errMsg'.
virtual bool DoValidateNumber(wxString * errMsg) const = 0;
// Event handlers.
void OnChar(wxKeyEvent& event);
void OnKillFocus(wxFocusEvent& event);
// Determine the current insertion point and text in the associated control.
void GetCurrentValueAndInsertionPoint(wxString& val, int& pos) const;
@ -297,6 +300,7 @@ protected:
// Implement wxNumValidatorBase pure virtual method.
virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const;
virtual bool DoValidateNumber(wxString * errMsg) const;
private:
// Minimal and maximal values accepted (inclusive).
@ -392,6 +396,10 @@ protected:
// Implement wxNumValidatorBase pure virtual method.
virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const;
virtual bool DoValidateNumber(wxString * errMsg) const;
//Checks that it doesn't have too many decimal digits.
bool ValidatePrecision(const wxString& s) const;
private:
// Maximum number of decimals digits after the decimal separator.

File diff suppressed because it is too large Load Diff

View File

@ -831,9 +831,7 @@
<ClCompile Include="..\..\..\src\widgets\NumericTextCtrl.cpp">
<Filter>src/widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\effects\NoiseReduction.cpp">
<Filter>src/effects</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\effects\NoiseReduction.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\AboutDialog.h">
@ -1655,8 +1653,9 @@
<ClInclude Include="..\..\..\src\widgets\NumericTextCtrl.h">
<Filter>src/widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\effects\NoiseReduction.h">
<Filter>src/effects</Filter>
<ClInclude Include="..\..\..\src\effects\NoiseReduction.h" />
<ClInclude Include="..\..\..\include\audacity\EffectAutomationParameters.h">
<Filter>includes\audacity</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>