Allow sub plugins for instruments aswell
* Move m_key member of Effect into Plugin * Pass key to Instrument ctors and instantiaters * Add pluginKeys to all plugin selector widgets, and let them pass the keys when instantiating the instruments; or, if the keys must be passed over threads, pass the keys to the Engine using `Engine::setDndPluginKey()` * As instrument plugin libraries now also need to get their key passed, their second argument, which was always the same as the first, is now used to pass the sub plugin keys. This affects *all* instrument plugins. * Plugin.h: Add more virtuals to `SubPluginFeatures` in order to draw logos and images into instrument selector widgets * LadspaSubPluginFeatures: Implement the `displayName` virtual because the new behaviour to resolve displayNames is to first look at the SubPluginFeatures, which, without override, returns the superior plugin's name (Plugin.cpp) Additional: * PluginFactory.h: Allow setting up search paths without discovering plugins yet * Plugin.h: Add full documentation (should be checked)
This commit is contained in:
@@ -148,11 +148,6 @@ public:
|
||||
m_noRun = _state;
|
||||
}
|
||||
|
||||
inline const Descriptor::SubPluginFeatures::Key & key() const
|
||||
{
|
||||
return m_key;
|
||||
}
|
||||
|
||||
EffectChain * effectChain() const
|
||||
{
|
||||
return m_parent;
|
||||
@@ -201,8 +196,6 @@ private:
|
||||
sampleFrame * _dst_buf, sample_rate_t _dst_sr,
|
||||
const f_cnt_t _frames );
|
||||
|
||||
Descriptor::SubPluginFeatures::Key m_key;
|
||||
|
||||
ch_cnt_t m_processors;
|
||||
|
||||
bool m_okay;
|
||||
|
||||
@@ -111,6 +111,9 @@ public:
|
||||
return s_instanceOfMe;
|
||||
}
|
||||
|
||||
static void setDndPluginKey(void* newKey);
|
||||
static void* pickDndPluginKey();
|
||||
|
||||
signals:
|
||||
void initProgress(const QString &msg);
|
||||
|
||||
@@ -137,6 +140,7 @@ private:
|
||||
static DummyTrackContainer * s_dummyTC;
|
||||
|
||||
static Ladspa2LMMS * s_ladspaManager;
|
||||
static void* s_dndPluginKey;
|
||||
|
||||
// even though most methods are static, an instance is needed for Qt slots/signals
|
||||
static LmmsCore * s_instanceOfMe;
|
||||
|
||||
@@ -55,8 +55,9 @@ public:
|
||||
|
||||
Q_DECLARE_FLAGS(Flags, Flag);
|
||||
|
||||
Instrument( InstrumentTrack * _instrument_track,
|
||||
const Descriptor * _descriptor );
|
||||
Instrument(InstrumentTrack * _instrument_track,
|
||||
const Descriptor * _descriptor,
|
||||
const Descriptor::SubPluginFeatures::Key * key = nullptr);
|
||||
virtual ~Instrument() = default;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -113,10 +114,12 @@ public:
|
||||
// provided functions:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// instantiate instrument-plugin with given name or return NULL
|
||||
// on failure
|
||||
static Instrument * instantiate( const QString & _plugin_name,
|
||||
InstrumentTrack * _instrument_track );
|
||||
//! instantiate instrument-plugin with given name or return NULL
|
||||
//! on failure
|
||||
static Instrument * instantiate(const QString & _plugin_name,
|
||||
InstrumentTrack * _instrument_track,
|
||||
const Plugin::Descriptor::SubPluginFeatures::Key* key,
|
||||
bool keyFromDnd = false);
|
||||
|
||||
virtual bool isFromTrack( const Track * _track ) const;
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "Piano.h"
|
||||
#include "PianoView.h"
|
||||
#include "Pitch.h"
|
||||
#include "Plugin.h"
|
||||
#include "Track.h"
|
||||
|
||||
|
||||
@@ -146,7 +147,9 @@ public:
|
||||
|
||||
|
||||
// load instrument whose name matches given one
|
||||
Instrument * loadInstrument( const QString & _instrument_name );
|
||||
Instrument * loadInstrument(const QString & _instrument_name,
|
||||
const Plugin::Descriptor::SubPluginFeatures::Key* key = nullptr,
|
||||
bool keyFromDnd = false);
|
||||
|
||||
AudioPort * audioPort()
|
||||
{
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "LadspaManager.h"
|
||||
|
||||
|
||||
//! Class responsible for sorting found plugins (by LadspaManager)
|
||||
//! into categories
|
||||
class LMMS_EXPORT Ladspa2LMMS : public LadspaManager
|
||||
{
|
||||
public:
|
||||
|
||||
169
include/Plugin.h
169
include/Plugin.h
@@ -40,7 +40,27 @@ class PixmapLoader;
|
||||
class PluginView;
|
||||
class AutomatableModel;
|
||||
|
||||
/**
|
||||
Abstract representation of a plugin
|
||||
|
||||
Such a plugin can be an Instrument, Effect, Tool plugin etc.
|
||||
|
||||
Plugins have descriptors, containing meta info, which is used especially
|
||||
by PluginFactory and friends.
|
||||
|
||||
There are also Plugin keys (class Key, confusingly under
|
||||
SubPluginFeatures), which contain pointers to the plugin descriptor.
|
||||
|
||||
Some plugins have sub plugins, e.g. there is one CALF Plugin and for
|
||||
each CALF effect, there is a CALF sub plugin. For those plugins, there
|
||||
are keys for each sub plugin. These keys also link to the superior
|
||||
Plugin::Descriptor. Additionally, they contain attributes that help the
|
||||
superior Plugin saving them and recognizing them when loading.
|
||||
|
||||
In case of sub plugins, the Descriptor has SubPluginFeatures. Those
|
||||
are a bit like values to the sub plugins' keys (in terms of a key-value-
|
||||
map).
|
||||
*/
|
||||
class LMMS_EXPORT Plugin : public Model, public JournallingObject
|
||||
{
|
||||
MM_OPERATORS
|
||||
@@ -59,9 +79,9 @@ public:
|
||||
Undefined = 255
|
||||
} ;
|
||||
|
||||
// descriptor holds information about a plugin - every external plugin
|
||||
// has to instantiate such a descriptor in an extern "C"-section so that
|
||||
// the plugin-loader is able to access information about the plugin
|
||||
//! Descriptor holds information about a plugin - every external plugin
|
||||
//! has to instantiate such a Descriptor in an extern "C"-section so that
|
||||
//! the plugin-loader is able to access information about the plugin
|
||||
struct Descriptor
|
||||
{
|
||||
const char * name;
|
||||
@@ -71,23 +91,49 @@ public:
|
||||
int version;
|
||||
PluginTypes type;
|
||||
const PixmapLoader * logo;
|
||||
const char * supportedFileTypes;
|
||||
const char * supportedFileTypes; //!< csv list of extensions
|
||||
|
||||
inline bool supportsFileType( const QString& extension ) const
|
||||
{
|
||||
return QString( supportedFileTypes ).split( QChar( ',' ) ).contains( extension );
|
||||
}
|
||||
|
||||
/**
|
||||
Access to non-key-data of a sub plugin
|
||||
|
||||
If you consider sub plugin keys as keys in a
|
||||
key-value-map, this is the lookup for the corresponding
|
||||
values. In order to have flexibility between different
|
||||
plugin APIs, this is rather an array of fixed data,
|
||||
but a bunch of virtual functions taking the key and
|
||||
returning some values (or modifying objects of other
|
||||
classes).
|
||||
*/
|
||||
class LMMS_EXPORT SubPluginFeatures
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Key reference a Plugin::Descriptor, and,
|
||||
if the plugin has sub plugins, also reference
|
||||
its sub plugin (using the attributes).
|
||||
When keys are saved, those attributes are
|
||||
written to XML in order to find the right sub
|
||||
plugin when realoading.
|
||||
|
||||
@note Any data that is not required to reference
|
||||
the right Plugin or sub plugin should
|
||||
not be here (but rather in
|
||||
SubPluginFeatures, which are like values
|
||||
in a key-value map).
|
||||
*/
|
||||
struct Key
|
||||
{
|
||||
typedef QMap<QString, QString> AttributeMap;
|
||||
|
||||
inline Key( const Plugin::Descriptor * desc = NULL,
|
||||
const QString & name = QString(),
|
||||
const AttributeMap & am = AttributeMap() )
|
||||
const QString & name = QString(),
|
||||
const AttributeMap & am = AttributeMap()
|
||||
)
|
||||
:
|
||||
desc( desc ),
|
||||
name( name ),
|
||||
@@ -101,12 +147,28 @@ public:
|
||||
|
||||
inline bool isValid() const
|
||||
{
|
||||
return desc != NULL && name.isNull() == false;
|
||||
return desc != nullptr;
|
||||
}
|
||||
|
||||
//! Key to subplugin: reference to parent descriptor
|
||||
//! Key to plugin: reference to its descriptor
|
||||
const Plugin::Descriptor* desc;
|
||||
//! Descriptive name like "Calf Phaser".
|
||||
//! Not required for key lookup and not saved
|
||||
//! only used sometimes to temporary store descriptive names
|
||||
//! @todo This is a bug, there should be a function
|
||||
//! in SubPluginFeatures (to get the name) instead
|
||||
QString name;
|
||||
//! Attributes that make up the key and identify
|
||||
//! the sub plugin. They are being loaded and saved
|
||||
AttributeMap attributes;
|
||||
|
||||
// helper functions to retrieve data that is
|
||||
// not part of the key, but mapped via desc->subPluginFeatures
|
||||
const char* additionalFileExtensions() const;
|
||||
const char* displayName() const;
|
||||
const char* description() const;
|
||||
const PixmapLoader* logo() const;
|
||||
} ;
|
||||
|
||||
typedef QList<Key> KeyList;
|
||||
@@ -125,11 +187,42 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
//! While PluginFactory only collects the plugins,
|
||||
//! this function is used by widgets like EffectSelectDialog
|
||||
//! to find all possible sub plugins
|
||||
virtual void listSubPluginKeys( const Plugin::Descriptor *, KeyList & ) const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// You can add stuff values mapped by "Key" below
|
||||
// The defaults are sane, i.e. redirect to sub plugins
|
||||
// supererior descriptor
|
||||
|
||||
virtual const char* additionalFileExtensions(const Key&) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual const char* displayName(const Key& k) const
|
||||
{
|
||||
return k.isValid()
|
||||
? k.desc->displayName
|
||||
: k.name.toUtf8().data();
|
||||
}
|
||||
|
||||
virtual const char* description(const Key& k) const
|
||||
{
|
||||
return k.isValid() ? k.desc->description : "";
|
||||
}
|
||||
|
||||
virtual const PixmapLoader* logo(const Key& k) const
|
||||
{
|
||||
Q_ASSERT(k.desc);
|
||||
return k.desc->logo;
|
||||
}
|
||||
|
||||
protected:
|
||||
const Plugin::PluginTypes m_type;
|
||||
} ;
|
||||
@@ -140,48 +233,66 @@ public:
|
||||
// typedef a list so we can easily work with list of plugin descriptors
|
||||
typedef QList<Descriptor*> DescriptorList;
|
||||
|
||||
// contructor of a plugin
|
||||
Plugin( const Descriptor * descriptor, Model * parent );
|
||||
//! Constructor of a plugin
|
||||
//! @param key Sub plugins must pass a key here, optional otherwise.
|
||||
//! See the key() function
|
||||
Plugin(const Descriptor * descriptor, Model * parent,
|
||||
const Descriptor::SubPluginFeatures::Key *key = nullptr);
|
||||
virtual ~Plugin();
|
||||
|
||||
// returns display-name out of descriptor
|
||||
virtual QString displayName() const
|
||||
{
|
||||
return Model::displayName().isEmpty()
|
||||
? m_descriptor->displayName
|
||||
: Model::displayName();
|
||||
}
|
||||
//! Return display-name out of sub plugin or descriptor
|
||||
virtual QString displayName() const;
|
||||
|
||||
// return plugin-type
|
||||
//! Return logo out of sub plugin or descriptor
|
||||
const PixmapLoader *logo() const;
|
||||
|
||||
//! Return plugin type
|
||||
inline PluginTypes type( void ) const
|
||||
{
|
||||
return m_descriptor->type;
|
||||
}
|
||||
|
||||
// return plugin-descriptor for further information
|
||||
//! Return plugin Descriptor
|
||||
inline const Descriptor * descriptor() const
|
||||
{
|
||||
return m_descriptor;
|
||||
}
|
||||
|
||||
// can be called if a file matching supportedFileTypes should be
|
||||
// loaded/processed with the help of this plugin
|
||||
//! Return the key referencing this plugin. If the Plugin has no
|
||||
//! sub plugin features, the key is pretty useless. If it has,
|
||||
//! this key will also contain the sub plugin attributes, and will be
|
||||
//! a key to those SubPluginFeatures.
|
||||
inline const Descriptor::SubPluginFeatures::Key & key() const
|
||||
{
|
||||
return m_key;
|
||||
}
|
||||
|
||||
//! Can be called if a file matching supportedFileTypes should be
|
||||
//! loaded/processed with the help of this plugin
|
||||
virtual void loadFile( const QString & file );
|
||||
|
||||
// Called if external source needs to change something but we cannot
|
||||
// reference the class header. Should return null if not key not found.
|
||||
//! Called if external source needs to change something but we cannot
|
||||
//! reference the class header. Should return null if not key not found.
|
||||
virtual AutomatableModel* childModel( const QString & modelName );
|
||||
|
||||
// returns an instance of a plugin whose name matches to given one
|
||||
// if specified plugin couldn't be loaded, it creates a dummy-plugin
|
||||
static Plugin * instantiate( const QString& pluginName, Model * parent, void * data );
|
||||
//! Overload if the argument passed to the plugin is a subPluginKey
|
||||
//! If you can not pass the key and are aware that it's stored in
|
||||
//! Engine::pickDndPluginKey(), use this function, too
|
||||
static Plugin * instantiateWithKey(const QString& pluginName, Model * parent,
|
||||
const Descriptor::SubPluginFeatures::Key *key,
|
||||
bool keyFromDnd = false);
|
||||
|
||||
// create a view for the model
|
||||
//! Return an instance of a plugin whose name matches to given one
|
||||
//! if specified plugin couldn't be loaded, it creates a dummy-plugin
|
||||
//! @param data Anything the plugin expects. If this is a pointer to a sub plugin key,
|
||||
//! use instantiateWithKey instead
|
||||
static Plugin * instantiate(const QString& pluginName, Model * parent, void *data);
|
||||
|
||||
//! Create a view for the model
|
||||
PluginView * createView( QWidget * parent );
|
||||
|
||||
|
||||
protected:
|
||||
// create a view for the model
|
||||
//! Create a view for the model
|
||||
virtual PluginView* instantiateView( QWidget * ) = 0;
|
||||
void collectErrorForUI( QString errMsg );
|
||||
|
||||
@@ -189,6 +300,8 @@ protected:
|
||||
private:
|
||||
const Descriptor * m_descriptor;
|
||||
|
||||
Descriptor::SubPluginFeatures::Key m_key;
|
||||
|
||||
// pointer to instantiation-function in plugin
|
||||
typedef Plugin * ( * InstantiationHook )( Model * , void * );
|
||||
|
||||
|
||||
@@ -60,7 +60,8 @@ class PluginDescWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PluginDescWidget( const Plugin::Descriptor & _pd, QWidget * _parent );
|
||||
typedef Plugin::Descriptor::SubPluginFeatures::Key PluginKey;
|
||||
PluginDescWidget( const PluginKey & _pk, QWidget * _parent );
|
||||
|
||||
|
||||
protected:
|
||||
@@ -72,7 +73,7 @@ protected:
|
||||
private:
|
||||
constexpr static int DEFAULT_HEIGHT{24};
|
||||
|
||||
const Plugin::Descriptor & m_pluginDescriptor;
|
||||
PluginKey m_pluginKey;
|
||||
QPixmap m_logo;
|
||||
|
||||
bool m_mouseOver;
|
||||
|
||||
@@ -26,10 +26,13 @@
|
||||
#define PLUGINFACTORY_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include "lmms_export.h"
|
||||
#include "Plugin.h"
|
||||
@@ -41,12 +44,10 @@ class LMMS_EXPORT PluginFactory
|
||||
public:
|
||||
struct PluginInfo
|
||||
{
|
||||
PluginInfo() : library(nullptr), descriptor(nullptr) {}
|
||||
|
||||
const QString name() const;
|
||||
QFileInfo file;
|
||||
std::shared_ptr<QLibrary> library;
|
||||
Plugin::Descriptor* descriptor;
|
||||
std::shared_ptr<QLibrary> library = nullptr;
|
||||
Plugin::Descriptor* descriptor = nullptr;
|
||||
|
||||
bool isNull() const {return ! library;}
|
||||
};
|
||||
@@ -56,6 +57,8 @@ public:
|
||||
PluginFactory();
|
||||
~PluginFactory();
|
||||
|
||||
static void setupSearchPaths();
|
||||
|
||||
/// Returns the singleton instance of PluginFactory. You won't need to call
|
||||
/// this directly, use pluginFactory instead.
|
||||
static PluginFactory* instance();
|
||||
@@ -64,10 +67,17 @@ public:
|
||||
const Plugin::DescriptorList descriptors() const;
|
||||
const Plugin::DescriptorList descriptors(Plugin::PluginTypes type) const;
|
||||
|
||||
struct PluginInfoAndKey
|
||||
{
|
||||
PluginInfo info;
|
||||
Plugin::Descriptor::SubPluginFeatures::Key key;
|
||||
bool isNull() const { return info.isNull(); }
|
||||
};
|
||||
|
||||
/// Returns a list of all found plugins' PluginFactory::PluginInfo objects.
|
||||
const PluginInfoList& pluginInfos() const;
|
||||
/// Returns a plugin that support the given file extension
|
||||
const PluginInfo pluginSupportingExtension(const QString& ext);
|
||||
const PluginInfoAndKey pluginSupportingExtension(const QString& ext);
|
||||
|
||||
/// Returns the PluginInfo object of the plugin with the given name.
|
||||
/// If the plugin is not found, an empty PluginInfo is returned (use
|
||||
@@ -84,7 +94,9 @@ public slots:
|
||||
private:
|
||||
DescriptorMap m_descriptors;
|
||||
PluginInfoList m_pluginInfos;
|
||||
QMap<QString, PluginInfo> m_pluginByExt;
|
||||
|
||||
QMap<QString, PluginInfoAndKey> m_pluginByExt;
|
||||
QVector<std::string> m_garbage; //!< cleaned up at destruction
|
||||
|
||||
QHash<QString, QString> m_errors;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user