Files
lmms/src/core/Plugin.cpp
2019-03-22 18:32:59 +01:00

316 lines
6.6 KiB
C++

/*
* Plugin.cpp - implementation of plugin-class including plugin-loader
*
* Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#include "Plugin.h"
#include <QtGlobal>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QLibrary>
#include <QMessageBox>
#include "embed.h"
#include "Engine.h"
#include "GuiApplication.h"
#include "DummyPlugin.h"
#include "AutomatableModel.h"
#include "Song.h"
static PixmapLoader dummyLoader;
static Plugin::Descriptor dummyPluginDescriptor =
{
"dummy",
"dummy",
QT_TRANSLATE_NOOP( "pluginBrowser", "no description" ),
"Tobias Doerffel <tobydox/at/users.sf.net>",
0x0100,
Plugin::Undefined,
&dummyLoader,
NULL
} ;
Plugin::Plugin(const Descriptor * descriptor, Model * parent, const
Descriptor::SubPluginFeatures::Key* key) :
Model(parent),
JournallingObject(),
m_descriptor(descriptor),
m_key(key ? *key : Descriptor::SubPluginFeatures::Key(m_descriptor))
{
if( m_descriptor == NULL )
{
m_descriptor = &dummyPluginDescriptor;
}
}
Plugin::~Plugin()
{
}
template<class T>
T use_this_or(T this_param, T or_param)
{
return this_param ? this_param : 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
? (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;
}
QString Plugin::Descriptor::SubPluginFeatures::Key::additionalFileExtensions() const
{
Q_ASSERT(isValid());
return desc->subPluginFeatures
// get from sub plugin
? desc->subPluginFeatures->additionalFileExtensions(*this)
// no sub plugin, so no *additional* file extensions
: QString();
}
QString Plugin::Descriptor::SubPluginFeatures::Key::displayName() const
{
Q_ASSERT(isValid());
return desc->subPluginFeatures
// get from sub plugin
? use_this_or(desc->subPluginFeatures->displayName(*this),
QString::fromUtf8(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;
}
QString Plugin::Descriptor::SubPluginFeatures::Key::description() const
{
Q_ASSERT(isValid());
return desc->subPluginFeatures
? use_this_or(desc->subPluginFeatures->description(*this),
QString::fromUtf8(desc->description))
: desc->description;
}
void Plugin::loadFile( const QString & )
{
}
AutomatableModel * Plugin::childModel( const QString & )
{
static FloatModel fm;
return &fm;
}
#include "PluginFactory.h"
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());
Plugin* inst;
if( pi.isNull() )
{
if( gui )
{
QMessageBox::information( NULL,
tr( "Plugin not found" ),
tr( "The plugin \"%1\" wasn't found or could not be loaded!\nReason: \"%2\"" ).
arg( pluginName ).arg( pluginFactory->errorString(pluginName) ),
QMessageBox::Ok | QMessageBox::Default );
}
inst = new DummyPlugin();
}
else
{
InstantiationHook instantiationHook;
if ((instantiationHook = ( InstantiationHook ) pi.library->resolve( "lmms_plugin_main" )))
{
inst = instantiationHook(parent, data);
if(!inst) {
inst = new DummyPlugin();
}
}
else
{
if( gui )
{
QMessageBox::information( NULL,
tr( "Error while loading plugin" ),
tr( "Failed to load plugin \"%1\"!").arg( pluginName ),
QMessageBox::Ok | QMessageBox::Default );
}
inst = new DummyPlugin();
}
}
return inst;
}
void Plugin::collectErrorForUI( QString errMsg )
{
Engine::getSong()->collectError( errMsg );
}
PluginView * Plugin::createView( QWidget * parent )
{
PluginView * pv = instantiateView( parent );
if( pv != NULL )
{
pv->setModel( this );
}
return pv;
}
Plugin::Descriptor::SubPluginFeatures::Key::Key( const QDomElement & key ) :
desc( NULL ),
name( key.attribute( "key" ) ),
attributes()
{
QDomNodeList l = key.elementsByTagName( "attribute" );
for( int i = 0; !l.item( i ).isNull(); ++i )
{
QDomElement e = l.item( i ).toElement();
attributes[e.attribute( "name" )] = e.attribute( "value" );
}
}
QDomElement Plugin::Descriptor::SubPluginFeatures::Key::saveXML(
QDomDocument & doc ) const
{
QDomElement e = doc.createElement( "key" );
for( AttributeMap::ConstIterator it = attributes.begin();
it != attributes.end(); ++it )
{
QDomElement a = doc.createElement( "attribute" );
a.setAttribute( "name", it.key() );
a.setAttribute( "value", it.value() );
e.appendChild( a );
}
return e;
}