1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
|
/*!*******************************************************************
Audacity: A Digital Audio Editor
@file PluginProvider.h
@brief Generalized interface for discovery of plug-ins for one protocol
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_PLUGINPROVIDER_H__
#define __AUDACITY_PLUGINPROVIDER_H__
#include <functional>
#include <memory>
#include "Identifier.h"
#include "ComponentInterface.h"
#include "ComponentInterfaceSymbol.h"
using PluginID = wxString;
using PluginIDs = wxArrayString;
// Incomplete type not defined in libraries -- TODO clean that up:
class PluginManagerInterface;
// ============================================================================
//
// Don't even think about adding provider types, like effect, importer, etc. in
// here. The provider interface should not have to change when new types of
// plug-ins are added to Audacity.
//
// In addition a single provider may want to provide multiple plug-in types.
// ============================================================================
// ============================================================================
///
/// PluginProvider is an interface for discovering dynamically loaded libraries
/// according to some third party protocol, but also used in registering
/// the built-in effects and commands.
/// Classes derived from it can handle more specific plug-in protocols.
///
// ============================================================================
//! Interface for host side of one plug-in ("component") protocol that may
//! locate shared libraries with client-side code. A factory of plug-in objects
//! that represent those clients. One library may contain multiple plug-ins.
class COMPONENTS_API PluginProvider /* not final */
: public ComponentInterface
{
public:
//![Optional] Implementation may provide plugin validator
//!that may be used to perform additional checks. It's expected
//!that validation does actions that possibly can crash or throw,
//!for that reason it's not supposed to run within a main process.
//TODO: it may seem reasonable to require providers to perform that check
//in DiscoverPluginsAtPath, but some plugin types can safely provide meta
//data, which is a good reason to ask to avoid such checks during plugin
//discovery...
class Validator
{
public:
//!\param pluginInterface loaded plugin
virtual void Validate(ComponentInterface& pluginInterface) = 0;
};
virtual ~PluginProvider();
//! Called immediately after creation. Let provider initialize
/*! @return "true" if initialization 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 plug-ins provided by this
/*!
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;
//! File types associated with this protocol
/*!
"Paths" returned by FindModulePaths() and passed back to
DiscoverPluginsAtPath() have provider-specific meaning. They are not
necessarily file system paths to existent files that could be placed in any
folder and queried for plug-in 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;
//! Where plug-in files should be copied to install them
/*!
@return may be empty. Drag-and-drop is supported only if GetFileExtensions()
returns nonempty and this function returns nonempty.
*/
virtual FilePath InstallPath() = 0;
//! Called so that a provider of a static set of plug-ins can register them.
virtual void AutoRegisterPlugins(PluginManagerInterface & pluginManager) = 0;
//! Find available "paths", which may each be presented to the user, and
//! then reexamined (possibly loading libraries) to find one or more plug-ins
/*!
Paths are not necessarily file system paths. Only the provider reinterprets
the paths.
Modules may be associated with plug-ins, one-to-many.
@see GetFileExtensions DiscoverPluginsAtPath
*/
virtual PluginPaths
FindModulePaths(PluginManagerInterface & pluginManager) = 0;
//! Further expand a path reported by FindModulePaths
/*!
Once the user selects desired paths from FindModulePaths(), a call to
DiscoverPluginsAtPath() will be made to request registration of one or more
plug-ins.
If the provider must create an instance of the plug-in to register it, the
instance should be deleted after registration.
May discover more than one plug-in at the path, and may call-back with
a ComponentInterface that reports a path not equal to the given path
(perhaps appending other information to it).
@param errMsg message does not need to mention the path and may be nonempty
even if some plug-ins are also discovered successfully.
@return the number of plug-ins found
*/
using RegistrationCallback = std::function<
const PluginID &(PluginProvider *, ComponentInterface *) >;
virtual unsigned DiscoverPluginsAtPath(
const PluginPath & path, TranslatableString &errMsg,
const RegistrationCallback &callback )
= 0;
/**
* \brief Performs plugin/module existence check, still plugin may fail to load.
* Implementation should avoid loading plugins during this check.
* \param path Internal plugin path/ID discovered via DiscoverPluginsAtPath
* or module path returned by FindModulePaths
*/
virtual bool CheckPluginExist(const PluginPath& path) const = 0;
//! Implementation can provide plugin specific checks to the plugin instances.
//! By default returns null.
virtual std::unique_ptr<Validator> MakeValidator() const;
//! Load the plug-in at a path reported by DiscoverPluginsAtPath
/*!
@return smart pointer managing the later unloading
*/
virtual std::unique_ptr<ComponentInterface>
LoadPlugin(const PluginPath & path) = 0;
};
// ----------------------------------------------------------------------------
// Since there may be multiple embedded providers, the entry function will
// be declared static so as not to interfere with other providers during link.
// ----------------------------------------------------------------------------
#define DECLARE_PROVIDER_ENTRY(name) \
static std::unique_ptr<PluginProvider> name()
// ----------------------------------------------------------------------------
// This will create a class and instance that will register the provider entry
// point during Audacity startup. At the appropriate time, the entry point
// will be called to create the provider instance.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Provides the base for embedded provider registration. If used, a Register()
// method must be supplied explicitly.
// ----------------------------------------------------------------------------
#define DECLARE_BUILTIN_PROVIDER_BASE(name) \
class name \
{ \
public: \
name() {Register();} \
~name() {Unregister();} \
void Register(); \
void Unregister(); \
}; \
static name name ## _instance;
// ----------------------------------------------------------------------------
// Provides the full embedded provider registration process. Nothing further is
// required (other than supplying the provider entry point function).
// ----------------------------------------------------------------------------
#define DECLARE_BUILTIN_PROVIDER(name) \
DECLARE_BUILTIN_PROVIDER_BASE(name) \
void name::Register() \
{ \
RegisterProviderFactory(AudacityModule); \
} \
void name::Unregister() \
{ \
UnregisterProviderFactory(AudacityModule); \
}
#endif // __AUDACITY_MODULEINTERFACE_H__
|