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:
Johannes Lorenz
2018-12-27 18:43:13 +01:00
parent 05128b9a33
commit a1b355828e
47 changed files with 612 additions and 245 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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()
{

View File

@@ -30,6 +30,8 @@
#include "LadspaManager.h"
//! Class responsible for sorting found plugins (by LadspaManager)
//! into categories
class LMMS_EXPORT Ladspa2LMMS : public LadspaManager
{
public:

View File

@@ -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 * );

View File

@@ -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;

View File

@@ -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;

View File

@@ -728,10 +728,10 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return( new FreeBoyInstrument(
static_cast<InstrumentTrack *>( _data ) ) );
static_cast<InstrumentTrack *>( m ) ) );
}

View File

@@ -1390,9 +1390,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return new GigInstrument( static_cast<InstrumentTrack *>( _data ) );
return new GigInstrument( static_cast<InstrumentTrack *>( m ) );
}
}

View File

@@ -44,6 +44,16 @@ LadspaSubPluginFeatures::LadspaSubPluginFeatures( Plugin::PluginTypes _type ) :
const char *LadspaSubPluginFeatures::displayName(const Plugin::Descriptor::SubPluginFeatures::Key &k) const
{
const ladspa_key_t & lkey = subPluginKeyToLadspaKey(&k);
Ladspa2LMMS * lm = Engine::getLADSPAManager();
return lm->getName(lkey).toUtf8().data();
}
void LadspaSubPluginFeatures::fillDescriptionWidget( QWidget * _parent,
const Key * _key ) const
{

View File

@@ -25,8 +25,8 @@
*
*/
#ifndef _LADSPA_SUBPLUGIN_FEATURES_H
#define _LADSPA_SUBPLUGIN_FEATURES_H
#ifndef LADSPA_SUBPLUGIN_FEATURES_H
#define LADSPA_SUBPLUGIN_FEATURES_H
#include "LadspaManager.h"
#include "Plugin.h"
@@ -37,11 +37,13 @@ class LadspaSubPluginFeatures : public Plugin::Descriptor::SubPluginFeatures
public:
LadspaSubPluginFeatures( Plugin::PluginTypes _type );
virtual void fillDescriptionWidget( QWidget * _parent,
const Key * _key ) const;
const char* displayName(const Key& k) const override;
void fillDescriptionWidget( QWidget * _parent,
const Key * _key ) const override;
virtual void listSubPluginKeys( const Plugin::Descriptor * _desc,
KeyList & _kl ) const;
KeyList & _kl ) const override;
static ladspa_key_t subPluginKeyToLadspaKey( const Key * _key );

View File

@@ -79,9 +79,9 @@ Plugin::Descriptor PLUGIN_EXPORT opulenz_plugin_descriptor =
};
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return( new OpulenzInstrument( static_cast<InstrumentTrack *>( _data ) ) );
return( new OpulenzInstrument( static_cast<InstrumentTrack *>( m ) ) );
}
}

View File

@@ -877,8 +877,8 @@ void XpressiveView::helpClicked() {
extern "C" {
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main(Model *, void * _data) {
return (new Xpressive(static_cast<InstrumentTrack *>(_data)));
PLUGIN_EXPORT Plugin * lmms_plugin_main(Model *m, void *) {
return (new Xpressive(static_cast<InstrumentTrack *>(m)));
}
}

View File

@@ -1277,10 +1277,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main(Model * model, void *)
{
return new audioFileProcessor(
static_cast<InstrumentTrack *>( _data ) );
return new audioFileProcessor(static_cast<InstrumentTrack *>(model));
}

View File

@@ -584,9 +584,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return( new bitInvader( static_cast<InstrumentTrack *>( _data ) ) );
return( new bitInvader( static_cast<InstrumentTrack *>( m ) ) );
}

View File

@@ -43,9 +43,9 @@ Plugin::Descriptor PLUGIN_EXPORT carlapatchbay_plugin_descriptor =
NULL
} ;
PLUGIN_EXPORT Plugin* lmms_plugin_main(Model*, void* data)
PLUGIN_EXPORT Plugin* lmms_plugin_main(Model* m, void*)
{
return new CarlaInstrument(static_cast<InstrumentTrack*>(data), &carlapatchbay_plugin_descriptor, true);
return new CarlaInstrument(static_cast<InstrumentTrack*>(m), &carlapatchbay_plugin_descriptor, true);
}
}

View File

@@ -43,9 +43,9 @@ Plugin::Descriptor PLUGIN_EXPORT carlarack_plugin_descriptor =
NULL
} ;
PLUGIN_EXPORT Plugin* lmms_plugin_main(Model*, void* data)
PLUGIN_EXPORT Plugin* lmms_plugin_main(Model* m, void*)
{
return new CarlaInstrument(static_cast<InstrumentTrack*>(data), &carlarack_plugin_descriptor, false);
return new CarlaInstrument(static_cast<InstrumentTrack*>(m), &carlarack_plugin_descriptor, false);
}
}

