drumstick  2.9.0
C++ MIDI libraries using Qt objects, idioms, and style.
backendmanager.cpp
Go to the documentation of this file.
1 /*
2  Drumstick RT (realtime MIDI In/Out)
3  Copyright (C) 2009-2023 Pedro Lopez-Cabanillas <plcl@users.sf.net>
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <QCoreApplication>
20 #include <QDir>
21 #include <QLibraryInfo>
22 #include <QPluginLoader>
23 #include <QtGlobal>
25 
31 namespace drumstick { namespace rt {
32 
50  class BackendManager::BackendManagerPrivate {
51  public:
52  QList<MIDIInput*> m_inputsList;
53  QList<MIDIOutput*> m_outputsList;
54 
55  QString m_inputBackend{QLatin1String("Network")};
56  #if defined(Q_OS_LINUX)
57  QStringList m_outputBackends{QLatin1String("SonivoxEAS"),QLatin1String("FluidSynth"),QLatin1String("ALSA")};
58  #elif defined(Q_OS_DARWIN)
59  QStringList m_outputBackends{QLatin1String("DLS Synth"),QLatin1String("FluidSynth"),QLatin1String("CoreMIDI")};
60  #elif defined(Q_OS_WINDOWS)
61  QStringList m_outputBackends{QLatin1String("Windows MM"),QLatin1String("FluidSynth")};
62  #elif defined(Q_OS_UNIX)
63  QStringList m_outputBackends{QLatin1String("FluidSynth"),QLatin1String("OSS")};
64  #else
65  QStringList m_outputBackends{m_inputBackend};
66  #endif
67 
68  ~BackendManagerPrivate()
69  {
70  clearLists();
71  }
72  void clearLists()
73  {
74  m_inputsList.clear();
75  m_outputsList.clear();
76  }
77  void appendDir(const QString& candidate, QStringList& result)
78  {
79  QDir checked(candidate.trimmed());
80  //qDebug() << Q_FUNC_INFO << candidate << "exists:" << checked.exists();
81  if (checked.exists() && !result.contains(checked.absolutePath())) {
82  result << checked.absolutePath();
83  }
84  }
85  };
86 
90  BackendManager::BackendManager(): d(new BackendManagerPrivate)
91  {
92  QVariantMap defaultSettings {
93  { QSTR_DRUMSTICKRT_PUBLICNAMEIN, QStringLiteral("MIDI In")},
94  { QSTR_DRUMSTICKRT_PUBLICNAMEOUT, QStringLiteral("MIDI Out")}
95  };
96  refresh(defaultSettings);
97  }
98 
103  { }
104 
110  {
111  QStringList result;
112  QString appPath = QCoreApplication::applicationDirPath() + QDir::separator();
113  #if defined(Q_OS_WIN)
114  d->appendDir( appPath + QSTR_DRUMSTICK, result );
115  d->appendDir( appPath + "../lib/" + QSTR_DRUMSTICK, result );
116  #else
117  #if defined(Q_OS_MAC)
118  d->appendDir( appPath + QStringLiteral("../PlugIns/") + QSTR_DRUMSTICK, result );
119  #endif // Linux, Unix...
120  QStringList libs;
121  libs << "../lib/";
122  #if defined(LIBSUFFIX)
123  QString libextra(QT_STRINGIFY(LIBSUFFIX));
124  if (QDir::isAbsolutePath(libextra)) {
125  d->appendDir( libextra + QDir::separator() + QSTR_DRUMSTICK, result );
126  } else {
127  libs << QString("../%1/").arg(libextra);
128  }
129  #endif
130  foreach(const QString& lib, libs) {
131  d->appendDir( appPath + lib + QSTR_DRUMSTICK, result );
132  }
133  #endif
134  d->appendDir( appPath + ".." + QDir::separator() + QSTR_DRUMSTICK, result );
135  QByteArray envdir = qgetenv(QSTR_DRUMSTICKRT.toLatin1());
136  //qDebug() << Q_FUNC_INFO << "envdir:" << envdir;
137  if(!envdir.isEmpty()) {
138  d->appendDir(QString(envdir), result );
139  }
140  d->appendDir( QDir::homePath() + QDir::separator() + QSTR_DRUMSTICK, result );
141 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
142  d->appendDir( QLibraryInfo::location(QLibraryInfo::PluginsPath) + QDir::separator() + QSTR_DRUMSTICK, result );
143 #else
144  d->appendDir( QLibraryInfo::path(QLibraryInfo::PluginsPath) + QDir::separator() + QSTR_DRUMSTICK, result );
145 #endif
146  foreach(const QString& path, QCoreApplication::libraryPaths()) {
147  d->appendDir( path + QDir::separator() + QSTR_DRUMSTICK, result );
148  }
149  return result;
150  }
151 
157  {
158  QVariantMap tmpMap;
159  settings->beginGroup(QSTR_DRUMSTICKRT_GROUP);
160  const QStringList allKeys = settings->allKeys();
161  //qDebug() << Q_FUNC_INFO << allKeys;
162  for(const auto &k : allKeys) {
163  tmpMap.insert(k, settings->value(k));
164  }
165  settings->endGroup();
166  refresh(tmpMap);
167  }
168 
174  void BackendManager::refresh(const QVariantMap &map)
175  {
176  QString name_in;
177  QString name_out;
178  QStringList names;
179  QStringList paths;
180 
181  d->appendDir(map.value(QSTR_DRUMSTICKRT_PATH).toString(), paths);
182  name_in = map.value(QSTR_DRUMSTICKRT_PUBLICNAMEIN).toString();
183  name_out = map.value(QSTR_DRUMSTICKRT_PUBLICNAMEOUT).toString();
184  names << map.value(QSTR_DRUMSTICKRT_EXCLUDED).toStringList();
185  names << (name_in.isEmpty() ? QStringLiteral("MIDI In") : name_in);
186  names << (name_out.isEmpty() ? QStringLiteral("MIDI Out") : name_out);
187  paths << defaultPaths();
188  //qDebug() << Q_FUNC_INFO << "names:" << names;
189  //qDebug() << Q_FUNC_INFO << "paths:" << paths;
190 
191  d->clearLists();
192 
193  // Dynamic backends
194  foreach(const QString& dir, paths) {
195  QDir pluginsDir(dir);
196  foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
197  if (QLibrary::isLibrary(fileName)) {
198  QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
199  QObject *obj = loader.instance();
200  if (obj != nullptr) {
201  MIDIInput *input = qobject_cast<MIDIInput*>(obj);
202  if (input != nullptr && !d->m_inputsList.contains(input)) {
203  if (!name_in.isEmpty()) {
204  input->setPublicName(name_in);
205  }
206  input->setExcludedConnections(names);
207  d->m_inputsList << input;
208  } else {
209  MIDIOutput *output = qobject_cast<MIDIOutput*>(obj);
210  if (output != nullptr && !d->m_outputsList.contains(output)) {
211  if (!name_out.isEmpty()) {
212  output->setPublicName(name_out);
213  }
214  output->setExcludedConnections(names);
215  d->m_outputsList << output;
216  }
217  }
218  }
219  }
220  }
221  }
222 
223  // Static backends
224  foreach(QObject* obj, QPluginLoader::staticInstances()) {
225  if (obj != nullptr) {
226  MIDIInput *input = qobject_cast<MIDIInput*>(obj);
227  if (input != nullptr && !d->m_inputsList.contains(input)) {
228  if (!name_in.isEmpty()) {
229  input->setPublicName(name_in);
230  }
231  input->setExcludedConnections(names);
232  d->m_inputsList << input;
233  } else {
234  MIDIOutput *output = qobject_cast<MIDIOutput*>(obj);
235  if (output != nullptr && !d->m_outputsList.contains(output)) {
236  if (!name_out.isEmpty()) {
237  output->setPublicName(name_out);
238  }
239  output->setExcludedConnections(names);
240  d->m_outputsList << output;
241  }
242  }
243  }
244  }
245  }
246 
248  {
249  return d->m_inputsList;
250  }
251 
252  QList<MIDIOutput*> BackendManager::availableOutputs()
253  {
254  return d->m_outputsList;
255  }
256 
258  {
259  foreach (MIDIInput* i, d->m_inputsList) {
260  if (i->backendName() == name) {
261  return i;
262  }
263  }
264  return nullptr;
265  }
266 
268  {
269  foreach (MIDIOutput* i, d->m_outputsList) {
270  if (i->backendName() == name) {
271  return i;
272  }
273  }
274  return nullptr;
275  }
276 
278  {
279  QStringList names{name};
280  names << d->m_inputBackend;
281  names.removeDuplicates();
282  if (!names.isEmpty()) {
283  foreach(const QString& n, names) {
284  foreach(MIDIInput* input, d->m_inputsList) {
285  if (input->backendName() == n) {
286  return input;
287  }
288  }
289  }
290  }
291  return nullptr;
292  }
293 
295  {
296  QStringList names{name};
297  names << d->m_outputBackends;
298  names.removeDuplicates();
299  if (!names.isEmpty()) {
300  foreach(const QString& n, names) {
301  foreach(MIDIOutput* output, d->m_outputsList) {
302  if (output->backendName() == n) {
303  return output;
304  }
305  }
306  }
307  }
308  return nullptr;
309  }
310 
311  const QString BackendManager::QSTR_DRUMSTICK = QStringLiteral("drumstick2");
312  const QString BackendManager::QSTR_DRUMSTICK_VERSION = QStringLiteral(QT_STRINGIFY(VERSION));
313  const QString BackendManager::QSTR_DRUMSTICKRT = QStringLiteral("DRUMSTICKRT");
314  const QString BackendManager::QSTR_DRUMSTICKRT_GROUP = QStringLiteral("DrumstickRT");
315  const QString BackendManager::QSTR_DRUMSTICKRT_PUBLICNAMEIN = QStringLiteral("PublicNameIN");
316  const QString BackendManager::QSTR_DRUMSTICKRT_PUBLICNAMEOUT = QStringLiteral("PublicNameOUT");
317  const QString BackendManager::QSTR_DRUMSTICKRT_EXCLUDED = QStringLiteral("ExcludedNames");
318  const QString BackendManager::QSTR_DRUMSTICKRT_PATH = QStringLiteral("BackendsPath");
319 
325  {
326  return BackendManager::QSTR_DRUMSTICK_VERSION;
327  }
328 
329 } // namespace rt
330 } // namespace drumstick
BackendManager class declaration.
The QObject class is the base class of all Qt objects.
The QSettings class provides persistent platform-independent application settings.
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
MIDI IN interface.
Definition: rtmidiinput.h:56
virtual void setExcludedConnections(QStringList conns)=0
setExcludedConnections
virtual QString backendName()=0
backendName
virtual void setPublicName(QString name)=0
setPublicName
MIDI OUT interface.
Definition: rtmidioutput.h:122
virtual void setExcludedConnections(QStringList conns)=0
setExcludedConnections
virtual QString backendName()=0
backendName
virtual void setPublicName(QString name)=0
setPublicName
QString DRUMSTICK_RT_EXPORT drumstickLibraryVersion()
drumstickLibraryVersion provides the Drumstick version as an edited QString
Drumstick common.
Definition: alsaclient.cpp:68