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.

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