View File

@@ -367,9 +367,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model * m, void * )
{
return new kickerInstrument( static_cast<InstrumentTrack *>( _data ) );
return new kickerInstrument( static_cast<InstrumentTrack *>( m ) );
}

View File

@@ -1029,11 +1029,11 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model * m, void * )
{
return( new lb302Synth(
static_cast<InstrumentTrack *>( _data ) ) );
static_cast<InstrumentTrack *>( m ) ) );
}

View File

@@ -1828,9 +1828,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return new MonstroInstrument( static_cast<InstrumentTrack *>( _data ) );
return new MonstroInstrument( static_cast<InstrumentTrack *>( m ) );
}

View File

@@ -918,9 +918,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * _data )
{
return( new NesInstrument( static_cast<InstrumentTrack *>( _data ) ) );
return( new NesInstrument( static_cast<InstrumentTrack *>( m ) ) );
}

View File

@@ -636,9 +636,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return( new organicInstrument( static_cast<InstrumentTrack *>( _data ) ) );
return( new organicInstrument( static_cast<InstrumentTrack *>( m ) ) );
}

View File

@@ -66,9 +66,9 @@ Plugin::Descriptor PLUGIN_EXPORT patman_plugin_descriptor =
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return new patmanInstrument( static_cast<InstrumentTrack *>( _data ) );
return new patmanInstrument( static_cast<InstrumentTrack *>( m ) );
}
}

View File

@@ -1150,9 +1150,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return new sf2Instrument( static_cast<InstrumentTrack *>( _data ) );
return new sf2Instrument( static_cast<InstrumentTrack *>( m ) );
}

View File

@@ -1122,9 +1122,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model*, void* data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* m, void* )
{
return new sfxrInstrument( static_cast<InstrumentTrack *>( data ) );
return new sfxrInstrument( static_cast<InstrumentTrack *>( m ) );
}

View File

@@ -792,10 +792,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return( new sidInstrument(
static_cast<InstrumentTrack *>( _data ) ) );
return( new sidInstrument( static_cast<InstrumentTrack *>( m ) ) );
}

View File

@@ -756,9 +756,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model * m, void * )
{
return new malletsInstrument( static_cast<InstrumentTrack *>( _data ) );
return new malletsInstrument( static_cast<InstrumentTrack *>( m ) );
}

View File

@@ -723,9 +723,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* model, void * )
{
return new TripleOscillator( static_cast<InstrumentTrack *>( _data ) );
return new TripleOscillator( static_cast<InstrumentTrack *>( model ) );
}
}

View File

@@ -1167,9 +1167,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
Q_DECL_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
Q_DECL_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return new vestigeInstrument( static_cast<InstrumentTrack *>( _data ) );
return new vestigeInstrument( static_cast<InstrumentTrack *>( m ) );
}

View File

@@ -682,9 +682,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return( new vibed( static_cast<InstrumentTrack *>( _data ) ) );
return( new vibed( static_cast<InstrumentTrack *>( m ) ) );
}

View File

@@ -1279,9 +1279,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
{
return( new WatsynInstrument( static_cast<InstrumentTrack *>( _data ) ) );
return( new WatsynInstrument( static_cast<InstrumentTrack *>( m ) ) );
}

View File

@@ -652,10 +652,9 @@ extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *, void * _data )
PLUGIN_EXPORT Plugin * lmms_plugin_main(Model * m, void *)
{
return new ZynAddSubFxInstrument( static_cast<InstrumentTrack *>( _data ) );
return new ZynAddSubFxInstrument(static_cast<InstrumentTrack *>(m));
}

View File

