File: TransformFactory.h

package info (click to toggle)
sonic-visualiser 5.2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,744 kB
  • sloc: cpp: 158,888; ansic: 11,920; sh: 1,785; makefile: 517; xml: 64; perl: 31
file content (343 lines) | stat: -rw-r--r-- 12,703 bytes parent folder | download | duplicates (2)
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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */

/*
    Sonic Visualiser
    An audio file viewer and annotation editor.
    Centre for Digital Music, Queen Mary, University of London.
    This file copyright 2006-2007 Chris Cannam and QMUL.
   
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.  See the file
    COPYING included with this distribution for more information.
*/

#ifndef SV_TRANSFORM_FACTORY_H
#define SV_TRANSFORM_FACTORY_H

#include "TransformDescription.h"

#include "base/TextMatcher.h"

#include <vamp-hostsdk/Plugin.h>

#include <QObject>
#include <QStringList>
#include <QThread>
#include <QMutex>

#include <map>
#include <set>
#include <memory>
#include <atomic>

namespace sv {

/**
 * TransformFactory catalogues both "installed" transforms (based on
 * plugins available to load) and "uninstalled" ones (based on RDF or
 * other metadata, possibly found online).
 *
 * You can retrieve a list of properties of either of these, and given
 * a transform ID, the TransformFactory can tell you whether the
 * transform is installed, not yet installed, or unknown. You can also
 * search both transform catalogues by keyword.
 *
 * TransformFactory can also construct the plugin for a transform,
 * transfer parameter bundles back and forth from plugin to transform,
 * and return various information about a transform. (These
 * capabilities are for installed transforms only. If a method name
 * contains "Transform" without qualification, it refers only to
 * installed ones.)
 *
 * The process of populating the transform catalogues can be handled
 * synchronously or asynchronously. There are two optional population
 * threads, for installed and uninstalled transforms, which can be
 * started with startPopulatingInstalledTransforms() and
 * startPopulatingUninstalledTransforms() respectively. Signals
 * installedTransformsPopulated and uninstalledTransformsPopulated are
 * emitted by each when they complete.
 *
 * If a function is called which depends on either installed or
 * uninstalled transforms having been populated, at a time when
 * population is not complete, it will first populate them, either by
 * waiting for the population thread or by populating them
 * synchronously. The exceptions are the search functions, which do
 * not wait for uninstalled transforms to finish populating - they may
 * just return incomplete data in that case.
 */
class TransformFactory : public QObject
{
    Q_OBJECT

public:
    static TransformFactory *getInstance();
    static void deleteInstance(); // only when exiting

public slots:
    /**
     * Instruct the transform factory to query and load only certain
     * types of transforms. Only transforms of the types specified
     * will be made available. This must be called before
     * startPopulatingUninstalledTransforms() to have any effect. The
     * default is to load all transform types that are found.
     */
    void restrictTransformTypes(std::set<Transform::Type>);
    
    /**
     * Start populating the installed transforms in a background
     * thread. Any call that depends on installed transform
     * information will wait for this thread to complete before it
     * acts. Calling this is optional; if you don't call it, installed
     * transforms will be populated the first time information about
     * them is requested.
     */
    void startPopulatingInstalledTransforms();

    /**
     * Start populating metadata about uninstalled transforms in a
     * background thread. Any call that depends specifically on
     * uninstalled transform information will wait for this thread to
     * complete before it acts.
     *
     * Note that the first thing the thread does is sleep until the
     * installed transforms have finished populating - if you don't
     * populate those, this will do nothing!
     */
    void startPopulatingUninstalledTransforms();

public:
    /**
     * Return true if the installed transforms have been populated,
     * i.e. if a call to something like haveTransform() will return
     * without having to do the work of scanning plugins. If this
     * returns false, then population may be in progress or may have
     * not been started at all.
     */
    bool havePopulatedInstalledTransforms();
    
    /**
     * Return true if the uninstalled transforms have finished being
     * populated, i.e. if a call to something like
     * getUninstalledTransformDescriptions() will return without
     * having to do the work of retrieving metadata. If this returns
     * false, then population may be in progress or may have not been
     * started at all.
     */
    bool havePopulatedUninstalledTransforms();

    /**
     * Return descriptions for all installed transforms. The returned
     * transforms are sorted in "display" order by name.
     */
    TransformList getInstalledTransformDescriptions();
    
    TransformDescription getInstalledTransformDescription(TransformId id);
    bool haveAnyInstalledTransforms();

    TransformList getUninstalledTransformDescriptions();
    TransformDescription getUninstalledTransformDescription(TransformId id);
    bool haveAnyUninstalledTransforms(bool waitForCheckToComplete = false);
    
    typedef enum {
        TransformUnknown,
        TransformInstalled,
        TransformNotInstalled
    } TransformInstallStatus;

    TransformInstallStatus getTransformInstallStatus(TransformId id);

    typedef std::map<TransformId, TextMatcher::Match> SearchResults;
    SearchResults search(QString keyword);
    SearchResults search(QStringList keywords);

    // All of the remaining functions act upon installed transforms
    // only.
    
    std::vector<TransformDescription::Type> getTransformTypes();
    std::vector<QString> getTransformCategories(TransformDescription::Type);
    std::vector<QString> getTransformMakers(TransformDescription::Type);
    QString getTransformTypeName(TransformDescription::Type) const;

    /**
     * Return true if the given transform is installed. If this
     * returns false, none of the following methods will return
     * anything useful.
     */
    bool haveTransform(TransformId identifier);

