From 739aee858e73574631fbefb9d6161c2b501c2682 Mon Sep 17 00:00:00 2001 From: trialuser02 Date: Sun, 12 May 2013 10:08:23 +0000 Subject: added plugin cache git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@3441 90c681e8-e032-0410-971d-27865f9a5e38 --- src/plugins/General/mpris/mpris2/root2object.cpp | 2 +- src/qmmp/decoder.cpp | 166 +++++++++++------------ src/qmmp/decoder.h | 8 +- src/qmmp/metadatamanager.cpp | 6 +- src/qmmp/output.cpp | 10 +- src/qmmp/plugincache.cpp | 125 +++++++++++++++++ src/qmmp/plugincache.h | 57 ++++++++ src/qmmp/qmmp.pro | 6 +- src/qmmpui/aboutdialog.cpp | 2 +- src/qmmpui/configdialog.cpp | 2 +- 10 files changed, 280 insertions(+), 104 deletions(-) create mode 100644 src/qmmp/plugincache.cpp create mode 100644 src/qmmp/plugincache.h diff --git a/src/plugins/General/mpris/mpris2/root2object.cpp b/src/plugins/General/mpris/mpris2/root2object.cpp index 5bf47e31f..126a81391 100644 --- a/src/plugins/General/mpris/mpris2/root2object.cpp +++ b/src/plugins/General/mpris/mpris2/root2object.cpp @@ -64,7 +64,7 @@ QString Root2Object::identity() const QStringList Root2Object::supportedMimeTypes() const { QStringList mimeTypes; - foreach(DecoderFactory *factory, *Decoder::factories()) + foreach(DecoderFactory *factory, Decoder::factories()) mimeTypes << factory->properties().contentTypes; foreach(EngineFactory *factory, *AbstractEngine::factories()) mimeTypes << factory->properties().contentTypes; diff --git a/src/qmmp/decoder.cpp b/src/qmmp/decoder.cpp index 2c6b9a469..1f0c1d4c4 100644 --- a/src/qmmp/decoder.cpp +++ b/src/qmmp/decoder.cpp @@ -10,10 +10,7 @@ #include #include #include - -#include "effect.h" -#include "effectfactory.h" - +#include "plugincache.h" #include "buffer.h" #include "output.h" #include "visual.h" @@ -85,82 +82,60 @@ QMap Decoder::takeMetaData() } // static methods -QList *Decoder::m_factories = 0; -QList *Decoder::m_disabledFactories = 0; +QStringList Decoder::m_disabledNames; DecoderFactory *Decoder::m_lastFactory = 0; -QHash *Decoder::m_files = 0; +QList *Decoder::m_cache = 0; -//sort factories by priority -static bool _decoderLessComparator(DecoderFactory* f1, DecoderFactory* f2) +//sort cache items by priority +/*static bool _decoderLessComparator(DecoderFactory* f1, DecoderFactory* f2) { return f1->properties().priority < f2->properties().priority; -} +}*/ void Decoder::checkFactories() { - if (!m_factories) - { - QSettings settings (Qmmp::configFile(), QSettings::IniFormat); - QStringList disabledNames = settings.value("Decoder/disabled_plugins").toStringList (); - - m_factories = new QList; - m_disabledFactories = new QList; - m_files = new QHash ; + if (m_cache) + return; - QDir pluginsDir (Qmmp::pluginsPath()); - pluginsDir.cd("Input"); - foreach (QString fileName, pluginsDir.entryList(QDir::Files)) - { - QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); - QObject *plugin = loader.instance(); - if (loader.isLoaded()) - qDebug("Decoder: loaded plugin %s", qPrintable(fileName)); - else - qWarning("Decoder: %s", qPrintable(loader.errorString ())); - DecoderFactory *factory = 0; - - if (plugin) - factory = qobject_cast(plugin); - - if (factory) - { - m_factories->append(factory); - m_files->insert(factory, pluginsDir.absoluteFilePath(fileName)); - qApp->installTranslator(factory->createTranslator(qApp)); - if(disabledNames.contains(factory->properties().shortName)) - m_disabledFactories->append(factory); - } - } - //remove physically deleted plugins from disabled list - QStringList names; - foreach (DecoderFactory *factory, *m_factories) - { - names.append(factory->properties().shortName); - } - foreach (QString name, disabledNames) + m_cache = new QList; + QSettings settings (Qmmp::configFile(), QSettings::IniFormat); + QDir pluginsDir (Qmmp::pluginsPath()); + pluginsDir.cd("Input"); + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + PluginCache *item = new PluginCache(pluginsDir.absoluteFilePath(fileName), &settings); + if(item->hasError()) { - if (!names.contains(name)) - disabledNames.removeAll(name); + delete item; + continue; } - settings.setValue("Decoder/disabled_plugins",disabledNames); - qSort(m_factories->begin(), m_factories->end(), _decoderLessComparator); + m_cache->append(item); } + m_disabledNames = settings.value("Decoder/disabled_plugins").toStringList(); } QString Decoder::file(DecoderFactory *factory) { checkFactories(); - return m_files->value(factory); + foreach(PluginCache *item, *m_cache) + { + if(item->shortName() == factory->properties().shortName) + return item->file(); + } + return QString(); } QStringList Decoder::protocols() { checkFactories(); QStringList protocolsList; - foreach(DecoderFactory *f, *m_factories) + + foreach (PluginCache *item, *m_cache) { - if(isEnabled(f)) - protocolsList << f->properties().protocols; + if(m_disabledNames.contains(item->shortName())) + continue; + if(item->decoderFactory()) + protocolsList << item->decoderFactory()->properties().protocols; } protocolsList.removeDuplicates(); return protocolsList; @@ -190,22 +165,33 @@ DecoderFactory *Decoder::findByPath(const QString& source, bool useContent) return fact; } - foreach(DecoderFactory *fact, *m_factories) + foreach(PluginCache *item, *m_cache) { - if(fact->properties().noInput && !fact->properties().protocols.contains("file")) + if(m_disabledNames.contains(item->shortName())) + continue; + + fact = item->decoderFactory(); + + if(fact && fact->properties().noInput && !fact->properties().protocols.contains("file")) continue; - if (isEnabled(fact) && fact->canDecode(&buffer)) + if (fact->canDecode(&buffer)) { + m_lastFactory = fact; return fact; } } + fact = 0; } - if (fact && fact->supports(source) && isEnabled(fact)) //try last factory + if (fact && isEnabled(fact) && fact->supports(source)) //try last factory return fact; - foreach(fact, *m_factories) + + foreach (PluginCache *item, *m_cache) { - if (fact->supports(source) && isEnabled(fact)) + if(m_disabledNames.contains(item->shortName())) + continue; + DecoderFactory *fact = item->decoderFactory(); + if(fact && fact->supports(source)) { m_lastFactory = fact; return fact; @@ -219,11 +205,12 @@ DecoderFactory *Decoder::findByMime(const QString& type) if(type.isEmpty()) return 0; checkFactories(); - DecoderFactory *fact; - foreach(fact, *m_factories) + foreach (PluginCache *item, *m_cache) { - if (isEnabled(fact) && !fact->properties().noInput - && fact->properties().contentTypes.contains(type)) + if(m_disabledNames.contains(item->shortName())) + continue; + DecoderFactory *fact = item->decoderFactory(); + if(fact && !fact->properties().noInput && fact->properties().contentTypes.contains(type)) return fact; } return 0; @@ -232,12 +219,13 @@ DecoderFactory *Decoder::findByMime(const QString& type) DecoderFactory *Decoder::findByContent(QIODevice *input) { checkFactories(); - foreach(DecoderFactory *fact, *m_factories) + foreach (PluginCache *item, *m_cache) { - if (isEnabled(fact) && !fact->properties().noInput && fact->canDecode(input)) - { + if(m_disabledNames.contains(item->shortName())) + continue; + DecoderFactory *fact = item->decoderFactory(); + if(fact && !fact->properties().noInput && fact->canDecode(input)) return fact; - } } return 0; } @@ -245,10 +233,13 @@ DecoderFactory *Decoder::findByContent(QIODevice *input) DecoderFactory *Decoder::findByProtocol(const QString &p) { checkFactories(); - foreach(DecoderFactory *fact, *m_factories) + foreach (PluginCache *item, *m_cache) { - if (isEnabled(fact) && fact->properties().protocols.contains(p)) - return fact; + if(m_disabledNames.contains(item->shortName())) + continue; + + if (item->decoderFactory() && item->decoderFactory()->properties().protocols.contains(p)) + return item->decoderFactory(); } return 0; } @@ -256,35 +247,36 @@ DecoderFactory *Decoder::findByProtocol(const QString &p) void Decoder::setEnabled(DecoderFactory* factory, bool enable) { checkFactories(); - if (!m_factories->contains(factory)) + if (!factories().contains(factory)) return; if(enable == isEnabled(factory)) return; if(enable) - m_disabledFactories->removeAll(factory); + m_disabledNames.removeAll(factory->properties().shortName); else - m_disabledFactories->append(factory); + m_disabledNames.append(factory->properties().shortName); - QStringList disabledNames; - foreach(DecoderFactory *f, *m_disabledFactories) - { - disabledNames << f->properties().shortName; - } - disabledNames.removeDuplicates(); + m_disabledNames.removeDuplicates(); QSettings settings (Qmmp::configFile(), QSettings::IniFormat); - settings.setValue("Decoder/disabled_plugins", disabledNames); + settings.setValue("Decoder/disabled_plugins", m_disabledNames); } bool Decoder::isEnabled(DecoderFactory* factory) { checkFactories(); - return !m_disabledFactories->contains(factory); + return !m_disabledNames.contains(factory->properties().shortName); } -QList *Decoder::factories() +QList Decoder::factories() { checkFactories(); - return m_factories; + QList list; + foreach (PluginCache *item, *m_cache) + { + if(item->decoderFactory()) + list.append(item->decoderFactory()); + } + return list; } diff --git a/src/qmmp/decoder.h b/src/qmmp/decoder.h index cc0b2d4ee..2b250774d 100644 --- a/src/qmmp/decoder.h +++ b/src/qmmp/decoder.h @@ -20,6 +20,7 @@ class Decoder; class DecoderFactory; class QIODevice; +class PluginCache; /*! @brief The Decoder class provides the base interface class of audio decoders. * @author Brad Hughes @@ -128,7 +129,7 @@ public: /*! * Returns a list of decoder factories. */ - static QList *factories(); + static QList factories(); /*! * Returns plugin file path. * @param factory Decoder plugin factory. @@ -162,10 +163,9 @@ protected: private: static void checkFactories(); - static QList *m_factories; - static QList *m_disabledFactories; static DecoderFactory *m_lastFactory; - static QHash *m_files; + static QList *m_cache; + static QStringList m_disabledNames; AudioParameters m_parameters; QIODevice *m_input; bool m_hasMetaData; diff --git a/src/qmmp/metadatamanager.cpp b/src/qmmp/metadatamanager.cpp index 21bfef294..f0cc7d88c 100644 --- a/src/qmmp/metadatamanager.cpp +++ b/src/qmmp/metadatamanager.cpp @@ -69,7 +69,7 @@ QList MetaDataManager::createPlayList(const QString &fileName, bool list << new FileInfo(fileName); return list; } - foreach(fact, *Decoder::factories()) + foreach(fact, Decoder::factories()) { if(fact->properties().protocols.contains(scheme) && Decoder::isEnabled(fact)) return fact->createPlayList(fileName, useMetaData); @@ -115,7 +115,7 @@ MetaDataModel* MetaDataManager::createMetaDataModel(const QString &path, QObject QStringList MetaDataManager::filters() const { QStringList filters; - foreach(DecoderFactory *fact, *Decoder::factories()) + foreach(DecoderFactory *fact, Decoder::factories()) { if (Decoder::isEnabled(fact) && !fact->properties().filters.isEmpty()) filters << fact->properties().description + " (" + fact->properties().filters.join(" ") + ")"; @@ -131,7 +131,7 @@ QStringList MetaDataManager::filters() const QStringList MetaDataManager::nameFilters() const { QStringList filters; - foreach(DecoderFactory *fact, *Decoder::factories()) + foreach(DecoderFactory *fact, Decoder::factories()) { if (Decoder::isEnabled(fact)) filters << fact->properties().filters; diff --git a/src/qmmp/output.cpp b/src/qmmp/output.cpp index 703696c88..fcc931a16 100644 --- a/src/qmmp/output.cpp +++ b/src/qmmp/output.cpp @@ -78,18 +78,18 @@ void Output::checkFactories() QDir pluginsDir (Qmmp::pluginsPath()); pluginsDir.cd("Output"); - foreach ( QString fileName, pluginsDir.entryList ( QDir::Files ) ) + foreach (QString fileName, pluginsDir.entryList (QDir::Files)) { - QPluginLoader loader ( pluginsDir.absoluteFilePath ( fileName ) ); + QPluginLoader loader (pluginsDir.absoluteFilePath (fileName)); QObject *plugin = loader.instance(); - if ( loader.isLoaded() ) - qDebug ( "Output: loaded plugin %s", qPrintable ( fileName ) ); + if (loader.isLoaded()) + qDebug ("Output: loaded plugin %s", qPrintable (fileName)); else qWarning("Output: %s", qPrintable(loader.errorString ())); OutputFactory *factory = 0; if (plugin) - factory = qobject_cast ( plugin ); + factory = qobject_cast (plugin); if (factory) { diff --git a/src/qmmp/plugincache.cpp b/src/qmmp/plugincache.cpp new file mode 100644 index 000000000..4be3e6164 --- /dev/null +++ b/src/qmmp/plugincache.cpp @@ -0,0 +1,125 @@ +/*************************************************************************** + * Copyright (C) 2013 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "decoderfactory.h" +#include "outputfactory.h" +#include "plugincache.h" + +PluginCache::PluginCache(const QString &file, QSettings *settings) +{ + m_error = false; + m_instance = 0; + m_decoderFactory = 0; + bool update = false; + QFileInfo info(file); + m_path = info.QFileInfo::canonicalFilePath(); + + settings->beginGroup("PluginCache"); + QString copy = m_path; + if(settings->allKeys().contains(copy.remove(0,1))) + { + QStringList values = settings->value(m_path).toStringList(); + if(values.count() != 2) + update = true; + else + { + m_shortName = values.at(0); + update = (info.lastModified().toString(Qt::ISODate) != values.at(1)); + } + } + else + update = true; + + + if(update) + { + if(DecoderFactory *factory = decoderFactory()) + { + m_shortName = factory->properties().shortName; + } + /*else if(OutputFactory *factory = outputFactory()) + { + m_shortName = factory->properties().shortName; + }*/ + else + m_error = true; + + if (!m_error) + { + QStringList values; + values << m_shortName; + values << info.lastModified().toString(Qt::ISODate); + settings->setValue(m_path, values); + qDebug("PluginCache: added to cache: %s", qPrintable(m_path)); + } + } + + settings->endGroup(); +} + +const QString PluginCache::shortName() const +{ + return m_shortName; +} + +const QString PluginCache::file() const +{ + return m_path; +} + +DecoderFactory *PluginCache::decoderFactory() +{ + if(!m_decoderFactory) + { + m_decoderFactory = qobject_cast (instance()); + if(m_decoderFactory) + qApp->installTranslator(m_decoderFactory->createTranslator(qApp)); + } + return m_decoderFactory; +} + +bool PluginCache::hasError() const +{ + return m_error; +} + +QObject *PluginCache::instance() +{ + if(m_error) + return 0; + if(m_instance) + return m_instance; + QPluginLoader loader(m_path); + m_instance = loader.instance(); + if (loader.isLoaded()) + qDebug("PluginCache: loaded plugin %s", qPrintable(QFileInfo(m_path).fileName())); + else + { + m_error = true; + qWarning("PluginCache: %s", qPrintable(loader.errorString ())); + } + return m_instance; +} diff --git a/src/qmmp/plugincache.h b/src/qmmp/plugincache.h new file mode 100644 index 000000000..34aa4427f --- /dev/null +++ b/src/qmmp/plugincache.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2013 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef PLUGINCACHE_H +#define PLUGINCACHE_H + +#include +#include +#include + +class DecoderFactory; + +/*! @internal + * @author Ilya Kotov + */ +class PluginCache +{ +public: + PluginCache(const QString &file, QSettings *settings); + + const QString shortName() const; + const QString file() const; + bool hasError() const; + + + DecoderFactory *decoderFactory(); + + //OutputFactory *outputFactory(); + //EngineFactory *engineFactory(); + +private: + QObject *instance(); + QString m_path; + QString m_shortName; + bool m_error; + QObject *m_instance; + DecoderFactory *m_decoderFactory; +}; + +#endif // PLUGINCACHE_H diff --git a/src/qmmp/qmmp.pro b/src/qmmp/qmmp.pro index 5b20b3d0c..41191d798 100644 --- a/src/qmmp/qmmp.pro +++ b/src/qmmp/qmmp.pro @@ -36,7 +36,8 @@ HEADERS += \ volume.h \ volumecontrol_p.h \ outputwriter_p.h \ - recycler_p.h + recycler_p.h \ + plugincache.h SOURCES += recycler.cpp \ decoder.cpp \ output.cpp \ @@ -64,7 +65,8 @@ SOURCES += recycler.cpp \ qmmpsettings.cpp \ eqsettings.cpp \ qmmpevents.cpp \ - outputwriter.cpp + outputwriter.cpp \ + plugincache.cpp FORMS += unix:TARGET = ../../lib/qmmp win32:TARGET = ../../../bin/qmmp diff --git a/src/qmmpui/aboutdialog.cpp b/src/qmmpui/aboutdialog.cpp index ef79034e4..c464ae5f2 100644 --- a/src/qmmpui/aboutdialog.cpp +++ b/src/qmmpui/aboutdialog.cpp @@ -75,7 +75,7 @@ QString AboutDialog::loadAbout() text.append("
"+tr("Input plugins:")+"
"); text.append("
    "); - foreach(DecoderFactory *fact, *Decoder::factories()) + foreach(DecoderFactory *fact, Decoder::factories()) { text.append("
  • "); text.append(fact->properties().name); diff --git a/src/qmmpui/configdialog.cpp b/src/qmmpui/configdialog.cpp index dc7e92977..e98e09b7d 100644 --- a/src/qmmpui/configdialog.cpp +++ b/src/qmmpui/configdialog.cpp @@ -182,7 +182,7 @@ void ConfigDialog::loadPluginsInfo() load input plugins information */ item = new QTreeWidgetItem (m_ui->treeWidget, QStringList() << tr("Decoders")); - foreach(DecoderFactory *factory, *Decoder::factories()) + foreach(DecoderFactory *factory, Decoder::factories()) { new PluginItem (item, factory, Decoder::file(factory)); } -- cgit v1.2.3-13-gbd6f