From a1b355828e347b8e7fca8118873fc834953c1d67 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Thu, 27 Dec 2018 18:43:13 +0100 Subject: [PATCH 1/8] 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) --- include/Effect.h | 7 - include/Engine.h | 4 + include/Instrument.h | 15 +- include/InstrumentTrack.h | 5 +- include/Ladspa2LMMS.h | 2 + include/Plugin.h | 169 +++++++++++++++--- include/PluginBrowser.h | 5 +- include/PluginFactory.h | 24 ++- plugins/FreeBoy/FreeBoy.cpp | 4 +- plugins/GigPlayer/GigPlayer.cpp | 4 +- .../LadspaEffect/LadspaSubPluginFeatures.cpp | 10 ++ .../LadspaEffect/LadspaSubPluginFeatures.h | 12 +- plugins/OpulenZ/OpulenZ.cpp | 4 +- plugins/Xpressive/Xpressive.cpp | 4 +- .../audio_file_processor.cpp | 5 +- plugins/bit_invader/bit_invader.cpp | 4 +- plugins/carlapatchbay/carlapatchbay.cpp | 4 +- plugins/carlarack/carlarack.cpp | 4 +- plugins/kicker/kicker.cpp | 4 +- plugins/lb302/lb302.cpp | 4 +- plugins/monstro/Monstro.cpp | 4 +- plugins/nes/Nes.cpp | 4 +- plugins/organic/organic.cpp | 4 +- plugins/patman/patman.cpp | 4 +- plugins/sf2_player/sf2_player.cpp | 4 +- plugins/sfxr/sfxr.cpp | 4 +- plugins/sid/sid_instrument.cpp | 5 +- plugins/stk/mallets/mallets.cpp | 4 +- .../triple_oscillator/TripleOscillator.cpp | 4 +- plugins/vestige/vestige.cpp | 4 +- plugins/vibed/vibed.cpp | 4 +- plugins/watsyn/Watsyn.cpp | 4 +- plugins/zynaddsubfx/ZynAddSubFx.cpp | 5 +- src/core/Effect.cpp | 5 +- src/core/Engine.cpp | 21 +++ src/core/Instrument.cpp | 27 ++- src/core/LadspaManager.cpp | 2 +- src/core/Plugin.cpp | 137 +++++++++++++- src/core/PluginFactory.cpp | 109 +++++++---- src/core/PresetPreviewPlayHandle.cpp | 4 +- src/gui/EffectSelectDialog.cpp | 100 +++++------ src/gui/FileBrowser.cpp | 11 +- src/gui/InstrumentView.cpp | 2 +- src/gui/PluginBrowser.cpp | 44 +++-- src/gui/TrackContainerView.cpp | 8 +- src/gui/widgets/TrackLabelButton.cpp | 8 +- src/tracks/InstrumentTrack.cpp | 31 +++- 47 files changed, 612 insertions(+), 245 deletions(-) diff --git a/include/Effect.h b/include/Effect.h index d6aa04d97..3d765fdc0 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -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; diff --git a/include/Engine.h b/include/Engine.h index fc2547996..18960ec8f 100644 --- a/include/Engine.h +++ b/include/Engine.h @@ -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; diff --git a/include/Instrument.h b/include/Instrument.h index a373ae4ac..c3df04729 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -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; diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index fb12e825a..dd78b2f9a 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -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() { diff --git a/include/Ladspa2LMMS.h b/include/Ladspa2LMMS.h index 14899487c..28fa25b89 100644 --- a/include/Ladspa2LMMS.h +++ b/include/Ladspa2LMMS.h @@ -30,6 +30,8 @@ #include "LadspaManager.h" +//! Class responsible for sorting found plugins (by LadspaManager) +//! into categories class LMMS_EXPORT Ladspa2LMMS : public LadspaManager { public: diff --git a/include/Plugin.h b/include/Plugin.h index a2cc7d696..034d8a06c 100644 --- a/include/Plugin.h +++ b/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 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 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 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 * ); diff --git a/include/PluginBrowser.h b/include/PluginBrowser.h index 75c7cd291..f7c46db72 100644 --- a/include/PluginBrowser.h +++ b/include/PluginBrowser.h @@ -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; diff --git a/include/PluginFactory.h b/include/PluginFactory.h index 56d32c4e4..17b178108 100644 --- a/include/PluginFactory.h +++ b/include/PluginFactory.h @@ -26,10 +26,13 @@ #define PLUGINFACTORY_H #include +#include #include #include #include +#include +#include #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 library; - Plugin::Descriptor* descriptor; + std::shared_ptr 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 m_pluginByExt; + + QMap m_pluginByExt; + QVector m_garbage; //!< cleaned up at destruction QHash m_errors; diff --git a/plugins/FreeBoy/FreeBoy.cpp b/plugins/FreeBoy/FreeBoy.cpp index dd05444a6..7e5252344 100644 --- a/plugins/FreeBoy/FreeBoy.cpp +++ b/plugins/FreeBoy/FreeBoy.cpp @@ -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( _data ) ) ); + static_cast( m ) ) ); } diff --git a/plugins/GigPlayer/GigPlayer.cpp b/plugins/GigPlayer/GigPlayer.cpp index bf5990252..200439dae 100644 --- a/plugins/GigPlayer/GigPlayer.cpp +++ b/plugins/GigPlayer/GigPlayer.cpp @@ -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( _data ) ); + return new GigInstrument( static_cast( m ) ); } } diff --git a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp index e9344e943..1b055fe73 100644 --- a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp +++ b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp @@ -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 { diff --git a/plugins/LadspaEffect/LadspaSubPluginFeatures.h b/plugins/LadspaEffect/LadspaSubPluginFeatures.h index 904c8133b..b7613827b 100644 --- a/plugins/LadspaEffect/LadspaSubPluginFeatures.h +++ b/plugins/LadspaEffect/LadspaSubPluginFeatures.h @@ -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 ); diff --git a/plugins/OpulenZ/OpulenZ.cpp b/plugins/OpulenZ/OpulenZ.cpp index d8d5f3e26..8e5b7f098 100644 --- a/plugins/OpulenZ/OpulenZ.cpp +++ b/plugins/OpulenZ/OpulenZ.cpp @@ -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( _data ) ) ); + return( new OpulenzInstrument( static_cast( m ) ) ); } } diff --git a/plugins/Xpressive/Xpressive.cpp b/plugins/Xpressive/Xpressive.cpp index cb0293710..f0154f75b 100644 --- a/plugins/Xpressive/Xpressive.cpp +++ b/plugins/Xpressive/Xpressive.cpp @@ -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(_data))); +PLUGIN_EXPORT Plugin * lmms_plugin_main(Model *m, void *) { + return (new Xpressive(static_cast(m))); } } diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index 6c080f7c9..ce14e1ac2 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -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( _data ) ); + return new audioFileProcessor(static_cast(model)); } diff --git a/plugins/bit_invader/bit_invader.cpp b/plugins/bit_invader/bit_invader.cpp index ecc77be0b..c370c409c 100644 --- a/plugins/bit_invader/bit_invader.cpp +++ b/plugins/bit_invader/bit_invader.cpp @@ -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( _data ) ) ); + return( new bitInvader( static_cast( m ) ) ); } diff --git a/plugins/carlapatchbay/carlapatchbay.cpp b/plugins/carlapatchbay/carlapatchbay.cpp index 69c71ce68..60e022156 100644 --- a/plugins/carlapatchbay/carlapatchbay.cpp +++ b/plugins/carlapatchbay/carlapatchbay.cpp @@ -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(data), &carlapatchbay_plugin_descriptor, true); + return new CarlaInstrument(static_cast(m), &carlapatchbay_plugin_descriptor, true); } } diff --git a/plugins/carlarack/carlarack.cpp b/plugins/carlarack/carlarack.cpp index 8bc7d372d..d057eff83 100644 --- a/plugins/carlarack/carlarack.cpp +++ b/plugins/carlarack/carlarack.cpp @@ -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(data), &carlarack_plugin_descriptor, false); + return new CarlaInstrument(static_cast(m), &carlarack_plugin_descriptor, false); } } diff --git a/plugins/kicker/kicker.cpp b/plugins/kicker/kicker.cpp index 2087cf880..d204babab 100644 --- a/plugins/kicker/kicker.cpp +++ b/plugins/kicker/kicker.cpp @@ -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( _data ) ); + return new kickerInstrument( static_cast( m ) ); } diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index d32f14e88..e556e42bf 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -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( _data ) ) ); + static_cast( m ) ) ); } diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index baee242bb..fb089aa0c 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -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( _data ) ); + return new MonstroInstrument( static_cast( m ) ); } diff --git a/plugins/nes/Nes.cpp b/plugins/nes/Nes.cpp index 5b34dcb1f..ba64edb06 100644 --- a/plugins/nes/Nes.cpp +++ b/plugins/nes/Nes.cpp @@ -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( _data ) ) ); + return( new NesInstrument( static_cast( m ) ) ); } diff --git a/plugins/organic/organic.cpp b/plugins/organic/organic.cpp index b6d45c8d3..63aee0dc6 100644 --- a/plugins/organic/organic.cpp +++ b/plugins/organic/organic.cpp @@ -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( _data ) ) ); + return( new organicInstrument( static_cast( m ) ) ); } diff --git a/plugins/patman/patman.cpp b/plugins/patman/patman.cpp index 6ab7adce7..0ea9968da 100644 --- a/plugins/patman/patman.cpp +++ b/plugins/patman/patman.cpp @@ -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( _data ) ); + return new patmanInstrument( static_cast( m ) ); } } diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 4bf75777c..138e8165d 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -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( _data ) ); + return new sf2Instrument( static_cast( m ) ); } diff --git a/plugins/sfxr/sfxr.cpp b/plugins/sfxr/sfxr.cpp index c99f46f88..2718d66d7 100644 --- a/plugins/sfxr/sfxr.cpp +++ b/plugins/sfxr/sfxr.cpp @@ -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( data ) ); + return new sfxrInstrument( static_cast( m ) ); } diff --git a/plugins/sid/sid_instrument.cpp b/plugins/sid/sid_instrument.cpp index 2eb46be56..024e9ae61 100644 --- a/plugins/sid/sid_instrument.cpp +++ b/plugins/sid/sid_instrument.cpp @@ -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( _data ) ) ); + return( new sidInstrument( static_cast( m ) ) ); } diff --git a/plugins/stk/mallets/mallets.cpp b/plugins/stk/mallets/mallets.cpp index 7111bcdaa..ee1e1fbc3 100644 --- a/plugins/stk/mallets/mallets.cpp +++ b/plugins/stk/mallets/mallets.cpp @@ -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( _data ) ); + return new malletsInstrument( static_cast( m ) ); } diff --git a/plugins/triple_oscillator/TripleOscillator.cpp b/plugins/triple_oscillator/TripleOscillator.cpp index 6b644fd46..a883f75fa 100644 --- a/plugins/triple_oscillator/TripleOscillator.cpp +++ b/plugins/triple_oscillator/TripleOscillator.cpp @@ -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( _data ) ); + return new TripleOscillator( static_cast( model ) ); } } diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 73ea33a51..fe91358b3 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -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( _data ) ); + return new vestigeInstrument( static_cast( m ) ); } diff --git a/plugins/vibed/vibed.cpp b/plugins/vibed/vibed.cpp index f33a90428..bde5c8917 100644 --- a/plugins/vibed/vibed.cpp +++ b/plugins/vibed/vibed.cpp @@ -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( _data ) ) ); + return( new vibed( static_cast( m ) ) ); } diff --git a/plugins/watsyn/Watsyn.cpp b/plugins/watsyn/Watsyn.cpp index 0122b293a..2787e39b7 100644 --- a/plugins/watsyn/Watsyn.cpp +++ b/plugins/watsyn/Watsyn.cpp @@ -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( _data ) ) ); + return( new WatsynInstrument( static_cast( m ) ) ); } diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index ad8d9a78c..8235ad147 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -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( _data ) ); + return new ZynAddSubFxInstrument(static_cast(m)); } diff --git a/src/core/Effect.cpp b/src/core/Effect.cpp index 8cdcc9c60..c84297753 100644 --- a/src/core/Effect.cpp +++ b/src/core/Effect.cpp @@ -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( p ) != NULL ) { diff --git a/src/core/Engine.cpp b/src/core/Engine.cpp index a53abbe5d..7f89c20f3 100644 --- a/src/core/Engine.cpp +++ b/src/core/Engine.cpp @@ -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(newKey)); + s_dndPluginKey = newKey; +} + + + + +void *LmmsCore::pickDndPluginKey() +{ + return s_dndPluginKey; +} + + + + LmmsCore * LmmsCore::s_instanceOfMe = NULL; diff --git a/src/core/Instrument.cpp b/src/core/Instrument.cpp index 534bb783a..ba608da14 100644 --- a/src/core/Instrument.cpp +++ b/src/core/Instrument.cpp @@ -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( p ) != NULL ) - { - // everything ok, so return pointer - return dynamic_cast( 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(p)) + return dynamic_cast(p); delete p; return( new DummyInstrument( _instrument_track ) ); } diff --git a/src/core/LadspaManager.cpp b/src/core/LadspaManager.cpp index 4336e50a5..febbe5a91 100644 --- a/src/core/LadspaManager.cpp +++ b/src/core/LadspaManager.cpp @@ -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 ); diff --git a/src/core/Plugin.cpp b/src/core/Plugin.cpp index b479d7d8d..e7f80b5ab 100644 --- a/src/core/Plugin.cpp +++ b/src/core/Plugin.cpp @@ -22,11 +22,15 @@ * */ +#include #include #include #include #include +// 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 +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(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(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( } - diff --git a/src/core/PluginFactory.cpp b/src/core/PluginFactory.cpp index a87e49270..a25dca54a 100644 --- a/src/core/PluginFactory.cpp +++ b/src/core/PluginFactory.cpp @@ -28,8 +28,11 @@ #include #include #include +#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::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(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(library->resolve(descriptorName.toUtf8().constData())); - if(pluginDescriptor == nullptr) + pluginDescriptor = reinterpret_cast(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; diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index dc36819b7..ca0e52194 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -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 ) { diff --git a/src/gui/EffectSelectDialog.cpp b/src/gui/EffectSelectDialog.cpp index 64b180d48..4b59a19b1 100644 --- a/src/gui/EffectSelectDialog.cpp +++ b/src/gui/EffectSelectDialog.cpp @@ -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() ) - { - 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() ) + { + if( w->parent() == subWidget ) + { + subLayout->addWidget( w ); + } + } - textWidgetLayout->addWidget(subWidget); - } - else - { - QLabel *label = new QLabel(m_descriptionWidget); - QString labelText = "

" + tr("Name") + ": " + QString::fromUtf8(descriptor.displayName) + "

"; - labelText += "

" + tr("Description") + ": " + qApp->translate( "pluginBrowser", descriptor.description ) + "

"; - labelText += "

" + tr("Author") + ": " + QString::fromUtf8(descriptor.author) + "

"; + textWidgetLayout->addWidget(subWidget); + } + else + { + QLabel *label = new QLabel(m_descriptionWidget); + QString labelText = "

" + tr("Name") + ": " + QString::fromUtf8(descriptor.displayName) + "

"; + labelText += "

" + tr("Description") + ": " + qApp->translate( "pluginBrowser", descriptor.description ) + "

"; + labelText += "

" + tr("Author") + ": " + QString::fromUtf8(descriptor.author) + "

"; - 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(); } } diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 05727d332..4311e4e05 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -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; diff --git a/src/gui/InstrumentView.cpp b/src/gui/InstrumentView.cpp index 9e8fc58c1..93e153f6f 100644 --- a/src/gui/InstrumentView.cpp +++ b/src/gui/InstrumentView.cpp @@ -57,7 +57,7 @@ void InstrumentView::setModel( Model * _model, bool ) if( dynamic_cast( _model ) != NULL ) { ModelView::setModel( _model ); - instrumentTrackWindow()->setWindowIcon( model()->descriptor()->logo->pixmap() ); + instrumentTrackWindow()->setWindowIcon( model()->logo()->pixmap() ); connect( model(), SIGNAL( destroyed( QObject * ) ), this, SLOT( close() ) ); } } diff --git a/src/gui/PluginBrowser.cpp b/src/gui/PluginBrowser.cpp index dc0fc35e0..27747bc53 100644 --- a/src/gui/PluginBrowser.cpp +++ b/src/gui/PluginBrowser.cpp @@ -31,6 +31,7 @@ #include #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 ); } } diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index 2772ef104..7c69d5eb8 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -384,8 +384,9 @@ void TrackContainerView::dropEvent( QDropEvent * _de ) InstrumentTrack * it = dynamic_cast( 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 ); diff --git a/src/gui/widgets/TrackLabelButton.cpp b/src/gui/widgets/TrackLabelButton.cpp index db310a05e..361db740e 100644 --- a/src/gui/widgets/TrackLabelButton.cpp +++ b/src/gui/widgets/TrackLabelButton.cpp @@ -195,9 +195,15 @@ void TrackLabelButton::paintEvent( QPaintEvent * _pe ) InstrumentTrack * it = dynamic_cast( 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 ) { diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 298430b03..2b25982df 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -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 ); From 4d64c422b22f3176aea30955575ab3af287e9e4f Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Thu, 27 Dec 2018 21:59:50 +0100 Subject: [PATCH 2/8] Fix Engine.cpp not compiling on some compilers --- src/core/Engine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/Engine.cpp b/src/core/Engine.cpp index 7f89c20f3..50e25b0b4 100644 --- a/src/core/Engine.cpp +++ b/src/core/Engine.cpp @@ -29,6 +29,7 @@ #include "FxMixer.h" #include "Ladspa2LMMS.h" #include "Mixer.h" +#include "Plugin.h" #include "PresetPreviewPlayHandle.h" #include "ProjectJournal.h" #include "Song.h" @@ -118,7 +119,7 @@ void LmmsCore::updateFramesPerTick() void LmmsCore::setDndPluginKey(void *newKey) { - assert(static_cast(newKey)); + Q_ASSERT(static_cast(newKey)); s_dndPluginKey = newKey; } From fcd1a7ee86ca4e1471176853b28fb66762c124f7 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Thu, 27 Dec 2018 22:15:56 +0100 Subject: [PATCH 3/8] Fix or remove wrong or useless debug printfs --- src/core/Plugin.cpp | 1 - src/core/PluginFactory.cpp | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/core/Plugin.cpp b/src/core/Plugin.cpp index e7f80b5ab..7fcbd9795 100644 --- a/src/core/Plugin.cpp +++ b/src/core/Plugin.cpp @@ -220,7 +220,6 @@ Plugin * Plugin::instantiate(const QString& pluginName, Model * parent, } return new DummyPlugin(); } - qDebug() << "Using PluginInfo for " << pluginName; Plugin* inst; InstantiationHook instantiationHook; diff --git a/src/core/PluginFactory.cpp b/src/core/PluginFactory.cpp index a25dca54a..ec390ae6e 100644 --- a/src/core/PluginFactory.cpp +++ b/src/core/PluginFactory.cpp @@ -182,7 +182,7 @@ void PluginFactory::discoverPlugins() } else { - qDebug() << "Ignoring" << file << "(no lmms_plugin_main())"; + //qDebug() << "Ignoring" << file.absoluteFilePath() << "(no lmms_plugin_main())"; } if(pluginDescriptor) @@ -193,9 +193,6 @@ void PluginFactory::discoverPlugins() info.descriptor = pluginDescriptor; pluginInfos << info; - qDebug() << "Add" << info.file << "with type" - << info.descriptor->type; - auto addSupportedFileTypes = [this](const char* supportedFileTypes, const PluginInfo& info, @@ -204,7 +201,7 @@ void PluginFactory::discoverPlugins() if(supportedFileTypes) for (const QString& ext : QString(supportedFileTypes).split(',')) { - qDebug() << "Plugin " << info.name() << "supports" << ext; + //qDebug() << "Plugin " << info.name() << "supports" << ext; PluginInfoAndKey infoAndKey; infoAndKey.info = info; infoAndKey.key = key From f3b23830fbd9ef57ea9b1c6a2ad4aab7649881a0 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Thu, 27 Dec 2018 22:37:34 +0100 Subject: [PATCH 4/8] Fix missing IntrumentTrack header --- plugins/carlapatchbay/carlapatchbay.cpp | 1 + plugins/carlarack/carlarack.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/carlapatchbay/carlapatchbay.cpp b/plugins/carlapatchbay/carlapatchbay.cpp index 60e022156..ac00630d4 100644 --- a/plugins/carlapatchbay/carlapatchbay.cpp +++ b/plugins/carlapatchbay/carlapatchbay.cpp @@ -25,6 +25,7 @@ #include "carla.h" #include "embed.h" +#include "InstrumentTrack.h" extern "C" { diff --git a/plugins/carlarack/carlarack.cpp b/plugins/carlarack/carlarack.cpp index d057eff83..c0a39f9c2 100644 --- a/plugins/carlarack/carlarack.cpp +++ b/plugins/carlarack/carlarack.cpp @@ -25,6 +25,7 @@ #include "carla.h" #include "embed.h" +#include "InstrumentTrack.h" extern "C" { From d5dcebed83b21928975a641834dc08875407ff4e Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 18 Jan 2019 23:22:52 +0100 Subject: [PATCH 5/8] Use QString for SubPluginFeatures' virtuals The former virtuals returned `const char*`, which lead to invalid reads when `LadspaSubPluginFeatures` returned pointers to temporary `QByteArray::data`. --- include/Plugin.h | 12 +++++------ .../LadspaEffect/LadspaSubPluginFeatures.cpp | 4 ++-- .../LadspaEffect/LadspaSubPluginFeatures.h | 2 +- src/core/Plugin.cpp | 20 ++++++++++++++----- src/core/PluginFactory.cpp | 8 ++++---- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/include/Plugin.h b/include/Plugin.h index 034d8a06c..48c5f90c7 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -165,9 +165,9 @@ public: // 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; + QString additionalFileExtensions() const; + QString displayName() const; + QString description() const; const PixmapLoader* logo() const; } ; @@ -200,19 +200,19 @@ public: // The defaults are sane, i.e. redirect to sub plugins // supererior descriptor - virtual const char* additionalFileExtensions(const Key&) const + virtual QString additionalFileExtensions(const Key&) const { return nullptr; } - virtual const char* displayName(const Key& k) const + virtual QString displayName(const Key& k) const { return k.isValid() ? k.desc->displayName : k.name.toUtf8().data(); } - virtual const char* description(const Key& k) const + virtual QString description(const Key& k) const { return k.isValid() ? k.desc->description : ""; } diff --git a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp index 1b055fe73..4cefa90b5 100644 --- a/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp +++ b/plugins/LadspaEffect/LadspaSubPluginFeatures.cpp @@ -44,11 +44,11 @@ LadspaSubPluginFeatures::LadspaSubPluginFeatures( Plugin::PluginTypes _type ) : -const char *LadspaSubPluginFeatures::displayName(const Plugin::Descriptor::SubPluginFeatures::Key &k) const +QString 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(); + return lm->getName(lkey); } diff --git a/plugins/LadspaEffect/LadspaSubPluginFeatures.h b/plugins/LadspaEffect/LadspaSubPluginFeatures.h index b7613827b..3f47734f9 100644 --- a/plugins/LadspaEffect/LadspaSubPluginFeatures.h +++ b/plugins/LadspaEffect/LadspaSubPluginFeatures.h @@ -37,7 +37,7 @@ class LadspaSubPluginFeatures : public Plugin::Descriptor::SubPluginFeatures public: LadspaSubPluginFeatures( Plugin::PluginTypes _type ); - const char* displayName(const Key& k) const override; + QString displayName(const Key& k) const override; void fillDescriptionWidget( QWidget * _parent, const Key * _key ) const override; diff --git a/src/core/Plugin.cpp b/src/core/Plugin.cpp index 7fcbd9795..2975cf104 100644 --- a/src/core/Plugin.cpp +++ b/src/core/Plugin.cpp @@ -89,6 +89,14 @@ T use_this_or(T this_param, T or_param) +QString use_this_or(QString this_param, QString or_param) +{ + return this_param.isNull() ? or_param : this_param; +} + + + + QString Plugin::displayName() const { return Model::displayName().isEmpty() // currently always empty @@ -113,7 +121,7 @@ const PixmapLoader* Plugin::logo() const -const char *Plugin::Descriptor::SubPluginFeatures::Key::additionalFileExtensions() const +QString Plugin::Descriptor::SubPluginFeatures::Key::additionalFileExtensions() const { Q_ASSERT(isValid()); return desc->subPluginFeatures @@ -126,12 +134,13 @@ const char *Plugin::Descriptor::SubPluginFeatures::Key::additionalFileExtensions -const char* Plugin::Descriptor::SubPluginFeatures::Key::displayName() const +QString 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) + ? use_this_or(desc->subPluginFeatures->displayName(*this), + QString::fromUtf8(desc->displayName)) // get from plugin : desc->displayName; } @@ -150,11 +159,12 @@ const PixmapLoader* Plugin::Descriptor::SubPluginFeatures::Key::logo() const -const char *Plugin::Descriptor::SubPluginFeatures::Key::description() const +QString Plugin::Descriptor::SubPluginFeatures::Key::description() const { Q_ASSERT(isValid()); return desc->subPluginFeatures - ? use_this_or(desc->subPluginFeatures->description(*this), desc->description) + ? use_this_or(desc->subPluginFeatures->description(*this), + QString::fromUtf8(desc->description)) : desc->description; } diff --git a/src/core/PluginFactory.cpp b/src/core/PluginFactory.cpp index ec390ae6e..f84227091 100644 --- a/src/core/PluginFactory.cpp +++ b/src/core/PluginFactory.cpp @@ -194,12 +194,12 @@ void PluginFactory::discoverPlugins() pluginInfos << info; auto addSupportedFileTypes = - [this](const char* supportedFileTypes, + [this](QString supportedFileTypes, const PluginInfo& info, const Plugin::Descriptor::SubPluginFeatures::Key* key = nullptr) { - if(supportedFileTypes) - for (const QString& ext : QString(supportedFileTypes).split(',')) + if(!supportedFileTypes.isNull()) + for (const QString& ext : supportedFileTypes.split(',')) { //qDebug() << "Plugin " << info.name() << "supports" << ext; PluginInfoAndKey infoAndKey; @@ -212,7 +212,7 @@ void PluginFactory::discoverPlugins() }; if (info.descriptor->supportedFileTypes) - addSupportedFileTypes(info.descriptor->supportedFileTypes, info); + addSupportedFileTypes(QString(info.descriptor->supportedFileTypes), info); if (info.descriptor->subPluginFeatures) { From 2d71d6163bf9bb3bbdc715a265209397d58c8c1c Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 15 Mar 2019 18:42:34 +0100 Subject: [PATCH 6/8] Rework after code reading * Fix possible segfault in `SubPluginFeatures::displayName` * Minor fixes --- include/Plugin.h | 6 +++--- src/core/Plugin.cpp | 4 ++-- src/core/PluginFactory.cpp | 23 +++++++++++------------ 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/include/Plugin.h b/include/Plugin.h index 48c5f90c7..31c83c4ba 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -202,19 +202,19 @@ public: virtual QString additionalFileExtensions(const Key&) const { - return nullptr; + return QString(); } virtual QString displayName(const Key& k) const { return k.isValid() ? k.desc->displayName - : k.name.toUtf8().data(); + : k.name; } virtual QString description(const Key& k) const { - return k.isValid() ? k.desc->description : ""; + return k.isValid() ? k.desc->description : QString(); } virtual const PixmapLoader* logo(const Key& k) const diff --git a/src/core/Plugin.cpp b/src/core/Plugin.cpp index 2975cf104..1562044f9 100644 --- a/src/core/Plugin.cpp +++ b/src/core/Plugin.cpp @@ -127,8 +127,8 @@ QString Plugin::Descriptor::SubPluginFeatures::Key::additionalFileExtensions() c return desc->subPluginFeatures // get from sub plugin ? desc->subPluginFeatures->additionalFileExtensions(*this) - // get from plugin - : nullptr; + // no sub plugin, so no *additional* file extensions + : QString(); } diff --git a/src/core/PluginFactory.cpp b/src/core/PluginFactory.cpp index f84227091..abf642122 100644 --- a/src/core/PluginFactory.cpp +++ b/src/core/PluginFactory.cpp @@ -180,10 +180,6 @@ void PluginFactory::discoverPlugins() continue; } } - else - { - //qDebug() << "Ignoring" << file.absoluteFilePath() << "(no lmms_plugin_main())"; - } if(pluginDescriptor) { @@ -199,15 +195,18 @@ void PluginFactory::discoverPlugins() const Plugin::Descriptor::SubPluginFeatures::Key* key = nullptr) { if(!supportedFileTypes.isNull()) - for (const QString& ext : 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); + for (const QString& ext : 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); + } } }; From 52d1f5588a02cad0adbec46a3ce3435f003402a3 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Mar 2019 11:20:37 +0100 Subject: [PATCH 7/8] Remove useless include --- include/Plugin.h | 4 ++-- src/core/Plugin.cpp | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/include/Plugin.h b/include/Plugin.h index 31c83c4ba..9a0757c35 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -196,8 +196,8 @@ public: private: - // You can add stuff values mapped by "Key" below - // The defaults are sane, i.e. redirect to sub plugins + // You can add values mapped by "Key" below + // The defaults are sane, i.e. redirect to sub plugin's // supererior descriptor virtual QString additionalFileExtensions(const Key&) const diff --git a/src/core/Plugin.cpp b/src/core/Plugin.cpp index cd1cf8b99..411f6fe58 100644 --- a/src/core/Plugin.cpp +++ b/src/core/Plugin.cpp @@ -22,16 +22,14 @@ * */ +#include "Plugin.h" + #include #include #include #include #include -// comment separator to prevent clang's header sorting -#include "lmmsconfig.h" - -#include "Plugin.h" #include "embed.h" #include "Engine.h" #include "GuiApplication.h" @@ -314,3 +312,4 @@ QDomElement Plugin::Descriptor::SubPluginFeatures::Key::saveXML( } + From 34835811e1877191ac46c34012015c67965e5dc7 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Mar 2019 20:35:21 +0100 Subject: [PATCH 8/8] Fix invalid display names --- include/Plugin.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/Plugin.h b/include/Plugin.h index 9a0757c35..af42b0f10 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -207,9 +207,7 @@ public: virtual QString displayName(const Key& k) const { - return k.isValid() - ? k.desc->displayName - : k.name; + return k.isValid() ? k.name : QString(); } virtual QString description(const Key& k) const