    /**
     * A single transform ID can lead to many possible Transforms,
     * with different parameters and execution context settings.
     * Return the default one for the given transform.
     */
    Transform getDefaultTransformFor(TransformId identifier,
                                     sv_samplerate_t rate = 0);

    /**
     * Full name of a transform, suitable for putting on a menu.
     */
    QString getTransformName(TransformId identifier);

    /**
     * Brief but friendly name of a transform, suitable for use
     * as the name of the output layer.
     */
    QString getTransformFriendlyName(TransformId identifier);

    QString getTransformUnits(TransformId identifier);

    Provider getTransformProvider(TransformId identifier);

    Vamp::Plugin::InputDomain getTransformInputDomain(TransformId identifier);

    /**
     * Return true if the transform has any configurable parameters,
     * i.e. if getConfigurationForTransform can ever return a non-trivial
     * (not equivalent to empty) configuration string.
     */
    bool isTransformConfigurable(TransformId identifier);

    /**
     * If the transform has a prescribed number or range of channel
     * inputs, return true and set minChannels and maxChannels to the
     * minimum and maximum number of channel inputs the transform can
     * accept.  Return false if it doesn't care.
     */
    bool getTransformChannelRange(TransformId identifier,
                                  int &minChannels, int &maxChannels);

    /**
     * Load an appropriate plugin for the given transform and set the
     * parameters, program and configuration strings on that plugin
     * from the Transform object.
     *
     * Note that this requires that the transform has a meaningful
     * sample rate set, as that is used as the rate for the plugin.  A
     * Transform can legitimately have rate set at zero (= "use the
     * rate of the input source"), so the caller will need to test for
     * this case.
     *
     * Returns the plugin thus loaded.  This will be a
     * Vamp::PluginBase, but not necessarily a Vamp::Plugin (only if
     * the transform was a feature-extraction type -- call
     * downcastVampPlugin if you only want Vamp::Plugins).  Returns
     * nullptr if no suitable plugin was available.
     *
     * (NB at the time of writing this is only used in Sonic
     * Annotator, which does not use model transform objects. In SV
     * the model transformers load their own plugins.)
     */
    std::shared_ptr<Vamp::PluginBase> instantiatePluginFor(const Transform &transform);

    /**
     * Set the plugin parameters, program and configuration strings on
     * the given Transform object from the given plugin instance.
     * Note that no check is made whether the plugin is actually the
     * "correct" one for the transform.
     */
    void setParametersFromPlugin(Transform &transform, std::shared_ptr<Vamp::PluginBase> plugin);

    /**
     * Set the parameters, program and configuration strings on the
     * given plugin from the given Transform object.
     */
    void setPluginParameters(const Transform &transform, std::shared_ptr<Vamp::PluginBase> plugin);
    
    /**
     * If the given Transform object has no processing step and block
     * sizes set, set them to appropriate defaults for the given
     * plugin.
     */
    void makeContextConsistentWithPlugin(Transform &transform, std::shared_ptr<Vamp::PluginBase> plugin); 

    /**
     * Retrieve a <plugin ... /> XML fragment that describes the
     * plugin parameters, program and configuration data for the given
     * transform.
     *
     * This function is provided for backward compatibility only.  Use
     * Transform::toXml where compatibility with PluginXml
     * descriptions of transforms is not required.
     */
    QString getPluginConfigurationXml(const Transform &transform);

    /**
     * Set the plugin parameters, program and configuration strings on
     * the given Transform object from the given <plugin ... /> XML
     * fragment.
     *
     * This function is provided for backward compatibility only.  Use
     * Transform(QString) where compatibility with PluginXml
     * descriptions of transforms is not required.
     */
    void setParametersFromPluginConfigurationXml(Transform &transform,
                                                 QString xml);
    
    QString getStartupFailureReport() const {
        return m_errorString;
    }

signals:
    void installedTransformsPopulated();
    void uninstalledTransformsPopulated();
    
protected:
    std::set<Transform::Type> m_transformTypeRestriction;

    typedef std::map<TransformId, TransformDescription> TransformDescriptionMap;

    TransformDescriptionMap m_transforms;
    std::atomic<bool> m_installedTransformsPopulated;

    TransformDescriptionMap m_uninstalledTransforms;
    std::atomic<bool> m_uninstalledTransformsPopulated;

    QString m_errorString;
    
    void populateInstalledTransforms();
    void populateUninstalledTransforms();
    void populateFeatureExtractionPlugins(TransformDescriptionMap &);
    void populateRealTimePlugins(TransformDescriptionMap &);

    std::shared_ptr<Vamp::PluginBase> instantiateDefaultPluginFor(TransformId id, sv_samplerate_t rate);
    QMutex m_installedTransformsMutex;
    QMutex m_uninstalledTransformsMutex;

    class InstalledTransformsPopulateThread : public QThread
    {
    public:
        InstalledTransformsPopulateThread(TransformFactory *factory) :
            m_factory(factory) {
        }
        void run() override;
        TransformFactory *m_factory;
    };
    InstalledTransformsPopulateThread *m_installedThread;

    class UninstalledTransformsPopulateThread : public QThread
    {
    public:
        UninstalledTransformsPopulateThread(TransformFactory *factory) :
            m_factory(factory) {
        }
        void run() override;
        TransformFactory *m_factory;
    };
    UninstalledTransformsPopulateThread *m_uninstalledThread;
    
    std::atomic<bool> m_exiting;
    std::atomic<bool> m_populatingSlowly;

    SearchResults searchUnadjusted(QStringList keywords);

    static TransformFactory *m_instance;

    TransformFactory();
    virtual ~TransformFactory();
};

} // end namespace sv

#endif