@@ -36,9 +36,8 @@
Effect::Effect( const Plugin::Descriptor * _desc,
Model * _parent,
const Descriptor::SubPluginFeatures::Key * _key ) :
Plugin( _desc, _parent ),
Plugin( _desc, _parent, _key ),
m_parent( NULL ),
m_key( _key ? *_key : Descriptor::SubPluginFeatures::Key() ),
m_processors( 1 ),
m_okay( true ),
m_noRun( false ),
@@ -117,7 +116,7 @@ Effect * Effect::instantiate( const QString& pluginName,
Model * _parent,
Descriptor::SubPluginFeatures::Key * _key )
{
Plugin * p = Plugin::instantiate( pluginName, _parent, _key );
Plugin * p = Plugin::instantiateWithKey( pluginName, _parent, _key );
// check whether instantiated plugin is an effect
if( dynamic_cast<Effect *>( p ) != NULL )
{

View File

@@ -41,6 +41,7 @@ BBTrackContainer * LmmsCore::s_bbTrackContainer = NULL;
Song * LmmsCore::s_song = NULL;
ProjectJournal * LmmsCore::s_projectJournal = NULL;
Ladspa2LMMS * LmmsCore::s_ladspaManager = NULL;
void* LmmsCore::s_dndPluginKey = nullptr;
DummyTrackContainer * LmmsCore::s_dummyTC = NULL;
@@ -112,4 +113,24 @@ void LmmsCore::updateFramesPerTick()
DefaultTicksPerTact / s_song->getTempo();
}
void LmmsCore::setDndPluginKey(void *newKey)
{
assert(static_cast<Plugin::Descriptor::SubPluginFeatures::Key*>(newKey));
s_dndPluginKey = newKey;
}
void *LmmsCore::pickDndPluginKey()
{
return s_dndPluginKey;
}
LmmsCore * LmmsCore::s_instanceOfMe = NULL;

View File

@@ -27,9 +27,10 @@
#include "DummyInstrument.h"
Instrument::Instrument( InstrumentTrack * _instrument_track,
const Descriptor * _descriptor ) :
Plugin( _descriptor, NULL/* _instrument_track*/ ),
Instrument::Instrument(InstrumentTrack * _instrument_track,
const Descriptor * _descriptor,
const Descriptor::SubPluginFeatures::Key *key) :
Plugin(_descriptor, NULL/* _instrument_track*/, key),
m_instrumentTrack( _instrument_track )
{
}
@@ -56,19 +57,15 @@ f_cnt_t Instrument::beatLen( NotePlayHandle * ) const
Instrument * Instrument::instantiate( const QString & _plugin_name,
InstrumentTrack * _instrument_track )
Instrument *Instrument::instantiate(const QString &_plugin_name,
InstrumentTrack *_instrument_track, const Descriptor::SubPluginFeatures::Key *key, bool keyFromDnd)
{
Plugin * p = Plugin::instantiate( _plugin_name, _instrument_track,
_instrument_track );
// check whether instantiated plugin is an instrument
if( dynamic_cast<Instrument *>( p ) != NULL )
{
// everything ok, so return pointer
return dynamic_cast<Instrument *>( p );
}
// not quite... so delete plugin and return dummy instrument
if(keyFromDnd)
Q_ASSERT(!key);
// copy from above // TODO! common cleaner func
Plugin * p = Plugin::instantiateWithKey(_plugin_name, _instrument_track, key, keyFromDnd);
if(dynamic_cast<Instrument *>(p))
return dynamic_cast<Instrument *>(p);
delete p;
return( new DummyInstrument( _instrument_track ) );
}

View File

@@ -40,7 +40,7 @@
LadspaManager::LadspaManager()
{
// Make sure plugin search paths are set up
PluginFactory::instance();
PluginFactory::setupSearchPaths();
QStringList ladspaDirectories = QString( getenv( "LADSPA_PATH" ) ).
split( LADSPA_PATH_SEPERATOR );

View File

@@ -22,11 +22,15 @@
*
*/
#include <QtGlobal>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QLibrary>
#include <QMessageBox>
// comment separator to prevent clang's header sorting
#include "lmmsconfig.h"
#include "Plugin.h"
#include "embed.h"
#include "Engine.h"
@@ -53,10 +57,12 @@ static Plugin::Descriptor dummyPluginDescriptor =
Plugin::Plugin( const Descriptor * descriptor, Model * parent ) :
Model( parent ),
Plugin::Plugin(const Descriptor * descriptor, Model * parent, const
Descriptor::SubPluginFeatures::Key* key) :
Model(parent),
JournallingObject(),
m_descriptor( descriptor )
m_descriptor(descriptor),
m_key(key ? *key : Descriptor::SubPluginFeatures::Key(m_descriptor))
{
if( m_descriptor == NULL )
{
@@ -74,6 +80,87 @@ Plugin::~Plugin()
template<class T>
T use_this_or(T this_param, T or_param)
{
return this_param ? this_param : or_param;
}
QString Plugin::displayName() const
{
return Model::displayName().isEmpty() // currently always empty
? (m_descriptor->subPluginFeatures && m_key.isValid())
// get from sub plugin
? m_key.displayName()
// get from plugin
: m_descriptor->displayName
: Model::displayName();
}
const PixmapLoader* Plugin::logo() const
{
return (m_descriptor->subPluginFeatures && m_key.isValid())
? m_key.logo()
: m_descriptor->logo;
}
const char *Plugin::Descriptor::SubPluginFeatures::Key::additionalFileExtensions() const
{
Q_ASSERT(isValid());
return desc->subPluginFeatures
// get from sub plugin
? desc->subPluginFeatures->additionalFileExtensions(*this)
// get from plugin
: nullptr;
}
const char* Plugin::Descriptor::SubPluginFeatures::Key::displayName() const
{
Q_ASSERT(isValid());
return desc->subPluginFeatures
// get from sub plugin
? use_this_or(desc->subPluginFeatures->displayName(*this), desc->displayName)
// get from plugin
: desc->displayName;
}
const PixmapLoader* Plugin::Descriptor::SubPluginFeatures::Key::logo() const
{
Q_ASSERT(isValid());
return desc->subPluginFeatures
? use_this_or(desc->subPluginFeatures->logo(*this), desc->logo)
: desc->logo;
}
const char *Plugin::Descriptor::SubPluginFeatures::Key::description() const
{
Q_ASSERT(isValid());
return desc->subPluginFeatures
? use_this_or(desc->subPluginFeatures->description(*this), desc->description)
: desc->description;
}
void Plugin::loadFile( const QString & )
{
}
@@ -90,10 +177,37 @@ AutomatableModel * Plugin::childModel( const QString & )
#include "PluginFactory.h"
Plugin * Plugin::instantiate( const QString& pluginName, Model * parent,
void * data )
Plugin * Plugin::instantiateWithKey(const QString& pluginName, Model * parent,
const Descriptor::SubPluginFeatures::Key *key,
bool keyFromDnd)
{
if(keyFromDnd)
Q_ASSERT(!key);
const Descriptor::SubPluginFeatures::Key *keyPtr = keyFromDnd
? static_cast<Plugin::Descriptor::SubPluginFeatures::Key*>(Engine::pickDndPluginKey())
: key;
const PluginFactory::PluginInfo& pi = pluginFactory->pluginInfo(pluginName.toUtf8());
if(keyPtr)
{
// descriptor is not yet set when loading - set it now
Descriptor::SubPluginFeatures::Key keyCopy = *keyPtr;
keyCopy.desc = pi.descriptor;
return Plugin::instantiate(pluginName, parent, &keyCopy);
}
else
return Plugin::instantiate(pluginName, parent,
// the keys are never touched anywhere
const_cast<Descriptor::SubPluginFeatures::Key *>(keyPtr));
}
Plugin * Plugin::instantiate(const QString& pluginName, Model * parent,
void *data)
{
const PluginFactory::PluginInfo& pi = pluginFactory->pluginInfo(pluginName.toUtf8());
if( pi.isNull() )
{
if( gui )
@@ -106,9 +220,15 @@ Plugin * Plugin::instantiate( const QString& pluginName, Model * parent,
}
return new DummyPlugin();
}
qDebug() << "Using PluginInfo for " << pluginName;
InstantiationHook instantiationHook = ( InstantiationHook ) pi.library->resolve( "lmms_plugin_main" );
if( instantiationHook == NULL )
Plugin* inst;
InstantiationHook instantiationHook;
if ((instantiationHook = ( InstantiationHook ) pi.library->resolve( "lmms_plugin_main" )))
{
inst = instantiationHook(parent, data);
}
else
{
if( gui )
{
@@ -120,7 +240,7 @@ Plugin * Plugin::instantiate( const QString& pluginName, Model * parent,
return new DummyPlugin();
}
Plugin * inst = instantiationHook( parent, data );
return inst;
}
@@ -181,4 +301,3 @@ QDomElement Plugin::Descriptor::SubPluginFeatures::Key::saveXML(
}

View File

@@ -28,8 +28,11 @@
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QLibrary>
#include "lmmsconfig.h"
#include "ConfigManager.h"
#include "Plugin.h"
#include "embed.h"
#ifdef LMMS_BUILD_WIN32
QStringList nameFilters("*.dll");
@@ -45,6 +48,16 @@ qint64 qHash(const QFileInfo& fi)
std::unique_ptr<PluginFactory> PluginFactory::s_instance;
PluginFactory::PluginFactory()
{
setupSearchPaths();
discoverPlugins();
}
PluginFactory::~PluginFactory()
{
}
void PluginFactory::setupSearchPaths()
{
// Adds a search path relative to the main executable if the path exists.
auto addRelativeIfExists = [](const QString & path) {
@@ -76,12 +89,6 @@ PluginFactory::PluginFactory()
QDir::addSearchPath("plugins", env_path);
QDir::addSearchPath("plugins", ConfigManager::inst()->workingDir() + "plugins");
discoverPlugins();
}
PluginFactory::~PluginFactory()
{
}
PluginFactory* PluginFactory::instance()
@@ -107,9 +114,9 @@ const PluginFactory::PluginInfoList& PluginFactory::pluginInfos() const
return m_pluginInfos;
}
const PluginFactory::PluginInfo PluginFactory::pluginSupportingExtension(const QString& ext)
const PluginFactory::PluginInfoAndKey PluginFactory::pluginSupportingExtension(const QString& ext)
{
return m_pluginByExt.value(ext, PluginInfo());
return m_pluginByExt.value(ext, PluginInfoAndKey());
}
const PluginFactory::PluginInfo PluginFactory::pluginInfo(const char* name) const
@@ -150,42 +157,82 @@ void PluginFactory::discoverPlugins()
for (const QFileInfo& file : files)
{
auto library = std::make_shared<QLibrary>(file.absoluteFilePath());
if (! library->load()) {
m_errors[file.baseName()] = library->errorString();
qWarning("%s", library->errorString().toLocal8Bit().data());
continue;
}
if (library->resolve("lmms_plugin_main") == nullptr) {
continue;
}
QString descriptorName = file.baseName() + "_plugin_descriptor";
if( descriptorName.left(3) == "lib" )
Plugin::Descriptor* pluginDescriptor = nullptr;
if (library->resolve("lmms_plugin_main"))
{
descriptorName = descriptorName.mid(3);
}
QString descriptorName = file.baseName() + "_plugin_descriptor";
if( descriptorName.left(3) == "lib" )
{
descriptorName = descriptorName.mid(3);
}
Plugin::Descriptor* pluginDescriptor = reinterpret_cast<Plugin::Descriptor*>(library->resolve(descriptorName.toUtf8().constData()));
if(pluginDescriptor == nullptr)
pluginDescriptor = reinterpret_cast<Plugin::Descriptor*>(library->resolve(descriptorName.toUtf8().constData()));
if(pluginDescriptor == nullptr)
{
qWarning() << qApp->translate("PluginFactory", "LMMS plugin %1 does not have a plugin descriptor named %2!").
arg(file.absoluteFilePath()).arg(descriptorName);
continue;
}
}
else
{
qWarning() << qApp->translate("PluginFactory", "LMMS plugin %1 does not have a plugin descriptor named %2!").
arg(file.absoluteFilePath()).arg(descriptorName);
continue;
qDebug() << "Ignoring" << file << "(no lmms_plugin_main())";
}
PluginInfo info;
info.file = file;
info.library = library;
info.descriptor = pluginDescriptor;
pluginInfos << info;
for (const QString& ext : QString(info.descriptor->supportedFileTypes).split(','))
if(pluginDescriptor)
{
m_pluginByExt.insert(ext, info);
}
PluginInfo info;
info.file = file;
info.library = library;
info.descriptor = pluginDescriptor;
pluginInfos << info;
descriptors.insert(info.descriptor->type, info.descriptor);
qDebug() << "Add" << info.file << "with type"
<< info.descriptor->type;
auto addSupportedFileTypes =
[this](const char* supportedFileTypes,
const PluginInfo& info,
const Plugin::Descriptor::SubPluginFeatures::Key* key = nullptr)
{
if(supportedFileTypes)
for (const QString& ext : QString(supportedFileTypes).split(','))
{
qDebug() << "Plugin " << info.name() << "supports" << ext;
PluginInfoAndKey infoAndKey;
infoAndKey.info = info;
infoAndKey.key = key
? *key
: Plugin::Descriptor::SubPluginFeatures::Key();
m_pluginByExt.insert(ext, infoAndKey);
}
};
if (info.descriptor->supportedFileTypes)
addSupportedFileTypes(info.descriptor->supportedFileTypes, info);
if (info.descriptor->subPluginFeatures)
{
Plugin::Descriptor::SubPluginFeatures::KeyList
subPluginKeys;
info.descriptor->subPluginFeatures->listSubPluginKeys(
info.descriptor,
subPluginKeys);
for(const Plugin::Descriptor::SubPluginFeatures::Key& key
: subPluginKeys)
{
addSupportedFileTypes(key.additionalFileExtensions(), info, &key);
}
}
descriptors.insert(info.descriptor->type, info.descriptor);
}
}
m_pluginInfos = pluginInfos;

View File

@@ -137,8 +137,10 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
suffix().toLower();
if( i == NULL || !i->descriptor()->supportsFileType( ext ) )
{
const PluginFactory::PluginInfoAndKey& infoAndKey =
pluginFactory->pluginSupportingExtension(ext);
i = s_previewTC->previewInstrumentTrack()->
loadInstrument(pluginFactory->pluginSupportingExtension(ext).name());
loadInstrument(infoAndKey.info.name(), &infoAndKey.key);
}
if( i != NULL )
{

View File

@@ -53,11 +53,6 @@ EffectSelectDialog::EffectSelectDialog( QWidget * _parent ) :
if( desc->subPluginFeatures )
{
desc->subPluginFeatures->listSubPluginKeys(
// as iterators are always stated to be not
// equal with pointers, we dereference the
// iterator and take the address of the item,
// so we're on the safe side and the compiler
// likely will reduce that to just "it"
desc,
subPluginEffectKeys );
}
@@ -79,14 +74,14 @@ EffectSelectDialog::EffectSelectDialog( QWidget * _parent ) :
{
QString name;
QString type;
if( ( *it ).desc->subPluginFeatures )
if( it->desc->subPluginFeatures )
{
name = ( *it ).name;
type = ( *it ).desc->displayName;
name = it->displayName();
type = it->desc->displayName;
}
else
{
name = ( *it ).desc->displayName;
name = it->desc->displayName;
type = "LMMS";
}
m_sourceModel.setItem( row, 0, new QStandardItem( name ) );
@@ -184,62 +179,63 @@ void EffectSelectDialog::rowChanged( const QModelIndex & _idx,
{
m_currentSelection = m_effectKeys[m_model.mapToSource( _idx ).row()];
}
if( m_currentSelection.desc )
if( m_currentSelection.desc )
{
m_descriptionWidget = new QWidget;
QHBoxLayout *hbox = new QHBoxLayout( m_descriptionWidget );
QHBoxLayout *hbox = new QHBoxLayout( m_descriptionWidget );
Plugin::Descriptor const & descriptor = *( m_currentSelection.desc );
Plugin::Descriptor const & descriptor = *( m_currentSelection.desc );
if ( descriptor.logo )
{
QLabel *logoLabel = new QLabel( m_descriptionWidget );
logoLabel->setPixmap( descriptor.logo->pixmap() );
logoLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
const PixmapLoader* pixLoa = m_currentSelection.logo();
if (pixLoa)
{
QLabel *logoLabel = new QLabel( m_descriptionWidget );
logoLabel->setPixmap(pixLoa->pixmap());
logoLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
hbox->addWidget( logoLabel );
hbox->setAlignment( logoLabel, Qt::AlignTop);
}
hbox->addWidget( logoLabel );
hbox->setAlignment( logoLabel, Qt::AlignTop);
}
QWidget *textualInfoWidget = new QWidget( m_descriptionWidget );
QWidget *textualInfoWidget = new QWidget( m_descriptionWidget );
hbox->addWidget(textualInfoWidget);
hbox->addWidget(textualInfoWidget);
QVBoxLayout * textWidgetLayout = new QVBoxLayout( textualInfoWidget);
textWidgetLayout->setMargin( 4 );
textWidgetLayout->setSpacing( 0 );
QVBoxLayout * textWidgetLayout = new QVBoxLayout( textualInfoWidget);
textWidgetLayout->setMargin( 4 );
textWidgetLayout->setSpacing( 0 );
if ( m_currentSelection.desc->subPluginFeatures )
{
QWidget *subWidget = new QWidget(textualInfoWidget);
QVBoxLayout * subLayout = new QVBoxLayout( subWidget );
subLayout->setMargin( 4 );
subLayout->setSpacing( 0 );
m_currentSelection.desc->subPluginFeatures->
fillDescriptionWidget( subWidget, &m_currentSelection );
for( QWidget * w : subWidget->findChildren<QWidget *>() )
{
if( w->parent() == subWidget )
{
subLayout->addWidget( w );
}
}
if ( m_currentSelection.desc->subPluginFeatures )
{
QWidget *subWidget = new QWidget(textualInfoWidget);
QVBoxLayout * subLayout = new QVBoxLayout( subWidget );
subLayout->setMargin( 4 );
subLayout->setSpacing( 0 );
m_currentSelection.desc->subPluginFeatures->
fillDescriptionWidget( subWidget, &m_currentSelection );
for( QWidget * w : subWidget->findChildren<QWidget *>() )
{
if( w->parent() == subWidget )
{
subLayout->addWidget( w );
}
}
textWidgetLayout->addWidget(subWidget);
}
else
{
QLabel *label = new QLabel(m_descriptionWidget);
QString labelText = "<p><b>" + tr("Name") + ":</b> " + QString::fromUtf8(descriptor.displayName) + "</p>";
labelText += "<p><b>" + tr("Description") + ":</b> " + qApp->translate( "pluginBrowser", descriptor.description ) + "</p>";
labelText += "<p><b>" + tr("Author") + ":</b> " + QString::fromUtf8(descriptor.author) + "</p>";
textWidgetLayout->addWidget(subWidget);
}
else
{
QLabel *label = new QLabel(m_descriptionWidget);
QString labelText = "<p><b>" + tr("Name") + ":</b> " + QString::fromUtf8(descriptor.displayName) + "</p>";
labelText += "<p><b>" + tr("Description") + ":</b> " + qApp->translate( "pluginBrowser", descriptor.description ) + "</p>";
labelText += "<p><b>" + tr("Author") + ":</b> " + QString::fromUtf8(descriptor.author) + "</p>";
label->setText(labelText);
textWidgetLayout->addWidget(label);
}
label->setText(labelText);
textWidgetLayout->addWidget(label);
}
ui->scrollArea->setWidget( m_descriptionWidget );
ui->scrollArea->setWidget( m_descriptionWidget );
m_descriptionWidget->show();
}
}

View File

@@ -180,7 +180,7 @@ void FileBrowser::reloadTree( void )
void FileBrowser::expandItems( QTreeWidgetItem * item )
{
int numChildren = item ? item->childCount() : m_fileBrowserTreeWidget->topLevelItemCount();
int numChildren = item ? item->childCount() : m_fileBrowserTreeWidget->topLevelItemCount();
for( int i = 0; i < numChildren; ++i )
{
QTreeWidgetItem * it = item ? item->child( i ) : m_fileBrowserTreeWidget->topLevelItem(i);
@@ -241,7 +241,7 @@ void FileBrowser::addItems(const QString & path )
Directory *dd = new Directory( cur_file, path,
m_filter );
m_fileBrowserTreeWidget->insertTopLevelItem( i,dd );
dd->update();
dd->update(); // add files to the directory
orphan = false;
break;
}
@@ -406,7 +406,7 @@ void FileBrowserTreeWidget::mousePressEvent(QMouseEvent * me )
delete tf;
}
else if( ( f->extension ()== "xiz" || f->extension() == "sf2" || f->extension() == "sf3" || f->extension() == "gig" || f->extension() == "pat" ) &&
! pluginFactory->pluginSupportingExtension(f->extension()).isNull() )
! pluginFactory->pluginSupportingExtension(f->extension()).info.isNull() )
{
m_previewPlayHandle = new PresetPreviewPlayHandle( f->fullName(), f->handling() == FileItem::LoadByPlugin );
}
@@ -549,8 +549,9 @@ void FileBrowserTreeWidget::handleFile(FileItem * f, InstrumentTrack * it )
if( i == NULL ||
!i->descriptor()->supportsFileType( e ) )
{
i = it->loadInstrument(
pluginFactory->pluginSupportingExtension(e).name() );
PluginFactory::PluginInfoAndKey piakn =
pluginFactory->pluginSupportingExtension(e);
i = it->loadInstrument(piakn.info.name(), &piakn.key);
}
i->loadFile( f->fullName() );
break;

View File

@@ -57,7 +57,7 @@ void InstrumentView::setModel( Model * _model, bool )
if( dynamic_cast<Instrument *>( _model ) != NULL )
{
ModelView::setModel( _model );
instrumentTrackWindow()->setWindowIcon( model()->descriptor()->logo->pixmap() );
instrumentTrackWindow()->setWindowIcon( model()->logo()->pixmap() );
connect( model(), SIGNAL( destroyed( QObject * ) ), this, SLOT( close() ) );
}
}

View File

@@ -31,6 +31,7 @@
#include <QStyleOption>
#include "embed.h"
#include "Engine.h"
#include "templates.h"
#include "gui_templates.h"
#include "StringPairDrag.h"
@@ -85,9 +86,30 @@ PluginDescList::PluginDescList(QWidget *parent) :
return qstricmp( d1->displayName, d2->displayName ) < 0 ? true : false;
}
);
for (const Plugin::Descriptor* desc : descs)
typedef Plugin::Descriptor::SubPluginFeatures::KeyList PluginKeyList;
typedef Plugin::Descriptor::SubPluginFeatures::Key PluginKey;
PluginKeyList subPluginKeys, pluginKeys;
for (const Plugin::Descriptor* desc: descs)
{
PluginDescWidget* p = new PluginDescWidget( *desc, this );
if( desc->subPluginFeatures )
{
desc->subPluginFeatures->listSubPluginKeys(
desc,
subPluginKeys );
}
else
{
pluginKeys << PluginKey( desc, desc->name );
}
}
pluginKeys += subPluginKeys;
for (const PluginKey& key : pluginKeys)
{
PluginDescWidget* p = new PluginDescWidget( key, this );
p->show();
layout->addWidget(p);
}
@@ -99,23 +121,23 @@ PluginDescList::PluginDescList(QWidget *parent) :
PluginDescWidget::PluginDescWidget( const Plugin::Descriptor & _pd,
PluginDescWidget::PluginDescWidget(const PluginKey &_pk,
QWidget * _parent ) :
QWidget( _parent ),
m_pluginDescriptor( _pd ),
m_logo( _pd.logo->pixmap() ),
m_pluginKey( _pk ),
m_logo( _pk.logo()->pixmap() ),
m_mouseOver( false )
{
setFixedHeight( DEFAULT_HEIGHT );
setMouseTracking( true );
setCursor( Qt::PointingHandCursor );
setToolTip(_pd.description);
setToolTip(_pk.description());
}
void PluginDescWidget::paintEvent( QPaintEvent * e )
void PluginDescWidget::paintEvent( QPaintEvent * )
{
QPainter p( this );
@@ -140,8 +162,7 @@ void PluginDescWidget::paintEvent( QPaintEvent * e )
}
p.setFont( f );
p.drawText( 10 + logo_size.width(), 15,
m_pluginDescriptor.displayName );
p.drawText( 10 + logo_size.width(), 15, m_pluginKey.displayName());
}
@@ -171,8 +192,9 @@ void PluginDescWidget::mousePressEvent( QMouseEvent * _me )
{
if( _me->button() == Qt::LeftButton )
{
new StringPairDrag( "instrument", m_pluginDescriptor.name,
m_logo, this );
Engine::setDndPluginKey(&m_pluginKey);
new StringPairDrag("instrument",
QString::fromUtf8(m_pluginKey.desc->name), m_logo, this);
leaveEvent( _me );
}
}

View File

@@ -384,8 +384,9 @@ void TrackContainerView::dropEvent( QDropEvent * _de )
InstrumentTrack * it = dynamic_cast<InstrumentTrack *>(
Track::create( Track::InstrumentTrack,
m_tc ) );
Instrument * i = it->loadInstrument(
pluginFactory->pluginSupportingExtension(FileItem::extension(value)).name());
PluginFactory::PluginInfoAndKey piakn =
pluginFactory->pluginSupportingExtension(FileItem::extension(value));
Instrument * i = it->loadInstrument(piakn.info.name(), &piakn.key);
i->loadFile( value );
//it->toggledInstrumentTrackButton( true );
_de->accept();
@@ -529,7 +530,8 @@ InstrumentLoaderThread::InstrumentLoaderThread( QObject *parent, InstrumentTrack
void InstrumentLoaderThread::run()
{
Instrument *i = m_it->loadInstrument( m_name );
Instrument *i = m_it->loadInstrument(m_name, nullptr,
true /*always DnD*/);
QObject *parent = i->parent();
i->setParent( 0 );
i->moveToThread( m_containerThread );

View File

@@ -195,9 +195,15 @@ void TrackLabelButton::paintEvent( QPaintEvent * _pe )
InstrumentTrack * it =
dynamic_cast<InstrumentTrack *>( m_trackView->getTrack() );
const PixmapLoader * pl;
auto get_logo = [](InstrumentTrack* it) -> const PixmapLoader*
{
return it->instrument()->key().isValid()
? it->instrument()->key().logo()
: it->instrument()->descriptor()->logo;
};
if( it && it->instrument() &&
it->instrument()->descriptor() &&
( pl = it->instrument()->descriptor()->logo ) )
( pl = get_logo(it) ) )
{
if( pl->pixmapName() != m_iconName )
{

View File

@@ -735,7 +735,10 @@ void InstrumentTrack::saveTrackSpecificSettings( QDomDocument& doc, QDomElement
{
QDomElement i = doc.createElement( "instrument" );
i.setAttribute( "name", m_instrument->descriptor()->name );
m_instrument->saveState( doc, i );
QDomElement ins = m_instrument->saveState( doc, i );
if(m_instrument->key().isValid()) {
ins.appendChild( m_instrument->key().saveXML( doc ) );
}
thisElement.appendChild( i );
}
m_soundShaping.saveState( doc, thisElement );
@@ -796,9 +799,13 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement
}
else if( node.nodeName() == "instrument" )
{
typedef Plugin::Descriptor::SubPluginFeatures::Key PluginKey;
PluginKey key( node.toElement().elementsByTagName( "key" ).item( 0 ).toElement() );
delete m_instrument;
m_instrument = NULL;
m_instrument = Instrument::instantiate( node.toElement().attribute( "name" ), this );
m_instrument = Instrument::instantiate(
node.toElement().attribute( "name" ), this, &key);
m_instrument->restoreState( node.firstChildElement() );
emit instrumentChanged();
@@ -812,7 +819,8 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement
{
delete m_instrument;
m_instrument = NULL;
m_instrument = Instrument::instantiate( node.nodeName(), this );
m_instrument = Instrument::instantiate(
node.nodeName(), this, nullptr, true);
if( m_instrument->nodeName() == node.nodeName() )
{
m_instrument->restoreState( node.toElement() );
@@ -837,15 +845,20 @@ void InstrumentTrack::setPreviewMode( const bool value )
Instrument * InstrumentTrack::loadInstrument( const QString & _plugin_name )
Instrument * InstrumentTrack::loadInstrument(const QString & _plugin_name,
const Plugin::Descriptor::SubPluginFeatures::Key *key, bool keyFromDnd)
{
if(keyFromDnd)
Q_ASSERT(!key);
silenceAllNotes( true );
lock();
delete m_instrument;
m_instrument = Instrument::instantiate( _plugin_name, this );
m_instrument = Instrument::instantiate(_plugin_name, this,
key, keyFromDnd);
unlock();
setName( m_instrument->displayName() );
setName(m_instrument->displayName());
emit instrumentChanged();
@@ -1733,7 +1746,7 @@ void InstrumentTrackWindow::dropEvent( QDropEvent* event )
if( type == "instrument" )
{
m_track->loadInstrument( value );
m_track->loadInstrument( value, nullptr, true /* DnD */ );
Engine::getSong()->setModified();
@@ -1759,7 +1772,9 @@ void InstrumentTrackWindow::dropEvent( QDropEvent* event )
if( !i->descriptor()->supportsFileType( ext ) )
{
i = m_track->loadInstrument( pluginFactory->pluginSupportingExtension(ext).name() );
PluginFactory::PluginInfoAndKey piakn =
pluginFactory->pluginSupportingExtension(ext);
i = m_track->loadInstrument(piakn.info.name(), &piakn.key);
}
i->loadFile( value );