1 /**********************************************************************
2 
3   Audacity: A Digital Audio Editor
4 
5   PluginManager.h
6 
7   Leland Lucius
8 
9 **********************************************************************/
10 
11 #ifndef __AUDACITY_PLUGINMANAGER_H__
12 #define __AUDACITY_PLUGINMANAGER_H__
13 
14 #include <wx/defs.h>
15 
16 #include "wxArrayStringEx.h"
17 #include <map>
18 #include <memory>
19 
20 #include "EffectInterface.h"
21 #include "PluginInterface.h"
22 
23 class wxArrayString;
24 class FileConfig;
25 
26 ///////////////////////////////////////////////////////////////////////////////
27 //
28 // PluginDescriptor
29 //
30 ///////////////////////////////////////////////////////////////////////////////
31 
32 typedef enum : unsigned {
33    PluginTypeNone = 0,          // 2.1.0 placeholder entries...not used by 2.1.1 or greater
34    PluginTypeStub =1,               // Used for plugins that have not yet been registered
35    PluginTypeEffect =1<<1,
36    PluginTypeAudacityCommand=1<<2,
37    PluginTypeExporter=1<<3,
38    PluginTypeImporter=1<<4,
39    PluginTypeModule=1<<5,
40 } PluginType;
41 
42 // TODO:  Convert this to multiple derived classes
43 class AUDACITY_DLL_API PluginDescriptor
44 {
45 public:
46    PluginDescriptor();
47    PluginDescriptor &operator =(PluginDescriptor &&);
48    virtual ~PluginDescriptor();
49 
50    bool IsInstantiated() const;
51 
52    PluginType GetPluginType() const;
53 
54    // All plugins
55 
56    // These return untranslated strings
57    const wxString & GetID() const;
58    const wxString & GetProviderID() const;
59    const PluginPath & GetPath() const;
60    const ComponentInterfaceSymbol & GetSymbol() const;
61 
62    wxString GetUntranslatedVersion() const;
63    // There is no translated version
64 
65    wxString GetVendor() const;
66 
67    bool IsEnabled() const;
68    bool IsValid() const;
69 
70    void SetEnabled(bool enable);
71    void SetValid(bool valid);
72 
73    // Effect plugins only
74 
75    // Internal string only, no translated counterpart!
76    // (Use Effect::GetFamilyName instead)
77    // This string persists in configuration files
78    // So config compatibility will break if it is changed across Audacity versions
79    wxString GetEffectFamily() const;
80 
81    EffectType GetEffectType() const;
82    bool IsEffectDefault() const;
83    bool IsEffectInteractive() const;
84    bool IsEffectLegacy() const;
85    bool IsEffectRealtime() const;
86    bool IsEffectAutomatable() const;
87 
88    // Importer plugins only
89 
90    const wxString & GetImporterIdentifier() const;
91    const TranslatableString & GetImporterFilterDescription() const;
92    const FileExtensions & GetImporterExtensions() const;
93 
94 private:
95    friend class PluginManager;
96 
97    ComponentInterface *GetInstance();
98    void SetInstance(std::unique_ptr<ComponentInterface> instance);
99 
100    void SetPluginType(PluginType type);
101 
102    // These should be passed an untranslated value
103    void SetID(const PluginID & ID);
104    void SetProviderID(const PluginID & providerID);
105    void SetPath(const PluginPath & path);
106    void SetSymbol(const ComponentInterfaceSymbol & symbol);
107 
108    // These should be passed an untranslated value wrapped in XO() so
109    // the value will still be extracted for translation
110    void SetVersion(const wxString & version);
111    void SetVendor(const wxString & vendor);
112 
113    // "family" should be an untranslated string wrapped in wxT()
114    void SetEffectFamily(const wxString & family);
115    void SetEffectType(EffectType type);
116    void SetEffectDefault(bool dflt);
117    void SetEffectInteractive(bool interactive);
118    void SetEffectLegacy(bool legacy);
119    void SetEffectRealtime(bool realtime);
120    void SetEffectAutomatable(bool automatable);
121 
122    void SetImporterIdentifier(const wxString & identifier);
123    void SetImporterFilterDescription(const TranslatableString & filterDesc);
124    void SetImporterExtensions(FileExtensions extensions);
125 
126    // Common
127 
128    // Among other purposes, PluginDescriptor acts as the resource handle,
129    // or smart pointer, to a resource created in a plugin library, and is responsible
130    // for a cleanup of this pointer.
131    std::unique_ptr<ComponentInterface> muInstance; // may be null for a module
132    ComponentInterface *mInstance;
133 
134    PluginType mPluginType;
135 
136    wxString mID;
137    PluginPath mPath;
138    ComponentInterfaceSymbol mSymbol;
139    wxString mVersion;
140    wxString mVendor;
141    wxString mProviderID;
142    bool mEnabled;
143    bool mValid;
144 
145    // Effects
146 
147    wxString mEffectFamily;
148    EffectType mEffectType;
149    bool mEffectInteractive;
150    bool mEffectDefault;
151    bool mEffectLegacy;
152    bool mEffectRealtime;
153    bool mEffectAutomatable;
154 
155    // Importers
156 
157    wxString mImporterIdentifier;
158    FileExtensions mImporterExtensions;
159 };
160 
161 ///////////////////////////////////////////////////////////////////////////////
162 //
163 // PluginManager
164 //
165 ///////////////////////////////////////////////////////////////////////////////
166 
167 typedef std::map<PluginID, PluginDescriptor> PluginMap;
168 
169 typedef wxArrayString PluginIDs;
170 
171 class PluginRegistrationDialog;
172 
173 class AUDACITY_DLL_API PluginManager final : public PluginManagerInterface
174 {
175 public:
176 
177    RegistryPath GetPluginEnabledSetting( const PluginID &ID ) const;
178    RegistryPath GetPluginEnabledSetting( const PluginDescriptor &desc ) const;
179 
180    // PluginManagerInterface implementation
181 
182    bool IsPluginRegistered(
183       const PluginPath &path, const TranslatableString *pSymbol) override;
184 
185    const PluginID & RegisterPlugin(ModuleInterface *module) override;
186    const PluginID & RegisterPlugin(ModuleInterface *provider, ComponentInterface *command);
187    const PluginID & RegisterPlugin(ModuleInterface *provider, EffectDefinitionInterface *effect, int type) override;
188 
189    void FindFilesInPathList(const wxString & pattern,
190                                     const FilePaths & pathList,
191                                     FilePaths & files,
192                                     bool directories = false) override;
193 
194    bool HasSharedConfigGroup(const PluginID & ID, const RegistryPath & group) /* not override */;
195    bool GetSharedConfigSubgroups(const PluginID & ID, const RegistryPath & group, RegistryPaths &subgroups) override;
196 
197    bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, wxString & value, const wxString & defval = _T("")) override;
198    bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, int & value, int defval = 0) override;
199    bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, bool & value, bool defval = false) override;
200    bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, float & value, float defval = 0.0) override;
201    bool GetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, double & value, double defval = 0.0) override;
202 
203    bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const wxString & value) override;
204    bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const int & value) override;
205    bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const bool & value) override;
206    bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const float & value) override;
207    bool SetSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const double & value) override;
208 
209    bool RemoveSharedConfigSubgroup(const PluginID & ID, const RegistryPath & group) override;
210    bool RemoveSharedConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key) override;
211 
212    bool HasPrivateConfigGroup(const PluginID & ID, const RegistryPath & group) /* not override */;
213    bool GetPrivateConfigSubgroups(const PluginID & ID, const RegistryPath & group, RegistryPaths &subgroups) override;
214 
215    bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, wxString & value, const wxString & defval = _T("")) override;
216    bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, int & value, int defval = 0) override;
217    bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, bool & value, bool defval = false) override;
218    bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, float & value, float defval = 0.0) override;
219    bool GetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, double & value, double defval = 0.0) override;
220 
221    bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const wxString & value) override;
222    bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const int & value) override;
223    bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const bool & value) override;
224    bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const float & value) override;
225    bool SetPrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key, const double & value) override;
226 
227    bool RemovePrivateConfigSubgroup(const PluginID & ID, const RegistryPath & group) override;
228    bool RemovePrivateConfig(const PluginID & ID, const RegistryPath & group, const RegistryPath & key) override;
229 
230    // PluginManager implementation
231 
232    void Initialize();
233    void Terminate();
234 
235    bool DropFile(const wxString &fileName);
236 
237    static PluginManager & Get();
238 
239    static PluginID GetID(ModuleInterface *module);
240    static PluginID GetID(ComponentInterface *command);
241    static PluginID GetID(EffectDefinitionInterface *effect);
242 
243    // This string persists in configuration files
244    // So config compatibility will break if it is changed across Audacity versions
245    static wxString GetPluginTypeString(PluginType type);
246 
247    int GetPluginCount(PluginType type);
248    const PluginDescriptor *GetPlugin(const PluginID & ID) const;
249 
250    //! @name iteration over plugins of certain types, supporting range-for syntax
251    //! @{
252    class Iterator {
253    public:
254       //! Iterates all, even disabled
255       explicit Iterator(PluginManager &manager);
256       //! Iterates only enabled and matching plugins, with family enabled too if an effect
257       Iterator(PluginManager &manager,
258          int pluginType //!< bitwise or of values in PluginType
259       );
260       //! Iterates only enabled and matching effects, with family enabled too
261       Iterator(PluginManager &manager, EffectType type);
262       bool operator != (int) const {
263          return mIterator != mPm.mPlugins.end();
264       }
265       Iterator &operator ++ ();
266       auto &operator *() const { return mIterator->second; }
267    private:
268       void Advance(bool incrementing);
269       const PluginManager &mPm;
270       PluginMap::iterator mIterator;
271       EffectType mEffectType{ EffectTypeNone };
272       int mPluginType{ PluginTypeNone };
273    };
274    struct Range {
275       Iterator first;
beginRange276       Iterator begin() const { return first; }
endRange277       int end() const { return 0; }
278    };
279 
AllPlugins()280    Range AllPlugins() { return { Iterator{ *this } }; }
PluginsOfType(int type)281    Range PluginsOfType(int type) { return { Iterator{ *this, type } }; }
EffectsOfType(EffectType type)282    Range EffectsOfType(EffectType type) { return { Iterator{ *this, type } }; }
283    //! @}
284 
285    bool IsPluginEnabled(const PluginID & ID);
286    void EnablePlugin(const PluginID & ID, bool enable);
287 
288    const ComponentInterfaceSymbol & GetSymbol(const PluginID & ID);
289    ComponentInterface *GetInstance(const PluginID & ID);
290 
291    void CheckForUpdates(bool bFast = false);
292 
293    //! Used only by Nyquist Workbench module
294    const PluginID & RegisterPlugin(
295       std::unique_ptr<EffectDefinitionInterface> effect, PluginType type );
296    void UnregisterPlugin(const PluginID & ID);
297 
298    //! Load from preferences
299    void Load();
300    //! Save to preferences
301    void Save();
302 
303 private:
304    // private! Use Get()
305    PluginManager();
306    ~PluginManager();
307 
308    void LoadGroup(FileConfig *pRegistry, PluginType type);
309    void SaveGroup(FileConfig *pRegistry, PluginType type);
310 
311    PluginDescriptor & CreatePlugin(const PluginID & id, ComponentInterface *ident, PluginType type);
312 
313    FileConfig *GetSettings();
314 
315    bool HasGroup(const RegistryPath & group);
316    bool GetSubgroups(const RegistryPath & group, RegistryPaths & subgroups);
317 
318    bool GetConfig(const RegistryPath & key, wxString & value, const wxString & defval = L"");
319    bool GetConfig(const RegistryPath & key, int & value, int defval = 0);
320    bool GetConfig(const RegistryPath & key, bool & value, bool defval = false);
321    bool GetConfig(const RegistryPath & key, float & value, float defval = 0.0);
322    bool GetConfig(const RegistryPath & key, double & value, double defval = 0.0);
323 
324    bool SetConfig(const RegistryPath & key, const wxString & value);
325    bool SetConfig(const RegistryPath & key, const int & value);
326    bool SetConfig(const RegistryPath & key, const bool & value);
327    bool SetConfig(const RegistryPath & key, const float & value);
328    bool SetConfig(const RegistryPath & key, const double & value);
329 
330    /* Return values are keys for lookup in a config file */
331    RegistryPath SettingsPath(const PluginID & ID, bool shared);
332    RegistryPath SharedGroup(const PluginID & ID, const RegistryPath & group);
333    RegistryPath SharedKey(const PluginID & ID, const RegistryPath & group, const RegistryPath & key);
334    RegistryPath PrivateGroup(const PluginID & ID, const RegistryPath & group);
335    RegistryPath PrivateKey(const PluginID & ID, const RegistryPath & group, const RegistryPath & key);
336 
337    // The PluginID must be kept unique.  Since the wxFileConfig class does not preserve
338    // case, we use base64 encoding.
339    wxString ConvertID(const PluginID & ID);
340    wxString b64encode(const void *in, int len);
341    int b64decode(const wxString &in, void *out);
342 
343 private:
344    friend std::default_delete<PluginManager>;
345    static std::unique_ptr<PluginManager> mInstance;
346 
347    bool IsDirty();
348    void SetDirty(bool dirty = true);
349    std::unique_ptr<FileConfig> mSettings;
350 
351    bool mDirty;
352    int mCurrentIndex;
353 
354    PluginMap mPlugins;
355 };
356 
357 // Defining these special names in the low-level PluginManager.h
358 // is unfortunate
359 // Internal name should be stable across versions
360 #define NYQUIST_PROMPT_ID wxT("Nyquist Prompt")
361 // User-visible name might change in later versions
362 #define NYQUIST_PROMPT_NAME XO("Nyquist Prompt")
363 
364 #endif /* __AUDACITY_PLUGINMANAGER_H__ */
365