1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-10-20 17:41:13 +02:00

New library for components

This commit is contained in:
Paul Licameli
2021-02-25 20:52:08 -05:00
parent dd87ec0fbd
commit 54b5f7d12c
55 changed files with 232 additions and 133 deletions

View File

@@ -7,6 +7,7 @@ set( LIBRARIES
lib-strings
lib-utility
lib-uuid
lib-components
)
if ( ${_OPT}has_networking )

View File

@@ -0,0 +1,29 @@
#[[
Various abstract base classes related to modules and plugins.
ComponentInterfaceSymbol, which pairs an internal identifier string (suitable
for storing as a configuration file value) with a user-visible translatable
string. It serves to "name" various things.
CommandParameters, for write and reading key-value pairs to and from strings.
]]#
list( APPEND SOURCES
ComponentInterface.cpp
ComponentInterface.h
ComponentInterfaceSymbol.h
ConfigInterface.cpp
ConfigInterface.h
EffectAutomationParameters.cpp
EffectAutomationParameters.h
EffectInterface.cpp
EffectInterface.h
ModuleInterface.cpp
ModuleInterface.h
PluginInterface.cpp
PluginInterface.h
)
audacity_library( lib-components "${SOURCES}"
"lib-strings-interface;PRIVATE;wxBase"
"" ""
)

View File

@@ -0,0 +1,10 @@
/**********************************************************************
Audacity: A Digital Audio Editor
@file ComponentInterface.cpp
**********************************************************************/
#include "ComponentInterface.h"
ComponentInterface::~ComponentInterface() = default;

View File

@@ -0,0 +1,88 @@
/**********************************************************************
Audacity: A Digital Audio Editor
ComponentInterface.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_COMPONENT_INTERFACE_H__
#define __AUDACITY_COMPONENT_INTERFACE_H__
#include "Identifier.h"
#include "Internat.h"
#include <wx/string.h> // member variables
class ComponentInterfaceSymbol;
using VendorSymbol = ComponentInterfaceSymbol;
class ShuttleParams;
/**************************************************************************//**
\brief ComponentInterface provides name / vendor / version functions to identify
plugins. It is what makes a class a plug-in. Additionally it provides an
optional parameter definitions function, for those components such as commands,
effects and (soon) preference pagess that define parameters.
********************************************************************************/
class COMPONENTS_API ComponentInterface /* not final */
{
public:
virtual ~ComponentInterface();
// These should return an untranslated value
virtual PluginPath GetPath() = 0;
// The internal string persists in configuration files
// So config compatibility will break if it is changed across Audacity versions
virtual ComponentInterfaceSymbol GetSymbol() = 0;
virtual VendorSymbol GetVendor() = 0;
virtual wxString GetVersion() = 0;
// This returns a translated string
// Any verb should be present tense indicative, not imperative
virtual TranslatableString GetDescription() = 0;
// non-virtual convenience function
TranslatableString GetName();
// Parameters, if defined. false means no defined parameters.
virtual bool DefineParams( ShuttleParams & WXUNUSED(S) ){ return false;};
};
#endif // __AUDACITY_IDENTINTERFACE_H__

View File

