Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1758 lines
65KB

  1. /*
  2. * Carla plugin host
  3. * Copyright (C) 2011-2023 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or 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. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "pluginlistdialog.hpp"
  18. #ifdef __clang__
  19. # pragma clang diagnostic push
  20. # pragma clang diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy"
  21. # pragma clang diagnostic ignored "-Wdeprecated-register"
  22. #elif defined(__GNUC__) && __GNUC__ >= 8
  23. # pragma GCC diagnostic push
  24. # pragma GCC diagnostic ignored "-Wclass-memaccess"
  25. # pragma GCC diagnostic ignored "-Wdeprecated-copy"
  26. #endif
  27. #include "ui_pluginlistdialog.h"
  28. #include <QtCore/QDir>
  29. #include <QtCore/QFileInfo>
  30. #include <QtCore/QList>
  31. #ifdef __clang__
  32. # pragma clang diagnostic pop
  33. #elif defined(__GNUC__) && __GNUC__ >= 8
  34. # pragma GCC diagnostic pop
  35. #endif
  36. #include "qcarlastring.hpp"
  37. #include "qsafesettings.hpp"
  38. #include "CarlaBackendUtils.hpp"
  39. #include "CarlaFrontend.h"
  40. #include "CarlaUtils.h"
  41. #include "CarlaString.hpp"
  42. #include <cstdlib>
  43. CARLA_BACKEND_USE_NAMESPACE
  44. // --------------------------------------------------------------------------------------------------------------------
  45. // Carla Settings keys
  46. #define CARLA_KEY_PATHS_LADSPA "Paths/LADSPA"
  47. #define CARLA_KEY_PATHS_DSSI "Paths/DSSI"
  48. #define CARLA_KEY_PATHS_LV2 "Paths/LV2"
  49. #define CARLA_KEY_PATHS_VST2 "Paths/VST2"
  50. #define CARLA_KEY_PATHS_VST3 "Paths/VST3"
  51. #define CARLA_KEY_PATHS_CLAP "Paths/CLAP"
  52. #define CARLA_KEY_PATHS_SF2 "Paths/SF2"
  53. #define CARLA_KEY_PATHS_SFZ "Paths/SFZ"
  54. #define CARLA_KEY_PATHS_JSFX "Paths/JSFX"
  55. // --------------------------------------------------------------------------------------------------------------------
  56. // Carla Settings defaults
  57. // --------------------------------------------------------------------------------------------------------------------
  58. // utils
  59. const char* getEnv(const char* const env, const char* const fallback)
  60. {
  61. if (const char* const value = std::getenv(env))
  62. return value;
  63. return fallback;
  64. }
  65. QCarlaString getTMP()
  66. {
  67. QCarlaString tmp;
  68. if (const char* const envTMP = std::getenv("TMP"))
  69. {
  70. tmp = envTMP;
  71. }
  72. else
  73. {
  74. #ifdef CARLA_OS_WIN
  75. qWarning("TMP variable not set");
  76. #endif
  77. tmp = QDir::tempPath();
  78. }
  79. if (!QDir(tmp).exists())
  80. {
  81. qWarning("TMP does not exist");
  82. tmp = "/";
  83. }
  84. return tmp;
  85. }
  86. QCarlaString getHome()
  87. {
  88. QCarlaString home;
  89. if (const char* const envHOME = std::getenv("HOME"))
  90. {
  91. home = envHOME;
  92. }
  93. else
  94. {
  95. #ifndef CARLA_OS_WIN
  96. qWarning("HOME variable not set");
  97. #endif
  98. home = QDir::toNativeSeparators(QDir::homePath());
  99. }
  100. if (!QDir(home).exists())
  101. {
  102. qWarning("HOME does not exist");
  103. home = getTMP();
  104. }
  105. return home;
  106. }
  107. // --------------------------------------------------------------------------------------------------------------------
  108. // Default Plugin Folders (get)
  109. struct DefaultPaths {
  110. QCarlaString ladspa;
  111. QCarlaString dssi;
  112. QCarlaString lv2;
  113. QCarlaString vst2;
  114. QCarlaString vst3;
  115. QCarlaString clap;
  116. QCarlaString sf2;
  117. QCarlaString sfz;
  118. QCarlaString jsfx;
  119. void init()
  120. {
  121. const QCarlaString HOME = getHome();
  122. #if defined(CARLA_OS_WIN)
  123. const char* const envAPPDATA = std::getenv("APPDATA");
  124. const char* const envLOCALAPPDATA = getEnv("LOCALAPPDATA", envAPPDATA);
  125. const char* const envPROGRAMFILES = std::getenv("PROGRAMFILES");
  126. const char* const envPROGRAMFILESx86 = std::getenv("PROGRAMFILES(x86)");
  127. const char* const envCOMMONPROGRAMFILES = std::getenv("COMMONPROGRAMFILES");
  128. const char* const envCOMMONPROGRAMFILESx86 = std::getenv("COMMONPROGRAMFILES(x86)");
  129. // Small integrity tests
  130. if (envAPPDATA == nullptr)
  131. {
  132. qFatal("APPDATA variable not set, cannot continue");
  133. abort();
  134. }
  135. if (envPROGRAMFILES == nullptr)
  136. {
  137. qFatal("PROGRAMFILES variable not set, cannot continue");
  138. abort();
  139. }
  140. if (envCOMMONPROGRAMFILES == nullptr)
  141. {
  142. qFatal("COMMONPROGRAMFILES variable not set, cannot continue");
  143. abort();
  144. }
  145. const QCarlaString APPDATA(envAPPDATA);
  146. const QCarlaString LOCALAPPDATA(envLOCALAPPDATA);
  147. const QCarlaString PROGRAMFILES(envPROGRAMFILES);
  148. const QCarlaString COMMONPROGRAMFILES(envCOMMONPROGRAMFILES);
  149. ladspa = APPDATA + "\\LADSPA";
  150. ladspa += ";" + PROGRAMFILES + "\\LADSPA";
  151. dssi = APPDATA + "\\DSSI";
  152. dssi += ";" + PROGRAMFILES + "\\DSSI";
  153. lv2 = APPDATA + "\\LV2";
  154. lv2 += ";" + COMMONPROGRAMFILES + "\\LV2";
  155. vst2 = PROGRAMFILES + "\\VstPlugins";
  156. vst2 += ";" + PROGRAMFILES + "\\Steinberg\\VstPlugins";
  157. jsfx = APPDATA + "\\REAPER\\Effects";
  158. //jsfx += ";" + PROGRAMFILES + "\\REAPER\\InstallData\\Effects";
  159. #ifdef CARLA_OS_WIN64
  160. vst2 += ";" + COMMONPROGRAMFILES + "\\VST2";
  161. #endif
  162. vst3 = COMMONPROGRAMFILES + "\\VST3";
  163. vst3 += ";" + LOCALAPPDATA + "\\Programs\\Common\\VST3";
  164. clap = COMMONPROGRAMFILES + "\\CLAP";
  165. clap += ";" + LOCALAPPDATA + "\\Programs\\Common\\CLAP";
  166. sf2 = APPDATA + "\\SF2";
  167. sfz = APPDATA + "\\SFZ";
  168. if (envPROGRAMFILESx86 != nullptr)
  169. {
  170. const QCarlaString PROGRAMFILESx86(envPROGRAMFILESx86);
  171. ladspa += ";" + PROGRAMFILESx86 + "\\LADSPA";
  172. dssi += ";" + PROGRAMFILESx86 + "\\DSSI";
  173. vst2 += ";" + PROGRAMFILESx86 + "\\VstPlugins";
  174. vst2 += ";" + PROGRAMFILESx86 + "\\Steinberg\\VstPlugins";
  175. //jsfx += ";" + PROGRAMFILESx86 + "\\REAPER\\InstallData\\Effects";
  176. }
  177. if (envCOMMONPROGRAMFILESx86 != nullptr)
  178. {
  179. const QCarlaString COMMONPROGRAMFILESx86(envCOMMONPROGRAMFILESx86);
  180. vst3 += COMMONPROGRAMFILESx86 + "\\VST3";
  181. clap += COMMONPROGRAMFILESx86 + "\\CLAP";
  182. }
  183. #elif defined(CARLA_OS_HAIKU)
  184. ladspa = HOME + "/.ladspa";
  185. ladspa += ":/system/add-ons/media/ladspaplugins";
  186. ladspa += ":/system/lib/ladspa";
  187. dssi = HOME + "/.dssi";
  188. dssi += ":/system/add-ons/media/dssiplugins";
  189. dssi += ":/system/lib/dssi";
  190. lv2 = HOME + "/.lv2";
  191. lv2 += ":/system/add-ons/media/lv2plugins";
  192. vst2 = HOME + "/.vst";
  193. vst2 += ":/system/add-ons/media/vstplugins";
  194. vst3 = HOME + "/.vst3";
  195. vst3 += ":/system/add-ons/media/vst3plugins";
  196. clap = HOME + "/.clap";
  197. clap += ":/system/add-ons/media/clapplugins";
  198. #elif defined(CARLA_OS_MAC)
  199. ladspa = HOME + "/Library/Audio/Plug-Ins/LADSPA";
  200. ladspa += ":/Library/Audio/Plug-Ins/LADSPA";
  201. dssi = HOME + "/Library/Audio/Plug-Ins/DSSI";
  202. dssi += ":/Library/Audio/Plug-Ins/DSSI";
  203. lv2 = HOME + "/Library/Audio/Plug-Ins/LV2";
  204. lv2 += ":/Library/Audio/Plug-Ins/LV2";
  205. vst2 = HOME + "/Library/Audio/Plug-Ins/VST";
  206. vst2 += ":/Library/Audio/Plug-Ins/VST";
  207. vst3 = HOME + "/Library/Audio/Plug-Ins/VST3";
  208. vst3 += ":/Library/Audio/Plug-Ins/VST3";
  209. clap = HOME + "/Library/Audio/Plug-Ins/CLAP";
  210. clap += ":/Library/Audio/Plug-Ins/CLAP";
  211. jsfx = HOME + "/Library/Application Support/REAPER/Effects";
  212. //jsfx += ":/Applications/REAPER.app/Contents/InstallFiles/Effects";
  213. #else
  214. const QCarlaString CONFIG_HOME(getEnv("XDG_CONFIG_HOME", (HOME + "/.config").toUtf8()));
  215. ladspa = HOME + "/.ladspa";
  216. ladspa += ":/usr/lib/ladspa";
  217. ladspa += ":/usr/local/lib/ladspa";
  218. dssi = HOME + "/.dssi";
  219. dssi += ":/usr/lib/dssi";
  220. dssi += ":/usr/local/lib/dssi";
  221. lv2 = HOME + "/.lv2";
  222. lv2 += ":/usr/lib/lv2";
  223. lv2 += ":/usr/local/lib/lv2";
  224. vst2 = HOME + "/.vst";
  225. vst2 += ":/usr/lib/vst";
  226. vst2 += ":/usr/local/lib/vst";
  227. vst2 += HOME + "/.lxvst";
  228. vst2 += ":/usr/lib/lxvst";
  229. vst2 += ":/usr/local/lib/lxvst";
  230. vst3 = HOME + "/.vst3";
  231. vst3 += ":/usr/lib/vst3";
  232. vst3 += ":/usr/local/lib/vst3";
  233. clap = HOME + "/.clap";
  234. clap += ":/usr/lib/clap";
  235. clap += ":/usr/local/lib/clap";
  236. sf2 = HOME + "/.sounds/sf2";
  237. sf2 += ":" + HOME + "/.sounds/sf3";
  238. sf2 += ":/usr/share/sounds/sf2";
  239. sf2 += ":/usr/share/sounds/sf3";
  240. sf2 += ":/usr/share/soundfonts";
  241. sfz = HOME + "/.sounds/sfz";
  242. sfz += ":/usr/share/sounds/sfz";
  243. jsfx = CONFIG_HOME + "/REAPER/Effects";
  244. //jsfx += ":" + "/opt/REAPER/InstallData/Effects";
  245. #endif
  246. #ifndef CARLA_OS_WIN
  247. QCarlaString winePrefix;
  248. if (const char* const envWINEPREFIX = std::getenv("WINEPREFIX"))
  249. winePrefix = envWINEPREFIX;
  250. if (winePrefix.isEmpty())
  251. winePrefix = HOME + "/.wine";
  252. if (QDir(winePrefix).exists())
  253. {
  254. vst2 += ":" + winePrefix + "/drive_c/Program Files/VstPlugins";
  255. vst3 += ":" + winePrefix + "/drive_c/Program Files/Common Files/VST3";
  256. clap += ":" + winePrefix + "/drive_c/Program Files/Common Files/CLAP";
  257. #ifdef CARLA_OS_64BIT
  258. if (QDir(winePrefix + "/drive_c/Program Files (x86)").exists())
  259. {
  260. vst2 += ":" + winePrefix + "/drive_c/Program Files (x86)/VstPlugins";
  261. vst3 += ":" + winePrefix + "/drive_c/Program Files (x86)/Common Files/VST3";
  262. clap += ":" + winePrefix + "/drive_c/Program Files (x86)/Common Files/CLAP";
  263. }
  264. #endif
  265. }
  266. #endif
  267. }
  268. void loadFromEnv()
  269. {
  270. if (const char* const envLADSPA = std::getenv("LADSPA_PATH"))
  271. ladspa = envLADSPA;
  272. if (const char* const envDSSI = std::getenv("DSSI_PATH"))
  273. dssi = envDSSI;
  274. if (const char* const envLV2 = std::getenv("LV2_PATH"))
  275. lv2 = envLV2;
  276. if (const char* const envVST = std::getenv("VST_PATH"))
  277. vst2 = envVST;
  278. if (const char* const envVST3 = std::getenv("VST3_PATH"))
  279. vst3 = envVST3;
  280. if (const char* const envCLAP = std::getenv("CLAP_PATH"))
  281. clap = envCLAP;
  282. if (const char* const envSF2 = std::getenv("SF2_PATH"))
  283. sf2 = envSF2;
  284. if (const char* const envSFZ = std::getenv("SFZ_PATH"))
  285. sfz = envSFZ;
  286. if (const char* const envJSFX = std::getenv("JSFX_PATH"))
  287. jsfx = envJSFX;
  288. }
  289. };
  290. // --------------------------------------------------------------------------------------------------------------------
  291. PluginInfo checkPluginCached(const CarlaCachedPluginInfo* const desc, const PluginType ptype)
  292. {
  293. PluginInfo pinfo = {};
  294. pinfo.API = PLUGIN_QUERY_API_VERSION;
  295. pinfo.build = BINARY_NATIVE;
  296. pinfo.type = ptype;
  297. pinfo.hints = desc->hints;
  298. pinfo.name = desc->name;
  299. pinfo.label = desc->label;
  300. pinfo.maker = desc->maker;
  301. pinfo.category = getPluginCategoryAsString(desc->category);
  302. pinfo.audioIns = desc->audioIns;
  303. pinfo.audioOuts = desc->audioOuts;
  304. pinfo.cvIns = desc->cvIns;
  305. pinfo.cvOuts = desc->cvOuts;
  306. pinfo.midiIns = desc->midiIns;
  307. pinfo.midiOuts = desc->midiOuts;
  308. pinfo.parametersIns = desc->parameterIns;
  309. pinfo.parametersOuts = desc->parameterOuts;
  310. switch (ptype)
  311. {
  312. case PLUGIN_LV2:
  313. {
  314. const QString label(desc->label);
  315. pinfo.filename = label.split(CARLA_OS_SEP).first();
  316. pinfo.label = label.section(CARLA_OS_SEP, 1);
  317. }
  318. break;
  319. case PLUGIN_SFZ:
  320. pinfo.filename = pinfo.label;
  321. pinfo.label = pinfo.name;
  322. break;
  323. default:
  324. break;
  325. }
  326. return pinfo;
  327. }
  328. // --------------------------------------------------------------------------------------------------------------------
  329. // Backwards-compatible horizontalAdvance/width call, depending on Qt version
  330. static inline
  331. int fontMetricsHorizontalAdvance(const QFontMetrics& fontMetrics, const QString& string)
  332. {
  333. #if QT_VERSION >= 0x50b00
  334. return fontMetrics.horizontalAdvance(string);
  335. #else
  336. return fontMetrics.width(string);
  337. #endif
  338. }
  339. // --------------------------------------------------------------------------------------------------------------------
  340. typedef QList<PluginInfo> QPluginInfoList;
  341. class QSafePluginListSettings : public QSafeSettings
  342. {
  343. public:
  344. inline QSafePluginListSettings()
  345. : QSafeSettings() {}
  346. inline QSafePluginListSettings(const QString& organization, const QString& application)
  347. : QSafeSettings(organization, application) {}
  348. QPluginInfoList valuePluginInfoList(const QString& key) const
  349. {
  350. /*
  351. QVariant var(value(key, {}));
  352. if (!var.isNull() && var.convert(QVariant::List) && var.isValid())
  353. {
  354. QList<QVariant> varVariant(var.toList());
  355. QPluginInfoList varReal;
  356. varReal.reserve(varVariant.size());
  357. for (QVariant v : varVariant)
  358. {
  359. CARLA_SAFE_ASSERT_BREAK(!v.isNull());
  360. CARLA_SAFE_ASSERT_BREAK(v.convert(QVariant::UserType));
  361. CARLA_SAFE_ASSERT_BREAK(v.isValid());
  362. // varReal.append(v.toU);
  363. }
  364. }
  365. */
  366. return {};
  367. }
  368. void setValue(const QString& key, const uint value)
  369. {
  370. QSafeSettings::setValue(key, value);
  371. }
  372. void setValue(const QString& key, const QPluginInfoList& value)
  373. {
  374. }
  375. };
  376. // --------------------------------------------------------------------------------------------------------------------
  377. template <class T> inline T static_cast_void(const void* ptr)
  378. {
  379. return static_cast<T>(ptr);
  380. }
  381. struct PluginInfoBytes {
  382. uint API;
  383. uint build;
  384. uint type;
  385. uint hints;
  386. uint64_t uniqueId;
  387. uint audioIns;
  388. uint audioOuts;
  389. uint cvIns;
  390. uint cvOuts;
  391. uint midiIns;
  392. uint midiOuts;
  393. uint parametersIns;
  394. uint parametersOuts;
  395. };
  396. QVariant asVariant(const PluginInfo& plugin)
  397. {
  398. const PluginInfoBytes data = {
  399. plugin.API,
  400. plugin.build,
  401. plugin.type,
  402. plugin.hints,
  403. plugin.uniqueId,
  404. plugin.audioIns,
  405. plugin.audioOuts,
  406. plugin.cvIns,
  407. plugin.cvOuts,
  408. plugin.midiIns,
  409. plugin.midiOuts,
  410. plugin.parametersIns,
  411. plugin.parametersOuts
  412. };
  413. QByteArray qdata(static_cast_void<const char*>(&data), sizeof(data));
  414. {
  415. const QByteArray qcategory(plugin.category.toUtf8());
  416. qdata += qcategory.constData();
  417. qdata += '\0';
  418. }
  419. {
  420. const QByteArray qfilename(plugin.filename.toUtf8());
  421. qdata += qfilename.constData();
  422. qdata += '\0';
  423. }
  424. {
  425. const QByteArray qname(plugin.name.toUtf8());
  426. qdata += qname.constData();
  427. qdata += '\0';
  428. }
  429. {
  430. const QByteArray qlabel(plugin.label.toUtf8());
  431. qdata += qlabel.constData();
  432. qdata += '\0';
  433. }
  434. {
  435. const QByteArray qmaker(plugin.maker.toUtf8());
  436. qdata += qmaker.constData();
  437. qdata += '\0';
  438. }
  439. QVariant var;
  440. var.setValue(qdata);
  441. return var;
  442. }
  443. PluginInfo asPluginInfo(const QVariant& var)
  444. {
  445. const QByteArray qdata(var.toByteArray());
  446. CARLA_SAFE_ASSERT_RETURN((size_t)qdata.size() >= sizeof(PluginInfoBytes) + sizeof(char)*5, {});
  447. const PluginInfoBytes* const data = static_cast_void<const PluginInfoBytes*>(qdata.constData());
  448. PluginInfo plugin = {
  449. data->API,
  450. data->build,
  451. static_cast<PluginType>(data->type),
  452. data->hints,
  453. {}, {}, {}, {}, {},
  454. data->uniqueId,
  455. data->audioIns,
  456. data->audioOuts,
  457. data->cvIns,
  458. data->cvOuts,
  459. data->midiIns,
  460. data->midiOuts,
  461. data->parametersIns,
  462. data->parametersOuts
  463. };
  464. const char* sdata = static_cast_void<const char*>(data) + sizeof(PluginInfoBytes);
  465. plugin.category = QString::fromUtf8(sdata);
  466. sdata += plugin.category.size() + 1;
  467. plugin.filename = QString::fromUtf8(sdata);
  468. sdata += plugin.filename.size() + 1;
  469. plugin.name = QString::fromUtf8(sdata);
  470. sdata += plugin.name.size() + 1;
  471. plugin.label = QString::fromUtf8(sdata);
  472. sdata += plugin.label.size() + 1;
  473. plugin.maker = QString::fromUtf8(sdata);
  474. sdata += plugin.maker.size() + 1;
  475. return plugin;
  476. }
  477. // --------------------------------------------------------------------------------------------------------------------
  478. // Plugin List Dialog
  479. struct PluginListDialog::Self {
  480. enum TableIndex {
  481. TABLEWIDGET_ITEM_FAVORITE,
  482. TABLEWIDGET_ITEM_NAME,
  483. TABLEWIDGET_ITEM_LABEL,
  484. TABLEWIDGET_ITEM_MAKER,
  485. TABLEWIDGET_ITEM_BINARY,
  486. };
  487. // To be changed by parent
  488. bool hasLoadedLv2Plugins = false;
  489. Ui_PluginListDialog ui;
  490. HostSettings hostSettings = {};
  491. int fLastTableIndex = 0;
  492. PluginInfo fRetPlugin;
  493. QWidget* const fRealParent;
  494. QStringList fFavoritePlugins;
  495. bool fFavoritePluginsChanged = false;
  496. const QString fTrYes;
  497. const QString fTrNo;
  498. const QString fTrNative;
  499. Self(QWidget* const parent)
  500. : fRealParent(parent),
  501. fTrYes(tr("Yes")),
  502. fTrNo(tr("No")),
  503. fTrNative(tr("Native")) {}
  504. static Self& create(QWidget* const parent)
  505. {
  506. Self* const self = new Self(parent);
  507. return *self;
  508. }
  509. inline QString tr(const char* const txt)
  510. {
  511. return fRealParent != nullptr ? fRealParent->tr(txt) : QString::fromUtf8(txt);
  512. }
  513. void createFavoritePluginDict()
  514. {
  515. #if 0
  516. return {
  517. 'name' : plugin['name'],
  518. 'build' : plugin['build'],
  519. 'type' : plugin['type'],
  520. 'filename': plugin['filename'],
  521. 'label' : plugin['label'],
  522. 'uniqueId': plugin['uniqueId'],
  523. }
  524. #endif
  525. }
  526. void checkFilters()
  527. {
  528. const QCarlaString text = ui.lineEdit->text().toLower();
  529. const bool hideEffects = !ui.ch_effects->isChecked();
  530. const bool hideInstruments = !ui.ch_instruments->isChecked();
  531. const bool hideMidi = !ui.ch_midi->isChecked();
  532. const bool hideOther = !ui.ch_other->isChecked();
  533. const bool hideInternal = !ui.ch_internal->isChecked();
  534. const bool hideLadspa = !ui.ch_ladspa->isChecked();
  535. const bool hideDssi = !ui.ch_dssi->isChecked();
  536. const bool hideLV2 = !ui.ch_lv2->isChecked();
  537. const bool hideVST2 = !ui.ch_vst->isChecked();
  538. const bool hideVST3 = !ui.ch_vst3->isChecked();
  539. const bool hideCLAP = !ui.ch_clap->isChecked();
  540. const bool hideAU = !ui.ch_au->isChecked();
  541. const bool hideJSFX = !ui.ch_jsfx->isChecked();
  542. const bool hideKits = !ui.ch_kits->isChecked();
  543. const bool hideNative = !ui.ch_native->isChecked();
  544. const bool hideBridged = !ui.ch_bridged->isChecked();
  545. const bool hideBridgedWine = !ui.ch_bridged_wine->isChecked();
  546. const bool hideNonFavs = ui.ch_favorites->isChecked();
  547. const bool hideNonRtSafe = ui.ch_rtsafe->isChecked();
  548. const bool hideNonCV = ui.ch_cv->isChecked();
  549. const bool hideNonGui = ui.ch_gui->isChecked();
  550. const bool hideNonIDisp = ui.ch_inline_display->isChecked();
  551. const bool hideNonStereo = ui.ch_stereo->isChecked();
  552. #if 0
  553. if HAIKU or LINUX or MACOS:
  554. nativeBins = [BINARY_POSIX32, BINARY_POSIX64]
  555. wineBins = [BINARY_WIN32, BINARY_WIN64]
  556. elif WINDOWS:
  557. nativeBins = [BINARY_WIN32, BINARY_WIN64]
  558. wineBins = []
  559. else:
  560. nativeBins = []
  561. wineBins = []
  562. #endif
  563. ui.tableWidget->setRowCount(fLastTableIndex);
  564. for (int i=0; i<fLastTableIndex; ++i)
  565. {
  566. const PluginInfo plugin = asPluginInfo(ui.tableWidget->item(i, TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+1));
  567. const QString ptext = ui.tableWidget->item(i, TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+2).toString();
  568. const uint aIns = plugin.audioIns;
  569. const uint aOuts = plugin.audioOuts;
  570. const uint cvIns = plugin.cvIns;
  571. const uint cvOuts = plugin.cvOuts;
  572. const uint mIns = plugin.midiIns;
  573. const uint mOuts = plugin.midiOuts;
  574. const uint phints = plugin.hints;
  575. const PluginType ptype = plugin.type;
  576. const QString categ = plugin.category;
  577. const bool isSynth = phints & PLUGIN_IS_SYNTH;
  578. const bool isEffect = aIns > 0 && aOuts > 0 && !isSynth;
  579. const bool isMidi = aIns == 0 && aOuts == 0 && mIns > 0 && mOuts > 0;
  580. const bool isKit = ptype == PLUGIN_SF2 || ptype == PLUGIN_SFZ;
  581. const bool isOther = !(isEffect || isSynth || isMidi || isKit);
  582. const bool isNative = plugin.build == BINARY_NATIVE;
  583. const bool isRtSafe = phints & PLUGIN_IS_RTSAFE;
  584. const bool isStereo = (aIns == 2 && aOuts == 2) || (isSynth && aOuts == 2);
  585. const bool hasCV = cvIns + cvOuts > 0;
  586. const bool hasGui = phints & PLUGIN_HAS_CUSTOM_UI;
  587. const bool hasIDisp = phints & PLUGIN_HAS_INLINE_DISPLAY;
  588. #if 0
  589. const bool isBridged = bool(not isNative and plugin.build in nativeBins);
  590. const bool isBridgedWine = bool(not isNative and plugin.build in wineBins);
  591. #else
  592. const bool isBridged = false;
  593. const bool isBridgedWine = false;
  594. #endif
  595. const auto hasText = [text, ptext]() {
  596. const QStringList textSplit = text.strip().split(' ');
  597. for (const QString& t : textSplit)
  598. if (ptext.contains(t))
  599. return true;
  600. return false;
  601. };
  602. /**/ if (hideEffects && isEffect)
  603. ui.tableWidget->hideRow(i);
  604. else if (hideInstruments && isSynth)
  605. ui.tableWidget->hideRow(i);
  606. else if (hideMidi && isMidi)
  607. ui.tableWidget->hideRow(i);
  608. else if (hideOther && isOther)
  609. ui.tableWidget->hideRow(i);
  610. else if (hideKits && isKit)
  611. ui.tableWidget->hideRow(i);
  612. else if (hideInternal && ptype == PLUGIN_INTERNAL)
  613. ui.tableWidget->hideRow(i);
  614. else if (hideLadspa && ptype == PLUGIN_LADSPA)
  615. ui.tableWidget->hideRow(i);
  616. else if (hideDssi && ptype == PLUGIN_DSSI)
  617. ui.tableWidget->hideRow(i);
  618. else if (hideLV2 && ptype == PLUGIN_LV2)
  619. ui.tableWidget->hideRow(i);
  620. else if (hideVST2 && ptype == PLUGIN_VST2)
  621. ui.tableWidget->hideRow(i);
  622. else if (hideVST3 && ptype == PLUGIN_VST3)
  623. ui.tableWidget->hideRow(i);
  624. else if (hideCLAP && ptype == PLUGIN_CLAP)
  625. ui.tableWidget->hideRow(i);
  626. else if (hideAU && ptype == PLUGIN_AU)
  627. ui.tableWidget->hideRow(i);
  628. else if (hideJSFX && ptype == PLUGIN_JSFX)
  629. ui.tableWidget->hideRow(i);
  630. else if (hideNative && isNative)
  631. ui.tableWidget->hideRow(i);
  632. else if (hideBridged && isBridged)
  633. ui.tableWidget->hideRow(i);
  634. else if (hideBridgedWine && isBridgedWine)
  635. ui.tableWidget->hideRow(i);
  636. else if (hideNonRtSafe && not isRtSafe)
  637. ui.tableWidget->hideRow(i);
  638. else if (hideNonCV && not hasCV)
  639. ui.tableWidget->hideRow(i);
  640. else if (hideNonGui && not hasGui)
  641. ui.tableWidget->hideRow(i);
  642. else if (hideNonIDisp && not hasIDisp)
  643. ui.tableWidget->hideRow(i);
  644. else if (hideNonStereo && not isStereo)
  645. ui.tableWidget->hideRow(i);
  646. else if (text.isNotEmpty() && ! hasText())
  647. ui.tableWidget->hideRow(i);
  648. #if 0
  649. else if (hideNonFavs && _createFavoritePluginDict(plugin) not in fFavoritePlugins)
  650. ui.tableWidget->hideRow(i);
  651. #endif
  652. else if (ui.ch_cat_all->isChecked() or
  653. (ui.ch_cat_delay->isChecked() && categ == "delay") or
  654. (ui.ch_cat_distortion->isChecked() && categ == "distortion") or
  655. (ui.ch_cat_dynamics->isChecked() && categ == "dynamics") or
  656. (ui.ch_cat_eq->isChecked() && categ == "eq") or
  657. (ui.ch_cat_filter->isChecked() && categ == "filter") or
  658. (ui.ch_cat_modulator->isChecked() && categ == "modulator") or
  659. (ui.ch_cat_synth->isChecked() && categ == "synth") or
  660. (ui.ch_cat_utility->isChecked() && categ == "utility") or
  661. (ui.ch_cat_other->isChecked() && categ == "other"))
  662. ui.tableWidget->showRow(i);
  663. else
  664. ui.tableWidget->hideRow(i);
  665. }
  666. }
  667. void addPluginToTable(const PluginInfo& plugin, const PluginType ptype)
  668. {
  669. if (plugin.API != PLUGIN_QUERY_API_VERSION)
  670. return;
  671. PluginInfo plugincopy = plugin;
  672. switch (ptype)
  673. {
  674. case PLUGIN_INTERNAL:
  675. case PLUGIN_LV2:
  676. case PLUGIN_SF2:
  677. case PLUGIN_SFZ:
  678. case PLUGIN_JSFX:
  679. plugincopy.build = BINARY_NATIVE;
  680. break;
  681. default:
  682. break;
  683. }
  684. const int index = fLastTableIndex;
  685. #if 0
  686. const bool isFav = bool(self._createFavoritePluginDict(plugin) in self.fFavoritePlugins)
  687. #else
  688. const bool isFav = false;
  689. #endif
  690. QTableWidgetItem* const itemFav = new QTableWidgetItem;
  691. itemFav->setCheckState(isFav ? Qt::Checked : Qt::Unchecked);
  692. itemFav->setText(isFav ? " " : " ");
  693. const QString pluginText = (plugin.name + plugin.label + plugin.maker + plugin.filename).toLower();
  694. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_FAVORITE, itemFav);
  695. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_NAME, new QTableWidgetItem(plugin.name));
  696. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_LABEL, new QTableWidgetItem(plugin.label));
  697. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_MAKER, new QTableWidgetItem(plugin.maker));
  698. ui.tableWidget->setItem(index, TABLEWIDGET_ITEM_BINARY, new QTableWidgetItem(QFileInfo(plugin.filename).fileName()));
  699. QTableWidgetItem* const itemName = ui.tableWidget->item(index, TABLEWIDGET_ITEM_NAME);
  700. itemName->setData(Qt::UserRole+1, asVariant(plugincopy));
  701. itemName->setData(Qt::UserRole+2, pluginText);
  702. fLastTableIndex += 1;
  703. }
  704. uint reAddInternalHelper(QSafePluginListSettings& settingsDB, const PluginType ptype, const char* const path)
  705. {
  706. QString ptypeStr, ptypeStrTr;
  707. switch (ptype)
  708. {
  709. case PLUGIN_INTERNAL:
  710. ptypeStr = "Internal";
  711. ptypeStrTr = tr("Internal");
  712. break;
  713. case PLUGIN_LV2:
  714. ptypeStr = "LV2";
  715. ptypeStrTr = ptypeStr;
  716. break;
  717. case PLUGIN_AU:
  718. ptypeStr = "AU";
  719. ptypeStrTr = ptypeStr;
  720. break;
  721. case PLUGIN_SFZ:
  722. ptypeStr = "SFZ";
  723. ptypeStrTr = ptypeStr;
  724. break;
  725. // TODO(jsfx) what to do here?
  726. default:
  727. return 0;
  728. }
  729. QPluginInfoList plugins = settingsDB.valuePluginInfoList("Plugins/" + ptypeStr);
  730. uint pluginCount = settingsDB.valueUInt("PluginCount/" + ptypeStr, 0);
  731. if (ptype == PLUGIN_AU)
  732. carla_juce_init();
  733. const uint pluginCountNew = carla_get_cached_plugin_count(ptype, path);
  734. #if 0
  735. if (pluginCountNew != pluginCount || plugins.size() != pluginCount ||
  736. (plugins.size() > 0 && plugins[0].API != PLUGIN_QUERY_API_VERSION))
  737. #endif
  738. {
  739. plugins.clear();
  740. pluginCount = pluginCountNew;
  741. QApplication::instance()->processEvents(QEventLoop::ExcludeUserInputEvents, 50);
  742. if (ptype == PLUGIN_AU)
  743. carla_juce_idle();
  744. for (uint i=0; i<pluginCountNew; ++i)
  745. {
  746. const CarlaCachedPluginInfo* const descInfo = carla_get_cached_plugin_info(ptype, i);
  747. if (descInfo == nullptr)
  748. continue;
  749. const PluginInfo info = checkPluginCached(descInfo, ptype);
  750. plugins.append(info);
  751. if ((i % 50) == 0)
  752. {
  753. QApplication::instance()->processEvents(QEventLoop::ExcludeUserInputEvents, 50);
  754. if (ptype == PLUGIN_AU)
  755. carla_juce_idle();
  756. }
  757. }
  758. settingsDB.setValue("Plugins/" + ptypeStr, plugins);
  759. settingsDB.setValue("PluginCount/" + ptypeStr, pluginCount);
  760. }
  761. if (ptype == PLUGIN_AU)
  762. carla_juce_cleanup();
  763. // prepare rows in advance
  764. ui.tableWidget->setRowCount(fLastTableIndex + plugins.size());
  765. for (const PluginInfo& plugin : plugins)
  766. addPluginToTable(plugin, ptype);
  767. return pluginCount;
  768. }
  769. void reAddPlugins()
  770. {
  771. QSafePluginListSettings settingsDB("falkTX", "CarlaPlugins5");
  772. fLastTableIndex = 0;
  773. ui.tableWidget->setSortingEnabled(false);
  774. ui.tableWidget->clearContents();
  775. DefaultPaths paths;
  776. paths.init();
  777. paths.loadFromEnv();
  778. QCarlaString LV2_PATH;
  779. {
  780. const QSafeSettings settings("falkTX", "Carla2");
  781. LV2_PATH = settings.valueString(CARLA_KEY_PATHS_LV2, paths.lv2);
  782. }
  783. // ------------------------------------------------------------------------------------------------------------
  784. // plugins handled through backend
  785. const uint internalCount = reAddInternalHelper(settingsDB, PLUGIN_INTERNAL, "");
  786. const uint lv2Count = reAddInternalHelper(settingsDB, PLUGIN_LV2, LV2_PATH.toUtf8());
  787. #ifdef CARLA_OS_MAC
  788. const uint auCount = reAddInternalHelper(settingsDB, PLUGIN_AU, "");
  789. #else
  790. const uint auCount = 0;
  791. #endif
  792. // ------------------------------------------------------------------------------------------------------------
  793. // LADSPA
  794. QList<QPluginInfoList> ladspaPlugins;
  795. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_native");
  796. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_posix32");
  797. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_posix64");
  798. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_win32");
  799. ladspaPlugins += settingsDB.valuePluginInfoList("Plugins/LADSPA_win64");
  800. // ------------------------------------------------------------------------------------------------------------
  801. // DSSI
  802. QList<QPluginInfoList> dssiPlugins;
  803. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_native");
  804. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_posix32");
  805. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_posix64");
  806. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_win32");
  807. dssiPlugins += settingsDB.valuePluginInfoList("Plugins/DSSI_win64");
  808. // ------------------------------------------------------------------------------------------------------------
  809. // VST2
  810. QList<QPluginInfoList> vst2Plugins;
  811. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_native");
  812. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_posix32");
  813. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_posix64");
  814. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_win32");
  815. vst2Plugins += settingsDB.valuePluginInfoList("Plugins/VST2_win64");
  816. // ------------------------------------------------------------------------------------------------------------
  817. // VST3
  818. QList<QPluginInfoList> vst3Plugins;
  819. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_native");
  820. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_posix32");
  821. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_posix64");
  822. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_win32");
  823. vst3Plugins += settingsDB.valuePluginInfoList("Plugins/VST3_win64");
  824. // ------------------------------------------------------------------------------------------------------------
  825. // CLAP
  826. QList<QPluginInfoList> clapPlugins;
  827. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_native");
  828. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_posix32");
  829. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_posix64");
  830. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_win32");
  831. clapPlugins += settingsDB.valuePluginInfoList("Plugins/CLAP_win64");
  832. #ifdef CARLA_OS_MAC
  833. // ------------------------------------------------------------------------------------------------------------
  834. // AU (extra non-cached)
  835. QList<QPluginInfoList> auPlugins32 = settingsDB.valuePluginInfoList("Plugins/AU_posix32");
  836. #endif
  837. // ------------------------------------------------------------------------------------------------------------
  838. // JSFX
  839. QPluginInfoList jsfxPlugins = settingsDB.valuePluginInfoList("Plugins/JSFX");
  840. // ------------------------------------------------------------------------------------------------------------
  841. // Kits
  842. QList<QPluginInfoList> sf2s;
  843. sf2s += settingsDB.valuePluginInfoList("Plugins/SF2");
  844. QPluginInfoList sfzs = settingsDB.valuePluginInfoList("Plugins/SFZ");
  845. // ------------------------------------------------------------------------------------------------------------
  846. // count plugins first, so we can create rows in advance
  847. int ladspaCount = 0;
  848. int dssiCount = 0;
  849. int vstCount = 0;
  850. int vst3Count = 0;
  851. int clapCount = 0;
  852. int au32Count = 0;
  853. int jsfxCount = jsfxPlugins.size();
  854. int sf2Count = 0;
  855. int sfzCount = sfzs.size();
  856. for (const QPluginInfoList& plugins : ladspaPlugins)
  857. ladspaCount += plugins.size();
  858. for (const QPluginInfoList& plugins : dssiPlugins)
  859. dssiCount += plugins.size();
  860. for (const QPluginInfoList& plugins : vst2Plugins)
  861. vstCount += plugins.size();
  862. for (const QPluginInfoList& plugins : vst3Plugins)
  863. vst3Count += plugins.size();
  864. for (const QPluginInfoList& plugins : clapPlugins)
  865. clapCount += plugins.size();
  866. #ifdef CARLA_OS_MAC
  867. for (const QPluginInfoList& plugins : auPlugins32)
  868. au32Count += plugins.size();
  869. #endif
  870. for (const QPluginInfoList& plugins : sf2s)
  871. sf2Count += plugins.size();
  872. ui.tableWidget->setRowCount(fLastTableIndex +
  873. ladspaCount + dssiCount + vstCount + vst3Count + clapCount +
  874. auCount + au32Count + jsfxCount + sf2Count + sfzCount);
  875. constexpr const char* const txt = "Have %1 Internal, %2 LADSPA, %3 DSSI, %4 LV2, %5 VST2, %6 VST3, %7 CLAP"
  876. #ifdef CARLA_OS_MAC
  877. ", %8 AudioUnit and %9 JSFX plugins, plus %10 Sound Kits"
  878. #endif
  879. " and %8 JSFX plugins, plus %9 Sound Kits";
  880. ui.label->setText(fRealParent->tr(txt)
  881. .arg(QString::number(internalCount))
  882. .arg(QString::number(ladspaCount))
  883. .arg(QString::number(dssiCount))
  884. .arg(QString::number(lv2Count))
  885. .arg(QString::number(vstCount))
  886. .arg(QString::number(vst3Count))
  887. .arg(QString::number(clapCount))
  888. #ifdef CARLA_OS_MAC
  889. .arg(QString::number(auCount+au32Count))
  890. #endif
  891. .arg(QString::number(jsfxCount))
  892. .arg(QString::number(sf2Count+sfzCount))
  893. );
  894. // ------------------------------------------------------------------------------------------------------------
  895. // now add all plugins to the table
  896. for (const QPluginInfoList& plugins : ladspaPlugins)
  897. for (const PluginInfo& plugin : plugins)
  898. addPluginToTable(plugin, PLUGIN_LADSPA);
  899. for (const QPluginInfoList& plugins : dssiPlugins)
  900. for (const PluginInfo& plugin : plugins)
  901. addPluginToTable(plugin, PLUGIN_DSSI);
  902. for (const QPluginInfoList& plugins : vst2Plugins)
  903. for (const PluginInfo& plugin : plugins)
  904. addPluginToTable(plugin, PLUGIN_VST2);
  905. for (const QPluginInfoList& plugins : vst3Plugins)
  906. for (const PluginInfo& plugin : plugins)
  907. addPluginToTable(plugin, PLUGIN_VST3);
  908. for (const QPluginInfoList& plugins : clapPlugins)
  909. for (const PluginInfo& plugin : plugins)
  910. addPluginToTable(plugin, PLUGIN_CLAP);
  911. #ifdef CARLA_OS_MAC
  912. for (const QPluginInfoList& plugins : auPlugins32)
  913. for (const PluginInfo& plugin : plugins)
  914. addPluginToTable(plugin, PLUGIN_AU);
  915. #endif
  916. for (const PluginInfo& plugin : jsfxPlugins)
  917. addPluginToTable(plugin, PLUGIN_JSFX);
  918. for (const QPluginInfoList& sf2 : sf2s)
  919. for (const PluginInfo& sf2_i : sf2)
  920. addPluginToTable(sf2_i, PLUGIN_SF2);
  921. for (const PluginInfo& sfz : sfzs)
  922. addPluginToTable(sfz, PLUGIN_SFZ);
  923. // ------------------------------------------------------------------------------------------------------------
  924. ui.tableWidget->setSortingEnabled(true);
  925. checkFilters();
  926. checkPlugin(ui.tableWidget->currentRow());
  927. }
  928. void checkPlugin(const int row)
  929. {
  930. if (row >= 0)
  931. {
  932. ui.b_add->setEnabled(true);
  933. PluginInfo plugin = asPluginInfo(ui.tableWidget->item(row, TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+1));
  934. const bool isSynth = plugin.hints & PLUGIN_IS_SYNTH;
  935. const bool isEffect = plugin.audioIns > 0 && plugin.audioOuts > 0 && !isSynth;
  936. const bool isMidi = plugin.audioIns == 0 &&
  937. plugin.audioOuts == 0 &&
  938. plugin.midiIns > 0 && plugin.midiOuts > 0;
  939. // const bool isKit = plugin['type'] in (PLUGIN_SF2, PLUGIN_SFZ);
  940. // const bool isOther = ! (isEffect || isSynth || isMidi || isKit);
  941. QString ptype;
  942. /**/ if (isSynth)
  943. ptype = "Instrument";
  944. else if (isEffect)
  945. ptype = "Effect";
  946. else if (isMidi)
  947. ptype = "MIDI Plugin";
  948. else
  949. ptype = "Other";
  950. QString parch;
  951. /**/ if (plugin.build == BINARY_NATIVE)
  952. parch = fTrNative;
  953. else if (plugin.build == BINARY_POSIX32)
  954. parch = "posix32";
  955. else if (plugin.build == BINARY_POSIX64)
  956. parch = "posix64";
  957. else if (plugin.build == BINARY_WIN32)
  958. parch = "win32";
  959. else if (plugin.build == BINARY_WIN64)
  960. parch = "win64";
  961. else if (plugin.build == BINARY_OTHER)
  962. parch = tr("Other");
  963. else if (plugin.build == BINARY_WIN32)
  964. parch = tr("Unknown");
  965. ui.l_format->setText(getPluginTypeAsString(plugin.type));
  966. ui.l_type->setText(ptype);
  967. ui.l_arch->setText(parch);
  968. ui.l_id->setText(QString::number(plugin.uniqueId));
  969. ui.l_ains->setText(QString::number(plugin.audioIns));
  970. ui.l_aouts->setText(QString::number(plugin.audioOuts));
  971. ui.l_cvins->setText(QString::number(plugin.cvIns));
  972. ui.l_cvouts->setText(QString::number(plugin.cvOuts));
  973. ui.l_mins->setText(QString::number(plugin.midiIns));
  974. ui.l_mouts->setText(QString::number(plugin.midiOuts));
  975. ui.l_pins->setText(QString::number(plugin.parametersIns));
  976. ui.l_pouts->setText(QString::number(plugin.parametersOuts));
  977. ui.l_gui->setText(plugin.hints & PLUGIN_HAS_CUSTOM_UI ? fTrYes : fTrNo);
  978. ui.l_idisp->setText(plugin.hints & PLUGIN_HAS_INLINE_DISPLAY ? fTrYes : fTrNo);
  979. ui.l_bridged->setText(plugin.hints & PLUGIN_IS_BRIDGE ? fTrYes : fTrNo);
  980. ui.l_synth->setText(isSynth ? fTrYes : fTrNo);
  981. }
  982. else
  983. {
  984. ui.b_add->setEnabled(false);
  985. ui.l_format->setText("---");
  986. ui.l_type->setText("---");
  987. ui.l_arch->setText("---");
  988. ui.l_id->setText("---");
  989. ui.l_ains->setText("---");
  990. ui.l_aouts->setText("---");
  991. ui.l_cvins->setText("---");
  992. ui.l_cvouts->setText("---");
  993. ui.l_mins->setText("---");
  994. ui.l_mouts->setText("---");
  995. ui.l_pins->setText("---");
  996. ui.l_pouts->setText("---");
  997. ui.l_gui->setText("---");
  998. ui.l_idisp->setText("---");
  999. ui.l_bridged->setText("---");
  1000. ui.l_synth->setText("---");
  1001. }
  1002. }
  1003. };
  1004. PluginListDialog::PluginListDialog(QWidget* const parent, const HostSettings& hostSettings)
  1005. : QDialog(parent),
  1006. self(Self::create(parent))
  1007. {
  1008. self.ui.setupUi(this);
  1009. self.hostSettings = hostSettings;
  1010. // ----------------------------------------------------------------------------------------------------------------
  1011. // Set-up GUI
  1012. self.ui.b_add->setEnabled(false);
  1013. addAction(self.ui.act_focus_search);
  1014. QObject::connect(self.ui.act_focus_search, &QAction::triggered,
  1015. this, &PluginListDialog::slot_focusSearchFieldAndSelectAll);
  1016. #if BINARY_NATIVE == BINARY_POSIX32 || BINARY_NATIVE == BINARY_WIN32
  1017. self.ui.ch_bridged->setText(tr("Bridged (64bit)"));
  1018. #else
  1019. self.ui.ch_bridged->setText(tr("Bridged (32bit)"));
  1020. #endif
  1021. #if !(defined(CARLA_OS_LINUX) || defined(CARLA_OS_MAC))
  1022. self.ui.ch_bridged_wine->setChecked(false);
  1023. self.ui.ch_bridged_wine->setEnabled(false);
  1024. #endif
  1025. #ifdef CARLA_OS_MAC
  1026. setWindowModality(Qt::WindowModal);
  1027. #else
  1028. self.ui.ch_au->setChecked(false);
  1029. self.ui.ch_au->setEnabled(false);
  1030. self.ui.ch_au->setVisible(false);
  1031. #endif
  1032. self.ui.tab_info->tabBar()->hide();
  1033. self.ui.tab_reqs->tabBar()->hide();
  1034. // FIXME, why /2 needed?
  1035. self.ui.tab_info->setMinimumWidth(self.ui.la_id->width()/2 +
  1036. fontMetricsHorizontalAdvance(self.ui.l_id->fontMetrics(), "9999999999") + 6*3);
  1037. setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
  1038. // ----------------------------------------------------------------------------------------------------------------
  1039. // Load settings
  1040. loadSettings();
  1041. // ----------------------------------------------------------------------------------------------------------------
  1042. // Disable bridges if not enabled in settings
  1043. #if 0
  1044. // NOTE: We Assume win32 carla build will not run win64 plugins
  1045. if (WINDOWS and not kIs64bit) or not host.showPluginBridges:
  1046. self.ui.ch_native.setChecked(True)
  1047. self.ui.ch_native.setEnabled(False)
  1048. self.ui.ch_native.setVisible(True)
  1049. self.ui.ch_bridged.setChecked(False)
  1050. self.ui.ch_bridged.setEnabled(False)
  1051. self.ui.ch_bridged.setVisible(False)
  1052. self.ui.ch_bridged_wine.setChecked(False)
  1053. self.ui.ch_bridged_wine.setEnabled(False)
  1054. self.ui.ch_bridged_wine.setVisible(False)
  1055. elif not host.showWineBridges:
  1056. self.ui.ch_bridged_wine.setChecked(False)
  1057. self.ui.ch_bridged_wine.setEnabled(False)
  1058. self.ui.ch_bridged_wine.setVisible(False)
  1059. #endif
  1060. // ----------------------------------------------------------------------------------------------------------------
  1061. // Set-up Icons
  1062. if (hostSettings.useSystemIcons)
  1063. {
  1064. #if 0
  1065. self.ui.b_add.setIcon(getIcon('list-add', 16, 'svgz'))
  1066. self.ui.b_cancel.setIcon(getIcon('dialog-cancel', 16, 'svgz'))
  1067. self.ui.b_clear_filters.setIcon(getIcon('edit-clear', 16, 'svgz'))
  1068. self.ui.b_refresh.setIcon(getIcon('view-refresh', 16, 'svgz'))
  1069. QTableWidgetItem* const hhi = self.ui.tableWidget->horizontalHeaderItem(self.TABLEWIDGET_ITEM_FAVORITE);
  1070. hhi.setIcon(getIcon('bookmarks', 16, 'svgz'))
  1071. #endif
  1072. }
  1073. // ----------------------------------------------------------------------------------------------------------------
  1074. // Set-up connections
  1075. QObject::connect(this, &QDialog::finished, this, &PluginListDialog::slot_saveSettings);
  1076. QObject::connect(self.ui.b_add, &QPushButton::clicked, this, &PluginListDialog::slot_addPlugin);
  1077. QObject::connect(self.ui.b_cancel, &QPushButton::clicked, this, &QDialog::reject);
  1078. QObject::connect(self.ui.b_refresh, &QPushButton::clicked, this, &PluginListDialog::slot_refreshPlugins);
  1079. QObject::connect(self.ui.b_clear_filters, &QPushButton::clicked, this, &PluginListDialog::slot_clearFilters);
  1080. QObject::connect(self.ui.lineEdit, &QLineEdit::textChanged, this, &PluginListDialog::slot_checkFilters);
  1081. QObject::connect(self.ui.tableWidget, &QTableWidget::currentCellChanged,
  1082. this, &PluginListDialog::slot_checkPlugin);
  1083. QObject::connect(self.ui.tableWidget, &QTableWidget::cellClicked,
  1084. this, &PluginListDialog::slot_cellClicked);
  1085. QObject::connect(self.ui.tableWidget, &QTableWidget::cellDoubleClicked,
  1086. this, &PluginListDialog::slot_cellDoubleClicked);
  1087. QObject::connect(self.ui.ch_internal, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1088. QObject::connect(self.ui.ch_ladspa, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1089. QObject::connect(self.ui.ch_dssi, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1090. QObject::connect(self.ui.ch_lv2, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1091. QObject::connect(self.ui.ch_vst, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1092. QObject::connect(self.ui.ch_vst3, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1093. QObject::connect(self.ui.ch_clap, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1094. QObject::connect(self.ui.ch_au, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1095. QObject::connect(self.ui.ch_jsfx, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1096. QObject::connect(self.ui.ch_kits, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1097. QObject::connect(self.ui.ch_effects, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1098. QObject::connect(self.ui.ch_instruments, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1099. QObject::connect(self.ui.ch_midi, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1100. QObject::connect(self.ui.ch_other, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1101. QObject::connect(self.ui.ch_native, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1102. QObject::connect(self.ui.ch_bridged, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1103. QObject::connect(self.ui.ch_bridged_wine, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1104. QObject::connect(self.ui.ch_favorites, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1105. QObject::connect(self.ui.ch_rtsafe, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1106. QObject::connect(self.ui.ch_cv, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1107. QObject::connect(self.ui.ch_gui, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1108. QObject::connect(self.ui.ch_inline_display, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1109. QObject::connect(self.ui.ch_stereo, &QCheckBox::clicked, this, &PluginListDialog::slot_checkFilters);
  1110. QObject::connect(self.ui.ch_cat_all, &QCheckBox::clicked,
  1111. this, &PluginListDialog::slot_checkFiltersCategoryAll);
  1112. QObject::connect(self.ui.ch_cat_delay, &QCheckBox::clicked,
  1113. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1114. QObject::connect(self.ui.ch_cat_distortion, &QCheckBox::clicked,
  1115. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1116. QObject::connect(self.ui.ch_cat_dynamics, &QCheckBox::clicked,
  1117. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1118. QObject::connect(self.ui.ch_cat_eq, &QCheckBox::clicked,
  1119. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1120. QObject::connect(self.ui.ch_cat_filter, &QCheckBox::clicked,
  1121. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1122. QObject::connect(self.ui.ch_cat_modulator, &QCheckBox::clicked,
  1123. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1124. QObject::connect(self.ui.ch_cat_synth, &QCheckBox::clicked,
  1125. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1126. QObject::connect(self.ui.ch_cat_utility, &QCheckBox::clicked,
  1127. this, &PluginListDialog::slot_checkFiltersCategorySpecific);
  1128. QObject::connect(self.ui.ch_cat_other, &QCheckBox::clicked, this,
  1129. &PluginListDialog::slot_checkFiltersCategorySpecific);
  1130. // ----------------------------------------------------------------------------------------------------------------
  1131. // Post-connect setup
  1132. self.reAddPlugins();
  1133. slot_focusSearchFieldAndSelectAll();
  1134. }
  1135. PluginListDialog::~PluginListDialog()
  1136. {
  1137. delete &self;
  1138. }
  1139. // --------------------------------------------------------------------------------------------------------------------
  1140. // public methods
  1141. const PluginInfo& PluginListDialog::getSelectedPluginInfo() const
  1142. {
  1143. return self.fRetPlugin;
  1144. }
  1145. // --------------------------------------------------------------------------------------------------------------------
  1146. // protected methods
  1147. void PluginListDialog::showEvent(QShowEvent* const event)
  1148. {
  1149. slot_focusSearchFieldAndSelectAll();
  1150. QDialog::showEvent(event);
  1151. }
  1152. // --------------------------------------------------------------------------------------------------------------------
  1153. // private methods
  1154. void PluginListDialog::loadSettings()
  1155. {
  1156. const QSafeSettings settings("falkTX", "CarlaDatabase2");
  1157. self.fFavoritePlugins = settings.valueStringList("PluginDatabase/Favorites");
  1158. self.fFavoritePluginsChanged = false;
  1159. restoreGeometry(settings.valueByteArray("PluginDatabase/Geometry"));
  1160. self.ui.ch_effects->setChecked(settings.valueBool("PluginDatabase/ShowEffects", true));
  1161. self.ui.ch_instruments->setChecked(settings.valueBool("PluginDatabase/ShowInstruments", true));
  1162. self.ui.ch_midi->setChecked(settings.valueBool("PluginDatabase/ShowMIDI", true));
  1163. self.ui.ch_other->setChecked(settings.valueBool("PluginDatabase/ShowOther", true));
  1164. self.ui.ch_internal->setChecked(settings.valueBool("PluginDatabase/ShowInternal", true));
  1165. self.ui.ch_ladspa->setChecked(settings.valueBool("PluginDatabase/ShowLADSPA", true));
  1166. self.ui.ch_dssi->setChecked(settings.valueBool("PluginDatabase/ShowDSSI", true));
  1167. self.ui.ch_lv2->setChecked(settings.valueBool("PluginDatabase/ShowLV2", true));
  1168. self.ui.ch_vst->setChecked(settings.valueBool("PluginDatabase/ShowVST2", true));
  1169. self.ui.ch_vst3->setChecked(settings.valueBool("PluginDatabase/ShowVST3", true));
  1170. self.ui.ch_clap->setChecked(settings.valueBool("PluginDatabase/ShowCLAP", true));
  1171. #ifdef CARLA_OS_MAC
  1172. self.ui.ch_au->setChecked(settings.valueBool("PluginDatabase/ShowAU", true));
  1173. #endif
  1174. self.ui.ch_jsfx->setChecked(settings.valueBool("PluginDatabase/ShowJSFX", true));
  1175. self.ui.ch_kits->setChecked(settings.valueBool("PluginDatabase/ShowKits", true));
  1176. self.ui.ch_native->setChecked(settings.valueBool("PluginDatabase/ShowNative", true));
  1177. self.ui.ch_bridged->setChecked(settings.valueBool("PluginDatabase/ShowBridged", true));
  1178. self.ui.ch_bridged_wine->setChecked(settings.valueBool("PluginDatabase/ShowBridgedWine", true));
  1179. self.ui.ch_favorites->setChecked(settings.valueBool("PluginDatabase/ShowFavorites", false));
  1180. self.ui.ch_rtsafe->setChecked(settings.valueBool("PluginDatabase/ShowRtSafe", false));
  1181. self.ui.ch_cv->setChecked(settings.valueBool("PluginDatabase/ShowHasCV", false));
  1182. self.ui.ch_gui->setChecked(settings.valueBool("PluginDatabase/ShowHasGUI", false));
  1183. self.ui.ch_inline_display->setChecked(settings.valueBool("PluginDatabase/ShowHasInlineDisplay", false));
  1184. self.ui.ch_stereo->setChecked(settings.valueBool("PluginDatabase/ShowStereoOnly", false));
  1185. self.ui.lineEdit->setText(settings.valueString("PluginDatabase/SearchText", ""));
  1186. const QString categories = settings.valueString("PluginDatabase/ShowCategory", "all");
  1187. if (categories == "all" or categories.length() < 2)
  1188. {
  1189. self.ui.ch_cat_all->setChecked(true);
  1190. self.ui.ch_cat_delay->setChecked(false);
  1191. self.ui.ch_cat_distortion->setChecked(false);
  1192. self.ui.ch_cat_dynamics->setChecked(false);
  1193. self.ui.ch_cat_eq->setChecked(false);
  1194. self.ui.ch_cat_filter->setChecked(false);
  1195. self.ui.ch_cat_modulator->setChecked(false);
  1196. self.ui.ch_cat_synth->setChecked(false);
  1197. self.ui.ch_cat_utility->setChecked(false);
  1198. self.ui.ch_cat_other->setChecked(false);
  1199. }
  1200. else
  1201. {
  1202. self.ui.ch_cat_all->setChecked(false);
  1203. self.ui.ch_cat_delay->setChecked(categories.contains(":delay:"));
  1204. self.ui.ch_cat_distortion->setChecked(categories.contains(":distortion:"));
  1205. self.ui.ch_cat_dynamics->setChecked(categories.contains(":dynamics:"));
  1206. self.ui.ch_cat_eq->setChecked(categories.contains(":eq:"));
  1207. self.ui.ch_cat_filter->setChecked(categories.contains(":filter:"));
  1208. self.ui.ch_cat_modulator->setChecked(categories.contains(":modulator:"));
  1209. self.ui.ch_cat_synth->setChecked(categories.contains(":synth:"));
  1210. self.ui.ch_cat_utility->setChecked(categories.contains(":utility:"));
  1211. self.ui.ch_cat_other->setChecked(categories.contains(":other:"));
  1212. }
  1213. const QByteArray tableGeometry = settings.valueByteArray("PluginDatabase/TableGeometry_6");
  1214. QHeaderView* const horizontalHeader = self.ui.tableWidget->horizontalHeader();
  1215. if (! tableGeometry.isNull())
  1216. {
  1217. horizontalHeader->restoreState(tableGeometry);
  1218. }
  1219. else
  1220. {
  1221. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_NAME, 250);
  1222. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_LABEL, 200);
  1223. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_MAKER, 150);
  1224. self.ui.tableWidget->sortByColumn(self.TABLEWIDGET_ITEM_NAME, Qt::AscendingOrder);
  1225. }
  1226. horizontalHeader->setSectionResizeMode(self.TABLEWIDGET_ITEM_FAVORITE, QHeaderView::Fixed);
  1227. self.ui.tableWidget->setColumnWidth(self.TABLEWIDGET_ITEM_FAVORITE, 24);
  1228. self.ui.tableWidget->setSortingEnabled(true);
  1229. }
  1230. // -----------------------------------------------------------------------------------------------------------------
  1231. // private slots
  1232. void PluginListDialog::slot_cellClicked(int row, int column)
  1233. {
  1234. if (column != self.TABLEWIDGET_ITEM_FAVORITE)
  1235. return;
  1236. const QTableWidgetItem* const widget = self.ui.tableWidget->item(row, self.TABLEWIDGET_ITEM_FAVORITE);
  1237. const PluginInfo plugin = asPluginInfo(self.ui.tableWidget->item(row, self.TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+1));
  1238. #if 0
  1239. plugin = self._createFavoritePluginDict(plugin);
  1240. #endif
  1241. if (widget->checkState() == Qt::Checked)
  1242. {
  1243. #if 0
  1244. if (not plugin in self.fFavoritePlugins)
  1245. {
  1246. self.fFavoritePlugins.append(plugin);
  1247. self.fFavoritePluginsChanged = true;
  1248. }
  1249. #endif
  1250. }
  1251. else
  1252. {
  1253. #if 0
  1254. try:
  1255. self.fFavoritePlugins.remove(plugin);
  1256. self.fFavoritePluginsChanged = True;
  1257. except ValueError:
  1258. pass
  1259. #endif
  1260. }
  1261. }
  1262. void PluginListDialog::slot_cellDoubleClicked(int, int column)
  1263. {
  1264. if (column != self.TABLEWIDGET_ITEM_FAVORITE)
  1265. slot_addPlugin();
  1266. }
  1267. void PluginListDialog::slot_focusSearchFieldAndSelectAll()
  1268. {
  1269. self.ui.lineEdit->setFocus();
  1270. self.ui.lineEdit->selectAll();
  1271. }
  1272. void PluginListDialog::slot_addPlugin()
  1273. {
  1274. if (self.ui.tableWidget->currentRow() >= 0)
  1275. {
  1276. self.fRetPlugin = asPluginInfo(self.ui.tableWidget->item(self.ui.tableWidget->currentRow(),
  1277. self.TABLEWIDGET_ITEM_NAME)->data(Qt::UserRole+1));
  1278. accept();
  1279. }
  1280. else
  1281. {
  1282. reject();
  1283. }
  1284. }
  1285. void PluginListDialog::slot_checkPlugin(const int row)
  1286. {
  1287. self.checkPlugin(row);
  1288. }
  1289. void PluginListDialog::slot_checkFilters()
  1290. {
  1291. self.checkFilters();
  1292. }
  1293. void PluginListDialog::slot_checkFiltersCategoryAll(const bool clicked)
  1294. {
  1295. const bool notClicked = !clicked;
  1296. self.ui.ch_cat_delay->setChecked(notClicked);
  1297. self.ui.ch_cat_distortion->setChecked(notClicked);
  1298. self.ui.ch_cat_dynamics->setChecked(notClicked);
  1299. self.ui.ch_cat_eq->setChecked(notClicked);
  1300. self.ui.ch_cat_filter->setChecked(notClicked);
  1301. self.ui.ch_cat_modulator->setChecked(notClicked);
  1302. self.ui.ch_cat_synth->setChecked(notClicked);
  1303. self.ui.ch_cat_utility->setChecked(notClicked);
  1304. self.ui.ch_cat_other->setChecked(notClicked);
  1305. self.checkFilters();
  1306. }
  1307. void PluginListDialog::slot_checkFiltersCategorySpecific(bool clicked)
  1308. {
  1309. if (clicked)
  1310. {
  1311. self.ui.ch_cat_all->setChecked(false);
  1312. }
  1313. else if (! (self.ui.ch_cat_delay->isChecked() ||
  1314. self.ui.ch_cat_distortion->isChecked() ||
  1315. self.ui.ch_cat_dynamics->isChecked() ||
  1316. self.ui.ch_cat_eq->isChecked() ||
  1317. self.ui.ch_cat_filter->isChecked() ||
  1318. self.ui.ch_cat_modulator->isChecked() ||
  1319. self.ui.ch_cat_synth->isChecked() ||
  1320. self.ui.ch_cat_utility->isChecked() ||
  1321. self.ui.ch_cat_other->isChecked()))
  1322. {
  1323. self.ui.ch_cat_all->setChecked(true);
  1324. }
  1325. self.checkFilters();
  1326. }
  1327. void PluginListDialog::slot_refreshPlugins()
  1328. {
  1329. #if 0
  1330. if (PluginRefreshW(this, self.hostSettings, self.hasLoadedLv2Plugins).exec())
  1331. reAddPlugins();
  1332. #endif
  1333. }
  1334. void PluginListDialog::slot_clearFilters()
  1335. {
  1336. blockSignals(true);
  1337. self.ui.ch_internal->setChecked(true);
  1338. self.ui.ch_ladspa->setChecked(true);
  1339. self.ui.ch_dssi->setChecked(true);
  1340. self.ui.ch_lv2->setChecked(true);
  1341. self.ui.ch_vst->setChecked(true);
  1342. self.ui.ch_vst3->setChecked(true);
  1343. self.ui.ch_clap->setChecked(true);
  1344. self.ui.ch_jsfx->setChecked(true);
  1345. self.ui.ch_kits->setChecked(true);
  1346. self.ui.ch_instruments->setChecked(true);
  1347. self.ui.ch_effects->setChecked(true);
  1348. self.ui.ch_midi->setChecked(true);
  1349. self.ui.ch_other->setChecked(true);
  1350. self.ui.ch_native->setChecked(true);
  1351. self.ui.ch_bridged->setChecked(false);
  1352. self.ui.ch_bridged_wine->setChecked(false);
  1353. self.ui.ch_favorites->setChecked(false);
  1354. self.ui.ch_rtsafe->setChecked(false);
  1355. self.ui.ch_stereo->setChecked(false);
  1356. self.ui.ch_cv->setChecked(false);
  1357. self.ui.ch_gui->setChecked(false);
  1358. self.ui.ch_inline_display->setChecked(false);
  1359. if (self.ui.ch_au->isEnabled())
  1360. self.ui.ch_au->setChecked(true);
  1361. self.ui.ch_cat_all->setChecked(true);
  1362. self.ui.ch_cat_delay->setChecked(false);
  1363. self.ui.ch_cat_distortion->setChecked(false);
  1364. self.ui.ch_cat_dynamics->setChecked(false);
  1365. self.ui.ch_cat_eq->setChecked(false);
  1366. self.ui.ch_cat_filter->setChecked(false);
  1367. self.ui.ch_cat_modulator->setChecked(false);
  1368. self.ui.ch_cat_synth->setChecked(false);
  1369. self.ui.ch_cat_utility->setChecked(false);
  1370. self.ui.ch_cat_other->setChecked(false);
  1371. self.ui.lineEdit->clear();
  1372. blockSignals(false);
  1373. self.checkFilters();
  1374. }
  1375. // --------------------------------------------------------------------------------------------------------------------
  1376. void PluginListDialog::slot_saveSettings()
  1377. {
  1378. QSafeSettings settings("falkTX", "CarlaDatabase2");
  1379. settings.setValue("PluginDatabase/Geometry", saveGeometry());
  1380. settings.setValue("PluginDatabase/TableGeometry_6", self.ui.tableWidget->horizontalHeader()->saveState());
  1381. settings.setValue("PluginDatabase/ShowEffects", self.ui.ch_effects->isChecked());
  1382. settings.setValue("PluginDatabase/ShowInstruments", self.ui.ch_instruments->isChecked());
  1383. settings.setValue("PluginDatabase/ShowMIDI", self.ui.ch_midi->isChecked());
  1384. settings.setValue("PluginDatabase/ShowOther", self.ui.ch_other->isChecked());
  1385. settings.setValue("PluginDatabase/ShowInternal", self.ui.ch_internal->isChecked());
  1386. settings.setValue("PluginDatabase/ShowLADSPA", self.ui.ch_ladspa->isChecked());
  1387. settings.setValue("PluginDatabase/ShowDSSI", self.ui.ch_dssi->isChecked());
  1388. settings.setValue("PluginDatabase/ShowLV2", self.ui.ch_lv2->isChecked());
  1389. settings.setValue("PluginDatabase/ShowVST2", self.ui.ch_vst->isChecked());
  1390. settings.setValue("PluginDatabase/ShowVST3", self.ui.ch_vst3->isChecked());
  1391. settings.setValue("PluginDatabase/ShowCLAP", self.ui.ch_clap->isChecked());
  1392. settings.setValue("PluginDatabase/ShowAU", self.ui.ch_au->isChecked());
  1393. settings.setValue("PluginDatabase/ShowJSFX", self.ui.ch_jsfx->isChecked());
  1394. settings.setValue("PluginDatabase/ShowKits", self.ui.ch_kits->isChecked());
  1395. settings.setValue("PluginDatabase/ShowNative", self.ui.ch_native->isChecked());
  1396. settings.setValue("PluginDatabase/ShowBridged", self.ui.ch_bridged->isChecked());
  1397. settings.setValue("PluginDatabase/ShowBridgedWine", self.ui.ch_bridged_wine->isChecked());
  1398. settings.setValue("PluginDatabase/ShowFavorites", self.ui.ch_favorites->isChecked());
  1399. settings.setValue("PluginDatabase/ShowRtSafe", self.ui.ch_rtsafe->isChecked());
  1400. settings.setValue("PluginDatabase/ShowHasCV", self.ui.ch_cv->isChecked());
  1401. settings.setValue("PluginDatabase/ShowHasGUI", self.ui.ch_gui->isChecked());
  1402. settings.setValue("PluginDatabase/ShowHasInlineDisplay", self.ui.ch_inline_display->isChecked());
  1403. settings.setValue("PluginDatabase/ShowStereoOnly", self.ui.ch_stereo->isChecked());
  1404. settings.setValue("PluginDatabase/SearchText", self.ui.lineEdit->text());
  1405. if (self.ui.ch_cat_all->isChecked())
  1406. {
  1407. settings.setValue("PluginDatabase/ShowCategory", "all");
  1408. }
  1409. else
  1410. {
  1411. QCarlaString categories;
  1412. if (self.ui.ch_cat_delay->isChecked())
  1413. categories += ":delay";
  1414. if (self.ui.ch_cat_distortion->isChecked())
  1415. categories += ":distortion";
  1416. if (self.ui.ch_cat_dynamics->isChecked())
  1417. categories += ":dynamics";
  1418. if (self.ui.ch_cat_eq->isChecked())
  1419. categories += ":eq";
  1420. if (self.ui.ch_cat_filter->isChecked())
  1421. categories += ":filter";
  1422. if (self.ui.ch_cat_modulator->isChecked())
  1423. categories += ":modulator";
  1424. if (self.ui.ch_cat_synth->isChecked())
  1425. categories += ":synth";
  1426. if (self.ui.ch_cat_utility->isChecked())
  1427. categories += ":utility";
  1428. if (self.ui.ch_cat_other->isChecked())
  1429. categories += ":other";
  1430. if (categories.isNotEmpty())
  1431. categories += ":";
  1432. settings.setValue("PluginDatabase/ShowCategory", categories);
  1433. }
  1434. if (self.fFavoritePluginsChanged)
  1435. settings.setValue("PluginDatabase/Favorites", self.fFavoritePlugins);
  1436. }
  1437. // --------------------------------------------------------------------------------------------------------------------
  1438. const PluginListDialogResults*
  1439. carla_frontend_createAndExecPluginListDialog(void* const parent/*, const HostSettings& hostSettings*/)
  1440. {
  1441. const HostSettings hostSettings = {};
  1442. PluginListDialog gui(reinterpret_cast<QWidget*>(parent), hostSettings);
  1443. if (gui.exec())
  1444. {
  1445. static PluginListDialogResults ret;
  1446. static CarlaString category;
  1447. static CarlaString filename;
  1448. static CarlaString name;
  1449. static CarlaString label;
  1450. static CarlaString maker;
  1451. const PluginInfo& plugin(gui.getSelectedPluginInfo());
  1452. category = plugin.category.toUtf8();
  1453. filename = plugin.filename.toUtf8();
  1454. name = plugin.name.toUtf8();
  1455. label = plugin.label.toUtf8();
  1456. maker = plugin.maker.toUtf8();
  1457. ret.API = plugin.API;
  1458. ret.build = plugin.build;
  1459. ret.type = plugin.type;
  1460. ret.hints = plugin.hints;
  1461. ret.category = category;
  1462. ret.filename = filename;
  1463. ret.name = name;
  1464. ret.label = label;
  1465. ret.maker = maker;
  1466. ret.audioIns = plugin.audioIns;
  1467. ret.audioOuts = plugin.audioOuts;
  1468. ret.cvIns = plugin.cvIns;
  1469. ret.cvOuts = plugin.cvOuts;
  1470. ret.midiIns = plugin.midiIns;
  1471. ret.midiOuts = plugin.midiOuts;
  1472. ret.parametersIns = plugin.parametersIns;
  1473. ret.parametersOuts = plugin.parametersOuts;
  1474. return &ret;
  1475. }
  1476. return nullptr;
  1477. }
  1478. // --------------------------------------------------------------------------------------------------------------------