/* LibraryPluginHandler.cpp */
/* Copyright (C) 2011-2020 Michael Lugmair (Lucio Carreras)
*
* This file is part of sayonara player
*
* 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 3 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, see .
*/
#include "LibraryPluginHandler.h"
#include "Components/LibraryManagement/AbstractLibraryContainer.h"
#include "Utils/Utils.h"
#include "Utils/Algorithm.h"
#include "Utils/Settings/Settings.h"
#include "Utils/Logger/Logger.h"
#include
#include
#include
#include
#include
using Library::PluginHandler;
using Library::AbstractContainer;
using ContainerList=QList;
namespace Algorithm=Util::Algorithm;
struct PluginHandler::Private
{
AbstractContainer* emptyLibrary=nullptr;
AbstractContainer* currentLibrary=nullptr;
ContainerList libraryContainers;
AbstractContainer* find_library(const QString& name)
{
spLog(Log::Debug, this) << "Searching for Library " << name;
auto it = Algorithm::find(libraryContainers, [&name](AbstractContainer* c){
return (c->name() == name);
});
if (it != libraryContainers.end())
{
return *it;
}
return nullptr;
}
};
static QString convert_display_name(const QString& display_name)
{
QString ret = display_name.toLower().trimmed();
ret.replace(" ", "-");
return ret;
}
/*************************************************************************/
PluginHandler::PluginHandler() :
QObject(nullptr)
{
m = Pimpl::make();
}
PluginHandler::~PluginHandler() = default;
void PluginHandler::init(const ContainerList& containers, AbstractContainer* fallback_library)
{
m->emptyLibrary = fallback_library;
QString last_library = GetSetting(Set::Lib_CurPlugin);
initLibraries(containers);
initDllLibraries();
{ // First startup handling
bool has_local_library = Util::Algorithm::contains(m->libraryContainers, [](AbstractContainer* container){
return container->isLocal();
});
AbstractContainer* c = m->find_library(last_library);
if(!has_local_library && (c == nullptr))
{
setCurrentLibrary(-1);
}
else
{
setCurrentLibrary(last_library);
}
}
}
void PluginHandler::shutdown()
{
for(const auto& container : m->libraryContainers)
{
delete container;
}
m->libraryContainers.clear();
}
void PluginHandler::initLibraries(const QList& containers)
{
for(AbstractContainer* container : containers)
{
if(!container) {
continue;
}
spLog(Log::Debug, this) << "Add library " << container->displayName();
m->libraryContainers << container;
}
}
void PluginHandler::initDllLibraries()
{
// QDir plugin_dir = QDir(Util::libPath());
// QStringList dll_filenames = plugin_dir.entryList(QDir::Files);
// for(const QString& filename : dll_filenames)
// {
// QString absolute_path = plugin_dir.absoluteFilePath(filename);
// QPluginLoader loader(absolute_path);
// QJsonObject metadata = loader.metaData();
// QVariantMap map = metadata.toVariantMap();
// const auto keys = map.keys();
// bool has_correct_iid = false;
// for(const QString& key : keys)
// {
// if(key.trimmed() != "IID"){
// continue;
// }
// QString value = map[key].toString();
// if(value.startsWith("com.sayonara-player.apiv2."))
// {
// spLog(Log::Debug, this) << "Have found valid plugin with iid = " << value;
// has_correct_iid = true;
// }
// else if(value.startsWith("com.sayonara-player."))
// {
// spLog(Log::Info, this) << "Ignoring *outdated* plugin with iid = " << value << " at " << absolute_path;
// spLog(Log::Info, this) << "You can delete this file";
// }
// else
// {
// spLog(Log::Warning, this) << "Ignoring *invalid* plugin with iid = " << value << " at " << absolute_path;
// }
// break;
// }
// if(!has_correct_iid)
// {
// continue;
// }
// QObject* raw_plugin = loader.instance();
// if(!raw_plugin)
// {
// spLog(Log::Warning, this) << "Cannot load plugin: " << filename << ": " << loader.errorString();
// loader.unload();
// continue;
// }
// AbstractContainer* container = dynamic_cast(raw_plugin);
// if(!container)
// {
// loader.unload();
// continue;
// }
// spLog(Log::Info, this) << "Found library plugin " << container->displayName();
// m->libraryContainers << container;
// }
}
void PluginHandler::setCurrentLibrary(const QString& name)
{
setCurrentLibrary( m->find_library(name) );
}
void PluginHandler::setCurrentLibrary(int index)
{
AbstractContainer* ret = m->emptyLibrary;
if(!m->libraryContainers.isEmpty() && index >= 0)
{
index = std::min(index, m->libraryContainers.size() - 1);
ret = m->libraryContainers[index];
}
setCurrentLibrary(ret);
}
void PluginHandler::setCurrentLibrary(AbstractContainer* cur_library)
{
if(!cur_library)
{
if(m->libraryContainers.isEmpty())
{
cur_library = m->emptyLibrary;
}
else {
cur_library = m->libraryContainers.first();
}
}
m->currentLibrary = cur_library;
if(m->currentLibrary)
{
m->currentLibrary->init();
}
SetSetting(Set::Lib_CurPlugin, cur_library->name());
emit sigCurrentLibraryChanged();
}
AbstractContainer* PluginHandler::currentLibrary() const
{
return m->currentLibrary;
}
QWidget* PluginHandler::currentLibraryWidget() const
{
if(!m->currentLibrary){
return nullptr;
}
return m->currentLibrary->widget();
}
void PluginHandler::addLocalLibrary(Library::AbstractContainer* container)
{
if(container == nullptr) {
return;
}
int idx = Algorithm::indexOf(m->libraryContainers, [=](AbstractContainer* c){
return (c->isLocal() == false && c != m->emptyLibrary);
});
idx = std::max(idx, 0);
m->libraryContainers.insert(idx, container);
emit sigLibrariesChanged();
setCurrentLibrary(idx);
}
void PluginHandler::renameLocalLibrary(const QString& old_name, const QString& new_name)
{
AbstractContainer* c = m->find_library(convert_display_name(old_name));
if(c && c->isLocal())
{
c->rename(new_name);
emit sigLibrariesChanged();
}
}
void PluginHandler::removeLocalLibrary(const QString& name)
{
AbstractContainer* c = m->find_library(convert_display_name(name));
if(c && c->isLocal())
{
m->libraryContainers.removeAll(c);
if(m->currentLibrary == c)
{
setCurrentLibrary(0);
}
emit sigLibrariesChanged();
}
}
void PluginHandler::moveLocalLibrary(int old_index, int new_index)
{
// first index is empty library
if( !Util::between(old_index, m->libraryContainers) ||
!Util::between(new_index, m->libraryContainers))
{
return;
}
m->libraryContainers.move(old_index, new_index);
emit sigLibrariesChanged();
}
QList PluginHandler::libraries(bool also_empty) const
{
QList containers = m->libraryContainers;
if(also_empty) {
containers.push_front(m->emptyLibrary);
}
return containers;
}