@@ -0,0 +1,82 @@
/**********************************************************************
Audacity: A Digital Audio Editor
@file ComponentInterfaceSymbol.h
Paul Licameli split from ComponentInterface.h
**********************************************************************/
#ifndef __AUDACITY_COMPONENT_INTERFACE_SYMBOL__
#define __AUDACITY_COMPONENT_INTERFACE_SYMBOL__
#include "Identifier.h"
#include "Internat.h"
/**************************************************************************//**
\brief ComponentInterfaceSymbol pairs a persistent string identifier used internally
with an optional, different string as msgid for lookup in a translation catalog.
\details If there is need to change a msgid in a later version of the
program, change the constructor call to supply a second argument but leave the
first the same, so that compatibility of older configuration files containing
that internal string is not broken.
********************************************************************************/
class ComponentInterfaceSymbol
{
public:
ComponentInterfaceSymbol() = default;
// Allows implicit construction from a msgid re-used as an internal string
ComponentInterfaceSymbol( const TranslatableString &msgid )
: mInternal{ msgid.MSGID().GET(), }, mMsgid{ msgid }
{}
// Allows implicit construction from an internal string re-used as a msgid
ComponentInterfaceSymbol( const wxString &internal )
: mInternal{ internal }, mMsgid{ internal, {} }
{}
// Allows implicit construction from an internal string re-used as a msgid
ComponentInterfaceSymbol( const wxChar *msgid )
: mInternal{ msgid }, mMsgid{ msgid, {} }
{}
// Two-argument version distinguishes internal from translatable string
// such as when the first squeezes spaces out
ComponentInterfaceSymbol( const Identifier &internal,
const TranslatableString &msgid )
: mInternal{ internal.GET() }
// Do not permit non-empty msgid with empty internal
, mMsgid{ internal.empty() ? TranslatableString{} : msgid }
{}
const wxString &Internal() const { return mInternal; }
const TranslatableString &Msgid() const { return mMsgid; }
const TranslatableString Stripped() const { return mMsgid.Stripped(); }
const wxString Translation() const { return mMsgid.Translation(); }
const wxString StrippedTranslation() const
{ return Stripped().Translation(); }
bool empty() const { return mInternal.empty(); }
friend inline bool operator == (
const ComponentInterfaceSymbol &a, const ComponentInterfaceSymbol &b )
{ return a.mInternal == b.mInternal; }
friend inline bool operator != (
const ComponentInterfaceSymbol &a, const ComponentInterfaceSymbol &b )
{ return !( a == b ); }
private:
wxString mInternal;
TranslatableString mMsgid;
};
// TODO: real type distinctions for these aliases, and move them elsewhere
using EnumValueSymbol = ComponentInterfaceSymbol;
using NumericFormatSymbol = EnumValueSymbol;
using EffectFamilySymbol = ComponentInterfaceSymbol;
#endif

View File

@@ -0,0 +1,10 @@
/**********************************************************************
Audacity: A Digital Audio Editor
@file ConfigInterface.cpp
**********************************************************************/
#include "ConfigInterface.h"
ConfigClientInterface::~ConfigClientInterface() = default;

View File

@@ -0,0 +1,99 @@
/**********************************************************************
Audacity: A Digital Audio Editor
ConfigInterface.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_CONFIGINTERFACE_H__
#define __AUDACITY_CONFIGINTERFACE_H__
#include "Identifier.h"
#include <vector>
/*************************************************************************************//**
\class ConfigClientInterface
\brief ConfigClientInterface is an unholy get/set configuration class, which
differentiates between private and shared config. It should probably be replaced
with a Shuttle.
*******************************************************************************************/
class COMPONENTS_API ConfigClientInterface /* not final */
{
public:
virtual ~ConfigClientInterface();
virtual bool HasSharedConfigGroup(const RegistryPath & group) = 0;
virtual bool GetSharedConfigSubgroups(const RegistryPath & group, RegistryPaths & subgroups) = 0;
virtual bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, wxString & value, const wxString & defval) = 0;
virtual bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, int & value, int defval) = 0;
virtual bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, bool & value, bool defval) = 0;
virtual bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, float & value, float defval) = 0;
virtual bool GetSharedConfig(const RegistryPath & group, const RegistryPath & key, double & value, double defval) = 0;
virtual bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const wxString & value) = 0;
virtual bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const int & value) = 0;
virtual bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const bool & value) = 0;
virtual bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const float & value) = 0;
virtual bool SetSharedConfig(const RegistryPath & group, const RegistryPath & key, const double & value) = 0;
virtual bool RemoveSharedConfigSubgroup(const RegistryPath & group) = 0;
virtual bool RemoveSharedConfig(const RegistryPath & group, const RegistryPath & key) = 0;
virtual bool HasPrivateConfigGroup(const RegistryPath & group) = 0;
virtual bool GetPrivateConfigSubgroups(const RegistryPath & group, RegistryPaths &subgroups) = 0;
virtual bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, wxString & value, const wxString & defval) = 0;
virtual bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, int & value, int defval) = 0;
virtual bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, bool & value, bool defval) = 0;
virtual bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, float & value, float defval) = 0;
virtual bool GetPrivateConfig(const RegistryPath & group, const RegistryPath & key, double & value, double defval) = 0;
virtual bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const wxString & value) = 0;
virtual bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const int & value) = 0;
virtual bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const bool & value) = 0;
virtual bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const float & value) = 0;
virtual bool SetPrivateConfig(const RegistryPath & group, const RegistryPath & key, const double & value) = 0;
virtual bool RemovePrivateConfigSubgroup(const RegistryPath & group) = 0;
virtual bool RemovePrivateConfig(const RegistryPath & group, const RegistryPath & key) = 0;
};
#endif // __AUDACITY_CONFIGINTERFACE_H__

