19#include <QCoreApplication>
21#include <QLibraryInfo>
22#include <QPluginLoader>
50 class BackendManager::BackendManagerPrivate {
52 QList<QPluginLoader *> m_loaders;
53 QList<MIDIInput *> m_inputsList;
54 QList<MIDIOutput *> m_outputsList;
57 QString m_inputBackend{QLatin1String(
"Network")};
58#if defined(Q_OS_LINUX)
59 QStringList m_outputBackends{QLatin1String(
"SonivoxEAS"),QLatin1String(
"FluidSynth"),QLatin1String(
"ALSA")};
60#elif defined(Q_OS_DARWIN)
61 QStringList m_outputBackends{QLatin1String(
"DLS Synth"),QLatin1String(
"FluidSynth"),QLatin1String(
"CoreMIDI")};
62#elif defined(Q_OS_WINDOWS)
63 QStringList m_outputBackends{QLatin1String(
"Windows MM"),QLatin1String(
"FluidSynth")};
64#elif defined(Q_OS_UNIX)
65 QStringList m_outputBackends{QLatin1String(
"FluidSynth"),QLatin1String(
"OSS")};
67 QStringList m_outputBackends{m_inputBackend};
70 ~BackendManagerPrivate()
79 while (!m_loaders.empty()) {
80 QPluginLoader* pluginLoader = m_loaders.takeFirst();
82 pluginLoader->unload();
86 m_outputsList.clear();
90 void appendDir(
const QString &candidate, QStringList &result)
92 QDir checked(candidate.trimmed());
94 if (checked.exists() && !result.contains(checked.absolutePath())) {
95 result << checked.absolutePath();
99 bool isLoaderNeeded(
const QString &fileName)
101 auto it = std::find_if(m_loaders.constBegin(),
102 m_loaders.constEnd(),
103 [=](QPluginLoader *loader) {
104 return loader->fileName() == fileName;
106 return it == m_loaders.constEnd();
114 : d{new BackendManagerPrivate}
117 QVariantMap defaultSettings {
118 { QSTR_DRUMSTICKRT_PUBLICNAMEIN, QStringLiteral(
"MIDI In")},
119 { QSTR_DRUMSTICKRT_PUBLICNAMEOUT, QStringLiteral(
"MIDI Out")}
122 BackendManager::BackendManagerPrivate::m_instance =
this;
140 QString appPath = QCoreApplication::applicationDirPath() + QDir::separator();
141 #if defined(Q_OS_WIN)
142 d->appendDir( appPath + QSTR_DRUMSTICK, result );
143 d->appendDir( appPath +
"../lib/" + QSTR_DRUMSTICK, result );
145 #if defined(Q_OS_MAC)
146 d->appendDir( appPath + QStringLiteral(
"../PlugIns/") + QSTR_DRUMSTICK, result );
150 #if defined(LIBSUFFIX)
151 QString libextra(QT_STRINGIFY(LIBSUFFIX));
152 if (QDir::isAbsolutePath(libextra)) {
153 d->appendDir( libextra + QDir::separator() + QSTR_DRUMSTICK, result );
155 libs << QString(
"../%1/").arg(libextra);
158 foreach(
const QString& lib, libs) {
159 d->appendDir( appPath + lib + QSTR_DRUMSTICK, result );
162 d->appendDir( appPath +
".." + QDir::separator() + QSTR_DRUMSTICK, result );
163 QByteArray envdir = qgetenv(QSTR_DRUMSTICKRT.toLatin1());
165 if(!envdir.isEmpty()) {
166 d->appendDir(QString(envdir), result );
168 d->appendDir( QDir::homePath() + QDir::separator() + QSTR_DRUMSTICK, result );
169#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
170 d->appendDir( QLibraryInfo::location(QLibraryInfo::PluginsPath) + QDir::separator() + QSTR_DRUMSTICK, result );
172 d->appendDir( QLibraryInfo::path(QLibraryInfo::PluginsPath) + QDir::separator() + QSTR_DRUMSTICK, result );
174 foreach(
const QString& path, QCoreApplication::libraryPaths()) {
175 d->appendDir( path + QDir::separator() + QSTR_DRUMSTICK, result );
188 settings->beginGroup(QSTR_DRUMSTICKRT_GROUP);
189 const QStringList allKeys = settings->allKeys();
191 for(
const auto &k : allKeys) {
192 tmpMap.insert(k, settings->value(k));
194 settings->endGroup();
210 d->appendDir(map.value(QSTR_DRUMSTICKRT_PATH).toString(), paths);
211 name_in = map.value(QSTR_DRUMSTICKRT_PUBLICNAMEIN).toString();
212 name_out = map.value(QSTR_DRUMSTICKRT_PUBLICNAMEOUT).toString();
213 names << map.value(QSTR_DRUMSTICKRT_EXCLUDED).toStringList();
214 names << (name_in.isEmpty() ? QStringLiteral(
"MIDI In") : name_in);
215 names << (name_out.isEmpty() ? QStringLiteral(
"MIDI Out") : name_out);
221 foreach(
const QString& dir, paths) {
222 QDir pluginsDir(dir);
223 foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
224 auto absolutePath = pluginsDir.absoluteFilePath(fileName);
225 if (QLibrary::isLibrary(absolutePath) && d->isLoaderNeeded(absolutePath)) {
226 QPluginLoader *loader =
new QPluginLoader(absolutePath);
228 d->m_loaders << loader;
229 QObject *obj = loader->instance();
230 if (obj !=
nullptr) {
231 MIDIInput *input = qobject_cast<MIDIInput *>(obj);
232 if (input !=
nullptr && !d->m_inputsList.contains(input)) {
234 if (!name_in.isEmpty()) {
238 d->m_inputsList << input;
240 MIDIOutput *output = qobject_cast<MIDIOutput *>(obj);
241 if (output !=
nullptr && !d->m_outputsList.contains(output)) {
243 if (!name_out.isEmpty()) {
247 d->m_outputsList << output;
256 foreach(
QObject* obj, QPluginLoader::staticInstances()) {
257 if (obj !=
nullptr) {
258 MIDIInput *input = qobject_cast<MIDIInput*>(obj);
259 if (input !=
nullptr && !d->m_inputsList.contains(input)) {
260 if (!name_in.isEmpty()) {
264 d->m_inputsList << input;
266 MIDIOutput *output = qobject_cast<MIDIOutput*>(obj);
267 if (output !=
nullptr && !d->m_outputsList.contains(output)) {
268 if (!name_out.isEmpty()) {
272 d->m_outputsList << output;
278 foreach (
MIDIInput *
in, d->m_inputsList) {
279 if (!name_in.isEmpty()) {
282 in->setExcludedConnections(names);
286 if (!name_out.isEmpty()) {
295 return d->m_inputsList;
300 return d->m_outputsList;
305 foreach (
MIDIInput* i, d->m_inputsList) {
325 QStringList names{name};
326 names << d->m_inputBackend;
327 names.removeDuplicates();
328 if (!names.isEmpty()) {
329 foreach(
const QString& n, names) {
330 foreach(
MIDIInput* input, d->m_inputsList) {
342 QStringList names{name};
343 names << d->m_outputBackends;
344 names.removeDuplicates();
345 if (!names.isEmpty()) {
346 foreach(
const QString& n, names) {
347 foreach(
MIDIOutput* output, d->m_outputsList) {
357 const QString BackendManager::QSTR_DRUMSTICK = QStringLiteral(
"drumstick2");
358 const QString BackendManager::QSTR_DRUMSTICK_VERSION = QStringLiteral(QT_STRINGIFY(VERSION));
359 const QString BackendManager::QSTR_DRUMSTICKRT = QStringLiteral(
"DRUMSTICKRT");
360 const QString BackendManager::QSTR_DRUMSTICKRT_GROUP = QStringLiteral(
"DrumstickRT");
361 const QString BackendManager::QSTR_DRUMSTICKRT_PUBLICNAMEIN = QStringLiteral(
"PublicNameIN");
362 const QString BackendManager::QSTR_DRUMSTICKRT_PUBLICNAMEOUT = QStringLiteral(
"PublicNameOUT");
363 const QString BackendManager::QSTR_DRUMSTICKRT_EXCLUDED = QStringLiteral(
"ExcludedNames");
364 const QString BackendManager::QSTR_DRUMSTICKRT_PATH = QStringLiteral(
"BackendsPath");
366 BackendManager *BackendManager::BackendManagerPrivate::m_instance =
nullptr;
374 return BackendManager::QSTR_DRUMSTICK_VERSION;
385 if (BackendManager::BackendManagerPrivate::m_instance ==
nullptr) {
388 return BackendManager::BackendManagerPrivate::m_instance;
BackendManager class declaration.
The QObject class is the base class of all Qt objects.
The QSettings class provides persistent platform-independent application settings.
The BackendManager class manages lists of dynamic and static backends for applications based on drums...
QList< MIDIInput * > availableInputs()
availableInputs
virtual ~BackendManager()
~BackendManager destructor
BackendManager()
BackendManager constructor.
MIDIOutput * outputBackendByName(const QString name)
outputBackendByName
void refresh(QSettings *settings=nullptr)
refresh the list of backends
QList< MIDIOutput * > availableOutputs()
availableOutputs
MIDIOutput * findOutput(QString name)
findOutput returns the backend corresponding to the provided name, or a suitable output instead.
MIDIInput * findInput(QString name)
findInput returns the backend corresponding to the provided name, or a suitable input instead.
QStringList defaultPaths()
defaultPaths
MIDIInput * inputBackendByName(const QString name)
inputBackendByName
virtual void setExcludedConnections(QStringList conns)=0
setExcludedConnections
virtual QString backendName()=0
backendName
virtual void setPublicName(QString name)=0
setPublicName
BackendManager DRUMSTICK_RT_EXPORT * lastBackendManagerInstance()
lastBackendManagerInstance provides the latest BackendManager instance, or a new instance if needed.
QString DRUMSTICK_RT_EXPORT drumstickLibraryVersion()
drumstickLibraryVersion provides the Drumstick version as an edited QString