View File

@@ -0,0 +1,10 @@
/**********************************************************************
Audacity: A Digital Audio Editor
@file EffectAutomationParameters.cpp
**********************************************************************/
#include "EffectAutomationParameters.h"
CommandParameters::~CommandParameters() = default;

View File

@@ -0,0 +1,339 @@
/**********************************************************************
Audacity: A Digital Audio Editor
EffectAutomationParameters.h
(defining CommandParameters)
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_COMMAND_PARAMETERS_H__
#define __AUDACITY_COMMAND_PARAMETERS_H__
#include <locale.h>
#include <wx/cmdline.h> // for wxCmdLineParser::ConvertStringToArgs
#include <wx/fileconf.h> // to inherit
#include <algorithm>
#include "ComponentInterface.h"
#include "ComponentInterfaceSymbol.h"
/**
\brief CommandParameters, derived from wxFileConfig, is essentially doing
the same things as the Shuttle classes. It does text <-> binary conversions of
parameters. It does not seem to be using actual file read/writing.
Should it be converted to using Shuttle? Probably yes. Shuttle leads to shorter code.
And Shuttle is more multi-functional since Shuttle can report on signature, do the work of
wxWidget validators, and can create default dialogs. However until that conversion is
done, we need this class, and we use a pointer to one from within a Shuttle when interfacing
with the code that still uses it.
*/
class COMPONENTS_API CommandParameters final : public wxFileConfig
{
public:
CommandParameters(const wxString & parms = {})
: wxFileConfig(wxEmptyString,
wxEmptyString,
wxEmptyString,
wxEmptyString,
0)
{
SetExpandEnvVars(false);
SetParameters(parms);
}
virtual ~CommandParameters();
virtual bool HasGroup(const wxString & strName) const override
{
return wxFileConfig::HasGroup(NormalizeName(strName));
}
virtual bool HasEntry(const wxString& strName) const override
{
return wxFileConfig::HasEntry(NormalizeName(strName));
}
virtual bool DoReadString(const wxString & key, wxString *pStr) const override
{
return wxFileConfig::DoReadString(NormalizeName(key), pStr);
}
virtual bool DoReadLong(const wxString & key, long *pl) const override
{
return wxFileConfig::DoReadLong(NormalizeName(key), pl);
}
virtual bool DoReadDouble(const wxString & key, double *pd) const override
{
wxString str;
if (Read(key, &str))
{
struct lconv *info = localeconv();
wxString dec =
info ? wxString::FromUTF8(info->decimal_point) : wxString(".");
str.Replace(wxT(","), dec);
str.Replace(wxT("."), dec);
return str.ToDouble(pd);
}
return false;
}
virtual bool DoWriteString(const wxString & key, const wxString & szValue) override
{
return wxFileConfig::DoWriteString(NormalizeName(key), szValue);
}
virtual bool DoWriteLong(const wxString & key, long lValue) override
{
return wxFileConfig::DoWriteLong(NormalizeName(key), lValue);
}
virtual bool DoWriteDouble(const wxString & key, double value) override
{
return DoWriteString(key, wxString::Format(wxT("%.8g"), value));
}
bool ReadFloat(const wxString & key, float *pf) const
{
double d = *pf;
bool success = Read(key, &d);
if (success)
{
*pf = (float) d;
}
return success;
}
bool ReadFloat(const wxString & key, float *pf, float defVal) const
{
if (!ReadFloat(key, pf))
{
*pf = defVal;
}
return true;
}
bool WriteFloat(const wxString & key, float f)
{
return Write(key, f);
}
// For reading old config files with enumeration names that have been
// changed in later versions. Pair a string with an index into the other
// list of non-obsolete names.
using ObsoleteMap = std::pair< wxString, size_t >;
bool ReadEnum(const wxString & key, int *pi,
const EnumValueSymbol choices[], size_t nChoices,
const ObsoleteMap obsoletes[] = nullptr,
size_t nObsoletes = 0) const
{
wxString s;
if (!wxFileConfig::Read(key, &s))
{
return false;
}
*pi = std::find( choices, choices + nChoices,
EnumValueSymbol{ s, {} } ) - choices;
if (*pi == (int)nChoices)
*pi = -1;
if (*pi < 0 && obsoletes) {
auto index = std::find_if(obsoletes, obsoletes + nObsoletes,
[&](const ObsoleteMap &entry){
return entry.first == s; })
- obsoletes;
if (index < (int)nObsoletes)
*pi = (int)obsoletes[index].second;
}
return true;
}
bool ReadEnum(const wxString & key, int *pi, int defVal,
const EnumValueSymbol choices[], size_t nChoices,
const ObsoleteMap obsoletes[] = nullptr,
size_t nObsoletes = 0) const
{
if (!ReadEnum(key, pi, choices, nChoices, obsoletes, nObsoletes))
{
*pi = defVal;
}
return true;
}
bool WriteEnum(const wxString & key, int value,
const EnumValueSymbol choices[], size_t nChoices)
{
if (value < 0 || value >= (int)nChoices)
{
return false;
}
return wxFileConfig::Write(key, choices[value].Internal());
}
bool ReadAndVerify(const wxString & key, float *val, float defVal, float min, float max) const
{
ReadFloat(key, val, defVal);
return (*val >= min && *val <= max);
}
bool ReadAndVerify(const wxString & key, double *val, double defVal, double min, double max) const
{
Read(key, val, defVal);
return (*val >= min && *val <= max);
}
bool ReadAndVerify(const wxString & key, int *val, int defVal, int min, int max) const
{
Read(key, val, defVal);
return (*val >= min && *val <= max);
}
bool ReadAndVerify(const wxString & key, long *val, long defVal, long min, long max) const
{
Read(key, val, defVal);
return (*val >= min && *val <= max);
}
bool ReadAndVerify(const wxString & key, bool *val, bool defVal) const
{
Read(key, val, defVal);
return true;
}
bool ReadAndVerify(const wxString & key, wxString *val, const wxString & defVal) const
{
Read(key, val, defVal);
return true;
}
bool ReadAndVerify(const wxString & key, int *val, int defVal,
const EnumValueSymbol choices[], size_t nChoices,
const ObsoleteMap obsoletes[] = nullptr,
size_t nObsoletes = 0) const
{
ReadEnum(key, val, defVal, choices, nChoices, obsoletes, nObsoletes);
return (*val != wxNOT_FOUND);
}
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("=\"") + Escape(val) + wxT("\" ");
res = wxFileConfig::GetNextEntry(key, ndx);
}
str.Trim();
parms = str;
return true;
}
bool SetParameters(const wxString & parms)
{
wxFileConfig::SetPath(wxT("/"));
auto parsed = wxCmdLineParser::ConvertStringToArgs(parms);
for (size_t i = 0, cnt = parsed.size(); 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, Unescape(val)))
{
return false;
}
}
return true;
}
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("_"));
cleaned.Replace(wxT("="), wxT("_"));
return cleaned;
}
wxString Escape(wxString val)
{
val.Replace(wxT("\\"), wxT("\\\\"), true);
val.Replace(wxT("\""), wxT("\\\""), true);
val.Replace(wxT("\n"), wxT("\\n"), true);
return val;
}
wxString Unescape(wxString val)
{
val.Replace(wxT("\\n"), wxT("\n"), true);
val.Replace(wxT("\\\""), wxT("\""), true);
val.Replace(wxT("\\\\"), wxT("\\"), true);
return val;
}
};
#endif

View File

@@ -0,0 +1,18 @@
/**********************************************************************
Audacity: A Digital Audio Editor
@file EffectInterface.cpp
**********************************************************************/
#include "EffectInterface.h"
EffectDefinitionInterface::~EffectDefinitionInterface() = default;
EffectHostInterface::~EffectHostInterface() = default;
EffectClientInterface::~EffectClientInterface() = default;
EffectUIHostInterface::~EffectUIHostInterface() = default;
EffectUIClientInterface::~EffectUIClientInterface() = default;

View File

@@ -0,0 +1,290 @@
/**********************************************************************
Audacity: A Digital Audio Editor
EffectInterface.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_EFFECTINTERFACE_H__
#define __AUDACITY_EFFECTINTERFACE_H__
#include <functional>
#include "ComponentInterface.h"
#include "ComponentInterfaceSymbol.h"
#include "ConfigInterface.h"
#include "EffectAutomationParameters.h" // for command automation
class ShuttleGui;
typedef enum EffectType : int
{
EffectTypeNone,
EffectTypeHidden,
EffectTypeGenerate,
EffectTypeProcess,
EffectTypeAnalyze,
EffectTypeTool,
} EffectType;
using EffectFamilySymbol = ComponentInterfaceSymbol;
/*************************************************************************************//**
\class EffectDefinitionInterface
\brief EffectDefinitionInterface is a ComponentInterface that additionally tracks
flag-functions for interactivity, play-preview and whether the effect can run without a GUI.
*******************************************************************************************/
class COMPONENTS_API EffectDefinitionInterface /* not final */ : public ComponentInterface
{
public:
virtual ~EffectDefinitionInterface();
// Type determines how it behaves.
virtual EffectType GetType() = 0;
// Classification determines which menu it appears in.
virtual EffectType GetClassification() { return GetType();}
virtual EffectFamilySymbol GetFamily() = 0;
// These should move to the "EffectClientInterface" class once all
// 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
// effect to appear "above the line" in the menus.
virtual bool IsDefault() = 0;
// This will go away when all Effects have been updated to the new
// interface.
virtual bool IsLegacy() = 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 wxDialog;
class wxWindow;
class EffectUIHostInterface;
class EffectUIClientInterface;
/*************************************************************************************//**
\class EffectHostInterface
\brief EffectHostInterface is a decorator of a EffectUIClientInterface. It adds
virtual (abstract) functions to get presets and actually apply the effect. It uses
ConfigClientInterface to add Getters/setters for private and shared configs.
*******************************************************************************************/
class COMPONENTS_API EffectHostInterface /* not final */ : public ConfigClientInterface
{
public:
virtual ~EffectHostInterface();
virtual double GetDefaultDuration() = 0;
virtual double GetDuration() = 0;
virtual NumericFormatSymbol GetDurationFormat() = 0;
virtual void SetDuration(double seconds) = 0;
// Preset handling
virtual RegistryPath GetUserPresetsGroup(const RegistryPath & name) = 0;
virtual RegistryPath GetCurrentSettingsGroup() = 0;
virtual RegistryPath GetFactoryDefaultsGroup() = 0;
};
class sampleCount;
// ----------------------------------------------------------------------------
// Supported channel assignments
// ----------------------------------------------------------------------------
typedef enum
{
// Use to mark end of list
ChannelNameEOL = -1,
// The default channel assignment
ChannelNameMono,
// From this point, the channels follow the 22.2 surround sound format
ChannelNameFrontLeft,
ChannelNameFrontRight,
ChannelNameFrontCenter,
ChannelNameLowFrequency1,
ChannelNameBackLeft,
ChannelNameBackRight,
ChannelNameFrontLeftCenter,
ChannelNameFrontRightCenter,
ChannelNameBackCenter,
ChannelNameLowFrequency2,
ChannelNameSideLeft,
ChannelNameSideRight,
ChannelNameTopFrontLeft,
ChannelNameTopFrontRight,
ChannelNameTopFrontCenter,
ChannelNameTopCenter,
ChannelNameTopBackLeft,
ChannelNameTopBackRight,
ChannelNameTopSideLeft,
ChannelNameTopSideRight,
ChannelNameTopBackCenter,
ChannelNameBottomFrontCenter,
ChannelNameBottomFrontLeft,
ChannelNameBottomFrontRight,
} ChannelName, *ChannelNames;
/*************************************************************************************//**
\class EffectClientInterface
\brief EffectClientInterface provides the ident interface to Effect, and is what makes
Effect into a plug-in command. It has functions for realtime that are not part of
AudacityCommand.
*******************************************************************************************/
class COMPONENTS_API EffectClientInterface /* not final */ : public EffectDefinitionInterface
{
public:
using EffectDialogFactory = std::function<
wxDialog* ( wxWindow &parent,
EffectHostInterface*, EffectUIClientInterface* )
>;
virtual ~EffectClientInterface();
virtual bool SetHost(EffectHostInterface *host) = 0;
virtual unsigned GetAudioInCount() = 0;
virtual unsigned GetAudioOutCount() = 0;
virtual int GetMidiInCount() = 0;
virtual int GetMidiOutCount() = 0;
virtual void SetSampleRate(double rate) = 0;
// Suggest a block size, but the return is the size that was really set:
virtual size_t SetBlockSize(size_t maxBlockSize) = 0;
virtual size_t GetBlockSize() const = 0;
virtual sampleCount GetLatency() = 0;
virtual size_t GetTailSize() = 0;
virtual bool IsReady() = 0;
virtual bool ProcessInitialize(sampleCount totalLen, ChannelNames chanMap = NULL) = 0;
// This may be called during stack unwinding:
virtual bool ProcessFinalize() /* noexcept */ = 0;
virtual size_t ProcessBlock(float **inBlock, float **outBlock, size_t blockLen) = 0;
virtual bool RealtimeInitialize() = 0;
virtual bool RealtimeAddProcessor(unsigned numChannels, float sampleRate) = 0;
virtual bool RealtimeFinalize() = 0;
virtual bool RealtimeSuspend() = 0;
virtual bool RealtimeResume() = 0;
virtual bool RealtimeProcessStart() = 0;
virtual size_t RealtimeProcess(int group, float **inBuf, float **outBuf, size_t numSamples) = 0;
virtual bool RealtimeProcessEnd() = 0;
virtual bool ShowInterface(
wxWindow &parent, const EffectDialogFactory &factory,
bool forceModal = false
) = 0;
// Some effects will use define params to define what parameters they take.
// If they do, they won't need to implement Get or SetAutomation parameters.
// since the Effect class can do it. Or at least that is how things happen
// in AudacityCommand. IF we do the same in class Effect, then Effect maybe
// should derive by some route from AudacityCommand to pick up that
// functionality.
//virtual bool DefineParams( ShuttleParams & S){ return false;};
virtual bool GetAutomationParameters(CommandParameters & parms) = 0;
virtual bool SetAutomationParameters(CommandParameters & parms) = 0;
virtual bool LoadUserPreset(const RegistryPath & name) = 0;
virtual bool SaveUserPreset(const RegistryPath & name) = 0;
virtual RegistryPaths GetFactoryPresets() = 0;
virtual bool LoadFactoryPreset(int id) = 0;
virtual bool LoadFactoryDefaults() = 0;
};
/*************************************************************************************//**
\class EffectUIHostInterface
\brief EffectUIHostInterface has nothing in it. It is provided so that an Effect
can call SetHostUI passing in a pointer to an EffectUIHostInterface. It contains no
functionality and is provided, apparently, for type checking. Since only EffectUIHost
uses it, EffectUIHost could be used instead.
*******************************************************************************************/
class COMPONENTS_API EffectUIHostInterface
{
public:
virtual ~EffectUIHostInterface();
};
/*************************************************************************************//**
\class EffectUIClientInterface
\brief EffectUIClientInterface is an abstract base class to populate a UI and validate UI
values. It can import and export presets.
*******************************************************************************************/
class COMPONENTS_API EffectUIClientInterface /* not final */
{
public:
virtual ~EffectUIClientInterface();
virtual void SetHostUI(EffectUIHostInterface *host) = 0;
virtual bool IsGraphicalUI() = 0;
virtual bool PopulateUI(ShuttleGui &S) = 0;
virtual bool ValidateUI() = 0;
virtual bool HideUI() = 0;
virtual bool CloseUI() = 0;
virtual bool CanExportPresets() = 0;
virtual void ExportPresets() = 0;
virtual void ImportPresets() = 0;
virtual bool HasOptions() = 0;
virtual void ShowOptions() = 0;
};
#endif // __AUDACITY_EFFECTINTERFACE_H__

View File

@@ -0,0 +1,10 @@
/**********************************************************************
Audacity: A Digital Audio Editor
@file ModuleInterface.cpp
**********************************************************************/
#include "ModuleInterface.h"
ModuleInterface::~ModuleInterface() = default;

View File

@@ -0,0 +1,182 @@
/**********************************************************************
Audacity: A Digital Audio Editor
ModuleInterface.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_MODULEINTERFACE_H__
#define __AUDACITY_MODULEINTERFACE_H__
#include <functional>
#include <memory>
#include "Identifier.h"
#include "ComponentInterface.h"
#include "PluginInterface.h"
// ============================================================================
//
// Don't even think about adding module types, like effect, importer, etc. in
// here. The module interface should not have to change when new types of
// plugins are added to Audacity.
//
// In addition a single module may want to provide multiple plugin types.
// ============================================================================
// ============================================================================
///
/// ModuleInterface is a generic dll or so interface for Audacity, that is
/// used for plug ins. Classes derived from it can handle more specific plug
/// in types.
///
// ============================================================================
class COMPONENTS_API ModuleInterface /* not final */
: public ComponentInterface
{
public:
virtual ~ModuleInterface();
// Called immediately after creation to give the instance a chance to
// initialize. Return "true" if initialziation was successful.
virtual bool Initialize() = 0;
// Called just prior to deletion to allow releasing any resources.
virtual void Terminate() = 0;
// A symbol identifying the family of plugin provided by this module;
// if it is not empty, then the family as a whole can be enabled or
// disabled by the user in Preferences
virtual EffectFamilySymbol GetOptionalFamilySymbol() = 0;
// "Paths" returned by FindPluginPaths() and passed back to
// DiscoverPluginsAtPath() have module-specific meaning.
// They are not necessarily file system paths to existent files that
// could be placed in any folder and queried for
// plugin information.
// This function returns nonempty only when that is the case, and lists
// the possible extensions of such files (an empty string in a nonempty
// array means any file is a candidate).
virtual const FileExtensions &GetFileExtensions() = 0;
// Returns empty, or else, where to copy a plug-in file or bundle.
// Drag-and-drop is supported only if GetFileExtensions() returns nonempty and
// this function returns nonempty.
virtual FilePath InstallPath() = 0;
// Modules providing a single or static set of plugins may use
// AutoRegisterPlugins() to register those plugins.
virtual bool AutoRegisterPlugins(PluginManagerInterface & pluginManager) = 0;
// For modules providing an interface to other dynamically loaded plugins,
// the module returns a list of path names that will be presented to the
// user as "New" for enablement.
virtual PluginPaths FindPluginPaths(PluginManagerInterface & pluginManager) = 0;
// Once the user selects desired paths from FindPluginPaths(),
// a call to DiscoverPluginsAtPath()
// will be made to request registration of one or more plugins. If the module must create
// an instance of the plugin to register it, then the instance should be deleted
// after registration.
// May discover more than one plug-in at the path, and
// may call-back with paths not equal to path (perhaps appending
// other information to it).
// Error message does not need to mention the path and may be nonempty
// even if some plugins are also discovered successfully.
// Return value is the number of plugins found.
using RegistrationCallback =
std::function<
const PluginID &(ModuleInterface *, ComponentInterface *) >;
virtual unsigned DiscoverPluginsAtPath(
const PluginPath & path, TranslatableString &errMsg,
const RegistrationCallback &callback )
= 0;
// For modules providing an interface to other dynamically loaded plugins,
// the module returns true if the plugin is still valid, otherwise false.
virtual bool IsPluginValid(const PluginPath & path, bool bFast) = 0;
// When appropriate, CreateInstance() will be called to instantiate the plugin.
virtual std::unique_ptr<ComponentInterface>
CreateInstance(const PluginPath & path) = 0;
};
// ----------------------------------------------------------------------------
// Since there may be multiple embedded modules, the module entry function will
// be declared static so as not to interfere with other modules during link.
// ----------------------------------------------------------------------------
#define DECLARE_MODULE_ENTRY(name) \
static ModuleInterface * name()
// ----------------------------------------------------------------------------
// This will create a class and instance that will register the module entry
// point during Audacity startup. At the appropriate time, the entry point
// will be called to create the module instance.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Provides the base for embedded module registration. If used, a Register()
// method must be supplied explicitly.
// ----------------------------------------------------------------------------
#define DECLARE_BUILTIN_MODULE_BASE(name) \
class name \
{ \
public: \
name() {Register();} \
~name() {Unregister();} \
void Register(); \
void Unregister(); \
}; \
static name name ## _instance;
// ----------------------------------------------------------------------------
// Provides the full embedded module registration process. Nothing further is
// required (other than supplying the module entry point function).
// ----------------------------------------------------------------------------
#define DECLARE_BUILTIN_MODULE(name) \
DECLARE_BUILTIN_MODULE_BASE(name) \
void name::Register() \
{ \
RegisterProvider(AudacityModule); \
} \
void name::Unregister() \
{ \
UnregisterProvider(AudacityModule); \
}
#endif // __AUDACITY_MODULEINTERFACE_H__

View File

@@ -0,0 +1,10 @@
/**********************************************************************
Audacity: A Digital Audio Editor
@file PluginInterface.cpp
**********************************************************************/
#include "PluginInterface.h"
PluginManagerInterface::~PluginManagerInterface() = default;

View File

@@ -0,0 +1,118 @@
/**********************************************************************
Audacity: A Digital Audio Editor
PluginInterface.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_PLUGININTERFACE_H__
#define __AUDACITY_PLUGININTERFACE_H__
#include "ConfigInterface.h"
#include "EffectInterface.h"
#include "ComponentInterface.h"
#include "Identifier.h"
class ModuleInterface;
using PluginID = wxString;
using PluginIDs = wxArrayString;
class COMPONENTS_API PluginManagerInterface /* not final */
{
public:
virtual ~PluginManagerInterface();
static const PluginID &DefaultRegistrationCallback(
ModuleInterface *provider, ComponentInterface *ident );
static const PluginID &AudacityCommandRegistrationCallback(
ModuleInterface *provider, ComponentInterface *ident );
//! Was the plugin registry already populated for a path (maybe from loading the config file)?
/*!
@param path an identifier for the plug-in with meaning defined by provider; not always a file path
@param pName if supplied, a correction for the user visible name associated with the plug-in, if it is
registered already. (Needed because the configuration file only stores an internal name.)
*/
virtual bool IsPluginRegistered(
const PluginPath & path,
const TranslatableString *pName = nullptr) = 0;
virtual const PluginID & RegisterPlugin(ModuleInterface *module) = 0;
virtual const PluginID & RegisterPlugin(ModuleInterface *provider, EffectDefinitionInterface *effect, int type) = 0;
virtual void FindFilesInPathList(const wxString & pattern,
const FilePaths & pathList,
FilePaths & files,
bool directories = false) = 0;
virtual bool GetSharedConfigSubgroups(const PluginID & ID, const RegistryPath & group, RegistryPaths & subgroups) = 0;
virtual bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, wxString & value, const wxString & defval = wxString()) = 0;
virtual bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, int & value, int defval = 0) = 0;
virtual bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, bool & value, bool defval = false) = 0;
virtual bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, float & value, float defval = 0.0) = 0;
virtual bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, double & value, double defval = 0.0) = 0;
virtual bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const wxString & value) = 0;
virtual bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const int & value) = 0;
virtual bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const bool & value) = 0;
virtual bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const float & value) = 0;
virtual bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const double & value) = 0;
virtual bool RemoveSharedConfigSubgroup(const PluginID & ID, const RegistryPath & group) = 0;
virtual bool RemoveSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key) = 0;
virtual bool GetPrivateConfigSubgroups(const PluginID & ID, const RegistryPath & group, RegistryPaths & subgroups) = 0;
virtual bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, wxString & value, const wxString & defval = wxString()) = 0;
virtual bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, int & value, int defval = 0) = 0;
virtual bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, bool & value, bool defval = false) = 0;
virtual bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, float & value, float defval = 0.0) = 0;
virtual bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, double & value, double defval = 0.0) = 0;
virtual bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const wxString & value) = 0;
virtual bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const int & value) = 0;
virtual bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const bool & value) = 0;
virtual bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const float & value) = 0;
virtual bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const double & value) = 0;
virtual bool RemovePrivateConfigSubgroup(const PluginID & ID, const RegistryPath & group) = 0;
virtual bool RemovePrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key) = 0;
};
#endif // __AUDACITY_PLUGININTERFACE_H__